chore: re-format code

This commit is contained in:
arm64v8a
2022-11-18 14:20:30 +09:00
parent deab99af73
commit 62c236f0d5
97 changed files with 1129 additions and 1331 deletions

10
.clang-format Normal file
View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -51,4 +51,4 @@ namespace NekoRay {
}; };
extern ProfileManager *profileManager; extern ProfileManager *profileManager;
} } // namespace NekoRay

View File

@@ -22,4 +22,4 @@ namespace NekoRay {
// 按 显示 顺序 // 按 显示 顺序
[[nodiscard]] QList<QSharedPointer<ProxyEntity>> ProfilesWithOrder() const; [[nodiscard]] QList<QSharedPointer<ProxyEntity>> ProfilesWithOrder() const;
}; };
} } // namespace NekoRay

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -28,4 +28,4 @@ namespace NekoRay::traffic {
}; };
extern TrafficLooper *trafficLooper; extern TrafficLooper *trafficLooper;
} } // namespace NekoRay::traffic

View File

@@ -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

View File

@@ -60,7 +60,6 @@ namespace NekoRay::fmt {
virtual QString InsecureHint() { return {}; }; virtual QString InsecureHint() { return {}; };
QString DisplayInsecureHint(); QString DisplayInsecureHint();
}; };
} } // namespace NekoRay::fmt

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -90,4 +90,4 @@ namespace NekoRay::fmt {
return url.toString(); return url.toString();
} }
} } // namespace NekoRay::fmt

View File

@@ -15,4 +15,4 @@ namespace NekoRay::fmt {
QString DisplayAddress() override { return ""; }; QString DisplayAddress() override { return ""; };
}; };
} } // namespace NekoRay::fmt

View File

@@ -47,4 +47,4 @@ namespace NekoRay::fmt {
CoreObjOutboundBuildResult BuildCoreObjV2Ray() override; CoreObjOutboundBuildResult BuildCoreObjV2Ray() override;
}; };
} } // namespace NekoRay::fmt

View File

@@ -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

View File

@@ -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

View File

@@ -35,4 +35,4 @@ namespace NekoRay::fmt {
QString ToShareLink() override; QString ToShareLink() override;
}; };
} } // namespace NekoRay::fmt

View File

@@ -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

View File

@@ -33,4 +33,4 @@ namespace NekoRay::fmt {
QString InsecureHint() override; QString InsecureHint() override;
}; };
} } // namespace NekoRay::fmt

View File

@@ -38,4 +38,4 @@ namespace NekoRay::fmt {
QString InsecureHint() override; QString InsecureHint() override;
}; };
} } // namespace NekoRay::fmt

View File

@@ -34,4 +34,4 @@ namespace NekoRay::fmt {
QString InsecureHint() override; QString InsecureHint() override;
}; };
} } // namespace NekoRay::fmt

View File

@@ -56,4 +56,4 @@ namespace NekoRay::fmt {
} }
return nullptr; return nullptr;
} }
} } // namespace NekoRay::fmt

View File

@@ -33,5 +33,4 @@ namespace NekoRay::fmt {
QString InsecureHint() override; QString InsecureHint() override;
}; };
} } // namespace NekoRay::fmt

2
libs/format_cpp.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
git ls-files | grep -E "\.cpp|\.h" | grep -v "3rdparty" | xargs -n1 clang-format -i

View File

@@ -30,5 +30,4 @@ namespace NekoRay {
SING_BOX, SING_BOX,
}; };
} }
} } // namespace NekoRay

View File

@@ -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();

View File

@@ -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

View File

@@ -60,4 +60,4 @@ namespace NekoRay {
bool Load(); bool Load();
}; };
} } // namespace NekoRay

View File

@@ -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 + "/")

View File

@@ -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)

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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) {

View File

@@ -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));
} }

View File

@@ -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:

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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)
// { // {

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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(&current, &remaining, &wire_type, &field_number); ReadWireTypeAndFieldNumber(&current, &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(&current, &remaining); const uint64_t varint = ReadVarInt(&current, &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>(&current, &remaining); const uint64_t value = ReadFromBytes<uint64_t>(&current, &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(&current, &remaining); const uint64_t size = ReadVarInt(&current, &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>(&current, &remaining); const uint32_t value = ReadFromBytes<uint32_t>(&current, &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(&current, &remaining); const uint64_t varint = ReadVarInt(&current, &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(&current, &remaining); const uint64_t varint = ReadVarInt(&current, &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(&current, &remaining); const uint64_t varint = ReadVarInt(&current, &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;

View File

@@ -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.

View File

@@ -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();
} }
} }

View File

@@ -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

View File

@@ -42,6 +42,5 @@ namespace NekoRay::rpc {
}; };
inline Client *defaultClient; inline Client *defaultClient;
} } // namespace NekoRay::rpc
#endif #endif

View File

@@ -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

View File

@@ -28,5 +28,4 @@ namespace NekoRay::sub {
}; };
extern GroupUpdater *groupUpdater; extern GroupUpdater *groupUpdater;
} } // namespace NekoRay::sub

View File

@@ -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();

View File

@@ -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

View File

@@ -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

View File

@@ -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() {

View File

@@ -2,7 +2,7 @@
#ifdef __MINGW32__ #ifdef __MINGW32__
void Windows_SetCrashHandler(){} void Windows_SetCrashHandler() {}
#else #else

View File

@@ -19,4 +19,4 @@ namespace NekoRay {
bool descending = false; //默认升序,开这个就是降序 bool descending = false; //默认升序,开这个就是降序
bool scroll_to_started = false; bool scroll_to_started = false;
}; };
} } // namespace NekoRay

View File

@@ -13,4 +13,4 @@ namespace TrayIcon {
QIcon GetIcon(TrayIconStatus status); QIcon GetIcon(TrayIconStatus status);
} } // namespace TrayIcon

View File

@@ -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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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();
}; };

View File

@@ -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);

View File

@@ -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

View File

@@ -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) {

View File

@@ -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;
}; };

View File

@@ -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 *>()) {

View File

@@ -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);

View File

@@ -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);

View File

@@ -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"
"}"); "}");

View File

@@ -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;

View File

@@ -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);
} }

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
} }

View File

@@ -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;
}; };

View File

@@ -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);
} }

View File

@@ -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;
}; };

View File

@@ -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);

View File

@@ -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();

View File

@@ -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([=] {

View File

@@ -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() {

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
} }

View File

@@ -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);