mirror of
https://github.com/MatsuriDayo/nekoray.git
synced 2025-12-17 12:34:37 +03:00
chore: re-format code
This commit is contained in:
10
.clang-format
Normal file
10
.clang-format
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
BasedOnStyle: Google
|
||||||
|
ColumnLimit: 0
|
||||||
|
IndentWidth: 4
|
||||||
|
SortIncludes: Never
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
NamespaceIndentation: All
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
SpaceAfterCStyleCast: true
|
||||||
|
SpaceAfterTemplateKeyword: false
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: false
|
||||||
@@ -11,8 +11,7 @@ namespace NekoRay {
|
|||||||
|
|
||||||
// Common
|
// Common
|
||||||
|
|
||||||
QSharedPointer<BuildConfigResult>
|
QSharedPointer<BuildConfigResult> BuildConfig(const QSharedPointer<ProxyEntity> &ent, bool forTest, bool forExport) {
|
||||||
BuildConfig(const QSharedPointer<ProxyEntity> &ent, bool forTest, bool forExport) {
|
|
||||||
if (IS_NEKO_BOX) {
|
if (IS_NEKO_BOX) {
|
||||||
return BuildConfigSingBox(ent, forTest, forExport);
|
return BuildConfigSingBox(ent, forTest, forExport);
|
||||||
}
|
}
|
||||||
@@ -65,7 +64,7 @@ namespace NekoRay {
|
|||||||
if (outbound.contains(key)) {
|
if (outbound.contains(key)) {
|
||||||
auto v = custom[key];
|
auto v = custom[key];
|
||||||
auto v_orig = outbound[key];
|
auto v_orig = outbound[key];
|
||||||
if (v.isObject() && v_orig.isObject()) {// isObject 则合并?
|
if (v.isObject() && v_orig.isObject()) { // isObject 则合并?
|
||||||
auto vo = v.toObject();
|
auto vo = v.toObject();
|
||||||
QJsonObject vo_orig = v_orig.toObject();
|
QJsonObject vo_orig = v_orig.toObject();
|
||||||
ApplyCustomOutboundJsonSettings(vo, vo_orig);
|
ApplyCustomOutboundJsonSettings(vo, vo_orig);
|
||||||
@@ -79,8 +78,7 @@ namespace NekoRay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<BuildConfigResult>
|
QSharedPointer<BuildConfigResult> BuildConfigV2Ray(const QSharedPointer<ProxyEntity> &ent, bool forTest, bool forExport) {
|
||||||
BuildConfigV2Ray(const QSharedPointer<ProxyEntity> &ent, bool forTest, bool forExport) {
|
|
||||||
auto result = QSharedPointer<BuildConfigResult>(new BuildConfigResult);
|
auto result = QSharedPointer<BuildConfigResult>(new BuildConfigResult);
|
||||||
auto status = QSharedPointer<BuildConfigStatus>(new BuildConfigStatus);
|
auto status = QSharedPointer<BuildConfigStatus>(new BuildConfigStatus);
|
||||||
status->ent = ent;
|
status->ent = ent;
|
||||||
@@ -91,11 +89,13 @@ namespace NekoRay {
|
|||||||
result->coreConfig.insert("log", logObj);
|
result->coreConfig.insert("log", logObj);
|
||||||
|
|
||||||
// Inbounds
|
// Inbounds
|
||||||
QJsonObject sniffing{{"destOverride", dataStore->fake_dns ? QJsonArray{"fakedns", "http", "tls", "quic"}
|
QJsonObject sniffing{
|
||||||
|
{"destOverride", dataStore->fake_dns ? QJsonArray{"fakedns", "http", "tls", "quic"}
|
||||||
: QJsonArray{"http", "tls", "quic"}},
|
: QJsonArray{"http", "tls", "quic"}},
|
||||||
{"enabled", true},
|
{"enabled", true},
|
||||||
{"metadataOnly", false},
|
{"metadataOnly", false},
|
||||||
{"routeOnly", dataStore->sniffing_mode == SniffingMode::FOR_ROUTING},};
|
{"routeOnly", dataStore->sniffing_mode == SniffingMode::FOR_ROUTING},
|
||||||
|
};
|
||||||
|
|
||||||
// socks-in
|
// socks-in
|
||||||
if (InRange(dataStore->inbound_socks_port, 0, 65535) && !forTest) {
|
if (InRange(dataStore->inbound_socks_port, 0, 65535) && !forTest) {
|
||||||
@@ -104,8 +104,10 @@ namespace NekoRay {
|
|||||||
socksInbound["protocol"] = "socks";
|
socksInbound["protocol"] = "socks";
|
||||||
socksInbound["listen"] = dataStore->inbound_address;
|
socksInbound["listen"] = dataStore->inbound_address;
|
||||||
socksInbound["port"] = dataStore->inbound_socks_port;
|
socksInbound["port"] = dataStore->inbound_socks_port;
|
||||||
socksInbound["settings"] = QJsonObject({{"auth", "noauth"},
|
socksInbound["settings"] = QJsonObject{
|
||||||
{"udp", true},});
|
{"auth", "noauth"},
|
||||||
|
{"udp", true},
|
||||||
|
};
|
||||||
if (dataStore->fake_dns || dataStore->sniffing_mode != SniffingMode::DISABLE) {
|
if (dataStore->fake_dns || dataStore->sniffing_mode != SniffingMode::DISABLE) {
|
||||||
socksInbound["sniffing"] = sniffing;
|
socksInbound["sniffing"] = sniffing;
|
||||||
}
|
}
|
||||||
@@ -129,21 +131,37 @@ namespace NekoRay {
|
|||||||
if (!result->error.isEmpty()) return result;
|
if (!result->error.isEmpty()) return result;
|
||||||
|
|
||||||
// direct & bypass & block
|
// direct & bypass & block
|
||||||
status->outbounds += QJsonObject{{"protocol", "freedom"},
|
status->outbounds += QJsonObject{
|
||||||
{"tag", "direct"},};
|
{"protocol", "freedom"},
|
||||||
status->outbounds += QJsonObject{{"protocol", "freedom"},
|
{"tag", "direct"},
|
||||||
{"tag", "bypass"},};
|
};
|
||||||
status->outbounds += QJsonObject{{"protocol", "blackhole"},
|
status->outbounds += QJsonObject{
|
||||||
{"tag", "block"},};
|
{"protocol", "freedom"},
|
||||||
|
{"tag", "bypass"},
|
||||||
|
};
|
||||||
|
status->outbounds += QJsonObject{
|
||||||
|
{"protocol", "blackhole"},
|
||||||
|
{"tag", "block"},
|
||||||
|
};
|
||||||
|
|
||||||
// block for tun
|
// block for tun
|
||||||
if (!forTest) {
|
if (!forTest) {
|
||||||
status->routingRules += QJsonObject{{"type", "field"},
|
status->routingRules += QJsonObject{
|
||||||
{"ip", QJsonArray{"224.0.0.0/3", "169.254.0.0/16",},},
|
{"type", "field"},
|
||||||
{"outboundTag", "block"},};
|
{
|
||||||
status->routingRules += QJsonObject{{"type", "field"},
|
"ip",
|
||||||
|
QJsonArray{
|
||||||
|
"224.0.0.0/3",
|
||||||
|
"169.254.0.0/16",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{"outboundTag", "block"},
|
||||||
|
};
|
||||||
|
status->routingRules += QJsonObject{
|
||||||
|
{"type", "field"},
|
||||||
{"port", "135-139"},
|
{"port", "135-139"},
|
||||||
{"outboundTag", "block"},};
|
{"outboundTag", "block"},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNS Routing (tun2socks 用到,防污染)
|
// DNS Routing (tun2socks 用到,防污染)
|
||||||
@@ -161,13 +179,17 @@ namespace NekoRay {
|
|||||||
{"transportLayer", true}};
|
{"transportLayer", true}};
|
||||||
|
|
||||||
status->outbounds += dnsOut;
|
status->outbounds += dnsOut;
|
||||||
status->routingRules += QJsonObject{{"type", "field"},
|
status->routingRules += QJsonObject{
|
||||||
|
{"type", "field"},
|
||||||
{"port", "53"},
|
{"port", "53"},
|
||||||
{"inboundTag", QJsonArray{"socks-in", "http-in"}},
|
{"inboundTag", QJsonArray{"socks-in", "http-in"}},
|
||||||
{"outboundTag", "dns-out"},};
|
{"outboundTag", "dns-out"},
|
||||||
status->routingRules += QJsonObject{{"type", "field"},
|
};
|
||||||
|
status->routingRules += QJsonObject{
|
||||||
|
{"type", "field"},
|
||||||
{"inboundTag", QJsonArray{"dns-in"}},
|
{"inboundTag", QJsonArray{"dns-in"}},
|
||||||
{"outboundTag", "dns-out"},};
|
{"outboundTag", "dns-out"},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// custom inbound
|
// custom inbound
|
||||||
@@ -207,22 +229,30 @@ namespace NekoRay {
|
|||||||
if (directDnsAddress.contains("://")) {
|
if (directDnsAddress.contains("://")) {
|
||||||
auto directDnsIp = SubStrBefore(SubStrAfter(directDnsAddress, "://"), "/");
|
auto directDnsIp = SubStrBefore(SubStrAfter(directDnsAddress, "://"), "/");
|
||||||
if (IsIpAddress(directDnsIp)) {
|
if (IsIpAddress(directDnsIp)) {
|
||||||
status->routingRules.push_front(QJsonObject{{"type", "field"},
|
status->routingRules.push_front(QJsonObject{
|
||||||
|
{"type", "field"},
|
||||||
{"ip", QJsonArray{directDnsIp}},
|
{"ip", QJsonArray{directDnsIp}},
|
||||||
{"outboundTag", "direct"},});
|
{"outboundTag", "direct"},
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
status->routingRules.push_front(QJsonObject{{"type", "field"},
|
status->routingRules.push_front(QJsonObject{
|
||||||
|
{"type", "field"},
|
||||||
{"domain", QJsonArray{directDnsIp}},
|
{"domain", QJsonArray{directDnsIp}},
|
||||||
{"outboundTag", "direct"},});
|
{"outboundTag", "direct"},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else if (directDnsAddress != "localhost") {
|
} else if (directDnsAddress != "localhost") {
|
||||||
status->routingRules.push_front(QJsonObject{{"type", "field"},
|
status->routingRules.push_front(QJsonObject{
|
||||||
|
{"type", "field"},
|
||||||
{"ip", QJsonArray{directDnsAddress}},
|
{"ip", QJsonArray{directDnsAddress}},
|
||||||
{"outboundTag", "direct"},});
|
{"outboundTag", "direct"},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
dnsServers += QJsonObject{{"address", directDnsAddress},
|
dnsServers += QJsonObject{
|
||||||
|
{"address", directDnsAddress},
|
||||||
{"domains", status->domainListDNSDirect},
|
{"domains", status->domainListDNSDirect},
|
||||||
{"skipFallback", true},};
|
{"skipFallback", true},
|
||||||
|
};
|
||||||
|
|
||||||
dns["disableFallbackIfMatch"] = true;
|
dns["disableFallbackIfMatch"] = true;
|
||||||
dns["servers"] = dnsServers;
|
dns["servers"] = dnsServers;
|
||||||
@@ -365,19 +395,25 @@ namespace NekoRay {
|
|||||||
if (IS_NEKO_BOX) {
|
if (IS_NEKO_BOX) {
|
||||||
replaced["detour"] = tagOut;
|
replaced["detour"] = tagOut;
|
||||||
} else {
|
} else {
|
||||||
replaced["proxySettings"] = QJsonObject{{"tag", tagOut},
|
replaced["proxySettings"] = QJsonObject{
|
||||||
{"transportLayer", true},};
|
{"tag", tagOut},
|
||||||
|
{"transportLayer", true},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
status->outbounds.removeLast();
|
status->outbounds.removeLast();
|
||||||
status->outbounds += replaced;
|
status->outbounds += replaced;
|
||||||
} else {
|
} else {
|
||||||
if (IS_NEKO_BOX) {
|
if (IS_NEKO_BOX) {
|
||||||
status->routingRules += QJsonObject{{"inbound", QJsonArray{pastTag + "-mapping"}},
|
status->routingRules += QJsonObject{
|
||||||
{"outbound", tagOut},};
|
{"inbound", QJsonArray{pastTag + "-mapping"}},
|
||||||
|
{"outbound", tagOut},
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
status->routingRules += QJsonObject{{"type", "field"},
|
status->routingRules += QJsonObject{
|
||||||
|
{"type", "field"},
|
||||||
{"inboundTag", QJsonArray{pastTag + "-mapping"}},
|
{"inboundTag", QJsonArray{pastTag + "-mapping"}},
|
||||||
{"outboundTag", tagOut},};
|
{"outboundTag", tagOut},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -388,37 +424,46 @@ namespace NekoRay {
|
|||||||
|
|
||||||
// chain rules: this
|
// chain rules: this
|
||||||
auto mapping_port = MkPort();
|
auto mapping_port = MkPort();
|
||||||
auto thisExternalStat = ent->bean->NeedExternal(isFirstProfile,
|
auto thisExternalStat = ent->bean->NeedExternal(isFirstProfile, dataStore->running_spmode == SystemProxyMode::VPN);
|
||||||
dataStore->running_spmode == SystemProxyMode::VPN);
|
|
||||||
if (thisExternalStat == 2) dataStore->need_keep_vpn_off = true;
|
if (thisExternalStat == 2) dataStore->need_keep_vpn_off = true;
|
||||||
if (thisExternalStat == 1) {
|
if (thisExternalStat == 1) {
|
||||||
// mapping
|
// mapping
|
||||||
if (IS_NEKO_BOX) {
|
if (IS_NEKO_BOX) {
|
||||||
status->inbounds += QJsonObject{{"type", "direct"},
|
status->inbounds += QJsonObject{
|
||||||
|
{"type", "direct"},
|
||||||
{"tag", tagOut + "-mapping"},
|
{"tag", tagOut + "-mapping"},
|
||||||
{"listen", "127.0.0.1"},
|
{"listen", "127.0.0.1"},
|
||||||
{"listen_port", mapping_port},
|
{"listen_port", mapping_port},
|
||||||
{"override_address", ent->bean->serverAddress},
|
{"override_address", ent->bean->serverAddress},
|
||||||
{"override_port", ent->bean->serverPort},};
|
{"override_port", ent->bean->serverPort},
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
status->inbounds += QJsonObject{{"protocol", "dokodemo-door"},
|
status->inbounds += QJsonObject{
|
||||||
|
{"protocol", "dokodemo-door"},
|
||||||
{"tag", tagOut + "-mapping"},
|
{"tag", tagOut + "-mapping"},
|
||||||
{"listen", "127.0.0.1"},
|
{"listen", "127.0.0.1"},
|
||||||
{"port", mapping_port},
|
{"port", mapping_port},
|
||||||
{"settings", QJsonObject{ // to
|
{"settings", QJsonObject{
|
||||||
|
// to
|
||||||
{"address", ent->bean->serverAddress},
|
{"address", ent->bean->serverAddress},
|
||||||
{"port", ent->bean->serverPort},
|
{"port", ent->bean->serverPort},
|
||||||
{"network", "tcp,udp"},}},};
|
{"network", "tcp,udp"},
|
||||||
|
}},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
// no chain rule and not outbound, so need to set to direct
|
// no chain rule and not outbound, so need to set to direct
|
||||||
if (isFirstProfile) {
|
if (isFirstProfile) {
|
||||||
if (IS_NEKO_BOX) {
|
if (IS_NEKO_BOX) {
|
||||||
status->routingRules += QJsonObject{{"inbound", QJsonArray{tagOut + "-mapping"}},
|
status->routingRules += QJsonObject{
|
||||||
{"outbound", "direct"},};
|
{"inbound", QJsonArray{tagOut + "-mapping"}},
|
||||||
|
{"outbound", "direct"},
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
status->routingRules += QJsonObject{{"type", "field"},
|
status->routingRules += QJsonObject{
|
||||||
|
{"type", "field"},
|
||||||
{"inboundTag", QJsonArray{tagOut + "-mapping"}},
|
{"inboundTag", QJsonArray{tagOut + "-mapping"}},
|
||||||
{"outboundTag", "direct"},};
|
{"outboundTag", "direct"},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -487,11 +532,17 @@ namespace NekoRay {
|
|||||||
if (IS_NEKO_BOX) {
|
if (IS_NEKO_BOX) {
|
||||||
// TODO no such field?
|
// TODO no such field?
|
||||||
auto ds = dataStore->outbound_domain_strategy;
|
auto ds = dataStore->outbound_domain_strategy;
|
||||||
if (ds == "UseIPv4") { ds = "ipv4_only"; }
|
if (ds == "UseIPv4") {
|
||||||
else if (ds == "UseIPv6") { ds = "ipv6_only"; }
|
ds = "ipv4_only";
|
||||||
else if (ds == "PreferIPv4") { ds = "prefer_ipv4"; }
|
} else if (ds == "UseIPv6") {
|
||||||
else if (ds == "PreferIPv6") { ds = "prefer_ipv6"; }
|
ds = "ipv6_only";
|
||||||
else { ds = ""; }
|
} else if (ds == "PreferIPv4") {
|
||||||
|
ds = "prefer_ipv4";
|
||||||
|
} else if (ds == "PreferIPv6") {
|
||||||
|
ds = "prefer_ipv6";
|
||||||
|
} else {
|
||||||
|
ds = "";
|
||||||
|
}
|
||||||
outbound["domain_strategy"] = ds;
|
outbound["domain_strategy"] = ds;
|
||||||
// TODO apply mux
|
// TODO apply mux
|
||||||
} else {
|
} else {
|
||||||
@@ -500,8 +551,10 @@ namespace NekoRay {
|
|||||||
if (dataStore->mux_cool > 0 && !muxApplied) {
|
if (dataStore->mux_cool > 0 && !muxApplied) {
|
||||||
// TODO refactor mux settings
|
// TODO refactor mux settings
|
||||||
if (ent->type == "vmess" || ent->type == "trojan" || ent->type == "vless") {
|
if (ent->type == "vmess" || ent->type == "trojan" || ent->type == "vless") {
|
||||||
auto muxObj = QJsonObject{{"enabled", true},
|
auto muxObj = QJsonObject{
|
||||||
{"concurrency", dataStore->mux_cool},};
|
{"enabled", true},
|
||||||
|
{"concurrency", dataStore->mux_cool},
|
||||||
|
};
|
||||||
auto stream = GetStreamSettings(ent->bean.data());
|
auto stream = GetStreamSettings(ent->bean.data());
|
||||||
if (stream != nullptr && !stream->packet_encoding.isEmpty()) {
|
if (stream != nullptr && !stream->packet_encoding.isEmpty()) {
|
||||||
muxObj["packetEncoding"] = stream->packet_encoding;
|
muxObj["packetEncoding"] = stream->packet_encoding;
|
||||||
@@ -538,8 +591,7 @@ namespace NekoRay {
|
|||||||
|
|
||||||
// SingBox
|
// SingBox
|
||||||
|
|
||||||
QSharedPointer<BuildConfigResult>
|
QSharedPointer<BuildConfigResult> BuildConfigSingBox(const QSharedPointer<ProxyEntity> &ent, bool forTest, bool forExport) {
|
||||||
BuildConfigSingBox(const QSharedPointer<ProxyEntity> &ent, bool forTest, bool forExport) {
|
|
||||||
auto result = QSharedPointer<BuildConfigResult>(new BuildConfigResult);
|
auto result = QSharedPointer<BuildConfigResult>(new BuildConfigResult);
|
||||||
auto status = QSharedPointer<BuildConfigStatus>(new BuildConfigStatus);
|
auto status = QSharedPointer<BuildConfigStatus>(new BuildConfigStatus);
|
||||||
status->ent = ent;
|
status->ent = ent;
|
||||||
@@ -560,7 +612,6 @@ namespace NekoRay {
|
|||||||
if (dataStore->sniffing_mode != SniffingMode::DISABLE) {
|
if (dataStore->sniffing_mode != SniffingMode::DISABLE) {
|
||||||
socksInbound["sniff"] = true;
|
socksInbound["sniff"] = true;
|
||||||
socksInbound["sniff_override_destination"] = dataStore->sniffing_mode == SniffingMode::FOR_DESTINATION;
|
socksInbound["sniff_override_destination"] = dataStore->sniffing_mode == SniffingMode::FOR_DESTINATION;
|
||||||
|
|
||||||
}
|
}
|
||||||
status->inbounds += socksInbound;
|
status->inbounds += socksInbound;
|
||||||
}
|
}
|
||||||
@@ -570,14 +621,22 @@ namespace NekoRay {
|
|||||||
if (!result->error.isEmpty()) return result;
|
if (!result->error.isEmpty()) return result;
|
||||||
|
|
||||||
// direct & bypass & block
|
// direct & bypass & block
|
||||||
status->outbounds += QJsonObject{{"type", "direct"},
|
status->outbounds += QJsonObject{
|
||||||
{"tag", "direct"},};
|
{"type", "direct"},
|
||||||
status->outbounds += QJsonObject{{"type", "direct"},
|
{"tag", "direct"},
|
||||||
{"tag", "bypass"},};
|
};
|
||||||
status->outbounds += QJsonObject{{"type", "block"},
|
status->outbounds += QJsonObject{
|
||||||
{"tag", "block"},};
|
{"type", "direct"},
|
||||||
status->outbounds += QJsonObject{{"type", "dns"},
|
{"tag", "bypass"},
|
||||||
{"tag", "dns-out"},};
|
};
|
||||||
|
status->outbounds += QJsonObject{
|
||||||
|
{"type", "block"},
|
||||||
|
{"tag", "block"},
|
||||||
|
};
|
||||||
|
status->outbounds += QJsonObject{
|
||||||
|
{"type", "dns"},
|
||||||
|
{"tag", "dns-out"},
|
||||||
|
};
|
||||||
|
|
||||||
// custom inbound
|
// custom inbound
|
||||||
QJSONARRAY_ADD(status->inbounds, QString2QJsonObject(dataStore->custom_inbound)["inbounds"].toArray())
|
QJSONARRAY_ADD(status->inbounds, QString2QJsonObject(dataStore->custom_inbound)["inbounds"].toArray())
|
||||||
@@ -636,8 +695,9 @@ namespace NekoRay {
|
|||||||
rule["ip_cidr"] = ips;
|
rule["ip_cidr"] = ips;
|
||||||
rule["geoip"] = geoips;
|
rule["geoip"] = geoips;
|
||||||
} else {
|
} else {
|
||||||
if (domain_keyword.isEmpty() && domain_subdomain.isEmpty() && domain_full.isEmpty()
|
if (domain_keyword.isEmpty() && domain_subdomain.isEmpty() && domain_full.isEmpty() && geosites.isEmpty()) {
|
||||||
&& geosites.isEmpty()) { return rule; }
|
return rule;
|
||||||
|
}
|
||||||
rule["domain"] = domain_full;
|
rule["domain"] = domain_full;
|
||||||
rule["domain_suffix"] = domain_suffix;
|
rule["domain_suffix"] = domain_suffix;
|
||||||
rule["domain_keyword"] = domain_keyword;
|
rule["domain_keyword"] = domain_keyword;
|
||||||
@@ -653,10 +713,12 @@ namespace NekoRay {
|
|||||||
|
|
||||||
// Remote
|
// Remote
|
||||||
if (!forTest)
|
if (!forTest)
|
||||||
dnsServers += QJsonObject{{"tag", "dns-remote"},
|
dnsServers += QJsonObject{
|
||||||
|
{"tag", "dns-remote"},
|
||||||
{"address_resolver", "dns-underlying"},
|
{"address_resolver", "dns-underlying"},
|
||||||
{"address", dataStore->remote_dns},
|
{"address", dataStore->remote_dns},
|
||||||
{"detour", tagProxy},};
|
{"detour", tagProxy},
|
||||||
|
};
|
||||||
|
|
||||||
// neko only
|
// neko only
|
||||||
auto underlyingStr = forExport ? "local" : "underlying://0.0.0.0";
|
auto underlyingStr = forExport ? "local" : "underlying://0.0.0.0";
|
||||||
@@ -665,15 +727,19 @@ namespace NekoRay {
|
|||||||
auto directDNSAddress = dataStore->direct_dns;
|
auto directDNSAddress = dataStore->direct_dns;
|
||||||
if (directDNSAddress == "localhost") directDNSAddress = underlyingStr;
|
if (directDNSAddress == "localhost") directDNSAddress = underlyingStr;
|
||||||
if (!forTest)
|
if (!forTest)
|
||||||
dnsServers += QJsonObject{{"tag", "dns-direct"},
|
dnsServers += QJsonObject{
|
||||||
|
{"tag", "dns-direct"},
|
||||||
{"address_resolver", "dns-underlying"},
|
{"address_resolver", "dns-underlying"},
|
||||||
{"address", directDNSAddress.replace("+local://", "://")},
|
{"address", directDNSAddress.replace("+local://", "://")},
|
||||||
{"detour", "direct"},};
|
{"detour", "direct"},
|
||||||
|
};
|
||||||
|
|
||||||
// Underlying 100% Working DNS
|
// Underlying 100% Working DNS
|
||||||
dnsServers += QJsonObject{{"tag", "dns-underlying"},
|
dnsServers += QJsonObject{
|
||||||
|
{"tag", "dns-underlying"},
|
||||||
{"address", underlyingStr},
|
{"address", underlyingStr},
|
||||||
{"detour", "direct"},};
|
{"detour", "direct"},
|
||||||
|
};
|
||||||
|
|
||||||
// DNS rules
|
// DNS rules
|
||||||
auto add_rule_dns = [&](const QJsonArray &arr, const QString &server) {
|
auto add_rule_dns = [&](const QJsonArray &arr, const QString &server) {
|
||||||
@@ -740,9 +806,18 @@ namespace NekoRay {
|
|||||||
auto routeObj = QJsonObject{
|
auto routeObj = QJsonObject{
|
||||||
{"rules", routingRules},
|
{"rules", routingRules},
|
||||||
{"auto_detect_interface", true},
|
{"auto_detect_interface", true},
|
||||||
{"geoip", QJsonObject{{"path", geoip},},},
|
{
|
||||||
{"geosite", QJsonObject{{"path", geosite},},}
|
"geoip",
|
||||||
};
|
QJsonObject{
|
||||||
|
{"path", geoip},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geosite",
|
||||||
|
QJsonObject{
|
||||||
|
{"path", geosite},
|
||||||
|
},
|
||||||
|
}};
|
||||||
if (forExport) {
|
if (forExport) {
|
||||||
routeObj.remove("geoip");
|
routeObj.remove("geoip");
|
||||||
routeObj.remove("geosite");
|
routeObj.remove("geosite");
|
||||||
@@ -758,8 +833,7 @@ namespace NekoRay {
|
|||||||
{"stats", QJsonObject{
|
{"stats", QJsonObject{
|
||||||
{"enabled", true},
|
{"enabled", true},
|
||||||
{"outbounds", QJsonArray{tagProxy, "bypass"}},
|
{"outbounds", QJsonArray{tagProxy, "bypass"}},
|
||||||
}}
|
}}}},
|
||||||
}},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -827,4 +901,4 @@ namespace NekoRay {
|
|||||||
return QFileInfo(file2).absoluteFilePath();
|
return QFileInfo(file2).absoluteFilePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace NekoRay
|
||||||
@@ -58,4 +58,4 @@ namespace NekoRay {
|
|||||||
QString WriteVPNSingBoxConfig();
|
QString WriteVPNSingBoxConfig();
|
||||||
|
|
||||||
QString WriteVPNLinuxScript(const QString &protectPath, const QString &configPath);
|
QString WriteVPNLinuxScript(const QString &protectPath, const QString &configPath);
|
||||||
}
|
} // namespace NekoRay
|
||||||
|
|||||||
@@ -141,7 +141,11 @@ namespace NekoRay {
|
|||||||
// Profile
|
// Profile
|
||||||
|
|
||||||
int ProfileManager::NewProfileID() const {
|
int ProfileManager::NewProfileID() const {
|
||||||
if (profiles.empty()) { return 0; } else { return profiles.lastKey() + 1; }
|
if (profiles.empty()) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return profiles.lastKey() + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProfileManager::AddProfile(const QSharedPointer<ProxyEntity> &ent, int gid) {
|
bool ProfileManager::AddProfile(const QSharedPointer<ProxyEntity> &ent, int gid) {
|
||||||
@@ -192,7 +196,7 @@ namespace NekoRay {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Group
|
// Group
|
||||||
|
|
||||||
Group::Group() {
|
Group::Group() {
|
||||||
_add(new configItem("id", &id, itemType::integer));
|
_add(new configItem("id", &id, itemType::integer));
|
||||||
@@ -212,7 +216,11 @@ namespace NekoRay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ProfileManager::NewGroupID() const {
|
int ProfileManager::NewGroupID() const {
|
||||||
if (groups.empty()) { return 0; } else { return groups.lastKey() + 1; }
|
if (groups.empty()) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return groups.lastKey() + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProfileManager::AddGroup(const QSharedPointer<Group> &ent) {
|
bool ProfileManager::AddGroup(const QSharedPointer<Group> &ent) {
|
||||||
@@ -277,4 +285,4 @@ namespace NekoRay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace NekoRay
|
||||||
@@ -51,4 +51,4 @@ namespace NekoRay {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern ProfileManager *profileManager;
|
extern ProfileManager *profileManager;
|
||||||
}
|
} // namespace NekoRay
|
||||||
|
|||||||
@@ -22,4 +22,4 @@ namespace NekoRay {
|
|||||||
// 按 显示 顺序
|
// 按 显示 顺序
|
||||||
[[nodiscard]] QList<QSharedPointer<ProxyEntity>> ProfilesWithOrder() const;
|
[[nodiscard]] QList<QSharedPointer<ProxyEntity>> ProfilesWithOrder() const;
|
||||||
};
|
};
|
||||||
}
|
} // namespace NekoRay
|
||||||
|
|||||||
@@ -22,10 +22,9 @@ namespace NekoRay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ProfileFilter::Common(const QList<QSharedPointer<ProxyEntity>> &src,
|
||||||
ProfileFilter::Common(const QList<QSharedPointer<ProxyEntity>> &src,
|
|
||||||
const QList<QSharedPointer<ProxyEntity>> &dst,
|
const QList<QSharedPointer<ProxyEntity>> &dst,
|
||||||
QList<QSharedPointer<ProxyEntity >> &out,
|
QList<QSharedPointer<ProxyEntity>> &out,
|
||||||
bool by_address, bool keep_last) {
|
bool by_address, bool keep_last) {
|
||||||
QMap<QString, QSharedPointer<ProxyEntity>> hashMap;
|
QMap<QString, QSharedPointer<ProxyEntity>> hashMap;
|
||||||
|
|
||||||
@@ -65,8 +64,7 @@ namespace NekoRay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ProfileFilter::OnlyInSrc_ByPointer(const QList<QSharedPointer<ProxyEntity>> &src,
|
||||||
ProfileFilter::OnlyInSrc_ByPointer(const QList<QSharedPointer<ProxyEntity>> &src,
|
|
||||||
const QList<QSharedPointer<ProxyEntity>> &dst,
|
const QList<QSharedPointer<ProxyEntity>> &dst,
|
||||||
QList<QSharedPointer<ProxyEntity>> &out) {
|
QList<QSharedPointer<ProxyEntity>> &out) {
|
||||||
for (const auto &ent: src) {
|
for (const auto &ent: src) {
|
||||||
@@ -74,4 +72,4 @@ namespace NekoRay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace NekoRay
|
||||||
@@ -8,29 +8,28 @@ namespace NekoRay {
|
|||||||
static void Uniq(
|
static void Uniq(
|
||||||
const QList<QSharedPointer<ProxyEntity>> &in,
|
const QList<QSharedPointer<ProxyEntity>> &in,
|
||||||
QList<QSharedPointer<ProxyEntity>> &out,
|
QList<QSharedPointer<ProxyEntity>> &out,
|
||||||
bool by_address = false, //def by bean
|
bool by_address = false, // def by bean
|
||||||
bool keep_last = false //def keep first
|
bool keep_last = false // def keep first
|
||||||
);
|
);
|
||||||
|
|
||||||
static void Common(
|
static void Common(
|
||||||
const QList<QSharedPointer<ProxyEntity>> &src,
|
const QList<QSharedPointer<ProxyEntity>> &src,
|
||||||
const QList<QSharedPointer<ProxyEntity>> &dst,
|
const QList<QSharedPointer<ProxyEntity>> &dst,
|
||||||
QList<QSharedPointer<ProxyEntity>> &out,
|
QList<QSharedPointer<ProxyEntity>> &out,
|
||||||
bool by_address = false, //def by bean
|
bool by_address = false, // def by bean
|
||||||
bool keep_last = false //def keep first
|
bool keep_last = false // def keep first
|
||||||
);
|
);
|
||||||
|
|
||||||
static void OnlyInSrc(
|
static void OnlyInSrc(
|
||||||
const QList<QSharedPointer<ProxyEntity>> &src,
|
const QList<QSharedPointer<ProxyEntity>> &src,
|
||||||
const QList<QSharedPointer<ProxyEntity>> &dst,
|
const QList<QSharedPointer<ProxyEntity>> &dst,
|
||||||
QList<QSharedPointer<NekoRay::ProxyEntity>> &out,
|
QList<QSharedPointer<NekoRay::ProxyEntity>> &out,
|
||||||
bool by_address = false //def by bean
|
bool by_address = false // def by bean
|
||||||
);
|
);
|
||||||
|
|
||||||
static void OnlyInSrc_ByPointer(
|
static void OnlyInSrc_ByPointer(
|
||||||
const QList<QSharedPointer<ProxyEntity>> &src,
|
const QList<QSharedPointer<ProxyEntity>> &src,
|
||||||
const QList<QSharedPointer<ProxyEntity>> &dst,
|
const QList<QSharedPointer<ProxyEntity>> &dst,
|
||||||
QList<QSharedPointer<ProxyEntity>> &out
|
QList<QSharedPointer<ProxyEntity>> &out);
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}
|
} // namespace NekoRay
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace NekoRay {
|
|||||||
class CustomBean;
|
class CustomBean;
|
||||||
|
|
||||||
class ChainBean;
|
class ChainBean;
|
||||||
};
|
}; // namespace fmt
|
||||||
|
|
||||||
class ProxyEntity : public JsonStore {
|
class ProxyEntity : public JsonStore {
|
||||||
public:
|
public:
|
||||||
@@ -29,8 +29,7 @@ namespace NekoRay {
|
|||||||
int gid = 0;
|
int gid = 0;
|
||||||
int latency = 0;
|
int latency = 0;
|
||||||
QSharedPointer<fmt::AbstractBean> bean;
|
QSharedPointer<fmt::AbstractBean> bean;
|
||||||
QSharedPointer<traffic::TrafficData> traffic_data = QSharedPointer<traffic::TrafficData>(
|
QSharedPointer<traffic::TrafficData> traffic_data = QSharedPointer<traffic::TrafficData>(new traffic::TrafficData(""));
|
||||||
new traffic::TrafficData(""));
|
|
||||||
|
|
||||||
// Cache
|
// Cache
|
||||||
QString full_test_report;
|
QString full_test_report;
|
||||||
@@ -68,6 +67,5 @@ namespace NekoRay {
|
|||||||
[[nodiscard]] fmt::CustomBean *CustomBean() const {
|
[[nodiscard]] fmt::CustomBean *CustomBean() const {
|
||||||
return (fmt::CustomBean *) bean.get();
|
return (fmt::CustomBean *) bean.get();
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
} // namespace NekoRay
|
||||||
|
|||||||
@@ -37,4 +37,4 @@ namespace NekoRay::traffic {
|
|||||||
return QString("%1↑ %2↓").arg(ReadableSize(uplink), ReadableSize(downlink));
|
return QString("%1↑ %2↓").arg(ReadableSize(uplink), ReadableSize(downlink));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace NekoRay::traffic
|
||||||
|
|||||||
@@ -111,8 +111,7 @@ namespace NekoRay::traffic {
|
|||||||
runOnUiThread([=] {
|
runOnUiThread([=] {
|
||||||
auto m = GetMainWindow();
|
auto m = GetMainWindow();
|
||||||
if (proxy != nullptr) {
|
if (proxy != nullptr) {
|
||||||
m->refresh_status(
|
m->refresh_status(QObject::tr("Proxy: %1\nDirect: %2").arg(proxy->DisplaySpeed(), bypass->DisplaySpeed()));
|
||||||
QObject::tr("Proxy: %1\nDirect: %2").arg(proxy->DisplaySpeed(), bypass->DisplaySpeed()));
|
|
||||||
}
|
}
|
||||||
for (const auto &item: items) {
|
for (const auto &item: items) {
|
||||||
if (item->id < 0) continue;
|
if (item->id < 0) continue;
|
||||||
@@ -125,4 +124,4 @@ namespace NekoRay::traffic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace NekoRay::traffic
|
||||||
|
|||||||
@@ -28,4 +28,4 @@ namespace NekoRay::traffic {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern TrafficLooper *trafficLooper;
|
extern TrafficLooper *trafficLooper;
|
||||||
}
|
} // namespace NekoRay::traffic
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ namespace NekoRay::fmt {
|
|||||||
url.setScheme("nekoray");
|
url.setScheme("nekoray");
|
||||||
url.setHost(type);
|
url.setHost(type);
|
||||||
url.setFragment(QJsonObject2QString(b, true)
|
url.setFragment(QJsonObject2QString(b, true)
|
||||||
.toUtf8().toBase64(QByteArray::Base64UrlEncoding));
|
.toUtf8()
|
||||||
|
.toBase64(QByteArray::Base64UrlEncoding));
|
||||||
return url.toString();
|
return url.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,4 +73,4 @@ namespace NekoRay::fmt {
|
|||||||
onFinished();
|
onFinished();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ namespace NekoRay::fmt {
|
|||||||
virtual QString InsecureHint() { return {}; };
|
virtual QString InsecureHint() { return {}; };
|
||||||
|
|
||||||
QString DisplayInsecureHint();
|
QString DisplayInsecureHint();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace NekoRay::fmt {
|
|||||||
// https://sing-box.sagernet.org/configuration/shared/v2ray-transport
|
// https://sing-box.sagernet.org/configuration/shared/v2ray-transport
|
||||||
|
|
||||||
if (network != "tcp") {
|
if (network != "tcp") {
|
||||||
QJsonObject transport{{"type", network},};
|
QJsonObject transport{{"type", network}};
|
||||||
if (network == "ws") {
|
if (network == "ws") {
|
||||||
if (!path.isEmpty()) transport["path"] = path;
|
if (!path.isEmpty()) transport["path"] = path;
|
||||||
if (!host.isEmpty()) transport["headers"] = QJsonObject{{"Host", host}};
|
if (!host.isEmpty()) transport["headers"] = QJsonObject{{"Host", host}};
|
||||||
@@ -154,4 +154,4 @@ namespace NekoRay::fmt {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
|
|||||||
@@ -2,16 +2,14 @@
|
|||||||
#include "fmt/includes.h"
|
#include "fmt/includes.h"
|
||||||
|
|
||||||
#define MAKE_SETTINGS_STREAM_SETTINGS \
|
#define MAKE_SETTINGS_STREAM_SETTINGS \
|
||||||
if (!stream->packet_encoding.isEmpty()) settings["packetEncoding"] = stream->packet_encoding; \
|
if (!stream->packet_encoding.isEmpty()) settings["packetEncoding"] = stream->packet_encoding; \
|
||||||
outbound["settings"] = settings; \
|
outbound["settings"] = settings; \
|
||||||
auto streamSettings = stream->BuildStreamSettingsV2Ray(); \
|
auto streamSettings = stream->BuildStreamSettingsV2Ray(); \
|
||||||
outbound["streamSettings"] = streamSettings;
|
outbound["streamSettings"] = streamSettings;
|
||||||
|
|
||||||
namespace NekoRay::fmt {
|
namespace NekoRay::fmt {
|
||||||
QJsonObject V2rayStreamSettings::BuildStreamSettingsV2Ray() {
|
QJsonObject V2rayStreamSettings::BuildStreamSettingsV2Ray() {
|
||||||
QJsonObject streamSettings{
|
QJsonObject streamSettings{{"network", network}};
|
||||||
{"network", network},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (network == "ws") {
|
if (network == "ws") {
|
||||||
QJsonObject ws;
|
QJsonObject ws;
|
||||||
@@ -140,11 +138,8 @@ namespace NekoRay::fmt {
|
|||||||
{"id", uuid.trimmed()},
|
{"id", uuid.trimmed()},
|
||||||
{"alterId", aid},
|
{"alterId", aid},
|
||||||
{"security", security},
|
{"security", security},
|
||||||
}
|
}}},
|
||||||
}},
|
}}}};
|
||||||
}
|
|
||||||
}}
|
|
||||||
};
|
|
||||||
|
|
||||||
MAKE_SETTINGS_STREAM_SETTINGS
|
MAKE_SETTINGS_STREAM_SETTINGS
|
||||||
|
|
||||||
@@ -169,11 +164,8 @@ namespace NekoRay::fmt {
|
|||||||
QJsonObject{
|
QJsonObject{
|
||||||
{"id", password.trimmed()},
|
{"id", password.trimmed()},
|
||||||
{"encryption", "none"},
|
{"encryption", "none"},
|
||||||
}
|
}}},
|
||||||
}},
|
}}}};
|
||||||
}
|
|
||||||
}}
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
settings = QJsonObject{
|
settings = QJsonObject{
|
||||||
{"servers", QJsonArray{
|
{"servers", QJsonArray{
|
||||||
@@ -181,9 +173,7 @@ namespace NekoRay::fmt {
|
|||||||
{"address", serverAddress},
|
{"address", serverAddress},
|
||||||
{"port", serverPort},
|
{"port", serverPort},
|
||||||
{"password", password},
|
{"password", password},
|
||||||
}
|
}}}};
|
||||||
}}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MAKE_SETTINGS_STREAM_SETTINGS
|
MAKE_SETTINGS_STREAM_SETTINGS
|
||||||
@@ -201,4 +191,4 @@ namespace NekoRay::fmt {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
@@ -6,17 +6,17 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
|
||||||
#define WriteTempFile(fn, data) \
|
#define WriteTempFile(fn, data) \
|
||||||
QDir dir; \
|
QDir dir; \
|
||||||
if (!dir.exists("temp")) dir.mkdir("temp"); \
|
if (!dir.exists("temp")) dir.mkdir("temp"); \
|
||||||
QFile f(QString("temp/") + fn); \
|
QFile f(QString("temp/") + fn); \
|
||||||
bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); \
|
bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); \
|
||||||
if (ok) { \
|
if (ok) { \
|
||||||
f.write(data); \
|
f.write(data); \
|
||||||
} else { \
|
} else { \
|
||||||
result.error = f.errorString(); \
|
result.error = f.errorString(); \
|
||||||
} \
|
} \
|
||||||
f.close(); \
|
f.close(); \
|
||||||
auto TempFile = QFileInfo(f).absoluteFilePath();
|
auto TempFile = QFileInfo(f).absoluteFilePath();
|
||||||
|
|
||||||
namespace NekoRay::fmt {
|
namespace NekoRay::fmt {
|
||||||
// 0: no external
|
// 0: no external
|
||||||
@@ -123,4 +123,4 @@ namespace NekoRay::fmt {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
@@ -90,4 +90,4 @@ namespace NekoRay::fmt {
|
|||||||
return url.toString();
|
return url.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
@@ -15,4 +15,4 @@ namespace NekoRay::fmt {
|
|||||||
|
|
||||||
QString DisplayAddress() override { return ""; };
|
QString DisplayAddress() override { return ""; };
|
||||||
};
|
};
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
|
|||||||
@@ -47,4 +47,4 @@ namespace NekoRay::fmt {
|
|||||||
|
|
||||||
CoreObjOutboundBuildResult BuildCoreObjV2Ray() override;
|
CoreObjOutboundBuildResult BuildCoreObjV2Ray() override;
|
||||||
};
|
};
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
@@ -15,9 +15,7 @@ namespace NekoRay::fmt {
|
|||||||
|
|
||||||
QString V2rayStreamSettings::InsecureHint() const {
|
QString V2rayStreamSettings::InsecureHint() const {
|
||||||
if (allow_insecure) {
|
if (allow_insecure) {
|
||||||
return QObject::tr(
|
return QObject::tr("The configuration (insecure) can be detected and identified, the transmission is fully visible to the censor and is not resistant to man-in-the-middle tampering with the content of the communication.");
|
||||||
"The configuration (insecure) can be detected and identified, the transmission is fully visible to the censor and is not resistant to man-in-the-middle tampering with the content of the communication."
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -29,23 +27,20 @@ namespace NekoRay::fmt {
|
|||||||
return QObject::tr(
|
return QObject::tr(
|
||||||
"This configuration (Shadowsocks streaming cipher) can be accurately proactively detected and decrypted by censors without requiring a password, and cannot be mitigated by turning on IV replay filters on the server side.\n"
|
"This configuration (Shadowsocks streaming cipher) can be accurately proactively detected and decrypted by censors without requiring a password, and cannot be mitigated by turning on IV replay filters on the server side.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Learn more: https://github.com/net4people/bbs/issues/24"
|
"Learn more: https://github.com/net4people/bbs/issues/24");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString VMessBean::InsecureHint() {
|
QString VMessBean::InsecureHint() {
|
||||||
if (security == "none" || security == "zero") {
|
if (security == "none" || security == "zero") {
|
||||||
if (stream->security.isEmpty()) {
|
if (stream->security.isEmpty()) {
|
||||||
return QObject::tr(
|
return QObject::tr("This profile is cleartext, don't use it if the server is not in your local network.");
|
||||||
"This profile is cleartext, don't use it if the server is not in your local network.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (aid > 0) {
|
if (aid > 0) {
|
||||||
return QObject::tr(
|
return QObject::tr(
|
||||||
"This configuration (VMess MD5 authentication) has been deprecated by upstream because of its questionable resistance to tampering and concealment.\n"
|
"This configuration (VMess MD5 authentication) has been deprecated by upstream because of its questionable resistance to tampering and concealment.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"As of January 1, 2022, compatibility with MD5 authentication information will be disabled on the server side by default. Any client using MD5 authentication information will not be able to connect to a server with VMess MD5 authentication information disabled."
|
"As of January 1, 2022, compatibility with MD5 authentication information will be disabled on the server side by default. Any client using MD5 authentication information will not be able to connect to a server with VMess MD5 authentication information disabled.");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -63,5 +58,4 @@ namespace NekoRay::fmt {
|
|||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
namespace NekoRay::fmt {
|
namespace NekoRay::fmt {
|
||||||
|
|
||||||
#define DECODE_V2RAY_N_1 auto linkN = DecodeB64IfValid(SubStrBefore(SubStrAfter(link, "://"), "#"), QByteArray::Base64Option::Base64UrlEncoding); \
|
#define DECODE_V2RAY_N_1 \
|
||||||
|
auto linkN = DecodeB64IfValid(SubStrBefore(SubStrAfter(link, "://"), "#"), QByteArray::Base64Option::Base64UrlEncoding); \
|
||||||
if (linkN.isEmpty()) return false; \
|
if (linkN.isEmpty()) return false; \
|
||||||
auto hasRemarks = link.contains("#"); \
|
auto hasRemarks = link.contains("#"); \
|
||||||
if (hasRemarks) linkN += "#" + SubStrAfter(link, "#"); \
|
if (hasRemarks) linkN += "#" + SubStrAfter(link, "#"); \
|
||||||
@@ -149,4 +150,4 @@ namespace NekoRay::fmt {
|
|||||||
return !(username.isEmpty() || password.isEmpty());
|
return !(username.isEmpty() || password.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
|
|||||||
@@ -35,4 +35,4 @@ namespace NekoRay::fmt {
|
|||||||
|
|
||||||
QString ToShareLink() override;
|
QString ToShareLink() override;
|
||||||
};
|
};
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
@@ -3,7 +3,8 @@
|
|||||||
namespace Preset {
|
namespace Preset {
|
||||||
namespace Hysteria {
|
namespace Hysteria {
|
||||||
inline const char *command = "--no-check -c %config%";
|
inline const char *command = "--no-check -c %config%";
|
||||||
inline const char *config = "{\n"
|
inline const char *config =
|
||||||
|
"{\n"
|
||||||
" \"server\": \"127.0.0.1:%mapping_port%\",\n"
|
" \"server\": \"127.0.0.1:%mapping_port%\",\n"
|
||||||
" \"server_name\": \"example.com\",\n"
|
" \"server_name\": \"example.com\",\n"
|
||||||
" \"obfs\": \"fuck me till the daylight\",\n"
|
" \"obfs\": \"fuck me till the daylight\",\n"
|
||||||
@@ -13,7 +14,7 @@ namespace Preset {
|
|||||||
" \"listen\": \"127.0.0.1:%socks_port%\"\n"
|
" \"listen\": \"127.0.0.1:%socks_port%\"\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}";
|
"}";
|
||||||
}
|
} // namespace Hysteria
|
||||||
|
|
||||||
namespace SingBox {
|
namespace SingBox {
|
||||||
inline QStringList VpnImplementation = {"gvisor", "system"};
|
inline QStringList VpnImplementation = {"gvisor", "system"};
|
||||||
@@ -25,4 +26,4 @@ namespace Preset {
|
|||||||
"http={ip}:{http_port};https={ip}:{http_port};ftp={ip}:{http_port};socks={ip}:{socks_port}",
|
"http={ip}:{http_port};https={ip}:{http_port};ftp={ip}:{http_port};socks={ip}:{socks_port}",
|
||||||
"http=http://{ip}:{http_port};https=http://{ip}:{http_port}"};
|
"http=http://{ip}:{http_port};https=http://{ip}:{http_port}"};
|
||||||
}
|
}
|
||||||
}
|
} // namespace Preset
|
||||||
|
|||||||
@@ -33,4 +33,4 @@ namespace NekoRay::fmt {
|
|||||||
|
|
||||||
QString InsecureHint() override;
|
QString InsecureHint() override;
|
||||||
};
|
};
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
|
|||||||
@@ -38,4 +38,4 @@ namespace NekoRay::fmt {
|
|||||||
|
|
||||||
QString InsecureHint() override;
|
QString InsecureHint() override;
|
||||||
};
|
};
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
|
|||||||
@@ -34,4 +34,4 @@ namespace NekoRay::fmt {
|
|||||||
|
|
||||||
QString InsecureHint() override;
|
QString InsecureHint() override;
|
||||||
};
|
};
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
@@ -56,4 +56,4 @@ namespace NekoRay::fmt {
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
|
|||||||
@@ -33,5 +33,4 @@ namespace NekoRay::fmt {
|
|||||||
|
|
||||||
QString InsecureHint() override;
|
QString InsecureHint() override;
|
||||||
};
|
};
|
||||||
}
|
} // namespace NekoRay::fmt
|
||||||
|
|
||||||
|
|||||||
2
libs/format_cpp.sh
Executable file
2
libs/format_cpp.sh
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
git ls-files | grep -E "\.cpp|\.h" | grep -v "3rdparty" | xargs -n1 clang-format -i
|
||||||
@@ -30,5 +30,4 @@ namespace NekoRay {
|
|||||||
SING_BOX,
|
SING_BOX,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
} // namespace NekoRay
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
|
|
||||||
#define QRegExpValidator_Number new QRegularExpressionValidator(QRegularExpression("^[0-9]+$")
|
#define QRegExpValidator_Number new QRegularExpressionValidator(QRegularExpression("^[0-9]+$"), this)
|
||||||
|
|
||||||
// NekoRay Save&Load
|
// NekoRay Save&Load
|
||||||
|
|
||||||
@@ -23,9 +23,13 @@
|
|||||||
#define P_C_SAVE_STRING(a) bean->a = CACHE.a;
|
#define P_C_SAVE_STRING(a) bean->a = CACHE.a;
|
||||||
#define D_C_LOAD_STRING(a) CACHE.a = NekoRay::dataStore->a;
|
#define D_C_LOAD_STRING(a) CACHE.a = NekoRay::dataStore->a;
|
||||||
#define D_C_SAVE_STRING(a) NekoRay::dataStore->a = CACHE.a;
|
#define D_C_SAVE_STRING(a) NekoRay::dataStore->a = CACHE.a;
|
||||||
#define P_LOAD_INT(a) ui->a->setText(Int2String(bean->a)); ui->a->setValidator(QRegExpValidator_Number, this));
|
#define P_LOAD_INT(a) \
|
||||||
|
ui->a->setText(Int2String(bean->a)); \
|
||||||
|
ui->a->setValidator(QRegExpValidator_Number);
|
||||||
#define P_SAVE_INT(a) bean->a = ui->a->text().toInt();
|
#define P_SAVE_INT(a) bean->a = ui->a->text().toInt();
|
||||||
#define D_LOAD_INT(a) ui->a->setText(Int2String(NekoRay::dataStore->a)); ui->a->setValidator(QRegExpValidator_Number, this));
|
#define D_LOAD_INT(a) \
|
||||||
|
ui->a->setText(Int2String(NekoRay::dataStore->a)); \
|
||||||
|
ui->a->setValidator(QRegExpValidator_Number);
|
||||||
#define D_SAVE_INT(a) NekoRay::dataStore->a = ui->a->text().toInt();
|
#define D_SAVE_INT(a) NekoRay::dataStore->a = ui->a->text().toInt();
|
||||||
#define P_LOAD_COMBO(a) ui->a->setCurrentText(bean->a);
|
#define P_LOAD_COMBO(a) ui->a->setCurrentText(bean->a);
|
||||||
#define P_SAVE_COMBO(a) bean->a = ui->a->currentText();
|
#define P_SAVE_COMBO(a) bean->a = ui->a->currentText();
|
||||||
@@ -33,23 +37,24 @@
|
|||||||
#define D_SAVE_BOOL(a) NekoRay::dataStore->a = ui->a->isChecked();
|
#define D_SAVE_BOOL(a) NekoRay::dataStore->a = ui->a->isChecked();
|
||||||
|
|
||||||
#define D_LOAD_INT_ENABLE(i, e) \
|
#define D_LOAD_INT_ENABLE(i, e) \
|
||||||
if (NekoRay::dataStore->i > 0) { \
|
if (NekoRay::dataStore->i > 0) { \
|
||||||
ui->e->setChecked(true); \
|
ui->e->setChecked(true); \
|
||||||
ui->i->setText(Int2String(NekoRay::dataStore->i)); \
|
ui->i->setText(Int2String(NekoRay::dataStore->i)); \
|
||||||
} else { \
|
} else { \
|
||||||
ui->e->setChecked(false); \
|
ui->e->setChecked(false); \
|
||||||
ui->i->setText(Int2String(-NekoRay::dataStore->i)); \
|
ui->i->setText(Int2String(-NekoRay::dataStore->i)); \
|
||||||
} \
|
} \
|
||||||
ui->i->setValidator(QRegExpValidator_Number, this));
|
ui->i->setValidator(QRegExpValidator_Number);
|
||||||
#define D_SAVE_INT_ENABLE(i, e) \
|
#define D_SAVE_INT_ENABLE(i, e) \
|
||||||
if (ui->e->isChecked()) { \
|
if (ui->e->isChecked()) { \
|
||||||
NekoRay::dataStore->i = ui->i->text().toInt(); \
|
NekoRay::dataStore->i = ui->i->text().toInt(); \
|
||||||
} else { \
|
} else { \
|
||||||
NekoRay::dataStore->i = -ui->i->text().toInt(); \
|
NekoRay::dataStore->i = -ui->i->text().toInt(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define C_EDIT_JSON_ALLOW_EMPTY(a) auto editor = new JsonEditor(QString2QJsonObject(CACHE.a), this); \
|
#define C_EDIT_JSON_ALLOW_EMPTY(a) \
|
||||||
auto result = editor->OpenEditor(); \
|
auto editor = new JsonEditor(QString2QJsonObject(CACHE.a), this); \
|
||||||
CACHE.a = QJsonObject2QString(result, true); \
|
auto result = editor->OpenEditor(); \
|
||||||
if (result.isEmpty()) CACHE.a = ""; \
|
CACHE.a = QJsonObject2QString(result, true); \
|
||||||
editor->deleteLater();
|
if (result.isEmpty()) CACHE.a = ""; \
|
||||||
|
editor->deleteLater();
|
||||||
|
|||||||
@@ -76,13 +76,15 @@ namespace NekoRay {
|
|||||||
// preset routing
|
// preset routing
|
||||||
Routing::Routing(int preset) : JsonStore() {
|
Routing::Routing(int preset) : JsonStore() {
|
||||||
if (preset == 1) {
|
if (preset == 1) {
|
||||||
direct_ip = "geoip:cn\n"
|
direct_ip =
|
||||||
|
"geoip:cn\n"
|
||||||
"geoip:private";
|
"geoip:private";
|
||||||
direct_domain = "geosite:cn";
|
direct_domain = "geosite:cn";
|
||||||
proxy_ip = "";
|
proxy_ip = "";
|
||||||
proxy_domain = "";
|
proxy_domain = "";
|
||||||
block_ip = "";
|
block_ip = "";
|
||||||
block_domain = "geosite:category-ads-all\n"
|
block_domain =
|
||||||
|
"geosite:category-ads-all\n"
|
||||||
"domain:appcenter.ms\n"
|
"domain:appcenter.ms\n"
|
||||||
"domain:app-measurement.com\n"
|
"domain:app-measurement.com\n"
|
||||||
"domain:firebase.io\n"
|
"domain:firebase.io\n"
|
||||||
@@ -353,4 +355,4 @@ namespace NekoRay {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace NekoRay
|
||||||
|
|||||||
@@ -60,4 +60,4 @@ namespace NekoRay {
|
|||||||
|
|
||||||
bool Load();
|
bool Load();
|
||||||
};
|
};
|
||||||
}
|
} // namespace NekoRay
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ namespace NekoRay {
|
|||||||
int test_concurrent = 5;
|
int test_concurrent = 5;
|
||||||
int traffic_loop_interval = 500;
|
int traffic_loop_interval = 500;
|
||||||
bool connection_statistics = false;
|
bool connection_statistics = false;
|
||||||
int current_group = 0; //group id
|
int current_group = 0; // group id
|
||||||
int mux_cool = -8;
|
int mux_cool = -8;
|
||||||
QString theme = "0";
|
QString theme = "0";
|
||||||
QString v2ray_asset_dir = "";
|
QString v2ray_asset_dir = "";
|
||||||
@@ -137,8 +137,8 @@ namespace NekoRay {
|
|||||||
|
|
||||||
inline int coreType = NekoRay::CoreType::V2RAY;
|
inline int coreType = NekoRay::CoreType::V2RAY;
|
||||||
|
|
||||||
}
|
} // namespace NekoRay
|
||||||
|
|
||||||
#define IS_NEKO_BOX (NekoRay::coreType == NekoRay::CoreType::SING_BOX)
|
#define IS_NEKO_BOX (NekoRay::coreType == NekoRay::CoreType::SING_BOX)
|
||||||
#define ROUTES_PREFIX_NAME QString( IS_NEKO_BOX ? "routes_box" : "routes" )
|
#define ROUTES_PREFIX_NAME QString(IS_NEKO_BOX ? "routes_box" : "routes")
|
||||||
#define ROUTES_PREFIX QString( ROUTES_PREFIX_NAME + "/" )
|
#define ROUTES_PREFIX QString(ROUTES_PREFIX_NAME + "/")
|
||||||
|
|||||||
@@ -24,9 +24,14 @@ inline std::function<void(QString, QString)> MW_dialog_message;
|
|||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
|
|
||||||
#define QJSONARRAY_ADD(arr, add) for(const auto &a: (add)) { (arr) += a; }
|
#define QJSONARRAY_ADD(arr, add) \
|
||||||
#define QJSONOBJECT_COPY(src, dst, key) if (src.contains(key)) dst[key] = src[key];
|
for (const auto &a: (add)) { \
|
||||||
#define QJSONOBJECT_COPY2(src, dst, src_key, dst_key) if (src.contains(src_key)) dst[dst_key] = src[src_key];
|
(arr) += a; \
|
||||||
|
}
|
||||||
|
#define QJSONOBJECT_COPY(src, dst, key) \
|
||||||
|
if (src.contains(key)) dst[key] = src[key];
|
||||||
|
#define QJSONOBJECT_COPY2(src, dst, src_key, dst_key) \
|
||||||
|
if (src.contains(src_key)) dst[dst_key] = src[src_key];
|
||||||
|
|
||||||
#define Int2String(num) QString::number(num)
|
#define Int2String(num) QString::number(num)
|
||||||
|
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ int main(int argc, char *argv[]) {
|
|||||||
QCoreApplication::installTranslator(&trans_qt);
|
QCoreApplication::installTranslator(&trans_qt);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Signals
|
// Signals
|
||||||
signal(SIGTERM, signal_handler);
|
signal(SIGTERM, signal_handler);
|
||||||
signal(SIGINT, signal_handler);
|
signal(SIGINT, signal_handler);
|
||||||
|
|
||||||
|
|||||||
@@ -25,11 +25,10 @@ namespace Qv2ray::components::proxy {
|
|||||||
|
|
||||||
using ProcessArgument = QPair<QString, QStringList>;
|
using ProcessArgument = QPair<QString, QStringList>;
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
QStringList macOSgetNetworkServices()
|
QStringList macOSgetNetworkServices() {
|
||||||
{
|
|
||||||
QProcess p;
|
QProcess p;
|
||||||
p.setProgram("/usr/sbin/networksetup");
|
p.setProgram("/usr/sbin/networksetup");
|
||||||
p.setArguments(QStringList{ "-listallnetworkservices" });
|
p.setArguments(QStringList{"-listallnetworkservices"});
|
||||||
p.start();
|
p.start();
|
||||||
p.waitForStarted();
|
p.waitForStarted();
|
||||||
p.waitForFinished();
|
p.waitForFinished();
|
||||||
@@ -39,11 +38,9 @@ namespace Qv2ray::components::proxy {
|
|||||||
QStringList result;
|
QStringList result;
|
||||||
|
|
||||||
// Start from 1 since first line is unneeded.
|
// Start from 1 since first line is unneeded.
|
||||||
for (auto i = 1; i < lines.count(); i++)
|
for (auto i = 1; i < lines.count(); i++) {
|
||||||
{
|
|
||||||
// * means disabled.
|
// * means disabled.
|
||||||
if (!lines[i].contains("*"))
|
if (!lines[i].contains("*")) {
|
||||||
{
|
|
||||||
result << lines[i];
|
result << lines[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,8 +55,7 @@ namespace Qv2ray::components::proxy {
|
|||||||
// NO_CONST(L"DefaultConnectionSettings");
|
// NO_CONST(L"DefaultConnectionSettings");
|
||||||
///
|
///
|
||||||
/// INTERNAL FUNCTION
|
/// INTERNAL FUNCTION
|
||||||
bool __QueryProxyOptions()
|
bool __QueryProxyOptions() {
|
||||||
{
|
|
||||||
INTERNET_PER_CONN_OPTION_LIST List;
|
INTERNET_PER_CONN_OPTION_LIST List;
|
||||||
INTERNET_PER_CONN_OPTION Option[5];
|
INTERNET_PER_CONN_OPTION Option[5];
|
||||||
//
|
//
|
||||||
@@ -76,45 +72,37 @@ namespace Qv2ray::components::proxy {
|
|||||||
List.dwOptionError = 0;
|
List.dwOptionError = 0;
|
||||||
List.pOptions = Option;
|
List.pOptions = Option;
|
||||||
|
|
||||||
if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize))
|
if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) {
|
||||||
{
|
|
||||||
LOG("InternetQueryOption failed, GLE=" + QSTRN(GetLastError()));
|
LOG("InternetQueryOption failed, GLE=" + QSTRN(GetLastError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG("System default proxy info:");
|
LOG("System default proxy info:");
|
||||||
|
|
||||||
if (Option[0].Value.pszValue != nullptr)
|
if (Option[0].Value.pszValue != nullptr) {
|
||||||
{
|
|
||||||
LOG(QString::fromWCharArray(Option[0].Value.pszValue));
|
LOG(QString::fromWCharArray(Option[0].Value.pszValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL) == PROXY_TYPE_AUTO_PROXY_URL)
|
if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL) == PROXY_TYPE_AUTO_PROXY_URL) {
|
||||||
{
|
|
||||||
LOG("PROXY_TYPE_AUTO_PROXY_URL");
|
LOG("PROXY_TYPE_AUTO_PROXY_URL");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_DETECT) == PROXY_TYPE_AUTO_DETECT)
|
if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_DETECT) == PROXY_TYPE_AUTO_DETECT) {
|
||||||
{
|
|
||||||
LOG("PROXY_TYPE_AUTO_DETECT");
|
LOG("PROXY_TYPE_AUTO_DETECT");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Option[2].Value.dwValue & PROXY_TYPE_DIRECT) == PROXY_TYPE_DIRECT)
|
if ((Option[2].Value.dwValue & PROXY_TYPE_DIRECT) == PROXY_TYPE_DIRECT) {
|
||||||
{
|
|
||||||
LOG("PROXY_TYPE_DIRECT");
|
LOG("PROXY_TYPE_DIRECT");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Option[2].Value.dwValue & PROXY_TYPE_PROXY) == PROXY_TYPE_PROXY)
|
if ((Option[2].Value.dwValue & PROXY_TYPE_PROXY) == PROXY_TYPE_PROXY) {
|
||||||
{
|
|
||||||
LOG("PROXY_TYPE_PROXY");
|
LOG("PROXY_TYPE_PROXY");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize))
|
if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) {
|
||||||
{
|
|
||||||
LOG("InternetQueryOption failed,GLE=" + QSTRN(GetLastError()));
|
LOG("InternetQueryOption failed,GLE=" + QSTRN(GetLastError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Option[4].Value.pszValue != nullptr)
|
if (Option[4].Value.pszValue != nullptr) {
|
||||||
{
|
|
||||||
LOG(QString::fromStdWString(Option[4].Value.pszValue));
|
LOG(QString::fromStdWString(Option[4].Value.pszValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,25 +110,21 @@ namespace Qv2ray::components::proxy {
|
|||||||
nSize = sizeof(INTERNET_VERSION_INFO);
|
nSize = sizeof(INTERNET_VERSION_INFO);
|
||||||
InternetQueryOption(nullptr, INTERNET_OPTION_VERSION, &Version, &nSize);
|
InternetQueryOption(nullptr, INTERNET_OPTION_VERSION, &Version, &nSize);
|
||||||
|
|
||||||
if (Option[0].Value.pszValue != nullptr)
|
if (Option[0].Value.pszValue != nullptr) {
|
||||||
{
|
|
||||||
GlobalFree(Option[0].Value.pszValue);
|
GlobalFree(Option[0].Value.pszValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Option[3].Value.pszValue != nullptr)
|
if (Option[3].Value.pszValue != nullptr) {
|
||||||
{
|
|
||||||
GlobalFree(Option[3].Value.pszValue);
|
GlobalFree(Option[3].Value.pszValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Option[4].Value.pszValue != nullptr)
|
if (Option[4].Value.pszValue != nullptr) {
|
||||||
{
|
|
||||||
GlobalFree(Option[4].Value.pszValue);
|
GlobalFree(Option[4].Value.pszValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool __SetProxyOptions(LPWSTR proxy_full_addr, bool isPAC)
|
bool __SetProxyOptions(LPWSTR proxy_full_addr, bool isPAC) {
|
||||||
{
|
|
||||||
INTERNET_PER_CONN_OPTION_LIST list;
|
INTERNET_PER_CONN_OPTION_LIST list;
|
||||||
DWORD dwBufSize = sizeof(list);
|
DWORD dwBufSize = sizeof(list);
|
||||||
// Fill the list structure.
|
// Fill the list structure.
|
||||||
@@ -148,16 +132,14 @@ namespace Qv2ray::components::proxy {
|
|||||||
// NULL == LAN, otherwise connectoid name.
|
// NULL == LAN, otherwise connectoid name.
|
||||||
list.pszConnection = nullptr;
|
list.pszConnection = nullptr;
|
||||||
|
|
||||||
if (nullptr == proxy_full_addr)
|
if (nullptr == proxy_full_addr) {
|
||||||
{
|
|
||||||
LOG("Clearing system proxy");
|
LOG("Clearing system proxy");
|
||||||
//
|
//
|
||||||
list.dwOptionCount = 1;
|
list.dwOptionCount = 1;
|
||||||
list.pOptions = new INTERNET_PER_CONN_OPTION[1];
|
list.pOptions = new INTERNET_PER_CONN_OPTION[1];
|
||||||
|
|
||||||
// Ensure that the memory was allocated.
|
// Ensure that the memory was allocated.
|
||||||
if (nullptr == list.pOptions)
|
if (nullptr == list.pOptions) {
|
||||||
{
|
|
||||||
// Return if the memory wasn't allocated.
|
// Return if the memory wasn't allocated.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -165,16 +147,13 @@ namespace Qv2ray::components::proxy {
|
|||||||
// Set flags.
|
// Set flags.
|
||||||
list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS;
|
list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS;
|
||||||
list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT;
|
list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT;
|
||||||
}
|
} else if (isPAC) {
|
||||||
else if (isPAC)
|
|
||||||
{
|
|
||||||
LOG("Setting system proxy for PAC");
|
LOG("Setting system proxy for PAC");
|
||||||
//
|
//
|
||||||
list.dwOptionCount = 2;
|
list.dwOptionCount = 2;
|
||||||
list.pOptions = new INTERNET_PER_CONN_OPTION[2];
|
list.pOptions = new INTERNET_PER_CONN_OPTION[2];
|
||||||
|
|
||||||
if (nullptr == list.pOptions)
|
if (nullptr == list.pOptions) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,16 +163,13 @@ namespace Qv2ray::components::proxy {
|
|||||||
// Set proxy name.
|
// Set proxy name.
|
||||||
list.pOptions[1].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL;
|
list.pOptions[1].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL;
|
||||||
list.pOptions[1].Value.pszValue = proxy_full_addr;
|
list.pOptions[1].Value.pszValue = proxy_full_addr;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG("Setting system proxy for Global Proxy");
|
LOG("Setting system proxy for Global Proxy");
|
||||||
//
|
//
|
||||||
list.dwOptionCount = 2;
|
list.dwOptionCount = 2;
|
||||||
list.pOptions = new INTERNET_PER_CONN_OPTION[2];
|
list.pOptions = new INTERNET_PER_CONN_OPTION[2];
|
||||||
|
|
||||||
if (nullptr == list.pOptions)
|
if (nullptr == list.pOptions) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,8 +186,7 @@ namespace Qv2ray::components::proxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set proxy for LAN.
|
// Set proxy for LAN.
|
||||||
if (!InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize))
|
if (!InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize)) {
|
||||||
{
|
|
||||||
LOG("InternetSetOption failed for LAN, GLE=" + QSTRN(GetLastError()));
|
LOG("InternetSetOption failed for LAN, GLE=" + QSTRN(GetLastError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,25 +196,21 @@ namespace Qv2ray::components::proxy {
|
|||||||
DWORD size = sizeof(entry), count;
|
DWORD size = sizeof(entry), count;
|
||||||
LPRASENTRYNAME entryAddr = &entry;
|
LPRASENTRYNAME entryAddr = &entry;
|
||||||
auto ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count);
|
auto ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count);
|
||||||
if (ERROR_BUFFER_TOO_SMALL == ret)
|
if (ERROR_BUFFER_TOO_SMALL == ret) {
|
||||||
{
|
|
||||||
entries.resize(count);
|
entries.resize(count);
|
||||||
entries[0].dwSize = sizeof(RASENTRYNAME);
|
entries[0].dwSize = sizeof(RASENTRYNAME);
|
||||||
entryAddr = entries.data();
|
entryAddr = entries.data();
|
||||||
ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count);
|
ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count);
|
||||||
}
|
}
|
||||||
if (ERROR_SUCCESS != ret)
|
if (ERROR_SUCCESS != ret) {
|
||||||
{
|
|
||||||
LOG("Failed to list entry names");
|
LOG("Failed to list entry names");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set proxy for each connectoid.
|
// Set proxy for each connectoid.
|
||||||
for (DWORD i = 0; i < count; ++i)
|
for (DWORD i = 0; i < count; ++i) {
|
||||||
{
|
|
||||||
list.pszConnection = entryAddr[i].szEntryName;
|
list.pszConnection = entryAddr[i].szEntryName;
|
||||||
if (!InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize))
|
if (!InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize)) {
|
||||||
{
|
|
||||||
LOG("InternetSetOption failed for connectoid " + QString::fromWCharArray(list.pszConnection) + ", GLE=" + QSTRN(GetLastError()));
|
LOG("InternetSetOption failed for connectoid " + QString::fromWCharArray(list.pszConnection) + ", GLE=" + QSTRN(GetLastError()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,19 +222,16 @@ namespace Qv2ray::components::proxy {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void SetSystemProxy(int httpPort, int socksPort) {
|
void SetSystemProxy(int httpPort, int socksPort) {
|
||||||
const QString &address = "127.0.0.1";
|
const QString &address = "127.0.0.1";
|
||||||
bool hasHTTP = (httpPort > 0 && httpPort < 65536);
|
bool hasHTTP = (httpPort > 0 && httpPort < 65536);
|
||||||
bool hasSOCKS = (socksPort > 0 && socksPort < 65536);
|
bool hasSOCKS = (socksPort > 0 && socksPort < 65536);
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (!hasHTTP)
|
if (!hasHTTP) {
|
||||||
{
|
|
||||||
LOG("Nothing?");
|
LOG("Nothing?");
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG("Qv2ray will set system proxy to use HTTP");
|
LOG("Qv2ray will set system proxy to use HTTP");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -294,8 +262,7 @@ void SetSystemProxy(int httpPort, int socksPort) {
|
|||||||
//
|
//
|
||||||
__QueryProxyOptions();
|
__QueryProxyOptions();
|
||||||
|
|
||||||
if (!__SetProxyOptions(proxyStrW, false))
|
if (!__SetProxyOptions(proxyStrW, false)) {
|
||||||
{
|
|
||||||
LOG("Failed to set proxy.");
|
LOG("Failed to set proxy.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,21 +359,18 @@ void SetSystemProxy(int httpPort, int socksPort) {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
for (const auto &service : macOSgetNetworkServices())
|
for (const auto &service: macOSgetNetworkServices()) {
|
||||||
{
|
|
||||||
LOG("Setting proxy for interface: " + service);
|
LOG("Setting proxy for interface: " + service);
|
||||||
if (hasHTTP)
|
if (hasHTTP) {
|
||||||
{
|
QProcess::execute("/usr/sbin/networksetup", {"-setwebproxystate", service, "on"});
|
||||||
QProcess::execute("/usr/sbin/networksetup", { "-setwebproxystate", service, "on" });
|
QProcess::execute("/usr/sbin/networksetup", {"-setsecurewebproxystate", service, "on"});
|
||||||
QProcess::execute("/usr/sbin/networksetup", { "-setsecurewebproxystate", service, "on" });
|
QProcess::execute("/usr/sbin/networksetup", {"-setwebproxy", service, address, QSTRN(httpPort)});
|
||||||
QProcess::execute("/usr/sbin/networksetup", { "-setwebproxy", service, address, QSTRN(httpPort) });
|
QProcess::execute("/usr/sbin/networksetup", {"-setsecurewebproxy", service, address, QSTRN(httpPort)});
|
||||||
QProcess::execute("/usr/sbin/networksetup", { "-setsecurewebproxy", service, address, QSTRN(httpPort) });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasSOCKS)
|
if (hasSOCKS) {
|
||||||
{
|
QProcess::execute("/usr/sbin/networksetup", {"-setsocksfirewallproxystate", service, "on"});
|
||||||
QProcess::execute("/usr/sbin/networksetup", { "-setsocksfirewallproxystate", service, "on" });
|
QProcess::execute("/usr/sbin/networksetup", {"-setsocksfirewallproxy", service, address, QSTRN(socksPort)});
|
||||||
QProcess::execute("/usr/sbin/networksetup", { "-setsocksfirewallproxy", service, address, QSTRN(socksPort) });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,8 +381,7 @@ void SetSystemProxy(int httpPort, int socksPort) {
|
|||||||
LOG("Clearing System Proxy");
|
LOG("Clearing System Proxy");
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (!__SetProxyOptions(nullptr, false))
|
if (!__SetProxyOptions(nullptr, false)) {
|
||||||
{
|
|
||||||
LOG("Failed to clear proxy.");
|
LOG("Failed to clear proxy.");
|
||||||
}
|
}
|
||||||
#elif defined(Q_OS_LINUX)
|
#elif defined(Q_OS_LINUX)
|
||||||
@@ -460,13 +423,12 @@ void SetSystemProxy(int httpPort, int socksPort) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
for (const auto &service : macOSgetNetworkServices())
|
for (const auto &service: macOSgetNetworkServices()) {
|
||||||
{
|
|
||||||
LOG("Clearing proxy for interface: " + service);
|
LOG("Clearing proxy for interface: " + service);
|
||||||
QProcess::execute("/usr/sbin/networksetup", { "-setautoproxystate", service, "off" });
|
QProcess::execute("/usr/sbin/networksetup", {"-setautoproxystate", service, "off"});
|
||||||
QProcess::execute("/usr/sbin/networksetup", { "-setwebproxystate", service, "off" });
|
QProcess::execute("/usr/sbin/networksetup", {"-setwebproxystate", service, "off"});
|
||||||
QProcess::execute("/usr/sbin/networksetup", { "-setsecurewebproxystate", service, "off" });
|
QProcess::execute("/usr/sbin/networksetup", {"-setsecurewebproxystate", service, "off"});
|
||||||
QProcess::execute("/usr/sbin/networksetup", { "-setsocksfirewallproxystate", service, "off" });
|
QProcess::execute("/usr/sbin/networksetup", {"-setsocksfirewallproxystate", service, "off"});
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
//
|
//
|
||||||
namespace Qv2ray::components::proxy
|
namespace Qv2ray::components::proxy {
|
||||||
{
|
|
||||||
void ClearSystemProxy();
|
void ClearSystemProxy();
|
||||||
void SetSystemProxy(int http_port, int socks_port);
|
void SetSystemProxy(int http_port, int socks_port);
|
||||||
} // namespace Qv2ray::components::proxy
|
} // namespace Qv2ray::components::proxy
|
||||||
|
|||||||
@@ -107,8 +107,7 @@ namespace Qv2ray::ui {
|
|||||||
rule.format = ipHostFormat;
|
rule.format = ipHostFormat;
|
||||||
highlightingRules.append(rule);
|
highlightingRules.append(rule);
|
||||||
//
|
//
|
||||||
rule.pattern = QRegularExpression(
|
rule.pattern = QRegularExpression("([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}(/|):" REGEX_PORT_NUMBER);
|
||||||
"([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}(/|):" REGEX_PORT_NUMBER);
|
|
||||||
rule.pattern.setPatternOptions(QRegularExpression::PatternOption::ExtendedPatternSyntaxOption);
|
rule.pattern.setPatternOptions(QRegularExpression::PatternOption::ExtendedPatternSyntaxOption);
|
||||||
rule.format = ipHostFormat;
|
rule.format = ipHostFormat;
|
||||||
highlightingRules.append(rule);
|
highlightingRules.append(rule);
|
||||||
@@ -120,7 +119,6 @@ namespace Qv2ray::ui {
|
|||||||
rule.format = tcpudpFormat;
|
rule.format = tcpudpFormat;
|
||||||
highlightingRules.append(rule);
|
highlightingRules.append(rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxHighlighter::highlightBlock(const QString &text) {
|
void SyntaxHighlighter::highlightBlock(const QString &text) {
|
||||||
|
|||||||
@@ -61,10 +61,8 @@
|
|||||||
#include <QToolTip>
|
#include <QToolTip>
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
|
||||||
namespace Qv2ray::ui::widgets
|
namespace Qv2ray::ui::widgets {
|
||||||
{
|
AutoCompleteTextEdit::AutoCompleteTextEdit(const QString &prefix, const QStringList &sourceStrings, QWidget *parent) : QPlainTextEdit(parent) {
|
||||||
AutoCompleteTextEdit::AutoCompleteTextEdit(const QString &prefix, const QStringList &sourceStrings, QWidget *parent) : QPlainTextEdit(parent)
|
|
||||||
{
|
|
||||||
this->prefix = prefix;
|
this->prefix = prefix;
|
||||||
this->setLineWrapMode(QPlainTextEdit::NoWrap);
|
this->setLineWrapMode(QPlainTextEdit::NoWrap);
|
||||||
c = new QCompleter(this);
|
c = new QCompleter(this);
|
||||||
@@ -75,12 +73,10 @@ namespace Qv2ray::ui::widgets
|
|||||||
QObject::connect(c, QOverload<const QString &>::of(&QCompleter::activated), this, &AutoCompleteTextEdit::insertCompletion);
|
QObject::connect(c, QOverload<const QString &>::of(&QCompleter::activated), this, &AutoCompleteTextEdit::insertCompletion);
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoCompleteTextEdit::~AutoCompleteTextEdit()
|
AutoCompleteTextEdit::~AutoCompleteTextEdit() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoCompleteTextEdit::insertCompletion(const QString &completion)
|
void AutoCompleteTextEdit::insertCompletion(const QString &completion) {
|
||||||
{
|
|
||||||
QTextCursor tc = textCursor();
|
QTextCursor tc = textCursor();
|
||||||
int extra = completion.length() - c->completionPrefix().length();
|
int extra = completion.length() - c->completionPrefix().length();
|
||||||
tc.movePosition(QTextCursor::Left);
|
tc.movePosition(QTextCursor::Left);
|
||||||
@@ -89,30 +85,26 @@ namespace Qv2ray::ui::widgets
|
|||||||
setTextCursor(tc);
|
setTextCursor(tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AutoCompleteTextEdit::lineUnderCursor() const
|
QString AutoCompleteTextEdit::lineUnderCursor() const {
|
||||||
{
|
|
||||||
QTextCursor tc = textCursor();
|
QTextCursor tc = textCursor();
|
||||||
tc.select(QTextCursor::LineUnderCursor);
|
tc.select(QTextCursor::LineUnderCursor);
|
||||||
return tc.selectedText();
|
return tc.selectedText();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AutoCompleteTextEdit::wordUnderCursor() const
|
QString AutoCompleteTextEdit::wordUnderCursor() const {
|
||||||
{
|
|
||||||
QTextCursor tc = textCursor();
|
QTextCursor tc = textCursor();
|
||||||
tc.select(QTextCursor::WordUnderCursor);
|
tc.select(QTextCursor::WordUnderCursor);
|
||||||
return tc.selectedText();
|
return tc.selectedText();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoCompleteTextEdit::focusInEvent(QFocusEvent *e)
|
void AutoCompleteTextEdit::focusInEvent(QFocusEvent *e) {
|
||||||
{
|
|
||||||
if (c)
|
if (c)
|
||||||
c->setWidget(this);
|
c->setWidget(this);
|
||||||
|
|
||||||
QPlainTextEdit::focusInEvent(e);
|
QPlainTextEdit::focusInEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoCompleteTextEdit::keyPressEvent(QKeyEvent *e)
|
void AutoCompleteTextEdit::keyPressEvent(QKeyEvent *e) {
|
||||||
{
|
|
||||||
const bool hasCtrlOrShiftModifier = e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::ShiftModifier);
|
const bool hasCtrlOrShiftModifier = e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::ShiftModifier);
|
||||||
const bool hasOtherModifiers = (e->modifiers() != Qt::NoModifier) && !hasCtrlOrShiftModifier; // has other modifiers
|
const bool hasOtherModifiers = (e->modifiers() != Qt::NoModifier) && !hasCtrlOrShiftModifier; // has other modifiers
|
||||||
//
|
//
|
||||||
@@ -121,24 +113,24 @@ namespace Qv2ray::ui::widgets
|
|||||||
const bool isTab = (e->modifiers().testFlag(Qt::NoModifier) && e->key() == Qt::Key_Tab);
|
const bool isTab = (e->modifiers().testFlag(Qt::NoModifier) && e->key() == Qt::Key_Tab);
|
||||||
const bool isOtherSpace = e->text() == " ";
|
const bool isOtherSpace = e->text() == " ";
|
||||||
//
|
//
|
||||||
if (isSpace || isTab || isOtherSpace)
|
if (isSpace || isTab || isOtherSpace) {
|
||||||
{
|
|
||||||
QToolTip::showText(this->mapToGlobal(QPoint(0, 0)), tr("You can not input space characters here."), this, QRect{}, 2000);
|
QToolTip::showText(this->mapToGlobal(QPoint(0, 0)), tr("You can not input space characters here."), this, QRect{}, 2000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if (c && c->popup()->isVisible())
|
if (c && c->popup()->isVisible()) {
|
||||||
{
|
|
||||||
// The following keys are forwarded by the completer to the widget
|
// The following keys are forwarded by the completer to the widget
|
||||||
switch (e->key())
|
switch (e->key()) {
|
||||||
{
|
|
||||||
case Qt::Key_Enter:
|
case Qt::Key_Enter:
|
||||||
case Qt::Key_Return:
|
case Qt::Key_Return:
|
||||||
case Qt::Key_Escape:
|
case Qt::Key_Escape:
|
||||||
case Qt::Key_Tab:
|
case Qt::Key_Tab:
|
||||||
case Qt::Key_Backtab: e->ignore(); return; // let the completer do default behavior
|
case Qt::Key_Backtab:
|
||||||
|
e->ignore();
|
||||||
|
return; // let the completer do default behavior
|
||||||
|
|
||||||
default: break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,14 +140,12 @@ namespace Qv2ray::ui::widgets
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// if we have other modifiers, or the text is empty, or the line does not start with our prefix.
|
// if we have other modifiers, or the text is empty, or the line does not start with our prefix.
|
||||||
if (hasOtherModifiers || e->text().isEmpty() || !lineUnderCursor().startsWith(prefix))
|
if (hasOtherModifiers || e->text().isEmpty() || !lineUnderCursor().startsWith(prefix)) {
|
||||||
{
|
|
||||||
c->popup()->hide();
|
c->popup()->hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto word = wordUnderCursor(); word != c->completionPrefix())
|
if (auto word = wordUnderCursor(); word != c->completionPrefix()) {
|
||||||
{
|
|
||||||
c->setCompletionPrefix(word);
|
c->setCompletionPrefix(word);
|
||||||
c->popup()->setCurrentIndex(c->completionModel()->index(0, 0));
|
c->popup()->setCurrentIndex(c->completionModel()->index(0, 0));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,10 +55,8 @@ QT_BEGIN_NAMESPACE
|
|||||||
class QCompleter;
|
class QCompleter;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Qv2ray::ui::widgets
|
namespace Qv2ray::ui::widgets {
|
||||||
{
|
class AutoCompleteTextEdit : public QPlainTextEdit {
|
||||||
class AutoCompleteTextEdit : public QPlainTextEdit
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -27,107 +27,86 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
QJsonTreeItem::QJsonTreeItem(QJsonTreeItem *parent)
|
QJsonTreeItem::QJsonTreeItem(QJsonTreeItem *parent) {
|
||||||
{
|
|
||||||
mParent = parent;
|
mParent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonTreeItem::~QJsonTreeItem()
|
QJsonTreeItem::~QJsonTreeItem() {
|
||||||
{
|
|
||||||
qDeleteAll(mChilds);
|
qDeleteAll(mChilds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QJsonTreeItem::appendChild(QJsonTreeItem *item)
|
void QJsonTreeItem::appendChild(QJsonTreeItem *item) {
|
||||||
{
|
|
||||||
mChilds.append(item);
|
mChilds.append(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonTreeItem *QJsonTreeItem::child(int row)
|
QJsonTreeItem *QJsonTreeItem::child(int row) {
|
||||||
{
|
|
||||||
return mChilds.value(row);
|
return mChilds.value(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonTreeItem *QJsonTreeItem::parent()
|
QJsonTreeItem *QJsonTreeItem::parent() {
|
||||||
{
|
|
||||||
return mParent;
|
return mParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QJsonTreeItem::childCount() const
|
int QJsonTreeItem::childCount() const {
|
||||||
{
|
|
||||||
return mChilds.count();
|
return mChilds.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
int QJsonTreeItem::row() const
|
int QJsonTreeItem::row() const {
|
||||||
{
|
|
||||||
if (mParent)
|
if (mParent)
|
||||||
return mParent->mChilds.indexOf(const_cast<QJsonTreeItem *>(this));
|
return mParent->mChilds.indexOf(const_cast<QJsonTreeItem *>(this));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QJsonTreeItem::setKey(const QString &key)
|
void QJsonTreeItem::setKey(const QString &key) {
|
||||||
{
|
|
||||||
mKey = key;
|
mKey = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QJsonTreeItem::setValue(const QString &value)
|
void QJsonTreeItem::setValue(const QString &value) {
|
||||||
{
|
|
||||||
mValue = value;
|
mValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QJsonTreeItem::setType(const QJsonValue::Type &type)
|
void QJsonTreeItem::setType(const QJsonValue::Type &type) {
|
||||||
{
|
|
||||||
mType = type;
|
mType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QJsonTreeItem::key() const
|
QString QJsonTreeItem::key() const {
|
||||||
{
|
|
||||||
return mKey;
|
return mKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QJsonTreeItem::value() const
|
QString QJsonTreeItem::value() const {
|
||||||
{
|
|
||||||
return mValue;
|
return mValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonValue::Type QJsonTreeItem::type() const
|
QJsonValue::Type QJsonTreeItem::type() const {
|
||||||
{
|
|
||||||
return mType;
|
return mType;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonTreeItem *QJsonTreeItem::load(const QJsonValue &value, QJsonTreeItem *parent)
|
QJsonTreeItem *QJsonTreeItem::load(const QJsonValue &value, QJsonTreeItem *parent) {
|
||||||
{
|
|
||||||
QJsonTreeItem *rootItem = new QJsonTreeItem(parent);
|
QJsonTreeItem *rootItem = new QJsonTreeItem(parent);
|
||||||
rootItem->setKey("root");
|
rootItem->setKey("root");
|
||||||
|
|
||||||
if (value.isObject())
|
if (value.isObject()) {
|
||||||
{
|
|
||||||
// Get all QJsonValue childs
|
// Get all QJsonValue childs
|
||||||
for (QString key : value.toObject().keys())
|
for (QString key: value.toObject().keys()) {
|
||||||
{
|
|
||||||
QJsonValue v = value.toObject().value(key);
|
QJsonValue v = value.toObject().value(key);
|
||||||
QJsonTreeItem *child = load(v, rootItem);
|
QJsonTreeItem *child = load(v, rootItem);
|
||||||
child->setKey(key);
|
child->setKey(key);
|
||||||
child->setType(v.type());
|
child->setType(v.type());
|
||||||
rootItem->appendChild(child);
|
rootItem->appendChild(child);
|
||||||
}
|
}
|
||||||
}
|
} else if (value.isArray()) {
|
||||||
else if (value.isArray())
|
|
||||||
{
|
|
||||||
// Get all QJsonValue childs
|
// Get all QJsonValue childs
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
for (QJsonValue v : value.toArray())
|
for (QJsonValue v: value.toArray()) {
|
||||||
{
|
|
||||||
QJsonTreeItem *child = load(v, rootItem);
|
QJsonTreeItem *child = load(v, rootItem);
|
||||||
child->setKey(QString::number(index));
|
child->setKey(QString::number(index));
|
||||||
child->setType(v.type());
|
child->setType(v.type());
|
||||||
rootItem->appendChild(child);
|
rootItem->appendChild(child);
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
rootItem->setValue(value.toVariant().toString());
|
rootItem->setValue(value.toVariant().toString());
|
||||||
rootItem->setType(value.type());
|
rootItem->setType(value.type());
|
||||||
}
|
}
|
||||||
@@ -137,75 +116,61 @@ QJsonTreeItem *QJsonTreeItem::load(const QJsonValue &value, QJsonTreeItem *paren
|
|||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
|
|
||||||
QJsonModel::QJsonModel(QObject *parent) : QAbstractItemModel(parent), mRootItem{ new QJsonTreeItem }
|
QJsonModel::QJsonModel(QObject *parent) : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} {
|
||||||
{
|
|
||||||
mHeaders.append("key");
|
mHeaders.append("key");
|
||||||
mHeaders.append("value");
|
mHeaders.append("value");
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonModel::QJsonModel(const QString &fileName, QObject *parent) : QAbstractItemModel(parent), mRootItem{ new QJsonTreeItem }
|
QJsonModel::QJsonModel(const QString &fileName, QObject *parent) : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} {
|
||||||
{
|
|
||||||
mHeaders.append("key");
|
mHeaders.append("key");
|
||||||
mHeaders.append("value");
|
mHeaders.append("value");
|
||||||
load(fileName);
|
load(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonModel::QJsonModel(QIODevice *device, QObject *parent) : QAbstractItemModel(parent), mRootItem{ new QJsonTreeItem }
|
QJsonModel::QJsonModel(QIODevice *device, QObject *parent) : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} {
|
||||||
{
|
|
||||||
mHeaders.append("key");
|
mHeaders.append("key");
|
||||||
mHeaders.append("value");
|
mHeaders.append("value");
|
||||||
load(device);
|
load(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonModel::QJsonModel(const QByteArray &json, QObject *parent) : QAbstractItemModel(parent), mRootItem{ new QJsonTreeItem }
|
QJsonModel::QJsonModel(const QByteArray &json, QObject *parent) : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} {
|
||||||
{
|
|
||||||
mHeaders.append("key");
|
mHeaders.append("key");
|
||||||
mHeaders.append("value");
|
mHeaders.append("value");
|
||||||
loadJson(json);
|
loadJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonModel::~QJsonModel()
|
QJsonModel::~QJsonModel() {
|
||||||
{
|
|
||||||
delete mRootItem;
|
delete mRootItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QJsonModel::load(const QString &fileName)
|
bool QJsonModel::load(const QString &fileName) {
|
||||||
{
|
|
||||||
QFile file(fileName);
|
QFile file(fileName);
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
if (file.open(QIODevice::ReadOnly))
|
if (file.open(QIODevice::ReadOnly)) {
|
||||||
{
|
|
||||||
success = load(&file);
|
success = load(&file);
|
||||||
file.close();
|
file.close();
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
success = false;
|
success = false;
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QJsonModel::load(QIODevice *device)
|
bool QJsonModel::load(QIODevice *device) {
|
||||||
{
|
|
||||||
return loadJson(device->readAll());
|
return loadJson(device->readAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QJsonModel::loadJson(const QByteArray &json)
|
bool QJsonModel::loadJson(const QByteArray &json) {
|
||||||
{
|
|
||||||
auto const &jdoc = QJsonDocument::fromJson(json);
|
auto const &jdoc = QJsonDocument::fromJson(json);
|
||||||
|
|
||||||
if (!jdoc.isNull())
|
if (!jdoc.isNull()) {
|
||||||
{
|
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
delete mRootItem;
|
delete mRootItem;
|
||||||
|
|
||||||
if (jdoc.isArray())
|
if (jdoc.isArray()) {
|
||||||
{
|
|
||||||
mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.array()));
|
mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.array()));
|
||||||
mRootItem->setType(QJsonValue::Array);
|
mRootItem->setType(QJsonValue::Array);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.object()));
|
mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.object()));
|
||||||
mRootItem->setType(QJsonValue::Object);
|
mRootItem->setType(QJsonValue::Object);
|
||||||
}
|
}
|
||||||
@@ -218,25 +183,20 @@ bool QJsonModel::loadJson(const QByteArray &json)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant QJsonModel::data(const QModelIndex &index, int role) const
|
QVariant QJsonModel::data(const QModelIndex &index, int role) const {
|
||||||
{
|
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
QJsonTreeItem *item = static_cast<QJsonTreeItem *>(index.internalPointer());
|
QJsonTreeItem *item = static_cast<QJsonTreeItem *>(index.internalPointer());
|
||||||
|
|
||||||
if (role == Qt::DisplayRole)
|
if (role == Qt::DisplayRole) {
|
||||||
{
|
|
||||||
if (index.column() == 0)
|
if (index.column() == 0)
|
||||||
return QString("%1").arg(item->key());
|
return QString("%1").arg(item->key());
|
||||||
|
|
||||||
if (index.column() == 1)
|
if (index.column() == 1)
|
||||||
return QString("%1").arg(item->value());
|
return QString("%1").arg(item->value());
|
||||||
}
|
} else if (Qt::EditRole == role) {
|
||||||
else if (Qt::EditRole == role)
|
if (index.column() == 1) {
|
||||||
{
|
|
||||||
if (index.column() == 1)
|
|
||||||
{
|
|
||||||
return QString("%1").arg(item->value());
|
return QString("%1").arg(item->value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,17 +204,14 @@ QVariant QJsonModel::data(const QModelIndex &index, int role) const
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QJsonModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
bool QJsonModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||||
{
|
|
||||||
int col = index.column();
|
int col = index.column();
|
||||||
|
|
||||||
if (Qt::EditRole == role)
|
if (Qt::EditRole == role) {
|
||||||
{
|
if (col == 1) {
|
||||||
if (col == 1)
|
|
||||||
{
|
|
||||||
QJsonTreeItem *item = static_cast<QJsonTreeItem *>(index.internalPointer());
|
QJsonTreeItem *item = static_cast<QJsonTreeItem *>(index.internalPointer());
|
||||||
item->setValue(value.toString());
|
item->setValue(value.toString());
|
||||||
emit dataChanged(index, index, { Qt::EditRole });
|
emit dataChanged(index, index, {Qt::EditRole});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,21 +219,17 @@ bool QJsonModel::setData(const QModelIndex &index, const QVariant &value, int ro
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant QJsonModel::headerData(int section, Qt::Orientation orientation, int role) const
|
QVariant QJsonModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
||||||
{
|
|
||||||
if (role != Qt::DisplayRole)
|
if (role != Qt::DisplayRole)
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
if (orientation == Qt::Horizontal)
|
if (orientation == Qt::Horizontal) {
|
||||||
{
|
|
||||||
return mHeaders.value(section);
|
return mHeaders.value(section);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex QJsonModel::index(int row, int column, const QModelIndex &parent) const
|
QModelIndex QJsonModel::index(int row, int column, const QModelIndex &parent) const {
|
||||||
{
|
|
||||||
if (!hasIndex(row, column, parent))
|
if (!hasIndex(row, column, parent))
|
||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
|
|
||||||
@@ -295,8 +248,7 @@ QModelIndex QJsonModel::index(int row, int column, const QModelIndex &parent) co
|
|||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex QJsonModel::parent(const QModelIndex &index) const
|
QModelIndex QJsonModel::parent(const QModelIndex &index) const {
|
||||||
{
|
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
|
|
||||||
@@ -309,8 +261,7 @@ QModelIndex QJsonModel::parent(const QModelIndex &index) const
|
|||||||
return createIndex(parentItem->row(), 0, parentItem);
|
return createIndex(parentItem->row(), 0, parentItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
int QJsonModel::rowCount(const QModelIndex &parent) const
|
int QJsonModel::rowCount(const QModelIndex &parent) const {
|
||||||
{
|
|
||||||
QJsonTreeItem *parentItem;
|
QJsonTreeItem *parentItem;
|
||||||
|
|
||||||
if (parent.column() > 0)
|
if (parent.column() > 0)
|
||||||
@@ -324,78 +275,61 @@ int QJsonModel::rowCount(const QModelIndex &parent) const
|
|||||||
return parentItem->childCount();
|
return parentItem->childCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
int QJsonModel::columnCount(const QModelIndex &parent) const
|
int QJsonModel::columnCount(const QModelIndex &parent) const {
|
||||||
{
|
|
||||||
Q_UNUSED(parent)
|
Q_UNUSED(parent)
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::ItemFlags QJsonModel::flags(const QModelIndex &index) const
|
Qt::ItemFlags QJsonModel::flags(const QModelIndex &index) const {
|
||||||
{
|
|
||||||
int col = index.column();
|
int col = index.column();
|
||||||
auto item = static_cast<QJsonTreeItem *>(index.internalPointer());
|
auto item = static_cast<QJsonTreeItem *>(index.internalPointer());
|
||||||
auto isArray = QJsonValue::Array == item->type();
|
auto isArray = QJsonValue::Array == item->type();
|
||||||
auto isObject = QJsonValue::Object == item->type();
|
auto isObject = QJsonValue::Object == item->type();
|
||||||
|
|
||||||
if ((col == 1) && !(isArray || isObject))
|
if ((col == 1) && !(isArray || isObject)) {
|
||||||
{
|
|
||||||
return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
|
return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return QAbstractItemModel::flags(index);
|
return QAbstractItemModel::flags(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonDocument QJsonModel::json() const
|
QJsonDocument QJsonModel::json() const {
|
||||||
{
|
|
||||||
auto v = genJson(mRootItem);
|
auto v = genJson(mRootItem);
|
||||||
QJsonDocument doc;
|
QJsonDocument doc;
|
||||||
|
|
||||||
if (v.isObject())
|
if (v.isObject()) {
|
||||||
{
|
|
||||||
doc = QJsonDocument(v.toObject());
|
doc = QJsonDocument(v.toObject());
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
doc = QJsonDocument(v.toArray());
|
doc = QJsonDocument(v.toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonValue QJsonModel::genJson(QJsonTreeItem *item) const
|
QJsonValue QJsonModel::genJson(QJsonTreeItem *item) const {
|
||||||
{
|
|
||||||
auto type = item->type();
|
auto type = item->type();
|
||||||
int nchild = item->childCount();
|
int nchild = item->childCount();
|
||||||
|
|
||||||
if (QJsonValue::Object == type)
|
if (QJsonValue::Object == type) {
|
||||||
{
|
|
||||||
QJsonObject jo;
|
QJsonObject jo;
|
||||||
|
|
||||||
for (int i = 0; i < nchild; ++i)
|
for (int i = 0; i < nchild; ++i) {
|
||||||
{
|
|
||||||
auto ch = item->child(i);
|
auto ch = item->child(i);
|
||||||
auto key = ch->key();
|
auto key = ch->key();
|
||||||
jo.insert(key, genJson(ch));
|
jo.insert(key, genJson(ch));
|
||||||
}
|
}
|
||||||
|
|
||||||
return jo;
|
return jo;
|
||||||
}
|
} else if (QJsonValue::Array == type) {
|
||||||
else if (QJsonValue::Array == type)
|
|
||||||
{
|
|
||||||
QJsonArray arr;
|
QJsonArray arr;
|
||||||
|
|
||||||
for (int i = 0; i < nchild; ++i)
|
for (int i = 0; i < nchild; ++i) {
|
||||||
{
|
|
||||||
auto ch = item->child(i);
|
auto ch = item->child(i);
|
||||||
arr.append(genJson(ch));
|
arr.append(genJson(ch));
|
||||||
}
|
}
|
||||||
|
|
||||||
return arr;
|
return arr;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
QJsonValue va(item->value());
|
QJsonValue va(item->value());
|
||||||
return va;
|
return va;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,9 +34,8 @@
|
|||||||
class QJsonModel;
|
class QJsonModel;
|
||||||
class QJsonItem;
|
class QJsonItem;
|
||||||
|
|
||||||
class QJsonTreeItem
|
class QJsonTreeItem {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
QJsonTreeItem(QJsonTreeItem *parent = nullptr);
|
QJsonTreeItem(QJsonTreeItem *parent = nullptr);
|
||||||
~QJsonTreeItem();
|
~QJsonTreeItem();
|
||||||
void appendChild(QJsonTreeItem *item);
|
void appendChild(QJsonTreeItem *item);
|
||||||
@@ -53,8 +52,8 @@ class QJsonTreeItem
|
|||||||
|
|
||||||
static QJsonTreeItem *load(const QJsonValue &value, QJsonTreeItem *parent = 0);
|
static QJsonTreeItem *load(const QJsonValue &value, QJsonTreeItem *parent = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
private:
|
private:
|
||||||
QString mKey;
|
QString mKey;
|
||||||
QString mValue;
|
QString mValue;
|
||||||
QJsonValue::Type mType;
|
QJsonValue::Type mType;
|
||||||
@@ -64,10 +63,9 @@ class QJsonTreeItem
|
|||||||
|
|
||||||
//---------------------------------------------------
|
//---------------------------------------------------
|
||||||
|
|
||||||
class QJsonModel : public QAbstractItemModel
|
class QJsonModel : public QAbstractItemModel {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit QJsonModel(QObject *parent = nullptr);
|
explicit QJsonModel(QObject *parent = nullptr);
|
||||||
QJsonModel(const QString &fileName, QObject *parent = nullptr);
|
QJsonModel(const QString &fileName, QObject *parent = nullptr);
|
||||||
QJsonModel(QIODevice *device, QObject *parent = nullptr);
|
QJsonModel(QIODevice *device, QObject *parent = nullptr);
|
||||||
@@ -86,7 +84,7 @@ class QJsonModel : public QAbstractItemModel
|
|||||||
Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
|
Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
|
||||||
QJsonDocument json() const;
|
QJsonDocument json() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QJsonValue genJson(QJsonTreeItem *) const;
|
QJsonValue genJson(QJsonTreeItem *) const;
|
||||||
|
|
||||||
QJsonTreeItem *mRootItem;
|
QJsonTreeItem *mRootItem;
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
#include "main/NekoRay.hpp"
|
#include "main/NekoRay.hpp"
|
||||||
|
|
||||||
JsonEditor::JsonEditor(const QJsonObject& rootObject, QWidget *parent) : QDialog(parent) {
|
JsonEditor::JsonEditor(const QJsonObject& rootObject, QWidget* parent) : QDialog(parent) {
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
// QvMessageBusConnect(JsonEditor);
|
// QvMessageBusConnect(JsonEditor);
|
||||||
//
|
//
|
||||||
original = rootObject;
|
original = rootObject;
|
||||||
final = rootObject;
|
final = rootObject;
|
||||||
@@ -23,7 +23,7 @@ JsonEditor::JsonEditor(const QJsonObject& rootObject, QWidget *parent) : QDialog
|
|||||||
jsonTree->resizeColumnToContents(0);
|
jsonTree->resizeColumnToContents(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//QvMessageBusSlotImpl(JsonEditor)
|
// QvMessageBusSlotImpl(JsonEditor)
|
||||||
// {
|
// {
|
||||||
// switch (msg)
|
// switch (msg)
|
||||||
// {
|
// {
|
||||||
|
|||||||
@@ -4,28 +4,26 @@
|
|||||||
#include "qv2ray/v2/ui/widgets/common/QJsonModel.hpp"
|
#include "qv2ray/v2/ui/widgets/common/QJsonModel.hpp"
|
||||||
#include "ui_w_JsonEditor.h"
|
#include "ui_w_JsonEditor.h"
|
||||||
|
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
|
||||||
class JsonEditor
|
class JsonEditor
|
||||||
: public QDialog
|
: public QDialog,
|
||||||
, private Ui::JsonEditor
|
private Ui::JsonEditor {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit JsonEditor(const QJsonObject& rootObject, QWidget *parent = nullptr);
|
explicit JsonEditor(const QJsonObject& rootObject, QWidget* parent = nullptr);
|
||||||
~JsonEditor();
|
~JsonEditor();
|
||||||
QJsonObject OpenEditor();
|
QJsonObject OpenEditor();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_jsonEditor_textChanged();
|
void on_jsonEditor_textChanged();
|
||||||
|
|
||||||
void on_formatJsonBtn_clicked();
|
void on_formatJsonBtn_clicked();
|
||||||
|
|
||||||
void on_removeCommentsBtn_clicked();
|
void on_removeCommentsBtn_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QJsonModel model;
|
QJsonModel model;
|
||||||
QJsonObject original;
|
QJsonObject original;
|
||||||
QJsonObject final;
|
QJsonObject final;
|
||||||
|
|||||||
@@ -16,9 +16,10 @@ namespace Qv2ray::common::network {
|
|||||||
class NetworkRequestHelper : QObject {
|
class NetworkRequestHelper : QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
explicit NetworkRequestHelper(QObject *parent) : QObject(parent) {};
|
explicit NetworkRequestHelper(QObject *parent) : QObject(parent){};
|
||||||
|
|
||||||
~NetworkRequestHelper() override = default;;
|
~NetworkRequestHelper() override = default;
|
||||||
|
;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static NekoHTTPResponse HttpGet(const QUrl &url);
|
static NekoHTTPResponse HttpGet(const QUrl &url);
|
||||||
|
|||||||
@@ -39,4 +39,4 @@ namespace Qv2ray::components::GeositeReader {
|
|||||||
GeositeEntries[filepath] = list;
|
GeositeEntries[filepath] = list;
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
} // namespace Qv2ray::components::geosite
|
} // namespace Qv2ray::components::GeositeReader
|
||||||
|
|||||||
@@ -15,18 +15,15 @@
|
|||||||
|
|
||||||
#include "picoproto.hpp"
|
#include "picoproto.hpp"
|
||||||
|
|
||||||
namespace picoproto
|
namespace picoproto {
|
||||||
{
|
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
|
||||||
|
|
||||||
// To keep the dependencies down, here's a local copy of the widespread bit_cast
|
// To keep the dependencies down, here's a local copy of the widespread bit_cast
|
||||||
// operator. This is necessary because in practice weird things can happen if
|
// operator. This is necessary because in practice weird things can happen if
|
||||||
// you just try to use reinterpret_cast.
|
// you just try to use reinterpret_cast.
|
||||||
template<class Dest, class Source>
|
template<class Dest, class Source>
|
||||||
inline Dest bit_cast(const Source &source)
|
inline Dest bit_cast(const Source &source) {
|
||||||
{
|
|
||||||
static_assert(sizeof(Dest) == sizeof(Source), "Sizes do not match");
|
static_assert(sizeof(Dest) == sizeof(Source), "Sizes do not match");
|
||||||
Dest dest;
|
Dest dest;
|
||||||
memcpy(&dest, &source, sizeof(dest));
|
memcpy(&dest, &source, sizeof(dest));
|
||||||
@@ -35,8 +32,7 @@ namespace picoproto
|
|||||||
|
|
||||||
// These are defined in:
|
// These are defined in:
|
||||||
// https://developers.google.com/protocol-buffers/docs/encoding
|
// https://developers.google.com/protocol-buffers/docs/encoding
|
||||||
enum WireType
|
enum WireType {
|
||||||
{
|
|
||||||
WIRETYPE_VARINT = 0,
|
WIRETYPE_VARINT = 0,
|
||||||
WIRETYPE_64BIT = 1,
|
WIRETYPE_64BIT = 1,
|
||||||
WIRETYPE_LENGTH_DELIMITED = 2,
|
WIRETYPE_LENGTH_DELIMITED = 2,
|
||||||
@@ -46,10 +42,8 @@ namespace picoproto
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Pull bytes from the stream, updating the state.
|
// Pull bytes from the stream, updating the state.
|
||||||
bool ConsumeBytes(uint8_t **current, size_t how_many, size_t *remaining)
|
bool ConsumeBytes(uint8_t **current, size_t how_many, size_t *remaining) {
|
||||||
{
|
if (how_many > *remaining) {
|
||||||
if (how_many > *remaining)
|
|
||||||
{
|
|
||||||
PP_LOG(ERROR) << "ReadBytes overrun!";
|
PP_LOG(ERROR) << "ReadBytes overrun!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -60,30 +54,26 @@ namespace picoproto
|
|||||||
|
|
||||||
// Grabs a particular type from the byte stream.
|
// Grabs a particular type from the byte stream.
|
||||||
template<class T>
|
template<class T>
|
||||||
T ReadFromBytes(uint8_t **current, size_t *remaining)
|
T ReadFromBytes(uint8_t **current, size_t *remaining) {
|
||||||
{
|
|
||||||
PP_CHECK(ConsumeBytes(current, sizeof(T), remaining));
|
PP_CHECK(ConsumeBytes(current, sizeof(T), remaining));
|
||||||
const T result = *(bit_cast<T *>(*current - sizeof(T)));
|
const T result = *(bit_cast<T *>(*current - sizeof(T)));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t ReadVarInt(uint8_t **current, size_t *remaining)
|
uint64_t ReadVarInt(uint8_t **current, size_t *remaining) {
|
||||||
{
|
|
||||||
uint64_t result = 0;
|
uint64_t result = 0;
|
||||||
bool keep_going;
|
bool keep_going;
|
||||||
int shift = 0;
|
int shift = 0;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
const uint8_t next_number = ReadFromBytes<uint8_t>(current, remaining);
|
const uint8_t next_number = ReadFromBytes<uint8_t>(current, remaining);
|
||||||
keep_going = (next_number >= 128);
|
keep_going = (next_number >= 128);
|
||||||
result += (uint64_t)(next_number & 0x7f) << shift;
|
result += (uint64_t) (next_number & 0x7f) << shift;
|
||||||
shift += 7;
|
shift += 7;
|
||||||
} while (keep_going);
|
} while (keep_going);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadWireTypeAndFieldNumber(uint8_t **current, size_t *remaining, uint8_t *wire_type, uint32_t *field_number)
|
void ReadWireTypeAndFieldNumber(uint8_t **current, size_t *remaining, uint8_t *wire_type, uint32_t *field_number) {
|
||||||
{
|
|
||||||
uint64_t wire_type_and_field_number = ReadVarInt(current, remaining);
|
uint64_t wire_type_and_field_number = ReadVarInt(current, remaining);
|
||||||
*wire_type = wire_type_and_field_number & 0x07;
|
*wire_type = wire_type_and_field_number & 0x07;
|
||||||
*field_number = wire_type_and_field_number >> 3;
|
*field_number = wire_type_and_field_number >> 3;
|
||||||
@@ -91,123 +81,106 @@ namespace picoproto
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::string FieldTypeDebugString(enum FieldType type)
|
std::string FieldTypeDebugString(enum FieldType type) {
|
||||||
{
|
switch (type) {
|
||||||
switch (type)
|
case FIELD_UNSET:
|
||||||
{
|
return "UNSET";
|
||||||
case FIELD_UNSET: return "UNSET"; break;
|
break;
|
||||||
case FIELD_UINT32: return "UINT32"; break;
|
case FIELD_UINT32:
|
||||||
case FIELD_UINT64: return "UINT64"; break;
|
return "UINT32";
|
||||||
case FIELD_BYTES: return "BYTES"; break;
|
break;
|
||||||
default: return "Unknown field type"; break;
|
case FIELD_UINT64:
|
||||||
|
return "UINT64";
|
||||||
|
break;
|
||||||
|
case FIELD_BYTES:
|
||||||
|
return "BYTES";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return "Unknown field type";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return "Should never get here";
|
return "Should never get here";
|
||||||
}
|
}
|
||||||
|
|
||||||
Field::Field(FieldType type, bool owns_data) : type(type), owns_data(owns_data)
|
Field::Field(FieldType type, bool owns_data) : type(type), owns_data(owns_data) {
|
||||||
{
|
|
||||||
cached_messages = nullptr;
|
cached_messages = nullptr;
|
||||||
switch (type)
|
switch (type) {
|
||||||
{
|
case FIELD_UINT32: {
|
||||||
case FIELD_UINT32:
|
|
||||||
{
|
|
||||||
value.v_uint32 = new std::vector<uint32_t>();
|
value.v_uint32 = new std::vector<uint32_t>();
|
||||||
}
|
} break;
|
||||||
break;
|
case FIELD_UINT64: {
|
||||||
case FIELD_UINT64:
|
|
||||||
{
|
|
||||||
value.v_uint64 = new std::vector<uint64_t>();
|
value.v_uint64 = new std::vector<uint64_t>();
|
||||||
}
|
} break;
|
||||||
break;
|
case FIELD_BYTES: {
|
||||||
case FIELD_BYTES:
|
|
||||||
{
|
|
||||||
value.v_bytes = new std::vector<std::pair<uint8_t *, size_t>>();
|
value.v_bytes = new std::vector<std::pair<uint8_t *, size_t>>();
|
||||||
cached_messages = new std::vector<Message *>();
|
cached_messages = new std::vector<Message *>();
|
||||||
}
|
} break;
|
||||||
break;
|
default: {
|
||||||
default:
|
|
||||||
{
|
|
||||||
PP_LOG(ERROR) << "Bad field type when constructing field: " << type;
|
PP_LOG(ERROR) << "Bad field type when constructing field: " << type;
|
||||||
}
|
} break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Field::Field(const Field &other) : type(other.type), owns_data(other.owns_data)
|
Field::Field(const Field &other) : type(other.type), owns_data(other.owns_data) {
|
||||||
{
|
switch (type) {
|
||||||
switch (type)
|
case FIELD_UINT32: {
|
||||||
{
|
|
||||||
case FIELD_UINT32:
|
|
||||||
{
|
|
||||||
value.v_uint32 = new std::vector<uint32_t>(*other.value.v_uint32);
|
value.v_uint32 = new std::vector<uint32_t>(*other.value.v_uint32);
|
||||||
}
|
} break;
|
||||||
break;
|
case FIELD_UINT64: {
|
||||||
case FIELD_UINT64:
|
|
||||||
{
|
|
||||||
value.v_uint64 = new std::vector<uint64_t>(*other.value.v_uint64);
|
value.v_uint64 = new std::vector<uint64_t>(*other.value.v_uint64);
|
||||||
}
|
} break;
|
||||||
break;
|
case FIELD_BYTES: {
|
||||||
case FIELD_BYTES:
|
if (owns_data) {
|
||||||
{
|
|
||||||
if (owns_data)
|
|
||||||
{
|
|
||||||
value.v_bytes = new std::vector<std::pair<uint8_t *, size_t>>();
|
value.v_bytes = new std::vector<std::pair<uint8_t *, size_t>>();
|
||||||
for (std::pair<uint8_t *, size_t> data_info : *other.value.v_bytes)
|
for (std::pair<uint8_t *, size_t> data_info: *other.value.v_bytes) {
|
||||||
{
|
|
||||||
uint8_t *new_data = new uint8_t[data_info.second];
|
uint8_t *new_data = new uint8_t[data_info.second];
|
||||||
std::copy_n(data_info.first, data_info.second, new_data);
|
std::copy_n(data_info.first, data_info.second, new_data);
|
||||||
value.v_bytes->push_back({ new_data, data_info.second });
|
value.v_bytes->push_back({new_data, data_info.second});
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
value.v_bytes = new std::vector<std::pair<uint8_t *, size_t>>(*other.value.v_bytes);
|
value.v_bytes = new std::vector<std::pair<uint8_t *, size_t>>(*other.value.v_bytes);
|
||||||
}
|
}
|
||||||
cached_messages = new std::vector<Message *>();
|
cached_messages = new std::vector<Message *>();
|
||||||
cached_messages->reserve(other.cached_messages->size());
|
cached_messages->reserve(other.cached_messages->size());
|
||||||
for (Message *other_cached_message : *other.cached_messages)
|
for (Message *other_cached_message: *other.cached_messages) {
|
||||||
{
|
|
||||||
Message *cached_message;
|
Message *cached_message;
|
||||||
if (other_cached_message)
|
if (other_cached_message) {
|
||||||
{
|
|
||||||
cached_message = new Message(*other_cached_message);
|
cached_message = new Message(*other_cached_message);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
cached_message = nullptr;
|
cached_message = nullptr;
|
||||||
}
|
}
|
||||||
cached_messages->push_back(cached_message);
|
cached_messages->push_back(cached_message);
|
||||||
}
|
}
|
||||||
}
|
} break;
|
||||||
break;
|
default: {
|
||||||
default:
|
|
||||||
{
|
|
||||||
PP_LOG(ERROR) << "Bad field type when constructing field: " << type;
|
PP_LOG(ERROR) << "Bad field type when constructing field: " << type;
|
||||||
}
|
} break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Field::~Field()
|
Field::~Field() {
|
||||||
{
|
switch (type) {
|
||||||
switch (type)
|
case FIELD_UINT32:
|
||||||
{
|
delete value.v_uint32;
|
||||||
case FIELD_UINT32: delete value.v_uint32; break;
|
break;
|
||||||
case FIELD_UINT64: delete value.v_uint64; break;
|
case FIELD_UINT64:
|
||||||
case FIELD_BYTES:
|
delete value.v_uint64;
|
||||||
{
|
break;
|
||||||
|
case FIELD_BYTES: {
|
||||||
if (owns_data)
|
if (owns_data)
|
||||||
for (std::pair<uint8_t *, size_t> data_info : *value.v_bytes)
|
for (std::pair<uint8_t *, size_t> data_info: *value.v_bytes)
|
||||||
delete[] data_info.first;
|
delete[] data_info.first;
|
||||||
delete value.v_bytes;
|
delete value.v_bytes;
|
||||||
|
|
||||||
for (Message *cached_message : *cached_messages)
|
for (Message *cached_message: *cached_messages)
|
||||||
if (cached_message)
|
if (cached_message)
|
||||||
delete cached_message;
|
delete cached_message;
|
||||||
delete cached_messages;
|
delete cached_messages;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: PP_LOG(ERROR) << "Bad field type when destroying field: " << type; break;
|
default:
|
||||||
|
PP_LOG(ERROR) << "Bad field type when destroying field: " << type;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,74 +192,61 @@ namespace picoproto
|
|||||||
|
|
||||||
Message::~Message(){};
|
Message::~Message(){};
|
||||||
|
|
||||||
bool Message::ParseFromBytes(uint8_t *bytes, size_t bytes_size)
|
bool Message::ParseFromBytes(uint8_t *bytes, size_t bytes_size) {
|
||||||
{
|
|
||||||
uint8_t *current = bytes;
|
uint8_t *current = bytes;
|
||||||
size_t remaining = bytes_size;
|
size_t remaining = bytes_size;
|
||||||
while (remaining > 0)
|
while (remaining > 0) {
|
||||||
{
|
|
||||||
uint8_t wire_type;
|
uint8_t wire_type;
|
||||||
uint32_t field_number;
|
uint32_t field_number;
|
||||||
ReadWireTypeAndFieldNumber(¤t, &remaining, &wire_type, &field_number);
|
ReadWireTypeAndFieldNumber(¤t, &remaining, &wire_type, &field_number);
|
||||||
switch (wire_type)
|
switch (wire_type) {
|
||||||
{
|
case WIRETYPE_VARINT: {
|
||||||
case WIRETYPE_VARINT:
|
|
||||||
{
|
|
||||||
Field *field = AddField(field_number, FIELD_UINT64);
|
Field *field = AddField(field_number, FIELD_UINT64);
|
||||||
const uint64_t varint = ReadVarInt(¤t, &remaining);
|
const uint64_t varint = ReadVarInt(¤t, &remaining);
|
||||||
field->value.v_uint64->push_back(varint);
|
field->value.v_uint64->push_back(varint);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WIRETYPE_64BIT:
|
case WIRETYPE_64BIT: {
|
||||||
{
|
|
||||||
Field *field = AddField(field_number, FIELD_UINT64);
|
Field *field = AddField(field_number, FIELD_UINT64);
|
||||||
const uint64_t value = ReadFromBytes<uint64_t>(¤t, &remaining);
|
const uint64_t value = ReadFromBytes<uint64_t>(¤t, &remaining);
|
||||||
field->value.v_uint64->push_back(value);
|
field->value.v_uint64->push_back(value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WIRETYPE_LENGTH_DELIMITED:
|
case WIRETYPE_LENGTH_DELIMITED: {
|
||||||
{
|
|
||||||
Field *field = AddField(field_number, FIELD_BYTES);
|
Field *field = AddField(field_number, FIELD_BYTES);
|
||||||
const uint64_t size = ReadVarInt(¤t, &remaining);
|
const uint64_t size = ReadVarInt(¤t, &remaining);
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
if (copy_arrays)
|
if (copy_arrays) {
|
||||||
{
|
|
||||||
data = new uint8_t[size];
|
data = new uint8_t[size];
|
||||||
std::copy_n(current, size, data);
|
std::copy_n(current, size, data);
|
||||||
field->owns_data = true;
|
field->owns_data = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
data = current;
|
data = current;
|
||||||
field->owns_data = false;
|
field->owns_data = false;
|
||||||
}
|
}
|
||||||
field->value.v_bytes->push_back({ data, size });
|
field->value.v_bytes->push_back({data, size});
|
||||||
field->cached_messages->push_back(nullptr);
|
field->cached_messages->push_back(nullptr);
|
||||||
current += size;
|
current += size;
|
||||||
remaining -= size;
|
remaining -= size;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WIRETYPE_GROUP_START:
|
case WIRETYPE_GROUP_START: {
|
||||||
{
|
|
||||||
PP_LOG(INFO) << field_number << ": GROUPSTART" << std::endl;
|
PP_LOG(INFO) << field_number << ": GROUPSTART" << std::endl;
|
||||||
PP_LOG(ERROR) << "Unhandled wire type encountered";
|
PP_LOG(ERROR) << "Unhandled wire type encountered";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WIRETYPE_GROUP_END:
|
case WIRETYPE_GROUP_END: {
|
||||||
{
|
|
||||||
PP_LOG(INFO) << field_number << ": GROUPEND" << std::endl;
|
PP_LOG(INFO) << field_number << ": GROUPEND" << std::endl;
|
||||||
PP_LOG(ERROR) << "Unhandled wire type encountered";
|
PP_LOG(ERROR) << "Unhandled wire type encountered";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WIRETYPE_32BIT:
|
case WIRETYPE_32BIT: {
|
||||||
{
|
|
||||||
Field *field = AddField(field_number, FIELD_UINT32);
|
Field *field = AddField(field_number, FIELD_UINT32);
|
||||||
const uint32_t value = ReadFromBytes<uint32_t>(¤t, &remaining);
|
const uint32_t value = ReadFromBytes<uint32_t>(¤t, &remaining);
|
||||||
field->value.v_uint32->push_back(value);
|
field->value.v_uint32->push_back(value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default: {
|
||||||
{
|
|
||||||
PP_LOG(ERROR) << "Unknown wire type encountered: " << static_cast<int>(wire_type) << " at offset" << (bytes_size - remaining);
|
PP_LOG(ERROR) << "Unknown wire type encountered: " << static_cast<int>(wire_type) << " at offset" << (bytes_size - remaining);
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
@@ -296,122 +256,107 @@ namespace picoproto
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Field *Message::AddField(int32_t number, enum FieldType type)
|
Field *Message::AddField(int32_t number, enum FieldType type) {
|
||||||
{
|
|
||||||
Field *field = GetField(number);
|
Field *field = GetField(number);
|
||||||
if (!field)
|
if (!field) {
|
||||||
{
|
|
||||||
fields.push_back(Field(type, copy_arrays));
|
fields.push_back(Field(type, copy_arrays));
|
||||||
field = &fields.back();
|
field = &fields.back();
|
||||||
field_map.insert({ number, fields.size() - 1 });
|
field_map.insert({number, fields.size() - 1});
|
||||||
}
|
}
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
Field *Message::GetField(int32_t number)
|
Field *Message::GetField(int32_t number) {
|
||||||
{
|
|
||||||
if (field_map.count(number) == 0)
|
if (field_map.count(number) == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return &(fields[field_map[number]]);
|
return &(fields[field_map[number]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Field *Message::GetFieldAndCheckType(int32_t number, enum FieldType type)
|
Field *Message::GetFieldAndCheckType(int32_t number, enum FieldType type) {
|
||||||
{
|
|
||||||
Field *field = GetField(number);
|
Field *field = GetField(number);
|
||||||
PP_CHECK(field) << "No field for " << number;
|
PP_CHECK(field) << "No field for " << number;
|
||||||
PP_CHECK(field->type == type) << "For field " << number << " wanted type " << FieldTypeDebugString(type) << " but found " << FieldTypeDebugString(field->type);
|
PP_CHECK(field->type == type) << "For field " << number << " wanted type " << FieldTypeDebugString(type) << " but found " << FieldTypeDebugString(field->type);
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Message::GetInt32(int32_t number)
|
int32_t Message::GetInt32(int32_t number) {
|
||||||
{
|
|
||||||
Field *field = GetFieldAndCheckType(number, FIELD_UINT32);
|
Field *field = GetFieldAndCheckType(number, FIELD_UINT32);
|
||||||
uint32_t first_value = (*(field->value.v_uint32))[0];
|
uint32_t first_value = (*(field->value.v_uint32))[0];
|
||||||
int32_t zig_zag_decoded = static_cast<int32_t>((first_value >> 1) ^ (-(first_value & 1)));
|
int32_t zig_zag_decoded = static_cast<int32_t>((first_value >> 1) ^ (-(first_value & 1)));
|
||||||
return zig_zag_decoded;
|
return zig_zag_decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t Message::GetInt64(int32_t number)
|
int64_t Message::GetInt64(int32_t number) {
|
||||||
{
|
|
||||||
Field *field = GetFieldAndCheckType(number, FIELD_UINT64);
|
Field *field = GetFieldAndCheckType(number, FIELD_UINT64);
|
||||||
uint64_t first_value = (*(field->value.v_uint64))[0];
|
uint64_t first_value = (*(field->value.v_uint64))[0];
|
||||||
int64_t zig_zag_decoded = static_cast<int64_t>((first_value >> 1) ^ (-(first_value & 1)));
|
int64_t zig_zag_decoded = static_cast<int64_t>((first_value >> 1) ^ (-(first_value & 1)));
|
||||||
return zig_zag_decoded;
|
return zig_zag_decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Message::GetUInt32(int32_t number)
|
uint32_t Message::GetUInt32(int32_t number) {
|
||||||
{
|
|
||||||
Field *field = GetFieldAndCheckType(number, FIELD_UINT32);
|
Field *field = GetFieldAndCheckType(number, FIELD_UINT32);
|
||||||
uint32_t first_value = (*(field->value.v_uint32))[0];
|
uint32_t first_value = (*(field->value.v_uint32))[0];
|
||||||
return first_value;
|
return first_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Message::GetUInt64(int32_t number)
|
uint64_t Message::GetUInt64(int32_t number) {
|
||||||
{
|
|
||||||
Field *field = GetFieldAndCheckType(number, FIELD_UINT64);
|
Field *field = GetFieldAndCheckType(number, FIELD_UINT64);
|
||||||
uint64_t first_value = (*(field->value.v_uint64))[0];
|
uint64_t first_value = (*(field->value.v_uint64))[0];
|
||||||
return first_value;
|
return first_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t Message::GetInt(int32_t number)
|
int64_t Message::GetInt(int32_t number) {
|
||||||
{
|
|
||||||
Field *field = GetField(number);
|
Field *field = GetField(number);
|
||||||
PP_CHECK(field) << "No field for " << number;
|
PP_CHECK(field) << "No field for " << number;
|
||||||
PP_CHECK((field->type == FIELD_UINT32) || (field->type == FIELD_UINT64))
|
PP_CHECK((field->type == FIELD_UINT32) || (field->type == FIELD_UINT64))
|
||||||
<< "For field " << number << " wanted integer type but found " << FieldTypeDebugString(field->type);
|
<< "For field " << number << " wanted integer type but found " << FieldTypeDebugString(field->type);
|
||||||
switch (field->type)
|
switch (field->type) {
|
||||||
{
|
case FIELD_UINT32:
|
||||||
case FIELD_UINT32: return GetInt32(number); break;
|
return GetInt32(number);
|
||||||
case FIELD_UINT64: return GetInt64(number); break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
// Should never get here.
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
case FIELD_UINT64:
|
||||||
|
return GetInt64(number);
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
// Should never get here.
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
// Should never get here.
|
// Should never get here.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Message::GetBool(int32_t number)
|
bool Message::GetBool(int32_t number) {
|
||||||
{
|
|
||||||
return (GetInt(number) != 0);
|
return (GetInt(number) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Message::GetFloat(int32_t number)
|
float Message::GetFloat(int32_t number) {
|
||||||
{
|
|
||||||
uint32_t int_value = GetUInt32(number);
|
uint32_t int_value = GetUInt32(number);
|
||||||
float float_value = *(bit_cast<float *>(&int_value));
|
float float_value = *(bit_cast<float *>(&int_value));
|
||||||
return float_value;
|
return float_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Message::GetDouble(int32_t number)
|
double Message::GetDouble(int32_t number) {
|
||||||
{
|
|
||||||
uint64_t int_value = GetUInt64(number);
|
uint64_t int_value = GetUInt64(number);
|
||||||
return *(bit_cast<double *>(&int_value));
|
return *(bit_cast<double *>(&int_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<uint8_t *, size_t> Message::GetBytes(int32_t number)
|
std::pair<uint8_t *, size_t> Message::GetBytes(int32_t number) {
|
||||||
{
|
|
||||||
Field *field = GetFieldAndCheckType(number, FIELD_BYTES);
|
Field *field = GetFieldAndCheckType(number, FIELD_BYTES);
|
||||||
std::pair<uint8_t *, size_t> first_value = (*(field->value.v_bytes))[0];
|
std::pair<uint8_t *, size_t> first_value = (*(field->value.v_bytes))[0];
|
||||||
return first_value;
|
return first_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Message::GetString(int32_t number)
|
std::string Message::GetString(int32_t number) {
|
||||||
{
|
|
||||||
Field *field = GetFieldAndCheckType(number, FIELD_BYTES);
|
Field *field = GetFieldAndCheckType(number, FIELD_BYTES);
|
||||||
std::pair<uint8_t *, size_t> first_value = (*(field->value.v_bytes))[0];
|
std::pair<uint8_t *, size_t> first_value = (*(field->value.v_bytes))[0];
|
||||||
std::string result(first_value.first, first_value.first + first_value.second);
|
std::string result(first_value.first, first_value.first + first_value.second);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Message *Message::GetMessage(int32_t number)
|
Message *Message::GetMessage(int32_t number) {
|
||||||
{
|
|
||||||
Field *field = GetFieldAndCheckType(number, FIELD_BYTES);
|
Field *field = GetFieldAndCheckType(number, FIELD_BYTES);
|
||||||
Message *cached_message = field->cached_messages->at(0);
|
Message *cached_message = field->cached_messages->at(0);
|
||||||
if (!cached_message)
|
if (!cached_message) {
|
||||||
{
|
|
||||||
std::pair<uint8_t *, size_t> first_value = (*(field->value.v_bytes))[0];
|
std::pair<uint8_t *, size_t> first_value = (*(field->value.v_bytes))[0];
|
||||||
cached_message = new Message(copy_arrays);
|
cached_message = new Message(copy_arrays);
|
||||||
cached_message->ParseFromBytes(first_value.first, first_value.second);
|
cached_message->ParseFromBytes(first_value.first, first_value.second);
|
||||||
@@ -420,232 +365,176 @@ namespace picoproto
|
|||||||
return cached_message;
|
return cached_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int32_t> Message::GetInt32Array(int32_t number)
|
std::vector<int32_t> Message::GetInt32Array(int32_t number) {
|
||||||
{
|
|
||||||
std::vector<uint64_t> raw_array = GetUInt64Array(number);
|
std::vector<uint64_t> raw_array = GetUInt64Array(number);
|
||||||
std::vector<int32_t> result;
|
std::vector<int32_t> result;
|
||||||
result.reserve(raw_array.size());
|
result.reserve(raw_array.size());
|
||||||
for (uint64_t raw_value : raw_array)
|
for (uint64_t raw_value: raw_array) {
|
||||||
{
|
|
||||||
int32_t zig_zag_decoded = static_cast<int32_t>((raw_value >> 1) ^ (-(raw_value & 1)));
|
int32_t zig_zag_decoded = static_cast<int32_t>((raw_value >> 1) ^ (-(raw_value & 1)));
|
||||||
result.push_back(zig_zag_decoded);
|
result.push_back(zig_zag_decoded);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int64_t> Message::GetInt64Array(int32_t number)
|
std::vector<int64_t> Message::GetInt64Array(int32_t number) {
|
||||||
{
|
|
||||||
std::vector<uint64_t> raw_array = GetUInt64Array(number);
|
std::vector<uint64_t> raw_array = GetUInt64Array(number);
|
||||||
std::vector<int64_t> result;
|
std::vector<int64_t> result;
|
||||||
result.reserve(raw_array.size());
|
result.reserve(raw_array.size());
|
||||||
for (uint64_t raw_value : raw_array)
|
for (uint64_t raw_value: raw_array) {
|
||||||
{
|
|
||||||
int64_t zig_zag_decoded = static_cast<int64_t>((raw_value >> 1) ^ (-(raw_value & 1)));
|
int64_t zig_zag_decoded = static_cast<int64_t>((raw_value >> 1) ^ (-(raw_value & 1)));
|
||||||
result.push_back(zig_zag_decoded);
|
result.push_back(zig_zag_decoded);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> Message::GetUInt32Array(int32_t number)
|
std::vector<uint32_t> Message::GetUInt32Array(int32_t number) {
|
||||||
{
|
|
||||||
std::vector<uint64_t> raw_array = GetUInt64Array(number);
|
std::vector<uint64_t> raw_array = GetUInt64Array(number);
|
||||||
std::vector<uint32_t> result;
|
std::vector<uint32_t> result;
|
||||||
result.reserve(raw_array.size());
|
result.reserve(raw_array.size());
|
||||||
for (uint64_t raw_value : raw_array)
|
for (uint64_t raw_value: raw_array) {
|
||||||
{
|
|
||||||
result.push_back(static_cast<uint32_t>(raw_value));
|
result.push_back(static_cast<uint32_t>(raw_value));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint64_t> Message::GetUInt64Array(int32_t number)
|
std::vector<uint64_t> Message::GetUInt64Array(int32_t number) {
|
||||||
{
|
|
||||||
std::vector<uint64_t> result;
|
std::vector<uint64_t> result;
|
||||||
Field *field = GetField(number);
|
Field *field = GetField(number);
|
||||||
if (!field)
|
if (!field) {
|
||||||
{
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (field->type == FIELD_UINT64)
|
if (field->type == FIELD_UINT64) {
|
||||||
{
|
|
||||||
result.reserve(field->value.v_uint64->size());
|
result.reserve(field->value.v_uint64->size());
|
||||||
for (uint64_t value : *field->value.v_uint64)
|
for (uint64_t value: *field->value.v_uint64) {
|
||||||
{
|
|
||||||
result.push_back(static_cast<uint64_t>(value));
|
result.push_back(static_cast<uint64_t>(value));
|
||||||
}
|
}
|
||||||
}
|
} else if (field->type == FIELD_UINT32) {
|
||||||
else if (field->type == FIELD_UINT32)
|
|
||||||
{
|
|
||||||
result.reserve(field->value.v_uint32->size());
|
result.reserve(field->value.v_uint32->size());
|
||||||
for (uint32_t value : *field->value.v_uint32)
|
for (uint32_t value: *field->value.v_uint32) {
|
||||||
{
|
|
||||||
result.push_back(static_cast<uint64_t>(value));
|
result.push_back(static_cast<uint64_t>(value));
|
||||||
}
|
}
|
||||||
}
|
} else if (field->type == FIELD_BYTES) {
|
||||||
else if (field->type == FIELD_BYTES)
|
for (std::pair<uint8_t *, size_t> data_info: *field->value.v_bytes) {
|
||||||
{
|
|
||||||
for (std::pair<uint8_t *, size_t> data_info : *field->value.v_bytes)
|
|
||||||
{
|
|
||||||
uint8_t *current = data_info.first;
|
uint8_t *current = data_info.first;
|
||||||
size_t remaining = data_info.second;
|
size_t remaining = data_info.second;
|
||||||
while (remaining > 0)
|
while (remaining > 0) {
|
||||||
{
|
|
||||||
const uint64_t varint = ReadVarInt(¤t, &remaining);
|
const uint64_t varint = ReadVarInt(¤t, &remaining);
|
||||||
result.push_back(static_cast<int64_t>(varint));
|
result.push_back(static_cast<int64_t>(varint));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
PP_LOG(ERROR) << "Expected field type UINT32, UINT64, or BYTES but got " << FieldTypeDebugString(field->type);
|
PP_LOG(ERROR) << "Expected field type UINT32, UINT64, or BYTES but got " << FieldTypeDebugString(field->type);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<bool> Message::GetBoolArray(int32_t number)
|
std::vector<bool> Message::GetBoolArray(int32_t number) {
|
||||||
{
|
|
||||||
std::vector<uint64_t> raw_array = GetUInt64Array(number);
|
std::vector<uint64_t> raw_array = GetUInt64Array(number);
|
||||||
std::vector<bool> result;
|
std::vector<bool> result;
|
||||||
result.reserve(raw_array.size());
|
result.reserve(raw_array.size());
|
||||||
for (uint64_t raw_value : raw_array)
|
for (uint64_t raw_value: raw_array) {
|
||||||
{
|
|
||||||
result.push_back(raw_value != 0);
|
result.push_back(raw_value != 0);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<float> Message::GetFloatArray(int32_t number)
|
std::vector<float> Message::GetFloatArray(int32_t number) {
|
||||||
{
|
|
||||||
std::vector<float> result;
|
std::vector<float> result;
|
||||||
Field *field = GetField(number);
|
Field *field = GetField(number);
|
||||||
if (!field)
|
if (!field) {
|
||||||
{
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (field->type == FIELD_UINT32)
|
if (field->type == FIELD_UINT32) {
|
||||||
{
|
|
||||||
result.reserve(field->value.v_uint32->size());
|
result.reserve(field->value.v_uint32->size());
|
||||||
for (uint32_t value : *field->value.v_uint32)
|
for (uint32_t value: *field->value.v_uint32) {
|
||||||
{
|
|
||||||
result.push_back(bit_cast<float>(value));
|
result.push_back(bit_cast<float>(value));
|
||||||
}
|
}
|
||||||
}
|
} else if (field->type == FIELD_BYTES) {
|
||||||
else if (field->type == FIELD_BYTES)
|
for (std::pair<uint8_t *, size_t> data_info: *field->value.v_bytes) {
|
||||||
{
|
|
||||||
for (std::pair<uint8_t *, size_t> data_info : *field->value.v_bytes)
|
|
||||||
{
|
|
||||||
uint8_t *current = data_info.first;
|
uint8_t *current = data_info.first;
|
||||||
size_t remaining = data_info.second;
|
size_t remaining = data_info.second;
|
||||||
while (remaining > 0)
|
while (remaining > 0) {
|
||||||
{
|
|
||||||
const uint64_t varint = ReadVarInt(¤t, &remaining);
|
const uint64_t varint = ReadVarInt(¤t, &remaining);
|
||||||
const uint32_t varint32 = static_cast<uint32_t>(varint & 0xffffffff);
|
const uint32_t varint32 = static_cast<uint32_t>(varint & 0xffffffff);
|
||||||
result.push_back(bit_cast<float>(varint32));
|
result.push_back(bit_cast<float>(varint32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
PP_LOG(ERROR) << "Expected field type UINT32 or BYTES but got " << FieldTypeDebugString(field->type);
|
PP_LOG(ERROR) << "Expected field type UINT32 or BYTES but got " << FieldTypeDebugString(field->type);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<double> Message::GetDoubleArray(int32_t number)
|
std::vector<double> Message::GetDoubleArray(int32_t number) {
|
||||||
{
|
|
||||||
std::vector<double> result;
|
std::vector<double> result;
|
||||||
Field *field = GetField(number);
|
Field *field = GetField(number);
|
||||||
if (!field)
|
if (!field) {
|
||||||
{
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (field->type == FIELD_UINT64)
|
if (field->type == FIELD_UINT64) {
|
||||||
{
|
|
||||||
result.reserve(field->value.v_uint64->size());
|
result.reserve(field->value.v_uint64->size());
|
||||||
for (uint64_t value : *field->value.v_uint64)
|
for (uint64_t value: *field->value.v_uint64) {
|
||||||
{
|
|
||||||
result.push_back(bit_cast<double>(value));
|
result.push_back(bit_cast<double>(value));
|
||||||
}
|
}
|
||||||
}
|
} else if (field->type == FIELD_BYTES) {
|
||||||
else if (field->type == FIELD_BYTES)
|
for (std::pair<uint8_t *, size_t> data_info: *field->value.v_bytes) {
|
||||||
{
|
|
||||||
for (std::pair<uint8_t *, size_t> data_info : *field->value.v_bytes)
|
|
||||||
{
|
|
||||||
uint8_t *current = data_info.first;
|
uint8_t *current = data_info.first;
|
||||||
size_t remaining = data_info.second;
|
size_t remaining = data_info.second;
|
||||||
while (remaining > 0)
|
while (remaining > 0) {
|
||||||
{
|
|
||||||
const uint64_t varint = ReadVarInt(¤t, &remaining);
|
const uint64_t varint = ReadVarInt(¤t, &remaining);
|
||||||
result.push_back(bit_cast<double>(varint));
|
result.push_back(bit_cast<double>(varint));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
PP_LOG(ERROR) << "Expected field type UINT64 or BYTES but got " << FieldTypeDebugString(field->type);
|
PP_LOG(ERROR) << "Expected field type UINT64 or BYTES but got " << FieldTypeDebugString(field->type);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<uint8_t *, size_t>> Message::GetByteArray(int32_t number)
|
std::vector<std::pair<uint8_t *, size_t>> Message::GetByteArray(int32_t number) {
|
||||||
{
|
|
||||||
std::vector<std::pair<uint8_t *, size_t>> result;
|
std::vector<std::pair<uint8_t *, size_t>> result;
|
||||||
Field *field = GetField(number);
|
Field *field = GetField(number);
|
||||||
if (!field)
|
if (!field) {
|
||||||
{
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (field->type == FIELD_BYTES)
|
if (field->type == FIELD_BYTES) {
|
||||||
{
|
|
||||||
result.reserve(field->value.v_bytes->size());
|
result.reserve(field->value.v_bytes->size());
|
||||||
for (std::pair<uint8_t *, size_t> data_info : *field->value.v_bytes)
|
for (std::pair<uint8_t *, size_t> data_info: *field->value.v_bytes) {
|
||||||
{
|
|
||||||
result.push_back(data_info);
|
result.push_back(data_info);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
PP_LOG(ERROR) << "Expected field type BYTES but got " << FieldTypeDebugString(field->type);
|
PP_LOG(ERROR) << "Expected field type BYTES but got " << FieldTypeDebugString(field->type);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Message::GetStringArray(int32_t number)
|
std::vector<std::string> Message::GetStringArray(int32_t number) {
|
||||||
{
|
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
Field *field = GetField(number);
|
Field *field = GetField(number);
|
||||||
if (!field)
|
if (!field)
|
||||||
return result;
|
return result;
|
||||||
if (field->type == FIELD_BYTES)
|
if (field->type == FIELD_BYTES) {
|
||||||
{
|
|
||||||
result.reserve(field->value.v_bytes->size());
|
result.reserve(field->value.v_bytes->size());
|
||||||
for (std::pair<uint8_t *, size_t> data_info : *field->value.v_bytes)
|
for (std::pair<uint8_t *, size_t> data_info: *field->value.v_bytes) {
|
||||||
{
|
|
||||||
result.push_back(std::string(data_info.first, data_info.first + data_info.second));
|
result.push_back(std::string(data_info.first, data_info.first + data_info.second));
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
PP_LOG(ERROR) << "Expected field type BYTES but got " << FieldTypeDebugString(field->type);
|
PP_LOG(ERROR) << "Expected field type BYTES but got " << FieldTypeDebugString(field->type);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Message *> Message::GetMessageArray(int32_t number)
|
std::vector<Message *> Message::GetMessageArray(int32_t number) {
|
||||||
{
|
|
||||||
std::vector<Message *> result;
|
std::vector<Message *> result;
|
||||||
Field *field = GetField(number);
|
Field *field = GetField(number);
|
||||||
if (!field)
|
if (!field)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
if (field->type == FIELD_BYTES)
|
if (field->type == FIELD_BYTES) {
|
||||||
{
|
|
||||||
result.reserve(field->value.v_bytes->size());
|
result.reserve(field->value.v_bytes->size());
|
||||||
for (size_t i = 0; i < field->value.v_bytes->size(); ++i)
|
for (size_t i = 0; i < field->value.v_bytes->size(); ++i) {
|
||||||
{
|
|
||||||
Message *cached_message = field->cached_messages->at(i);
|
Message *cached_message = field->cached_messages->at(i);
|
||||||
if (!cached_message)
|
if (!cached_message) {
|
||||||
{
|
|
||||||
std::pair<uint8_t *, size_t> value = field->value.v_bytes->at(i);
|
std::pair<uint8_t *, size_t> value = field->value.v_bytes->at(i);
|
||||||
cached_message = new Message(copy_arrays);
|
cached_message = new Message(copy_arrays);
|
||||||
cached_message->ParseFromBytes(value.first, value.second);
|
cached_message->ParseFromBytes(value.first, value.second);
|
||||||
@@ -653,9 +542,7 @@ namespace picoproto
|
|||||||
}
|
}
|
||||||
result.push_back(cached_message);
|
result.push_back(cached_message);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
PP_LOG(ERROR) << "Expected field type BYTES but got " << FieldTypeDebugString(field->type);
|
PP_LOG(ERROR) << "Expected field type BYTES but got " << FieldTypeDebugString(field->type);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -74,16 +74,14 @@
|
|||||||
if (!(X)) \
|
if (!(X)) \
|
||||||
PP_LOG(ERROR) << "PP_CHECK(" << #X << ") failed. "
|
PP_LOG(ERROR) << "PP_CHECK(" << #X << ") failed. "
|
||||||
|
|
||||||
namespace picoproto
|
namespace picoproto {
|
||||||
{
|
|
||||||
|
|
||||||
// These roughly correspond to the wire types used to save data in protobuf
|
// These roughly correspond to the wire types used to save data in protobuf
|
||||||
// files. The best reference to understand the full format is:
|
// files. The best reference to understand the full format is:
|
||||||
// https://developers.google.com/protocol-buffers/docs/encoding
|
// https://developers.google.com/protocol-buffers/docs/encoding
|
||||||
// Because we don't know the bit-depth of VarInts, they're always stored as
|
// Because we don't know the bit-depth of VarInts, they're always stored as
|
||||||
// uint64 values, which is why there's no specific type for them.
|
// uint64 values, which is why there's no specific type for them.
|
||||||
enum FieldType
|
enum FieldType {
|
||||||
{
|
|
||||||
FIELD_UNSET,
|
FIELD_UNSET,
|
||||||
FIELD_UINT32,
|
FIELD_UINT32,
|
||||||
FIELD_UINT64,
|
FIELD_UINT64,
|
||||||
@@ -100,8 +98,7 @@ namespace picoproto
|
|||||||
// data member, and handle all the allocation and deallocation of storage.
|
// data member, and handle all the allocation and deallocation of storage.
|
||||||
// It's unlikely you'll want to access this class directly, since you'll
|
// It's unlikely you'll want to access this class directly, since you'll
|
||||||
// normally want to use Message below to pull typed values.
|
// normally want to use Message below to pull typed values.
|
||||||
class Field
|
class Field {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
// You need to specify the type of a Field on creation, so that the right
|
// You need to specify the type of a Field on creation, so that the right
|
||||||
// storage can be set up for the values. You also need to indicate whether the
|
// storage can be set up for the values. You also need to indicate whether the
|
||||||
@@ -117,8 +114,7 @@ namespace picoproto
|
|||||||
// and deciding how to initialize and access the data based on that persuaded
|
// and deciding how to initialize and access the data based on that persuaded
|
||||||
// me this was the best approach. The `value` member contains whatever data
|
// me this was the best approach. The `value` member contains whatever data
|
||||||
// the field should be holding.
|
// the field should be holding.
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
std::vector<uint32_t> *v_uint32;
|
std::vector<uint32_t> *v_uint32;
|
||||||
std::vector<uint64_t> *v_uint64;
|
std::vector<uint64_t> *v_uint64;
|
||||||
std::vector<std::pair<uint8_t *, size_t>> *v_bytes;
|
std::vector<std::pair<uint8_t *, size_t>> *v_bytes;
|
||||||
@@ -138,8 +134,7 @@ namespace picoproto
|
|||||||
};
|
};
|
||||||
|
|
||||||
// The main interface for loading and accessing serialized protobuf data.
|
// The main interface for loading and accessing serialized protobuf data.
|
||||||
class Message
|
class Message {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
// If you're not sure about the lifetime of any binary data you're reading
|
// If you're not sure about the lifetime of any binary data you're reading
|
||||||
// from, just call this default constructor.
|
// from, just call this default constructor.
|
||||||
|
|||||||
@@ -9,11 +9,11 @@
|
|||||||
namespace Qv2ray::base {
|
namespace Qv2ray::base {
|
||||||
template<typename... T>
|
template<typename... T>
|
||||||
inline void log_internal(T... v) {}
|
inline void log_internal(T... v) {}
|
||||||
}
|
} // namespace Qv2ray::base
|
||||||
|
|
||||||
#define JsonToString(a) QJsonObject2QString(a,false)
|
#define JsonToString(a) QJsonObject2QString(a, false)
|
||||||
#define JsonFromString(a) QString2QJsonObject(a)
|
#define JsonFromString(a) QString2QJsonObject(a)
|
||||||
#define QvMessageBoxWarn(a, b, c) MessageBoxWarning(b,c)
|
#define QvMessageBoxWarn(a, b, c) MessageBoxWarning(b, c)
|
||||||
|
|
||||||
inline QString VerifyJsonString(const QString &source) {
|
inline QString VerifyJsonString(const QString &source) {
|
||||||
QJsonParseError error{};
|
QJsonParseError error{};
|
||||||
@@ -23,7 +23,7 @@ inline QString VerifyJsonString(const QString &source) {
|
|||||||
if (error.error == QJsonParseError::NoError) {
|
if (error.error == QJsonParseError::NoError) {
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
//LOG("WARNING: Json parse returns: " + error.errorString());
|
// LOG("WARNING: Json parse returns: " + error.errorString());
|
||||||
return error.errorString();
|
return error.errorString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
28
rpc/gRPC.cpp
28
rpc/gRPC.cpp
@@ -34,13 +34,13 @@ namespace QtGrpc {
|
|||||||
|
|
||||||
// TODO WTF
|
// TODO WTF
|
||||||
// https://github.com/semlanik/qtprotobuf/issues/116
|
// https://github.com/semlanik/qtprotobuf/issues/116
|
||||||
// setCachingEnabled: 5 bytesDownloaded
|
// setCachingEnabled: 5 bytesDownloaded
|
||||||
// QNetworkReplyImpl: backend error: caching was enabled after some bytes had been written
|
// QNetworkReplyImpl: backend error: caching was enabled after some bytes had been written
|
||||||
|
|
||||||
// async
|
// async
|
||||||
QNetworkReply *post(const QString &method, const QString &service, const QByteArray &args) {
|
QNetworkReply *post(const QString &method, const QString &service, const QByteArray &args) {
|
||||||
QUrl callUrl = url_base + "/" + service + "/" + method;
|
QUrl callUrl = url_base + "/" + service + "/" + method;
|
||||||
// qDebug() << "Service call url: " << callUrl;
|
// qDebug() << "Service call url: " << callUrl;
|
||||||
|
|
||||||
QNetworkRequest request(callUrl);
|
QNetworkRequest request(callUrl);
|
||||||
request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false);
|
request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false);
|
||||||
@@ -144,15 +144,17 @@ namespace QtGrpc {
|
|||||||
QMutex lock;
|
QMutex lock;
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
|
||||||
runOnUiThread([&] {
|
runOnUiThread(
|
||||||
|
[&] {
|
||||||
err = call(methodName, serviceName, requestArray, responseArray, timeout_ms);
|
err = call(methodName, serviceName, requestArray, responseArray, timeout_ms);
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}, nm);
|
},
|
||||||
|
nm);
|
||||||
|
|
||||||
lock.lock();
|
lock.lock();
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
// qDebug() << "rsp err" << err;
|
// qDebug() << "rsp err" << err;
|
||||||
// qDebug() << "rsp array" << responseArray;
|
// qDebug() << "rsp array" << responseArray;
|
||||||
|
|
||||||
if (err != QNetworkReply::NetworkError::NoError) {
|
if (err != QNetworkReply::NetworkError::NoError) {
|
||||||
return err;
|
return err;
|
||||||
@@ -162,9 +164,8 @@ namespace QtGrpc {
|
|||||||
}
|
}
|
||||||
return QNetworkReply::NetworkError::NoError;
|
return QNetworkReply::NetworkError::NoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
} // namespace QtGrpc
|
||||||
|
|
||||||
namespace NekoRay::rpc {
|
namespace NekoRay::rpc {
|
||||||
Client::Client(std::function<void(const QString &)> onError, const QString &target, const QString &token) {
|
Client::Client(std::function<void(const QString &)> onError, const QString &target, const QString &token) {
|
||||||
@@ -172,10 +173,9 @@ namespace NekoRay::rpc {
|
|||||||
this->onError = std::move(onError);
|
this->onError = std::move(onError);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NOT_OK *rpcOK = false; \
|
#define NOT_OK \
|
||||||
onError( \
|
*rpcOK = false; \
|
||||||
QString("QNetworkReply::NetworkError code: %1\n").arg(status) \
|
onError(QString("QNetworkReply::NetworkError code: %1\n").arg(status));
|
||||||
);
|
|
||||||
|
|
||||||
void Client::Exit() {
|
void Client::Exit() {
|
||||||
libcore::EmptyReq request;
|
libcore::EmptyReq request;
|
||||||
@@ -276,6 +276,6 @@ namespace NekoRay::rpc {
|
|||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // namespace NekoRay::rpc
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -42,6 +42,5 @@ namespace NekoRay::rpc {
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline Client *defaultClient;
|
inline Client *defaultClient;
|
||||||
}
|
} // namespace NekoRay::rpc
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -33,15 +33,14 @@ namespace NekoRay::sub {
|
|||||||
stream->security = "tls";
|
stream->security = "tls";
|
||||||
}
|
}
|
||||||
// 2. TLS SNI: v2rayN config builder generate sni like this, so set sni here for their format.
|
// 2. TLS SNI: v2rayN config builder generate sni like this, so set sni here for their format.
|
||||||
if (stream->security == "tls" && IsIpAddress(ent->bean->serverAddress)
|
if (stream->security == "tls" && IsIpAddress(ent->bean->serverAddress) && (!stream->host.isEmpty()) && stream->sni.isEmpty()) {
|
||||||
&& (!stream->host.isEmpty()) && stream->sni.isEmpty()) {
|
stream->sni = stream->host;
|
||||||
stream->sni = stream->host;;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RawUpdater::update(const QString &str) {
|
void RawUpdater::update(const QString &str) {
|
||||||
// Base64 encoded subscription
|
// Base64 encoded subscription
|
||||||
if (auto str2 = DecodeB64IfValid(str);!str2.isEmpty()) {
|
if (auto str2 = DecodeB64IfValid(str); !str2.isEmpty()) {
|
||||||
update(str2);
|
update(str2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -202,7 +201,7 @@ namespace NekoRay::sub {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// https://github.com/Dreamacro/clash/wiki/configuration
|
// https://github.com/Dreamacro/clash/wiki/configuration
|
||||||
void RawUpdater::updateClash(const QString &str) {
|
void RawUpdater::updateClash(const QString &str) {
|
||||||
#ifndef NKR_NO_EXTERNAL
|
#ifndef NKR_NO_EXTERNAL
|
||||||
try {
|
try {
|
||||||
@@ -364,8 +363,7 @@ namespace NekoRay::sub {
|
|||||||
|
|
||||||
auto resp = NetworkRequestHelper::HttpGet(content);
|
auto resp = NetworkRequestHelper::HttpGet(content);
|
||||||
if (!resp.error.isEmpty()) {
|
if (!resp.error.isEmpty()) {
|
||||||
MW_show_log("<<<<<<<< " + QObject::tr("Requesting subscription %1 error: %2")
|
MW_show_log("<<<<<<<< " + QObject::tr("Requesting subscription %1 error: %2").arg(groupName, resp.error + "\n" + resp.data));
|
||||||
.arg(groupName, resp.error + "\n" + resp.data));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,8 +421,10 @@ namespace NekoRay::sub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto change = "\n" + QObject::tr("Added %1 profiles:\n%2\nDeleted %3 Profiles:\n%4")
|
auto change = "\n" + QObject::tr("Added %1 profiles:\n%2\nDeleted %3 Profiles:\n%4")
|
||||||
.arg(only_out.length()).arg(notice_added)
|
.arg(only_out.length())
|
||||||
.arg(only_in.length()).arg(notice_deleted);
|
.arg(notice_added)
|
||||||
|
.arg(only_in.length())
|
||||||
|
.arg(notice_deleted);
|
||||||
if (only_out.length() + only_in.length() == 0) change = QObject::tr("Nothing");
|
if (only_out.length() + only_in.length() == 0) change = QObject::tr("Nothing");
|
||||||
MW_show_log("<<<<<<<< " + QObject::tr("Change of %1:").arg(group->name) + " " + change);
|
MW_show_log("<<<<<<<< " + QObject::tr("Change of %1:").arg(group->name) + " " + change);
|
||||||
MW_dialog_message("SubUpdater", "finish-dingyue");
|
MW_dialog_message("SubUpdater", "finish-dingyue");
|
||||||
@@ -433,4 +433,4 @@ namespace NekoRay::sub {
|
|||||||
MW_dialog_message("SubUpdater", "finish");
|
MW_dialog_message("SubUpdater", "finish");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // namespace NekoRay::sub
|
||||||
|
|||||||
@@ -28,5 +28,4 @@ namespace NekoRay::sub {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern GroupUpdater *groupUpdater;
|
extern GroupUpdater *groupUpdater;
|
||||||
}
|
} // namespace NekoRay::sub
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ void AutoRun_SetEnabled(bool enable) {
|
|||||||
QFileInfo fInfo(appPath);
|
QFileInfo fInfo(appPath);
|
||||||
QString name = fInfo.baseName();
|
QString name = fInfo.baseName();
|
||||||
|
|
||||||
QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
|
QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
|
||||||
QSettings::NativeFormat);
|
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
settings.setValue(name, Windows_GenAutoRunString());
|
settings.setValue(name, Windows_GenAutoRunString());
|
||||||
@@ -38,8 +37,7 @@ void AutoRun_SetEnabled(bool enable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool AutoRun_IsEnabled() {
|
bool AutoRun_IsEnabled() {
|
||||||
QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
|
QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
|
||||||
QSettings::NativeFormat);
|
|
||||||
|
|
||||||
//以程序名称作为注册表中的键
|
//以程序名称作为注册表中的键
|
||||||
//根据键获取对应的值(程序路径)
|
//根据键获取对应的值(程序路径)
|
||||||
@@ -50,7 +48,6 @@ bool AutoRun_IsEnabled() {
|
|||||||
return settings.value(name).toString() == Windows_GenAutoRunString();
|
return settings.value(name).toString() == Windows_GenAutoRunString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
@@ -194,13 +191,13 @@ void AutoRun_SetEnabled(bool enable) {
|
|||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||||
ts.setCodec("UTF-8");
|
ts.setCodec("UTF-8");
|
||||||
#endif
|
#endif
|
||||||
ts << QLatin1String("[Desktop Entry]") << NEWLINE //
|
ts << QLatin1String("[Desktop Entry]") << NEWLINE
|
||||||
<< QLatin1String("Name=") << appName << NEWLINE //
|
<< QLatin1String("Name=") << appName << NEWLINE
|
||||||
<< QLatin1String("Exec=") << appCmdList.join(" ") << NEWLINE //
|
<< QLatin1String("Exec=") << appCmdList.join(" ") << NEWLINE
|
||||||
<< QLatin1String("Terminal=") << "false" << NEWLINE //
|
<< QLatin1String("Terminal=") << "false" << NEWLINE
|
||||||
<< QLatin1String("Categories=") << "Network" << NEWLINE //
|
<< QLatin1String("Categories=") << "Network" << NEWLINE
|
||||||
<< QLatin1String("Type=") << "Application" << NEWLINE //
|
<< QLatin1String("Type=") << "Application" << NEWLINE
|
||||||
<< QLatin1String("StartupNotify=") << "false" << NEWLINE //
|
<< QLatin1String("StartupNotify=") << "false" << NEWLINE
|
||||||
<< QLatin1String("X-GNOME-Autostart-enabled=") << "true" << NEWLINE;
|
<< QLatin1String("X-GNOME-Autostart-enabled=") << "true" << NEWLINE;
|
||||||
ts.flush();
|
ts.flush();
|
||||||
iniFile.close();
|
iniFile.close();
|
||||||
|
|||||||
@@ -95,17 +95,21 @@ namespace NekoRay::sys {
|
|||||||
MW_show_log("[Error] core exited, restarting.\n");
|
MW_show_log("[Error] core exited, restarting.\n");
|
||||||
|
|
||||||
// Restart
|
// Restart
|
||||||
setTimeout([=] {
|
setTimeout(
|
||||||
|
[=] {
|
||||||
Kill();
|
Kill();
|
||||||
ExternalProcess::started = false;
|
ExternalProcess::started = false;
|
||||||
Start();
|
Start();
|
||||||
}, this, 1000);
|
},
|
||||||
|
this, 1000);
|
||||||
} else if (state == QProcess::Running && restart_id >= 0) {
|
} else if (state == QProcess::Running && restart_id >= 0) {
|
||||||
// Restart profile
|
// Restart profile
|
||||||
setTimeout([=] {
|
setTimeout(
|
||||||
|
[=] {
|
||||||
MW_dialog_message("ExternalProcess", "CoreRestarted," + Int2String(restart_id));
|
MW_dialog_message("ExternalProcess", "CoreRestarted," + Int2String(restart_id));
|
||||||
restart_id = -1;
|
restart_id = -1;
|
||||||
}, this, 1000);
|
},
|
||||||
|
this, 1000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -122,4 +126,4 @@ namespace NekoRay::sys {
|
|||||||
write((dataStore->core_token + "\n").toUtf8());
|
write((dataStore->core_token + "\n").toUtf8());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace NekoRay::sys
|
||||||
|
|||||||
@@ -43,4 +43,4 @@ namespace NekoRay::sys {
|
|||||||
|
|
||||||
// start & kill change this list
|
// start & kill change this list
|
||||||
inline QList<ExternalProcess *> running_ext;
|
inline QList<ExternalProcess *> running_ext;
|
||||||
}
|
} // namespace NekoRay::sys
|
||||||
|
|||||||
@@ -9,14 +9,14 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
typedef BOOL( WINAPI *MINIDUMPWRITEDUMP )(
|
typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)(
|
||||||
HANDLE hProcess,
|
HANDLE hProcess,
|
||||||
DWORD dwPid,
|
DWORD dwPid,
|
||||||
HANDLE hFile,
|
HANDLE hFile,
|
||||||
MINIDUMP_TYPE DumpType,
|
MINIDUMP_TYPE DumpType,
|
||||||
CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
||||||
CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
|
CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
|
||||||
CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
|
CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
|
||||||
|
|
||||||
LONG CreateCrashHandler(EXCEPTION_POINTERS *pException) {
|
LONG CreateCrashHandler(EXCEPTION_POINTERS *pException) {
|
||||||
QDir::setCurrent(QApplication::applicationDirPath());
|
QDir::setCurrent(QApplication::applicationDirPath());
|
||||||
@@ -30,7 +30,7 @@ LONG CreateCrashHandler(EXCEPTION_POINTERS *pException) {
|
|||||||
//创建 Dump 文件
|
//创建 Dump 文件
|
||||||
QDateTime CurDTime = QDateTime::currentDateTime();
|
QDateTime CurDTime = QDateTime::currentDateTime();
|
||||||
QString current_date = CurDTime.toString("yyyy_MM_dd_hh_mm_ss");
|
QString current_date = CurDTime.toString("yyyy_MM_dd_hh_mm_ss");
|
||||||
//dmp文件的命名
|
// dmp文件的命名
|
||||||
QString dumpText = "Dump_" + current_date + ".dmp";
|
QString dumpText = "Dump_" + current_date + ".dmp";
|
||||||
EXCEPTION_RECORD *record = pException->ExceptionRecord;
|
EXCEPTION_RECORD *record = pException->ExceptionRecord;
|
||||||
QString errCode(QString::number(record->ExceptionCode, 16));
|
QString errCode(QString::number(record->ExceptionCode, 16));
|
||||||
@@ -54,12 +54,16 @@ LONG CreateCrashHandler(EXCEPTION_POINTERS *pException) {
|
|||||||
//创建消息提示
|
//创建消息提示
|
||||||
QMessageBox::warning(NULL, "Application crashed",
|
QMessageBox::warning(NULL, "Application crashed",
|
||||||
QString("ErrorCode: %1 ErrorAddr:%2 ErrorFlag: %3 ErrorPara: %4\nVersion: %5\nDump file at %6")
|
QString("ErrorCode: %1 ErrorAddr:%2 ErrorFlag: %3 ErrorPara: %4\nVersion: %5\nDump file at %6")
|
||||||
.arg(errCode).arg(errAddr).arg(errFlag).arg(errPara)
|
.arg(errCode)
|
||||||
.arg(NKR_VERSION).arg(dumpText),
|
.arg(errAddr)
|
||||||
|
.arg(errFlag)
|
||||||
|
.arg(errPara)
|
||||||
|
.arg(NKR_VERSION)
|
||||||
|
.arg(dumpText),
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
return EXCEPTION_EXECUTE_HANDLER;
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Windows_SetCrashHandler() {
|
void Windows_SetCrashHandler() {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
|
|
||||||
void Windows_SetCrashHandler(){}
|
void Windows_SetCrashHandler() {}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|||||||
@@ -19,4 +19,4 @@ namespace NekoRay {
|
|||||||
bool descending = false; //默认升序,开这个就是降序
|
bool descending = false; //默认升序,开这个就是降序
|
||||||
bool scroll_to_started = false;
|
bool scroll_to_started = false;
|
||||||
};
|
};
|
||||||
}
|
} // namespace NekoRay
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ namespace TrayIcon {
|
|||||||
|
|
||||||
QIcon GetIcon(TrayIconStatus status);
|
QIcon GetIcon(TrayIconStatus status);
|
||||||
|
|
||||||
}
|
} // namespace TrayIcon
|
||||||
|
|||||||
@@ -85,10 +85,8 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
|
|||||||
auto str = QInputDialog::getItem(this, ui->sys_proxy_format->text() + " (Windows)",
|
auto str = QInputDialog::getItem(this, ui->sys_proxy_format->text() + " (Windows)",
|
||||||
tr("Advanced system proxy settings. Please select a format."),
|
tr("Advanced system proxy settings. Please select a format."),
|
||||||
Preset::Windows::system_proxy_format,
|
Preset::Windows::system_proxy_format,
|
||||||
Preset::Windows::system_proxy_format.indexOf(
|
Preset::Windows::system_proxy_format.indexOf(NekoRay::dataStore->system_proxy_format),
|
||||||
NekoRay::dataStore->system_proxy_format),
|
false, &ok);
|
||||||
false, &ok
|
|
||||||
);
|
|
||||||
if (ok) NekoRay::dataStore->system_proxy_format = str;
|
if (ok) NekoRay::dataStore->system_proxy_format = str;
|
||||||
});
|
});
|
||||||
#else
|
#else
|
||||||
@@ -174,7 +172,8 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
|
|||||||
bool ok;
|
bool ok;
|
||||||
auto s = QInputDialog::getText(nullptr, tr("Add"),
|
auto s = QInputDialog::getText(nullptr, tr("Add"),
|
||||||
tr("Please input the core name."),
|
tr("Please input the core name."),
|
||||||
QLineEdit::Normal, "", &ok).trimmed();
|
QLineEdit::Normal, "", &ok)
|
||||||
|
.trimmed();
|
||||||
if (s.isEmpty() || !ok) return;
|
if (s.isEmpty() || !ok) return;
|
||||||
if (CACHE.extraCore.contains(s)) return;
|
if (CACHE.extraCore.contains(s)) return;
|
||||||
extra_core_layout->addWidget(new ExtraCoreWidget(&CACHE.extraCore, s));
|
extra_core_layout->addWidget(new ExtraCoreWidget(&CACHE.extraCore, s));
|
||||||
@@ -212,8 +211,7 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
|
|||||||
QString core_name_new = dynamic_cast<QRadioButton *>(sender())->text();
|
QString core_name_new = dynamic_cast<QRadioButton *>(sender())->text();
|
||||||
if (QMessageBox::question(this, tr("Confirmation"),
|
if (QMessageBox::question(this, tr("Confirmation"),
|
||||||
tr("Switching the core to %1, click \"Yes\" to complete the switch and the program will restart. This feature may be unstable, please do not switch frequently.")
|
tr("Switching the core to %1, click \"Yes\" to complete the switch and the program will restart. This feature may be unstable, please do not switch frequently.")
|
||||||
.arg(core_name_new)
|
.arg(core_name_new)) == QMessageBox::StandardButton::Yes) {
|
||||||
) == QMessageBox::StandardButton::Yes) {
|
|
||||||
QFile file;
|
QFile file;
|
||||||
file.setFileName("groups/coreType");
|
file.setFileName("groups/coreType");
|
||||||
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
|
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DialogBasicSettings : public QDialog {
|
class DialogBasicSettings : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DialogBasicSettings(QWidget *parent = nullptr);
|
explicit DialogBasicSettings(QWidget *parent = nullptr);
|
||||||
@@ -32,7 +32,6 @@ private:
|
|||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void on_set_custom_icon_clicked();
|
void on_set_custom_icon_clicked();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DIALOG_BASIC_SETTINGS_H
|
#endif // DIALOG_BASIC_SETTINGS_H
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
|
|
||||||
#include "ui/mainwindow_interface.h"
|
#include "ui/mainwindow_interface.h"
|
||||||
|
|
||||||
DialogHotkey::DialogHotkey(QWidget *parent) :
|
DialogHotkey::DialogHotkey(QWidget *parent) : QDialog(parent), ui(new Ui::DialogHotkey) {
|
||||||
QDialog(parent), ui(new Ui::DialogHotkey) {
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->show_mainwindow->setKeySequence(NekoRay::dataStore->hotkey_mainwindow);
|
ui->show_mainwindow->setKeySequence(NekoRay::dataStore->hotkey_mainwindow);
|
||||||
ui->show_groups->setKeySequence(NekoRay::dataStore->hotkey_group);
|
ui->show_groups->setKeySequence(NekoRay::dataStore->hotkey_group);
|
||||||
|
|||||||
@@ -4,11 +4,13 @@
|
|||||||
#include "main/NekoRay.hpp"
|
#include "main/NekoRay.hpp"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class DialogHotkey; }
|
namespace Ui {
|
||||||
|
class DialogHotkey;
|
||||||
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class DialogHotkey : public QDialog {
|
class DialogHotkey : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DialogHotkey(QWidget *parent = nullptr);
|
explicit DialogHotkey(QWidget *parent = nullptr);
|
||||||
|
|||||||
@@ -12,17 +12,16 @@
|
|||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
#define AddGroupToListIfExist(_id) \
|
#define AddGroupToListIfExist(_id) \
|
||||||
auto __ent = NekoRay::profileManager->GetGroup(_id); \
|
auto __ent = NekoRay::profileManager->GetGroup(_id); \
|
||||||
if (__ent != nullptr) { \
|
if (__ent != nullptr) { \
|
||||||
auto wI = new QListWidgetItem(); \
|
auto wI = new QListWidgetItem(); \
|
||||||
auto w = new GroupItem(this, __ent, wI); \
|
auto w = new GroupItem(this, __ent, wI); \
|
||||||
wI->setData(114514, _id); \
|
wI->setData(114514, _id); \
|
||||||
ui->listWidget->addItem(wI); \
|
ui->listWidget->addItem(wI); \
|
||||||
ui->listWidget->setItemWidget(wI, w); \
|
ui->listWidget->setItemWidget(wI, w); \
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogManageGroups::DialogManageGroups(QWidget *parent) :
|
DialogManageGroups::DialogManageGroups(QWidget *parent) : QDialog(parent), ui(new Ui::DialogManageGroups) {
|
||||||
QDialog(parent), ui(new Ui::DialogManageGroups) {
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
for (auto id: NekoRay::profileManager->_groups) {
|
for (auto id: NekoRay::profileManager->_groups) {
|
||||||
@@ -47,14 +46,13 @@ void DialogManageGroups::on_add_clicked() {
|
|||||||
|
|
||||||
if (ret == QDialog::Accepted) {
|
if (ret == QDialog::Accepted) {
|
||||||
NekoRay::profileManager->AddGroup(ent);
|
NekoRay::profileManager->AddGroup(ent);
|
||||||
AddGroupToListIfExist(ent->id)
|
AddGroupToListIfExist(ent->id);
|
||||||
MW_dialog_message(Dialog_DialogManageGroups, "refresh-1");
|
MW_dialog_message(Dialog_DialogManageGroups, "refresh-1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogManageGroups::on_update_all_clicked() {
|
void DialogManageGroups::on_update_all_clicked() {
|
||||||
if (QMessageBox::question(this, tr("Confirmation"), tr("Update all subscriptions?"))
|
if (QMessageBox::question(this, tr("Confirmation"), tr("Update all subscriptions?")) == QMessageBox::StandardButton::Yes) {
|
||||||
== QMessageBox::StandardButton::Yes) {
|
|
||||||
for (const auto &gid: NekoRay::profileManager->_groups) {
|
for (const auto &gid: NekoRay::profileManager->_groups) {
|
||||||
auto group = NekoRay::profileManager->GetGroup(gid);
|
auto group = NekoRay::profileManager->GetGroup(gid);
|
||||||
if (group == nullptr || group->url.isEmpty()) continue;
|
if (group == nullptr || group->url.isEmpty()) continue;
|
||||||
|
|||||||
@@ -8,11 +8,13 @@
|
|||||||
#include "db/Group.hpp"
|
#include "db/Group.hpp"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class DialogManageGroups; }
|
namespace Ui {
|
||||||
|
class DialogManageGroups;
|
||||||
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class DialogManageGroups : public QDialog {
|
class DialogManageGroups : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DialogManageGroups(QWidget *parent = nullptr);
|
explicit DialogManageGroups(QWidget *parent = nullptr);
|
||||||
|
|||||||
@@ -10,22 +10,21 @@
|
|||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
|
|
||||||
#define REFRESH_ACTIVE_ROUTING(a, r) \
|
#define REFRESH_ACTIVE_ROUTING(a, r) \
|
||||||
active_routing = a; \
|
active_routing = a; \
|
||||||
ui->active_routing->setText("[" + active_routing + "]"); \
|
ui->active_routing->setText("[" + active_routing + "]"); \
|
||||||
setWindowTitle(title_base + " [" + a + "]"); \
|
setWindowTitle(title_base + " [" + a + "]"); \
|
||||||
SetRouteConfig(*r);
|
SetRouteConfig(*r);
|
||||||
|
|
||||||
#define SAVE_TO_ROUTING(r) \
|
#define SAVE_TO_ROUTING(r) \
|
||||||
r->direct_ip = directIPTxt->toPlainText(); \
|
r->direct_ip = directIPTxt->toPlainText(); \
|
||||||
r->direct_domain = directDomainTxt->toPlainText(); \
|
r->direct_domain = directDomainTxt->toPlainText(); \
|
||||||
r->proxy_ip = proxyIPTxt->toPlainText(); \
|
r->proxy_ip = proxyIPTxt->toPlainText(); \
|
||||||
r->proxy_domain = proxyDomainTxt->toPlainText(); \
|
r->proxy_domain = proxyDomainTxt->toPlainText(); \
|
||||||
r->block_ip = blockIPTxt->toPlainText(); \
|
r->block_ip = blockIPTxt->toPlainText(); \
|
||||||
r->block_domain = blockDomainTxt->toPlainText(); \
|
r->block_domain = blockDomainTxt->toPlainText(); \
|
||||||
r->custom = CACHE.custom_route;
|
r->custom = CACHE.custom_route;
|
||||||
|
|
||||||
DialogManageRoutes::DialogManageRoutes(QWidget *parent) :
|
DialogManageRoutes::DialogManageRoutes(QWidget *parent) : QDialog(parent), ui(new Ui::DialogManageRoutes) {
|
||||||
QDialog(parent), ui(new Ui::DialogManageRoutes) {
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
title_base = windowTitle();
|
title_base = windowTitle();
|
||||||
|
|
||||||
@@ -171,9 +170,7 @@ void DialogManageRoutes::on_load_save_clicked() {
|
|||||||
r->load_control_force = true;
|
r->load_control_force = true;
|
||||||
r->fn = ROUTES_PREFIX + fn;
|
r->fn = ROUTES_PREFIX + fn;
|
||||||
if (r->Load()) {
|
if (r->Load()) {
|
||||||
auto btn = QMessageBox::question(nullptr,
|
if (QMessageBox::question(nullptr, software_name, tr("Load routing: %1").arg(fn) + "\n" + r->toString()) == QMessageBox::Yes) {
|
||||||
software_name, tr("Load routing: %1").arg(fn) + "\n" + r->toString());
|
|
||||||
if (btn == QMessageBox::Yes) {
|
|
||||||
REFRESH_ACTIVE_ROUTING(fn, r)
|
REFRESH_ACTIVE_ROUTING(fn, r)
|
||||||
w->accept();
|
w->accept();
|
||||||
}
|
}
|
||||||
@@ -186,9 +183,7 @@ void DialogManageRoutes::on_load_save_clicked() {
|
|||||||
auto r = std::make_unique<NekoRay::Routing>();
|
auto r = std::make_unique<NekoRay::Routing>();
|
||||||
SAVE_TO_ROUTING(r)
|
SAVE_TO_ROUTING(r)
|
||||||
r->fn = ROUTES_PREFIX + fn;
|
r->fn = ROUTES_PREFIX + fn;
|
||||||
auto btn = QMessageBox::question(nullptr, software_name,
|
if (QMessageBox::question(nullptr, software_name, tr("Save routing: %1").arg(fn) + "\n" + r->toString()) == QMessageBox::Yes) {
|
||||||
tr("Save routing: %1").arg(fn) + "\n" + r->toString());
|
|
||||||
if (btn == QMessageBox::Yes) {
|
|
||||||
r->Save();
|
r->Save();
|
||||||
REFRESH_ACTIVE_ROUTING(fn, r)
|
REFRESH_ACTIVE_ROUTING(fn, r)
|
||||||
w->accept();
|
w->accept();
|
||||||
@@ -198,8 +193,7 @@ void DialogManageRoutes::on_load_save_clicked() {
|
|||||||
connect(remove, &QPushButton::clicked, w, [=] {
|
connect(remove, &QPushButton::clicked, w, [=] {
|
||||||
auto fn = lineEdit->text();
|
auto fn = lineEdit->text();
|
||||||
if (!fn.isEmpty() && NekoRay::Routing::List().length() > 1) {
|
if (!fn.isEmpty() && NekoRay::Routing::List().length() > 1) {
|
||||||
auto btn = QMessageBox::question(nullptr, software_name, tr("Remove routing: %1").arg(fn));
|
if (QMessageBox::question(nullptr, software_name, tr("Remove routing: %1").arg(fn)) == QMessageBox::Yes) {
|
||||||
if (btn == QMessageBox::Yes) {
|
|
||||||
QFile f(ROUTES_PREFIX + fn);
|
QFile f(ROUTES_PREFIX + fn);
|
||||||
f.remove();
|
f.remove();
|
||||||
if (NekoRay::dataStore->active_routing == fn) {
|
if (NekoRay::dataStore->active_routing == fn) {
|
||||||
|
|||||||
@@ -7,11 +7,13 @@
|
|||||||
#include "main/NekoRay.hpp"
|
#include "main/NekoRay.hpp"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class DialogManageRoutes; }
|
namespace Ui {
|
||||||
|
class DialogManageRoutes;
|
||||||
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class DialogManageRoutes : public QDialog {
|
class DialogManageRoutes : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DialogManageRoutes(QWidget *parent = nullptr);
|
explicit DialogManageRoutes(QWidget *parent = nullptr);
|
||||||
@@ -53,5 +55,3 @@ public slots:
|
|||||||
|
|
||||||
void on_load_save_clicked();
|
void on_load_save_clicked();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,7 @@
|
|||||||
#include "main/GuiUtils.hpp"
|
#include "main/GuiUtils.hpp"
|
||||||
#include "main/NekoRay.hpp"
|
#include "main/NekoRay.hpp"
|
||||||
|
|
||||||
DialogVPNSettings::DialogVPNSettings(QWidget *parent) :
|
DialogVPNSettings::DialogVPNSettings(QWidget *parent) : QDialog(parent), ui(new Ui::DialogVPNSettings) {
|
||||||
QDialog(parent), ui(new Ui::DialogVPNSettings) {
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
ui->fake_dns->setVisible(!IS_NEKO_BOX);
|
ui->fake_dns->setVisible(!IS_NEKO_BOX);
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class DialogVPNSettings; }
|
namespace Ui {
|
||||||
|
class DialogVPNSettings;
|
||||||
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class DialogVPNSettings : public QDialog {
|
class DialogVPNSettings : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DialogVPNSettings(QWidget *parent = nullptr);
|
explicit DialogVPNSettings(QWidget *parent = nullptr);
|
||||||
@@ -22,8 +23,6 @@ private:
|
|||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void accept() override;
|
void accept() override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // NEKORAY_DIALOG_VPN_SETTINGS_H
|
||||||
#endif //NEKORAY_DIALOG_VPN_SETTINGS_H
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
|
|
||||||
DialogEditGroup::DialogEditGroup(const QSharedPointer<NekoRay::Group> &ent, QWidget *parent) :
|
DialogEditGroup::DialogEditGroup(const QSharedPointer<NekoRay::Group> &ent, QWidget *parent)
|
||||||
QDialog(parent), ui(new Ui::DialogEditGroup) {
|
: QDialog(parent), ui(new Ui::DialogEditGroup) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
connect(ui->type, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=](int index) {
|
connect(ui->type, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=](int index) {
|
||||||
|
|||||||
@@ -4,11 +4,13 @@
|
|||||||
#include "db/Group.hpp"
|
#include "db/Group.hpp"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class DialogEditGroup; }
|
namespace Ui {
|
||||||
|
class DialogEditGroup;
|
||||||
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class DialogEditGroup : public QDialog {
|
class DialogEditGroup : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DialogEditGroup(const QSharedPointer<NekoRay::Group> &ent, QWidget *parent = nullptr);
|
explicit DialogEditGroup(const QSharedPointer<NekoRay::Group> &ent, QWidget *parent = nullptr);
|
||||||
@@ -18,5 +20,3 @@ public:
|
|||||||
private:
|
private:
|
||||||
Ui::DialogEditGroup *ui;
|
Ui::DialogEditGroup *ui;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,7 @@
|
|||||||
#define LOAD_TYPE(a) ui->type->addItem(NekoRay::ProfileManager::NewProxyEntity(a)->bean->DisplayType(), a);
|
#define LOAD_TYPE(a) ui->type->addItem(NekoRay::ProfileManager::NewProxyEntity(a)->bean->DisplayType(), a);
|
||||||
|
|
||||||
DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId, QWidget *parent)
|
DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId, QWidget *parent)
|
||||||
: QDialog(parent),
|
: QDialog(parent), ui(new Ui::DialogEditProfile) {
|
||||||
ui(new Ui::DialogEditProfile) {
|
|
||||||
// setup UI
|
// setup UI
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->dialog_layout->setAlignment(ui->left, Qt::AlignTop);
|
ui->dialog_layout->setAlignment(ui->left, Qt::AlignTop);
|
||||||
@@ -244,7 +243,7 @@ void DialogEditProfile::typeSelected(const QString &newType) {
|
|||||||
ui->name->setText(ent->bean->name);
|
ui->name->setText(ent->bean->name);
|
||||||
ui->address->setText(ent->bean->serverAddress);
|
ui->address->setText(ent->bean->serverAddress);
|
||||||
ui->port->setText(Int2String(ent->bean->serverPort));
|
ui->port->setText(Int2String(ent->bean->serverPort));
|
||||||
ui->port->setValidator(QRegExpValidator_Number, this));
|
ui->port->setValidator(QRegExpValidator_Number);
|
||||||
|
|
||||||
// 星号
|
// 星号
|
||||||
for (auto label: findChildren<QLabel *>()) {
|
for (auto label: findChildren<QLabel *>()) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace Ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DialogEditProfile : public QDialog {
|
class DialogEditProfile : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DialogEditProfile(const QString &_type, int profileOrGroupId, QWidget *parent = nullptr);
|
explicit DialogEditProfile(const QString &_type, int profileOrGroupId, QWidget *parent = nullptr);
|
||||||
|
|||||||
@@ -4,11 +4,13 @@
|
|||||||
#include "profile_editor.h"
|
#include "profile_editor.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class EditChain; }
|
namespace Ui {
|
||||||
|
class EditChain;
|
||||||
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class EditChain : public QWidget, public ProfileEditor {
|
class EditChain : public QWidget, public ProfileEditor {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit EditChain(QWidget *parent = nullptr);
|
explicit EditChain(QWidget *parent = nullptr);
|
||||||
|
|||||||
@@ -5,16 +5,15 @@
|
|||||||
#include "fmt/CustomBean.hpp"
|
#include "fmt/CustomBean.hpp"
|
||||||
#include "fmt/Preset.hpp"
|
#include "fmt/Preset.hpp"
|
||||||
|
|
||||||
EditCustom::EditCustom(QWidget *parent) :
|
EditCustom::EditCustom(QWidget *parent) : QWidget(parent), ui(new Ui::EditCustom) {
|
||||||
QWidget(parent), ui(new Ui::EditCustom) {
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->config_simple->setPlaceholderText("example:\n"
|
ui->config_simple->setPlaceholderText(
|
||||||
|
"example:\n"
|
||||||
" server-address: \"127.0.0.1:%mapping_port%\"\n"
|
" server-address: \"127.0.0.1:%mapping_port%\"\n"
|
||||||
" listen-address: \"127.0.0.1\"\n"
|
" listen-address: \"127.0.0.1\"\n"
|
||||||
" listen-port: %socks_port%\n"
|
" listen-port: %socks_port%\n"
|
||||||
" host: your-domain.com\n"
|
" host: your-domain.com\n"
|
||||||
" sni: your-domain.com\n"
|
" sni: your-domain.com\n");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EditCustom::~EditCustom() {
|
EditCustom::~EditCustom() {
|
||||||
@@ -36,11 +35,11 @@ void EditCustom::onStart(QSharedPointer<NekoRay::ProxyEntity> _ent) {
|
|||||||
preset_config = Preset::Hysteria::config;
|
preset_config = Preset::Hysteria::config;
|
||||||
ui->config_simple->setPlaceholderText("");
|
ui->config_simple->setPlaceholderText("");
|
||||||
ui->core->hide();
|
ui->core->hide();
|
||||||
ui->core_l->setText(
|
ui->core_l->setText(tr("Please read the documentation. If you don't understand, use a share link instead."));
|
||||||
tr("Please read the documentation. If you don't understand, use a share link instead."));
|
|
||||||
} else if (preset_core == "internal") {
|
} else if (preset_core == "internal") {
|
||||||
preset_command = preset_config = "";
|
preset_command = preset_config = "";
|
||||||
ui->config_simple->setPlaceholderText("{\n"
|
ui->config_simple->setPlaceholderText(
|
||||||
|
"{\n"
|
||||||
" \"type\": \"socks\",\n"
|
" \"type\": \"socks\",\n"
|
||||||
" // ...\n"
|
" // ...\n"
|
||||||
"}");
|
"}");
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include "profile_editor.h"
|
#include "profile_editor.h"
|
||||||
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class EditCustom; }
|
namespace Ui {
|
||||||
|
class EditCustom;
|
||||||
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class EditCustom : public QWidget, public ProfileEditor {
|
class EditCustom : public QWidget, public ProfileEditor {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QString preset_core;
|
QString preset_core;
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
|
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
|
||||||
EditNaive::EditNaive(QWidget *parent) :
|
EditNaive::EditNaive(QWidget *parent) : QWidget(parent), ui(new Ui::EditNaive) {
|
||||||
QWidget(parent), ui(new Ui::EditNaive) {
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include "profile_editor.h"
|
#include "profile_editor.h"
|
||||||
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class EditNaive; }
|
namespace Ui {
|
||||||
|
class EditNaive;
|
||||||
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class EditNaive : public QWidget, public ProfileEditor {
|
class EditNaive : public QWidget, public ProfileEditor {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit EditNaive(QWidget *parent = nullptr);
|
explicit EditNaive(QWidget *parent = nullptr);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class EditShadowSocks : public QWidget, public ProfileEditor {
|
class EditShadowSocks : public QWidget, public ProfileEditor {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit EditShadowSocks(QWidget *parent = nullptr);
|
explicit EditShadowSocks(QWidget *parent = nullptr);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class EditSocksHttp : public QWidget, public ProfileEditor {
|
class EditSocksHttp : public QWidget, public ProfileEditor {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit EditSocksHttp(QWidget *parent = nullptr);
|
explicit EditSocksHttp(QWidget *parent = nullptr);
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
|
|
||||||
#include "fmt/TrojanVLESSBean.hpp"
|
#include "fmt/TrojanVLESSBean.hpp"
|
||||||
|
|
||||||
EditTrojanVLESS::EditTrojanVLESS(QWidget *parent) :
|
EditTrojanVLESS::EditTrojanVLESS(QWidget *parent) : QWidget(parent), ui(new Ui::EditTrojanVLESS) {
|
||||||
QWidget(parent), ui(new Ui::EditTrojanVLESS) {
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include "profile_editor.h"
|
#include "profile_editor.h"
|
||||||
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class EditTrojanVLESS; }
|
namespace Ui {
|
||||||
|
class EditTrojanVLESS;
|
||||||
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class EditTrojanVLESS : public QWidget, public ProfileEditor {
|
class EditTrojanVLESS : public QWidget, public ProfileEditor {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit EditTrojanVLESS(QWidget *parent = nullptr);
|
explicit EditTrojanVLESS(QWidget *parent = nullptr);
|
||||||
@@ -24,5 +25,3 @@ private:
|
|||||||
Ui::EditTrojanVLESS *ui;
|
Ui::EditTrojanVLESS *ui;
|
||||||
QSharedPointer<NekoRay::ProxyEntity> ent;
|
QSharedPointer<NekoRay::ProxyEntity> ent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
|
|
||||||
#include "fmt/VMessBean.hpp"
|
#include "fmt/VMessBean.hpp"
|
||||||
|
|
||||||
EditVMess::EditVMess(QWidget *parent) :
|
EditVMess::EditVMess(QWidget *parent) : QWidget(parent), ui(new Ui::EditVMess) {
|
||||||
QWidget(parent), ui(new Ui::EditVMess) {
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include "profile_editor.h"
|
#include "profile_editor.h"
|
||||||
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class EditVMess; }
|
namespace Ui {
|
||||||
|
class EditVMess;
|
||||||
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class EditVMess : public QWidget, public ProfileEditor {
|
class EditVMess : public QWidget, public ProfileEditor {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit EditVMess(QWidget *parent = nullptr);
|
explicit EditVMess(QWidget *parent = nullptr);
|
||||||
@@ -24,5 +25,3 @@ private:
|
|||||||
Ui::EditVMess *ui;
|
Ui::EditVMess *ui;
|
||||||
QSharedPointer<NekoRay::ProxyEntity> ent;
|
QSharedPointer<NekoRay::ProxyEntity> ent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -55,13 +55,10 @@ void UI_InitMainWindow() {
|
|||||||
mainwindow = new MainWindow;
|
mainwindow = new MainWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
|
||||||
: QMainWindow(parent), ui(new Ui::MainWindow) {
|
|
||||||
mainwindow = this;
|
mainwindow = this;
|
||||||
MW_dialog_message = [=](const QString &a, const QString &b) {
|
MW_dialog_message = [=](const QString &a, const QString &b) {
|
||||||
runOnUiThread([=] {
|
runOnUiThread([=] { dialog_message_impl(a, b); });
|
||||||
dialog_message_impl(a, b);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Load Manager
|
// Load Manager
|
||||||
@@ -111,10 +108,8 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
ui->toolButton_preferences->setMenu(ui->menu_preferences);
|
ui->toolButton_preferences->setMenu(ui->menu_preferences);
|
||||||
ui->toolButton_server->setMenu(ui->menu_server);
|
ui->toolButton_server->setMenu(ui->menu_server);
|
||||||
ui->menubar->setVisible(false);
|
ui->menubar->setVisible(false);
|
||||||
connect(ui->toolButton_document, &QToolButton::clicked, this,
|
connect(ui->toolButton_document, &QToolButton::clicked, this, [=] { QDesktopServices::openUrl(QUrl("https://matsuridayo.github.io/")); });
|
||||||
[=] { QDesktopServices::openUrl(QUrl("https://matsuridayo.github.io/")); });
|
connect(ui->toolButton_ads, &QToolButton::clicked, this, [=] { QDesktopServices::openUrl(QUrl("https://matsuricom.github.io/")); });
|
||||||
connect(ui->toolButton_ads, &QToolButton::clicked, this,
|
|
||||||
[=] { QDesktopServices::openUrl(QUrl("https://matsuricom.github.io/")); });
|
|
||||||
connect(ui->toolButton_update, &QToolButton::clicked, this, [=] { runOnNewThread([=] { CheckUpdate(); }); });
|
connect(ui->toolButton_update, &QToolButton::clicked, this, [=] { runOnNewThread([=] { CheckUpdate(); }); });
|
||||||
|
|
||||||
// Setup log UI
|
// Setup log UI
|
||||||
@@ -142,19 +137,13 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
bar->setValue(bar->maximum());
|
bar->setValue(bar->maximum());
|
||||||
});
|
});
|
||||||
MW_show_log = [=](const QString &log) {
|
MW_show_log = [=](const QString &log) {
|
||||||
runOnUiThread([=] {
|
runOnUiThread([=] { show_log_impl(log); });
|
||||||
show_log_impl(log);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
MW_show_log_ext = [=](const QString &tag, const QString &log) {
|
MW_show_log_ext = [=](const QString &tag, const QString &log) {
|
||||||
runOnUiThread([=] {
|
runOnUiThread([=] { show_log_impl("[" + tag + "] " + log); });
|
||||||
show_log_impl("[" + tag + "] " + log);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
MW_show_log_ext_vt100 = [=](const QString &log) {
|
MW_show_log_ext_vt100 = [=](const QString &log) {
|
||||||
runOnUiThread([=] {
|
runOnUiThread([=] { show_log_impl(cleanVT100String(log)); });
|
||||||
show_log_impl(cleanVT100String(log));
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// table UI
|
// table UI
|
||||||
@@ -163,8 +152,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
group->order = ui->proxyListTable->order;
|
group->order = ui->proxyListTable->order;
|
||||||
group->Save();
|
group->Save();
|
||||||
};
|
};
|
||||||
connect(ui->proxyListTable->horizontalHeader(), &QHeaderView::sectionClicked, this,
|
connect(ui->proxyListTable->horizontalHeader(), &QHeaderView::sectionClicked, this, [=](int logicalIndex) {
|
||||||
[=](int logicalIndex) {
|
|
||||||
NekoRay::GroupSortAction action;
|
NekoRay::GroupSortAction action;
|
||||||
// 不正确的descending实现
|
// 不正确的descending实现
|
||||||
if (proxy_last_order == logicalIndex) {
|
if (proxy_last_order == logicalIndex) {
|
||||||
@@ -238,12 +226,11 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
this->refresh_groups();
|
this->refresh_groups();
|
||||||
|
|
||||||
// Setup Tray
|
// Setup Tray
|
||||||
tray = new QSystemTrayIcon(this);//初始化托盘对象tray
|
tray = new QSystemTrayIcon(this); //初始化托盘对象tray
|
||||||
tray->setIcon(TrayIcon::GetIcon(TrayIcon::NONE));
|
tray->setIcon(TrayIcon::GetIcon(TrayIcon::NONE));
|
||||||
tray->setContextMenu(ui->menu_program);//创建托盘菜单
|
tray->setContextMenu(ui->menu_program); //创建托盘菜单
|
||||||
tray->show();//让托盘图标显示在系统托盘上
|
tray->show(); //让托盘图标显示在系统托盘上
|
||||||
connect(tray, &QSystemTrayIcon::activated, this,
|
connect(tray, &QSystemTrayIcon::activated, this, [=](QSystemTrayIcon::ActivationReason reason) {
|
||||||
[=](QSystemTrayIcon::ActivationReason reason) {
|
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case QSystemTrayIcon::Trigger:
|
case QSystemTrayIcon::Trigger:
|
||||||
if (this->isVisible()) {
|
if (this->isVisible()) {
|
||||||
@@ -310,9 +297,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
r.load_control_force = true;
|
r.load_control_force = true;
|
||||||
r.fn = ROUTES_PREFIX + fn;
|
r.fn = ROUTES_PREFIX + fn;
|
||||||
if (r.Load()) {
|
if (r.Load()) {
|
||||||
auto btn = QMessageBox::question(GetMessageBoxParent(), software_name,
|
if (QMessageBox::question(GetMessageBoxParent(), software_name, tr("Load routing and apply: %1").arg(fn) + "\n" + r.toString()) == QMessageBox::Yes) {
|
||||||
tr("Load routing and apply: %1").arg(fn) + "\n" + r.toString());
|
|
||||||
if (btn == QMessageBox::Yes) {
|
|
||||||
NekoRay::Routing::SetToActive(fn);
|
NekoRay::Routing::SetToActive(fn);
|
||||||
if (NekoRay::dataStore->started_id >= 0) {
|
if (NekoRay::dataStore->started_id >= 0) {
|
||||||
neko_start(NekoRay::dataStore->started_id);
|
neko_start(NekoRay::dataStore->started_id);
|
||||||
@@ -343,16 +328,12 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
});
|
});
|
||||||
connect(ui->menu_spmode, &QMenu::aboutToShow, this, [=]() {
|
connect(ui->menu_spmode, &QMenu::aboutToShow, this, [=]() {
|
||||||
ui->menu_spmode_disabled->setChecked(NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::DISABLE);
|
ui->menu_spmode_disabled->setChecked(NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::DISABLE);
|
||||||
ui->menu_spmode_system_proxy->setChecked(
|
ui->menu_spmode_system_proxy->setChecked(NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::SYSTEM_PROXY);
|
||||||
NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::SYSTEM_PROXY);
|
|
||||||
ui->menu_spmode_vpn->setChecked(NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::VPN);
|
ui->menu_spmode_vpn->setChecked(NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::VPN);
|
||||||
});
|
});
|
||||||
connect(ui->menu_spmode_system_proxy, &QAction::triggered, this,
|
connect(ui->menu_spmode_system_proxy, &QAction::triggered, this, [=]() { neko_set_spmode(NekoRay::SystemProxyMode::SYSTEM_PROXY); });
|
||||||
[=]() { neko_set_spmode(NekoRay::SystemProxyMode::SYSTEM_PROXY); });
|
connect(ui->menu_spmode_vpn, &QAction::triggered, this, [=]() { neko_set_spmode(NekoRay::SystemProxyMode::VPN); });
|
||||||
connect(ui->menu_spmode_vpn, &QAction::triggered, this,
|
connect(ui->menu_spmode_disabled, &QAction::triggered, this, [=]() { neko_set_spmode(NekoRay::SystemProxyMode::DISABLE); });
|
||||||
[=]() { neko_set_spmode(NekoRay::SystemProxyMode::VPN); });
|
|
||||||
connect(ui->menu_spmode_disabled, &QAction::triggered, this,
|
|
||||||
[=]() { neko_set_spmode(NekoRay::SystemProxyMode::DISABLE); });
|
|
||||||
connect(ui->menu_qr, &QAction::triggered, this, [=]() { display_qr_link(false); });
|
connect(ui->menu_qr, &QAction::triggered, this, [=]() { display_qr_link(false); });
|
||||||
connect(ui->menu_tcp_ping, &QAction::triggered, this, [=]() { speedtest_current_group(0); });
|
connect(ui->menu_tcp_ping, &QAction::triggered, this, [=]() { speedtest_current_group(0); });
|
||||||
connect(ui->menu_url_test, &QAction::triggered, this, [=]() { speedtest_current_group(1); });
|
connect(ui->menu_url_test, &QAction::triggered, this, [=]() { speedtest_current_group(1); });
|
||||||
@@ -471,8 +452,7 @@ void MainWindow::dialog_message_impl(const QString &sender, const QString &info)
|
|||||||
if (info.contains("VPNChanged") && NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::VPN) {
|
if (info.contains("VPNChanged") && NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::VPN) {
|
||||||
MessageBoxWarning(tr("VPN settings changed"), tr("Restart VPN to take effect."));
|
MessageBoxWarning(tr("VPN settings changed"), tr("Restart VPN to take effect."));
|
||||||
} else if (changed && NekoRay::dataStore->started_id >= 0 &&
|
} else if (changed && NekoRay::dataStore->started_id >= 0 &&
|
||||||
QMessageBox::question(GetMessageBoxParent(), tr("Confirmation"),
|
QMessageBox::question(GetMessageBoxParent(), tr("Confirmation"), tr("Settings changed, restart proxy?")) == QMessageBox::StandardButton::Yes) {
|
||||||
tr("Settings changed, restart proxy?")) == QMessageBox::StandardButton::Yes) {
|
|
||||||
neko_start(NekoRay::dataStore->started_id);
|
neko_start(NekoRay::dataStore->started_id);
|
||||||
}
|
}
|
||||||
refresh_status();
|
refresh_status();
|
||||||
@@ -509,12 +489,13 @@ void MainWindow::dialog_message_impl(const QString &sender, const QString &info)
|
|||||||
|
|
||||||
inline bool dialog_is_using = false;
|
inline bool dialog_is_using = false;
|
||||||
|
|
||||||
#define USE_DIALOG(a) if (dialog_is_using) return; \
|
#define USE_DIALOG(a) \
|
||||||
dialog_is_using = true; \
|
if (dialog_is_using) return; \
|
||||||
auto dialog = new a(this); \
|
dialog_is_using = true; \
|
||||||
dialog->exec(); \
|
auto dialog = new a(this); \
|
||||||
dialog->deleteLater(); \
|
dialog->exec(); \
|
||||||
dialog_is_using = false;
|
dialog->deleteLater(); \
|
||||||
|
dialog_is_using = false;
|
||||||
|
|
||||||
void MainWindow::on_menu_basic_settings_triggered() {
|
void MainWindow::on_menu_basic_settings_triggered() {
|
||||||
USE_DIALOG(DialogBasicSettings)
|
USE_DIALOG(DialogBasicSettings)
|
||||||
@@ -578,7 +559,9 @@ void MainWindow::on_menu_exit_triggered() {
|
|||||||
QCoreApplication::quit();
|
QCoreApplication::quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define neko_set_spmode_FAILED refresh_status(); return;
|
#define neko_set_spmode_FAILED \
|
||||||
|
refresh_status(); \
|
||||||
|
return;
|
||||||
|
|
||||||
void MainWindow::neko_set_spmode(int mode, bool save) {
|
void MainWindow::neko_set_spmode(int mode, bool save) {
|
||||||
if (mode != NekoRay::dataStore->running_spmode) {
|
if (mode != NekoRay::dataStore->running_spmode) {
|
||||||
@@ -908,10 +891,10 @@ void MainWindow::on_proxyListTable_itemDoubleClicked(QTableWidgetItem *item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define NO_ADD_TO_SUBSCRIPTION_GROUP \
|
#define NO_ADD_TO_SUBSCRIPTION_GROUP \
|
||||||
if (!NekoRay::profileManager->CurrentGroup()->url.isEmpty()) { \
|
if (!NekoRay::profileManager->CurrentGroup()->url.isEmpty()) { \
|
||||||
MessageBoxWarning(software_name, MainWindow::tr("Manual addition of profiles is not allowed in subscription groupings.")); \
|
MessageBoxWarning(software_name, MainWindow::tr("Manual addition of profiles is not allowed in subscription groupings.")); \
|
||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_menu_add_from_input_triggered() {
|
void MainWindow::on_menu_add_from_input_triggered() {
|
||||||
NO_ADD_TO_SUBSCRIPTION_GROUP
|
NO_ADD_TO_SUBSCRIPTION_GROUP
|
||||||
@@ -977,10 +960,7 @@ void MainWindow::on_menu_delete_triggered() {
|
|||||||
void MainWindow::on_menu_reset_traffic_triggered() {
|
void MainWindow::on_menu_reset_traffic_triggered() {
|
||||||
auto ents = get_now_selected();
|
auto ents = get_now_selected();
|
||||||
if (ents.count() == 0) return;
|
if (ents.count() == 0) return;
|
||||||
if (QMessageBox::question(this,
|
if (QMessageBox::question(this, tr("Confirmation"), QString(tr("Reset traffic of %1 item(s) ?")).arg(ents.count())) == QMessageBox::StandardButton::Yes) {
|
||||||
tr("Confirmation"),
|
|
||||||
QString(tr("Reset traffic of %1 item(s) ?")).arg(ents.count()))
|
|
||||||
== QMessageBox::StandardButton::Yes) {
|
|
||||||
for (const auto &ent: ents) {
|
for (const auto &ent: ents) {
|
||||||
ent->traffic_data->Reset();
|
ent->traffic_data->Reset();
|
||||||
ent->Save();
|
ent->Save();
|
||||||
@@ -994,9 +974,7 @@ void MainWindow::on_menu_profile_debug_info_triggered() {
|
|||||||
if (ents.count() != 1) return;
|
if (ents.count() != 1) return;
|
||||||
auto btn = QMessageBox::information(this, software_name, ents.first()->ToJsonBytes(), "OK", "Edit", "Reload", 0, 0);
|
auto btn = QMessageBox::information(this, software_name, ents.first()->ToJsonBytes(), "OK", "Edit", "Reload", 0, 0);
|
||||||
if (btn == 1) {
|
if (btn == 1) {
|
||||||
QDesktopServices::openUrl(QUrl::fromLocalFile(
|
QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(QString("profiles/%1.json").arg(ents.first()->id)).absoluteFilePath()));
|
||||||
QFileInfo(QString("profiles/%1.json").arg(ents.first()->id)).absoluteFilePath()
|
|
||||||
));
|
|
||||||
} else if (btn == 2) {
|
} else if (btn == 2) {
|
||||||
ents.first()->Load();
|
ents.first()->Load();
|
||||||
refresh_proxy_list();
|
refresh_proxy_list();
|
||||||
@@ -1194,11 +1172,7 @@ void MainWindow::on_menu_delete_repeat_triggered() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (out_del.length() > 0 &&
|
if (out_del.length() > 0 &&
|
||||||
QMessageBox::question(this,
|
QMessageBox::question(this, tr("Confirmation"), tr("Remove %1 item(s) ?").arg(out_del.length()) + "\n" + remove_display) == QMessageBox::StandardButton::Yes) {
|
||||||
tr("Confirmation"),
|
|
||||||
tr("Remove %1 item(s) ?").arg(out_del.length()) + "\n" + remove_display
|
|
||||||
) == QMessageBox::StandardButton::Yes) {
|
|
||||||
|
|
||||||
for (const auto &ent: out_del) {
|
for (const auto &ent: out_del) {
|
||||||
NekoRay::profileManager->DeleteProfile(ent->id);
|
NekoRay::profileManager->DeleteProfile(ent->id);
|
||||||
}
|
}
|
||||||
@@ -1229,11 +1203,7 @@ void MainWindow::on_menu_remove_unavailable_triggered() {
|
|||||||
remove_display += ent->bean->DisplayTypeAndName() + "\n";
|
remove_display += ent->bean->DisplayTypeAndName() + "\n";
|
||||||
}
|
}
|
||||||
if (out_del.length() > 0 &&
|
if (out_del.length() > 0 &&
|
||||||
QMessageBox::question(this,
|
QMessageBox::question(this, tr("Confirmation"), tr("Remove %1 item(s) ?").arg(out_del.length()) + "\n" + remove_display) == QMessageBox::StandardButton::Yes) {
|
||||||
tr("Confirmation"),
|
|
||||||
tr("Remove %1 item(s) ?").arg(out_del.length()) + "\n" + remove_display
|
|
||||||
) == QMessageBox::StandardButton::Yes) {
|
|
||||||
|
|
||||||
for (const auto &ent: out_del) {
|
for (const auto &ent: out_del) {
|
||||||
NekoRay::profileManager->DeleteProfile(ent->id);
|
NekoRay::profileManager->DeleteProfile(ent->id);
|
||||||
}
|
}
|
||||||
@@ -1244,8 +1214,7 @@ void MainWindow::on_menu_remove_unavailable_triggered() {
|
|||||||
void MainWindow::on_menu_resolve_domain_triggered() {
|
void MainWindow::on_menu_resolve_domain_triggered() {
|
||||||
if (QMessageBox::question(this,
|
if (QMessageBox::question(this,
|
||||||
tr("Confirmation"),
|
tr("Confirmation"),
|
||||||
tr("Resolving current group domain to IP, if support.")
|
tr("Resolving current group domain to IP, if support.")) != QMessageBox::StandardButton::Yes) {
|
||||||
) != QMessageBox::StandardButton::Yes) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mw_sub_updating) return;
|
if (mw_sub_updating) return;
|
||||||
@@ -1401,10 +1370,7 @@ void MainWindow::refresh_connection_list(const QJsonArray &arr) {
|
|||||||
} else {
|
} else {
|
||||||
f->setText(tr("Active"));
|
f->setText(tr("Active"));
|
||||||
}
|
}
|
||||||
f->setToolTip(tr("Start: %1\nEnd: %2").arg(
|
f->setToolTip(tr("Start: %1\nEnd: %2").arg(DisplayTime(start_t), end_t > 0 ? DisplayTime(end_t) : ""));
|
||||||
DisplayTime(start_t),
|
|
||||||
end_t > 0 ? DisplayTime(end_t) : ""
|
|
||||||
));
|
|
||||||
ui->tableWidget_conn->setItem(row, 0, f);
|
ui->tableWidget_conn->setItem(row, 0, f);
|
||||||
|
|
||||||
// C1: Outbound
|
// C1: Outbound
|
||||||
@@ -1425,7 +1391,6 @@ void MainWindow::refresh_connection_list(const QJsonArray &arr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Hotkey
|
// Hotkey
|
||||||
|
|
||||||
#ifndef NKR_NO_EXTERNAL
|
#ifndef NKR_NO_EXTERNAL
|
||||||
@@ -1498,16 +1463,13 @@ bool MainWindow::StartVPNProcess() {
|
|||||||
//
|
//
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
runOnNewThread([=] {
|
runOnNewThread([=] {
|
||||||
vpn_pid = 1; //TODO get pid?
|
vpn_pid = 1; // TODO get pid?
|
||||||
WinCommander::runProcessElevated(QApplication::applicationDirPath() + "/nekobox_core.exe",
|
WinCommander::runProcessElevated(QApplication::applicationDirPath() + "/nekobox_core.exe",
|
||||||
{"--disable-color", "run", "-c", configPath},
|
{"--disable-color", "run", "-c", configPath},
|
||||||
"",
|
"",
|
||||||
NekoRay::dataStore->vpn_hide_console
|
NekoRay::dataStore->vpn_hide_console); // blocking
|
||||||
); // blocking
|
|
||||||
vpn_pid = 0;
|
vpn_pid = 0;
|
||||||
runOnUiThread([=] {
|
runOnUiThread([=] { neko_set_spmode(NekoRay::SystemProxyMode::DISABLE); });
|
||||||
neko_set_spmode(NekoRay::SystemProxyMode::DISABLE);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
#else
|
#else
|
||||||
QFile::remove(protectPath);
|
QFile::remove(protectPath);
|
||||||
|
|||||||
@@ -20,7 +20,9 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace NekoRay::sys { class CoreProcess; }
|
namespace NekoRay::sys {
|
||||||
|
class CoreProcess;
|
||||||
|
}
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
@@ -29,7 +31,7 @@ namespace Ui {
|
|||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class MainWindow : public QMainWindow {
|
class MainWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MainWindow(QWidget *parent = nullptr);
|
explicit MainWindow(QWidget *parent = nullptr);
|
||||||
@@ -166,7 +168,6 @@ private:
|
|||||||
|
|
||||||
bool StopVPNProcess();
|
bool StopVPNProcess();
|
||||||
|
|
||||||
|
|
||||||
// grpc and ...
|
// grpc and ...
|
||||||
|
|
||||||
static void ExitNekorayCore();
|
static void ExitNekorayCore();
|
||||||
|
|||||||
@@ -20,9 +20,11 @@ using namespace NekoRay::rpc;
|
|||||||
void MainWindow::setup_grpc() {
|
void MainWindow::setup_grpc() {
|
||||||
#ifndef NKR_NO_GRPC
|
#ifndef NKR_NO_GRPC
|
||||||
// Setup Connection
|
// Setup Connection
|
||||||
defaultClient = new Client([=](const QString &errStr) {
|
defaultClient = new Client(
|
||||||
|
[=](const QString &errStr) {
|
||||||
MW_show_log("[Error] gRPC: " + errStr);
|
MW_show_log("[Error] gRPC: " + errStr);
|
||||||
}, "127.0.0.1:" + Int2String(NekoRay::dataStore->core_port), NekoRay::dataStore->core_token);
|
},
|
||||||
|
"127.0.0.1:" + Int2String(NekoRay::dataStore->core_port), NekoRay::dataStore->core_token);
|
||||||
auto t = new QTimer();
|
auto t = new QTimer();
|
||||||
connect(t, &QTimer::timeout, this, [=]() {
|
connect(t, &QTimer::timeout, this, [=]() {
|
||||||
bool ok = defaultClient->KeepAlive();
|
bool ok = defaultClient->KeepAlive();
|
||||||
@@ -38,9 +40,7 @@ void MainWindow::setup_grpc() {
|
|||||||
auto tt = new QThread;
|
auto tt = new QThread;
|
||||||
tt->start();
|
tt->start();
|
||||||
t->moveToThread(tt);
|
t->moveToThread(tt);
|
||||||
runOnUiThread([=] {
|
runOnUiThread([=] { t->start(2000); }, t);
|
||||||
t->start(2000);
|
|
||||||
}, t);
|
|
||||||
|
|
||||||
// Looper
|
// Looper
|
||||||
runOnNewThread([=] { NekoRay::traffic::trafficLooper->loop(); });
|
runOnNewThread([=] { NekoRay::traffic::trafficLooper->loop(); });
|
||||||
@@ -74,7 +74,7 @@ void MainWindow::speedtest_current_group(int mode) {
|
|||||||
runOnNewThread([=]() {
|
runOnNewThread([=]() {
|
||||||
auto group = NekoRay::profileManager->CurrentGroup();
|
auto group = NekoRay::profileManager->CurrentGroup();
|
||||||
if (group->archive) return;
|
if (group->archive) return;
|
||||||
auto order = ui->proxyListTable->order;//copy
|
auto order = ui->proxyListTable->order; // copy
|
||||||
|
|
||||||
QMutex lock_write;
|
QMutex lock_write;
|
||||||
QMutex lock_return;
|
QMutex lock_return;
|
||||||
@@ -152,9 +152,7 @@ void MainWindow::speedtest_current_group(int mode) {
|
|||||||
|
|
||||||
runOnUiThread([=] {
|
runOnUiThread([=] {
|
||||||
if (!result.error().empty()) {
|
if (!result.error().empty()) {
|
||||||
show_log_impl(
|
show_log_impl(tr("[%1] test error: %2").arg(profile->bean->DisplayTypeAndName(), result.error().c_str()));
|
||||||
tr("[%1] test error: %2").arg(profile->bean->DisplayTypeAndName(),
|
|
||||||
result.error().c_str()));
|
|
||||||
}
|
}
|
||||||
refresh_proxy_list(profile->id);
|
refresh_proxy_list(profile->id);
|
||||||
});
|
});
|
||||||
@@ -325,8 +323,8 @@ void MainWindow::CheckUpdate() {
|
|||||||
runOnUiThread([=] {
|
runOnUiThread([=] {
|
||||||
auto note_pre_release = response.is_pre_release() ? " (Pre-release)" : "";
|
auto note_pre_release = response.is_pre_release() ? " (Pre-release)" : "";
|
||||||
QMessageBox box(QMessageBox::Question, QObject::tr("Update") + note_pre_release,
|
QMessageBox box(QMessageBox::Question, QObject::tr("Update") + note_pre_release,
|
||||||
QObject::tr("Update found: %1\nRelease note:\n%2")
|
QObject::tr("Update found: %1\nRelease note:\n%2").arg(response.assets_name().c_str(), response.release_note().c_str()));
|
||||||
.arg(response.assets_name().c_str(), response.release_note().c_str()));
|
//
|
||||||
QAbstractButton *btn1 = nullptr;
|
QAbstractButton *btn1 = nullptr;
|
||||||
if (!NekoRay::dataStore->flag_use_appdata) {
|
if (!NekoRay::dataStore->flag_use_appdata) {
|
||||||
btn1 = box.addButton(QObject::tr("Update"), QMessageBox::AcceptRole);
|
btn1 = box.addButton(QObject::tr("Update"), QMessageBox::AcceptRole);
|
||||||
@@ -334,7 +332,7 @@ void MainWindow::CheckUpdate() {
|
|||||||
QAbstractButton *btn2 = box.addButton(QObject::tr("Open in browser"), QMessageBox::AcceptRole);
|
QAbstractButton *btn2 = box.addButton(QObject::tr("Open in browser"), QMessageBox::AcceptRole);
|
||||||
box.addButton(QObject::tr("Close"), QMessageBox::RejectRole);
|
box.addButton(QObject::tr("Close"), QMessageBox::RejectRole);
|
||||||
box.exec();
|
box.exec();
|
||||||
|
//
|
||||||
if (btn1 == box.clickedButton()) {
|
if (btn1 == box.clickedButton()) {
|
||||||
// Download Update
|
// Download Update
|
||||||
runOnNewThread([=] {
|
runOnNewThread([=] {
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ QString ParseSubInfo(const QString &info) {
|
|||||||
long long total = 0;
|
long long total = 0;
|
||||||
long long expire = 0;
|
long long expire = 0;
|
||||||
|
|
||||||
|
|
||||||
auto re0m = QRegularExpression("total=([0-9]+)").match(info);
|
auto re0m = QRegularExpression("total=([0-9]+)").match(info);
|
||||||
if (re0m.lastCapturedIndex() >= 1) {
|
if (re0m.lastCapturedIndex() >= 1) {
|
||||||
total = re0m.captured(1).toLongLong();
|
total = re0m.captured(1).toLongLong();
|
||||||
@@ -42,8 +41,7 @@ QString ParseSubInfo(const QString &info) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupItem::GroupItem(QWidget *parent, const QSharedPointer<NekoRay::Group> &ent, QListWidgetItem *item) :
|
GroupItem::GroupItem(QWidget *parent, const QSharedPointer<NekoRay::Group> &ent, QListWidgetItem *item) : QWidget(parent), ui(new Ui::GroupItem) {
|
||||||
QWidget(parent), ui(new Ui::GroupItem) {
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
this->ent = ent;
|
this->ent = ent;
|
||||||
@@ -51,8 +49,7 @@ GroupItem::GroupItem(QWidget *parent, const QSharedPointer<NekoRay::Group> &ent,
|
|||||||
if (ent == nullptr) return;
|
if (ent == nullptr) return;
|
||||||
|
|
||||||
connect(this, &GroupItem::edit_clicked, this, &GroupItem::on_edit_clicked);
|
connect(this, &GroupItem::edit_clicked, this, &GroupItem::on_edit_clicked);
|
||||||
connect(NekoRay::sub::groupUpdater, &NekoRay::sub::GroupUpdater::asyncUpdateCallback,
|
connect(NekoRay::sub::groupUpdater, &NekoRay::sub::GroupUpdater::asyncUpdateCallback, this, [=](int gid) { if (gid == this->ent->id) refresh_data(); });
|
||||||
this, [=](int gid) { if (gid == this->ent->id) refresh_data(); });
|
|
||||||
|
|
||||||
refresh_data();
|
refresh_data();
|
||||||
}
|
}
|
||||||
@@ -90,11 +87,13 @@ void GroupItem::refresh_data() {
|
|||||||
ui->subinfo->setText(info.join(" | "));
|
ui->subinfo->setText(info.join(" | "));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
runOnUiThread([=] {
|
runOnUiThread(
|
||||||
|
[=] {
|
||||||
adjustSize();
|
adjustSize();
|
||||||
item->setSizeHint(sizeHint());
|
item->setSizeHint(sizeHint());
|
||||||
dynamic_cast<QWidget *>(parent())->adjustSize();
|
dynamic_cast<QWidget *>(parent())->adjustSize();
|
||||||
}, this);
|
},
|
||||||
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupItem::on_update_sub_clicked() {
|
void GroupItem::on_update_sub_clicked() {
|
||||||
|
|||||||
@@ -6,11 +6,13 @@
|
|||||||
#include "db/Database.hpp"
|
#include "db/Database.hpp"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class GroupItem; }
|
namespace Ui {
|
||||||
|
class GroupItem;
|
||||||
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class GroupItem : public QWidget {
|
class GroupItem : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GroupItem(QWidget *parent, const QSharedPointer<NekoRay::Group> &ent, QListWidgetItem *item);
|
explicit GroupItem(QWidget *parent, const QSharedPointer<NekoRay::Group> &ent, QListWidgetItem *item);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public:
|
|||||||
this->setSelectionBehavior(QAbstractItemView::SelectRows);
|
this->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
};
|
};
|
||||||
|
|
||||||
// takes and returns the whole row
|
// takes and returns the whole row
|
||||||
QList<QTableWidgetItem *> takeRow(int row) {
|
QList<QTableWidgetItem *> takeRow(int row) {
|
||||||
QList<QTableWidgetItem *> rowItems;
|
QList<QTableWidgetItem *> rowItems;
|
||||||
for (int col = 0; col < columnCount(); ++col) {
|
for (int col = 0; col < columnCount(); ++col) {
|
||||||
@@ -24,7 +24,7 @@ public:
|
|||||||
return rowItems;
|
return rowItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets the whole row
|
// sets the whole row
|
||||||
void setRow(int row, const QList<QTableWidgetItem *> &rowItems) {
|
void setRow(int row, const QList<QTableWidgetItem *> &rowItems) {
|
||||||
for (int col = 0; col < columnCount(); ++col) {
|
for (int col = 0; col < columnCount(); ++col) {
|
||||||
setItem(row, col, rowItems.at(col));
|
setItem(row, col, rowItems.at(col));
|
||||||
@@ -88,36 +88,35 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/*
|
||||||
/*
|
|
||||||
* 2021.7.6 by gy
|
* 2021.7.6 by gy
|
||||||
* 拖拽 继承QTableWidget overwrite dropEvent事件
|
* 拖拽 继承QTableWidget overwrite dropEvent事件
|
||||||
* 功能:拖动一行到鼠标落下的位置
|
* 功能:拖动一行到鼠标落下的位置
|
||||||
* 注意:DragDropMode相关参数的设置
|
* 注意:DragDropMode相关参数的设置
|
||||||
*/
|
*/
|
||||||
void dropEvent(QDropEvent *event) override {
|
void dropEvent(QDropEvent *event) override {
|
||||||
// 原行号与目标行号的确定
|
// 原行号与目标行号的确定
|
||||||
int row_src, row_dst;
|
int row_src, row_dst;
|
||||||
row_src = this->currentRow();// 原行号 可加if
|
row_src = this->currentRow(); // 原行号 可加if
|
||||||
QTableWidgetItem *item = this->itemAt(event->pos());// 获取落点的item
|
QTableWidgetItem *item = this->itemAt(event->pos()); // 获取落点的item
|
||||||
if (item != nullptr) {
|
if (item != nullptr) {
|
||||||
// 判断是否为空
|
// 判断是否为空
|
||||||
row_dst = item->row();// 不为空 获取其行号
|
row_dst = item->row(); // 不为空 获取其行号
|
||||||
// 保证鼠标落下的位置 就是拖拽的一行最后所移动到的位置(考虑插入新行 移除原行的上下变化)
|
// 保证鼠标落下的位置 就是拖拽的一行最后所移动到的位置(考虑插入新行 移除原行的上下变化)
|
||||||
row_src = (row_src > row_dst ? row_src + 1 : row_src);// 如果src在dst的下方(行号大),后续插入dst会影响src的行号
|
row_src = (row_src > row_dst ? row_src + 1 : row_src); // 如果src在dst的下方(行号大),后续插入dst会影响src的行号
|
||||||
row_dst = (row_src < row_dst ? row_dst + 1 : row_dst);// 如果src在dst的上方(行号小),后续移除src会影响dst的行号
|
row_dst = (row_src < row_dst ? row_dst + 1 : row_dst); // 如果src在dst的上方(行号小),后续移除src会影响dst的行号
|
||||||
this->insertRow(row_dst);// 插入一行
|
this->insertRow(row_dst); // 插入一行
|
||||||
} else {
|
} else {
|
||||||
// 落点没有item 说明拖动到了最下面
|
// 落点没有item 说明拖动到了最下面
|
||||||
row_dst = this->rowCount();// 获取行总数
|
row_dst = this->rowCount(); // 获取行总数
|
||||||
this->insertRow(row_dst);// 在最后新增一行
|
this->insertRow(row_dst); // 在最后新增一行
|
||||||
}
|
}
|
||||||
// 执行移动 并移除原行
|
// 执行移动 并移除原行
|
||||||
for (int i = 0; i < this->columnCount(); i++) {
|
for (int i = 0; i < this->columnCount(); i++) {
|
||||||
// 遍历列
|
// 遍历列
|
||||||
this->setItem(row_dst, i, this->takeItem(row_src, i));// 每一列item的移动
|
this->setItem(row_dst, i, this->takeItem(row_src, i)); // 每一列item的移动
|
||||||
}
|
}
|
||||||
this->removeRow(row_src);// 删除原行
|
this->removeRow(row_src); // 删除原行
|
||||||
|
|
||||||
// Then save the order
|
// Then save the order
|
||||||
_save_order(true);
|
_save_order(true);
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
ProxyItem::ProxyItem(QWidget *parent, const QSharedPointer<NekoRay::ProxyEntity> &ent, QListWidgetItem *item) :
|
ProxyItem::ProxyItem(QWidget *parent, const QSharedPointer<NekoRay::ProxyEntity> &ent, QListWidgetItem *item)
|
||||||
QWidget(parent), ui(new Ui::ProxyItem) {
|
: QWidget(parent), ui(new Ui::ProxyItem) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
this->item = item;
|
this->item = item;
|
||||||
this->ent = ent;
|
this->ent = ent;
|
||||||
@@ -24,17 +24,18 @@ void ProxyItem::refresh_data() {
|
|||||||
ui->traffic->setText(ent->traffic_data->DisplayTraffic());
|
ui->traffic->setText(ent->traffic_data->DisplayTraffic());
|
||||||
ui->test_result->setText(ent->DisplayLatency());
|
ui->test_result->setText(ent->DisplayLatency());
|
||||||
|
|
||||||
runOnUiThread([=] {
|
runOnUiThread(
|
||||||
|
[=] {
|
||||||
adjustSize();
|
adjustSize();
|
||||||
item->setSizeHint(sizeHint());
|
item->setSizeHint(sizeHint());
|
||||||
dynamic_cast<QWidget *>(parent())->adjustSize();
|
dynamic_cast<QWidget *>(parent())->adjustSize();
|
||||||
}, this);
|
},
|
||||||
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyItem::on_remove_clicked() {
|
void ProxyItem::on_remove_clicked() {
|
||||||
if (!this->remove_confirm ||
|
if (!this->remove_confirm ||
|
||||||
QMessageBox::question(this, tr("Confirmation"), tr("Remove %1?").arg(ent->bean->DisplayName()))
|
QMessageBox::question(this, tr("Confirmation"), tr("Remove %1?").arg(ent->bean->DisplayName())) == QMessageBox::StandardButton::Yes) {
|
||||||
== QMessageBox::StandardButton::Yes) {
|
|
||||||
// TODO do remove (or not) -> callback
|
// TODO do remove (or not) -> callback
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,13 @@
|
|||||||
#include "db/ProxyEntity.hpp"
|
#include "db/ProxyEntity.hpp"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class ProxyItem; }
|
namespace Ui {
|
||||||
|
class ProxyItem;
|
||||||
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class ProxyItem : public QWidget {
|
class ProxyItem : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ProxyItem(QWidget *parent, const QSharedPointer<NekoRay::ProxyEntity> &ent, QListWidgetItem *item);
|
explicit ProxyItem(QWidget *parent, const QSharedPointer<NekoRay::ProxyEntity> &ent, QListWidgetItem *item);
|
||||||
|
|||||||
Reference in New Issue
Block a user