From 36d82303a4c9a85d28107c54d799c1bfbe0c11fb Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 13 Feb 2020 22:50:51 +0800 Subject: [PATCH 001/332] add: added connection handler file --- Qv2ray.pro | 3 ++- makespec/BUILDVERSION | 2 +- src/core/handler/ConnectionHandler.cpp | 0 src/core/handler/ConnectionHandler.hpp | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 src/core/handler/ConnectionHandler.cpp create mode 100644 src/core/handler/ConnectionHandler.hpp diff --git a/Qv2ray.pro b/Qv2ray.pro index 9c8a6a68..c0d45319 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -84,9 +84,10 @@ Qv2rayAddSource(core, config, ConfigUpgrade, cpp) Qv2rayAddSource(core, connection, ConnectionIO, cpp, hpp) Qv2rayAddSource(core, connection, Generation, cpp, hpp) Qv2rayAddSource(core, connection, Serialization, cpp, hpp) -Qv2rayAddSource(core, _, CoreUtils, cpp, hpp) Qv2rayAddSource(core, kernel, KernelInteractions, cpp, hpp) Qv2rayAddSource(core, kernel, APIBackend, cpp, hpp) +Qv2rayAddSource(core, handler, ConnectionHandler, cpp, hpp) +Qv2rayAddSource(core, _, CoreUtils, cpp, hpp) Qv2rayAddSource(ui, editors, w_InboundEditor, cpp, hpp, ui) Qv2rayAddSource(ui, editors, w_JsonEditor, cpp, hpp, ui) Qv2rayAddSource(ui, editors, w_OutboundEditor, cpp, hpp, ui) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 38ab567f..9bb70db0 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3861 +3862 diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/src/core/handler/ConnectionHandler.hpp @@ -0,0 +1 @@ +#pragma once From 93e613df295d38033b7ffe8e5218a55284823cea Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 14 Feb 2020 00:20:27 +0800 Subject: [PATCH 002/332] wip: add: added new config structure and config directory layout --- Qv2ray.pro | 1 + makespec/BUILDVERSION | 2 +- src/base/Qv2rayBase.hpp | 1 + src/base/models/QvConfigModel.hpp | 34 ++++++++--- src/core/config/ConfigUpgrade.cpp | 70 ++++++++++++++++++----- src/core/handler/ConnectionHandler.hpp | 22 +++++++ src/core/handler/V2rayInstanceHandler.cpp | 0 src/core/handler/V2rayInstanceHandler.hpp | 0 8 files changed, 109 insertions(+), 21 deletions(-) create mode 100644 src/core/handler/V2rayInstanceHandler.cpp create mode 100644 src/core/handler/V2rayInstanceHandler.hpp diff --git a/Qv2ray.pro b/Qv2ray.pro index c0d45319..a7b2484c 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -87,6 +87,7 @@ Qv2rayAddSource(core, connection, Serialization, cpp, hpp) Qv2rayAddSource(core, kernel, KernelInteractions, cpp, hpp) Qv2rayAddSource(core, kernel, APIBackend, cpp, hpp) Qv2rayAddSource(core, handler, ConnectionHandler, cpp, hpp) +Qv2rayAddSource(core, handler, V2rayInstanceHandler, cpp, hpp) Qv2rayAddSource(core, _, CoreUtils, cpp, hpp) Qv2rayAddSource(ui, editors, w_InboundEditor, cpp, hpp, ui) Qv2rayAddSource(ui, editors, w_JsonEditor, cpp, hpp, ui) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 9bb70db0..7f5b8d72 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3862 +3863 diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index 30d8009d..ce284b1d 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -55,6 +55,7 @@ extern const bool isDebugBuild; // Get Configured Config Dir Path #define QV2RAY_CONFIG_DIR (Qv2ray::Qv2rayConfigPath) #define QV2RAY_CONFIG_FILE (QV2RAY_CONFIG_DIR + "Qv2ray.conf") +#define QV2RAY_CONNECTIONS_DIR (QV2RAY_CONFIG_DIR + "connections/") #define QV2RAY_SUBSCRIPTION_DIR (QV2RAY_CONFIG_DIR + "subscriptions/") // Get GFWList and PAC file path. diff --git a/src/base/models/QvConfigModel.hpp b/src/base/models/QvConfigModel.hpp index 3237c0ec..299ca180 100644 --- a/src/base/models/QvConfigModel.hpp +++ b/src/base/models/QvConfigModel.hpp @@ -4,14 +4,12 @@ #include "base/models/QvConfigIdentifier.hpp" #include -const int QV2RAY_CONFIG_VERSION = 8; +const int QV2RAY_CONFIG_VERSION = 9; namespace Qv2ray::base { namespace config { - - struct QvBarLine { QString Family; bool Bold; @@ -123,7 +121,6 @@ namespace Qv2ray::base bool withLocalDNS; QList dnsList; Qv2rayForwardProxyConfig forwardProxyConfig; - Qv2rayConnectionConfig() : bypassCN(true), enableProxy(true), withLocalDNS(false), dnsList(QStringList() << "8.8.4.4" << "1.1.1.1") { } XTOSTRUCT(O(bypassCN, enableProxy, withLocalDNS, dnsList, forwardProxyConfig)) }; @@ -135,6 +132,27 @@ namespace Qv2ray::base XTOSTRUCT(O(enableAPI, statsPort)) }; + struct QvGroupObject { + QString groupId; + QString displayName; + QvGroupObject(): groupId(QUuid::createUuid().toString()), displayName() {} + XTOSTRUCT(O(displayName)) + }; + + struct QvConnectionObject { + QString displayName; + QString connectionId; + QString groupId; + // + time_t importDate; + long latency; + long upLinkData; + long downLinkData; + QvConnectionObject(): displayName(), importDate(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())), + latency(0), upLinkData(0), downLinkData(0) { } + XTOSTRUCT(O(displayName, importDate, latency, upLinkData, downLinkData)) + }; + struct Qv2rayConfig { int config_version; bool tProxySupport; @@ -145,7 +163,9 @@ namespace Qv2ray::base ConnectionIdentifier autoStartConfig; QString ignoredVersion; // - QList configs; + QList groups; + QList connections; + //QList configs; QMap subscriptions; // Qv2rayUIConfig uiConfig; @@ -162,7 +182,7 @@ namespace Qv2ray::base v2AssetsPath(), autoStartConfig(), ignoredVersion(), - configs(), + connections(), subscriptions(), uiConfig(), apiConfig(), @@ -176,7 +196,7 @@ namespace Qv2ray::base logLevel, autoStartConfig, v2CorePath, v2AssetsPath, - configs, + connections, uiConfig, subscriptions, inboundConfig, connectionConfig, toolBarConfig, apiConfig)) }; diff --git a/src/core/config/ConfigUpgrade.cpp b/src/core/config/ConfigUpgrade.cpp index 9d24b6f6..1376603b 100644 --- a/src/core/config/ConfigUpgrade.cpp +++ b/src/core/config/ConfigUpgrade.cpp @@ -6,7 +6,7 @@ #include "base/Qv2rayBase.hpp" #include "common/QvHelpers.hpp" -#define UPDATELOG(msg) LOG(SETTINGS, " [" + QSTRN(fromVersion) + "-" + QSTRN(fromVersion + 1) + "] --> " + msg) +#define UPGRADELOG(msg) LOG(SETTINGS, " [" + QSTRN(fromVersion) + "-" + QSTRN(fromVersion + 1) + "] --> " + msg) namespace Qv2ray { @@ -19,7 +19,7 @@ namespace Qv2ray // From 1 to 2, we changed the config_version from 'string' to 'int' root.remove("config_version"); root["config_version"] = 2; - UPDATELOG("Upgrading config_version from old value " + v1_oldConfigVersion + " to 2") + UPGRADELOG("Upgrading config_version from old value " + v1_oldConfigVersion + " to 2") break; } @@ -37,8 +37,8 @@ namespace Qv2ray QFile::copy(vCoreFilePath, vCoreDestPath); QFile::copy(v2CtlFilePath, v2CtlDestPath); root.remove("v2CorePath"); - UPDATELOG("v2CorePath value from: " + vCoreFilePath + " to " + vCoreDestPath) - UPDATELOG("v2CtlFilePath value from: " + v2CtlFilePath + " to " + v2CtlDestPath) + UPGRADELOG("v2CorePath value from: " + vCoreFilePath + " to " + vCoreDestPath) + UPGRADELOG("v2CtlFilePath value from: " + v2CtlFilePath + " to " + v2CtlDestPath) break; } @@ -49,7 +49,7 @@ namespace Qv2ray root.remove("proxyDefault"); root["enableProxy"] = oldProxyDefault; //enableProxy - UPDATELOG("key: proxyDefault->enableProxy, value from: " + QSTRN(oldProxyDefault) + " to " + QSTRN(oldProxyDefault)) + UPGRADELOG("key: proxyDefault->enableProxy, value from: " + QSTRN(oldProxyDefault) + " to " + QSTRN(oldProxyDefault)) break; } @@ -62,12 +62,12 @@ namespace Qv2ray // From 3 to 4, we changed 'runAsRoot' to 'tProxySupport' auto v3_oldrunAsRoot = root["runAsRoot"].toBool(); root.insert("tProxySupport", v3_oldrunAsRoot); - UPDATELOG("Upgrading runAsRoot to tProxySupport, the value is not changed: " + QSTRN(v3_oldrunAsRoot)) + UPGRADELOG("Upgrading runAsRoot to tProxySupport, the value is not changed: " + QSTRN(v3_oldrunAsRoot)) // QString path; path = QV2RAY_DEFAULT_VCORE_PATH; root["v2CorePath"] = path; - UPDATELOG("Added v2CorePath to the config file.") + UPGRADELOG("Added v2CorePath to the config file.") // QJsonObject uiSettings; uiSettings["language"] = root["language"].toString("en-US").replace("-", "_"); @@ -75,7 +75,7 @@ namespace Qv2ray // root["inboundConfig"] = root["inBoundSettings"]; root.remove("inBoundSettings"); - UPDATELOG("Renamed inBoundSettings to inboundConfig.") + UPGRADELOG("Renamed inBoundSettings to inboundConfig.") // //connectionConfig QJsonObject o; @@ -85,9 +85,9 @@ namespace Qv2ray o["bypassCN"] = !v2_oldProxyCN; o["enableStats"] = true; o["statsPort"] = 13459; - UPDATELOG("Default statistics enabled.") + UPGRADELOG("Default statistics enabled.") root["connectionConfig"] = o; - UPDATELOG("Renamed some connection configs to connectionConfig.") + UPGRADELOG("Renamed some connection configs to connectionConfig.") // // Do we need renaming here? // //auto inbound = root["inboundConfig"].toObject(); @@ -100,7 +100,7 @@ namespace Qv2ray ConnectionIdentifier i; i.connectionName = root["autoStartConfig"].toString(); root["autoStartConfig"] = GetRootObject(i); - UPDATELOG("Added subscription feature to autoStartConfig.") + UPGRADELOG("Added subscription feature to autoStartConfig.") break; } @@ -122,7 +122,7 @@ namespace Qv2ray } root["subscriptions"] = newSubscriptions; - UPDATELOG("Added subscription renewal options.") + UPGRADELOG("Added subscription renewal options.") break; } @@ -141,9 +141,53 @@ namespace Qv2ray auto uiConfig = root["uiConfig"].toObject(); uiConfig["language"] = lang; root["uiConfig"] = uiConfig; - UPDATELOG("Changed language: " + lang) + UPGRADELOG("Changed language: " + lang) break; } + + // From version 8 to 9, we introduced a lot of new connection metainfo(s) + case 8: { + // Generate a default group + auto groupId = QUuid::createUuid().toString(); + QJsonObject defaultGroup; + defaultGroup["groupId"] = groupId; + defaultGroup["displayName"] = QObject::tr("Default Group"); + QJsonArray groups; + groups.push_back(defaultGroup); + root["groups"] = groups; + + if (!QDir(QV2RAY_CONNECTIONS_DIR).exists()) { + QDir().mkpath(QV2RAY_CONNECTIONS_DIR); + } + + for (auto config : root["configs"].toArray()) { + UPGRADELOG("Migrating: " + config.toString()) + // + // MOVE FILES. + auto filePath = QV2RAY_CONNECTIONS_DIR + config.toString() + QV2RAY_CONFIG_FILE_EXTENSION; + auto configFile = QFile(filePath); + auto newUuid = QUuid::createUuid().toString(); + DEBUG(SETTINGS, "Generated new UUID: " + newUuid); + + if (configFile.exists()) { + auto newPath = QV2RAY_CONNECTIONS_DIR + newUuid + QV2RAY_CONFIG_FILE_EXTENSION; + configFile.rename(newPath); + UPGRADELOG("Moved: " + filePath + " to " + newPath); + } else { + UPGRADELOG("WARNING! This file is not found, possible loss of data!") + continue; + } + + QJsonObject connectionObject; + connectionObject["displayName"] = config.toString(); + connectionObject["connectionId"] = newUuid; + connectionObject["groupId"] = groupId; + // + auto connections = root["connections"].toArray(); + connections.push_back(connectionObject); + root["connections"] = connections; + } + } } root["config_version"] = root["config_version"].toInt() + 1; diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 6f70f09b..8315fb66 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -1 +1,23 @@ #pragma once + +#include "base/Qv2rayBase.hpp" + +class ConnectionGroupIdentifier; + +namespace Qv2ray::core::handler +{ + class ConnectionHandler : public QObject + { + Q_OBJECT + explicit ConnectionHandler(); + ~ConnectionHandler(); + void ReloadConnections(); + + public slots: + optional DeleteConnection(const ConnectionIdentifier &identifier); + // + optional RenameConnection(const ConnectionIdentifier &identifier, const QString &newName); + optional MoveConnection(const ConnectionIdentifier &identifier, const ConnectionGroupIdentifier &newGroup); + optional DuplicateConnection(const ConnectionIdentifier &identifier, ConnectionIdentifier *newIdentifier); + }; +} diff --git a/src/core/handler/V2rayInstanceHandler.cpp b/src/core/handler/V2rayInstanceHandler.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/core/handler/V2rayInstanceHandler.hpp b/src/core/handler/V2rayInstanceHandler.hpp new file mode 100644 index 00000000..e69de29b From 3fceacd6ea2eecd26d308ef19a52ec2b93e41b86 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 14 Feb 2020 18:50:07 +0800 Subject: [PATCH 003/332] wip: tmp: add: added ConnectionWidget --- src/ui/widgets/ConnectionWidget.cpp | 21 +++++++++ src/ui/widgets/ConnectionWidget.hpp | 27 +++++++++++ src/ui/widgets/ConnectionWidget.ui | 71 +++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 src/ui/widgets/ConnectionWidget.cpp create mode 100644 src/ui/widgets/ConnectionWidget.hpp create mode 100644 src/ui/widgets/ConnectionWidget.ui diff --git a/src/ui/widgets/ConnectionWidget.cpp b/src/ui/widgets/ConnectionWidget.cpp new file mode 100644 index 00000000..9101f2a1 --- /dev/null +++ b/src/ui/widgets/ConnectionWidget.cpp @@ -0,0 +1,21 @@ +#include "formwidget.h" +#include "QMessageBox" +#include "ui_formwidget.h" + +Formwidget::Formwidget(int id, QWidget *parent) : + QWidget(parent), + ui(new Ui::Formwidget) +{ + _id = id; + ui->setupUi(this); +} + +Formwidget::~Formwidget() +{ + delete ui; +} + +void Formwidget::on_pushButton_clicked() +{ + QMessageBox::information(this, "d", QString::number(_id)); +} diff --git a/src/ui/widgets/ConnectionWidget.hpp b/src/ui/widgets/ConnectionWidget.hpp new file mode 100644 index 00000000..6d745c0d --- /dev/null +++ b/src/ui/widgets/ConnectionWidget.hpp @@ -0,0 +1,27 @@ +#ifndef FORMWIDGET_H +#define FORMWIDGET_H + +#include + +namespace Ui +{ + class Formwidget; +} + +class Formwidget : public QWidget +{ + Q_OBJECT + + public: + explicit Formwidget(int id, QWidget *parent = nullptr); + ~Formwidget(); + + private slots: + void on_pushButton_clicked(); + + private: + int _id; + Ui::Formwidget *ui; +}; + +#endif // FORMWIDGET_H diff --git a/src/ui/widgets/ConnectionWidget.ui b/src/ui/widgets/ConnectionWidget.ui new file mode 100644 index 00000000..d2a43730 --- /dev/null +++ b/src/ui/widgets/ConnectionWidget.ui @@ -0,0 +1,71 @@ + + + Formwidget + + + + 0 + 0 + 474 + 83 + + + + Form + + + + + + + + Connection Name + + + + + + + Type + + + + + + + TextLabel + + + + + + + + + Latency + + + + + + + + + Edit + + + + + + + Ping + + + + + + + + + + From ee9c347a8203c8d5ed7747d3a8e634d0026fc180 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 14 Feb 2020 20:47:20 +0800 Subject: [PATCH 004/332] wip: add: added Qv2ray project strcture model diagram --- qv2ray-config-models.qmodel | 294 +++++ qv2ray-new.qmodel | 2321 +++++++++++++++++++++++++++++++++++ qv2ray.qmodel | 2187 +++++++++++++++++++++++++++++++++ 3 files changed, 4802 insertions(+) create mode 100644 qv2ray-config-models.qmodel create mode 100644 qv2ray-new.qmodel create mode 100644 qv2ray.qmodel diff --git a/qv2ray-config-models.qmodel b/qv2ray-config-models.qmodel new file mode 100644 index 00000000..859a3f02 --- /dev/null +++ b/qv2ray-config-models.qmodel @@ -0,0 +1,294 @@ + + + + {e33c4c89-9b5b-44c4-9790-17cef05732d8} + + + + + + + + {6035e8ea-cf65-4a95-b11b-59d640802d5e} + + + Qv2ray-config-models + + + + + + + {0a303cb9-6681-4f79-9779-e61a34ac44ea} + + + + + + + + + + {0a303cb9-6681-4f79-9779-e61a34ac44ea} + + + Qv2ray-config-models + + + + + + + + + + + + {89aa1d96-388b-49c0-a4e6-bf55bb570889} + + + {314756b5-bc93-49b8-ae97-957fe8b30d44} + BaseGroupObject + x:410;y:235 + x:-75;y:-50;w:150;h:100 + false + 0 + + + false + + + + + + + + + {7dd68311-11eb-43d0-9e64-91daeae12d97} + + + Display Name + x:350;y:215 + x:0;y:0;w:84.2031;h:30 + + + + + + + + + {e51a8692-6ecb-4052-8e09-f1b1ee3a2b92} + + + Connection Groups + x:260;y:230 + x:-235;y:-75;w:470;h:150 + + + + + + + + + {b4dc36e8-31f6-4637-9f8f-c27ee155e301} + + + List<ConnectionId> + x:350;y:235 + x:0;y:0;w:111.391;h:30 + + + + + + + + + {ffc9dfd5-2441-4b3b-b814-3ac76fb03c7e} + + + Subscriptions + x:565;y:230 + x:-240;y:-75;w:480;h:150 + + + + + + + + + {3634dcd7-fac8-4993-b3e7-c10450dae1de} + + + Nothing here since the base group +is enough + x:85;y:215 + x:0;y:0;w:186.047;h:44 + + + + + + + + + {41e1ca4e-8395-472f-8470-912cf2c7b9d1} + + + Some other metadata of subscription + x:535;y:220 + x:0;y:0;w:199.766;h:30 + + + + + + + + + + + {d27ab510-0eda-4d06-ac71-cd8b1d68571f} + + + {48b1692c-e2da-49cb-b1da-dd1030084013} + Address, last-renewed...... + x:610;y:205 + x:-75;y:-15;w:150;h:30 + 0 + + + false + + + + + + 1581683831371 + General + + + + + + + + + + {314756b5-bc93-49b8-ae97-957fe8b30d44} + + + + + + + + {314756b5-bc93-49b8-ae97-957fe8b30d44} + + + BaseGroupObject + + + + + + + + + + {e2922977-d357-43f0-822a-624245d6b470} + + + + + + + + {e2922977-d357-43f0-822a-624245d6b470} + + + New Item + + + + + + + + + + {8a788e13-b40c-4a33-8121-f0a4817428b1} + + + + + + + + {8a788e13-b40c-4a33-8121-f0a4817428b1} + + + Address + + + + + + + + + + {ec54fd48-400e-4e7d-9e74-b6333d2101c1} + + + + + + + + {ec54fd48-400e-4e7d-9e74-b6333d2101c1} + + + Some other metadata of subscription + + + + + + + + + + {48b1692c-e2da-49cb-b1da-dd1030084013} + + + + + + + + {48b1692c-e2da-49cb-b1da-dd1030084013} + + + Address, last-renewed...... + + + + + + + + + + + + + + + + + + diff --git a/qv2ray-new.qmodel b/qv2ray-new.qmodel new file mode 100644 index 00000000..a066e428 --- /dev/null +++ b/qv2ray-new.qmodel @@ -0,0 +1,2321 @@ + + + + {184bb3ed-eb77-4571-9a4c-408ed27a1eb5} + + + + + + + + {fffb726b-5aa7-48bd-943f-58d956367038} + + + Qv2ray-new + + + + + + + {370e74be-62e3-4d96-a911-122a41cca49f} + + + + + + + + + + {370e74be-62e3-4d96-a911-122a41cca49f} + + + Qv2ray-new + + + + + + + + + + {5d6a4dd6-8e17-4482-833c-9ce7c42972ba} + + + Qv2ray Main Application + x:460;y:460 + x:-355;y:-345;w:710;h:690 + + + + + + + + + + + {9cdb07b7-5f86-41c7-a9d5-f43396a58f28} + + + {024fd01e-41da-48d6-ad7a-a42003f6f43c} + MainWindow + x:220;y:410 + x:-80;y:-55;w:160;h:110 + false + 0 + + + + + + + + + + + {b82f4d3e-625f-48e2-91ee-fc242f3702b8} + + + API Data + x:960;y:290 + x:0;y:0;w:58.4531;h:30 + + + + + + + + + {67f7174e-a17f-42f7-a4d4-ae8e941cfe66} + + + API Backends + x:875;y:285 + x:-55;y:-55;w:110;h:110 + + + + + + + + + {3092ef19-9acc-4e9f-8218-45815f844cde} + + + V2ray Core + + x:1090;y:260 + x:-60;y:-75;w:120;h:150 + + + + + + + + + {80ac5d0a-cacb-41a5-8512-941d9f049dee} + + + Logs + x:955;y:200 + x:0;y:0;w:38.375;h:30 + + + + + + + + + + + {fe42c651-f134-4968-8b3a-775487035f5a} + + + {332eb659-610e-4dda-a031-a8d4533ff654} + Complex Editor + x:220;y:675 + x:-70;y:-30;w:140;h:60 + 0 + + + + + + + + + + + + + {2fc66815-2b1d-4a33-b5ec-2abaff6cbfea} + + + {3e71f0fe-ef4f-4bda-be19-cdbc546d7748} + Outbound Editor + x:695;y:615 + x:-75;y:-30;w:150;h:60 + 0 + + + + + + + + + + + + + {b3f3a2d9-6638-4fd2-b3eb-2ab601681eb2} + + + {96ce5d9a-03e7-4a98-a25a-0e9aff2ff6b4} + Inbound Editor + x:695;y:765 + x:-75;y:-30;w:150;h:60 + false + 0 + + + + + + + + + + + + + {8bd583d2-3d43-4589-8dd1-522f484fb3f5} + + + {5340a8a0-ad20-438c-83af-833d5d8fce40} + {fe42c651-f134-4968-8b3a-775487035f5a} + {2fc66815-2b1d-4a33-b5ec-2abaff6cbfea} + + + + + + + + + + + + + {1401c7cd-fd3b-4c86-a03a-45e9c5a0547e} + + + {d510ad05-6490-42cf-bb73-66a80152c478} + {fe42c651-f134-4968-8b3a-775487035f5a} + {b3f3a2d9-6638-4fd2-b3eb-2ab601681eb2} + + + + + + + + + + + + + {d2304b1e-082c-4edb-87f5-b753a3c2ca32} + + + {26a11a27-d179-4355-9273-e1fa54ef13e1} + Connection Handler + x:695;y:455 + x:-95;y:-80;w:190;h:160 + false + 0 + + + false + + + + + + + + + + + {5e3887ac-4379-4760-b460-b0a0b165ee6a} + + + {8caf1563-5c81-46eb-b0ac-64f745ca617a} + Instance Handler + x:585;y:260 + x:-80;y:-70;w:160;h:140 + false + 0 + + + false + + + + + + + + + + + {d106a7a1-4a2a-4285-b817-f2fa75c14c3f} + + + {8e66ff8b-f122-4cbc-90d3-c823ab513c06} + VCore Instance + x:745;y:220 + x:-50;y:-20;w:100;h:40 + false + 0 + + + false + + + + + + + + + + + {6374ef07-f681-45cc-b845-daa9648bed8f} + + + {7c2667ea-cc97-4418-91b6-430e18a77ce5} + API Subsystem + x:740;y:310 + x:-45;y:-15;w:90;h:30 + 0 + + + false + + + + + + + + + + + {978ff457-2ba6-44f0-a678-1d88e8522cec} + + + {a15d947a-8d8d-49aa-803f-d1c7c6a60ee1} + {6374ef07-f681-45cc-b845-daa9648bed8f} + {d106a7a1-4a2a-4285-b817-f2fa75c14c3f} + + + + + + + + + + + + + {45a3d828-e197-494a-ae71-96c8fd1700d1} + + + {c5c2659d-6f38-4949-9965-e32f2401d5db} + {d106a7a1-4a2a-4285-b817-f2fa75c14c3f} + {6374ef07-f681-45cc-b845-daa9648bed8f} + + + + + + + + + + + + + {c83289b3-1a90-4b54-9e7d-dd8c39ea69e8} + + + {29039158-2c91-412a-a46b-5e99e713192f} + gRPC + x:880;y:305 + x:-25;y:-15;w:50;h:30 + 0 + + + false + + + + + + + + + + + {be9c1a6c-47bb-4324-b207-eafe52316c61} + + + {820260d5-8128-4c25-b4b4-406b326c7a10} + {6374ef07-f681-45cc-b845-daa9648bed8f} + {c83289b3-1a90-4b54-9e7d-dd8c39ea69e8} + + + + + + + + + + + + + {128ad389-d81b-45eb-9540-dae42d8aebbb} + + + {182d4943-e868-4a84-a0af-524b79f9a3f4} + libqvb + x:880;y:270 + x:-25;y:-15;w:50;h:30 + 0 + + + false + + + + + + + + + + + {542fc889-55d8-4c98-ab40-757643783477} + + + {11d29c88-d70f-4449-a4de-8e66479b9fa0} + VCore + x:1080;y:225 + x:-25;y:-15;w:50;h:30 + 6 + + + false + + + + + + + + + + + {1251483a-1f28-49ce-993f-cc8e026b1032} + + + {ed27c562-ee05-4562-8c40-495f1a0656fb} + API Server + x:1085;y:295 + x:-35;y:-15;w:70;h:30 + 6 + + + false + + + + + + + + + + + {79c1970d-6bbe-4e27-a12e-ab05de0ef5ad} + + + {08967768-9ee2-4c54-af60-6062cd3d84cc} + {6374ef07-f681-45cc-b845-daa9648bed8f} + {128ad389-d81b-45eb-9540-dae42d8aebbb} + + + + + + + + + + + + + {0cdb1818-740b-47fb-b032-7d118d3d08f2} + + + {18b95586-196e-44dc-8909-2cdccbeed443} + {1251483a-1f28-49ce-993f-cc8e026b1032} + {128ad389-d81b-45eb-9540-dae42d8aebbb} + + + + + + + + + + + + + {eeff0c5c-5232-46fc-a99c-9ca9ce3a56f6} + + + {8b101bdc-747f-4b4f-afb4-34027f38ba1b} + {c83289b3-1a90-4b54-9e7d-dd8c39ea69e8} + {1251483a-1f28-49ce-993f-cc8e026b1032} + + + + + + + + + + + + + {93e9e2ab-66ed-4673-9478-4e6be7de3a32} + + + {c489034f-fb95-43e4-a691-c0c8f81f6732} + {1251483a-1f28-49ce-993f-cc8e026b1032} + {c83289b3-1a90-4b54-9e7d-dd8c39ea69e8} + + + + + + + + + + + + + {77daf339-4128-48b5-9985-65b792190e58} + + + {8ee49c6b-0699-4760-8e3a-f666ff26497d} + {1251483a-1f28-49ce-993f-cc8e026b1032} + {128ad389-d81b-45eb-9540-dae42d8aebbb} + + + + + + + + + + + {7f001f20-53ab-4326-8fa7-f855205979ff} + + + Multiple Instances Allowed + x:835;y:260 + x:-345;y:-90;w:690;h:180 + + + + + + + + + + + {d8c54afe-8be5-420f-87d4-4dfbcc7c45fb} + + + {fe9ee5e9-bc98-448e-ac9c-ba5e04d63a2c} + {5e3887ac-4379-4760-b460-b0a0b165ee6a} + {d106a7a1-4a2a-4285-b817-f2fa75c14c3f} + + + + + + + + + + + + + {63bf51dc-13e3-406c-853f-8e41ab7cbe31} + + + {38f8f1bb-5261-4e8b-80ff-fb6e28d4ef34} + {5e3887ac-4379-4760-b460-b0a0b165ee6a} + {6374ef07-f681-45cc-b845-daa9648bed8f} + + + + + + + + + + + + + {017afa8f-f6f3-49a2-b9dc-739fe35077cf} + + + {90dc94b2-75c5-47f5-b7ef-e6c44a2acbe1} + Connection Grouping + x:695;y:415 + x:-80;y:-15;w:160;h:30 + false + 0 + + + false + + + + + + + + + + + {8897aaae-f42a-44f6-a1f0-096681218480} + + + {8cb24a6e-6cf6-4d83-8c0a-fe6a8ce0cfc0} + Rename, MoveGroup, Delete + x:695;y:445 + x:-80;y:-15;w:160;h:30 + false + 0 + + + false + + + + + + + + + + + {16f5dfda-2ad6-4411-a904-3df513c7053d} + + + {487746e4-62f9-4bee-915d-59e4adfc5313} + {d2304b1e-082c-4edb-87f5-b753a3c2ca32} + {5e3887ac-4379-4760-b460-b0a0b165ee6a} + + + + + + + + + + + + + {379c4ee3-bd11-4875-8bd2-142acbc0bf55} + + + {7042e2b8-4d2a-4a0a-97a1-b252784a9177} + {d2304b1e-082c-4edb-87f5-b753a3c2ca32} + {9cdb07b7-5f86-41c7-a9d5-f43396a58f28} + + + + + + + + + + + {b0cb11f7-c811-492b-932e-f6cf17949151} + + + MainWindow is just a UI + x:150;y:405 + x:0;y:0;w:134.984;h:30 + + + + + + + + + + + {24156d2d-1b74-472d-8802-af330d625f64} + + + {40672bb4-a325-4079-bc65-ac622e2fc129} + {5e3887ac-4379-4760-b460-b0a0b165ee6a} + {d2304b1e-082c-4edb-87f5-b753a3c2ca32} + + + + + + + + + + + {06aa7113-f904-488f-99aa-306c034ce990} + + + Logs, Stats + x:450;y:405 + x:0;y:0;w:67.8906;h:30 + + + + + + + + + + + {86b3afbe-bf4c-4863-b8a0-0d591c3ad319} + + + {219e4bda-9edc-466c-851a-c9ef4aa09c99} + {542fc889-55d8-4c98-ab40-757643783477} + {d106a7a1-4a2a-4285-b817-f2fa75c14c3f} + + + + + + + + + + + + + {8924dd9c-a9bd-4d05-965c-8f2eee6ce829} + + + {a01cf9cc-689d-4665-80f5-8249ed4c75c9} + {9cdb07b7-5f86-41c7-a9d5-f43396a58f28} + {fe42c651-f134-4968-8b3a-775487035f5a} + + + + + + + + + + + {7c4701bf-2778-4403-a768-3d409b02527c} + + + Calling UI + x:190;y:480 + x:0;y:0;w:63.375;h:30 + + + + + + + + + + + {2d08cb81-c09f-48a8-b11d-f01fa2f14f44} + + + {c2f03aa5-8b01-4b6b-b8e2-f629365d8ff6} + {9cdb07b7-5f86-41c7-a9d5-f43396a58f28} + {2fc66815-2b1d-4a33-b5ec-2abaff6cbfea} + + + + + + + + + + + + + {bbbce101-6be1-46cf-b9ac-7c97d9bd4a63} + + + {19f39c99-ee3c-4515-8d78-b15fa5b4c958} + {2fc66815-2b1d-4a33-b5ec-2abaff6cbfea} + {8897aaae-f42a-44f6-a1f0-096681218480} + + + + + + + + + + + + + {79e16c58-9f62-4885-b036-3d132f64d438} + + + {2c117206-e84b-4804-9580-311d5eea4c74} + {fe42c651-f134-4968-8b3a-775487035f5a} + {d2304b1e-082c-4edb-87f5-b753a3c2ca32} + + + + + + + + + + + {d425ba1d-decd-414e-b658-c13050e16620} + + + Calling UI + x:310;y:460 + x:0;y:0;w:63.375;h:30 + + + + + + + + + {a923f715-0031-4aa7-acac-545d5d3a40ff} + + + Save Connection +emit Reload Signal + x:290;y:595 + x:0;y:0;w:107.156;h:44 + + + + + + + + + + + {005d75d6-a751-450e-a24c-2b245995c0d7} + + + {b7fc0dad-353c-4976-aee6-a7fed8e7d84b} + {9cdb07b7-5f86-41c7-a9d5-f43396a58f28} + {d2304b1e-082c-4edb-87f5-b753a3c2ca32} + + + + + + + + + + + {cab9f230-723e-4970-988a-68332251c5c5} + + + Save Connection +emit Reload Signal + x:635;y:525 + x:0;y:0;w:107.156;h:44 + + + + + + + + + + + {c4ad0ced-7e74-4952-9ea2-75eae540d300} + + + {8bfff749-7ebd-47d7-aeed-33f2bdb041bc} + Start/Stop + x:585;y:235 + x:-70;y:-15;w:140;h:30 + false + 0 + + + false + + + + + + + + + + + {931d4405-3c3a-4065-9714-5fa1da88321b} + + + {8c615125-5163-473d-9c1f-c2485cb33423} + Subscription Manager + x:220;y:295 + x:-90;y:-30;w:180;h:60 + 0 + + + + + + + + + + + + + {3f407a1e-06f6-44ac-8c7f-6c30081791ed} + + + {1969c8f7-b021-4dbf-9dc9-f455ad96f690} + {9cdb07b7-5f86-41c7-a9d5-f43396a58f28} + {931d4405-3c3a-4065-9714-5fa1da88321b} + + + + + + + + + + + + + {2bf50f1f-8760-4b81-af8c-7bb3f70a4ea8} + + + {9aecd5c9-d511-4050-8791-ad686d0a9803} + {931d4405-3c3a-4065-9714-5fa1da88321b} + {d2304b1e-082c-4edb-87f5-b753a3c2ca32} + + + + + + + + + + + + + {9f7167ea-5a08-49e6-9c52-c23addc22b66} + + + {9cb865b0-5659-4c50-9781-7bf5f14317b2} + Import Window + x:695;y:690 + x:-75;y:-30;w:150;h:60 + false + 0 + + + + + + + + + + + + + {4013dabb-bd60-4159-b220-e151f3cb05a9} + + + {0646e4d1-324f-4a16-9e06-49c698fae274} + {9cdb07b7-5f86-41c7-a9d5-f43396a58f28} + {9f7167ea-5a08-49e6-9c52-c23addc22b66} + + + + + + + + + + + + + {4a3f484d-27ea-40e6-a0db-8418083ac30d} + + + {0857831e-9ee9-44e5-a9c0-4e183309e47a} + {9f7167ea-5a08-49e6-9c52-c23addc22b66} + {d2304b1e-082c-4edb-87f5-b753a3c2ca32} + + + + + + + + + + + + + {19d6bb21-70c0-4f30-9c5e-9c297baaf824} + + + {15d39bde-4eed-45b9-8b21-9e54b785656a} + Subscription Management + x:695;y:475 + x:-80;y:-15;w:160;h:30 + false + 0 + + + false + + + + + + + + + + + {e33ed197-062d-4142-84f4-87f76c7ac5a7} + + + {5723e540-6362-4a03-861e-b0dc85b2305c} + Final Config Generation + x:585;y:295 + x:-70;y:-15;w:140;h:30 + 0 + + + false + + + + + + + + + {e08bfec6-8ca5-45e9-8909-524ea035f730} + + + libqv2ray (just an abstraction, not to split) + x:600;y:355 + x:-205;y:-210;w:410;h:420 + + + + + + + + + {b370e8e2-a5ce-4ee8-91c7-5da5ce043699} + + + GUI Editors + x:460;y:685 + x:-345;y:-110;w:690;h:220 + + + + + + + + + + + {977d5436-740b-4e67-8789-11b266e0d037} + + + {68e6538a-4724-41cb-bd3a-cbbbc83a651a} + {9cdb07b7-5f86-41c7-a9d5-f43396a58f28} + {8897aaae-f42a-44f6-a1f0-096681218480} + + + + + + + + + + + {e71bd7e6-4fdd-4fe1-b887-f210c4382edb} + + + Grouping, renaming ping + x:395;y:440 + x:0;y:0;w:140.762;h:30 + false + + + + + + + + + + + {994e5753-eef9-4980-bd59-13951a44f73e} + + + {afdf8f1c-b8d5-4398-9ec9-614dbbca17c4} + Latency Testing + x:695;y:505 + x:-80;y:-15;w:160;h:30 + false + 0 + + + false + + + + + + + + + + + {d7343d7c-5c4f-4b05-b4d5-edaf9e3a39d9} + + + {1be8c6f3-6de7-4244-97aa-9cfd9b04b452} + Proxy Settings + x:585;y:265 + x:-70;y:-15;w:140;h:30 + false + 0 + + + false + + + + + + 1581683386156 + General + + + + + + + + + + {024fd01e-41da-48d6-ad7a-a42003f6f43c} + + + + + + + + {024fd01e-41da-48d6-ad7a-a42003f6f43c} + + + MainWindow + + + + + + + {2bf95785-db26-495f-a011-9f048fad10a1} + + + + + + + + {2bf95785-db26-495f-a011-9f048fad10a1} + + + {024fd01e-41da-48d6-ad7a-a42003f6f43c} + {8cb24a6e-6cf6-4d83-8c0a-fe6a8ce0cfc0} + + + + + + + + + + {a01cf9cc-689d-4665-80f5-8249ed4c75c9} + + + + + + + + {a01cf9cc-689d-4665-80f5-8249ed4c75c9} + + + {024fd01e-41da-48d6-ad7a-a42003f6f43c} + {332eb659-610e-4dda-a031-a8d4533ff654} + + + + + + + + + + {c2f03aa5-8b01-4b6b-b8e2-f629365d8ff6} + + + + + + + + {c2f03aa5-8b01-4b6b-b8e2-f629365d8ff6} + + + {024fd01e-41da-48d6-ad7a-a42003f6f43c} + {3e71f0fe-ef4f-4bda-be19-cdbc546d7748} + + + + + + + + + + {b7fc0dad-353c-4976-aee6-a7fed8e7d84b} + + + + + + + + {b7fc0dad-353c-4976-aee6-a7fed8e7d84b} + + + {024fd01e-41da-48d6-ad7a-a42003f6f43c} + {26a11a27-d179-4355-9273-e1fa54ef13e1} + + + + + + + + + + {1969c8f7-b021-4dbf-9dc9-f455ad96f690} + + + + + + + + {1969c8f7-b021-4dbf-9dc9-f455ad96f690} + + + {024fd01e-41da-48d6-ad7a-a42003f6f43c} + {8c615125-5163-473d-9c1f-c2485cb33423} + + + + + + + + + + {0646e4d1-324f-4a16-9e06-49c698fae274} + + + + + + + + {0646e4d1-324f-4a16-9e06-49c698fae274} + + + {024fd01e-41da-48d6-ad7a-a42003f6f43c} + {9cb865b0-5659-4c50-9781-7bf5f14317b2} + + + + + + + + + + {68e6538a-4724-41cb-bd3a-cbbbc83a651a} + + + + + + + + {68e6538a-4724-41cb-bd3a-cbbbc83a651a} + + + {024fd01e-41da-48d6-ad7a-a42003f6f43c} + {8cb24a6e-6cf6-4d83-8c0a-fe6a8ce0cfc0} + + + + + + + + + + + + + + + + + + + + + {332eb659-610e-4dda-a031-a8d4533ff654} + + + + + + + + {332eb659-610e-4dda-a031-a8d4533ff654} + + + Complex Editor + + + + + + + {5340a8a0-ad20-438c-83af-833d5d8fce40} + + + + + + + + {5340a8a0-ad20-438c-83af-833d5d8fce40} + + + {332eb659-610e-4dda-a031-a8d4533ff654} + {3e71f0fe-ef4f-4bda-be19-cdbc546d7748} + + + + + + + + + + {d510ad05-6490-42cf-bb73-66a80152c478} + + + + + + + + {d510ad05-6490-42cf-bb73-66a80152c478} + + + {332eb659-610e-4dda-a031-a8d4533ff654} + {96ce5d9a-03e7-4a98-a25a-0e9aff2ff6b4} + + + + + + + + + + {2c117206-e84b-4804-9580-311d5eea4c74} + + + + + + + + {2c117206-e84b-4804-9580-311d5eea4c74} + + + {332eb659-610e-4dda-a031-a8d4533ff654} + {26a11a27-d179-4355-9273-e1fa54ef13e1} + + + + + + + + + + + + + + + + + + + + + {3e71f0fe-ef4f-4bda-be19-cdbc546d7748} + + + + + + + + {3e71f0fe-ef4f-4bda-be19-cdbc546d7748} + + + Outbound Editor + + + + + + + {19f39c99-ee3c-4515-8d78-b15fa5b4c958} + + + + + + + + {19f39c99-ee3c-4515-8d78-b15fa5b4c958} + + + {3e71f0fe-ef4f-4bda-be19-cdbc546d7748} + {8cb24a6e-6cf6-4d83-8c0a-fe6a8ce0cfc0} + + + + + + + + + + + + + + + + + + + + + {96ce5d9a-03e7-4a98-a25a-0e9aff2ff6b4} + + + + + + + + {96ce5d9a-03e7-4a98-a25a-0e9aff2ff6b4} + + + Inbound Editor + + + + + + + + + + {26a11a27-d179-4355-9273-e1fa54ef13e1} + + + + + + + + {26a11a27-d179-4355-9273-e1fa54ef13e1} + + + Connection Handler + + + + + + + {487746e4-62f9-4bee-915d-59e4adfc5313} + + + + + + + + {487746e4-62f9-4bee-915d-59e4adfc5313} + + + {26a11a27-d179-4355-9273-e1fa54ef13e1} + {8caf1563-5c81-46eb-b0ac-64f745ca617a} + + + + + + + + + + {7042e2b8-4d2a-4a0a-97a1-b252784a9177} + + + + + + + + {7042e2b8-4d2a-4a0a-97a1-b252784a9177} + + + {26a11a27-d179-4355-9273-e1fa54ef13e1} + {024fd01e-41da-48d6-ad7a-a42003f6f43c} + + + + + + + + + + + + + + + + + + + + + {8caf1563-5c81-46eb-b0ac-64f745ca617a} + + + + + + + + {8caf1563-5c81-46eb-b0ac-64f745ca617a} + + + Instance Handler + + + + + + + {fe9ee5e9-bc98-448e-ac9c-ba5e04d63a2c} + + + + + + + + {fe9ee5e9-bc98-448e-ac9c-ba5e04d63a2c} + + + {8caf1563-5c81-46eb-b0ac-64f745ca617a} + {8e66ff8b-f122-4cbc-90d3-c823ab513c06} + + + + + + + + + + {38f8f1bb-5261-4e8b-80ff-fb6e28d4ef34} + + + + + + + + {38f8f1bb-5261-4e8b-80ff-fb6e28d4ef34} + + + {8caf1563-5c81-46eb-b0ac-64f745ca617a} + {7c2667ea-cc97-4418-91b6-430e18a77ce5} + + + + + + + + + + {40672bb4-a325-4079-bc65-ac622e2fc129} + + + + + + + + {40672bb4-a325-4079-bc65-ac622e2fc129} + + + {8caf1563-5c81-46eb-b0ac-64f745ca617a} + {26a11a27-d179-4355-9273-e1fa54ef13e1} + + + + + + + + + + + + + + + + + + + + + {8e66ff8b-f122-4cbc-90d3-c823ab513c06} + + + + + + + + {8e66ff8b-f122-4cbc-90d3-c823ab513c06} + + + VCore Instance + + + + + + + {c5c2659d-6f38-4949-9965-e32f2401d5db} + + + + + + + + {c5c2659d-6f38-4949-9965-e32f2401d5db} + + + {8e66ff8b-f122-4cbc-90d3-c823ab513c06} + {7c2667ea-cc97-4418-91b6-430e18a77ce5} + + + + + + + + + + + + + + + + + + + + + {7c2667ea-cc97-4418-91b6-430e18a77ce5} + + + + + + + + {7c2667ea-cc97-4418-91b6-430e18a77ce5} + + + API Subsystem + + + + + + + {a15d947a-8d8d-49aa-803f-d1c7c6a60ee1} + + + + + + + + {a15d947a-8d8d-49aa-803f-d1c7c6a60ee1} + + + {7c2667ea-cc97-4418-91b6-430e18a77ce5} + {8e66ff8b-f122-4cbc-90d3-c823ab513c06} + + + + + + + + + + {820260d5-8128-4c25-b4b4-406b326c7a10} + + + + + + + + {820260d5-8128-4c25-b4b4-406b326c7a10} + + + {7c2667ea-cc97-4418-91b6-430e18a77ce5} + {29039158-2c91-412a-a46b-5e99e713192f} + + + + + + + + + + {08967768-9ee2-4c54-af60-6062cd3d84cc} + + + + + + + + {08967768-9ee2-4c54-af60-6062cd3d84cc} + + + {7c2667ea-cc97-4418-91b6-430e18a77ce5} + {182d4943-e868-4a84-a0af-524b79f9a3f4} + + + + + + + + + + + + + + + + + + + + + {29039158-2c91-412a-a46b-5e99e713192f} + + + + + + + + {29039158-2c91-412a-a46b-5e99e713192f} + + + gRPC + + + + + + + {8b101bdc-747f-4b4f-afb4-34027f38ba1b} + + + + + + + + {8b101bdc-747f-4b4f-afb4-34027f38ba1b} + + + {29039158-2c91-412a-a46b-5e99e713192f} + {ed27c562-ee05-4562-8c40-495f1a0656fb} + + + + + + + + + + + + + + + + + + + + + {182d4943-e868-4a84-a0af-524b79f9a3f4} + + + + + + + + {182d4943-e868-4a84-a0af-524b79f9a3f4} + + + libqvb + + + + + + + + + + {11d29c88-d70f-4449-a4de-8e66479b9fa0} + + + + + + + + {11d29c88-d70f-4449-a4de-8e66479b9fa0} + + + VCore + + + + + + + {219e4bda-9edc-466c-851a-c9ef4aa09c99} + + + + + + + + {219e4bda-9edc-466c-851a-c9ef4aa09c99} + + + {11d29c88-d70f-4449-a4de-8e66479b9fa0} + {8e66ff8b-f122-4cbc-90d3-c823ab513c06} + + + + + + + + + + + + + + + + + + + + + {ed27c562-ee05-4562-8c40-495f1a0656fb} + + + + + + + + {ed27c562-ee05-4562-8c40-495f1a0656fb} + + + API Server + + + + + + + {18b95586-196e-44dc-8909-2cdccbeed443} + + + + + + + + {18b95586-196e-44dc-8909-2cdccbeed443} + + + {ed27c562-ee05-4562-8c40-495f1a0656fb} + {182d4943-e868-4a84-a0af-524b79f9a3f4} + + + + + + + + + + {c489034f-fb95-43e4-a691-c0c8f81f6732} + + + + + + + + {c489034f-fb95-43e4-a691-c0c8f81f6732} + + + {ed27c562-ee05-4562-8c40-495f1a0656fb} + {29039158-2c91-412a-a46b-5e99e713192f} + + + + + + + + + + {8ee49c6b-0699-4760-8e3a-f666ff26497d} + + + + + + + + {8ee49c6b-0699-4760-8e3a-f666ff26497d} + + + {ed27c562-ee05-4562-8c40-495f1a0656fb} + {182d4943-e868-4a84-a0af-524b79f9a3f4} + + + + + + + + + + + + + + + + + + + + + {90dc94b2-75c5-47f5-b7ef-e6c44a2acbe1} + + + + + + + + {90dc94b2-75c5-47f5-b7ef-e6c44a2acbe1} + + + Connection Grouping + + + + + + + + + + {8cb24a6e-6cf6-4d83-8c0a-fe6a8ce0cfc0} + + + + + + + + {8cb24a6e-6cf6-4d83-8c0a-fe6a8ce0cfc0} + + + Rename, MoveGroup, Delete + + + + + + + + + + {8bfff749-7ebd-47d7-aeed-33f2bdb041bc} + + + + + + + + {8bfff749-7ebd-47d7-aeed-33f2bdb041bc} + + + Start/Stop + + + + + + + + + + {8c615125-5163-473d-9c1f-c2485cb33423} + + + + + + + + {8c615125-5163-473d-9c1f-c2485cb33423} + + + Subscription Manager + + + + + + + {9aecd5c9-d511-4050-8791-ad686d0a9803} + + + + + + + + {9aecd5c9-d511-4050-8791-ad686d0a9803} + + + {8c615125-5163-473d-9c1f-c2485cb33423} + {26a11a27-d179-4355-9273-e1fa54ef13e1} + + + + + + + + + + + + + + + + + + + + + {9cb865b0-5659-4c50-9781-7bf5f14317b2} + + + + + + + + {9cb865b0-5659-4c50-9781-7bf5f14317b2} + + + Import Window + + + + + + + {0857831e-9ee9-44e5-a9c0-4e183309e47a} + + + + + + + + {0857831e-9ee9-44e5-a9c0-4e183309e47a} + + + {9cb865b0-5659-4c50-9781-7bf5f14317b2} + {26a11a27-d179-4355-9273-e1fa54ef13e1} + + + + + + + + + + + + + + + + + + + + + {15d39bde-4eed-45b9-8b21-9e54b785656a} + + + + + + + + {15d39bde-4eed-45b9-8b21-9e54b785656a} + + + Subscription Management + + + + + + + + + + {5723e540-6362-4a03-861e-b0dc85b2305c} + + + + + + + + {5723e540-6362-4a03-861e-b0dc85b2305c} + + + Final Config Generation + + + + + + + + + + {afdf8f1c-b8d5-4398-9ec9-614dbbca17c4} + + + + + + + + {afdf8f1c-b8d5-4398-9ec9-614dbbca17c4} + + + Latency Testing + + + + + + + + + + {1be8c6f3-6de7-4244-97aa-9cfd9b04b452} + + + + + + + + {1be8c6f3-6de7-4244-97aa-9cfd9b04b452} + + + Proxy Settings + + + + + + + + + + + + + + + + + + diff --git a/qv2ray.qmodel b/qv2ray.qmodel new file mode 100644 index 00000000..2cb9aa5c --- /dev/null +++ b/qv2ray.qmodel @@ -0,0 +1,2187 @@ + + + + {647facf6-b866-494f-8176-c4b0a4e270fa} + + + + + + + + {1fbb5f76-94d9-4a40-9ebe-a30cbbf63220} + + + Qv2ray + + + + + + + {5d758152-dfff-4d98-b146-4b6e36bdabce} + + + + + + + + + + {5d758152-dfff-4d98-b146-4b6e36bdabce} + + + Qv2ray Project + + + + + + + + + + {f6ee22ba-16b8-4eda-a555-6f07146a95bd} + + + Qv2ray Main Application + x:325;y:300 + x:-265;y:-250;w:530;h:500 + + + + + + + + + + + {65ccb664-7d23-49af-bd43-b64819db3edf} + + + {6ad7d3a9-980b-4204-8b05-4a95a2590142} + libqvb + x:680;y:290 + x:-35;y:-15;w:70;h:30 + false + 0 + + + false + + + + + + + + + {7c54c0a5-fe32-4d79-a5a3-34271c3e546e} + + + Qv2ray Main Application + x:325;y:300 + x:-265;y:-250;w:530;h:500 + + + + + + + + + + + {f981796c-f7b4-4e18-91a2-3420666256fb} + + + {3064dafb-dd8a-42ea-ab52-28969e928093} + gRPC + x:680;y:320 + x:-35;y:-15;w:70;h:30 + false + 0 + + + false + + + + + + + + + {3092ef19-9acc-4e9f-8218-45815f844cde} + + + V2ray Core + + x:850;y:220 + x:-60;y:-50;w:120;h:100 + + + + + + + + + + + {714b823e-b623-4996-ac32-85a2c4c9d573} + + + {da0b94e2-e659-42ab-b277-0e0f99bc1ad4} + API Server + x:850;y:245 + x:-35;y:-15;w:70;h:30 + 6 + + + false + + + + + + + + + + + {c1148a34-5ee5-40b7-82bb-4443257b5889} + + + {0e260e3d-f985-4f8f-8c75-f231168f699a} + {65ccb664-7d23-49af-bd43-b64819db3edf} + {714b823e-b623-4996-ac32-85a2c4c9d573} + + + + + + + + + + + + + {f25ff544-a77c-473e-8add-3daa66baf3e7} + + + {6d4a24b8-ae09-4098-879f-fec552683813} + {f981796c-f7b4-4e18-91a2-3420666256fb} + {714b823e-b623-4996-ac32-85a2c4c9d573} + + + + + + + + + + + {67f7174e-a17f-42f7-a4d4-ae8e941cfe66} + + + API Backends + x:685;y:295 + x:-55;y:-50;w:110;h:100 + + + + + + + + + + + {7f5df3c3-1620-4246-85be-c826bbcf2b14} + + + {4cc4f787-2b0d-44f1-836f-504127f4be9f} + VCore Instance + x:505;y:215 + x:-65;y:-20;w:130;h:40 + false + 0 + + + false + + + + + + + + + + + {a88cf4c8-f373-4541-8ced-45bd090701b1} + + + {c8d7e622-29ff-46e7-8c79-fa1dd14cdf0d} + API Subsystem + x:515;y:275 + x:-45;y:-15;w:90;h:30 + 0 + + + false + + + + + + + + + + + {cd59252c-e0bb-481e-8af2-b2837d7a1281} + + + {67fccf14-dd98-41c2-862e-f8b4e11f8567} + {a88cf4c8-f373-4541-8ced-45bd090701b1} + {65ccb664-7d23-49af-bd43-b64819db3edf} + + + + + + + + + + + + + {6a6ce171-6c13-448b-be4e-9d161cfd72b9} + + + {2af676c9-410f-421d-849d-b5845e81ab88} + {a88cf4c8-f373-4541-8ced-45bd090701b1} + {f981796c-f7b4-4e18-91a2-3420666256fb} + + + + + + + + + + + + + {0649f129-c137-4abd-9d23-b203f5bbd9c4} + + + {114dbf85-856e-4407-8b13-4904fa6c1647} + {7f5df3c3-1620-4246-85be-c826bbcf2b14} + {a88cf4c8-f373-4541-8ced-45bd090701b1} + + + + + + + + + + + + + {9d5d8698-1d97-4e9d-80bf-b582d5b1cde8} + + + {7c1da3e6-c685-48ed-9004-11d84a986eb3} + V2ray Core + x:850;y:210 + x:-35;y:-15;w:70;h:30 + 6 + + + false + + + + + + + + + + + {a0434b2e-35db-4d44-9a1e-eb5ac1f01ec6} + + + {8a32d7cb-3a75-405e-b24d-ff396f753682} + {7f5df3c3-1620-4246-85be-c826bbcf2b14} + {9d5d8698-1d97-4e9d-80bf-b582d5b1cde8} + + + + + + + + + + + + + {c3bd399e-a413-442c-af8e-d3ab73d73d14} + + + {1f93aa2e-b153-4e2f-b5fe-1fee96683b26} + {9d5d8698-1d97-4e9d-80bf-b582d5b1cde8} + {7f5df3c3-1620-4246-85be-c826bbcf2b14} + + + + + + + + + + + + + {331a0c67-72ba-44b1-92a5-c7a4043899ed} + + + {4cec28d7-c858-4a4c-bedf-10ec969c756b} + MainWindow + x:255;y:160 + x:-125;y:-75;w:250;h:150 + false + 0 + + + + + + + + + + + + + {ae9dec4f-1083-46d6-818c-23631ba67051} + + + {f3687dc7-5ce8-4bc4-aa73-bf330d37704f} + {65ccb664-7d23-49af-bd43-b64819db3edf} + {a88cf4c8-f373-4541-8ced-45bd090701b1} + + + + + + + + + + + + + {f3d6a1b9-21e3-490d-8b20-b06251dd8025} + + + {c7ce52aa-d1a4-427e-b804-2336af2135a0} + {f981796c-f7b4-4e18-91a2-3420666256fb} + {a88cf4c8-f373-4541-8ced-45bd090701b1} + + + + + + + + + + + + + {f95573af-ee08-4d4f-b651-fed454722cda} + + + {aa5ac575-c065-46e6-b027-abdd5362f822} + {a88cf4c8-f373-4541-8ced-45bd090701b1} + {7f5df3c3-1620-4246-85be-c826bbcf2b14} + + + + + + + + + + + + + {f5787892-5c13-4382-8b12-830bee191e2f} + + + {eac2202d-ea45-45d5-951f-84aaf5838477} + Complex Editor + x:475;y:385 + x:-80;y:-55;w:160;h:110 + false + 0 + + + + + + + + + + + + + {bf367d5b-c6a4-4d65-bf27-0aedbf745494} + + + {10da184e-1f18-419b-a568-f84d0b8cb5b9} + Outbound Editor + x:240;y:500 + x:-75;y:-30;w:150;h:60 + 0 + + + + + + + + + + + + + {7bb4a1cc-0818-41f0-9480-e6e7d7d587dd} + + + {29d0c915-7299-446a-9f31-47a415b72019} + {331a0c67-72ba-44b1-92a5-c7a4043899ed} + {f5787892-5c13-4382-8b12-830bee191e2f} + + + + + + + + + + + + + {a5a017fe-7797-4654-b65b-02c5036117c5} + + + {f8596457-a8fd-4704-be31-7a58fe73141e} + {331a0c67-72ba-44b1-92a5-c7a4043899ed} + {bf367d5b-c6a4-4d65-bf27-0aedbf745494} + + + + + + + + + + + + + {504cc120-a770-4515-b6a9-394e4340a1d9} + + + {808b0c79-8a40-47d5-a8a9-842996c693f9} + {331a0c67-72ba-44b1-92a5-c7a4043899ed} + {7f5df3c3-1620-4246-85be-c826bbcf2b14} + + + + + + + + + + + + + {6e96a8bc-636f-4868-89a3-4b4535c31fbd} + + + {1554c3b4-07db-4396-8c69-f26102588dea} + {7f5df3c3-1620-4246-85be-c826bbcf2b14} + {331a0c67-72ba-44b1-92a5-c7a4043899ed} + + + + + + + + + + + + + {d475b70d-5c35-48ef-9e12-8e6074cef0b6} + + + {ea524fac-ec83-443a-981f-88fbe66738eb} + Inbound Editor + x:480;y:505 + x:-70;y:-30;w:140;h:60 + 0 + + + + + + + + + + + + + {8cad2b46-4c39-4ec5-addd-217c62cb334c} + + + {90bd5fdc-fb41-41a5-b699-ccdc38fcece9} + Import Window + x:150;y:400 + x:-70;y:-30;w:140;h:60 + 0 + + + + + + + + + + + + + {8f70c3f7-a8b7-42e4-917a-0fcb990c2887} + + + {182461ab-c66a-4375-8951-42ccd00b952d} + Read all connection + x:260;y:130 + x:-80;y:-15;w:160;h:30 + false + 0 + + + false + + + + + + + + + + + {9ec67e74-cd1d-4513-82e5-4e26aacd9cb2} + + + {6bf9198f-a72d-4627-b328-958f4e281149} + Rename, Copy, Import + x:260;y:170 + x:-80;y:-15;w:160;h:30 + false + 0 + + + false + + + + + + + + + + + {86df7aba-f62e-4d76-8970-4f004a1f8907} + + + {d94c84f3-2476-48f6-8aad-7804e38f6104} + Import Outbound + x:485;y:380 + x:-55;y:-15;w:110;h:30 + false + 0 + + + false + + + + + + + + + + + {d61c0e9f-5de2-41a4-a06d-590ca99be67e} + + + {c780f06b-ad7a-416a-9d5b-bfe560eb647a} + Import Inbound + x:485;y:415 + x:-55;y:-15;w:110;h:30 + false + 0 + + + false + + + + + + + + + + + {72cb5a68-b5ea-4304-ad85-de172266f932} + + + {024bcb44-2f51-4cce-85b1-41ca426840a7} + {86df7aba-f62e-4d76-8970-4f004a1f8907} + {bf367d5b-c6a4-4d65-bf27-0aedbf745494} + + + + + + + + + + + + + {4ab10295-4c1e-43de-b1ce-2ac3523095ae} + + + {62162518-233b-49c2-8eda-b839ebdc83e8} + {d61c0e9f-5de2-41a4-a06d-590ca99be67e} + {d475b70d-5c35-48ef-9e12-8e6074cef0b6} + + + + + + + + + + + + + {11295256-e0d3-43f1-a260-289efe9329e7} + + + {7c6a365e-16ca-4b36-946c-77274c0b387e} + {86df7aba-f62e-4d76-8970-4f004a1f8907} + {8cad2b46-4c39-4ec5-addd-217c62cb334c} + + + + + + + + + + + + + {08adb605-58ee-40db-8301-8eea4e9e8ff3} + + + {48a68af3-e668-4208-88d3-23de250b4935} + {9ec67e74-cd1d-4513-82e5-4e26aacd9cb2} + {8cad2b46-4c39-4ec5-addd-217c62cb334c} + + + + + + + + + + + + + {944c6346-47de-42c3-869e-602ae07d4083} + + + {ca9bbb33-692c-402e-9092-98347ceaa086} + Edit Outbound + x:245;y:510 + x:-45;y:-15;w:90;h:30 + 0 + + + false + + + + + + + + + + + {625d91d4-0676-4edf-b9db-b4652c21317c} + + + {ece50c7a-9c7b-4467-897e-0b91ee01808e} + Edit Inbound + x:485;y:515 + x:-40;y:-15;w:80;h:30 + 0 + + + false + + + + + + + + + + + {b20999ed-2456-4141-9f72-9b7d1cff0a71} + + + {9c702aa5-f4dd-4cca-b75a-61cfc4b72092} + Import Connection + x:160;y:410 + x:-55;y:-15;w:110;h:30 + 0 + + + false + + + + + + + + + + + {e1383713-b639-4f22-92c2-feb4f79ae366} + + + {65a02863-854a-47e8-a273-f1a20800c56f} + Subscriptions + x:505;y:120 + x:-65;y:-55;w:130;h:110 + false + 0 + + + + + + + + + + + + + {71e1d74b-205d-41ce-a52b-3284af59b433} + + + {a7893f71-d00a-4e44-b8c9-c73ea5557aea} + Subscription Manager + x:260;y:210 + x:-80;y:-15;w:160;h:30 + false + 0 + + + false + + + + + + + + + + + {ddd689b7-94ac-42b3-9df4-4ec503c9b853} + + + {80fece9b-8ca1-46b9-af3a-a56205ee65bc} + {71e1d74b-205d-41ce-a52b-3284af59b433} + {e1383713-b639-4f22-92c2-feb4f79ae366} + + + + + + + + + + + + + {ae132a61-7bf0-46cf-8ee9-d5d8f31f9f00} + + + {d85d7210-8d4d-4c0a-953d-c6000e8c0da0} + Edit + x:505;y:105 + x:-30;y:-15;w:60;h:30 + false + 0 + + + false + + + + + + + + + + + {630cd69b-530e-4db7-81d9-39dc93f47dc6} + + + {d8c611fa-860a-4b15-b7f2-d646d68e7753} + Update + x:505;y:140 + x:-30;y:-15;w:60;h:30 + 0 + + + false + + + + + + + + + {80ac5d0a-cacb-41a5-8512-941d9f049dee} + + + Logs + x:655;y:190 + x:0;y:0;w:38.375;h:30 + + + + + + + + + {b82f4d3e-625f-48e2-91ee-fc242f3702b8} + + + API Data + x:750;y:285 + x:0;y:0;w:58.4531;h:30 + + + + + + + + + {15510e86-df0f-424b-ba8d-f5ea49d6fe26} + + + Logs + x:395;y:170 + x:0;y:0;w:38.375;h:30 + + + + + + 1581681873740 + General + + + + + + + + + + {6ad7d3a9-980b-4204-8b05-4a95a2590142} + + + + + + + + {6ad7d3a9-980b-4204-8b05-4a95a2590142} + + + libqvb + + + + + + + {0e260e3d-f985-4f8f-8c75-f231168f699a} + + + + + + + + {0e260e3d-f985-4f8f-8c75-f231168f699a} + + + {6ad7d3a9-980b-4204-8b05-4a95a2590142} + {da0b94e2-e659-42ab-b277-0e0f99bc1ad4} + + + + + + + + + + {f3687dc7-5ce8-4bc4-aa73-bf330d37704f} + + + + + + + + {f3687dc7-5ce8-4bc4-aa73-bf330d37704f} + + + {6ad7d3a9-980b-4204-8b05-4a95a2590142} + {c8d7e622-29ff-46e7-8c79-fa1dd14cdf0d} + + + + + + + + + + + + + + + + + + + + + {3064dafb-dd8a-42ea-ab52-28969e928093} + + + + + + + + {3064dafb-dd8a-42ea-ab52-28969e928093} + + + gRPC + + + + + + + {6d4a24b8-ae09-4098-879f-fec552683813} + + + + + + + + {6d4a24b8-ae09-4098-879f-fec552683813} + + + {3064dafb-dd8a-42ea-ab52-28969e928093} + {da0b94e2-e659-42ab-b277-0e0f99bc1ad4} + + + + + + + + + + {c7ce52aa-d1a4-427e-b804-2336af2135a0} + + + + + + + + {c7ce52aa-d1a4-427e-b804-2336af2135a0} + + + {3064dafb-dd8a-42ea-ab52-28969e928093} + {c8d7e622-29ff-46e7-8c79-fa1dd14cdf0d} + + + + + + + + + + + + + + + + + + + + + {da0b94e2-e659-42ab-b277-0e0f99bc1ad4} + + + + + + + + {da0b94e2-e659-42ab-b277-0e0f99bc1ad4} + + + API Server + + + + + + + + + + {2307c1f4-c5a9-468c-ac8e-b133f405dacb} + + + + + + + + {2307c1f4-c5a9-468c-ac8e-b133f405dacb} + + + API Subsystem + + + + + + + + + + {9bbe1038-6d75-4735-95bd-20ac2e67e8ec} + + + + + + + + {9bbe1038-6d75-4735-95bd-20ac2e67e8ec} + + + VCore Handler + + + + + + + + + + {4cc4f787-2b0d-44f1-836f-504127f4be9f} + + + + + + + + {4cc4f787-2b0d-44f1-836f-504127f4be9f} + + + VCore Instance + + + + + + + {5968bca0-f1af-4d41-a7d3-2df1ed5b44ec} + + + + + + + + {5968bca0-f1af-4d41-a7d3-2df1ed5b44ec} + + + {4cc4f787-2b0d-44f1-836f-504127f4be9f} + {2307c1f4-c5a9-468c-ac8e-b133f405dacb} + + + + + + + + + + {ebb1f404-55c2-4a30-8a36-a5e4b63b5954} + + + + + + + + {ebb1f404-55c2-4a30-8a36-a5e4b63b5954} + + + {4cc4f787-2b0d-44f1-836f-504127f4be9f} + {6ad7d3a9-980b-4204-8b05-4a95a2590142} + + + + + + + + + + {a6f3bd91-9468-4db7-a066-29fd843ef58b} + + + + + + + + {a6f3bd91-9468-4db7-a066-29fd843ef58b} + + + {4cc4f787-2b0d-44f1-836f-504127f4be9f} + {3064dafb-dd8a-42ea-ab52-28969e928093} + + + + + + + + + + {57123e36-f47f-4d9a-a471-2ef175c024b7} + + + + + + + + {57123e36-f47f-4d9a-a471-2ef175c024b7} + + + {4cc4f787-2b0d-44f1-836f-504127f4be9f} + {2307c1f4-c5a9-468c-ac8e-b133f405dacb} + + + + + + + + + + {114dbf85-856e-4407-8b13-4904fa6c1647} + + + + + + + + {114dbf85-856e-4407-8b13-4904fa6c1647} + + + {4cc4f787-2b0d-44f1-836f-504127f4be9f} + {c8d7e622-29ff-46e7-8c79-fa1dd14cdf0d} + + + + + + + + + + {8a32d7cb-3a75-405e-b24d-ff396f753682} + + + + + + + + {8a32d7cb-3a75-405e-b24d-ff396f753682} + + + {4cc4f787-2b0d-44f1-836f-504127f4be9f} + {7c1da3e6-c685-48ed-9004-11d84a986eb3} + + + + + + + + + + {1554c3b4-07db-4396-8c69-f26102588dea} + + + + + + + + {1554c3b4-07db-4396-8c69-f26102588dea} + + + {4cc4f787-2b0d-44f1-836f-504127f4be9f} + {4cec28d7-c858-4a4c-bedf-10ec969c756b} + + + + + + + + + + + + + + + + + + + + + {c8d7e622-29ff-46e7-8c79-fa1dd14cdf0d} + + + + + + + + {c8d7e622-29ff-46e7-8c79-fa1dd14cdf0d} + + + API Subsystem + + + + + + + {67fccf14-dd98-41c2-862e-f8b4e11f8567} + + + + + + + + {67fccf14-dd98-41c2-862e-f8b4e11f8567} + + + {c8d7e622-29ff-46e7-8c79-fa1dd14cdf0d} + {6ad7d3a9-980b-4204-8b05-4a95a2590142} + + + + + + + + + + {2af676c9-410f-421d-849d-b5845e81ab88} + + + + + + + + {2af676c9-410f-421d-849d-b5845e81ab88} + + + {c8d7e622-29ff-46e7-8c79-fa1dd14cdf0d} + {3064dafb-dd8a-42ea-ab52-28969e928093} + + + + + + + + + + {aa5ac575-c065-46e6-b027-abdd5362f822} + + + + + + + + {aa5ac575-c065-46e6-b027-abdd5362f822} + + + {c8d7e622-29ff-46e7-8c79-fa1dd14cdf0d} + {4cc4f787-2b0d-44f1-836f-504127f4be9f} + + + + + + + + + + + + + + + + + + + + + {7c1da3e6-c685-48ed-9004-11d84a986eb3} + + + + + + + + {7c1da3e6-c685-48ed-9004-11d84a986eb3} + + + V2ray Core + + + + + + + {1f93aa2e-b153-4e2f-b5fe-1fee96683b26} + + + + + + + + {1f93aa2e-b153-4e2f-b5fe-1fee96683b26} + + + {7c1da3e6-c685-48ed-9004-11d84a986eb3} + {4cc4f787-2b0d-44f1-836f-504127f4be9f} + + + + + + + + + + + + + + + + + + + + + {4cec28d7-c858-4a4c-bedf-10ec969c756b} + + + + + + + + {4cec28d7-c858-4a4c-bedf-10ec969c756b} + + + MainWindow + + + + + + + {29d0c915-7299-446a-9f31-47a415b72019} + + + + + + + + {29d0c915-7299-446a-9f31-47a415b72019} + + + {4cec28d7-c858-4a4c-bedf-10ec969c756b} + {eac2202d-ea45-45d5-951f-84aaf5838477} + + + + + + + + + + {f8596457-a8fd-4704-be31-7a58fe73141e} + + + + + + + + {f8596457-a8fd-4704-be31-7a58fe73141e} + + + {4cec28d7-c858-4a4c-bedf-10ec969c756b} + {10da184e-1f18-419b-a568-f84d0b8cb5b9} + + + + + + + + + + {808b0c79-8a40-47d5-a8a9-842996c693f9} + + + + + + + + {808b0c79-8a40-47d5-a8a9-842996c693f9} + + + {4cec28d7-c858-4a4c-bedf-10ec969c756b} + {4cc4f787-2b0d-44f1-836f-504127f4be9f} + + + + + + + + + + {b65a2ae4-3841-4f62-91f2-c30c1c22d02d} + + + + + + + + {b65a2ae4-3841-4f62-91f2-c30c1c22d02d} + + + {4cec28d7-c858-4a4c-bedf-10ec969c756b} + {90bd5fdc-fb41-41a5-b699-ccdc38fcece9} + + + + + + + + + + + + + + + + + + + + + {eac2202d-ea45-45d5-951f-84aaf5838477} + + + + + + + + {eac2202d-ea45-45d5-951f-84aaf5838477} + + + Complex Editor + + + + + + + {62e0375b-dce4-45f1-bd40-626c6581d76a} + + + + + + + + {62e0375b-dce4-45f1-bd40-626c6581d76a} + + + {eac2202d-ea45-45d5-951f-84aaf5838477} + {ea524fac-ec83-443a-981f-88fbe66738eb} + + + + + + + + + + {e1dda574-c583-4530-90dd-d7f56bf30b5b} + + + + + + + + {e1dda574-c583-4530-90dd-d7f56bf30b5b} + + + {eac2202d-ea45-45d5-951f-84aaf5838477} + {10da184e-1f18-419b-a568-f84d0b8cb5b9} + + + + + + + + + + {59e3e836-4cb4-4d9a-a935-4b9a104ad95e} + + + + + + + + {59e3e836-4cb4-4d9a-a935-4b9a104ad95e} + + + {eac2202d-ea45-45d5-951f-84aaf5838477} + {90bd5fdc-fb41-41a5-b699-ccdc38fcece9} + + + + + + + + + + + + + + + + + + + + + {10da184e-1f18-419b-a568-f84d0b8cb5b9} + + + + + + + + {10da184e-1f18-419b-a568-f84d0b8cb5b9} + + + Outbound Editor + + + + + + + + + + {ea524fac-ec83-443a-981f-88fbe66738eb} + + + + + + + + {ea524fac-ec83-443a-981f-88fbe66738eb} + + + Inbound Editor + + + + + + + + + + {90bd5fdc-fb41-41a5-b699-ccdc38fcece9} + + + + + + + + {90bd5fdc-fb41-41a5-b699-ccdc38fcece9} + + + Import Window + + + + + + + {9db8d768-66f7-4829-9ccd-ae4e6a5cdf76} + + + + + + + + {9db8d768-66f7-4829-9ccd-ae4e6a5cdf76} + + + {90bd5fdc-fb41-41a5-b699-ccdc38fcece9} + {eac2202d-ea45-45d5-951f-84aaf5838477} + + + + + + + + + + + + + + + + + + + + + {182461ab-c66a-4375-8951-42ccd00b952d} + + + + + + + + {182461ab-c66a-4375-8951-42ccd00b952d} + + + Read all connection + + + + + + + + + + {6bf9198f-a72d-4627-b328-958f4e281149} + + + + + + + + {6bf9198f-a72d-4627-b328-958f4e281149} + + + Rename, Copy, Import + + + + + + + {48a68af3-e668-4208-88d3-23de250b4935} + + + + + + + + {48a68af3-e668-4208-88d3-23de250b4935} + + + {6bf9198f-a72d-4627-b328-958f4e281149} + {90bd5fdc-fb41-41a5-b699-ccdc38fcece9} + + + + + + + + + + + + + + + + + + + + + {d94c84f3-2476-48f6-8aad-7804e38f6104} + + + + + + + + {d94c84f3-2476-48f6-8aad-7804e38f6104} + + + Import Outbound + + + + + + + {024bcb44-2f51-4cce-85b1-41ca426840a7} + + + + + + + + {024bcb44-2f51-4cce-85b1-41ca426840a7} + + + {d94c84f3-2476-48f6-8aad-7804e38f6104} + {10da184e-1f18-419b-a568-f84d0b8cb5b9} + + + + + + + + + + {7c6a365e-16ca-4b36-946c-77274c0b387e} + + + + + + + + {7c6a365e-16ca-4b36-946c-77274c0b387e} + + + {d94c84f3-2476-48f6-8aad-7804e38f6104} + {90bd5fdc-fb41-41a5-b699-ccdc38fcece9} + + + + + + + + + + + + + + + + + + + + + {c780f06b-ad7a-416a-9d5b-bfe560eb647a} + + + + + + + + {c780f06b-ad7a-416a-9d5b-bfe560eb647a} + + + Import Inbound + + + + + + + {62162518-233b-49c2-8eda-b839ebdc83e8} + + + + + + + + {62162518-233b-49c2-8eda-b839ebdc83e8} + + + {c780f06b-ad7a-416a-9d5b-bfe560eb647a} + {ea524fac-ec83-443a-981f-88fbe66738eb} + + + + + + + + + + + + + + + + + + + + + {ca9bbb33-692c-402e-9092-98347ceaa086} + + + + + + + + {ca9bbb33-692c-402e-9092-98347ceaa086} + + + Edit Outbound + + + + + + + + + + {ece50c7a-9c7b-4467-897e-0b91ee01808e} + + + + + + + + {ece50c7a-9c7b-4467-897e-0b91ee01808e} + + + Edit Inbound + + + + + + + + + + {9c702aa5-f4dd-4cca-b75a-61cfc4b72092} + + + + + + + + {9c702aa5-f4dd-4cca-b75a-61cfc4b72092} + + + Import Connection + + + + + + + + + + {65a02863-854a-47e8-a273-f1a20800c56f} + + + + + + + + {65a02863-854a-47e8-a273-f1a20800c56f} + + + Subscriptions + + + + + + + + + + {a7893f71-d00a-4e44-b8c9-c73ea5557aea} + + + + + + + + {a7893f71-d00a-4e44-b8c9-c73ea5557aea} + + + Subscription Manager + + + + + + + {80fece9b-8ca1-46b9-af3a-a56205ee65bc} + + + + + + + + {80fece9b-8ca1-46b9-af3a-a56205ee65bc} + + + {a7893f71-d00a-4e44-b8c9-c73ea5557aea} + {65a02863-854a-47e8-a273-f1a20800c56f} + + + + + + + + + + + + + + + + + + + + + {d85d7210-8d4d-4c0a-953d-c6000e8c0da0} + + + + + + + + {d85d7210-8d4d-4c0a-953d-c6000e8c0da0} + + + Edit + + + + + + + + + + {d8c611fa-860a-4b15-b7f2-d646d68e7753} + + + + + + + + {d8c611fa-860a-4b15-b7f2-d646d68e7753} + + + Update + + + + + + + + + + + + + + + + + . + + From 2f716a9a443b71ddb96aaab081de73c0095cb637 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 14 Feb 2020 23:34:09 +0800 Subject: [PATCH 005/332] wip: we commented everything out just to make the build pass, added ConfigUpgrader --- Qv2ray.pro | 10 +- makespec/BUILDVERSION | 2 +- src/base/GlobalInstances.hpp | 5 - src/base/Qv2rayBase.hpp | 8 +- src/base/Qv2rayLog.cpp | 2 +- src/base/models/QvConfigIdentifier.hpp | 78 +- src/base/models/QvConfigModel.hpp | 307 ++--- src/base/models/QvSafeType.hpp | 13 +- src/common/QvHelpers.hpp | 5 + src/components/tcping/QvTCPing.cpp | 2 +- src/components/tcping/QvTCPing.hpp | 4 +- src/core/config/ConfigUpgrade.cpp | 138 +- src/core/handler/ConnectionHandler.hpp | 29 +- src/core/kernel/APIBackend.cpp | 6 +- src/core/kernel/APIBackend.hpp | 4 +- src/core/kernel/KernelInteractions.cpp | 23 +- src/core/kernel/KernelInteractions.hpp | 26 +- src/ui/editors/w_RoutesEditor.cpp | 6 +- src/ui/models/ConnectionTreeModel.cpp | 0 src/ui/models/ConnectionTreeModel.hpp | 0 .../InboundNodeModel.cpp | 0 .../InboundNodeModel.hpp | 2 +- .../{nodemodels => models}/NodeModelsBase.hpp | 0 .../OutboundNodeModel.cpp | 0 .../OutboundNodeModel.hpp | 2 +- .../{nodemodels => models}/RuleNodeModel.cpp | 0 .../{nodemodels => models}/RuleNodeModel.hpp | 2 +- src/ui/w_ExportConfig.cpp | 6 +- src/ui/w_ExportConfig.hpp | 2 +- src/ui/w_MainWindow.cpp | 1193 ++++++++--------- src/ui/w_MainWindow.hpp | 16 +- src/ui/w_MainWindow_extra.cpp | 214 +-- src/ui/w_PreferencesWindow.cpp | 60 +- src/ui/w_SubscriptionManager.cpp | 27 +- src/ui/w_SubscriptionManager.hpp | 4 +- src/ui/widgets/ConnectionWidget.cpp | 4 +- 36 files changed, 1089 insertions(+), 1111 deletions(-) create mode 100644 src/ui/models/ConnectionTreeModel.cpp create mode 100644 src/ui/models/ConnectionTreeModel.hpp rename src/ui/{nodemodels => models}/InboundNodeModel.cpp (100%) rename src/ui/{nodemodels => models}/InboundNodeModel.hpp (97%) rename src/ui/{nodemodels => models}/NodeModelsBase.hpp (100%) rename src/ui/{nodemodels => models}/OutboundNodeModel.cpp (100%) rename src/ui/{nodemodels => models}/OutboundNodeModel.hpp (97%) rename src/ui/{nodemodels => models}/RuleNodeModel.cpp (100%) rename src/ui/{nodemodels => models}/RuleNodeModel.hpp (98%) diff --git a/Qv2ray.pro b/Qv2ray.pro index a7b2484c..38f8e12d 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -94,10 +94,11 @@ Qv2rayAddSource(ui, editors, w_JsonEditor, cpp, hpp, ui) Qv2rayAddSource(ui, editors, w_OutboundEditor, cpp, hpp, ui) Qv2rayAddSource(ui, editors, w_RoutesEditor, cpp, hpp, ui) Qv2rayAddSource(ui, editors, w_RoutesEditor_extra, cpp) -Qv2rayAddSource(ui, nodemodels, InboundNodeModel, cpp, hpp) -Qv2rayAddSource(ui, nodemodels, OutboundNodeModel, cpp, hpp) -Qv2rayAddSource(ui, nodemodels, RuleNodeModel, cpp, hpp) -Qv2rayAddSource(ui, nodemodels, NodeModelsBase, hpp) +Qv2rayAddSource(ui, models, InboundNodeModel, cpp, hpp) +Qv2rayAddSource(ui, models, OutboundNodeModel, cpp, hpp) +Qv2rayAddSource(ui, models, RuleNodeModel, cpp, hpp) +Qv2rayAddSource(ui, models, NodeModelsBase, hpp) +Qv2rayAddSource(ui, models, ConnectionTreeModel, cpp, hpp) Qv2rayAddSource(ui, messaging, QvMessageBus, cpp, hpp) Qv2rayAddSource(ui, _, w_ExportConfig, cpp, hpp, ui) Qv2rayAddSource(ui, _, w_ImportConfig, cpp, hpp, ui) @@ -106,6 +107,7 @@ Qv2rayAddSource(ui, _, w_MainWindow_extra, cpp) Qv2rayAddSource(ui, _, w_PreferencesWindow, cpp, hpp, ui) Qv2rayAddSource(ui, _, w_ScreenShot_Core, cpp, hpp, ui) Qv2rayAddSource(ui, _, w_SubscriptionManager, cpp, hpp, ui) +Qv2rayAddSource(ui, widgets, ConnectionWidget, cpp, hpp, ui) Qv2rayAddSource(ui, widgets, StreamSettingsWidget, cpp, hpp, ui) SOURCES += $$PWD/src/main.cpp diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 7f5b8d72..fb97fa29 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3863 +3864 diff --git a/src/base/GlobalInstances.hpp b/src/base/GlobalInstances.hpp index e58a0d24..494e3b93 100644 --- a/src/base/GlobalInstances.hpp +++ b/src/base/GlobalInstances.hpp @@ -7,11 +7,6 @@ #include // Instantiation for Qv2ray global objects. -#ifdef QT_DEBUG -const bool isDebugBuild = true; -#else -const bool isDebugBuild = false; -#endif namespace Qv2ray { diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index ce284b1d..5940b380 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -44,7 +44,12 @@ using namespace Qv2ray::base::objects::transfer; #define QV2RAY_BUILD_INFO QString(_QV2RAY_BUILD_INFO_STR_) #define QV2RAY_BUILD_EXTRA_INFO QString(_QV2RAY_BUILD_EXTRA_INFO_STR_) -extern const bool isDebugBuild; +#ifdef QT_DEBUG +inline const bool isDebugBuild = true; +#else +inline const bool isDebugBuild = false; +#endif + // Base folder suffix. #ifdef QT_DEBUG # define QV2RAY_CONFIG_DIR_SUFFIX "_debug/" @@ -107,7 +112,6 @@ extern const bool isDebugBuild; #define QSTRN(num) QString::number(num) - #define OUTBOUND_TAG_DIRECT "outBound_DIRECT" #define OUTBOUND_TAG_PROXY "outBound_PROXY" #define OUTBOUND_TAG_FORWARD_PROXY "_QV2RAY_FORWARD_PROXY_" diff --git a/src/base/Qv2rayLog.cpp b/src/base/Qv2rayLog.cpp index 93171f3c..cc2fb552 100644 --- a/src/base/Qv2rayLog.cpp +++ b/src/base/Qv2rayLog.cpp @@ -1,5 +1,5 @@ #include "Qv2rayLog.hpp" -#include "GlobalInstances.hpp" +#include "Qv2rayBase.hpp" namespace Qv2ray::base { diff --git a/src/base/models/QvConfigIdentifier.hpp b/src/base/models/QvConfigIdentifier.hpp index 275053ee..3710b286 100644 --- a/src/base/models/QvConfigIdentifier.hpp +++ b/src/base/models/QvConfigIdentifier.hpp @@ -1,56 +1,38 @@ #pragma once #include #include +#include "base/models/QvSafeType.hpp" #include "3rdparty/x2struct/x2struct.hpp" namespace Qv2ray::base { - struct ConnectionIdentifier { - QString subscriptionName; - QString connectionName; - ConnectionIdentifier() { }; - bool isEmpty() - { - return connectionName.isEmpty(); - } - ConnectionIdentifier(QString connectionName) - { - this->connectionName = connectionName; - } - ConnectionIdentifier(QString connectionName, QString subscriptionName) - { - this->connectionName = connectionName; - this->subscriptionName = subscriptionName; - } - const QString IdentifierString() const - { - return connectionName + (subscriptionName.isEmpty() ? "" : " (" + subscriptionName + ")"); - } - friend bool operator==(ConnectionIdentifier &left, ConnectionIdentifier &right) - { - return left.subscriptionName == right.subscriptionName && left.connectionName == right.connectionName; - } - friend bool operator!=(ConnectionIdentifier &left, ConnectionIdentifier &right) - { - return !(left == right); - } - friend bool operator==(ConnectionIdentifier &left, QString &right) - { - return left.IdentifierString() == right; - } - friend bool operator!=(ConnectionIdentifier &left, QString &right) - { - return !(left.IdentifierString() == right); - } - // To make QMap happy - friend bool operator<(const ConnectionIdentifier left, const ConnectionIdentifier right) - { - return left.IdentifierString() < right.IdentifierString(); - } - friend bool operator>(const ConnectionIdentifier left, const ConnectionIdentifier right) - { - return left.IdentifierString() > right.IdentifierString(); - } - XTOSTRUCT(O(subscriptionName, connectionName)) + using namespace std::chrono; + // Common struct for Groups and Subscriptions + struct _QvGroupObjectBase { + QString displayName; + QList connections; + _QvGroupObjectBase(): displayName(), connections() { } + }; + + struct QvGroupObject : _QvGroupObjectBase { + QvGroupObject() { } + XTOSTRUCT(O(displayName, connections)) + }; + + struct QvSubscriptionObject : _QvGroupObjectBase { + QString address; + time_t lastUpdated; + float updateInterval; + QvSubscriptionObject(): address(""), lastUpdated(system_clock::to_time_t(system_clock::now())), updateInterval(10) { } + XTOSTRUCT(O(lastUpdated, updateInterval, address, connections, displayName)) + }; + + struct QvConnectionObject { + QString displayName; + time_t importDate; + long latency; + ulong upLinkData; + ulong downLinkData; + QvConnectionObject(): displayName(), importDate(system_clock::to_time_t(system_clock::now())), latency(0), upLinkData(0), downLinkData(0) { } + XTOSTRUCT(O(displayName, importDate, latency, upLinkData, downLinkData)) }; } -Q_DECLARE_METATYPE(Qv2ray::base::ConnectionIdentifier); diff --git a/src/base/models/QvConfigModel.hpp b/src/base/models/QvConfigModel.hpp index 299ca180..b73a5a80 100644 --- a/src/base/models/QvConfigModel.hpp +++ b/src/base/models/QvConfigModel.hpp @@ -6,199 +6,146 @@ const int QV2RAY_CONFIG_VERSION = 9; -namespace Qv2ray::base +namespace Qv2ray::base::config { - namespace config - { - struct QvBarLine { - QString Family; - bool Bold; - bool Italic; - int ColorA; - int ColorR; - int ColorG; - int ColorB; - int ContentType; - double Size; - QString Message; - QvBarLine() - : Family("Consolas") - , Bold(true) - , Italic(false) - , ColorA(255), ColorR(255), ColorG(255), ColorB(255) - , ContentType(0) - , Size(9), - Message("") { } - XTOSTRUCT(O(Bold, Italic, ColorA, ColorR, ColorG, ColorB, Size, Family, Message, ContentType)) - }; + struct QvBarLine { + QString Family; + bool Bold, Italic; + int ColorA, ColorR, ColorG, ColorB; + int ContentType; + double Size; + QString Message; + QvBarLine(): Family("Consolas"), Bold(true), Italic(false), ColorA(255), ColorR(255), ColorG(255), ColorB(255), + ContentType(0), Size(9), Message("") { } + XTOSTRUCT(O(Bold, Italic, ColorA, ColorR, ColorG, ColorB, Size, Family, Message, ContentType)) + }; - struct QvBarPage { - int OffsetYpx; - QList Lines; - QvBarPage() : OffsetYpx(5) { } - XTOSTRUCT(O(OffsetYpx, Lines)) - }; + struct QvBarPage { + int OffsetYpx; + QList Lines; + QvBarPage(): OffsetYpx(5) { } + XTOSTRUCT(O(OffsetYpx, Lines)) + }; - struct Qv2rayToolBarConfig { - QList Pages; - XTOSTRUCT(O(Pages)) - }; + struct Qv2rayToolBarConfig { + QList Pages; + XTOSTRUCT(O(Pages)) + }; - struct Qv2raySubscriptionConfig { - time_t lastUpdated; - float updateInterval; - QString address; - Qv2raySubscriptionConfig() : lastUpdated(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())), updateInterval(5), address("") { } - XTOSTRUCT(O(lastUpdated, updateInterval, address)) - }; + struct Qv2rayPACConfig { + bool enablePAC; + int port; + QString localIP; + bool useSocksProxy; + Qv2rayPACConfig(): enablePAC(false), port(8989), useSocksProxy(false) { } + XTOSTRUCT(O(enablePAC, port, localIP, useSocksProxy)) + }; - struct Qv2rayPACConfig { - bool enablePAC; - int port; - QString localIP; - bool useSocksProxy; - Qv2rayPACConfig() : enablePAC(false), port(8989), useSocksProxy(false) { } - XTOSTRUCT(O(enablePAC, port, localIP, useSocksProxy)) - }; + struct Qv2rayForwardProxyConfig { + bool enableForwardProxy; + QString type; + QString serverAddress; + int port; + bool useAuth; + QString username; + QString password; + Qv2rayForwardProxyConfig(): enableForwardProxy(false), type("http"), serverAddress("127.0.0.1"), port(8008), + useAuth(false), username(), password() { } + XTOSTRUCT(O(enableForwardProxy, type, serverAddress, port, useAuth, username, password)) + }; - struct Qv2rayForwardProxyConfig { - bool enableForwardProxy; - QString type; - QString serverAddress; - int port; - bool useAuth; - QString username; - QString password; + struct Qv2rayInboundsConfig { + QString listenip; + bool setSystemProxy; + Qv2rayPACConfig pacConfig; - Qv2rayForwardProxyConfig() : - enableForwardProxy(false), - type("http"), serverAddress("127.0.0.1"), port(8008), useAuth(false), - username("username"), password("password") - { } + // SOCKS + bool useSocks; + int socks_port; + bool socks_useAuth; + bool socksUDP; + QString socksLocalIP; + objects::AccountObject socksAccount; + // HTTP + bool useHTTP; + int http_port; + bool http_useAuth; + objects::AccountObject httpAccount; - XTOSTRUCT(O(enableForwardProxy, type, serverAddress, port, useAuth, username, password)) - }; + Qv2rayInboundsConfig(): + listenip("127.0.0.1"), setSystemProxy(false), pacConfig(), + useSocks(true), socks_port(1088), socks_useAuth(false), socksUDP(true), socksLocalIP("127.0.0.1"), socksAccount(), + useHTTP(true), http_port(8888), http_useAuth(false), httpAccount() {} - struct Qv2rayInboundsConfig { - QString listenip; - bool setSystemProxy; - Qv2rayPACConfig pacConfig; + XTOSTRUCT(O(setSystemProxy, pacConfig, listenip, useSocks, useHTTP, socks_port, socks_useAuth, socksAccount, socksUDP, socksLocalIP, http_port, http_useAuth, httpAccount)) + }; - // SOCKS - bool useSocks; - int socks_port; - bool socks_useAuth; - bool socksUDP; - QString socksLocalIP; - objects::AccountObject socksAccount; - // HTTP - bool useHTTP; - int http_port; - bool http_useAuth; - objects::AccountObject httpAccount; + struct Qv2rayUIConfig { + QString theme; + QString language; + bool useDarkTheme; + bool useDarkTrayIcon; + int maximumLogLines; + Qv2rayUIConfig() : theme("Fusion"), language("en_US"), useDarkTheme(false), useDarkTrayIcon(true), maximumLogLines(500) { } + XTOSTRUCT(O(theme, language, useDarkTheme, useDarkTrayIcon, maximumLogLines)) + }; - Qv2rayInboundsConfig(): - listenip("127.0.0.1"), setSystemProxy(false), pacConfig(), - useSocks(true), socks_port(1088), socks_useAuth(false), socksUDP(true), socksLocalIP("127.0.0.1"), socksAccount(), - useHTTP(true), http_port(8888), http_useAuth(false), httpAccount() {} + struct Qv2rayConnectionConfig { + bool bypassCN; + bool enableProxy; + bool withLocalDNS; + QList dnsList; + Qv2rayForwardProxyConfig forwardProxyConfig; + Qv2rayConnectionConfig() : bypassCN(true), enableProxy(true), withLocalDNS(false), dnsList(QStringList() << "8.8.4.4" << "1.1.1.1") { } + XTOSTRUCT(O(bypassCN, enableProxy, withLocalDNS, dnsList, forwardProxyConfig)) + }; - XTOSTRUCT(O(setSystemProxy, pacConfig, listenip, useSocks, useHTTP, socks_port, socks_useAuth, socksAccount, socksUDP, socksLocalIP, http_port, http_useAuth, httpAccount)) - }; + struct Qv2rayAPIConfig { + bool enableAPI; + int statsPort; + Qv2rayAPIConfig(): enableAPI(true), statsPort(15490) { } + XTOSTRUCT(O(enableAPI, statsPort)) + }; - struct Qv2rayUIConfig { - QString theme; - QString language; - bool useDarkTheme; - bool useDarkTrayIcon; - int maximumLogLines; - Qv2rayUIConfig() : theme("Fusion"), language("en_US"), useDarkTheme(false), useDarkTrayIcon(true), maximumLogLines(500) { } - XTOSTRUCT(O(theme, language, useDarkTheme, useDarkTrayIcon, maximumLogLines)) - }; + struct Qv2rayConfig { + int config_version; + bool tProxySupport; + int logLevel; + // + QString v2CorePath; + QString v2AssetsPath; + QString ignoredVersion; + QString autoStartId; + // + // Key = groupId, connectionId, subscriptionId + QMap groups; + QMap subscriptions; + /// Connections are used privately. + QMap connections; + // + Qv2rayUIConfig uiConfig; + Qv2rayAPIConfig apiConfig; + Qv2rayToolBarConfig toolBarConfig; + Qv2rayInboundsConfig inboundConfig; + Qv2rayConnectionConfig connectionConfig; - struct Qv2rayConnectionConfig { - bool bypassCN; - bool enableProxy; - bool withLocalDNS; - QList dnsList; - Qv2rayForwardProxyConfig forwardProxyConfig; - Qv2rayConnectionConfig() : bypassCN(true), enableProxy(true), withLocalDNS(false), dnsList(QStringList() << "8.8.4.4" << "1.1.1.1") { } - XTOSTRUCT(O(bypassCN, enableProxy, withLocalDNS, dnsList, forwardProxyConfig)) - }; + Qv2rayConfig(): + config_version(QV2RAY_CONFIG_VERSION), + tProxySupport(false), + logLevel(), + v2CorePath(), + v2AssetsPath(), + ignoredVersion(), + groups(), + subscriptions(), + connections(), + uiConfig(), apiConfig(), toolBarConfig(), inboundConfig(), connectionConfig() { } - struct Qv2rayAPIConfig { - bool enableAPI; - int statsPort; - Qv2rayAPIConfig(): enableAPI(true), statsPort(15490) { } - XTOSTRUCT(O(enableAPI, statsPort)) - }; - - struct QvGroupObject { - QString groupId; - QString displayName; - QvGroupObject(): groupId(QUuid::createUuid().toString()), displayName() {} - XTOSTRUCT(O(displayName)) - }; - - struct QvConnectionObject { - QString displayName; - QString connectionId; - QString groupId; - // - time_t importDate; - long latency; - long upLinkData; - long downLinkData; - QvConnectionObject(): displayName(), importDate(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())), - latency(0), upLinkData(0), downLinkData(0) { } - XTOSTRUCT(O(displayName, importDate, latency, upLinkData, downLinkData)) - }; - - struct Qv2rayConfig { - int config_version; - bool tProxySupport; - int logLevel; - // - QString v2CorePath; - QString v2AssetsPath; - ConnectionIdentifier autoStartConfig; - QString ignoredVersion; - // - QList groups; - QList connections; - //QList configs; - QMap subscriptions; - // - Qv2rayUIConfig uiConfig; - Qv2rayAPIConfig apiConfig; - Qv2rayInboundsConfig inboundConfig; - Qv2rayConnectionConfig connectionConfig; - Qv2rayToolBarConfig toolBarConfig; - - Qv2rayConfig(): - config_version(QV2RAY_CONFIG_VERSION), - tProxySupport(false), - logLevel(), - v2CorePath(), - v2AssetsPath(), - autoStartConfig(), - ignoredVersion(), - connections(), - subscriptions(), - uiConfig(), - apiConfig(), - inboundConfig(), - connectionConfig(), - toolBarConfig() { } - - XTOSTRUCT(O(config_version, - ignoredVersion, - tProxySupport, - logLevel, - autoStartConfig, - v2CorePath, v2AssetsPath, - connections, - uiConfig, - subscriptions, inboundConfig, connectionConfig, toolBarConfig, apiConfig)) - }; - } + XTOSTRUCT(O(config_version, ignoredVersion, + tProxySupport, + logLevel, uiConfig, + v2CorePath, v2AssetsPath, + groups, connections, subscriptions, + autoStartId, inboundConfig, connectionConfig, toolBarConfig, apiConfig)) + }; } diff --git a/src/base/models/QvSafeType.hpp b/src/base/models/QvSafeType.hpp index a5f3823c..158fe962 100644 --- a/src/base/models/QvSafeType.hpp +++ b/src/base/models/QvSafeType.hpp @@ -1,5 +1,4 @@ #pragma once - #include #include #include @@ -12,6 +11,7 @@ const Base& raw() const { return *this; } \ }; +using namespace std; namespace Qv2ray::base::safetype { // To prevent anonying QJsonObject misuse @@ -22,10 +22,15 @@ namespace Qv2ray::base::safetype SAFE_TYPEDEF(QJsonObject, CONFIGROOT) SAFE_TYPEDEF(QJsonObject, PROXYSETTING) // + SAFE_TYPEDEF(QJsonArray, ROUTERULELIST) SAFE_TYPEDEF(QJsonArray, INOUTLIST) - SAFE_TYPEDEF(INOUTLIST, OUTBOUNDS) - SAFE_TYPEDEF(INOUTLIST, INBOUNDS) SAFE_TYPEDEF(QJsonObject, ROUTING) SAFE_TYPEDEF(QJsonObject, ROUTERULE) - SAFE_TYPEDEF(QJsonArray, ROUTERULELIST) + SAFE_TYPEDEF(INOUTLIST, OUTBOUNDS) + SAFE_TYPEDEF(INOUTLIST, INBOUNDS) + // + SAFE_TYPEDEF(QString, SubscriptionId) + SAFE_TYPEDEF(QString, ConnectionId) + SAFE_TYPEDEF(QString, GroupId) } + diff --git a/src/common/QvHelpers.hpp b/src/common/QvHelpers.hpp index 51ba4786..d1bcf09c 100644 --- a/src/common/QvHelpers.hpp +++ b/src/common/QvHelpers.hpp @@ -37,6 +37,11 @@ namespace Qv2ray::common // This function cannot be marked as inline. QString RemoveInvalidFileName(const QString &fileName); bool IsValidFileName(const QString &fileName); + inline QString GenerateUuid() + { + return GenerateRandomString().toLower(); + //return QUuid::createUuid().toString(QUuid::WithoutBraces); + } // template QString StructToJsonString(const TYPE t) diff --git a/src/components/tcping/QvTCPing.cpp b/src/components/tcping/QvTCPing.cpp index c92248fd..a48d9d95 100644 --- a/src/components/tcping/QvTCPing.cpp +++ b/src/components/tcping/QvTCPing.cpp @@ -27,7 +27,7 @@ namespace Qv2ray::components::tcping worker->cancel(); } } - void QvTCPingModel::StartPing(const ConnectionIdentifier &connectionName, const QString &hostName, int port) + void QvTCPingModel::StartPing(const QvConnectionObject &connectionName, const QString &hostName, int port) { QvTCPingData data; data.hostName = hostName; diff --git a/src/components/tcping/QvTCPing.hpp b/src/components/tcping/QvTCPing.hpp index 14ac9c10..d2cc76d9 100644 --- a/src/components/tcping/QvTCPing.hpp +++ b/src/components/tcping/QvTCPing.hpp @@ -5,7 +5,7 @@ namespace Qv2ray::components::tcping { struct QvTCPingData { - ConnectionIdentifier connectionIdentifier; + QvConnectionObject connectionIdentifier; QString hostName; int port; QString errorMessage; @@ -19,7 +19,7 @@ namespace Qv2ray::components::tcping public: explicit QvTCPingModel(int defaultCount = 5, QObject *parent = nullptr); - void StartPing(const ConnectionIdentifier &connectionName, const QString &hostName, int port); + void StartPing(const QvConnectionObject &connectionName, const QString &hostName, int port); void StopAllPing(); signals: void PingFinished(QvTCPingData data); diff --git a/src/core/config/ConfigUpgrade.cpp b/src/core/config/ConfigUpgrade.cpp index 1376603b..079d93a6 100644 --- a/src/core/config/ConfigUpgrade.cpp +++ b/src/core/config/ConfigUpgrade.cpp @@ -14,45 +14,6 @@ namespace Qv2ray QJsonObject UpgradeConfig_Inc(int fromVersion, QJsonObject root) { switch (fromVersion) { - case 1: { - auto v1_oldConfigVersion = root["config_version"].toString(); - // From 1 to 2, we changed the config_version from 'string' to 'int' - root.remove("config_version"); - root["config_version"] = 2; - UPGRADELOG("Upgrading config_version from old value " + v1_oldConfigVersion + " to 2") - break; - } - - case 2: { - // We copied those files. - auto vCoreFilePath = root["v2CorePath"].toString(); - auto vCoreDestPath = QString(QV2RAY_DEFAULT_VCORE_PATH); - // We also need v2ctl - auto v2CtlFilePath = QFileInfo(vCoreFilePath).dir().path() + "/v2ctl"; - auto v2CtlDestPath = QFileInfo(vCoreDestPath).dir().path() + "/v2ctl"; -#ifdef Q_OS_WIN - v2CtlFilePath = v2CtlFilePath.append(".exe"); - v2CtlDestPath = v2CtlDestPath.append(".exe"); -#endif - QFile::copy(vCoreFilePath, vCoreDestPath); - QFile::copy(v2CtlFilePath, v2CtlDestPath); - root.remove("v2CorePath"); - UPGRADELOG("v2CorePath value from: " + vCoreFilePath + " to " + vCoreDestPath) - UPGRADELOG("v2CtlFilePath value from: " + v2CtlFilePath + " to " + v2CtlDestPath) - break; - } - - case 3: { - // We changed a key name in the config file. - //proxyDefault - auto oldProxyDefault = root["proxyDefault"].toBool(); - root.remove("proxyDefault"); - root["enableProxy"] = oldProxyDefault; - //enableProxy - UPGRADELOG("key: proxyDefault->enableProxy, value from: " + QSTRN(oldProxyDefault) + " to " + QSTRN(oldProxyDefault)) - break; - } - // -------------------------------------------------------------------------------------- // Below is for Qv2ray version 2 case 4: { @@ -97,9 +58,9 @@ namespace Qv2ray // //root["inboundConfig"] = inbound; // //UPDATELOG("Renamed usePAC to enablePAC.") // - ConnectionIdentifier i; - i.connectionName = root["autoStartConfig"].toString(); - root["autoStartConfig"] = GetRootObject(i); + QJsonObject i; + i["connectionName"] = root["autoStartConfig"].toString(); + root["autoStartConfig"] = i; UPGRADELOG("Added subscription feature to autoStartConfig.") break; } @@ -113,7 +74,7 @@ namespace Qv2ray for (auto item = subs.begin(); item != subs.end(); item++) { auto key = item.key(); - Qv2raySubscriptionConfig _conf; + QvSubscriptionObject _conf; _conf.address = item.value().toString(); _conf.lastUpdated = system_clock::to_time_t(system_clock::now()); _conf.updateInterval = 5; @@ -148,25 +109,27 @@ namespace Qv2ray // From version 8 to 9, we introduced a lot of new connection metainfo(s) case 8: { // Generate a default group - auto groupId = QUuid::createUuid().toString(); QJsonObject defaultGroup; - defaultGroup["groupId"] = groupId; + QStringList defaultGroupConnectionId; defaultGroup["displayName"] = QObject::tr("Default Group"); - QJsonArray groups; - groups.push_back(defaultGroup); - root["groups"] = groups; + QString defaultGroupId = "000000000000"; if (!QDir(QV2RAY_CONNECTIONS_DIR).exists()) { QDir().mkpath(QV2RAY_CONNECTIONS_DIR); } + QString autoStartId; + UPGRADELOG("Upgrading connections...") + QJsonObject rootConnections; + for (auto config : root["configs"].toArray()) { UPGRADELOG("Migrating: " + config.toString()) // // MOVE FILES. - auto filePath = QV2RAY_CONNECTIONS_DIR + config.toString() + QV2RAY_CONFIG_FILE_EXTENSION; + // OLD PATH is at QV2RAY_CONFIG_DIR + auto filePath = QV2RAY_CONFIG_DIR + config.toString() + QV2RAY_CONFIG_FILE_EXTENSION; auto configFile = QFile(filePath); - auto newUuid = QUuid::createUuid().toString(); + auto newUuid = GenerateUuid(); DEBUG(SETTINGS, "Generated new UUID: " + newUuid); if (configFile.exists()) { @@ -180,13 +143,76 @@ namespace Qv2ray QJsonObject connectionObject; connectionObject["displayName"] = config.toString(); - connectionObject["connectionId"] = newUuid; - connectionObject["groupId"] = groupId; - // - auto connections = root["connections"].toArray(); - connections.push_back(connectionObject); - root["connections"] = connections; + defaultGroupConnectionId << newUuid; + DEBUG(SETTINGS, "Pushed uuid: " + newUuid + " to default group.") + rootConnections[newUuid] = connectionObject; } + + // Upgrading subscriptions. + QJsonObject rootSubscriptions = root.take("subscriptions").toObject(); + QJsonObject newSubscriptions; + + for (auto i = 0; i < rootSubscriptions.count(); i++) { + auto key = rootSubscriptions.keys()[i]; + auto value = rootSubscriptions.value(key); + // + UPGRADELOG("Upgrading subscription: " + key) + QString subsUuid = GenerateUuid(); + QJsonObject subs; + QStringList subsConnectionIds; + subs["address"] = value["address"].toString(); + subs["lastUpdated"] = value["lastUpdated"]; + subs["updateInterval"] = value["updateInterval"]; + subs["displayName"] = key; + // + auto baseDirPath = QV2RAY_SUBSCRIPTION_DIR + key; + auto newDirPath = QV2RAY_SUBSCRIPTION_DIR + subsUuid; + QDir newDir(newDirPath); + + if (!newDir.exists()) { + newDir.mkpath(newDirPath); + } + + // With extensions + auto fileList = GetFileList(baseDirPath); + + // Copy every file within a subscription. + for (auto fileName : fileList) { + auto subsConnectionId = GenerateUuid(); + auto baseFilePath = baseDirPath + "/" + fileName; + auto newFilePath = newDirPath + "/" + subsConnectionId + QV2RAY_CONFIG_FILE_EXTENSION; + // + QJsonObject subsConnection; + subsConnection["displayName"] = fileName.chopped(QString(QV2RAY_CONFIG_FILE_EXTENSION).count()); + QFile(baseFilePath).rename(newFilePath); + UPGRADELOG("Moved subscription file from: " + baseFilePath + " to: " + newFilePath); + subsConnectionIds << subsConnectionId; + rootConnections[subsConnectionId] = subsConnection; + } + + subs["connections"] = QJsonArray::fromStringList(subsConnectionIds); + newSubscriptions[subsUuid] = subs; + QDir().rmdir(baseDirPath); + } + + defaultGroup["connections"] = QJsonArray::fromStringList(defaultGroupConnectionId); + QJsonObject groups; + groups[defaultGroupId] = defaultGroup; + root["groups"] = groups; + root["connections"] = rootConnections; + root["subscriptions"] = newSubscriptions; + UPGRADELOG("Finished upgrading config, version 8.") + break; + } + + default: { + // Due to technical issue, we cannot maintain all of those upgrade processes anymore. + // Check https://github.com/Qv2ray/Qv2ray/issues/353#issuecomment-586117507 for more information + QvMessageBoxWarn(nullptr, QObject::tr("Configuration Upgrade Failed"), + QObject::tr("Unsupported config version number: ") + QSTRN(fromVersion) + NEWLINE + NEWLINE + + QObject::tr("Please upgrade firstly up to Qv2ray v2.0/v2.1 and try again.")); + throw new runtime_error("The configuration version of your old Qv2ray installation is out-of-date and that" + " version is not supported anymore, please try to update to an intermediate version of Qv2ray first."); } } diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 8315fb66..7047c305 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -2,22 +2,29 @@ #include "base/Qv2rayBase.hpp" -class ConnectionGroupIdentifier; +class QvConnectionListModel; namespace Qv2ray::core::handler { class ConnectionHandler : public QObject { - Q_OBJECT - explicit ConnectionHandler(); - ~ConnectionHandler(); - void ReloadConnections(); - - public slots: - optional DeleteConnection(const ConnectionIdentifier &identifier); + // Q_OBJECT + //public: + // explicit ConnectionHandler(); + // ~ConnectionHandler(); + // void ReloadConnections(); + // // Get operations. + // QvConnectionListModel GetConnections(); // - optional RenameConnection(const ConnectionIdentifier &identifier, const QString &newName); - optional MoveConnection(const ConnectionIdentifier &identifier, const ConnectionGroupIdentifier &newGroup); - optional DuplicateConnection(const ConnectionIdentifier &identifier, ConnectionIdentifier *newIdentifier); + //public slots: + // optional DeleteConnection(const ConnectionId &id); + // optional RenameConnection(const ConnectionId &id, const QString &newName); + // optional DuplicateConnection(const ConnectionId &id, ConnectionId *newId); + // optional MoveConnection(const ConnectionId &id, const GroupId &newGroupId); + // // Group Operations + // optional DeleteGroup(const GroupId &id); + // optional RenameGroup(const GroupId &id, const QString &newName); }; } + +using namespace Qv2ray::core::handler; diff --git a/src/core/kernel/APIBackend.cpp b/src/core/kernel/APIBackend.cpp index 6177631e..91bafd9f 100644 --- a/src/core/kernel/APIBackend.cpp +++ b/src/core/kernel/APIBackend.cpp @@ -105,7 +105,7 @@ namespace Qv2ray::core::kernel::api thread->exit(); } - long APIWorkder::CallStatsAPIByName(QString name) + qint64 APIWorkder::CallStatsAPIByName(QString name) { if (apiFailedCounter == QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD) { LOG(VCORE, "API call failure threshold reached, cancelling further API aclls.") @@ -129,9 +129,9 @@ namespace Qv2ray::core::kernel::api apiFailedCounter++; } - auto data = response.stat().value(); + qint64 data = response.stat().value(); #else - auto data = GetStats(const_cast(name.toStdString().c_str()), 1000); + qint64 data = GetStats(const_cast(name.toStdString().c_str()), 1000); #endif if (data < 0) { diff --git a/src/core/kernel/APIBackend.hpp b/src/core/kernel/APIBackend.hpp index c76c3570..d576540b 100644 --- a/src/core/kernel/APIBackend.hpp +++ b/src/core/kernel/APIBackend.hpp @@ -26,11 +26,11 @@ namespace Qv2ray::core::kernel::api void process(); signals: - void OnDataReady(QString tag, long dataUp, long dataDown); + void OnDataReady(QString tag, qint64 dataUp, qint64 dataDown); void error(QString err); private: - long CallStatsAPIByName(QString name); + qint64 CallStatsAPIByName(QString name); QStringList inboundTags; QThread *thread; // diff --git a/src/core/kernel/KernelInteractions.cpp b/src/core/kernel/KernelInteractions.cpp index e6284630..cf1aef8f 100644 --- a/src/core/kernel/KernelInteractions.cpp +++ b/src/core/kernel/KernelInteractions.cpp @@ -145,7 +145,6 @@ namespace Qv2ray::core::kernel } // Write the final configuration to the disk. - QString json = JsonToString(root); QFile configFile(QV2RAY_GENERATED_FILE_PATH); StringToFile(&json, &configFile); @@ -226,7 +225,7 @@ namespace Qv2ray::core::kernel delete vProcess; } - void V2rayKernelInstance::onAPIDataReady(QString tag, long totalUp, long totalDown) + void V2rayKernelInstance::onAPIDataReady(QString tag, qulonglong totalUp, qulonglong totalDown) { auto dataup = totalUp - transferDataUp[tag]; transferDataUp[tag] = totalUp; @@ -238,23 +237,23 @@ namespace Qv2ray::core::kernel } // ------------------------------------------------------------- API FUNCTIONS -------------------------- - long V2rayKernelInstance::getTagSpeedUp(const QString &tag) + qulonglong V2rayKernelInstance::getTagSpeedUp(const QString &tag) { return transferSpeedUp[tag]; } - long V2rayKernelInstance::getTagSpeedDown(const QString &tag) + qulonglong V2rayKernelInstance::getTagSpeedDown(const QString &tag) { return transferSpeedDown[tag]; } - long V2rayKernelInstance::getTagDataUp(const QString &tag) + qulonglong V2rayKernelInstance::getTagDataUp(const QString &tag) { return transferDataUp[tag]; } - long V2rayKernelInstance::getTagDataDown(const QString &tag) + qulonglong V2rayKernelInstance::getTagDataDown(const QString &tag) { return transferDataDown[tag]; } - long V2rayKernelInstance::getAllDataUp() + qulonglong V2rayKernelInstance::getAllDataUp() { long val = 0; @@ -264,7 +263,7 @@ namespace Qv2ray::core::kernel return val; } - long V2rayKernelInstance::getAllDataDown() + qulonglong V2rayKernelInstance::getAllDataDown() { long val = 0; @@ -274,9 +273,9 @@ namespace Qv2ray::core::kernel return val; } - long V2rayKernelInstance::getAllSpeedUp() + qulonglong V2rayKernelInstance::getAllSpeedUp() { - long val = 0; + qulonglong val = 0; for (auto _val : transferSpeedUp.values()) { val += _val; @@ -284,9 +283,9 @@ namespace Qv2ray::core::kernel return val; } - long V2rayKernelInstance::getAllSpeedDown() + qulonglong V2rayKernelInstance::getAllSpeedDown() { - long val = 0; + qulonglong val = 0; for (auto _val : transferSpeedDown.values()) { val += _val; diff --git a/src/core/kernel/KernelInteractions.hpp b/src/core/kernel/KernelInteractions.hpp index af3c982e..d483d478 100644 --- a/src/core/kernel/KernelInteractions.hpp +++ b/src/core/kernel/KernelInteractions.hpp @@ -13,14 +13,14 @@ namespace Qv2ray::core::kernel ~V2rayKernelInstance() override; // // Speed - long getTagSpeedUp(const QString &tag); - long getTagSpeedDown(const QString &tag); - long getTagDataUp(const QString &tag); - long getTagDataDown(const QString &tag); - long getAllDataUp(); - long getAllDataDown(); - long getAllSpeedUp(); - long getAllSpeedDown(); + qulonglong getTagSpeedUp(const QString &tag); + qulonglong getTagSpeedDown(const QString &tag); + qulonglong getTagDataUp(const QString &tag); + qulonglong getTagDataDown(const QString &tag); + qulonglong getAllDataUp(); + qulonglong getAllDataDown(); + qulonglong getAllSpeedUp(); + qulonglong getAllSpeedDown(); // bool StartConnection(CONFIGROOT root); void StopConnection(); @@ -34,16 +34,16 @@ namespace Qv2ray::core::kernel void onProcessOutputReadyRead(QString); public slots: - void onAPIDataReady(QString tag, long totalUp, long totalDown); + void onAPIDataReady(QString tag, qulonglong totalUp, qulonglong totalDown); private: APIWorkder *apiWorker; QProcess *vProcess; bool apiEnabled; - QMap transferDataUp; - QMap transferDataDown; - QMap transferSpeedUp; - QMap transferSpeedDown; + QMap transferDataUp; + QMap transferDataDown; + QMap transferSpeedUp; + QMap transferSpeedDown; }; } diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index 29cfbead..b2bf8b2f 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -12,9 +12,9 @@ #include "ui/w_ImportConfig.hpp" #include "core/CoreUtils.hpp" -#include "ui/nodemodels/RuleNodeModel.hpp" -#include "ui/nodemodels/InboundNodeModel.hpp" -#include "ui/nodemodels/OutboundNodeModel.hpp" +#include "ui/models/RuleNodeModel.hpp" +#include "ui/models/InboundNodeModel.hpp" +#include "ui/models/OutboundNodeModel.hpp" #include "NodeStyle.hpp" #include "FlowView.hpp" diff --git a/src/ui/models/ConnectionTreeModel.cpp b/src/ui/models/ConnectionTreeModel.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/ui/models/ConnectionTreeModel.hpp b/src/ui/models/ConnectionTreeModel.hpp new file mode 100644 index 00000000..e69de29b diff --git a/src/ui/nodemodels/InboundNodeModel.cpp b/src/ui/models/InboundNodeModel.cpp similarity index 100% rename from src/ui/nodemodels/InboundNodeModel.cpp rename to src/ui/models/InboundNodeModel.cpp diff --git a/src/ui/nodemodels/InboundNodeModel.hpp b/src/ui/models/InboundNodeModel.hpp similarity index 97% rename from src/ui/nodemodels/InboundNodeModel.hpp rename to src/ui/models/InboundNodeModel.hpp index da46fad2..472bd410 100644 --- a/src/ui/nodemodels/InboundNodeModel.hpp +++ b/src/ui/models/InboundNodeModel.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include "ui/nodemodels/NodeModelsBase.hpp" +#include "ui/models/NodeModelsBase.hpp" class QvInboundNodeModel : public NodeDataModel { diff --git a/src/ui/nodemodels/NodeModelsBase.hpp b/src/ui/models/NodeModelsBase.hpp similarity index 100% rename from src/ui/nodemodels/NodeModelsBase.hpp rename to src/ui/models/NodeModelsBase.hpp diff --git a/src/ui/nodemodels/OutboundNodeModel.cpp b/src/ui/models/OutboundNodeModel.cpp similarity index 100% rename from src/ui/nodemodels/OutboundNodeModel.cpp rename to src/ui/models/OutboundNodeModel.cpp diff --git a/src/ui/nodemodels/OutboundNodeModel.hpp b/src/ui/models/OutboundNodeModel.hpp similarity index 97% rename from src/ui/nodemodels/OutboundNodeModel.hpp rename to src/ui/models/OutboundNodeModel.hpp index d0b3eb1c..1a23a985 100644 --- a/src/ui/nodemodels/OutboundNodeModel.hpp +++ b/src/ui/models/OutboundNodeModel.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include "ui/nodemodels/NodeModelsBase.hpp" +#include "ui/models/NodeModelsBase.hpp" class QvOutboundNodeModel : public NodeDataModel { diff --git a/src/ui/nodemodels/RuleNodeModel.cpp b/src/ui/models/RuleNodeModel.cpp similarity index 100% rename from src/ui/nodemodels/RuleNodeModel.cpp rename to src/ui/models/RuleNodeModel.cpp diff --git a/src/ui/nodemodels/RuleNodeModel.hpp b/src/ui/models/RuleNodeModel.hpp similarity index 98% rename from src/ui/nodemodels/RuleNodeModel.hpp rename to src/ui/models/RuleNodeModel.hpp index e4ea87cf..bf75fa2b 100644 --- a/src/ui/nodemodels/RuleNodeModel.hpp +++ b/src/ui/models/RuleNodeModel.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include "ui/nodemodels/NodeModelsBase.hpp" +#include "ui/models/NodeModelsBase.hpp" class QvRuleNodeDataModel : public NodeDataModel { diff --git a/src/ui/w_ExportConfig.cpp b/src/ui/w_ExportConfig.cpp index fea475ae..e871ee56 100644 --- a/src/ui/w_ExportConfig.cpp +++ b/src/ui/w_ExportConfig.cpp @@ -25,9 +25,11 @@ ConfigExporter::~ConfigExporter() { } -ConfigExporter::ConfigExporter(const CONFIGROOT &root, const ConnectionIdentifier &alias, QWidget *parent) : ConfigExporter(parent) +ConfigExporter::ConfigExporter(const ConnectionId &connection, QWidget *parent) : ConfigExporter(parent) { - message = ConvertConfigToString(root, alias.IdentifierString()); + // WIP + auto x = connection; + //message = ConvertConfigToString(root, alias.IdentifierString()); // QZXingEncoderConfig conf; conf.border = true; diff --git a/src/ui/w_ExportConfig.hpp b/src/ui/w_ExportConfig.hpp index ed14ee64..89208ff2 100644 --- a/src/ui/w_ExportConfig.hpp +++ b/src/ui/w_ExportConfig.hpp @@ -10,7 +10,7 @@ class ConfigExporter : public QDialog, private Ui::ExportConfigWindow Q_OBJECT public: - explicit ConfigExporter(const CONFIGROOT &root, const ConnectionIdentifier &alias, QWidget *parent = nullptr); + explicit ConfigExporter(const ConnectionId &connection, QWidget *parent = nullptr); ~ConfigExporter(); void OpenExport(); public slots: diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index cecd9759..8a8832ca 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -1,6 +1,15 @@ #pragma once -#include + +#include "w_MainWindow.hpp" +#include "w_ImportConfig.hpp" +#include "w_PreferencesWindow.hpp" +#include "w_SubscriptionManager.hpp" +#include "w_ExportConfig.hpp" +#include "ui/editors/w_OutboundEditor.hpp" +#include "ui/editors/w_RoutesEditor.hpp" +#include "ui/editors/w_JsonEditor.hpp" +//#include #include #include #include @@ -14,15 +23,6 @@ #include #include -#include "w_MainWindow.hpp" -#include "w_ImportConfig.hpp" -#include "w_PreferencesWindow.hpp" -#include "w_SubscriptionManager.hpp" -#include "w_ExportConfig.hpp" -#include "ui/editors/w_OutboundEditor.hpp" -#include "ui/editors/w_RoutesEditor.hpp" -#include "ui/editors/w_JsonEditor.hpp" - #include "components/plugins/toolbar/QvToolbar.hpp" #include "components/pac/QvPACHandler.hpp" @@ -36,27 +36,27 @@ #define qvAppLogBrowser this->logTextBrowsers[1] #define currentLogBrowser this->logTextBrowsers[currentLogBrowserId] // -#define ItemConnectionIdentifier(__item__) (__item__->data(0, Qt::UserRole).value()) +//#define ItemConnectionIdentifier(__item__) (__item__->data(0, Qt::UserRole).value()) // -#define CheckConfigType(_item_, TYPE) (connections.contains(ItemConnectionIdentifier(_item_)) && connections[ItemConnectionIdentifier(_item_)].configType == CONNECTION_ ## TYPE) +//#define CheckConfigType(_item_, TYPE) (connections.contains(ItemConnectionIdentifier(_item_)) && connections[ItemConnectionIdentifier(_item_)].configType == CONNECTION_ ## TYPE) // -#define SUBSCRIPTION_CONFIG_MODIFY_ASK(_item_) \ - if (!CheckConfigType(_item_, REGULAR)) { \ - if (QvMessageBoxAsk(this, QObject::tr("Editing a subscription config"), QObject::tr("You are trying to edit a config loaded from subscription.") + \ - NEWLINE + QObject::tr("All changes will be overwritten when the subscriptions are updated next time.") + \ - NEWLINE + QObject::tr("Are you still going to do so?")) != QMessageBox::Yes) { \ - return; \ - } \ - } \ - - -#define SUBSCRIPTION_CONFIG_MODIFY_DENY(_item_) \ - if (!CheckConfigType(_item_, REGULAR)) { \ - QvMessageBoxWarn(this, QObject::tr("Editing a subscription config"), QObject::tr("You should not modity this property of a config from a subscription")); \ - return; \ - } \ - -#define IsConnectableItem(item) (item != nullptr && item->childCount() == 0 && (CheckConfigType(item, REGULAR) || CheckConfigType(item, SUBSCRIPTION))) +//#define SUBSCRIPTION_CONFIG_MODIFY_ASK(_item_) \ +// if (!CheckConfigType(_item_, REGULAR)) { \ +// if (QvMessageBoxAsk(this, QObject::tr("Editing a subscription config"), QObject::tr("You are trying to edit a config loaded from subscription.") + \ +// NEWLINE + QObject::tr("All changes will be overwritten when the subscriptions are updated next time.") + \ +// NEWLINE + QObject::tr("Are you still going to do so?")) != QMessageBox::Yes) { \ +// return; \ +// } \ +// } \ +// +// +//#define SUBSCRIPTION_CONFIG_MODIFY_DENY(_item_) \ +// if (!CheckConfigType(_item_, REGULAR)) { \ +// QvMessageBoxWarn(this, QObject::tr("Editing a subscription config"), QObject::tr("You should not modity this property of a config from a subscription")); \ +// return; \ +// } \ +// +//#define IsConnectableItem(item) (item != nullptr && item->childCount() == 0 && (CheckConfigType(item, REGULAR) || CheckConfigType(item, SUBSCRIPTION))) #define IsSelectionConnectable (!connectionListWidget->selectedItems().empty() && IsConnectableItem(connectionListWidget->selectedItems().first())) // From https://gist.github.com/jemyzhang/7130092 @@ -274,27 +274,27 @@ void MainWindow::keyPressEvent(QKeyEvent *e) if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { // If pressed enter or return on connectionListWidget. // Try to connect to the selected connection. - if (focusWidget() == connectionListWidget) { - if (!IsSelectionConnectable) return; - - auto selections = connectionListWidget->selectedItems(); - QVariant v; - auto vv = v.value(); - ShowAndSetConnection(ItemConnectionIdentifier(selections.first()), true, true); - } + //if (focusWidget() == connectionListWidget) { + // if (!IsSelectionConnectable) return; + // + // auto selections = connectionListWidget->selectedItems(); + // QVariant v; + // auto vv = v.value(); + // ShowAndSetConnection(ItemConnectionIdentifier(selections.first()), true, true); + //} } } void MainWindow::on_action_StartThis_triggered() { - if (!IsSelectionConnectable) { - QvMessageBoxWarn(this, tr("No connection selected!"), tr("Please select a config from the list.")); - return; - } - - CurrentSelectedItemPtr = connectionListWidget->selectedItems().first(); - CurrentConnectionIdentifier = ItemConnectionIdentifier(CurrentSelectedItemPtr); - on_reconnectButton_clicked(); + //if (!IsSelectionConnectable) { + // QvMessageBoxWarn(this, tr("No connection selected!"), tr("Please select a config from the list.")); + // return; + //} + // + //CurrentSelectedItemPtr = connectionListWidget->selectedItems().first(); + //CurrentConnectionIdentifier = ItemConnectionIdentifier(CurrentSelectedItemPtr); + //on_reconnectButton_clicked(); } void MainWindow::VersionUpdate(QByteArray &data) { @@ -340,71 +340,68 @@ void MainWindow::OnConfigListChanged(bool need_restart) SetEditWidgetEnable(false); // // Store the latency test value. - QMap latencyValueCache; - - for (auto i = 0; i < connections.count(); i++) { - latencyValueCache[connections.keys()[i]] = connections.values()[i].latency; - } - + QMap latencyValueCache; + //for (auto i = 0; i < connections.count(); i++) { + // latencyValueCache[connections.keys()[i]] = connections.values()[i].latency; + //} connections.clear(); connectionListWidget->clear(); - auto _regularConnections = GetRegularConnections(GlobalConfig.configs); + QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP, only subscriptions are supported"); + //auto _regularConnections = GetRegularConnections(GlobalConfig.configs); auto _subsConnections = GetSubscriptionConnections(GlobalConfig.subscriptions.keys()); - - for (auto i = 0; i < _regularConnections.count(); i++) { - ConnectionObject _o; - _o.configType = CONNECTION_REGULAR; - _o.connectionName = _regularConnections.keys()[i]; - _o.config = _regularConnections.values()[i]; - auto name = _o.IdentifierString(); - _o.latency = latencyValueCache[name]; // restore latency values - connections[name] = _o; - auto item = new QTreeWidgetItem(QStringList() << _o.connectionName); - item->setData(0, Qt::UserRole, QVariant::fromValue(_o)); - connectionListWidget->addTopLevelItem(item); - } - - for (auto i = 0; i < _subsConnections.count(); i++) { - auto subName = _subsConnections.keys()[i]; - auto subTopLevelItem = new QTreeWidgetItem(QStringList() << tr("Subscription") + ": " + subName); - connectionListWidget->addTopLevelItem(subTopLevelItem); - - for (auto j = 0; j < _subsConnections.values()[i].count(); j++) { - ConnectionObject _o; - _o.configType = CONNECTION_SUBSCRIPTION; - _o.connectionName = _subsConnections.values()[i].keys()[j]; - _o.subscriptionName = subName; - _o.config = _subsConnections.values()[i].values()[j]; - // connection name generated from subscription name and connection name. - auto connName = _o.IdentifierString(); - _o.latency = latencyValueCache[connName]; - connections[connName] = _o; - auto item = new QTreeWidgetItem(QStringList() << _o.connectionName); - item->setData(0, Qt::UserRole, QVariant::fromValue(_o)); - subTopLevelItem->addChild(item); - } - } - - // We set the current selected item back... - if (connections.contains(CurrentConnectionIdentifier)) { - auto item = FindItemByIdentifier(CurrentConnectionIdentifier); - - if (item != nullptr) { - connectionListWidget->setCurrentItem(item); - connectionListWidget->scrollToItem(item); - } else if (connectionListWidget->topLevelItemCount() > 0) { - item = connectionListWidget->topLevelItem(0); - CurrentConnectionIdentifier = ItemConnectionIdentifier(item); - } else { - return; - } - - ShowAndSetConnection(CurrentConnectionIdentifier, false, false); - } - - connectionListWidget->sortItems(0, Qt::AscendingOrder); - - if (wasRunning) on_startButton_clicked(); + //for (auto i = 0; i < _regularConnections.count(); i++) { + // ConnectionObject _o; + // _o.configType = CONNECTION_REGULAR; + // _o.connectionName = _regularConnections.keys()[i]; + // _o.config = _regularConnections.values()[i]; + // auto name = _o.IdentifierString(); + // _o.latency = latencyValueCache[name]; // restore latency values + // connections[name] = _o; + // auto item = new QTreeWidgetItem(QStringList() << _o.connectionName); + // item->setData(0, Qt::UserRole, QVariant::fromValue(_o)); + // connectionListWidget->addTopLevelItem(item); + //} + //for (auto i = 0; i < _subsConnections.count(); i++) { + // auto subName = _subsConnections.keys()[i]; + // auto subTopLevelItem = new QTreeWidgetItem(QStringList() << tr("Subscription") + ": " + subName); + // connectionListWidget->addTopLevelItem(subTopLevelItem); + // + // for (auto j = 0; j < _subsConnections.values()[i].count(); j++) { + // ConnectionObject _o; + // _o.configType = CONNECTION_SUBSCRIPTION; + // _o.connectionName = _subsConnections.values()[i].keys()[j]; + // _o.subscriptionName = subName; + // _o.config = _subsConnections.values()[i].values()[j]; + // // connection name generated from subscription name and connection name. + // auto connName = _o.IdentifierString(); + // _o.latency = latencyValueCache[connName]; + // connections[connName] = _o; + // auto item = new QTreeWidgetItem(QStringList() << _o.connectionName); + // item->setData(0, Qt::UserRole, QVariant::fromValue(_o)); + // subTopLevelItem->addChild(item); + // } + //} + // + //// We set the current selected item back... + //if (connections.contains(CurrentConnectionIdentifier)) { + // auto item = FindItemByIdentifier(CurrentConnectionIdentifier); + // + // if (item != nullptr) { + // connectionListWidget->setCurrentItem(item); + // connectionListWidget->scrollToItem(item); + // } else if (connectionListWidget->topLevelItemCount() > 0) { + // item = connectionListWidget->topLevelItem(0); + // CurrentConnectionIdentifier = ItemConnectionIdentifier(item); + // } else { + // return; + // } + // + // ShowAndSetConnection(CurrentConnectionIdentifier, false, false); + //} + // + //connectionListWidget->sortItems(0, Qt::AscendingOrder); + // + //if (wasRunning) on_startButton_clicked(); } MainWindow::~MainWindow() { @@ -429,68 +426,68 @@ void MainWindow::setMasterLogHBar() } void MainWindow::on_startButton_clicked() { - if (!vinstance->KernelStarted) { - vCoreLogBrowser->clear(); - speedChartView->Clear(); - - // Check Selection - if (CurrentConnectionIdentifier.isEmpty()) { - QvMessageBoxWarn(this, tr("No connection selected!"), tr("Please select a config from the list.")); - return; - } - - auto name = CurrentConnectionIdentifier.IdentifierString(); - LOG(VCORE, "Connecting to: " + name) - vCoreLogBrowser->clear(); - bool startFlag = MWtryStartConnection(); - - if (startFlag) { - MWTryPingConnection(name); - speedTimerId = startTimer(1000); - pingTimerId = startTimer(60000); - this->hTray.showMessage("Qv2ray", tr("Connected: ") + name, this->windowIcon()); - hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + name); - statusLabel->setText(tr("Connected: ") + name); - } else { - // If failed, show mainwindow - this->show(); - } - - // Menu actions - action_Tray_Start->setEnabled(!startFlag); - action_Tray_Stop->setEnabled(startFlag); - action_Tray_Reconnect->setEnabled(startFlag); - tray_SystemProxyMenu->setEnabled(startFlag); - // Buttons - startButton->setEnabled(!startFlag); - stopButton->setEnabled(startFlag); - } else { - this->hTray.showMessage("Qv2ray", tr("Already connected to: ") + CurrentConnectionIdentifier.IdentifierString(), this->windowIcon()); - } + //if (!vinstance->KernelStarted) { + // vCoreLogBrowser->clear(); + // speedChartView->Clear(); + // + // // Check Selection + // if (CurrentConnectionIdentifier.isEmpty()) { + // QvMessageBoxWarn(this, tr("No connection selected!"), tr("Please select a config from the list.")); + // return; + // } + // + // auto name = CurrentConnectionIdentifier.IdentifierString(); + // LOG(VCORE, "Connecting to: " + name) + // vCoreLogBrowser->clear(); + // bool startFlag = MWtryStartConnection(); + // + // if (startFlag) { + // MWTryPingConnection(name); + // speedTimerId = startTimer(1000); + // pingTimerId = startTimer(60000); + // this->hTray.showMessage("Qv2ray", tr("Connected: ") + name, this->windowIcon()); + // hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + name); + // statusLabel->setText(tr("Connected: ") + name); + // } else { + // // If failed, show mainwindow + // this->show(); + // } + // + // // Menu actions + // action_Tray_Start->setEnabled(!startFlag); + // action_Tray_Stop->setEnabled(startFlag); + // action_Tray_Reconnect->setEnabled(startFlag); + // tray_SystemProxyMenu->setEnabled(startFlag); + // // Buttons + // startButton->setEnabled(!startFlag); + // stopButton->setEnabled(startFlag); + //} else { + // this->hTray.showMessage("Qv2ray", tr("Already connected to: ") + CurrentConnectionIdentifier.IdentifierString(), this->windowIcon()); + //} } void MainWindow::on_stopButton_clicked() { - // Is running or starting - killTimer(speedTimerId); - killTimer(pingTimerId); - // - MWStopConnection(); - // - hTray.setToolTip(TRAY_TOOLTIP_PREFIX); - statusLabel->setText(tr("Disconnected")); - action_Tray_Start->setEnabled(true); - action_Tray_Stop->setEnabled(false); - action_Tray_Reconnect->setEnabled(false); - // Set to false as the system proxy has been cleared in the StopConnection function. - tray_SystemProxyMenu->setEnabled(false); - startButton->setEnabled(true); - stopButton->setEnabled(false); - // - netspeedLabel->setText("0.00 B/s\r\n0.00 B/s"); - dataamountLabel->setText("0.00 B\r\n0.00 B"); - LOG(UI, "Stopped successfully.") - this->hTray.showMessage("Qv2ray", tr("Disconnected from: ") + CurrentConnectionIdentifier.IdentifierString()); + //// Is running or starting + //killTimer(speedTimerId); + //killTimer(pingTimerId); + //// + //MWStopConnection(); + //// + //hTray.setToolTip(TRAY_TOOLTIP_PREFIX); + //statusLabel->setText(tr("Disconnected")); + //action_Tray_Start->setEnabled(true); + //action_Tray_Stop->setEnabled(false); + //action_Tray_Reconnect->setEnabled(false); + //// Set to false as the system proxy has been cleared in the StopConnection function. + //tray_SystemProxyMenu->setEnabled(false); + //startButton->setEnabled(true); + //stopButton->setEnabled(false); + //// + //netspeedLabel->setText("0.00 B/s\r\n0.00 B/s"); + //dataamountLabel->setText("0.00 B\r\n0.00 B"); + //LOG(UI, "Stopped successfully.") + //this->hTray.showMessage("Qv2ray", tr("Disconnected from: ") + CurrentConnectionIdentifier.IdentifierString()); } void MainWindow::closeEvent(QCloseEvent *event) @@ -562,45 +559,45 @@ void MainWindow::on_actionExit_triggered() quit(); } -void MainWindow::ShowAndSetConnection(ConnectionIdentifier fullIdentifier, bool SetConnection, bool ApplyConnection) +void MainWindow::ShowAndSetConnection(QvConnectionObject fullIdentifier, bool SetConnection, bool ApplyConnection) { - // Check empty again... - if (!connections.contains(fullIdentifier)) return; - - SetEditWidgetEnable(true); + //// Check empty again... + //if (!connections.contains(fullIdentifier)) return; // - // --------- BRGIN Show Connection - auto conf = connections[fullIdentifier]; + //SetEditWidgetEnable(true); + //// + //// --------- BRGIN Show Connection + //auto conf = connections[fullIdentifier]; + //// + //auto isComplexConfig = IsComplexConfig(conf.config); + //routeCountLabel->setText(isComplexConfig ? tr("Complex") : tr("Simple")); // - auto isComplexConfig = IsComplexConfig(conf.config); - routeCountLabel->setText(isComplexConfig ? tr("Complex") : tr("Simple")); - - if (conf.latency == 0.0) { - latencyLabel->setText(tr("No data")); - } else { - latencyLabel->setText(QSTRN(conf.latency) + " " + tr("ms")); - } - - if (conf.configType == CONNECTION_SUBSCRIPTION) { - routeCountLabel->setText(routeCountLabel->text().append(" (" + tr("Subscription") + ":" + conf.subscriptionName + ")")); - } - - // Get Connection info - auto host_port = MWGetConnectionInfo(fullIdentifier.IdentifierString()); - _hostLabel->setText(get<0>(host_port)); - _portLabel->setText(QSTRN(get<1>(host_port))); - _OutBoundTypeLabel->setText(get<2>(host_port)); - - // Set to currentConnection - if (SetConnection) { - CurrentSelectedItemPtr = FindItemByIdentifier(fullIdentifier); - CurrentConnectionIdentifier = fullIdentifier; - } - - // Restart Connection - if (ApplyConnection) { - on_reconnectButton_clicked(); - } + //if (conf.latency == 0.0) { + // latencyLabel->setText(tr("No data")); + //} else { + // latencyLabel->setText(QSTRN(conf.latency) + " " + tr("ms")); + //} + // + //if (conf.configType == CONNECTION_SUBSCRIPTION) { + // routeCountLabel->setText(routeCountLabel->text().append(" (" + tr("Subscription") + ":" + conf.subscriptionName + ")")); + //} + // + //// Get Connection info + //auto host_port = MWGetConnectionInfo(fullIdentifier.IdentifierString()); + //_hostLabel->setText(get<0>(host_port)); + //_portLabel->setText(QSTRN(get<1>(host_port))); + //_OutBoundTypeLabel->setText(get<2>(host_port)); + // + //// Set to currentConnection + //if (SetConnection) { + // CurrentSelectedItemPtr = FindItemByIdentifier(fullIdentifier); + // CurrentConnectionIdentifier = fullIdentifier; + //} + // + //// Restart Connection + //if (ApplyConnection) { + // on_reconnectButton_clicked(); + //} } void MainWindow::on_preferencesBtn_clicked() { @@ -610,12 +607,12 @@ void MainWindow::on_preferencesBtn_clicked() } void MainWindow::on_connectionListWidget_doubleClicked(const QModelIndex &index) { - Q_UNUSED(index) - - if (!IsSelectionConnectable) return; - - ShowAndSetConnection(ItemConnectionIdentifier(connectionListWidget->currentItem()), true, false); - on_reconnectButton_clicked(); + //Q_UNUSED(index) + // + //if (!IsSelectionConnectable) return; + // + //ShowAndSetConnection(ItemConnectionIdentifier(connectionListWidget->currentItem()), true, false); + //on_reconnectButton_clicked(); } void MainWindow::on_clearlogButton_clicked() { @@ -623,246 +620,248 @@ void MainWindow::on_clearlogButton_clicked() } void MainWindow::on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { - Q_UNUSED(previous) - isRenamingInProgress = false; - - if (!IsConnectableItem(current)) return; - - // no need to check !isRenamingInProgress since it's always true. - ShowAndSetConnection(ItemConnectionIdentifier(current), !vinstance->KernelStarted, false); - //on_connectionListWidget_itemClicked(current, 0); + //Q_UNUSED(previous) + //isRenamingInProgress = false; + // + //if (!IsConnectableItem(current)) return; + // + //// no need to check !isRenamingInProgress since it's always true. + //ShowAndSetConnection(ItemConnectionIdentifier(current), !vinstance->KernelStarted, false); + ////on_connectionListWidget_itemClicked(current, 0); } void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint &pos) { - Q_UNUSED(pos) - auto _pos = QCursor::pos(); - auto item = connectionListWidget->itemAt(connectionListWidget->mapFromGlobal(_pos)); - - if (IsConnectableItem(item)) { - connectionListMenu->popup(_pos); - } + //Q_UNUSED(pos) + //auto _pos = QCursor::pos(); + //auto item = connectionListWidget->itemAt(connectionListWidget->mapFromGlobal(_pos)); + // + //if (IsConnectableItem(item)) { + // connectionListMenu->popup(_pos); + //} } void MainWindow::on_action_RCM_RenameConnection_triggered() { - auto item = connectionListWidget->currentItem(); - SUBSCRIPTION_CONFIG_MODIFY_DENY(item) - item->setFlags(item->flags() | Qt::ItemIsEditable); - isRenamingInProgress = true; - connectionListWidget->editItem(item); - renameOriginalIdentifier = ItemConnectionIdentifier(item); + //auto item = connectionListWidget->currentItem(); + //SUBSCRIPTION_CONFIG_MODIFY_DENY(item) + //item->setFlags(item->flags() | Qt::ItemIsEditable); + //isRenamingInProgress = true; + //connectionListWidget->editItem(item); + //renameOriginalIdentifier = ItemConnectionIdentifier(item); } void MainWindow::on_connectionListWidget_itemChanged(QTreeWidgetItem *item, int) { - DEBUG(UI, "A connection ListViewItem is changed. This should ONLY occur when renaming an connection.") - - if (!isRenamingInProgress) { - return; - } - - isRenamingInProgress = false; - // In this case it's after we entered the name. - // and tell user you should not rename a config from subscription. - auto newIdentifier = renameOriginalIdentifier; - newIdentifier.connectionName = item->text(0); - LOG(CONNECTION, "RENAME: " + renameOriginalIdentifier.IdentifierString() + " -> " + newIdentifier.IdentifierString()) - - // If I really did some changes. - if (renameOriginalIdentifier != newIdentifier) { - bool canContinueRename = true; - - if (newIdentifier.connectionName.trimmed().isEmpty()) { - QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name cannot be empty")); - canContinueRename = false; - } - - if (GlobalConfig.configs.contains(newIdentifier.connectionName)) { - QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name has been used already, Please choose another.")); - canContinueRename = false; - } - - if (!IsValidFileName(newIdentifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION)) { - QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name you suggested is not valid, please try another.")); - canContinueRename = false; - } - - if (!canContinueRename) { - // Set the item text back - assert(item != nullptr); // Let's say the item should not be null - item->setText(0, renameOriginalIdentifier.connectionName); - return; - } - - // Change auto start config. - // |--------------=== In case it's not in a subscription --| - if (GlobalConfig.autoStartConfig == renameOriginalIdentifier) { - GlobalConfig.autoStartConfig = newIdentifier; - } - - // Replace the items in the current loaded config list and settings. - // Note: This original name should only be a reguular. - GlobalConfig.configs.removeOne(renameOriginalIdentifier.connectionName); - GlobalConfig.configs.push_back(newIdentifier.connectionName); - // - connections[newIdentifier] = connections.take(renameOriginalIdentifier); - RenameConnection(renameOriginalIdentifier.connectionName, newIdentifier.connectionName); - LOG(UI, "Saving a global config") - SaveGlobalConfig(GlobalConfig); - // - item->setData(0, Qt::UserRole, QVariant::fromValue(newIdentifier)); - - if (CurrentConnectionIdentifier == renameOriginalIdentifier) { - CurrentConnectionIdentifier = newIdentifier; - - if (vinstance->KernelStarted) { - on_reconnectButton_clicked(); - } - } - - //OnConfigListChanged(CurrentConnectionIdentifier.connectionName == renameOriginalName); - } + //DEBUG(UI, "A connection ListViewItem is changed. This should ONLY occur when renaming an connection.") + // + //if (!isRenamingInProgress) { + // return; + //} + // + //isRenamingInProgress = false; + //// In this case it's after we entered the name. + //// and tell user you should not rename a config from subscription. + //auto newIdentifier = renameOriginalIdentifier; + //newIdentifier.connectionName = item->text(0); + //LOG(CONNECTION, "RENAME: " + renameOriginalIdentifier.IdentifierString() + " -> " + newIdentifier.IdentifierString()) + // + //// If I really did some changes. + //if (renameOriginalIdentifier != newIdentifier) { + // bool canContinueRename = true; + // + // if (newIdentifier.connectionName.trimmed().isEmpty()) { + // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name cannot be empty")); + // canContinueRename = false; + // } + // + // QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); + // //if (GlobalConfig.configs.contains(newIdentifier.connectionName)) { + // // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name has been used already, Please choose another.")); + // // canContinueRename = false; + // //} + // + // if (!IsValidFileName(newIdentifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION)) { + // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name you suggested is not valid, please try another.")); + // canContinueRename = false; + // } + // + // if (!canContinueRename) { + // // Set the item text back + // assert(item != nullptr); // Let's say the item should not be null + // item->setText(0, renameOriginalIdentifier.connectionName); + // return; + // } + // + // // Change auto start config. + // // |--------------=== In case it's not in a subscription --| + // if (GlobalConfig.autoStartConfig == renameOriginalIdentifier) { + // GlobalConfig.autoStartConfig = newIdentifier; + // } + // + // QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); + // //// Replace the items in the current loaded config list and settings. + // //// Note: This original name should only be a reguular. + // //GlobalConfig.configs.removeOne(renameOriginalIdentifier.connectionName); + // //GlobalConfig.configs.push_back(newIdentifier.connectionName); + // // + // //connections[newIdentifier] = connections.take(renameOriginalIdentifier); + // //RenameConnection(renameOriginalIdentifier.connectionName, newIdentifier.connectionName); + // //LOG(UI, "Saving a global config") + // //SaveGlobalConfig(GlobalConfig); + // //// + // //item->setData(0, Qt::UserRole, QVariant::fromValue(newIdentifier)); + // // + // //if (CurrentConnectionIdentifier == renameOriginalIdentifier) { + // // CurrentConnectionIdentifier = newIdentifier; + // // + // // if (vinstance->KernelStarted) { + // // on_reconnectButton_clicked(); + // // } + // //} + // //OnConfigListChanged(CurrentConnectionIdentifier.connectionName == renameOriginalName); + //} } void MainWindow::on_removeConfigButton_clicked() { - QList connlist; - - for (auto item : connectionListWidget->selectedItems()) { - if (IsConnectableItem(item)) { - connlist.append(ItemConnectionIdentifier(item)); - } - } - - LOG(UI, "Selected " + QSTRN(connlist.count()) + " items") - - if (connlist.isEmpty()) { - // Remove nothing means doing nothing. - return; - } - - if (QvMessageBoxAsk(this, tr("Removing Connection(s)"), tr("Are you sure to remove selected connection(s)?")) != QMessageBox::Yes) { - return; - } - - // A triple-state flag which indicates if the user wants to remove the configs loaded from a subscription. - int subscriptionRemovalCheckStatus = -1; - - for (auto conn : connlist) { - if (conn == CurrentConnectionIdentifier) { - on_stopButton_clicked(); - CurrentConnectionIdentifier = ConnectionIdentifier(); - } - - auto connData = connections[conn]; - - // Remove auto start config. - if (GlobalConfig.autoStartConfig.subscriptionName == connData.subscriptionName && - GlobalConfig.autoStartConfig.connectionName == connData.connectionName) - // If all those settings match. - { - GlobalConfig.autoStartConfig.subscriptionName.clear(); - GlobalConfig.autoStartConfig.connectionName.clear(); - } - - if (connData.configType == CONNECTION_REGULAR) { - // Just remove the regular configs. - if (!connData.subscriptionName.isEmpty()) { - LOG(UI, "Unexpected subscription name in a single regular config.") - connData.subscriptionName.clear(); - } - - GlobalConfig.configs.removeOne(conn.connectionName); - - if (!RemoveConnection(conn.connectionName)) { - QvMessageBoxWarn(this, tr("Removing this Connection"), tr("Failed to delete connection file, please delete manually.")); - } - } else if (connData.configType == CONNECTION_SUBSCRIPTION) { - if (subscriptionRemovalCheckStatus == -1) { - subscriptionRemovalCheckStatus = (QvMessageBoxAsk(this, tr("Removing a subscription config"), tr("Do you want to remove the config loaded from a subscription?")) == QMessageBox::Yes) - ? 1 // Yes i want - : 0; // No please keep - } - - if (subscriptionRemovalCheckStatus == 1) { - if (!RemoveSubscriptionConnection(connData.subscriptionName, connData.connectionName)) { - QvMessageBoxWarn(this, tr("Removing this Connection"), tr("Failed to delete connection file, please delete manually.")); - } - } - } else { - LOG(SETTINGS, "Unknown config type -> Not regular nor subscription...") - } - } - - LOG(UI, "Saving GlobalConfig") - SaveGlobalConfig(GlobalConfig); - OnConfigListChanged(false); - ShowAndSetConnection(CurrentConnectionIdentifier, false, false); + QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); + //QList connlist; + // + //for (auto item : connectionListWidget->selectedItems()) { + // if (IsConnectableItem(item)) { + // connlist.append(ItemConnectionIdentifier(item)); + // } + //} + // + //LOG(UI, "Selected " + QSTRN(connlist.count()) + " items") + // + //if (connlist.isEmpty()) { + // // Remove nothing means doing nothing. + // return; + //} + // + //if (QvMessageBoxAsk(this, tr("Removing Connection(s)"), tr("Are you sure to remove selected connection(s)?")) != QMessageBox::Yes) { + // return; + //} + // + //// A triple-state flag which indicates if the user wants to remove the configs loaded from a subscription. + //int subscriptionRemovalCheckStatus = -1; + // + //for (auto conn : connlist) { + // if (conn == CurrentConnectionIdentifier) { + // on_stopButton_clicked(); + // CurrentConnectionIdentifier = ConnectionIdentifier(); + // } + // + // auto connData = connections[conn]; + // + // // Remove auto start config. + // if (GlobalConfig.autoStartConfig.subscriptionName == connData.subscriptionName && + // GlobalConfig.autoStartConfig.connectionName == connData.connectionName) + // // If all those settings match. + // { + // GlobalConfig.autoStartConfig.subscriptionName.clear(); + // GlobalConfig.autoStartConfig.connectionName.clear(); + // } + // + // if (connData.configType == CONNECTION_REGULAR) { + // // Just remove the regular configs. + // if (!connData.subscriptionName.isEmpty()) { + // LOG(UI, "Unexpected subscription name in a single regular config.") + // connData.subscriptionName.clear(); + // } + // + // GlobalConfig.configs.removeOne(conn.connectionName); + // + // if (!RemoveConnection(conn.connectionName)) { + // QvMessageBoxWarn(this, tr("Removing this Connection"), tr("Failed to delete connection file, please delete manually.")); + // } + // } else if (connData.configType == CONNECTION_SUBSCRIPTION) { + // if (subscriptionRemovalCheckStatus == -1) { + // subscriptionRemovalCheckStatus = (QvMessageBoxAsk(this, tr("Removing a subscription config"), tr("Do you want to remove the config loaded from a subscription?")) == QMessageBox::Yes) + // ? 1 // Yes i want + // : 0; // No please keep + // } + // + // if (subscriptionRemovalCheckStatus == 1) { + // if (!RemoveSubscriptionConnection(connData.subscriptionName, connData.connectionName)) { + // QvMessageBoxWarn(this, tr("Removing this Connection"), tr("Failed to delete connection file, please delete manually.")); + // } + // } + // } else { + // LOG(SETTINGS, "Unknown config type -> Not regular nor subscription...") + // } + //} + // + //LOG(UI, "Saving GlobalConfig") + //SaveGlobalConfig(GlobalConfig); + //OnConfigListChanged(false); + //ShowAndSetConnection(CurrentConnectionIdentifier, false, false); } void MainWindow::on_importConfigButton_clicked() { - ImportConfigWindow w(this); - auto configs = w.OpenImport(); - - if (!configs.isEmpty()) { - for (auto conf : configs) { - auto name = configs.key(conf, ""); - - if (name.isEmpty()) - continue; - - SaveConnectionConfig(conf, &name, false); - GlobalConfig.configs.push_back(name); - } - - SaveGlobalConfig(GlobalConfig); - OnConfigListChanged(false); - } + QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); + //ImportConfigWindow w(this); + //auto configs = w.OpenImport(); + //if (!configs.isEmpty()) { + // for (auto conf : configs) { + // auto name = configs.key(conf, ""); + // + // if (name.isEmpty()) + // continue; + // + // SaveConnectionConfig(conf, &name, false); + // GlobalConfig.configs.push_back(name); + // } + // + // SaveGlobalConfig(GlobalConfig); + // OnConfigListChanged(false); + //} } void MainWindow::on_editConfigButton_clicked() { - // Check if we have a connection selected... - if (!IsSelectionConnectable) { - QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a Config")); - return; - } - - auto firstSelected = connectionListWidget->selectedItems().first(); - auto _identifier = ItemConnectionIdentifier(firstSelected); - SUBSCRIPTION_CONFIG_MODIFY_ASK(firstSelected) + //// Check if we have a connection selected... + //if (!IsSelectionConnectable) { + // QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a Config")); + // return; + //} // - auto outBoundRoot = connections[_identifier].config; - CONFIGROOT root; - bool isChanged = false; - - if (IsComplexConfig(outBoundRoot)) { - LOG(UI, "INFO: Opening route editor.") - RouteEditor routeWindow(outBoundRoot, this); - root = routeWindow.OpenEditor(); - isChanged = routeWindow.result() == QDialog::Accepted; - } else { - LOG(UI, "INFO: Opening single connection edit window.") - OutboundEditor w(OUTBOUND(outBoundRoot["outbounds"].toArray().first().toObject()), this); - auto outboundEntry = w.OpenEditor(); - isChanged = w.result() == QDialog::Accepted; - QJsonArray outboundsList; - outboundsList.push_back(outboundEntry); - root.insert("outbounds", outboundsList); - } - - QString alias = _identifier.connectionName; - - if (isChanged) { - if (CheckConfigType(firstSelected, SUBSCRIPTION)) { - auto name = connections[_identifier].connectionName; - // Assume name will not change. - SaveSubscriptionConfig(root, connections[_identifier].subscriptionName, &name); - } else { - connections[_identifier].config = root; - // true indicates the alias will NOT change - SaveConnectionConfig(root, &alias, true); - } - - OnConfigListChanged(alias == CurrentConnectionIdentifier.connectionName); - } + //auto firstSelected = connectionListWidget->selectedItems().first(); + //auto _identifier = ItemConnectionIdentifier(firstSelected); + //SUBSCRIPTION_CONFIG_MODIFY_ASK(firstSelected) + //// + //auto outBoundRoot = connections[_identifier].config; + //CONFIGROOT root; + //bool isChanged = false; + // + //if (IsComplexConfig(outBoundRoot)) { + // LOG(UI, "INFO: Opening route editor.") + // RouteEditor routeWindow(outBoundRoot, this); + // root = routeWindow.OpenEditor(); + // isChanged = routeWindow.result() == QDialog::Accepted; + //} else { + // LOG(UI, "INFO: Opening single connection edit window.") + // OutboundEditor w(OUTBOUND(outBoundRoot["outbounds"].toArray().first().toObject()), this); + // auto outboundEntry = w.OpenEditor(); + // isChanged = w.result() == QDialog::Accepted; + // QJsonArray outboundsList; + // outboundsList.push_back(outboundEntry); + // root.insert("outbounds", outboundsList); + //} + // + //QString alias = _identifier.connectionName; + // + //if (isChanged) { + // if (CheckConfigType(firstSelected, SUBSCRIPTION)) { + // auto name = connections[_identifier].connectionName; + // // Assume name will not change. + // SaveSubscriptionConfig(root, connections[_identifier].subscriptionName, &name); + // } else { + // connections[_identifier].config = root; + // // true indicates the alias will NOT change + // SaveConnectionConfig(root, &alias, true); + // } + // + // OnConfigListChanged(alias == CurrentConnectionIdentifier.connectionName); + //} } void MainWindow::on_reconnectButton_clicked() { @@ -872,57 +871,57 @@ void MainWindow::on_reconnectButton_clicked() void MainWindow::on_action_RCM_ConvToComplex_triggered() { - // Check if we have a connection selected... - if (!IsSelectionConnectable) { - QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a Config")); - return; - } - - auto selectedFirst = connectionListWidget->currentItem(); - auto _identifier = ItemConnectionIdentifier(selectedFirst); - SUBSCRIPTION_CONFIG_MODIFY_DENY(selectedFirst) + //// Check if we have a connection selected... + //if (!IsSelectionConnectable) { + // QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a Config")); + // return; + //} // - auto outBoundRoot = connections[_identifier].config; - CONFIGROOT root; - bool isChanged = false; + //auto selectedFirst = connectionListWidget->currentItem(); + //auto _identifier = ItemConnectionIdentifier(selectedFirst); + //SUBSCRIPTION_CONFIG_MODIFY_DENY(selectedFirst) + //// + //auto outBoundRoot = connections[_identifier].config; + //CONFIGROOT root; + //bool isChanged = false; + //// + //LOG(UI, "INFO: Opening route editor.") + //RouteEditor routeWindow(outBoundRoot, this); + //root = routeWindow.OpenEditor(); + //isChanged = routeWindow.result() == QDialog::Accepted; + //QString alias = _identifier.connectionName; // - LOG(UI, "INFO: Opening route editor.") - RouteEditor routeWindow(outBoundRoot, this); - root = routeWindow.OpenEditor(); - isChanged = routeWindow.result() == QDialog::Accepted; - QString alias = _identifier.connectionName; - - if (isChanged) { - connections[_identifier].config = root; - // true indicates the alias will NOT change - SaveConnectionConfig(root, &alias, true); - OnConfigListChanged(_identifier == CurrentConnectionIdentifier); - ShowAndSetConnection(CurrentConnectionIdentifier, false, false); - } + //if (isChanged) { + // connections[_identifier].config = root; + // // true indicates the alias will NOT change + // SaveConnectionConfig(root, &alias, true); + // OnConfigListChanged(_identifier == CurrentConnectionIdentifier); + // ShowAndSetConnection(CurrentConnectionIdentifier, false, false); + //} } void MainWindow::on_action_RCM_EditJson_triggered() { - // Check if we have a connection selected... - if (!IsSelectionConnectable) { - QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a Config")); - return; - } - - auto selectedFirst = connectionListWidget->currentItem(); - auto _identifier = ItemConnectionIdentifier(selectedFirst); - SUBSCRIPTION_CONFIG_MODIFY_DENY(selectedFirst) - JsonEditor w(connections[_identifier].config, this); - auto root = CONFIGROOT(w.OpenEditor()); - bool isChanged = w.result() == QDialog::Accepted; - QString alias = _identifier.connectionName; - - if (isChanged) { - connections[_identifier].config = root; - // Alias here will not change. - SaveConnectionConfig(root, &alias, true); - ShowAndSetConnection(CurrentConnectionIdentifier, false, false); - } + //// Check if we have a connection selected... + //if (!IsSelectionConnectable) { + // QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a Config")); + // return; + //} + // + //auto selectedFirst = connectionListWidget->currentItem(); + //auto _identifier = ItemConnectionIdentifier(selectedFirst); + //SUBSCRIPTION_CONFIG_MODIFY_DENY(selectedFirst) + //JsonEditor w(connections[_identifier].config, this); + //auto root = CONFIGROOT(w.OpenEditor()); + //bool isChanged = w.result() == QDialog::Accepted; + //QString alias = _identifier.connectionName; + // + //if (isChanged) { + // connections[_identifier].config = root; + // // Alias here will not change. + // SaveConnectionConfig(root, &alias, true); + // ShowAndSetConnection(CurrentConnectionIdentifier, false, false); + //} } void MainWindow::on_editJsonBtn_clicked() { @@ -931,55 +930,55 @@ void MainWindow::on_editJsonBtn_clicked() } void MainWindow::on_pingTestBtn_clicked() { - // Get data from UI - QList aliases; - auto selection = connectionListWidget->selectedItems(); - - if (selection.count() == 0) { - // Ping ALL connections, warning. - if (QvMessageBoxAsk(this, tr("Latency Test"), tr("You are about to run latency test on all servers, do you want to continue?")) == QMessageBox::Yes) { - aliases.append(connections.keys()); - } - } else { - for (auto i = 0; i < selection.count(); i++) { - auto thisItem = selection[i]; - - if (thisItem->childCount() > 0) { - // So we add another check to make sure the selected one is a subscription entry. - // Loop to add all sub-connections to the list. - for (auto j = 0; j < thisItem->childCount(); j++) { - aliases.append(ItemConnectionIdentifier(thisItem->child(j))); - } - } else { - aliases.append(ItemConnectionIdentifier(thisItem)); - } - } - } - - LOG(UI, "Will perform latency test on " + QSTRN(aliases.count()) + " hosts.") - latencyLabel->setText(tr("Testing...")); - - for (auto alias : aliases) { - MWTryPingConnection(alias); - } + //// Get data from UI + //QList aliases; + //auto selection = connectionListWidget->selectedItems(); + // + //if (selection.count() == 0) { + // // Ping ALL connections, warning. + // if (QvMessageBoxAsk(this, tr("Latency Test"), tr("You are about to run latency test on all servers, do you want to continue?")) == QMessageBox::Yes) { + // aliases.append(connections.keys()); + // } + //} else { + // for (auto i = 0; i < selection.count(); i++) { + // auto thisItem = selection[i]; + // + // if (thisItem->childCount() > 0) { + // // So we add another check to make sure the selected one is a subscription entry. + // // Loop to add all sub-connections to the list. + // for (auto j = 0; j < thisItem->childCount(); j++) { + // aliases.append(ItemConnectionIdentifier(thisItem->child(j))); + // } + // } else { + // aliases.append(ItemConnectionIdentifier(thisItem)); + // } + // } + //} + // + //LOG(UI, "Will perform latency test on " + QSTRN(aliases.count()) + " hosts.") + //latencyLabel->setText(tr("Testing...")); + // + //for (auto alias : aliases) { + // MWTryPingConnection(alias); + //} } void MainWindow::on_shareBtn_clicked() { - // Share QR - if (!IsSelectionConnectable) { - return; - } - - auto _identifier = ItemConnectionIdentifier(connectionListWidget->currentItem()); - auto root = connections[_identifier].config; - auto type = get<2>(GetConnectionInfo(root)); - - if (!IsComplexConfig(root) && (type == "vmess" || type == "shadowsocks")) { - ConfigExporter v(root, _identifier, this); - v.OpenExport(); - } else { - QvMessageBoxWarn(this, tr("Share Connection"), tr("There're no support of sharing configs other than vmess and shadowsocks")); - } + //// Share QR + //if (!IsSelectionConnectable) { + // return; + //} + // + //auto _identifier = ItemConnectionIdentifier(connectionListWidget->currentItem()); + //auto root = connections[_identifier].config; + //auto type = get<2>(GetConnectionInfo(root)); + // + //if (!IsComplexConfig(root) && (type == "vmess" || type == "shadowsocks")) { + // ConfigExporter v(root, _identifier, this); + // v.OpenExport(); + //} else { + // QvMessageBoxWarn(this, tr("Share Connection"), tr("There're no support of sharing configs other than vmess and shadowsocks")); + //} } void MainWindow::on_action_RCM_ShareQR_triggered() { @@ -987,63 +986,64 @@ void MainWindow::on_action_RCM_ShareQR_triggered() } void MainWindow::timerEvent(QTimerEvent *event) { - // Calling base class - QMainWindow::timerEvent(event); - - if (event->timerId() == speedTimerId) { - auto _totalSpeedUp = vinstance->getAllSpeedUp(); - auto _totalSpeedDown = vinstance->getAllSpeedDown(); - auto _totalDataUp = vinstance->getAllDataUp(); - auto _totalDataDown = vinstance->getAllDataDown(); - // - speedChartView->AddPointData(_totalSpeedUp, _totalSpeedDown); - // - auto totalSpeedUp = FormatBytes(_totalSpeedUp) + "/s"; - auto totalSpeedDown = FormatBytes(_totalSpeedDown) + "/s"; - auto totalDataUp = FormatBytes(_totalDataUp); - auto totalDataDown = FormatBytes(_totalDataDown); - // - netspeedLabel->setText(totalSpeedUp + NEWLINE + totalSpeedDown); - dataamountLabel->setText(totalDataUp + NEWLINE + totalDataDown); - // - hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + CurrentConnectionIdentifier.IdentifierString() + NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); - } else if (event->timerId() == qvLogTimerId) { - QString lastLog = readLastLog(); - - if (!lastLog.isEmpty()) { - qvAppLogBrowser->append(lastLog); - } - - CleanUpLogs(vCoreLogBrowser) - } else if (event->timerId() == pingTimerId) { - MWTryPingConnection(CurrentConnectionIdentifier); - } + //// Calling base class + //QMainWindow::timerEvent(event); + // + //if (event->timerId() == speedTimerId) { + // auto _totalSpeedUp = vinstance->getAllSpeedUp(); + // auto _totalSpeedDown = vinstance->getAllSpeedDown(); + // auto _totalDataUp = vinstance->getAllDataUp(); + // auto _totalDataDown = vinstance->getAllDataDown(); + // // + // speedChartView->AddPointData(_totalSpeedUp, _totalSpeedDown); + // // + // auto totalSpeedUp = FormatBytes(_totalSpeedUp) + "/s"; + // auto totalSpeedDown = FormatBytes(_totalSpeedDown) + "/s"; + // auto totalDataUp = FormatBytes(_totalDataUp); + // auto totalDataDown = FormatBytes(_totalDataDown); + // // + // netspeedLabel->setText(totalSpeedUp + NEWLINE + totalSpeedDown); + // dataamountLabel->setText(totalDataUp + NEWLINE + totalDataDown); + // // + // hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + CurrentConnectionIdentifier.IdentifierString() + NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); + //} else if (event->timerId() == qvLogTimerId) { + // QString lastLog = readLastLog(); + // + // if (!lastLog.isEmpty()) { + // qvAppLogBrowser->append(lastLog); + // } + // + // CleanUpLogs(vCoreLogBrowser) + //} else if (event->timerId() == pingTimerId) { + // MWTryPingConnection(CurrentConnectionIdentifier); + //} } void MainWindow::on_duplicateBtn_clicked() { - if (!IsSelectionConnectable) { - return; - } - - auto selectedFirst = connectionListWidget->currentItem(); - auto _identifier = ItemConnectionIdentifier(selectedFirst); - SUBSCRIPTION_CONFIG_MODIFY_ASK(selectedFirst) - CONFIGROOT conf; - // Alias may change. - QString alias = _identifier.connectionName; - bool isComplex = IsComplexConfig(connections[_identifier].config); - - if (connections[_identifier].configType == CONNECTION_REGULAR) { - conf = ConvertConfigFromFile(QV2RAY_CONFIG_DIR + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex); - } else { - conf = ConvertConfigFromFile(QV2RAY_SUBSCRIPTION_DIR + _identifier.subscriptionName + "/" + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex); - alias = _identifier.subscriptionName + "_" + _identifier.connectionName; - } - - SaveConnectionConfig(conf, &alias, false); - GlobalConfig.configs.push_back(alias); - SaveGlobalConfig(GlobalConfig); - this->OnConfigListChanged(false); + QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); + //if (!IsSelectionConnectable) { + // return; + //} + // + //auto selectedFirst = connectionListWidget->currentItem(); + //auto _identifier = ItemConnectionIdentifier(selectedFirst); + //SUBSCRIPTION_CONFIG_MODIFY_ASK(selectedFirst) + //CONFIGROOT conf; + //// Alias may change. + //QString alias = _identifier.connectionName; + //bool isComplex = IsComplexConfig(connections[_identifier].config); + // + //if (connections[_identifier].configType == CONNECTION_REGULAR) { + // conf = ConvertConfigFromFile(QV2RAY_CONFIG_DIR + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex); + //} else { + // conf = ConvertConfigFromFile(QV2RAY_SUBSCRIPTION_DIR + _identifier.subscriptionName + "/" + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex); + // alias = _identifier.subscriptionName + "_" + _identifier.connectionName; + //} + // + //SaveConnectionConfig(conf, &alias, false); + //GlobalConfig.configs.push_back(alias); + //SaveGlobalConfig(GlobalConfig); + //this->OnConfigListChanged(false); } void MainWindow::on_subsButton_clicked() @@ -1055,37 +1055,36 @@ void MainWindow::on_subsButton_clicked() void MainWindow::on_connectionListWidget_itemSelectionChanged() { - if (!isRenamingInProgress && !IsSelectionConnectable) { - // If renaming is not in progress AND our selection is invalid. - CurrentSelectedItemPtr = nullptr; - SetEditWidgetEnable(false); - routeCountLabel->setText(tr("N/A")); - _OutBoundTypeLabel->setText(tr("N/A")); - _hostLabel->setText(tr("N/A")); - _portLabel->setText(tr("N/A")); - latencyLabel->setText(tr("N/A")); - } else { - if (!connectionListWidget->selectedItems().isEmpty()) { - on_connectionListWidget_currentItemChanged(connectionListWidget->selectedItems().first(), nullptr); - CurrentSelectedItemPtr = connectionListWidget->selectedItems().first(); - } - } + //if (!isRenamingInProgress && !IsSelectionConnectable) { + // // If renaming is not in progress AND our selection is invalid. + // CurrentSelectedItemPtr = nullptr; + // SetEditWidgetEnable(false); + // routeCountLabel->setText(tr("N/A")); + // _OutBoundTypeLabel->setText(tr("N/A")); + // _hostLabel->setText(tr("N/A")); + // _portLabel->setText(tr("N/A")); + // latencyLabel->setText(tr("N/A")); + //} else { + // if (!connectionListWidget->selectedItems().isEmpty()) { + // on_connectionListWidget_currentItemChanged(connectionListWidget->selectedItems().first(), nullptr); + // CurrentSelectedItemPtr = connectionListWidget->selectedItems().first(); + // } + //} } void MainWindow::onPingFinished(QvTCPingData data) { - if (!connections.contains(data.connectionIdentifier)) { - return; - } - - connections[data.connectionIdentifier].latency = data.avg; - - if (IsConnectableItem(CurrentSelectedItemPtr)) { - ShowAndSetConnection(ItemConnectionIdentifier(CurrentSelectedItemPtr), false, false); - } + //if (!connections.contains(data.connectionIdentifier)) { + // return; + //} + //connections[data.connectionIdentifier].latency = data.avg; + //if (IsConnectableItem(CurrentSelectedItemPtr)) { + // ShowAndSetConnection(ItemConnectionIdentifier(CurrentSelectedItemPtr), false, false); + //} } QString MainWindow::GetCurrentConnectedConfigName() { - return CurrentConnectionIdentifier.IdentifierString(); + return ""; + //return CurrentConnectionIdentifier.IdentifierString(); } diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 72a97413..2faf98d4 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -25,7 +25,7 @@ enum QvConnectionType { CONNECTION_SUBSCRIPTION = 2 }; // -struct ConnectionObject : ConnectionIdentifier { +struct ConnectionObject : QvConnectionObject { QvConnectionType configType; double latency; CONFIGROOT config; @@ -75,7 +75,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow public: static MainWindow *mwInstance; - ConnectionIdentifier CurrentConnectionIdentifier; + QvConnectionObject CurrentConnectionIdentifier; V2rayKernelInstance *vinstance; QString GetCurrentConnectedConfigName(); @@ -94,7 +94,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow private: void SetEditWidgetEnable(bool enabled); - void ShowAndSetConnection(ConnectionIdentifier fullIdentifier, bool SetConnection, bool Apply); + void ShowAndSetConnection(QvConnectionObject fullIdentifier, bool SetConnection, bool Apply); CONFIGROOT currentFullConfig; // // Charts @@ -103,9 +103,9 @@ class MainWindow : public QMainWindow, Ui::MainWindow QMenu *connectionListMenu; /// Key --> ListWidget.item.text - QMap connections; + QMap connections; // - ConnectionIdentifier renameOriginalIdentifier; + QvConnectionObject renameOriginalIdentifier; bool isRenamingInProgress; // // ID for QTimers @@ -146,12 +146,12 @@ class MainWindow : public QMainWindow, Ui::MainWindow void MWFindAndStartAutoConfig(); bool MWtryStartConnection(); void MWStopConnection(); - void MWTryPingConnection(const ConnectionIdentifier &alias); - tuple MWGetConnectionInfo(const ConnectionIdentifier &alias); + void MWTryPingConnection(const QvConnectionObject &alias); + tuple MWGetConnectionInfo(const QvConnectionObject &alias); void MWSetSystemProxy(); void MWClearSystemProxy(bool); void CheckSubscriptionsUpdate(); // - QTreeWidgetItem *FindItemByIdentifier(ConnectionIdentifier identifier); + QTreeWidgetItem *FindItemByIdentifier(QvConnectionObject identifier); }; diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index 2b1fb1d3..f1715e67 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -5,59 +5,59 @@ #include "components/proxy/QvProxyConfigurator.hpp" #include "core/connection/Generation.hpp" -QTreeWidgetItem *MainWindow::FindItemByIdentifier(ConnectionIdentifier identifier) +QTreeWidgetItem *MainWindow::FindItemByIdentifier(QvConnectionObject identifier) { - // First filter out all items with our config name. - auto items = connectionListWidget->findItems(identifier.connectionName, Qt::MatchExactly | Qt::MatchRecursive); - - for (auto item : items) { - // This connectable prevents the an item with (which is the parent node of a subscription, having the same - // -- name as our current connected name) - if (!IsConnectableItem(item)) { - LOG(UI, "Invalid Item found: " + item->text(0)) - continue; - } - - auto thisIdentifier = ItemConnectionIdentifier(item); - DEBUG(UI, "Item Identifier: " + thisIdentifier.IdentifierString()) - - if (identifier == thisIdentifier) { - return item; - } - } - - LOG(UI, "Warning: Failed to find an item named: " + identifier.IdentifierString()) + //// First filter out all items with our config name. + //auto items = connectionListWidget->findItems(identifier.connectionName, Qt::MatchExactly | Qt::MatchRecursive); + // + //for (auto item : items) { + // // This connectable prevents the an item with (which is the parent node of a subscription, having the same + // // -- name as our current connected name) + // if (!IsConnectableItem(item)) { + // LOG(UI, "Invalid Item found: " + item->text(0)) + // continue; + // } + // + // auto thisIdentifier = ItemConnectionIdentifier(item); + // DEBUG(UI, "Item Identifier: " + thisIdentifier.IdentifierString()) + // + // if (identifier == thisIdentifier) { + // return item; + // } + //} + // + //LOG(UI, "Warning: Failed to find an item named: " + identifier.IdentifierString()) return nullptr; } void MainWindow::MWFindAndStartAutoConfig() { - if (!GlobalConfig.autoStartConfig.connectionName.isEmpty()) { - // User has auto start configured, we try to find that connection item. - auto name = GlobalConfig.autoStartConfig.subscriptionName.isEmpty() - ? GlobalConfig.autoStartConfig.connectionName - : GlobalConfig.autoStartConfig.connectionName + " (" + tr("Subscription:") + " " + GlobalConfig.autoStartConfig.subscriptionName + ")"; - // - LOG(UI, "Found auto start config: " + name) - auto item = FindItemByIdentifier(GlobalConfig.autoStartConfig); - - if (item != nullptr) { - // We found the item required and start it. - connectionListWidget->setCurrentItem(item); - on_connectionListWidget_currentItemChanged(item, nullptr); - connectionListWidget->scrollToItem(item); - tray_RootMenu->actions()[0]->setText(tr("Show")); - on_startButton_clicked(); - } else { - QvMessageBoxWarn(this, tr("Autostarting a config"), tr("Could not find a specified config named: ") + NEWLINE + - name + NEWLINE + NEWLINE + - tr("Please reset the settings in Preference Window")); - } - } else if (connectionListWidget->topLevelItemCount() > 0) { - // Make the first one our default selected item. - connectionListWidget->setCurrentItem(connectionListWidget->topLevelItem(0)); - ShowAndSetConnection(ItemConnectionIdentifier(connectionListWidget->topLevelItem(0)), true, false); - } + //if (!GlobalConfig.autoStartConfig.connectionName.isEmpty()) { + // // User has auto start configured, we try to find that connection item. + // auto name = GlobalConfig.autoStartConfig.subscriptionName.isEmpty() + // ? GlobalConfig.autoStartConfig.connectionName + // : GlobalConfig.autoStartConfig.connectionName + " (" + tr("Subscription:") + " " + GlobalConfig.autoStartConfig.subscriptionName + ")"; + // // + // LOG(UI, "Found auto start config: " + name) + // auto item = FindItemByIdentifier(GlobalConfig.autoStartConfig); + // + // if (item != nullptr) { + // // We found the item required and start it. + // connectionListWidget->setCurrentItem(item); + // on_connectionListWidget_currentItemChanged(item, nullptr); + // connectionListWidget->scrollToItem(item); + // tray_RootMenu->actions()[0]->setText(tr("Show")); + // on_startButton_clicked(); + // } else { + // QvMessageBoxWarn(this, tr("Autostarting a config"), tr("Could not find a specified config named: ") + NEWLINE + + // name + NEWLINE + NEWLINE + + // tr("Please reset the settings in Preference Window")); + // } + //} else if (connectionListWidget->topLevelItemCount() > 0) { + // // Make the first one our default selected item. + // connectionListWidget->setCurrentItem(connectionListWidget->topLevelItem(0)); + // ShowAndSetConnection(ItemConnectionIdentifier(connectionListWidget->topLevelItem(0)), true, false); + //} } void MainWindow::MWClearSystemProxy(bool showMessage) @@ -79,7 +79,8 @@ void MainWindow::MWSetSystemProxy() bool socksEnabled = GlobalConfig.inboundConfig.useSocks; // // Set system proxy if necessary - bool isComplex = IsComplexConfig(connections[CurrentConnectionIdentifier].config); + //bool isComplex = IsComplexConfig(connections[CurrentConnectionIdentifier].config); + bool isComplex = true; if (!isComplex) { // Is simple config and we will try to set system proxy. @@ -133,58 +134,59 @@ void MainWindow::MWSetSystemProxy() bool MainWindow::MWtryStartConnection() { - auto connectionRoot = connections[CurrentConnectionIdentifier].config; - currentFullConfig = GenerateRuntimeConfig(connectionRoot); - bool startFlag = this->vinstance->StartConnection(currentFullConfig); - - if (startFlag) { - bool usePAC = GlobalConfig.inboundConfig.pacConfig.enablePAC; - bool pacUseSocks = GlobalConfig.inboundConfig.pacConfig.useSocksProxy; - bool httpEnabled = GlobalConfig.inboundConfig.useHTTP; - bool socksEnabled = GlobalConfig.inboundConfig.useSocks; - - if (usePAC) { - bool canStartPAC = true; - QString pacProxyString; // Something like this --> SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT; http://proxy:8080 - auto pacIP = GlobalConfig.inboundConfig.pacConfig.localIP; - - if (pacIP.isEmpty()) { - LOG(PROXY, "PAC Local IP is empty, default to 127.0.0.1") - pacIP = "127.0.0.1"; - } - - if (pacUseSocks) { - if (socksEnabled) { - pacProxyString = "SOCKS5 " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.socks_port); - } else { - LOG(UI, "PAC is using SOCKS, but it is not enabled") - QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use SOCKS, but it is not enabled")); - canStartPAC = false; - } - } else { - if (httpEnabled) { - pacProxyString = "PROXY " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.http_port); - } else { - LOG(UI, "PAC is using HTTP, but it is not enabled") - QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use HTTP, but it is not enabled")); - canStartPAC = false; - } - } - - if (canStartPAC) { - pacServer.SetProxyString(pacProxyString); - pacServer.StartListen(); - } else { - LOG(PROXY, "Not starting PAC due to previous error.") - } - } - - if (GlobalConfig.inboundConfig.setSystemProxy) { - MWSetSystemProxy(); - } - } - - return startFlag; + //auto connectionRoot = connections[CurrentConnectionIdentifier].config; + //currentFullConfig = GenerateRuntimeConfig(connectionRoot); + //bool startFlag = this->vinstance->StartConnection(currentFullConfig); + // + //if (startFlag) { + // bool usePAC = GlobalConfig.inboundConfig.pacConfig.enablePAC; + // bool pacUseSocks = GlobalConfig.inboundConfig.pacConfig.useSocksProxy; + // bool httpEnabled = GlobalConfig.inboundConfig.useHTTP; + // bool socksEnabled = GlobalConfig.inboundConfig.useSocks; + // + // if (usePAC) { + // bool canStartPAC = true; + // QString pacProxyString; // Something like this --> SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT; http://proxy:8080 + // auto pacIP = GlobalConfig.inboundConfig.pacConfig.localIP; + // + // if (pacIP.isEmpty()) { + // LOG(PROXY, "PAC Local IP is empty, default to 127.0.0.1") + // pacIP = "127.0.0.1"; + // } + // + // if (pacUseSocks) { + // if (socksEnabled) { + // pacProxyString = "SOCKS5 " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.socks_port); + // } else { + // LOG(UI, "PAC is using SOCKS, but it is not enabled") + // QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use SOCKS, but it is not enabled")); + // canStartPAC = false; + // } + // } else { + // if (httpEnabled) { + // pacProxyString = "PROXY " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.http_port); + // } else { + // LOG(UI, "PAC is using HTTP, but it is not enabled") + // QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use HTTP, but it is not enabled")); + // canStartPAC = false; + // } + // } + // + // if (canStartPAC) { + // pacServer.SetProxyString(pacProxyString); + // pacServer.StartListen(); + // } else { + // LOG(PROXY, "Not starting PAC due to previous error.") + // } + // } + // + // if (GlobalConfig.inboundConfig.setSystemProxy) { + // MWSetSystemProxy(); + // } + //} + // + //return startFlag; + return false; } void MainWindow::MWStopConnection() @@ -202,7 +204,7 @@ void MainWindow::MWStopConnection() } } -void MainWindow::MWTryPingConnection(const ConnectionIdentifier &alias) +void MainWindow::MWTryPingConnection(const QvConnectionObject &alias) { try { auto info = MWGetConnectionInfo(alias); @@ -214,12 +216,12 @@ void MainWindow::MWTryPingConnection(const ConnectionIdentifier &alias) } } -tuple MainWindow::MWGetConnectionInfo(const ConnectionIdentifier &alias) +tuple MainWindow::MWGetConnectionInfo(const QvConnectionObject &alias) { - if (!connections.contains(alias)) - return make_tuple(tr("N/A"), 0, tr("N/A")); - - return GetConnectionInfo(connections[alias].config); + //if (!connections.contains(alias)) + // return make_tuple(tr("N/A"), 0, tr("N/A")); + // + //return GetConnectionInfo(connections[alias].config); } void MainWindow::CheckSubscriptionsUpdate() diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index fd661d4c..5af4d939 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -147,24 +147,26 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), CurrentBarPageId = 0; // // Empty for global config. - auto autoSub = CurrentConfig.autoStartConfig.subscriptionName; - auto autoCon = CurrentConfig.autoStartConfig.connectionName; - autoStartConnCombo->addItem(""); + //auto autoSub = CurrentConfig.autoStartConfig.subscriptionName; + //auto autoCon = CurrentConfig.autoStartConfig.connectionName; + //autoStartConnCombo->addItem(""); + QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - for (auto item : CurrentConfig.subscriptions.keys()) { - autoStartSubsCombo->addItem(item); - } - - autoStartSubsCombo->setCurrentText(autoSub); - - if (CurrentConfig.autoStartConfig.subscriptionName.isEmpty()) { - autoStartConnCombo->addItems(CurrentConfig.configs); - } else { - auto list = GetSubscriptionConnection(autoSub); - autoStartConnCombo->addItems(list.keys()); - } - - autoStartConnCombo->setCurrentText(autoCon); + // TODO: Now use grouping, subscriptions are the special type of group + //autoStartConnCombo->setCurrentText(autoCon);for (auto item : CurrentConfig.subscriptions.keys()) { + // autoStartSubsCombo->addItem(item); + //} + // + //autoStartSubsCombo->setCurrentText(autoSub); + // + //if (CurrentConfig.autoStartConfig.subscriptionName.isEmpty()) { + // autoStartConnCombo->addItems(CurrentConfig.configs); + //} else { + // auto list = GetSubscriptionConnection(autoSub); + // autoStartConnCombo->addItems(list.keys()); + //} + // + // // FP Settings if (CurrentConfig.connectionConfig.forwardProxyConfig.type.trimmed().isEmpty()) { @@ -936,22 +938,24 @@ void PreferencesWindow::on_pacProxyTxt_textEdited(const QString &arg1) void PreferencesWindow::on_autoStartSubsCombo_currentIndexChanged(const QString &arg1) { LOADINGCHECK - CurrentConfig.autoStartConfig.subscriptionName = arg1; - autoStartConnCombo->clear(); - - if (arg1.isEmpty()) { - autoStartConnCombo->addItem(""); - autoStartConnCombo->addItems(CurrentConfig.configs); - } else { - auto list = GetSubscriptionConnection(arg1); - autoStartConnCombo->addItems(list.keys()); - } + QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); + //CurrentConfig.autoStartConfig.subscriptionName = arg1; + //autoStartConnCombo->clear(); + // + //if (arg1.isEmpty()) { + // autoStartConnCombo->addItem(""); + // autoStartConnCombo->addItems(CurrentConfig.configs); + //} else { + // auto list = GetSubscriptionConnection(arg1); + // autoStartConnCombo->addItems(list.keys()); + //} } void PreferencesWindow::on_autoStartConnCombo_currentIndexChanged(const QString &arg1) { LOADINGCHECK - CurrentConfig.autoStartConfig.connectionName = arg1; + QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); + //CurrentConfig.autoStartConfig.connectionName = arg1; } void PreferencesWindow::on_startWithLoginCB_stateChanged(int arg1) diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 72f586d3..0ef41afc 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -34,7 +34,7 @@ QPair SubscribeEditor::GetSelectedConfig() return currentSelectedConfig; } -void SubscribeEditor::LoadSubscriptionList(QMap list) +void SubscribeEditor::LoadSubscriptionList(QMap list) { subscriptionList->clear(); @@ -98,13 +98,13 @@ void SubscribeEditor::on_updateButton_clicked() subscriptions.remove(currentSubName); subNameTxt->setText(newName); // + QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); // Update auto-start config if possible - auto ASsetting = GlobalConfig.autoStartConfig.subscriptionName; - - if (ASsetting == currentSubName) { - GlobalConfig.autoStartConfig.subscriptionName = newName; - } - + //auto ASsetting = GlobalConfig.autoStartConfig.subscriptionName; + // + //if (ASsetting == currentSubName) { + // GlobalConfig.autoStartConfig.subscriptionName = newName; + //} SaveGlobalConfig(GlobalConfig); // This will set the name to the new name. LoadSubscriptionList(subscriptions); @@ -174,12 +174,11 @@ void SubscribeEditor::on_removeSubsButton_clicked() QDir(QV2RAY_SUBSCRIPTION_DIR + name).removeRecursively(); } - // If removed a whole subscription... - if (GlobalConfig.autoStartConfig.subscriptionName == name) { - GlobalConfig.autoStartConfig = ConnectionIdentifier(); - SaveGlobalConfig(GlobalConfig); - } - + //// If removed a whole subscription... + //if (GlobalConfig.autoStartConfig.subscriptionName == name) { + // GlobalConfig.autoStartConfig = QvConnectionObject(); + // SaveGlobalConfig(GlobalConfig); + //} groupBox_2->setEnabled(subscriptionList->count() > 0); SaveConfig(); } @@ -212,7 +211,7 @@ void SubscribeEditor::on_subscriptionList_currentRowChanged(int currentRow) void SubscribeEditor::SaveConfig() { - QMap newConf; + QMap newConf; for (auto _ : subscriptions.toStdMap()) { if (!_.second.address.isEmpty()) { diff --git a/src/ui/w_SubscriptionManager.hpp b/src/ui/w_SubscriptionManager.hpp index 3abc7ce0..4116778e 100644 --- a/src/ui/w_SubscriptionManager.hpp +++ b/src/ui/w_SubscriptionManager.hpp @@ -38,11 +38,11 @@ class SubscribeEditor : public QDialog, private Ui::w_SubscribeEditor private: void StartUpdateSubscription(const QString &subscriptionName); void SaveConfig(); - void LoadSubscriptionList(QMap list); + void LoadSubscriptionList(QMap list); bool isUpdateInProgress = false; QvHttpRequestHelper helper; QPair currentSelectedConfig; - QMap subscriptions; + QMap subscriptions; QString currentSubName; }; diff --git a/src/ui/widgets/ConnectionWidget.cpp b/src/ui/widgets/ConnectionWidget.cpp index 9101f2a1..663ac14e 100644 --- a/src/ui/widgets/ConnectionWidget.cpp +++ b/src/ui/widgets/ConnectionWidget.cpp @@ -1,6 +1,6 @@ -#include "formwidget.h" +#include "ConnectionWidget.hpp" #include "QMessageBox" -#include "ui_formwidget.h" +#include "ui_ConnectionWidget.h" Formwidget::Formwidget(int id, QWidget *parent) : QWidget(parent), From 1ebce947c2299e6f9ba3c4df8837768434c932f3 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 15 Feb 2020 20:08:35 +0800 Subject: [PATCH 006/332] trigger: triggered downstream builders --- makespec/BUILDVERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 38ab567f..9bb70db0 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3861 +3862 From a43f97eb5627303c3ee1244de30c4de26a8db1b3 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 15 Feb 2020 21:10:10 +0800 Subject: [PATCH 007/332] wip: add: basic structure of new design --- Qv2ray.pro | 3 +- makespec/BUILDVERSION | 2 +- src/base/Qv2rayBase.hpp | 2 +- src/base/models/QvConfigIdentifier.hpp | 11 +-- src/base/models/QvSafeType.hpp | 11 +-- src/common/QvHelpers.cpp | 3 +- src/core/config/ConfigBackend.cpp | 13 +-- src/core/config/ConfigBackend.hpp | 3 +- src/core/handler/ConnectionHandler.cpp | 16 ++++ src/core/handler/ConnectionHandler.hpp | 113 +++++++++++++++++++---- src/core/handler/SubscriptionHandler.cpp | 1 + src/ui/models/InboundNodeModel.cpp | 2 +- src/ui/models/NodeModelsBase.hpp | 2 +- src/ui/models/OutboundNodeModel.cpp | 2 +- src/ui/models/RuleNodeModel.cpp | 2 +- src/ui/w_ExportConfig.cpp | 24 ++--- src/ui/w_ExportConfig.hpp | 4 +- src/ui/w_MainWindow.cpp | 12 +-- src/ui/w_MainWindow.hpp | 14 --- 19 files changed, 151 insertions(+), 89 deletions(-) create mode 100644 src/core/handler/SubscriptionHandler.cpp diff --git a/Qv2ray.pro b/Qv2ray.pro index 38f8e12d..174456fb 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -45,7 +45,7 @@ include($$PWD/makespec/00-deps.pri) # lrelease will not work when adding BEFORE 00-deps.pri CONFIG += lrelease embed_translations -DEFINES += QT_DEPRECATED_WARNINGS QV2RAY_VERSION_STRING=\"\\\"v$${VERSION}\\\"\" QAPPLICATION_CLASS=QApplication +DEFINES += QT_DEPRECATED_WARNINGS QV2RAY_VERSION_STRING=\"\\\"v$${VERSION}\\\"\" QAPPLICATION_CLASS=QApplication XTOSTRUCT_QT # Source file parser include($$PWD/makespec/01-sourcesparser.pri) @@ -87,6 +87,7 @@ Qv2rayAddSource(core, connection, Serialization, cpp, hpp) Qv2rayAddSource(core, kernel, KernelInteractions, cpp, hpp) Qv2rayAddSource(core, kernel, APIBackend, cpp, hpp) Qv2rayAddSource(core, handler, ConnectionHandler, cpp, hpp) +Qv2rayAddSource(core, handler, SubscriptionHandler, cpp) Qv2rayAddSource(core, handler, V2rayInstanceHandler, cpp, hpp) Qv2rayAddSource(core, _, CoreUtils, cpp, hpp) Qv2rayAddSource(ui, editors, w_InboundEditor, cpp, hpp, ui) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index fb97fa29..d1493f87 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3864 +3880 diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index 5940b380..546789aa 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -82,7 +82,7 @@ inline const bool isDebugBuild = false; #elif defined (QV2RAY_DEFAULT_VCORE_PATH) && defined (QV2RAY_DEFAULT_VASSETS_PATH) // ---- Using user-specified VCore and VAssets path #else -# error Both QV2RAY_DEFAULT_VCORE_PATH and QV2RAY_DEFAULT_VASSETS_PATH need to present when specifying the paths. +# error Both QV2RAY_DEFAULT_VCORE_PATH and QV2RAY_DEFAULT_VASSETS_PATH need to be presented when using manually specify the paths. #endif #ifdef Q_OS_WIN diff --git a/src/base/models/QvConfigIdentifier.hpp b/src/base/models/QvConfigIdentifier.hpp index 3710b286..2bb09fe9 100644 --- a/src/base/models/QvConfigIdentifier.hpp +++ b/src/base/models/QvConfigIdentifier.hpp @@ -1,7 +1,6 @@ #pragma once #include #include -#include "base/models/QvSafeType.hpp" #include "3rdparty/x2struct/x2struct.hpp" namespace Qv2ray::base { @@ -20,7 +19,7 @@ namespace Qv2ray::base struct QvSubscriptionObject : _QvGroupObjectBase { QString address; - time_t lastUpdated; + int64_t lastUpdated; float updateInterval; QvSubscriptionObject(): address(""), lastUpdated(system_clock::to_time_t(system_clock::now())), updateInterval(10) { } XTOSTRUCT(O(lastUpdated, updateInterval, address, connections, displayName)) @@ -28,10 +27,10 @@ namespace Qv2ray::base struct QvConnectionObject { QString displayName; - time_t importDate; - long latency; - ulong upLinkData; - ulong downLinkData; + int64_t importDate; + int64_t latency; + int64_t upLinkData; + int64_t downLinkData; QvConnectionObject(): displayName(), importDate(system_clock::to_time_t(system_clock::now())), latency(0), upLinkData(0), downLinkData(0) { } XTOSTRUCT(O(displayName, importDate, latency, upLinkData, downLinkData)) }; diff --git a/src/base/models/QvSafeType.hpp b/src/base/models/QvSafeType.hpp index 158fe962..0244f8ed 100644 --- a/src/base/models/QvSafeType.hpp +++ b/src/base/models/QvSafeType.hpp @@ -3,13 +3,16 @@ #include #include -#define SAFE_TYPEDEF(Base, name) \ +#define SAFE_TYPEDEF_EXTRA(Base, name, extra) \ class name : public Base { \ public: \ template \ explicit name (Args... args) : Base(args...) {} \ const Base& raw() const { return *this; } \ - }; + extra }; + +#define nothing +#define SAFE_TYPEDEF(Base, name) SAFE_TYPEDEF_EXTRA(Base, name, nothing) using namespace std; namespace Qv2ray::base::safetype @@ -28,9 +31,5 @@ namespace Qv2ray::base::safetype SAFE_TYPEDEF(QJsonObject, ROUTERULE) SAFE_TYPEDEF(INOUTLIST, OUTBOUNDS) SAFE_TYPEDEF(INOUTLIST, INBOUNDS) - // - SAFE_TYPEDEF(QString, SubscriptionId) - SAFE_TYPEDEF(QString, ConnectionId) - SAFE_TYPEDEF(QString, GroupId) } diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 367c123e..2abd8d4a 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -27,8 +27,7 @@ namespace Qv2ray::common QString StringFromFile(QFile *source) { source->open(QFile::ReadOnly); - QTextStream stream(source); - QString str = stream.readAll(); + QString str = QString::fromUtf8(source->readAll()); source->close(); return str; } diff --git a/src/core/config/ConfigBackend.cpp b/src/core/config/ConfigBackend.cpp index d22b4de2..18cf0f35 100644 --- a/src/core/config/ConfigBackend.cpp +++ b/src/core/config/ConfigBackend.cpp @@ -3,7 +3,7 @@ namespace Qv2ray::core::config { - void SaveGlobalConfig(Qv2rayConfig conf) + void SaveGlobalConfig(const Qv2rayConfig &conf) { GlobalConfig = conf; QFile config(QV2RAY_CONFIG_FILE); @@ -19,17 +19,6 @@ namespace Qv2ray::core::config Qv2rayConfigPath += "/"; } } - - void LoadGlobalConfig() - { - QFile file(QV2RAY_CONFIG_FILE); - file.open(QFile::ReadOnly); - QTextStream stream(&file); - auto str = stream.readAll(); - auto config = StructFromJsonString(str); - SaveGlobalConfig(config); - file.close(); - } } using namespace Qv2ray::core::config; diff --git a/src/core/config/ConfigBackend.hpp b/src/core/config/ConfigBackend.hpp index 08f94a1a..35966a29 100644 --- a/src/core/config/ConfigBackend.hpp +++ b/src/core/config/ConfigBackend.hpp @@ -2,9 +2,8 @@ namespace Qv2ray::core::config { - void SaveGlobalConfig(Qv2rayConfig conf); + void SaveGlobalConfig(const Qv2rayConfig &conf); void SetConfigDirPath(const QString &path); - void LoadGlobalConfig(); } using namespace Qv2ray::core; diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index e69de29b..d95387ce 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -0,0 +1,16 @@ +#include "ConnectionHandler.hpp" + +namespace Qv2ray::core::handlers +{ + ConnectionHandler::ConnectionHandler() + { + auto _connections = GlobalConfig.connections; + auto _subscriptions = GlobalConfig.subscriptions; + auto _groups = GlobalConfig.groups; + // + saveTimerId = startTimer(60000); + } + ConnectionHandler::~ConnectionHandler() + { + } +} diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 7047c305..1aba66a7 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -1,30 +1,105 @@ #pragma once #include "base/Qv2rayBase.hpp" +#include "core/kernel/KernelInteractions.hpp" -class QvConnectionListModel; - -namespace Qv2ray::core::handler +namespace Qv2ray::core::handlers { + template + class IDType + { + public: + IDType(const QString &id): m_id(id) {} + friend bool operator==(const IDType &lhs, const IDType &rhs) + { + return lhs.m_id == rhs.m_id; + } + private: + QString m_id; + }; + // + class __QvGroup; + class __QvConnection; + class __QvSubscription; + typedef IDType<__QvGroup> GroupId; + typedef IDType<__QvConnection> ConnectionId; + typedef IDType<__QvSubscription> SubscriptionId; + class ConnectionHandler : public QObject { - // Q_OBJECT - //public: - // explicit ConnectionHandler(); - // ~ConnectionHandler(); - // void ReloadConnections(); - // // Get operations. - // QvConnectionListModel GetConnections(); + Q_OBJECT + public: + explicit ConnectionHandler(); + ~ConnectionHandler(); // - //public slots: - // optional DeleteConnection(const ConnectionId &id); - // optional RenameConnection(const ConnectionId &id, const QString &newName); - // optional DuplicateConnection(const ConnectionId &id, ConnectionId *newId); - // optional MoveConnection(const ConnectionId &id, const GroupId &newGroupId); - // // Group Operations - // optional DeleteGroup(const GroupId &id); - // optional RenameGroup(const GroupId &id, const QString &newName); + const QList Groups() const + { + return groups.keys(); + } + const QList Connections() const + { + return connections.keys(); + } + const QList Subscriptions() const + { + return subscriptions.keys(); + } + public: + // + optional StartConnection(const ConnectionId &id); + optional StopConnection(const ConnectionId &id); + // + // Connection Operations. + const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); + optional DeleteConnection(const ConnectionId &id); + optional UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); + optional RenameConnection(const ConnectionId &id, const QString &newName); + optional DuplicateConnection(const ConnectionId &id); + optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); + // + // Misc Connection Operations + optional TestLatency(const ConnectionId &id); + optional TestLatency(const GroupId &id); + optional TestAllLatency(); + // + // Group Operations + const GroupId CreateGroup(const QString displayName); + optional DeleteGroup(const GroupId &id); + optional DuplicateGroup(const GroupId &id); + optional RenameGroup(const GroupId &id, const QString &newName); + // + // Subscriptions + const SubscriptionId CreateSubscription(const QString &displayName, const QString &address); + optional RenameSubscription(const SubscriptionId &id, const QString &newName); + optional DeleteSubscription(const SubscriptionId &id); + optional UpdateSubscription(const SubscriptionId &id); + optional UpdateSubscriptionASync(const SubscriptionId &id); + + signals: + void OnConnectionCreated(const ConnectionId &id, const QString &displayName); + void OnConnectionRenamed(const ConnectionId &id, const QString &originalName, const QString &newName); + void OnConnectionChanged(const ConnectionId &id); + void OnConnectionGroupChanged(const ConnectionId &id, const QString &originalGroup, const QString &newGroup); + // + void OnConnectionLatencyTestFinished(const ConnectionId &id); + // + void OnGroupCreated(const GroupId &id, const QString &displayName); + void OnGroupRenamed(const GroupId &id, const QString &oldName, const QString &newName); + void OnGroupDeleted(const GroupId &id, const QString &displayName); + // + void OnSubscriptionCreated(const SubscriptionId &id, const QString &displayName, const QString &address); + void OnSubscriptionDeleted(const SubscriptionId &id); + void OnSubscriptionRenamed(const SubscriptionId &id, const QString &oldName, const QString &newName); + void OnSubscriptionUpdateFinished(const SubscriptionId &id); + + private: + int saveTimerId; + QMap groups; + QMap connections; + QMap subscriptions; + // + QMap kernelInstances; }; } -using namespace Qv2ray::core::handler; +using namespace Qv2ray::core::handlers; diff --git a/src/core/handler/SubscriptionHandler.cpp b/src/core/handler/SubscriptionHandler.cpp new file mode 100644 index 00000000..8337712e --- /dev/null +++ b/src/core/handler/SubscriptionHandler.cpp @@ -0,0 +1 @@ +// diff --git a/src/ui/models/InboundNodeModel.cpp b/src/ui/models/InboundNodeModel.cpp index 4681ceb3..c83ba037 100644 --- a/src/ui/models/InboundNodeModel.cpp +++ b/src/ui/models/InboundNodeModel.cpp @@ -1,4 +1,4 @@ -#include "ui/nodemodels/InboundNodeModel.hpp" +#include "ui/models/InboundNodeModel.hpp" QvInboundNodeModel::QvInboundNodeModel(std::shared_ptr data): NodeDataModel() { diff --git a/src/ui/models/NodeModelsBase.hpp b/src/ui/models/NodeModelsBase.hpp index 2a5878d5..d5f92d86 100644 --- a/src/ui/models/NodeModelsBase.hpp +++ b/src/ui/models/NodeModelsBase.hpp @@ -18,7 +18,7 @@ using QtNodes::NodeValidationState; using QtNodes::NodeDataType; using QtNodes::NodeData; -#define GRAPH_NODE_LABEL_FONTSIZE_INCREMENT 3 +const int GRAPH_NODE_LABEL_FONTSIZE_INCREMENT = 3; namespace Qv2ray::ui::nodemodels { diff --git a/src/ui/models/OutboundNodeModel.cpp b/src/ui/models/OutboundNodeModel.cpp index bbf08251..a73d87a7 100644 --- a/src/ui/models/OutboundNodeModel.cpp +++ b/src/ui/models/OutboundNodeModel.cpp @@ -1,4 +1,4 @@ -#include "ui/nodemodels/OutboundNodeModel.hpp" +#include "ui/models/OutboundNodeModel.hpp" QvOutboundNodeModel::QvOutboundNodeModel(std::shared_ptr data): NodeDataModel() { diff --git a/src/ui/models/RuleNodeModel.cpp b/src/ui/models/RuleNodeModel.cpp index f0c7997e..f62c02ab 100644 --- a/src/ui/models/RuleNodeModel.cpp +++ b/src/ui/models/RuleNodeModel.cpp @@ -1,4 +1,4 @@ -#include "ui/nodemodels/RuleNodeModel.hpp" +#include "ui/models/RuleNodeModel.hpp" QvRuleNodeDataModel::QvRuleNodeDataModel(std::shared_ptr data): NodeDataModel() { diff --git a/src/ui/w_ExportConfig.cpp b/src/ui/w_ExportConfig.cpp index e871ee56..cb81bb91 100644 --- a/src/ui/w_ExportConfig.cpp +++ b/src/ui/w_ExportConfig.cpp @@ -25,18 +25,18 @@ ConfigExporter::~ConfigExporter() { } -ConfigExporter::ConfigExporter(const ConnectionId &connection, QWidget *parent) : ConfigExporter(parent) -{ - // WIP - auto x = connection; - //message = ConvertConfigToString(root, alias.IdentifierString()); - // - QZXingEncoderConfig conf; - conf.border = true; - conf.imageSize = QSize(400, 400); - auto img = qzxing.encodeData(message, conf); - image = img.copy(); -} +//ConfigExporter::ConfigExporter(QWidget *parent) : ConfigExporter(parent) +//{ +// // WIP +// // /auto &x = connection; +// //message = ConvertConfigToString(root, alias.IdentifierString()); +// // +// QZXingEncoderConfig conf; +// conf.border = true; +// conf.imageSize = QSize(400, 400); +// auto img = qzxing.encodeData(message, conf); +// image = img.copy(); +//} void ConfigExporter::OpenExport() { diff --git a/src/ui/w_ExportConfig.hpp b/src/ui/w_ExportConfig.hpp index 89208ff2..5e61bc94 100644 --- a/src/ui/w_ExportConfig.hpp +++ b/src/ui/w_ExportConfig.hpp @@ -10,7 +10,7 @@ class ConfigExporter : public QDialog, private Ui::ExportConfigWindow Q_OBJECT public: - explicit ConfigExporter(const ConnectionId &connection, QWidget *parent = nullptr); + explicit ConfigExporter(QWidget *parent = nullptr); ~ConfigExporter(); void OpenExport(); public slots: @@ -25,9 +25,7 @@ class ConfigExporter : public QDialog, private Ui::ExportConfigWindow void on_copyImageBtn_clicked(); void on_copyVMessBtn_clicked(); - private: - explicit ConfigExporter(QWidget *parent); QZXing qzxing; QImage image; QString message; diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 8a8832ca..fde5d5de 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -340,15 +340,15 @@ void MainWindow::OnConfigListChanged(bool need_restart) SetEditWidgetEnable(false); // // Store the latency test value. - QMap latencyValueCache; + //QMap latencyValueCache; //for (auto i = 0; i < connections.count(); i++) { // latencyValueCache[connections.keys()[i]] = connections.values()[i].latency; //} - connections.clear(); - connectionListWidget->clear(); - QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP, only subscriptions are supported"); - //auto _regularConnections = GetRegularConnections(GlobalConfig.configs); - auto _subsConnections = GetSubscriptionConnections(GlobalConfig.subscriptions.keys()); + //connections.clear(); + //connectionListWidget->clear(); + //QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP, only subscriptions are supported"); + ////auto _regularConnections = GetRegularConnections(GlobalConfig.configs); + //auto _subsConnections = GetSubscriptionConnections(GlobalConfig.subscriptions.keys()); //for (auto i = 0; i < _regularConnections.count(); i++) { // ConnectionObject _o; // _o.configType = CONNECTION_REGULAR; diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 2faf98d4..fd74780e 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -20,17 +20,6 @@ #include "ui/messaging/QvMessageBus.hpp" -enum QvConnectionType { - CONNECTION_REGULAR = 1, - CONNECTION_SUBSCRIPTION = 2 -}; -// -struct ConnectionObject : QvConnectionObject { - QvConnectionType configType; - double latency; - CONFIGROOT config; -}; - class MainWindow : public QMainWindow, Ui::MainWindow { Q_OBJECT @@ -101,9 +90,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow SpeedWidget *speedChartView; // QMenu *connectionListMenu; - - /// Key --> ListWidget.item.text - QMap connections; // QvConnectionObject renameOriginalIdentifier; bool isRenamingInProgress; From 519f29e3fc1a2ca27224cb1f6e827f2a1da85626 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 16 Feb 2020 00:00:46 +0800 Subject: [PATCH 008/332] wip: add: added a functionless UI --- makespec/BUILDVERSION | 2 +- src/base/Qv2rayLog.hpp | 2 + src/components/plugins/toolbar/QvToolbar.cpp | 135 ++++++++------- src/core/handler/ConnectionHandler.cpp | 61 ++++++- src/core/handler/ConnectionHandler.hpp | 73 +++++--- src/main.cpp | 15 +- src/ui/w_MainWindow.cpp | 172 +++++++++---------- src/ui/w_MainWindow.hpp | 33 ++-- src/ui/w_MainWindow_extra.cpp | 108 ++++++------ src/ui/widgets/ConnectionWidget.cpp | 21 +-- src/ui/widgets/ConnectionWidget.hpp | 26 ++- src/ui/widgets/ConnectionWidget.ui | 39 +++-- 12 files changed, 380 insertions(+), 307 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index d1493f87..d1c67ac8 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3880 +3881 diff --git a/src/base/Qv2rayLog.hpp b/src/base/Qv2rayLog.hpp index 79c46bb8..15423d48 100644 --- a/src/base/Qv2rayLog.hpp +++ b/src/base/Qv2rayLog.hpp @@ -49,3 +49,5 @@ const inline QString FILEIO = "COMMON-FILEIO" ; const inline QString PROXY = "COMPONENT-PROXY" ; const inline QString UPDATE = "COMPONENT-UPDATE" ; const inline QString PLUGIN = "COMPONENT-PLUGIN" ; +// ================================================================ +const inline QString CORE_HANDLER = "libQv2ray: ConnectionHandler"; diff --git a/src/components/plugins/toolbar/QvToolbar.cpp b/src/components/plugins/toolbar/QvToolbar.cpp index 56c8ad89..0ecdb877 100644 --- a/src/components/plugins/toolbar/QvToolbar.cpp +++ b/src/components/plugins/toolbar/QvToolbar.cpp @@ -31,13 +31,12 @@ namespace Qv2ray::components::plugins QString GetAnswerToRequest(const QString &pchRequest) { auto instance = MainWindow::mwInstance; - - if (instance == nullptr || instance->vinstance == nullptr) { - LOG(PLUGIN, "MainWindow != nullptr Assertion failed!") - return "{}"; - } - - auto vinstance = instance->vinstance; + //if (instance == nullptr || instance->vinstance == nullptr) { + // LOG(PLUGIN, "MainWindow != nullptr Assertion failed!") + // return "{}"; + //} + // + //auto vinstance = instance->vinstance; // auto req = pchRequest.trimmed(); QString reply = "{}"; @@ -81,67 +80,67 @@ namespace Qv2ray::components::plugins break; } - case 104: { - // Current Connection Name - CL.Message = instance->GetCurrentConnectedConfigName(); - break; - } - - case 105: { - // Current Connection Status - CL.Message = instance->vinstance->KernelStarted - ? QObject::tr("Connected") - : QObject::tr("Disconnected"); - break; - } - - case 201: { - // Total upload speed; - CL.Message = FormatBytes(vinstance->getAllSpeedUp()) + "/s"; - break; - } - - case 202: { - // Total download speed; - CL.Message = FormatBytes(vinstance->getAllSpeedDown()) + "/s"; - break; - } - - case 203: { - // Upload speed for tag - CL.Message = FormatBytes(vinstance->getTagSpeedUp(CL.Message)) + "/s"; - break; - } - - case 204: { - // Download speed for tag - CL.Message = FormatBytes(vinstance->getTagSpeedDown(CL.Message)) + "/s"; - break; - } - - case 301: { - // Total Upload - CL.Message = FormatBytes(vinstance->getAllDataUp()); - break; - } - - case 302: { - // Total download - CL.Message = FormatBytes(vinstance->getAllDataDown()); - break; - } - - case 303: { - // Upload for tag - CL.Message = FormatBytes(vinstance->getTagDataUp(CL.Message)); - break; - } - - case 304: { - // Download for tag - CL.Message = FormatBytes(vinstance->getTagDataDown(CL.Message)); - break; - } + //case 104: { + // // Current Connection Name + // CL.Message = instance->GetCurrentConnectedConfigName(); + // break; + //} + // + //case 105: { + // // Current Connection Status + // CL.Message = instance->vinstance->KernelStarted + // ? QObject::tr("Connected") + // : QObject::tr("Disconnected"); + // break; + //} + // + //case 201: { + // // Total upload speed; + // CL.Message = FormatBytes(vinstance->getAllSpeedUp()) + "/s"; + // break; + //} + // + //case 202: { + // // Total download speed; + // CL.Message = FormatBytes(vinstance->getAllSpeedDown()) + "/s"; + // break; + //} + // + //case 203: { + // // Upload speed for tag + // CL.Message = FormatBytes(vinstance->getTagSpeedUp(CL.Message)) + "/s"; + // break; + //} + // + //case 204: { + // // Download speed for tag + // CL.Message = FormatBytes(vinstance->getTagSpeedDown(CL.Message)) + "/s"; + // break; + //} + // + //case 301: { + // // Total Upload + // CL.Message = FormatBytes(vinstance->getAllDataUp()); + // break; + //} + // + //case 302: { + // // Total download + // CL.Message = FormatBytes(vinstance->getAllDataDown()); + // break; + //} + // + //case 303: { + // // Upload for tag + // CL.Message = FormatBytes(vinstance->getTagDataUp(CL.Message)); + // break; + //} + // + //case 304: { + // // Download for tag + // CL.Message = FormatBytes(vinstance->getTagDataDown(CL.Message)); + // break; + //} default: { CL.Message = "Not Supported?"; diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index d95387ce..ea042b17 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -2,14 +2,67 @@ namespace Qv2ray::core::handlers { + template + QList StringsToIdList(const QList &strings) + { + QList list; + + for (auto str : strings) { + list << IDType(str); + } + + return list; + } + ConnectionHandler::ConnectionHandler() { - auto _connections = GlobalConfig.connections; - auto _subscriptions = GlobalConfig.subscriptions; - auto _groups = GlobalConfig.groups; - // + DEBUG(CORE_HANDLER, "ConnectionHandler Constructor.") + + // Do we need to check how many of them are loaded? + for (auto i = 0; i < GlobalConfig.connections.count(); i++) { + connections[ConnectionId(GlobalConfig.connections.keys()[i])] = GlobalConfig.connections.values()[i]; + } + + for (auto i = 0; i < GlobalConfig.subscriptions.count(); i++) { + subscriptions[SubscriptionId(GlobalConfig.subscriptions.keys()[i])] = GlobalConfig.subscriptions.values()[i]; + } + + for (auto i = 0; i < GlobalConfig.groups.count(); i++) { + groups[GroupId(GlobalConfig.groups.keys()[i])] = GlobalConfig.groups.values()[i]; + } + saveTimerId = startTimer(60000); } + + const QList ConnectionHandler::Groups() const + { + return groups.keys(); + } + const QList ConnectionHandler::Subscriptions() const + { + return subscriptions.keys(); + } + const QList ConnectionHandler::Connections() const + { + return connections.keys(); + } + const QList ConnectionHandler::Connections(const GroupId &groupId) const + { + return StringsToIdList(groups[groupId].connections); + } + const QList ConnectionHandler::Connections(const SubscriptionId &subscriptionId) const + { + return StringsToIdList(subscriptions[subscriptionId].connections); + } + + const QvConnectionObject &ConnectionHandler::GetConnection(const ConnectionId &id) + { + if (!connections.contains(id)) { + LOG(CORE_HANDLER, "Cannot find id: " + id.toString()); + } + + return connections[id]; + } ConnectionHandler::~ConnectionHandler() { } diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 1aba66a7..a8f129fe 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -2,21 +2,37 @@ #include "base/Qv2rayBase.hpp" #include "core/kernel/KernelInteractions.hpp" +#include +#include + +template +class IDType +{ + public: + IDType(const QString &id): m_id(id) {} + friend bool operator==(const IDType &lhs, const IDType &rhs) + { + return lhs.m_id == rhs.m_id; + } + const QString &toString() const + { + return m_id; + } + uint qHash(uint seed) const + { + return ::qHash(m_id, seed); + } + private: + QString m_id; +}; + +template uint qHash(const IDType &key, uint seed = 0) +{ + return key.qHash(seed); +} namespace Qv2ray::core::handlers { - template - class IDType - { - public: - IDType(const QString &id): m_id(id) {} - friend bool operator==(const IDType &lhs, const IDType &rhs) - { - return lhs.m_id == rhs.m_id; - } - private: - QString m_id; - }; // class __QvGroup; class __QvConnection; @@ -32,24 +48,18 @@ namespace Qv2ray::core::handlers explicit ConnectionHandler(); ~ConnectionHandler(); // - const QList Groups() const - { - return groups.keys(); - } - const QList Connections() const - { - return connections.keys(); - } - const QList Subscriptions() const - { - return subscriptions.keys(); - } + const QList Groups() const; + const QList Connections() const; + const QList Connections(const GroupId &groupId) const; + const QList Connections(const SubscriptionId &subscriptionId) const; + const QList Subscriptions() const; public: // optional StartConnection(const ConnectionId &id); optional StopConnection(const ConnectionId &id); // // Connection Operations. + const QvConnectionObject &GetConnection(const ConnectionId &id); const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); optional DeleteConnection(const ConnectionId &id); optional UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); @@ -94,12 +104,21 @@ namespace Qv2ray::core::handlers private: int saveTimerId; - QMap groups; - QMap connections; - QMap subscriptions; + QHash groups; + QHash connections; + QHash subscriptions; // QMap kernelInstances; }; + // + inline unique_ptr connectionHandler = nullptr; + // + inline void InitialiseConnectionHandler() + { + LOG(CORE_HANDLER, "Initializing ConnectionHandler...") + connectionHandler = make_unique(); + } + // } using namespace Qv2ray::core::handlers; diff --git a/src/main.cpp b/src/main.cpp index 853a60f2..3f61cf54 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,9 @@ #include #include #include "ui/w_MainWindow.hpp" + +#include "core/config/ConfigBackend.hpp" +#include "core/handler/ConnectionHandler.hpp" #include "common/QvHelpers.hpp" #include "common/CommandArgs.hpp" #include "common/QvTranslator.hpp" @@ -21,12 +24,10 @@ void signalHandler(int signum) { cout << "Interrupt signal (" << signum << ") received." << endl; - - if (MainWindow::mwInstance && MainWindow::mwInstance->vinstance) { - cout << "Trying to stop connection..." << endl; - MainWindow::mwInstance->vinstance->StopConnection(); - } - + //if (MainWindow::mwInstance && MainWindow::mwInstance->vinstance) { + // cout << "Trying to stop connection..." << endl; + // MainWindow::mwInstance->vinstance->StopConnection(); + //} qApp->exit(-99); } @@ -446,6 +447,8 @@ int main(int argc, char *argv[]) } #endif + // Initialise Connection Handler + InitialiseConnectionHandler(); // Show MainWindow MainWindow w; #ifndef QT_DEBUG diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index fde5d5de..edf96087 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -1,6 +1,5 @@ #pragma once - #include "w_MainWindow.hpp" #include "w_ImportConfig.hpp" #include "w_PreferencesWindow.hpp" @@ -28,6 +27,9 @@ #include "core/connection/ConnectionIO.hpp" +// ========================================================================================== +#include "ui/widgets/ConnectionWidget.hpp" + // MainWindow.cpp --> Main MainWindow source file, handles mostly UI-related operations. #define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING @@ -88,18 +90,18 @@ QvMessageBusSlotImpl(MainWindow) } } -MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), vinstance(), hTray(this), tcpingHelper(3, this) +MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTray(this), tcpingHelper(3, this) { MainWindow::mwInstance = this; - vinstance = new V2rayKernelInstance(); - connect(vinstance, &V2rayKernelInstance::onProcessOutputReadyRead, this, &MainWindow::UpdateVCoreLog); - connect(vinstance, &V2rayKernelInstance::onProcessErrored, [this] { - on_stopButton_clicked(); - this->show(); - QvMessageBoxWarn(this, tr("V2ray vcore terminated."), - tr("V2ray vcore terminated unexpectedly.") + NEWLINE + NEWLINE + - tr("To solve the problem, read the V2ray log in the log text browser.")); - }); + //vinstance = new V2rayKernelInstance(); + //connect(vinstance, &V2rayKernelInstance::onProcessOutputReadyRead, this, &MainWindow::UpdateVCoreLog); + //connect(vinstance, &V2rayKernelInstance::onProcessErrored, [this] { + // on_stopButton_clicked(); + // this->show(); + // QvMessageBoxWarn(this, tr("V2ray vcore terminated."), + // tr("V2ray vcore terminated unexpectedly.") + NEWLINE + NEWLINE + + // tr("To solve the problem, read the V2ray log in the log text browser.")); + //}); // setupUi(this); QvMessageBusConnect(MainWindow); @@ -125,7 +127,7 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), vinstance(), hTray qvLogTimerId = startTimer(500); // requestHelper = new QvHttpRequestHelper(); - connect(&tcpingHelper, &QvTCPingModel::PingFinished, this, &MainWindow::onPingFinished); + //connect(&tcpingHelper, &QvTCPingModel::PingFinished, this, &MainWindow::onPingFinished); // this->setWindowIcon(QIcon(":/assets/icons/qv2ray.png")); hTray.setIcon(QIcon(GlobalConfig.uiConfig.useDarkTrayIcon ? ":/assets/icons/ui_dark/tray.png" : ":/assets/icons/ui_light/tray.png")); @@ -224,12 +226,10 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), vinstance(), hTray // // Find and start if there is an auto-connection MWFindAndStartAutoConfig(); - - // If we are not connected to anything, show the MainWindow. - if (!vinstance->KernelStarted) { - this->show(); - } - + //// If we are not connected to anything, show the MainWindow. + //if (!vinstance->KernelStarted) { + // this->show(); + //} connect(requestHelper, &QvHttpRequestHelper::httpRequestFinished, this, &MainWindow::VersionUpdate); requestHelper->get("https://api.github.com/repos/Qv2ray/Qv2ray/releases/latest"); @@ -325,19 +325,28 @@ void MainWindow::VersionUpdate(QByteArray &data) } else if (result == QMessageBox::Ignore) { // Set and save ingored version. GlobalConfig.ignoredVersion = newVersion.toString(); - SaveGlobalConfig(GlobalConfig); + //SaveGlobalConfig(GlobalConfig); } } } void MainWindow::OnConfigListChanged(bool need_restart) { - auto wasRunning = vinstance->KernelStarted && need_restart; + LOG(UI, "Loading data...") + auto conns = connectionHandler->Connections(); - if (wasRunning) on_stopButton_clicked(); + for (auto conn : conns) { + auto item = new QTreeWidgetItem(); + connectionListWidget->addTopLevelItem(item); + connectionListWidget->setItemWidget(item, 0, new ConnectionWidget(conn, connectionListWidget)); + } - LOG(UI, "Loading new GlobalConfig") - SetEditWidgetEnable(false); + //auto wasRunning = vinstance->KernelStarted && need_restart; + // + //if (wasRunning) on_stopButton_clicked(); + // + //LOG(UI, "Loading new GlobalConfig") + //SetEditWidgetEnable(false); // // Store the latency test value. //QMap latencyValueCache; @@ -407,7 +416,7 @@ MainWindow::~MainWindow() { killTimer(qvLogTimerId); hTray.hide(); - delete this->vinstance; + //delete this->vinstance; } void MainWindow::UpdateVCoreLog(const QString &log) { @@ -508,14 +517,14 @@ void MainWindow::on_activatedTray(QSystemTrayIcon::ActivationReason reason) #endif break; - case QSystemTrayIcon::MiddleClick: - if (vinstance->KernelStarted) { - on_stopButton_clicked(); - } else { - on_startButton_clicked(); - } - - break; + //case QSystemTrayIcon::MiddleClick: + // if (vinstance->KernelStarted) { + // on_stopButton_clicked(); + // } else { + // on_startButton_clicked(); + // } + // + // break; case QSystemTrayIcon::DoubleClick: #ifdef __APPLE__ @@ -549,7 +558,7 @@ void MainWindow::quit() StopProcessingPlugins(); } - tcpingHelper.StopAllPing(); + //tcpingHelper.StopAllPing(); on_stopButton_clicked(); ExitQv2ray(); } @@ -559,46 +568,46 @@ void MainWindow::on_actionExit_triggered() quit(); } -void MainWindow::ShowAndSetConnection(QvConnectionObject fullIdentifier, bool SetConnection, bool ApplyConnection) -{ - //// Check empty again... - //if (!connections.contains(fullIdentifier)) return; - // - //SetEditWidgetEnable(true); - //// - //// --------- BRGIN Show Connection - //auto conf = connections[fullIdentifier]; - //// - //auto isComplexConfig = IsComplexConfig(conf.config); - //routeCountLabel->setText(isComplexConfig ? tr("Complex") : tr("Simple")); - // - //if (conf.latency == 0.0) { - // latencyLabel->setText(tr("No data")); - //} else { - // latencyLabel->setText(QSTRN(conf.latency) + " " + tr("ms")); - //} - // - //if (conf.configType == CONNECTION_SUBSCRIPTION) { - // routeCountLabel->setText(routeCountLabel->text().append(" (" + tr("Subscription") + ":" + conf.subscriptionName + ")")); - //} - // - //// Get Connection info - //auto host_port = MWGetConnectionInfo(fullIdentifier.IdentifierString()); - //_hostLabel->setText(get<0>(host_port)); - //_portLabel->setText(QSTRN(get<1>(host_port))); - //_OutBoundTypeLabel->setText(get<2>(host_port)); - // - //// Set to currentConnection - //if (SetConnection) { - // CurrentSelectedItemPtr = FindItemByIdentifier(fullIdentifier); - // CurrentConnectionIdentifier = fullIdentifier; - //} - // - //// Restart Connection - //if (ApplyConnection) { - // on_reconnectButton_clicked(); - //} -} +//void MainWindow::ShowAndSetConnection(QvConnectionObject fullIdentifier, bool SetConnection, bool ApplyConnection) +//{ +//// Check empty again... +//if (!connections.contains(fullIdentifier)) return; +// +//SetEditWidgetEnable(true); +//// +//// --------- BRGIN Show Connection +//auto conf = connections[fullIdentifier]; +//// +//auto isComplexConfig = IsComplexConfig(conf.config); +//routeCountLabel->setText(isComplexConfig ? tr("Complex") : tr("Simple")); +// +//if (conf.latency == 0.0) { +// latencyLabel->setText(tr("No data")); +//} else { +// latencyLabel->setText(QSTRN(conf.latency) + " " + tr("ms")); +//} +// +//if (conf.configType == CONNECTION_SUBSCRIPTION) { +// routeCountLabel->setText(routeCountLabel->text().append(" (" + tr("Subscription") + ":" + conf.subscriptionName + ")")); +//} +// +//// Get Connection info +//auto host_port = MWGetConnectionInfo(fullIdentifier.IdentifierString()); +//_hostLabel->setText(get<0>(host_port)); +//_portLabel->setText(QSTRN(get<1>(host_port))); +//_OutBoundTypeLabel->setText(get<2>(host_port)); +// +//// Set to currentConnection +//if (SetConnection) { +// CurrentSelectedItemPtr = FindItemByIdentifier(fullIdentifier); +// CurrentConnectionIdentifier = fullIdentifier; +//} +// +//// Restart Connection +//if (ApplyConnection) { +// on_reconnectButton_clicked(); +//} +//} void MainWindow::on_preferencesBtn_clicked() { PreferencesWindow w(this); @@ -1071,20 +1080,3 @@ void MainWindow::on_connectionListWidget_itemSelectionChanged() // } //} } - -void MainWindow::onPingFinished(QvTCPingData data) -{ - //if (!connections.contains(data.connectionIdentifier)) { - // return; - //} - //connections[data.connectionIdentifier].latency = data.avg; - //if (IsConnectableItem(CurrentSelectedItemPtr)) { - // ShowAndSetConnection(ItemConnectionIdentifier(CurrentSelectedItemPtr), false, false); - //} -} - -QString MainWindow::GetCurrentConnectedConfigName() -{ - return ""; - //return CurrentConnectionIdentifier.IdentifierString(); -} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index fd74780e..dc93c552 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -7,15 +7,16 @@ #include "ui_w_MainWindow.h" -#include "core/CoreUtils.hpp" -#include "core/kernel/KernelInteractions.hpp" -#include "core/connection/ConnectionIO.hpp" +//#include "core/CoreUtils.hpp" +//#include "core/kernel/KernelInteractions.hpp" +//#include "core/connection/ConnectionIO.hpp" #include "common/LogHighlighter.hpp" #include "common/HTTPRequestHelper.hpp" -#include "components/tcping/QvTCPing.hpp" -#include "components/pac/QvPACHandler.hpp" + +//#include "components/tcping/QvTCPing.hpp" +//#include "components/pac/QvPACHandler.hpp" #include "components/speedchart/speedwidget.hpp" #include "ui/messaging/QvMessageBus.hpp" @@ -32,7 +33,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow void ReConnect() const; public slots: QvMessageBusSlotHeader - void onPingFinished(QvTCPingData data); + //void onPingFinished(QvTCPingData data); void UpdateVCoreLog(const QString &log); void OnConfigListChanged(bool need_restart); private slots: @@ -64,9 +65,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow public: static MainWindow *mwInstance; - QvConnectionObject CurrentConnectionIdentifier; - V2rayKernelInstance *vinstance; - QString GetCurrentConnectedConfigName(); + //QvConnectionObject CurrentConnectionIdentifier; protected: void mouseReleaseEvent(QMouseEvent *e) override; @@ -82,16 +81,17 @@ class MainWindow : public QMainWindow, Ui::MainWindow void on_connectionListWidget_itemSelectionChanged(); private: + // void SetEditWidgetEnable(bool enabled); - void ShowAndSetConnection(QvConnectionObject fullIdentifier, bool SetConnection, bool Apply); - CONFIGROOT currentFullConfig; + //void ShowAndSetConnection(QvConnectionObject fullIdentifier, bool SetConnection, bool Apply); + //CONFIGROOT currentFullConfig; // // Charts SpeedWidget *speedChartView; // QMenu *connectionListMenu; // - QvConnectionObject renameOriginalIdentifier; + //QvConnectionObject renameOriginalIdentifier; bool isRenamingInProgress; // // ID for QTimers @@ -103,8 +103,8 @@ class MainWindow : public QMainWindow, Ui::MainWindow // QvHttpRequestHelper *requestHelper; QSystemTrayIcon hTray; - PACServer pacServer; - QvTCPingModel tcpingHelper; + //PACServer pacServer; + //QvTCPingModel tcpingHelper; SyntaxHighlighter *vCoreLogHighlighter; SyntaxHighlighter *qvAppLogHighlighter; // @@ -132,12 +132,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow void MWFindAndStartAutoConfig(); bool MWtryStartConnection(); void MWStopConnection(); - void MWTryPingConnection(const QvConnectionObject &alias); - tuple MWGetConnectionInfo(const QvConnectionObject &alias); void MWSetSystemProxy(); void MWClearSystemProxy(bool); void CheckSubscriptionsUpdate(); - // - - QTreeWidgetItem *FindItemByIdentifier(QvConnectionObject identifier); }; diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index f1715e67..3610dc04 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -5,30 +5,30 @@ #include "components/proxy/QvProxyConfigurator.hpp" #include "core/connection/Generation.hpp" -QTreeWidgetItem *MainWindow::FindItemByIdentifier(QvConnectionObject identifier) -{ - //// First filter out all items with our config name. - //auto items = connectionListWidget->findItems(identifier.connectionName, Qt::MatchExactly | Qt::MatchRecursive); - // - //for (auto item : items) { - // // This connectable prevents the an item with (which is the parent node of a subscription, having the same - // // -- name as our current connected name) - // if (!IsConnectableItem(item)) { - // LOG(UI, "Invalid Item found: " + item->text(0)) - // continue; - // } - // - // auto thisIdentifier = ItemConnectionIdentifier(item); - // DEBUG(UI, "Item Identifier: " + thisIdentifier.IdentifierString()) - // - // if (identifier == thisIdentifier) { - // return item; - // } - //} - // - //LOG(UI, "Warning: Failed to find an item named: " + identifier.IdentifierString()) - return nullptr; -} +//QTreeWidgetItem *MainWindow::FindItemByIdentifier(QvConnectionObject identifier) +//{ +// //// First filter out all items with our config name. +// //auto items = connectionListWidget->findItems(identifier.connectionName, Qt::MatchExactly | Qt::MatchRecursive); +// // +// //for (auto item : items) { +// // // This connectable prevents the an item with (which is the parent node of a subscription, having the same +// // // -- name as our current connected name) +// // if (!IsConnectableItem(item)) { +// // LOG(UI, "Invalid Item found: " + item->text(0)) +// // continue; +// // } +// // +// // auto thisIdentifier = ItemConnectionIdentifier(item); +// // DEBUG(UI, "Item Identifier: " + thisIdentifier.IdentifierString()) +// // +// // if (identifier == thisIdentifier) { +// // return item; +// // } +// //} +// // +// //LOG(UI, "Warning: Failed to find an item named: " + identifier.IdentifierString()) +// return nullptr; +//} void MainWindow::MWFindAndStartAutoConfig() { @@ -191,39 +191,39 @@ bool MainWindow::MWtryStartConnection() void MainWindow::MWStopConnection() { - if (systemProxyEnabled) { - MWClearSystemProxy(false); - } - - this->vinstance->StopConnection(); - QFile(QV2RAY_GENERATED_FILE_PATH).remove(); - - if (GlobalConfig.inboundConfig.pacConfig.enablePAC) { - pacServer.StopServer(); - LOG(UI, "Stopping PAC server") - } -} - -void MainWindow::MWTryPingConnection(const QvConnectionObject &alias) -{ - try { - auto info = MWGetConnectionInfo(alias); - QString host = get<0>(info); - int port = get<1>(info); - tcpingHelper.StartPing(alias, host, port); - } catch (...) { - QvMessageBoxWarn(this, tr("Latency Test"), tr("Failed to test latency for this connection.")); - } -} - -tuple MainWindow::MWGetConnectionInfo(const QvConnectionObject &alias) -{ - //if (!connections.contains(alias)) - // return make_tuple(tr("N/A"), 0, tr("N/A")); + //if (systemProxyEnabled) { + // MWClearSystemProxy(false); + //} // - //return GetConnectionInfo(connections[alias].config); + //this->vinstance->StopConnection(); + //QFile(QV2RAY_GENERATED_FILE_PATH).remove(); + // + //if (GlobalConfig.inboundConfig.pacConfig.enablePAC) { + // pacServer.StopServer(); + // LOG(UI, "Stopping PAC server") + //} } +//void MainWindow::MWTryPingConnection(const QvConnectionObject &alias) +//{ +// //try { +// // auto info = MWGetConnectionInfo(alias); +// // QString host = get<0>(info); +// // int port = get<1>(info); +// // tcpingHelper.StartPing(alias, host, port); +// //} catch (...) { +// // QvMessageBoxWarn(this, tr("Latency Test"), tr("Failed to test latency for this connection.")); +// //} +//} +// +//tuple MainWindow::MWGetConnectionInfo(const QvConnectionObject &alias) +//{ +// //if (!connections.contains(alias)) +// // return make_tuple(tr("N/A"), 0, tr("N/A")); +// // +// //return GetConnectionInfo(connections[alias].config); +//} + void MainWindow::CheckSubscriptionsUpdate() { QStringList updateList; diff --git a/src/ui/widgets/ConnectionWidget.cpp b/src/ui/widgets/ConnectionWidget.cpp index 663ac14e..8e30be60 100644 --- a/src/ui/widgets/ConnectionWidget.cpp +++ b/src/ui/widgets/ConnectionWidget.cpp @@ -1,21 +1,22 @@ #include "ConnectionWidget.hpp" #include "QMessageBox" -#include "ui_ConnectionWidget.h" -Formwidget::Formwidget(int id, QWidget *parent) : - QWidget(parent), - ui(new Ui::Formwidget) +ConnectionWidget::ConnectionWidget(const ConnectionId &id, QWidget *parent): QWidget(parent), + _id(id), connection(connectionHandler->GetConnection(id)) { - _id = id; - ui->setupUi(this); + setupUi(this); + connNameLabel->setText(connection.displayName); + latencyLabel->setText(tr("Latency: ") + QSTRN(connection.latency) + " " + tr("ms")); } -Formwidget::~Formwidget() +ConnectionWidget::~ConnectionWidget() { - delete ui; } -void Formwidget::on_pushButton_clicked() +void ConnectionWidget::on_editBtn_clicked() +{ +} + +void ConnectionWidget::on_latencyBtn_clicked() { - QMessageBox::information(this, "d", QString::number(_id)); } diff --git a/src/ui/widgets/ConnectionWidget.hpp b/src/ui/widgets/ConnectionWidget.hpp index 6d745c0d..cd6f8d81 100644 --- a/src/ui/widgets/ConnectionWidget.hpp +++ b/src/ui/widgets/ConnectionWidget.hpp @@ -1,27 +1,23 @@ -#ifndef FORMWIDGET_H -#define FORMWIDGET_H +#pragma once #include +#include "ui_ConnectionWidget.h" +#include "core/handler/ConnectionHandler.hpp" -namespace Ui -{ - class Formwidget; -} - -class Formwidget : public QWidget +class ConnectionWidget : public QWidget, private Ui::ConnectionWidget { Q_OBJECT public: - explicit Formwidget(int id, QWidget *parent = nullptr); - ~Formwidget(); + explicit ConnectionWidget(const ConnectionId &id, QWidget *parent = nullptr); + ~ConnectionWidget(); private slots: - void on_pushButton_clicked(); + void on_editBtn_clicked(); + + void on_latencyBtn_clicked(); private: - int _id; - Ui::Formwidget *ui; + const ConnectionId _id; + const QvConnectionObject &connection; }; - -#endif // FORMWIDGET_H diff --git a/src/ui/widgets/ConnectionWidget.ui b/src/ui/widgets/ConnectionWidget.ui index d2a43730..23690e81 100644 --- a/src/ui/widgets/ConnectionWidget.ui +++ b/src/ui/widgets/ConnectionWidget.ui @@ -1,13 +1,13 @@ - Formwidget - + ConnectionWidget + 0 0 474 - 83 + 84 @@ -15,48 +15,61 @@ - + - + + + + 13 + + Connection Name - + - Type + Type: vmess + tls + ws - + + + + 8 + + - TextLabel + 0KB/0KB - + - Latency + Latency: 0ms + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + Edit - + Ping From 4c3dc850c2d191cf1cac689d5ae09a4834903c00 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 16 Feb 2020 20:28:30 +0800 Subject: [PATCH 009/332] wip: add: added full connection list view support --- makespec/BUILDVERSION | 2 +- src/base/Qv2rayLog.hpp | 32 +- src/common/CommandArgs.cpp | 8 +- src/common/HTTPRequestHelper.cpp | 10 +- src/common/QvHelpers.cpp | 6 +- src/components/geosite/QvGeositeReader.cpp | 6 +- src/components/pac/QvPACHandler.cpp | 16 +- .../plugins/toolbar/QvToolbar_linux.cpp | 8 +- .../plugins/toolbar/QvToolbar_win.cpp | 12 +- src/components/proxy/QvProxyConfigurator.cpp | 14 +- src/components/tcping/QvTCPing.cpp | 12 +- src/core/CoreUtils.cpp | 2 +- src/core/config/ConfigUpgrade.cpp | 8 +- src/core/connection/ConnectionIO.cpp | 26 +- src/core/connection/Generation.cpp | 22 +- src/core/connection/Serialization.cpp | 38 +- src/core/handler/ConnectionHandler.cpp | 14 +- src/core/handler/ConnectionHandler.hpp | 8 +- src/core/kernel/APIBackend.cpp | 12 +- src/core/kernel/KernelInteractions.cpp | 38 +- src/main.cpp | 64 +- src/ui/editors/w_InboundEditor.cpp | 8 +- src/ui/editors/w_JsonEditor.cpp | 2 +- src/ui/editors/w_OutboundEditor.cpp | 4 +- src/ui/editors/w_RoutesEditor.cpp | 52 +- src/ui/editors/w_RoutesEditor_extra.cpp | 28 +- src/ui/messaging/QvMessageBus.cpp | 4 +- src/ui/models/NodeModelsBase.hpp | 6 +- src/ui/w_ExportConfig.cpp | 2 +- src/ui/w_ImportConfig.cpp | 10 +- src/ui/w_MainWindow.cpp | 40 +- src/ui/w_MainWindow.ui | 649 +++++++++--------- src/ui/w_MainWindow_extra.cpp | 22 +- src/ui/w_PreferencesWindow.cpp | 50 +- src/ui/w_ScreenShot_Core.cpp | 2 +- src/ui/w_SubscriptionManager.cpp | 10 +- src/ui/widgets/ConnectionWidget.cpp | 16 - src/ui/widgets/ConnectionWidget.hpp | 56 +- src/ui/widgets/ConnectionWidget.ui | 62 +- 39 files changed, 710 insertions(+), 671 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index d1c67ac8..29276907 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3881 +3882 diff --git a/src/base/Qv2rayLog.hpp b/src/base/Qv2rayLog.hpp index 15423d48..e834ac77 100644 --- a/src/base/Qv2rayLog.hpp +++ b/src/base/Qv2rayLog.hpp @@ -31,23 +31,23 @@ namespace Qv2ray::base #define DEBUG(MODULE, MSG) __LOG_IMPL(QV2RAY_LOG_DEBUG, (MODULE), (MSG)); // Log modules used by Qv2ray -const inline QString INIT = "INIT" ; -const inline QString MESSAGING = "BASE-MESSAGING" ; -const inline QString UI = "CORE-UI" ; -const inline QString GRAPH = "CORE-UI-GRAPH" ; -const inline QString SETTINGS = "CORE-SETTINGS" ; -const inline QString VCORE = "CORE-VCORE" ; +const inline QString MODULE_INIT = "INIT" ; +const inline QString MODULE_MESSAGING = "BASE-MESSAGING" ; +const inline QString MODULE_UI = "CORE-UI" ; +const inline QString MODULE_GRAPH = "CORE-UI-GRAPH" ; +const inline QString MODULE_SETTINGS = "CORE-SETTINGS" ; +const inline QString MODULE_VCORE = "CORE-VCORE" ; // -const inline QString CONNECTION = "CORE-CONNECTION" ; -const inline QString SUBSCRIPTION = "CORE-SUBSCRIPTION" ; -const inline QString IMPORT = "CORE-IMPORT" ; -const inline QString EXPORT = "CORE-EXPORT" ; +const inline QString MODULE_CONNECTION = "CORE-CONNECTION" ; +const inline QString MODULE_SUBSCRIPTION = "CORE-SUBSCRIPTION" ; +const inline QString MODULE_IMPORT = "CORE-IMPORT" ; +const inline QString MODULE_EXPORT = "CORE-EXPORT" ; // -const inline QString NETWORK = "COMMON-NETWORK" ; -const inline QString FILEIO = "COMMON-FILEIO" ; +const inline QString MODULE_NETWORK = "COMMON-NETWORK" ; +const inline QString MODULE_FILEIO = "COMMON-FILEIO" ; // -const inline QString PROXY = "COMPONENT-PROXY" ; -const inline QString UPDATE = "COMPONENT-UPDATE" ; -const inline QString PLUGIN = "COMPONENT-PLUGIN" ; +const inline QString MODULE_PROXY = "COMPONENT-PROXY" ; +const inline QString MODULE_UPDATE = "COMPONENT-UPDATE" ; +const inline QString MODULE_PLUGIN = "COMPONENT-PLUGIN" ; // ================================================================ -const inline QString CORE_HANDLER = "libQv2ray: ConnectionHandler"; +const inline QString MODULE_CORE_HANDLER = "libQv2ray: ConnectionHandler"; diff --git a/src/common/CommandArgs.cpp b/src/common/CommandArgs.cpp index 5a1765f9..54081b41 100644 --- a/src/common/CommandArgs.cpp +++ b/src/common/CommandArgs.cpp @@ -36,22 +36,22 @@ namespace Qv2ray::common return CommandLineHelpRequested; if (parser.isSet(noAPIOption)) { - DEBUG(INIT, "noAPIOption is set.") + DEBUG(MODULE_INIT, "noAPIOption is set.") StartupOption.noAPI = true; } if (parser.isSet(runAsRootOption)) { - DEBUG(INIT, "runAsRootOption is set.") + DEBUG(MODULE_INIT, "runAsRootOption is set.") StartupOption.forceRunAsRootUser = true; } if (parser.isSet(debugOption)) { - DEBUG(INIT, "debugOption is set.") + DEBUG(MODULE_INIT, "debugOption is set.") StartupOption.debugLog = true; } if (parser.isSet(withToolbarOption)) { - DEBUG(INIT, "withToolbarOption is set.") + DEBUG(MODULE_INIT, "withToolbarOption is set.") StartupOption.enableToolbarPlguin = true; } diff --git a/src/common/HTTPRequestHelper.cpp b/src/common/HTTPRequestHelper.cpp index 609ffdc9..68fd06f9 100644 --- a/src/common/HTTPRequestHelper.cpp +++ b/src/common/HTTPRequestHelper.cpp @@ -19,7 +19,7 @@ namespace Qv2ray::common QUrl qUrl = QUrl(url); if (!qUrl.isValid()) { - LOG(NETWORK, "Provided URL is invalid: " + url) + LOG(MODULE_NETWORK, "Provided URL is invalid: " + url) return false; } @@ -29,7 +29,7 @@ namespace Qv2ray::common void QvHttpRequestHelper::setHeader(const QByteArray &key, const QByteArray &value) { - DEBUG(NETWORK, "Adding HTTP request header: " + key + ":" + value) + DEBUG(MODULE_NETWORK, "Adding HTTP request header: " + key + ":" + value) request.setRawHeader(key, value); } @@ -44,7 +44,7 @@ namespace Qv2ray::common accessManager.setProxy(QNetworkProxy(QNetworkProxy::ProxyType::NoProxy)); } - LOG(NETWORK, "Sync get is using system proxy settings") + LOG(MODULE_NETWORK, "Sync get is using system proxy settings") request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); reply = accessManager.get(request); connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished); @@ -104,13 +104,13 @@ namespace Qv2ray::common void QvHttpRequestHelper::onRequestFinished() { - LOG(NETWORK, "Network request errcode: " + QSTRN(reply->error())) + LOG(MODULE_NETWORK, "Network request errcode: " + QSTRN(reply->error())) emit httpRequestFinished(this->data); } void QvHttpRequestHelper::onReadyRead() { - DEBUG(NETWORK, "A request is now ready read") + DEBUG(MODULE_NETWORK, "A request is now ready read") this->data += reply->readAll(); } } diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 2abd8d4a..6a780fc5 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -72,7 +72,7 @@ namespace Qv2ray::common if (error.error == QJsonParseError::NoError) { return ""; } else { - LOG(UI, "WARNING: Json parse returns: " + error.errorString()) + LOG(MODULE_UI, "WARNING: Json parse returns: " + error.errorString()) return error.errorString(); } } @@ -172,7 +172,7 @@ namespace Qv2ray::common if (!QDir(baseDir).exists()) { QDir(baseDir).mkpath(baseDir); - LOG(FILEIO, "Making path: " + baseDir) + LOG(MODULE_FILEIO, "Making path: " + baseDir) } while (true) { @@ -180,7 +180,7 @@ namespace Qv2ray::common *fileName = *fileName + "_" + QSTRN(i); return; } else { - DEBUG(FILEIO, "File with name: " + *fileName + "_" + QSTRN(i) + extension + " already exists") + DEBUG(MODULE_FILEIO, "File with name: " + *fileName + "_" + QSTRN(i) + extension + " already exists") } i++; diff --git a/src/components/geosite/QvGeositeReader.cpp b/src/components/geosite/QvGeositeReader.cpp index 444ccf65..83f78c50 100644 --- a/src/components/geosite/QvGeositeReader.cpp +++ b/src/components/geosite/QvGeositeReader.cpp @@ -6,7 +6,7 @@ namespace Qv2ray::components::geosite QStringList ReadGeoSiteFromFile(QString filepath) { QStringList list; - LOG(FILEIO, "Reading geosites from: " + filepath) + LOG(MODULE_FILEIO, "Reading geosites from: " + filepath) // GOOGLE_PROTOBUF_VERIFY_VERSION; // @@ -14,7 +14,7 @@ namespace Qv2ray::components::geosite bool opened = f.open(QFile::OpenModeFlag::ReadOnly); if (!opened) { - LOG(FILEIO, "File cannot be opened: " + filepath) + LOG(MODULE_FILEIO, "File cannot be opened: " + filepath) return list; } @@ -29,7 +29,7 @@ namespace Qv2ray::components::geosite list << QString::fromStdString(e.country_code()).toLower(); } - LOG(FILEIO, "Loaded " + QSTRN(list.count()) + " geosite entries from data file.") + LOG(MODULE_FILEIO, "Loaded " + QSTRN(list.count()) + " geosite entries from data file.") // Optional: Delete all global objects allocated by libprotobuf. google::protobuf::ShutdownProtobufLibrary(); return list; diff --git a/src/components/pac/QvPACHandler.cpp b/src/components/pac/QvPACHandler.cpp index 7ddcae01..033f1a32 100644 --- a/src/components/pac/QvPACHandler.cpp +++ b/src/components/pac/QvPACHandler.cpp @@ -19,17 +19,17 @@ namespace Qv2ray::components::pac } void PACServer::SetProxyString(const QString &proxyString) { - DEBUG(PROXY, "Setting new PAC proxy string: " + proxyString) + DEBUG(MODULE_PROXY, "Setting new PAC proxy string: " + proxyString) this->proxyString = proxyString; } void PACServer::StartListen() { - LOG(PROXY, "Starting PAC listener") + LOG(MODULE_PROXY, "Starting PAC listener") // auto address = GlobalConfig.inboundConfig.listenip; auto port = GlobalConfig.inboundConfig.pacConfig.port; // - DEBUG(PROXY, "PAC Listening local endpoint: " + address + ":" + QSTRN(port)) + DEBUG(MODULE_PROXY, "PAC Listening local endpoint: " + address + ":" + QSTRN(port)) // QString gfwContent = StringFromFile(QV2RAY_RULES_GFWLIST_PATH); pacContent = ConvertGFWToPAC(gfwContent, proxyString); @@ -38,9 +38,9 @@ namespace Qv2ray::components::pac if (result) { isStarted = true; - DEBUG(PROXY, "Started PAC handler") + DEBUG(MODULE_PROXY, "Started PAC handler") } else { - LOG(PROXY, "Failed to listen on port " + QSTRN(port) + ", possible permission denied.") + LOG(MODULE_PROXY, "Failed to listen on port " + QSTRN(port) + ", possible permission denied.") QvMessageBoxWarn(nullptr, tr("PAC Handler"), tr("Failed to listen PAC request on this port, please verify the permissions")); } } @@ -49,7 +49,7 @@ namespace Qv2ray::components::pac { if (isStarted) { pacServer.close(); - DEBUG(PROXY, "PAC Handler stopped.") + DEBUG(MODULE_PROXY, "PAC Handler stopped.") isStarted = false; } } @@ -61,12 +61,12 @@ namespace Qv2ray::components::pac if (req->method() == QHttpRequest::HTTP_GET) { // if (req->path() == "/pac") { - DEBUG(PROXY, "Serving PAC file request.") + DEBUG(MODULE_PROXY, "Serving PAC file request.") // rsp->setHeader("Content-Type", "application/javascript; charset=utf-8"); rsp->writeHead(QHttpResponse::StatusCode::STATUS_OK); rsp->end(pacContent.toUtf8()); - DEBUG(PROXY, "Serving a pac file...") + DEBUG(MODULE_PROXY, "Serving a pac file...") } else { rsp->writeHead(QHttpResponse::StatusCode::STATUS_NOT_FOUND); rsp->end("NOT FOUND"); diff --git a/src/components/plugins/toolbar/QvToolbar_linux.cpp b/src/components/plugins/toolbar/QvToolbar_linux.cpp index 78b903aa..5ff3ec30 100644 --- a/src/components/plugins/toolbar/QvToolbar_linux.cpp +++ b/src/components/plugins/toolbar/QvToolbar_linux.cpp @@ -35,7 +35,7 @@ namespace Qv2ray::components::plugins::Toolbar } } } catch (...) { - LOG(PLUGIN, "Closing a broken socket.") + LOG(MODULE_PLUGIN, "Closing a broken socket.") } } void DataMessageQThread() @@ -55,8 +55,8 @@ namespace Qv2ray::components::plugins::Toolbar while (!isExiting) { bool result = server->waitForNewConnection(5000, &timeOut); - DEBUG(PLUGIN, "Plugin thread listening failed: " + server->errorString()) - DEBUG(PLUGIN, "waitForNewConnection: " + QString(result ? "true" : "false") + ", " + QString(timeOut ? "true" : "false")) + DEBUG(MODULE_PLUGIN, "Plugin thread listening failed: " + server->errorString()) + DEBUG(MODULE_PLUGIN, "waitForNewConnection: " + QString(result ? "true" : "false") + ", " + QString(timeOut ? "true" : "false")) } server->close(); @@ -73,7 +73,7 @@ namespace Qv2ray::components::plugins::Toolbar isExiting = true; if (linuxWorkerThread->isRunning()) { - LOG(PLUGIN, "Waiting for linuxWorkerThread to stop.") + LOG(MODULE_PLUGIN, "Waiting for linuxWorkerThread to stop.") linuxWorkerThread->wait(); } diff --git a/src/components/plugins/toolbar/QvToolbar_win.cpp b/src/components/plugins/toolbar/QvToolbar_win.cpp index 0717fe96..c9795d47 100644 --- a/src/components/plugins/toolbar/QvToolbar_win.cpp +++ b/src/components/plugins/toolbar/QvToolbar_win.cpp @@ -44,18 +44,18 @@ namespace Qv2ray::components::plugins::Toolbar hPipe = CreateNamedPipe(lpszPipename.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, 0, nullptr); if (hPipe == INVALID_HANDLE_VALUE) { - LOG(PLUGIN, "CreateNamedPipe failed, GLE=" + QSTRN(GetLastError())) + LOG(MODULE_PLUGIN, "CreateNamedPipe failed, GLE=" + QSTRN(GetLastError())) return static_cast(-1); } fConnected = ConnectNamedPipe(hPipe, nullptr) ? true : (GetLastError() == ERROR_PIPE_CONNECTED); if (fConnected) { - LOG(PLUGIN, "Client connected, creating a processing thread") + LOG(MODULE_PLUGIN, "Client connected, creating a processing thread") ThreadHandle = CreateThread(nullptr, 0, InstanceThread, hPipe, 0, &dwThreadId); if (ThreadHandle == nullptr) { - LOG(PLUGIN, "CreateThread failed, GLE=" + QSTRN(GetLastError())) + LOG(MODULE_PLUGIN, "CreateThread failed, GLE=" + QSTRN(GetLastError())) return static_cast(-1); } else CloseHandle(ThreadHandle); } else CloseHandle(hPipe); @@ -76,9 +76,9 @@ namespace Qv2ray::components::plugins::Toolbar if (!fSuccess || cbBytesRead == 0) { if (GetLastError() == ERROR_BROKEN_PIPE) { - LOG(PLUGIN, "InstanceThread: client disconnected, GLE=" + QSTRN(GetLastError())) + LOG(MODULE_PLUGIN, "InstanceThread: client disconnected, GLE=" + QSTRN(GetLastError())) } else { - LOG(PLUGIN, "InstanceThread ReadFile failed, GLE=" + QSTRN(GetLastError())) + LOG(MODULE_PLUGIN, "InstanceThread ReadFile failed, GLE=" + QSTRN(GetLastError())) } break; @@ -98,7 +98,7 @@ namespace Qv2ray::components::plugins::Toolbar fSuccess = WriteFile(hPipe, pchReply.c_str(), cbReplyBytes, &cbWritten, nullptr); if (!fSuccess || cbReplyBytes != cbWritten) { - LOG(PLUGIN, "InstanceThread WriteFile failed, GLE=" + QSTRN(GetLastError())) + LOG(MODULE_PLUGIN, "InstanceThread WriteFile failed, GLE=" + QSTRN(GetLastError())) break; } } diff --git a/src/components/proxy/QvProxyConfigurator.cpp b/src/components/proxy/QvProxyConfigurator.cpp index efbaac55..14cb79db 100644 --- a/src/components/proxy/QvProxyConfigurator.cpp +++ b/src/components/proxy/QvProxyConfigurator.cpp @@ -174,19 +174,19 @@ namespace Qv2ray::components::proxy bool hasSOCKS = (socksPort != 0); if (!(hasHTTP || hasSOCKS || usePAC)) { - LOG(PROXY, "Nothing?") + LOG(MODULE_PROXY, "Nothing?") return; } if (usePAC) { - LOG(PROXY, "Qv2ray will set system proxy to use PAC file") + LOG(MODULE_PROXY, "Qv2ray will set system proxy to use PAC file") } else { if (hasHTTP) { - LOG(PROXY, "Qv2ray will set system proxy to use HTTP") + LOG(MODULE_PROXY, "Qv2ray will set system proxy to use HTTP") } if (hasSOCKS) { - LOG(PROXY, "Qv2ray will set system proxy to use SOCKS") + LOG(MODULE_PROXY, "Qv2ray will set system proxy to use SOCKS") } } @@ -235,13 +235,13 @@ namespace Qv2ray::components::proxy // note: do not use std::all_of / any_of / none_of, // because those are short-circuit and cannot guarantee atomicity. auto result = std::count_if(actions.cbegin(), actions.cend(), [](const QString & action) { - DEBUG(PROXY, action) + DEBUG(MODULE_PROXY, action) return QProcess::execute(action) == QProcess::NormalExit; }) == actions.size(); if (!result) { - LOG(PROXY, "Something wrong happens when setting system proxy -> Gnome ONLY.") - LOG(PROXY, "If you are using KDE Plasma and receiving this message, just simply ignore this.") + LOG(MODULE_PROXY, "Something wrong happens when setting system proxy -> Gnome ONLY.") + LOG(MODULE_PROXY, "If you are using KDE Plasma and receiving this message, just simply ignore this.") } Q_UNUSED(result); diff --git a/src/components/tcping/QvTCPing.cpp b/src/components/tcping/QvTCPing.cpp index a48d9d95..62a0f144 100644 --- a/src/components/tcping/QvTCPing.cpp +++ b/src/components/tcping/QvTCPing.cpp @@ -34,16 +34,16 @@ namespace Qv2ray::components::tcping data.port = port; data.connectionIdentifier = connectionName; auto watcher = new QFutureWatcher(this); - DEBUG(NETWORK, "Start Ping: " + hostName + ":" + QSTRN(port)) + DEBUG(MODULE_NETWORK, "Start Ping: " + hostName + ":" + QSTRN(port)) watcher->setFuture(QtConcurrent::run(&QvTCPingModel::startTestLatency, data, count)); pingWorkingThreads.enqueue(watcher); connect(watcher, &QFutureWatcher::finished, this, [this, watcher]() { this->pingWorkingThreads.removeOne(watcher); auto result = watcher->result(); - DEBUG(NETWORK, "Ping finished: " + result.hostName + ":" + QSTRN(result.port) + " --> " + QSTRN(result.avg) + "ms") + DEBUG(MODULE_NETWORK, "Ping finished: " + result.hostName + ":" + QSTRN(result.port) + " --> " + QSTRN(result.avg) + "ms") if (!result.errorMessage.isEmpty()) { - LOG(NETWORK, "Ping --> " + result.errorMessage) + LOG(MODULE_NETWORK, "Ping --> " + result.errorMessage) } emit this->PingFinished(result); @@ -78,13 +78,13 @@ namespace Qv2ray::components::tcping if ((errcode = testLatency(resolved, &start, &end)) != 0) { if (errcode != -EADDRNOTAVAIL) { - LOG(NETWORK, "Error connecting to host: " + data.hostName + ":" + QSTRN(data.port) + " " + strerror(-errcode)) + LOG(MODULE_NETWORK, "Error connecting to host: " + data.hostName + ":" + QSTRN(data.port) + " " + strerror(-errcode)) errorCount++; } else { if (noAddress) { - LOG(NETWORK, ".") + LOG(MODULE_NETWORK, ".") } else { - LOG(NETWORK, "error connecting to host: " + QSTRN(-errcode) + " " + strerror(-errcode)) + LOG(MODULE_NETWORK, "error connecting to host: " + QSTRN(-errcode) + " " + strerror(-errcode)) } noAddress = true; diff --git a/src/core/CoreUtils.cpp b/src/core/CoreUtils.cpp index cabbf08b..5e54924c 100644 --- a/src/core/CoreUtils.cpp +++ b/src/core/CoreUtils.cpp @@ -18,7 +18,7 @@ namespace Qv2ray::core if (validOutboundFound) { return make_tuple(host, port, outboundType); } else { - LOG(UI, "Unknown outbound entry: " + outboundType + ", cannot deduce host and port.") + LOG(MODULE_UI, "Unknown outbound entry: " + outboundType + ", cannot deduce host and port.") } } diff --git a/src/core/config/ConfigUpgrade.cpp b/src/core/config/ConfigUpgrade.cpp index 079d93a6..2e916b43 100644 --- a/src/core/config/ConfigUpgrade.cpp +++ b/src/core/config/ConfigUpgrade.cpp @@ -6,7 +6,7 @@ #include "base/Qv2rayBase.hpp" #include "common/QvHelpers.hpp" -#define UPGRADELOG(msg) LOG(SETTINGS, " [" + QSTRN(fromVersion) + "-" + QSTRN(fromVersion + 1) + "] --> " + msg) +#define UPGRADELOG(msg) LOG(MODULE_SETTINGS, " [" + QSTRN(fromVersion) + "-" + QSTRN(fromVersion + 1) + "] --> " + msg) namespace Qv2ray { @@ -130,7 +130,7 @@ namespace Qv2ray auto filePath = QV2RAY_CONFIG_DIR + config.toString() + QV2RAY_CONFIG_FILE_EXTENSION; auto configFile = QFile(filePath); auto newUuid = GenerateUuid(); - DEBUG(SETTINGS, "Generated new UUID: " + newUuid); + DEBUG(MODULE_SETTINGS, "Generated new UUID: " + newUuid); if (configFile.exists()) { auto newPath = QV2RAY_CONNECTIONS_DIR + newUuid + QV2RAY_CONFIG_FILE_EXTENSION; @@ -144,7 +144,7 @@ namespace Qv2ray QJsonObject connectionObject; connectionObject["displayName"] = config.toString(); defaultGroupConnectionId << newUuid; - DEBUG(SETTINGS, "Pushed uuid: " + newUuid + " to default group.") + DEBUG(MODULE_SETTINGS, "Pushed uuid: " + newUuid + " to default group.") rootConnections[newUuid] = connectionObject; } @@ -223,7 +223,7 @@ namespace Qv2ray // Exported function QJsonObject UpgradeConfig(int fromVersion, int toVersion, QJsonObject root) { - LOG(SETTINGS, "Migrating config from version " + QSTRN(fromVersion) + " to " + QSTRN(toVersion)) + LOG(MODULE_SETTINGS, "Migrating config from version " + QSTRN(fromVersion) + " to " + QSTRN(toVersion)) for (int i = fromVersion; i < toVersion; i++) { root = UpgradeConfig_Inc(i, root); diff --git a/src/core/connection/ConnectionIO.cpp b/src/core/connection/ConnectionIO.cpp index 0ad437bb..0296c0e4 100644 --- a/src/core/connection/ConnectionIO.cpp +++ b/src/core/connection/ConnectionIO.cpp @@ -11,7 +11,7 @@ namespace Qv2ray::core::connection auto conf = CONFIGROOT(JsonFromString(jsonString)); if (conf.count() == 0) { - LOG(SETTINGS, "WARN: Possible file corruption, failed to load file: " + connection + " --> File might be empty.") + LOG(MODULE_SETTINGS, "WARN: Possible file corruption, failed to load file: " + connection + " --> File might be empty.") } return conf; @@ -41,12 +41,12 @@ namespace Qv2ray::core::connection confName.chop(sizeof(QV2RAY_CONFIG_FILE_EXTENSION) - 1); _config[confName] = _ReadConnection(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + _file); } else { - LOG(SUBSCRIPTION, "Found a file in subscription folder but without proper suffix: " + _file) + LOG(MODULE_SUBSCRIPTION, "Found a file in subscription folder but without proper suffix: " + _file) } } if (_config.isEmpty()) { - LOG(SUBSCRIPTION, "WARN: Maybe loading an empty subscrption: " + subscription) + LOG(MODULE_SUBSCRIPTION, "WARN: Maybe loading an empty subscrption: " + subscription) } return _config; @@ -58,7 +58,7 @@ namespace Qv2ray::core::connection QMap> list; for (auto singleSub : subscriptions) { - LOG(SUBSCRIPTION, "Processing subscription: " + singleSub) + LOG(MODULE_SUBSCRIPTION, "Processing subscription: " + singleSub) list[singleSub] = GetSubscriptionConnection(singleSub); } @@ -80,7 +80,7 @@ namespace Qv2ray::core::connection fullPath = QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION; } - LOG(SETTINGS, "Saving a config named: " + *alias) + LOG(MODULE_SETTINGS, "Saving a config named: " + *alias) QFile config(fullPath); return StringToFile(&str, &config); } @@ -98,14 +98,14 @@ namespace Qv2ray::core::connection // If there's already a file. THIS IS EXTREMELY RARE if (config.exists()) { - LOG(FILEIO, "Trying to overrwrite an existing subscription config file. THIS IS RARE") + LOG(MODULE_FILEIO, "Trying to overrwrite an existing subscription config file. THIS IS RARE") } - LOG(SETTINGS, "Saving a subscription named: " + fName) + LOG(MODULE_SETTINGS, "Saving a subscription named: " + fName) bool result = StringToFile(&str, &config); if (!result) { - LOG(FILEIO, "Failed to save a connection config from subscription: " + subscription + ", name: " + fName) + LOG(MODULE_FILEIO, "Failed to save a connection config from subscription: " + subscription + ", name: " + fName) } *name = fName; @@ -117,7 +117,7 @@ namespace Qv2ray::core::connection QFile config(QV2RAY_CONFIG_DIR + alias + QV2RAY_CONFIG_FILE_EXTENSION); if (!config.exists()) { - LOG(FILEIO, "Trying to remove a non-existing file?") + LOG(MODULE_FILEIO, "Trying to remove a non-existing file?") return false; } else { return config.remove(); @@ -129,7 +129,7 @@ namespace Qv2ray::core::connection QFile config(QV2RAY_SUBSCRIPTION_DIR + subsName + "/" + name + QV2RAY_CONFIG_FILE_EXTENSION); if (!config.exists()) { - LOG(FILEIO, "Trying to remove a non-existing file?") + LOG(MODULE_FILEIO, "Trying to remove a non-existing file?") return false; } else { return config.remove(); @@ -138,13 +138,13 @@ namespace Qv2ray::core::connection bool RenameConnection(const QString &originalName, const QString &newName) { - LOG(CONNECTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName) + LOG(MODULE_CONNECTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName) return QFile::rename(QV2RAY_CONFIG_DIR + originalName + QV2RAY_CONFIG_FILE_EXTENSION, QV2RAY_CONFIG_DIR + newName + QV2RAY_CONFIG_FILE_EXTENSION); } bool RenameSubscription(const QString &originalName, const QString &newName) { - LOG(SUBSCRIPTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName) + LOG(MODULE_SUBSCRIPTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName) return QDir().rename(QV2RAY_SUBSCRIPTION_DIR + originalName, QV2RAY_SUBSCRIPTION_DIR + newName); } @@ -153,7 +153,7 @@ namespace Qv2ray::core::connection QFile source(sourceFilePath); if (!source.exists()) { - LOG(FILEIO, "Trying to import from an non-existing file.") + LOG(MODULE_FILEIO, "Trying to import from an non-existing file.") return CONFIGROOT(); } diff --git a/src/core/connection/Generation.cpp b/src/core/connection/Generation.cpp index bfaf8383..28dc3c52 100644 --- a/src/core/connection/Generation.cpp +++ b/src/core/connection/Generation.cpp @@ -181,7 +181,7 @@ namespace Qv2ray::core::connection INBOUND GenerateInboundEntry(QString listen, int port, QString protocol, INBOUNDSETTING settings, QString tag, QJsonObject sniffing, QJsonObject allocate) { INBOUND root; - LOG(CONNECTION, "allocation is not used here.") + LOG(MODULE_CONNECTION, "allocation is not used here.") Q_UNUSED(allocate) JADD(listen, port, protocol, settings, tag, sniffing) RROOT @@ -261,7 +261,7 @@ namespace Qv2ray::core::connection } root["inbounds"] = inboundsList; - DEBUG(CONNECTION, "Added global config inbounds to the config") + DEBUG(MODULE_CONNECTION, "Added global config inbounds to the config") } // Process every inbounds to make sure a tag is configured, fixed API 0 speed @@ -272,7 +272,7 @@ namespace Qv2ray::core::connection auto _inboundItem = newTaggedInbounds[i].toObject(); if (!_inboundItem.contains("tag") || _inboundItem["tag"].toString().isEmpty()) { - LOG(SETTINGS, "Adding a tag to an inbound.") + LOG(MODULE_SETTINGS, "Adding a tag to an inbound.") _inboundItem["tag"] = GenerateRandomString(8); newTaggedInbounds[i] = _inboundItem; } @@ -294,7 +294,7 @@ namespace Qv2ray::core::connection // And what's more, process (by removing unused items) from a rule object. ROUTING routing = ROUTING(root["routing"].toObject()); ROUTERULELIST rules; - LOG(CONNECTION, "Processing an existing routing table.") + LOG(MODULE_CONNECTION, "Processing an existing routing table.") for (auto _rule : routing["rules"].toArray()) { auto _b = _rule.toObject(); @@ -308,14 +308,14 @@ namespace Qv2ray::core::connection _b.remove("balancerTag"); } } else { - LOG(SETTINGS, "We found a rule without QV2RAY_RULE_USE_BALANCER, so don't process it.") + LOG(MODULE_SETTINGS, "We found a rule without QV2RAY_RULE_USE_BALANCER, so don't process it.") } // If this entry has been disabled. if (_b.contains("QV2RAY_RULE_ENABLED") && _b["QV2RAY_RULE_ENABLED"].toBool() == true) { rules.append(_b); } else { - LOG(SETTINGS, "Discarded a rule as it's been set DISABLED") + LOG(MODULE_SETTINGS, "Discarded a rule as it's been set DISABLED") } } @@ -323,12 +323,12 @@ namespace Qv2ray::core::connection root["routing"] = routing; } else { // - LOG(CONNECTION, "Inserting default values to simple config") + LOG(MODULE_CONNECTION, "Inserting default values to simple config") if (root["outbounds"].toArray().count() != 1) { // There are no ROUTING but 2 or more outbounds.... This is rare, but possible. - LOG(CONNECTION, "WARN: This message usually indicates the config file has logic errors:") - LOG(CONNECTION, "WARN: --> The config file has NO routing section, however more than 1 outbounds are detected.") + LOG(MODULE_CONNECTION, "WARN: This message usually indicates the config file has logic errors:") + LOG(MODULE_CONNECTION, "WARN: --> The config file has NO routing section, however more than 1 outbounds are detected.") } auto routeObject = GenerateRoutes(GlobalConfig.connectionConfig.enableProxy, GlobalConfig.connectionConfig.bypassCN); @@ -342,7 +342,7 @@ namespace Qv2ray::core::connection auto firstOutbound = outboundArray.first().toObject(); if (firstOutbound[QV2RAY_USE_FPROXY_KEY].toBool(false)) { - LOG(CONNECTION, "Applying forward proxy to current connection.") + LOG(MODULE_CONNECTION, "Applying forward proxy to current connection.") auto proxy = PROXYSETTING(); proxy["tag"] = OUTBOUND_TAG_FORWARD_PROXY; firstOutbound["proxySettings"] = proxy; @@ -353,7 +353,7 @@ namespace Qv2ray::core::connection fpOutbound = GenerateHTTPSOCKSOut(fpConf.serverAddress, fpConf.port, fpConf.useAuth, fpConf.username, fpConf.password); outboundArray.push_back(GenerateOutboundEntry(fpConf.type.toLower(), fpOutbound, QJsonObject(), QJsonObject(), "0.0.0.0", OUTBOUND_TAG_FORWARD_PROXY)); } else { - LOG(CONNECTION, "WARNING: Unsupported outbound type: " + fpConf.type) + LOG(MODULE_CONNECTION, "WARNING: Unsupported outbound type: " + fpConf.type) } } else { // Remove proxySettings from firstOutbound diff --git a/src/core/connection/Serialization.cpp b/src/core/connection/Serialization.cpp index bd0800e2..42ba4cb3 100644 --- a/src/core/connection/Serialization.cpp +++ b/src/core/connection/Serialization.cpp @@ -38,7 +38,7 @@ namespace Qv2ray::core::connection auto ssServer = StructFromJsonString(JsonToString(outbound["settings"].toObject()["servers"].toArray().first().toObject())); sharelink = ConvertConfigToSSString(ssServer, alias, isSip002); } else { - LOG(CONNECTION, "Unsupported outbound type: " + type) + LOG(MODULE_CONNECTION, "Unsupported outbound type: " + type) } return sharelink; @@ -101,13 +101,13 @@ namespace Qv2ray::core::connection //auto ssUri = _ssUri.toStdString(); if (ssUri.length() < 5) { - LOG(CONNECTION, "ss:// string too short") + LOG(MODULE_CONNECTION, "ss:// string too short") *errMessage = QObject::tr("SS URI is too short"); } auto uri = ssUri.mid(5); auto hashPos = uri.lastIndexOf("#"); - DEBUG(CONNECTION, "Hash sign position: " + QSTRN(hashPos)) + DEBUG(MODULE_CONNECTION, "Hash sign position: " + QSTRN(hashPos)) if (hashPos >= 0) { // Get the name/remark @@ -123,13 +123,13 @@ namespace Qv2ray::core::connection // uri.erase(pluginPos); //} auto atPos = uri.indexOf('@'); - DEBUG(CONNECTION, "At sign position: " + QSTRN(atPos)) + DEBUG(MODULE_CONNECTION, "At sign position: " + QSTRN(atPos)) if (atPos < 0) { // Old URI scheme QString decoded = QByteArray::fromBase64(uri.toUtf8(), QByteArray::Base64Option::OmitTrailingEquals); auto colonPos = decoded.indexOf(':'); - DEBUG(CONNECTION, "Colon position: " + QSTRN(colonPos)) + DEBUG(MODULE_CONNECTION, "Colon position: " + QSTRN(colonPos)) if (colonPos < 0) { *errMessage = QObject::tr("Can't find the colon separator between method and password"); @@ -138,7 +138,7 @@ namespace Qv2ray::core::connection server.method = decoded.left(colonPos); decoded.remove(0, colonPos + 1); atPos = decoded.lastIndexOf('@'); - DEBUG(CONNECTION, "At sign position: " + QSTRN(atPos)) + DEBUG(MODULE_CONNECTION, "At sign position: " + QSTRN(atPos)) if (atPos < 0) { *errMessage = QObject::tr("Can't find the at separator between password and hostname"); @@ -147,7 +147,7 @@ namespace Qv2ray::core::connection server.password = decoded.mid(0, atPos); decoded.remove(0, atPos + 1); colonPos = decoded.lastIndexOf(':'); - DEBUG(CONNECTION, "Colon position: " + QSTRN(colonPos)) + DEBUG(MODULE_CONNECTION, "Colon position: " + QSTRN(colonPos)) if (colonPos < 0) { *errMessage = QObject::tr("Can't find the colon separator between hostname and port"); @@ -163,7 +163,7 @@ namespace Qv2ray::core::connection QString userInfo = Base64Decode(x.userName()); auto userInfoSp = userInfo.indexOf(':'); // - DEBUG(CONNECTION, "Userinfo splitter position: " + QSTRN(userInfoSp)) + DEBUG(MODULE_CONNECTION, "Userinfo splitter position: " + QSTRN(userInfoSp)) if (userInfoSp < 0) { *errMessage = QObject::tr("Can't find the colon separator between method and password"); @@ -180,7 +180,7 @@ namespace Qv2ray::core::connection outbounds.append(GenerateOutboundEntry("shadowsocks", GenerateShadowSocksOUT(QList() << server), QJsonObject())); JADD(outbounds) *alias = alias->isEmpty() ? d_name : *alias + "_" + d_name; - LOG(CONNECTION, "Deduced alias: " + *alias) + LOG(MODULE_CONNECTION, "Deduced alias: " + *alias) return root; } @@ -189,12 +189,12 @@ namespace Qv2ray::core::connection auto myAlias = QUrl::toPercentEncoding(alias); if (isSip002) { - LOG(CONNECTION, "Converting an ss-server config to Sip002 ss:// format") + LOG(MODULE_CONNECTION, "Converting an ss-server config to Sip002 ss:// format") QString plainUserInfo = server.method + ":" + server.password; QString userinfo(plainUserInfo.toUtf8().toBase64(QByteArray::Base64Option::Base64UrlEncoding).data()); return "ss://" + userinfo + "@" + server.address + ":" + QSTRN(server.port) + "#" + myAlias; } else { - LOG(CONNECTION, "Converting an ss-server config to old ss:// string format") + LOG(MODULE_CONNECTION, "Converting an ss-server config to old ss:// string format") QString ssUri = server.method + ":" + server.password + "@" + server.address + ":" + QSTRN(server.port); return "ss://" + ssUri.toUtf8().toBase64(QByteArray::Base64Option::OmitTrailingEquals) + "#" + myAlias; } @@ -205,11 +205,11 @@ namespace Qv2ray::core::connection CONFIGROOT ConvertConfigFromVMessString(const QString &vmessStr, QString *alias, QString *errMessage) { #define default CONFIGROOT() - LOG(SETTINGS, "Trying to convert from a vmess string.") + LOG(MODULE_SETTINGS, "Trying to convert from a vmess string.") QString vmess = vmessStr; if (vmess.trimmed() != vmess) { - LOG(SETTINGS, "VMess string has some prefix/postfix spaces, trimming.") + LOG(MODULE_SETTINGS, "VMess string has some prefix/postfix spaces, trimming.") vmess = vmessStr.trimmed(); } @@ -264,7 +264,7 @@ namespace Qv2ray::core::connection //return flag ? 0 : 1; } catch (exception *e) { *errMessage = e->what(); - LOG(IMPORT, "Failed to decode vmess string: " + *errMessage) + LOG(MODULE_IMPORT, "Failed to decode vmess string: " + *errMessage) delete e; return default; } @@ -292,15 +292,15 @@ namespace Qv2ray::core::connection if (vmessConf.contains(#key) && !vmessConf[#key].toVariant().toString().trimmed().isEmpty() \ && (val.size() <= 1 || val.contains(vmessConf[#key].toVariant().toString()))) {\ key = vmessConf[#key].toVariant().toString();\ - DEBUG(IMPORT, "Found key \"" #key "\" within the vmess object.")\ + DEBUG(MODULE_IMPORT, "Found key \"" #key "\" within the vmess object.")\ } else if (!val.isEmpty()) {\ key = val.first(); \ - DEBUG(IMPORT, "Using key \"" #key "\" from the first candidate list: " + key)\ + DEBUG(MODULE_IMPORT, "Using key \"" #key "\" from the first candidate list: " + key)\ } else{\ *errMessage = QObject::tr(#key " does not exist."); \ - LOG(IMPORT, "Cannot process \"" #key "\" since it's not included in the json object." ) \ - LOG(IMPORT, " --> values: " + val.join(";")) \ - LOG(IMPORT, " --> PS: " + ps) \ + LOG(MODULE_IMPORT, "Cannot process \"" #key "\" since it's not included in the json object." ) \ + LOG(MODULE_IMPORT, " --> values: " + val.join(";")) \ + LOG(MODULE_IMPORT, " --> PS: " + ps) \ }\ } // Strict check of VMess protocol, to check if the specified value is in the correct range. diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index ea042b17..ba77a1aa 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -16,7 +16,7 @@ namespace Qv2ray::core::handlers ConnectionHandler::ConnectionHandler() { - DEBUG(CORE_HANDLER, "ConnectionHandler Constructor.") + DEBUG(MODULE_CORE_HANDLER, "ConnectionHandler Constructor.") // Do we need to check how many of them are loaded? for (auto i = 0; i < GlobalConfig.connections.count(); i++) { @@ -58,11 +58,21 @@ namespace Qv2ray::core::handlers const QvConnectionObject &ConnectionHandler::GetConnection(const ConnectionId &id) { if (!connections.contains(id)) { - LOG(CORE_HANDLER, "Cannot find id: " + id.toString()); + LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); } return connections[id]; } + + const QvGroupObject &ConnectionHandler::GetGroup(const GroupId &id) + { + return groups[id]; + } + + const QvSubscriptionObject &ConnectionHandler::GetSubscription(const SubscriptionId &id) + { + return subscriptions[id]; + } ConnectionHandler::~ConnectionHandler() { } diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index a8f129fe..675a6ebb 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -73,13 +73,15 @@ namespace Qv2ray::core::handlers optional TestAllLatency(); // // Group Operations + const QvGroupObject &GetGroup(const GroupId &id); const GroupId CreateGroup(const QString displayName); optional DeleteGroup(const GroupId &id); optional DuplicateGroup(const GroupId &id); optional RenameGroup(const GroupId &id, const QString &newName); // // Subscriptions - const SubscriptionId CreateSubscription(const QString &displayName, const QString &address); + const QvSubscriptionObject &GetSubscription(const SubscriptionId &id); + const SubscriptionId &CreateSubscription(const QString &displayName, const QString &address); optional RenameSubscription(const SubscriptionId &id, const QString &newName); optional DeleteSubscription(const SubscriptionId &id); optional UpdateSubscription(const SubscriptionId &id); @@ -108,14 +110,14 @@ namespace Qv2ray::core::handlers QHash connections; QHash subscriptions; // - QMap kernelInstances; + QHash kernelInstances; }; // inline unique_ptr connectionHandler = nullptr; // inline void InitialiseConnectionHandler() { - LOG(CORE_HANDLER, "Initializing ConnectionHandler...") + LOG(MODULE_CORE_HANDLER, "Initializing ConnectionHandler...") connectionHandler = make_unique(); } // diff --git a/src/core/kernel/APIBackend.cpp b/src/core/kernel/APIBackend.cpp index 91bafd9f..8b84840f 100644 --- a/src/core/kernel/APIBackend.cpp +++ b/src/core/kernel/APIBackend.cpp @@ -19,15 +19,15 @@ namespace Qv2ray::core::kernel::api { thread = new QThread(); this->moveToThread(thread); - DEBUG(VCORE, "API Worker initialised.") + DEBUG(MODULE_VCORE, "API Worker initialised.") connect(this, SIGNAL(error(QString)), this, SLOT(errorString(QString))); connect(thread, SIGNAL(started()), this, SLOT(process())); connect(thread, &QThread::finished, []() { - LOG(VCORE, "API thread stopped") + LOG(MODULE_VCORE, "API thread stopped") }); started = true; thread->start(); - DEBUG(VCORE, "API Worker started.") + DEBUG(MODULE_VCORE, "API Worker started.") } void APIWorkder::StartAPI(QStringList tags) @@ -74,7 +74,7 @@ namespace Qv2ray::core::kernel::api Stub = service.NewStub(Channel); #else auto str = Dial(const_cast(channelAddress.toStdString().c_str()), 10000); - LOG(VCORE, QString(str)) + LOG(MODULE_VCORE, QString(str)) free(str); #endif dialed = true; @@ -108,7 +108,7 @@ namespace Qv2ray::core::kernel::api qint64 APIWorkder::CallStatsAPIByName(QString name) { if (apiFailedCounter == QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD) { - LOG(VCORE, "API call failure threshold reached, cancelling further API aclls.") + LOG(MODULE_VCORE, "API call failure threshold reached, cancelling further API aclls.") emit error("Failed to get statistics data, please check if V2ray is running properly"); apiFailedCounter++; return 0; @@ -135,7 +135,7 @@ namespace Qv2ray::core::kernel::api #endif if (data < 0) { - LOG(VCORE, "API call returns: " + QSTRN(data)) + LOG(MODULE_VCORE, "API call returns: " + QSTRN(data)) apiFailedCounter++; return 0; } diff --git a/src/core/kernel/KernelInteractions.cpp b/src/core/kernel/KernelInteractions.cpp index cf1aef8f..68d19a3c 100644 --- a/src/core/kernel/KernelInteractions.cpp +++ b/src/core/kernel/KernelInteractions.cpp @@ -12,14 +12,14 @@ namespace Qv2ray::core::kernel QFile coreFile(vCorePath); if (!coreFile.exists()) { - DEBUG(VCORE, "V2ray core file cannot be found.") + DEBUG(MODULE_VCORE, "V2ray core file cannot be found.") *message = tr("V2ray core executable not found."); return false; } // Use open() here to prevent `executing` a folder, which may have the same name as the V2ray core. if (!coreFile.open(QFile::ReadOnly)) { - DEBUG(VCORE, "V2ray core file cannot be opened, possibly be a folder?") + DEBUG(MODULE_VCORE, "V2ray core file cannot be opened, possibly be a folder?") *message = tr("V2ray core file cannot be opened, please ensure there's a file instead of a folder."); return false; } @@ -33,19 +33,19 @@ namespace Qv2ray::core::kernel bool hasGeoSite = FileExistsIn(QDir(vAssetsPath), "geosite.dat"); if (!hasGeoIP && !hasGeoSite) { - DEBUG(VCORE, "V2ray assets path contains none of those two files.") + DEBUG(MODULE_VCORE, "V2ray assets path contains none of those two files.") *message = tr("V2ray assets path is not valid."); return false; } if (!hasGeoIP) { - DEBUG(VCORE, "No geoip.dat in assets path, aborting.") + DEBUG(MODULE_VCORE, "No geoip.dat in assets path, aborting.") *message = tr("No geoip.dat in assets path."); return false; } if (!hasGeoSite) { - DEBUG(VCORE, "No geosite.dat in assets path, aborting.") + DEBUG(MODULE_VCORE, "No geosite.dat in assets path, aborting.") *message = tr("No geosite.dat in assets path."); return false; } @@ -66,13 +66,13 @@ namespace Qv2ray::core::kernel auto exitCode = proc.exitCode(); if (exitCode != 0) { - DEBUG(VCORE, "VCore failed with an exit code: " + QSTRN(exitCode)) + DEBUG(MODULE_VCORE, "VCore failed with an exit code: " + QSTRN(exitCode)) *message = tr("V2ray core failed with an exit code: ") + QSTRN(exitCode); return false; } QString output = proc.readAllStandardOutput(); - LOG(VCORE, "V2ray output: " + SplitLines(output).join(";")) + LOG(MODULE_VCORE, "V2ray output: " + SplitLines(output).join(";")) if (SplitLines(output).isEmpty()) { *message = tr("V2ray core returns empty string."); @@ -89,14 +89,14 @@ namespace Qv2ray::core::kernel QString v2rayCheckResult; if (ValidateKernel(GlobalConfig.v2CorePath, GlobalConfig.v2AssetsPath, &v2rayCheckResult)) { - DEBUG(VCORE, "V2ray version: " + v2rayCheckResult) + DEBUG(MODULE_VCORE, "V2ray version: " + v2rayCheckResult) // Append assets location env. QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert("V2RAY_LOCATION_ASSET", GlobalConfig.v2AssetsPath); // QProcess process; process.setProcessEnvironment(env); - DEBUG(VCORE, "Starting V2ray core with test options") + DEBUG(MODULE_VCORE, "Starting V2ray core with test options") process.start(GlobalConfig.v2CorePath, QStringList() << "-test" << "-config" << path, QIODevice::ReadWrite | QIODevice::Text); process.waitForFinished(); @@ -105,7 +105,7 @@ namespace Qv2ray::core::kernel QvMessageBoxWarn(nullptr, tr("Configuration Error"), output.mid(output.indexOf("anti-censorship.") + 17)); return false; } else { - DEBUG(VCORE, "Config file check passed.") + DEBUG(MODULE_VCORE, "Config file check passed.") return true; } } else { @@ -123,11 +123,11 @@ namespace Qv2ray::core::kernel emit onProcessOutputReadyRead(vProcess->readAllStandardOutput().trimmed()); }); connect(vProcess, &QProcess::stateChanged, [this](QProcess::ProcessState state) { - DEBUG(VCORE, "V2ray kernel process status changed: " + QVariant::fromValue(state).toString()) + DEBUG(MODULE_VCORE, "V2ray kernel process status changed: " + QVariant::fromValue(state).toString()) // If V2ray crashed AFTER we start it. if (KernelStarted && state == QProcess::NotRunning) { - LOG(VCORE, "V2ray kernel crashed.") + LOG(MODULE_VCORE, "V2ray kernel crashed.") StopConnection(); emit onProcessErrored(); } @@ -140,7 +140,7 @@ namespace Qv2ray::core::kernel bool V2rayKernelInstance::StartConnection(CONFIGROOT root) { if (KernelStarted) { - LOG(VCORE, "Status is invalid, expect STOPPED when calling StartConnection") + LOG(MODULE_VCORE, "Status is invalid, expect STOPPED when calling StartConnection") return false; } @@ -157,7 +157,7 @@ namespace Qv2ray::core::kernel vProcess->setProcessEnvironment(env); vProcess->start(GlobalConfig.v2CorePath, QStringList() << "-config" << filePath, QIODevice::ReadWrite | QIODevice::Text); vProcess->waitForStarted(); - DEBUG(VCORE, "V2ray core started.") + DEBUG(MODULE_VCORE, "V2ray core started.") KernelStarted = true; QStringList inboundTags; @@ -172,20 +172,20 @@ namespace Qv2ray::core::kernel inboundTags.append(tag); } - DEBUG(VCORE, "Found inbound tags: " + inboundTags.join(";")) + DEBUG(MODULE_VCORE, "Found inbound tags: " + inboundTags.join(";")) apiEnabled = false; // if (StartupOption.noAPI) { - LOG(VCORE, "API has been disabled by the command line argument \"-noAPI\"") + LOG(MODULE_VCORE, "API has been disabled by the command line argument \"-noAPI\"") } else if (!GlobalConfig.apiConfig.enableAPI) { - LOG(VCORE, "API has been disabled by the global config option") + LOG(MODULE_VCORE, "API has been disabled by the global config option") } else if (inboundTags.isEmpty()) { - LOG(VCORE, "API is disabled since no inbound tags configured. This is probably caused by a bad complex config.") + LOG(MODULE_VCORE, "API is disabled since no inbound tags configured. This is probably caused by a bad complex config.") } else { apiWorker->StartAPI(inboundTags); apiEnabled = true; - DEBUG(VCORE, "Qv2ray API started") + DEBUG(MODULE_VCORE, "Qv2ray API started") } return true; diff --git a/src/main.cpp b/src/main.cpp index 3f61cf54..40fc86a2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -42,8 +42,8 @@ bool verifyConfigAvaliability(QString path, bool checkExistingConfig) bool opened = testFile.open(QFile::OpenModeFlag::ReadWrite); if (!opened) { - LOG(SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.") - LOG(INIT, "---> Cannot create a new file or openwrite a file.") + LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.") + LOG(MODULE_INIT, "---> Cannot create a new file or openwrite a file.") return false; } else { testFile.write("Qv2ray test file, feel free to remove."); @@ -53,8 +53,8 @@ bool verifyConfigAvaliability(QString path, bool checkExistingConfig) if (!removed) { // This is rare, as we can create a file but failed to remove it. - LOG(SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.") - LOG(INIT, "---> Cannot remove a file.") + LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.") + LOG(MODULE_INIT, "---> Cannot remove a file.") return false; } } @@ -79,21 +79,21 @@ bool verifyConfigAvaliability(QString path, bool checkExistingConfig) auto err = VerifyJsonString(StringFromFile(&configFile)); if (!err.isEmpty()) { - LOG(INIT, "Json parse returns: " + err) + LOG(MODULE_INIT, "Json parse returns: " + err) return false; } else { // If the file format is valid. auto conf = JsonFromString(StringFromFile(&configFile)); - LOG(SETTINGS, "Path: " + path + " contains a config file, in version " + conf["config_version"].toVariant().toString()) + LOG(MODULE_SETTINGS, "Path: " + path + " contains a config file, in version " + conf["config_version"].toVariant().toString()) configFile.close(); return true; } } else { - LOG(SETTINGS, "File: " + configFile.fileName() + " cannot be opened!") + LOG(MODULE_SETTINGS, "File: " + configFile.fileName() + " cannot be opened!") return false; } } catch (...) { - LOG(SETTINGS, "Exception raised when checking config: " + configFile.fileName()) + LOG(MODULE_SETTINGS, "Exception raised when checking config: " + configFile.fileName()) //LOG(INIT, e->what()) QvMessageBoxWarn(nullptr, QObject::tr("Warning"), QObject::tr("Qv2ray cannot load the config file from here:") + NEWLINE + configFile.fileName()); return false; @@ -103,7 +103,7 @@ bool verifyConfigAvaliability(QString path, bool checkExistingConfig) bool initialiseQv2ray() { - LOG(INIT, "Application exec path: " + QApplication::applicationDirPath()) + LOG(MODULE_INIT, "Application exec path: " + QApplication::applicationDirPath()) const QString currentPathConfig = QApplication::applicationDirPath() + "/config" QV2RAY_CONFIG_DIR_SUFFIX; const QString configQv2ray = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/qv2ray" QV2RAY_CONFIG_DIR_SUFFIX; const QString homeQv2ray = QDir::homePath() + "/.qv2ray" QV2RAY_CONFIG_DIR_SUFFIX; @@ -132,11 +132,11 @@ bool initialiseQv2ray() if (hasExistingConfig) break; if (isValidConfigPath) { - DEBUG(INIT, "Path: " + path + " is valid.") + DEBUG(MODULE_INIT, "Path: " + path + " is valid.") configPath = path; hasExistingConfig = true; } else { - LOG(INIT, "Path: " + path + " does not contain a valid config file.") + LOG(MODULE_INIT, "Path: " + path + " does not contain a valid config file.") } } @@ -144,7 +144,7 @@ bool initialiseQv2ray() if (hasExistingConfig) { // Use the config path found by the checks above SetConfigDirPath(configPath); - LOG(INIT, "Using " + QV2RAY_CONFIG_DIR + " as the config path.") + LOG(MODULE_INIT, "Using " + QV2RAY_CONFIG_DIR + " as the config path.") } else { // // Create new config at these dirs, these are default values for each platform. @@ -158,7 +158,7 @@ bool initialiseQv2ray() // Check if the dirs are write-able if (mkpathResult && verifyConfigAvaliability(configPath, false)) { // Found a valid config dir, with write permission, but assume no config is located in it. - LOG(INIT, "Set " + configPath + " as the config path.") + LOG(MODULE_INIT, "Set " + configPath + " as the config path.") SetConfigDirPath(configPath); if (QFile::exists(QV2RAY_CONFIG_FILE)) { @@ -168,7 +168,7 @@ bool initialiseQv2ray() // It usually means that QV2RAY_CONFIG_FILE here is corrupted, in JSON format. // Otherwise Qv2ray would have loaded this config already instead of notifying to // create a new config in this folder. - LOG(INIT, "This should not occur: Qv2ray config exists but failed to load.") + LOG(MODULE_INIT, "This should not occur: Qv2ray config exists but failed to load.") QvMessageBoxWarn(nullptr, QObject::tr("Failed to initialise Qv2ray"), QObject::tr("Failed to determine the location of config file.") + NEWLINE + QObject::tr("Qv2ray will now exit.") + NEWLINE + @@ -183,12 +183,12 @@ bool initialiseQv2ray() // // Save initial config. SaveGlobalConfig(conf); - LOG(INIT, "Created initial config file.") + LOG(MODULE_INIT, "Created initial config file.") } else { // None of the path above can be used as a dir for storing config. // Even the last folder failed to pass the check. - LOG(INIT, "FATAL") - LOG(INIT, " ---> CANNOT find a proper place to store Qv2ray config files.") + LOG(MODULE_INIT, "FATAL") + LOG(MODULE_INIT, " ---> CANNOT find a proper place to store Qv2ray config files.") QString searchPath = configFilePaths.join(NEWLINE); QvMessageBoxWarn(nullptr, QObject::tr("Cannot Start Qv2ray"), QObject::tr("Cannot find a place to store config files.") + NEWLINE + @@ -202,7 +202,7 @@ bool initialiseQv2ray() if (!QDir(QV2RAY_GENERATED_DIR).exists()) { // The dir used to generate final config file, for V2ray interaction. QDir().mkdir(QV2RAY_GENERATED_DIR); - LOG(INIT, "Created config generation dir at: " + QV2RAY_GENERATED_DIR) + LOG(MODULE_INIT, "Created config generation dir at: " + QV2RAY_GENERATED_DIR) } return true; @@ -263,7 +263,7 @@ int main(int argc, char *argv[]) // finished: command line parsing LOG("QV2RAY_BUILD_INFO", QV2RAY_BUILD_INFO) LOG("QV2RAY_BUILD_EXTRA_INFO", QV2RAY_BUILD_EXTRA_INFO) - LOG(INIT, "Qv2ray " QV2RAY_VERSION_STRING " running on " + QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture() + NEWLINE) + LOG(MODULE_INIT, "Qv2ray " QV2RAY_VERSION_STRING " running on " + QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture() + NEWLINE) // // This line must be called before any other ones, since we are using these values to identify instances. SingleApplication::setApplicationName("Qv2ray"); @@ -286,7 +286,7 @@ int main(int argc, char *argv[]) // // Do not install en-US as it's the default language. bool _result_ = _qApp.installTranslator(Qv2rayTranslator.get()); - LOG(UI, "Installing a tranlator from OS: " + _lang + " -- " + (_result_ ? "OK" : "Failed")) + LOG(MODULE_UI, "Installing a tranlator from OS: " + _lang + " -- " + (_result_ ? "OK" : "Failed")) // LOG("LICENCE", NEWLINE "This program comes with ABSOLUTELY NO WARRANTY." NEWLINE "This is free software, and you are welcome to redistribute it" NEWLINE @@ -307,7 +307,7 @@ int main(int argc, char *argv[]) "Copyright (c) 2015-2020 qBittorrent (Anton Lashkov) (@qBittorrent): speedplotview (GPLv2)" NEWLINE NEWLINE) // - LOG(INIT, "Qv2ray Start Time: " + QSTRN(QTime::currentTime().msecsSinceStartOfDay())) + LOG(MODULE_INIT, "Qv2ray Start Time: " + QSTRN(QTime::currentTime().msecsSinceStartOfDay())) // #ifdef QT_DEBUG cout << "WARNING: ============================== This is a debug build, many features are not stable enough. ==============================" << endl; @@ -317,11 +317,11 @@ int main(int argc, char *argv[]) auto langs = GetFileList(QDir(":/translations")); if (langs.empty()) { - LOG(INIT, "FAILED to find any translations. THIS IS A BUILD ERROR.") + LOG(MODULE_INIT, "FAILED to find any translations. THIS IS A BUILD ERROR.") QvMessageBoxWarn(nullptr, QObject::tr("Cannot load languages"), QObject::tr("Qv2ray will continue running, but you cannot change the UI language.")); } else { for (auto lang : langs) { - LOG(INIT, "Found Translator: " + lang) + LOG(MODULE_INIT, "Found Translator: " + lang) } } @@ -354,18 +354,18 @@ int main(int argc, char *argv[]) auto confObject = StructFromJsonString(JsonToString(conf)); // Remove system translator, for loading custom translations. qApp->removeTranslator(Qv2rayTranslator.get()); - LOG(INIT, "Removed system translations") + LOG(MODULE_INIT, "Removed system translations") if (confObject.uiConfig.language.isEmpty()) { // Prevent empty. - LOG(UI, "Setting default UI language to en-US") + LOG(MODULE_UI, "Setting default UI language to en-US") confObject.uiConfig.language = "en-US"; } Qv2rayTranslator = std::move(QvTranslator(confObject.uiConfig.language).pTranslator); if (qApp->installTranslator(Qv2rayTranslator.get())) { - LOG(INIT, "Successfully installed a translator for " + confObject.uiConfig.language) + LOG(MODULE_INIT, "Successfully installed a translator for " + confObject.uiConfig.language) } else { // Do not translate these..... // If a translator fails to load, pop up a message. @@ -381,11 +381,11 @@ int main(int argc, char *argv[]) // Check OpenSSL version for auto-update and subscriptions auto osslReqVersion = QSslSocket::sslLibraryBuildVersionString(); auto osslCurVersion = QSslSocket::sslLibraryVersionString(); - LOG(NETWORK, "Current OpenSSL version: " + osslCurVersion) + LOG(MODULE_NETWORK, "Current OpenSSL version: " + osslCurVersion) if (!QSslSocket::supportsSsl()) { - LOG(NETWORK, "Required OpenSSL version: " + osslReqVersion) - LOG(NETWORK, "OpenSSL library MISSING, Quitting.") + LOG(MODULE_NETWORK, "Required OpenSSL version: " + osslReqVersion) + LOG(MODULE_NETWORK, "OpenSSL library MISSING, Quitting.") QvMessageBoxWarn(nullptr, QObject::tr("Dependency Missing"), QObject::tr("Cannot find openssl libs") + NEWLINE + QObject::tr("This could be caused by a missing of `openssl` package in your system.") + NEWLINE + @@ -443,7 +443,7 @@ int main(int argc, char *argv[]) if (themes.contains(confObject.uiConfig.theme)) { _qApp.setStyle(confObject.uiConfig.theme); - LOG(INIT + " " + UI, "Setting Qv2ray UI themes: " + confObject.uiConfig.theme) + LOG(MODULE_INIT + " " + MODULE_UI, "Setting Qv2ray UI themes: " + confObject.uiConfig.theme) } #endif @@ -465,7 +465,7 @@ int main(int argc, char *argv[]) // Will not block. QGuiApplication::setFallbackSessionManagementEnabled(false); QObject::connect(&_qApp, &QGuiApplication::commitDataRequest, []() { - LOG(INIT, "Quit triggered by session manager.") + LOG(MODULE_INIT, "Quit triggered by session manager.") }); #ifndef Q_OS_WIN signal(SIGUSR1, [](int) { @@ -476,7 +476,7 @@ int main(int argc, char *argv[]) }); #endif auto rcode = _qApp.exec(); - LOG(INIT, "Quitting normally") + LOG(MODULE_INIT, "Quitting normally") return rcode; #ifndef QT_DEBUG } catch (...) { diff --git a/src/ui/editors/w_InboundEditor.cpp b/src/ui/editors/w_InboundEditor.cpp index 8d4f1f06..6c111031 100644 --- a/src/ui/editors/w_InboundEditor.cpp +++ b/src/ui/editors/w_InboundEditor.cpp @@ -27,11 +27,11 @@ InboundEditor::InboundEditor(INBOUND root, QWidget *parent) : mtSettings = root["settings"].toObject(); } else { if (!root["protocol"].toString().isEmpty()) { - LOG(UI, "Unsupported inbound type: " + inboundType) + LOG(MODULE_UI, "Unsupported inbound type: " + inboundType) QvMessageBoxWarn(this, tr("Inbound type not supported"), tr("The inbound type is not supported by Qv2ray (yet). Please use JsonEditor to change the settings") + "\r\n" + tr("Inbound: ") + inboundType); } else { - LOG(UI, "Creating new inbound config") + LOG(MODULE_UI, "Creating new inbound config") root["protocol"] = inboundType = "http"; } } @@ -201,7 +201,7 @@ void InboundEditor::on_httpRemoveUserBtn_clicked() if (entry == item->text().trimmed()) { list.removeAt(i); httpSettings["accounts"] = list; - LOG(UI, "Removed http inbound user " + entry) + LOG(MODULE_UI, "Removed http inbound user " + entry) httpAccountListBox->takeItem(httpAccountListBox->currentRow()); } } @@ -254,7 +254,7 @@ void InboundEditor::on_socksRemoveUserBtn_clicked() if (entry == item->text().trimmed()) { list.removeAt(i); socksSettings["accounts"] = list; - LOG(UI, "Removed http inbound user " + entry) + LOG(MODULE_UI, "Removed http inbound user " + entry) socksAccountListBox->takeItem(socksAccountListBox->currentRow()); return; } diff --git a/src/ui/editors/w_JsonEditor.cpp b/src/ui/editors/w_JsonEditor.cpp index 15c1869a..41544c82 100644 --- a/src/ui/editors/w_JsonEditor.cpp +++ b/src/ui/editors/w_JsonEditor.cpp @@ -12,7 +12,7 @@ JsonEditor::JsonEditor(QJsonObject rootObject, QWidget *parent) : QString jsonString = JsonToString(rootObject); if (VerifyJsonString(jsonString).isEmpty()) { - LOG(UI, "Begin loading Json Model") + LOG(MODULE_UI, "Begin loading Json Model") jsonTree->setModel(&model); model.loadJson(QJsonDocument(rootObject).toJson()); } else { diff --git a/src/ui/editors/w_OutboundEditor.cpp b/src/ui/editors/w_OutboundEditor.cpp index fd7b8162..cf44102c 100644 --- a/src/ui/editors/w_OutboundEditor.cpp +++ b/src/ui/editors/w_OutboundEditor.cpp @@ -113,13 +113,13 @@ OUTBOUND OutboundEditor::GenerateConnectionJson() settings.insert("vnext", vnext); } else if (OutboundType == "shadowsocks") { streaming = QJsonObject(); - LOG(CONNECTION, "Shadowsocks outbound does not need StreamSettings.") + LOG(MODULE_CONNECTION, "Shadowsocks outbound does not need StreamSettings.") QJsonArray servers; servers.append(GetRootObject(shadowsocks)); settings["servers"] = servers; } else if (OutboundType == "socks") { streaming = QJsonObject(); - LOG(CONNECTION, "Socks outbound does not need StreamSettings.") + LOG(MODULE_CONNECTION, "Socks outbound does not need StreamSettings.") QJsonArray servers; servers.append(GetRootObject(socks)); settings["servers"] = servers; diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index b2bf8b2f..bd8a6f22 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -29,7 +29,7 @@ static bool isLoading = false; #define GetFirstNodeData(node, nodeModel, dataModel) (static_cast(static_cast((node).nodeDataModel())->outData(0).get())) #define CHECKEMPTYRULES if (this->rules.isEmpty()) { \ - LOG(UI, "No rules currently, we add one.") \ + LOG(MODULE_UI, "No rules currently, we add one.") \ AddNewRule(); \ } @@ -143,7 +143,7 @@ void RouteEditor::onNodeClicked(Node &n) if (isRule) { // It's a rule object currentRuleTag = GetFirstNodeData(n, QvRuleNodeDataModel, RuleNodeData)->GetRuleTag(); - DEBUG(GRAPH, "Selecting rule: " + currentRuleTag) + DEBUG(MODULE_GRAPH, "Selecting rule: " + currentRuleTag) ShowCurrentRuleDetail(); toolBox->setCurrentIndex(1); } else if (isOut || isIn) { @@ -171,7 +171,7 @@ void RouteEditor::onNodeClicked(Node &n) portLabel->setNum(port); hostLabel->setText(host); } else { - LOG(GRAPH, "Selected an unknown node, RARE.") + LOG(MODULE_GRAPH, "Selected an unknown node, RARE.") } } @@ -190,7 +190,7 @@ void RouteEditor::onConnectionCreated(QtNodes::Connection const &c) // It's a inbound-rule connection onNodeClicked(*sourceNode); onNodeClicked(*targetNode); - LOG(GRAPH, "Inbound-rule new connection.") + LOG(MODULE_GRAPH, "Inbound-rule new connection.") // Get all connected inbounds to this rule node. // QStringList has an helper to let us remove duplicates, see below. QStringList _inbounds; @@ -219,10 +219,10 @@ void RouteEditor::onConnectionCreated(QtNodes::Connection const &c) CurrentRule.QV2RAY_RULE_USE_BALANCER = false; // Update balancer settings. ShowCurrentRuleDetail(); - LOG(GRAPH, "Updated outbound: " + CurrentRule.outboundTag) + LOG(MODULE_GRAPH, "Updated outbound: " + CurrentRule.outboundTag) } else { // It's an impossible connection - LOG(GRAPH, "Unrecognized connection, RARE.") + LOG(MODULE_GRAPH, "Unrecognized connection, RARE.") } } @@ -242,7 +242,7 @@ void RouteEditor::onConnectionDeleted(QtNodes::Connection const &c) onNodeClicked(*target); currentRuleTag = GetFirstNodeData(*target, QvRuleNodeDataModel, RuleNodeData)->GetRuleTag(); auto _inboundTag = GetFirstNodeData(*source, QvInboundNodeModel, InboundNodeData)->GetInbound(); - LOG(UI, "Removing inbound: " + _inboundTag + " from rule: " + currentRuleTag) + LOG(MODULE_UI, "Removing inbound: " + _inboundTag + " from rule: " + currentRuleTag) CurrentRule.inboundTag.removeAll(_inboundTag); } else if (ruleNodes.values().contains(source) && outboundNodes.values().contains(target)) { // It's a rule-outbound connection @@ -255,10 +255,10 @@ void RouteEditor::onConnectionDeleted(QtNodes::Connection const &c) CurrentRule.outboundTag.clear(); } - LOG(GRAPH, "Removing an outbound: " + _outboundTag) + LOG(MODULE_GRAPH, "Removing an outbound: " + _outboundTag) } else { // It's an impossible connection - LOG(GRAPH, "Selected an unknown node, RARE.") + LOG(MODULE_GRAPH, "Selected an unknown node, RARE.") } } @@ -288,7 +288,7 @@ CONFIGROOT RouteEditor::OpenEditor() // Find balancer list if (!balancers.contains(_rule.balancerTag)) { - LOG(UI, "Cannot find a balancer for tag: " + _rule.balancerTag) + LOG(MODULE_UI, "Cannot find a balancer for tag: " + _rule.balancerTag) } else { auto _balancerList = balancers[_rule.balancerTag]; QJsonObject balancerEntry; @@ -331,7 +331,7 @@ CONFIGROOT RouteEditor::OpenEditor() continue; if (getTag(x) == defaultOutbound) { - LOG(CONNECTION, "Pushing default outbound to the front.") + LOG(MODULE_CONNECTION, "Pushing default outbound to the front.") // Put the default outbound to the first. _outbounds.push_front(x.raw()); } else { @@ -363,13 +363,13 @@ void RouteEditor::ShowCurrentRuleDetail() LOADINGCHECK if (currentRuleTag.isEmpty()) { - LOG(UI, "WARNING, trying to access a non-exist rule entry. return.") + LOG(MODULE_UI, "WARNING, trying to access a non-exist rule entry. return.") return; } if (!rules.contains(currentRuleTag)) { QvMessageBoxWarn(this, tr("Show rule details"), tr("A rule cannot be found: ") + currentRuleTag); - LOG(UI, "WARNING, trying to access a non-exist rule entry. return.") + LOG(MODULE_UI, "WARNING, trying to access a non-exist rule entry. return.") return; } @@ -570,15 +570,15 @@ void RouteEditor::on_enableBalancerCB_stateChanged(int arg1) balancersWidget->setEnabled(useBalancer); if (CurrentRule.balancerTag.isEmpty()) { - LOG(UI, "Creating a new balancer tag.") + LOG(MODULE_UI, "Creating a new balancer tag.") CurrentRule.balancerTag = GenerateRandomString(6); balancers[CurrentRule.balancerTag] = QStringList(); } - DEBUG(UI, "Balancer: " + CurrentRule.balancerTag) + DEBUG(MODULE_UI, "Balancer: " + CurrentRule.balancerTag) if (useBalancer) { - LOG(UI, "A rule has been set to use balancer, disconnect it to any outbound.") + LOG(MODULE_UI, "A rule has been set to use balancer, disconnect it to any outbound.") auto ruleNode = ruleNodes[currentRuleTag]; for (auto conn : Qv2ray::common::Values(nodeScene->connections())) { @@ -723,7 +723,7 @@ void RouteEditor::on_delBtn_clicked() //currentRuleTag = rules.firstKey(); //ShowCurrentRuleDetail(); } else { - LOG(UI, "Unknown node selected.") + LOG(MODULE_UI, "Unknown node selected.") QvMessageBoxWarn(this, tr("Error"), tr("Qv2ray entered an unknown state.")); } } @@ -773,9 +773,9 @@ void RouteEditor::on_editBtn_clicked() RenameItemTag(RENAME_INBOUND, getTag(_in), getTag(_result)); } - DEBUG(UI, "Removed old tag: " + getTag(_in)) + DEBUG(MODULE_UI, "Removed old tag: " + getTag(_in)) inbounds.remove(getTag(_in)); - DEBUG(UI, "Adding new tag: " + getTag(_result)) + DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result)) inbounds[getTag(_result)] = _result; } } else if (isOutbound) { @@ -810,18 +810,18 @@ void RouteEditor::on_editBtn_clicked() bool isTagChanged = getTag(_out) != getTag(_result); if (isTagChanged) { - DEBUG(UI, "Outbound tag is changed: " + QString(isTagChanged)) + DEBUG(MODULE_UI, "Outbound tag is changed: " + QString(isTagChanged)) RenameItemTag(RENAME_OUTBOUND, getTag(_out), getTag(_result)); - DEBUG(UI, "Removed old tag: " + getTag(_out)) + DEBUG(MODULE_UI, "Removed old tag: " + getTag(_out)) outbounds.remove(getTag(_out)); } - DEBUG(UI, "Adding new tag: " + getTag(_result)) + DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result)) outbounds[getTag(_result)] = _result; statusLabel->setText(tr("OK")); } } else { - LOG(UI, "Cannot apply 'edit' operation to non-inbound and non-outbound") + LOG(MODULE_UI, "Cannot apply 'edit' operation to non-inbound and non-outbound") } } @@ -842,13 +842,13 @@ void RouteEditor::on_ruleRenameBtn_clicked() auto newTag = ruleTagLineEdit->text(); if (newTag.isEmpty()) { - LOG(UI, "Tag is empty, this is ILLEGAL!") + LOG(MODULE_UI, "Tag is empty, this is ILLEGAL!") QvMessageBoxWarn(this, tr("Renaming a tag"), tr("New tag is empty, please try another.")); } else if (newTag == CurrentRule.QV2RAY_RULE_TAG) { - LOG(UI, "No tag changed, returning.") + LOG(MODULE_UI, "No tag changed, returning.") QvMessageBoxInfo(this, tr("Renaming a tag"), tr("New tag is the same as the original one.")); } else if (rules.contains(newTag)) { - LOG(UI, "Tag duplicate detected.") + LOG(MODULE_UI, "Tag duplicate detected.") QvMessageBoxWarn(this, tr("Renaming a tag"), tr("Duplicate rule tag detected, please try another.")); } else { RenameItemTag(RENAME_RULE, CurrentRule.QV2RAY_RULE_TAG, newTag); diff --git a/src/ui/editors/w_RoutesEditor_extra.cpp b/src/ui/editors/w_RoutesEditor_extra.cpp index 2def4fd6..87e8baa6 100644 --- a/src/ui/editors/w_RoutesEditor_extra.cpp +++ b/src/ui/editors/w_RoutesEditor_extra.cpp @@ -78,7 +78,7 @@ void RouteEditor::AddRule(RuleObject rule) for (auto inTag : rule.inboundTag) { if (!inboundNodes.contains(inTag)) { - LOG(UI, "No inbound tag found for rule: " + rule.QV2RAY_RULE_TAG + ", inbound tag: " + inTag) + LOG(MODULE_UI, "No inbound tag found for rule: " + rule.QV2RAY_RULE_TAG + ", inbound tag: " + inTag) QvMessageBoxWarn(this, tr("No Inbound"), tr("No inbound item found: ") + inTag); rule.inboundTag.removeAll(inTag); } else { @@ -90,10 +90,10 @@ void RouteEditor::AddRule(RuleObject rule) // If not using balancers (use outbound tag) if (!rule.QV2RAY_RULE_USE_BALANCER) { if (outboundNodes.contains(rule.outboundTag)) { - DEBUG(GRAPH, "Found outbound tag: " + rule.outboundTag + ", for rule: " + rule.QV2RAY_RULE_TAG) + DEBUG(MODULE_GRAPH, "Found outbound tag: " + rule.outboundTag + ", for rule: " + rule.QV2RAY_RULE_TAG) nodeScene->createConnection(*outboundNodes[rule.outboundTag], 0, node, 0); } else { - LOG(GRAPH, "Outbound tag not found: " + rule.outboundTag + ", for: " + rule.QV2RAY_RULE_TAG) + LOG(MODULE_GRAPH, "Outbound tag not found: " + rule.outboundTag + ", for: " + rule.QV2RAY_RULE_TAG) //QvMessageBoxWarn(this, tr("No outbound tag"), tr("Please connect the rule with an outbound.")); } } @@ -116,7 +116,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, auto node = static_cast(ruleNodes[originalTag]->nodeDataModel()); if (node == nullptr) { - LOG(GRAPH, "EMPTY NODE WARN") + LOG(MODULE_GRAPH, "EMPTY NODE WARN") } node->setData(newTag); @@ -129,7 +129,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, auto items = ruleListWidget->findItems(originalTag, Qt::MatchExactly); if (items.isEmpty()) { - LOG(UI, "Cannot find a node: " + originalTag) + LOG(MODULE_UI, "Cannot find a node: " + originalTag) } else { items.first()->setText(newTag); } @@ -138,7 +138,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, currentRuleTag = newTag; } } else { - LOG(UI, "There's nothing match " + originalTag + " in the containers.") + LOG(MODULE_UI, "There's nothing match " + originalTag + " in the containers.") } break; @@ -155,7 +155,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, auto node = static_cast(outboundNodes[newTag]->nodeDataModel()); if (node == nullptr) { - LOG(GRAPH, "EMPTY NODE WARN") + LOG(MODULE_GRAPH, "EMPTY NODE WARN") } node->setData(newTag); @@ -174,7 +174,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, // Resolve default outbound. ResolveDefaultOutboundTag(originalTag, newTag); } else { - LOG(UI, "Failed to rename an outbound --> Item not found.") + LOG(MODULE_UI, "Failed to rename an outbound --> Item not found.") } break; @@ -191,7 +191,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, auto node = static_cast(inboundNodes[newTag]->nodeDataModel()); if (node == nullptr) { - LOG(GRAPH, "EMPTY NODE WARN") + LOG(MODULE_GRAPH, "EMPTY NODE WARN") } node->setData(newTag); @@ -210,7 +210,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, } } } else { - LOG(UI, "Failed to rename an outbound --> Item not found.") + LOG(MODULE_UI, "Failed to rename an outbound --> Item not found.") } break; @@ -219,17 +219,17 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, void RouteEditor::ResolveDefaultOutboundTag(QString original, QString newTag) { - LOG(UI, "Resolving default outbound settings: default=" + defaultOutbound + " original=" + original + " new=" + newTag) + LOG(MODULE_UI, "Resolving default outbound settings: default=" + defaultOutbound + " original=" + original + " new=" + newTag) auto isDefaultChanged = original == defaultOutbound; defaultOutboundCombo->clear(); defaultOutboundCombo->addItems(outbounds.keys()); if (!isDefaultChanged) { - LOG(UI, "Default outbound is not changed: retaining: " + defaultOutbound) + LOG(MODULE_UI, "Default outbound is not changed: retaining: " + defaultOutbound) // Just simply restore the default one. defaultOutboundCombo->setCurrentText(defaultOutbound); } else if (newTag.isEmpty()) { - LOG(UI, "Default outbound is removed, using first key from the outbounds as the default one.") + LOG(MODULE_UI, "Default outbound is removed, using first key from the outbounds as the default one.") // Removed the default one, so set the first one as the default. if (outbounds.isEmpty()) { @@ -239,7 +239,7 @@ void RouteEditor::ResolveDefaultOutboundTag(QString original, QString newTag) defaultOutboundCombo->addItem(outbounds.firstKey()); } } else { - LOG(UI, "Default outbound is renamed, ") + LOG(MODULE_UI, "Default outbound is renamed, ") defaultOutboundCombo->setCurrentText(newTag); defaultOutbound = newTag; } diff --git a/src/ui/messaging/QvMessageBus.cpp b/src/ui/messaging/QvMessageBus.cpp index 9b6249ba..6c56e13a 100644 --- a/src/ui/messaging/QvMessageBus.cpp +++ b/src/ui/messaging/QvMessageBus.cpp @@ -13,13 +13,13 @@ namespace Qv2ray::ui::messaging void QvMessageBusObject::on_QvMessageReceived(QvMessage msg) { QMetaEnum metaEnum = QMetaEnum::fromType(); - DEBUG(MESSAGING, "Signal recieved: " + QString(metaEnum.valueToKey(msg))); + DEBUG(MODULE_MESSAGING, "Signal recieved: " + QString(metaEnum.valueToKey(msg))); } void QvMessageBusObject::EmitGlobalSignal(QvMessage msg) { QMetaEnum metaEnum = QMetaEnum::fromType(); - LOG(MESSAGING, "Emitting signal: " + QString(metaEnum.valueToKey(msg))); + LOG(MODULE_MESSAGING, "Emitting signal: " + QString(metaEnum.valueToKey(msg))); emit QvSendMessage(msg); } } diff --git a/src/ui/models/NodeModelsBase.hpp b/src/ui/models/NodeModelsBase.hpp index d5f92d86..36d3336b 100644 --- a/src/ui/models/NodeModelsBase.hpp +++ b/src/ui/models/NodeModelsBase.hpp @@ -31,7 +31,7 @@ namespace Qv2ray::ui::nodemodels public: InboundNodeData() { - DEBUG(GRAPH, "DANGER: Initialising a data model without value.") + DEBUG(MODULE_GRAPH, "DANGER: Initialising a data model without value.") } InboundNodeData(QString in) : _inboundTag(in) { } @@ -55,7 +55,7 @@ namespace Qv2ray::ui::nodemodels public: OutboundNodeData() : _outboundTag() { - DEBUG(GRAPH, "DANGER: Initialising a data model without value.") + DEBUG(MODULE_GRAPH, "DANGER: Initialising a data model without value.") } OutboundNodeData(QString out) : _outboundTag(out) { } @@ -79,7 +79,7 @@ namespace Qv2ray::ui::nodemodels public: RuleNodeData() : _ruleTag() { - DEBUG(GRAPH, "DANGER: Initialising a data model without value.") + DEBUG(MODULE_GRAPH, "DANGER: Initialising a data model without value.") } RuleNodeData(QString out) : _ruleTag(out) { } diff --git a/src/ui/w_ExportConfig.cpp b/src/ui/w_ExportConfig.cpp index cb81bb91..e7a9f9d6 100644 --- a/src/ui/w_ExportConfig.cpp +++ b/src/ui/w_ExportConfig.cpp @@ -75,7 +75,7 @@ void ConfigExporter::on_saveBtn_clicked() auto filePath = QFileDialog().getSaveFileName(this, tr("Save Image"), "", "Images (*.png)"); auto result = image.save(filePath); QDesktopServices::openUrl(QUrl::fromUserInput(filePath)); - LOG(FILEIO, "Saving an image to: " + filePath + " result: " + (result ? "OK" : "Failed")) + LOG(MODULE_FILEIO, "Saving an image to: " + filePath + " result: " + (result ? "OK" : "Failed")) } void ConfigExporter::on_copyImageBtn_clicked() diff --git a/src/ui/w_ImportConfig.cpp b/src/ui/w_ImportConfig.cpp index 642385f4..4e36489b 100644 --- a/src/ui/w_ImportConfig.cpp +++ b/src/ui/w_ImportConfig.cpp @@ -84,7 +84,7 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() //auto str = QZXing().decodeImage(pix); if (str.trimmed().isEmpty()) { - LOG(UI, "Cannot decode QR Code from an image, size: h=" + QSTRN(pix.width()) + ", v=" + QSTRN(pix.height())) + LOG(MODULE_UI, "Cannot decode QR Code from an image, size: h=" + QSTRN(pix.width()) + ", v=" + QSTRN(pix.height())) QvMessageBoxWarn(this, tr("Capture QRCode"), tr("Cannot find a valid QRCode from this region.")); } else { vmessConnectionStringTxt->appendPlainText(str.trimmed() + NEWLINE); @@ -124,7 +124,7 @@ void ImportConfigWindow::on_beginImportBtn_clicked() vmessConnectionStringTxt->clear(); errorsList->clear(); // - LOG(IMPORT, QSTRN(linkList.count()) + " string found in vmess box.") + LOG(MODULE_IMPORT, QSTRN(linkList.count()) + " string found in vmess box.") while (!linkList.isEmpty()) { aliasPrefix = nameTxt->text(); @@ -217,12 +217,12 @@ void ImportConfigWindow::on_editFileBtn_clicked() auto jsonCheckingError = VerifyJsonString(jsonString); if (!jsonCheckingError.isEmpty()) { - LOG(FILEIO, "Currupted JSON file detected") + LOG(MODULE_FILEIO, "Currupted JSON file detected") if (QvMessageBoxAsk(this, tr("Edit file as JSON"), tr("The file you selected has json syntax error. Continue editing may make you lose data. Would you like to continue?") + NEWLINE + jsonCheckingError) != QMessageBox::Yes) { return; } else { - LOG(FILEIO, "Continue editing curruped json file, data loss is expected.") + LOG(MODULE_FILEIO, "Continue editing curruped json file, data loss is expected.") } } @@ -238,7 +238,7 @@ void ImportConfigWindow::on_editFileBtn_clicked() QvMessageBoxWarn(this, tr("Edit file as JSON"), tr("Failed to save file, please check if you have proper permissions")); } } else { - LOG(FILEIO, "Canceled saving a file.") + LOG(MODULE_FILEIO, "Canceled saving a file.") } } diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index edf96087..03626716 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -234,7 +234,7 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr requestHelper->get("https://api.github.com/repos/Qv2ray/Qv2ray/releases/latest"); if (StartupOption.enableToolbarPlguin) { - LOG(UI, "Plugin daemon is enabled.") + LOG(MODULE_UI, "Plugin daemon is enabled.") StartProcessingPlugins(); } @@ -304,12 +304,12 @@ void MainWindow::VersionUpdate(QByteArray &data) QVersionNumber newVersion = QVersionNumber::fromString(root["tag_name"].toString("v").remove(0, 1)); QVersionNumber currentVersion = QVersionNumber::fromString(QString(QV2RAY_VERSION_STRING).remove(0, 1)); QVersionNumber ignoredVersion = QVersionNumber::fromString(GlobalConfig.ignoredVersion); - LOG(UPDATE, "Received update info, Latest: " + newVersion.toString() + " Current: " + currentVersion.toString() + " Ignored: " + ignoredVersion.toString()) + LOG(MODULE_UPDATE, "Received update info, Latest: " + newVersion.toString() + " Current: " + currentVersion.toString() + " Ignored: " + ignoredVersion.toString()) // If the version is newer than us. // And new version is newer than the ignored version. if (newVersion > currentVersion && newVersion > ignoredVersion) { - LOG(UPDATE, "New version detected.") + LOG(MODULE_UPDATE, "New version detected.") auto link = root["html_url"].toString(""); auto result = QvMessageBoxAsk(this, tr("Update"), tr("Found a new version: ") + root["tag_name"].toString("") + @@ -332,13 +332,35 @@ void MainWindow::VersionUpdate(QByteArray &data) void MainWindow::OnConfigListChanged(bool need_restart) { - LOG(UI, "Loading data...") - auto conns = connectionHandler->Connections(); + LOG(MODULE_UI, "Loading data...") + auto groups = connectionHandler->Groups(); - for (auto conn : conns) { - auto item = new QTreeWidgetItem(); - connectionListWidget->addTopLevelItem(item); - connectionListWidget->setItemWidget(item, 0, new ConnectionWidget(conn, connectionListWidget)); + for (auto group : groups) { + auto groupItem = new QTreeWidgetItem(); + connectionListWidget->addTopLevelItem(groupItem); + connectionListWidget->setItemWidget(groupItem, 0, new ConnectionWidget(group, connectionListWidget)); + auto connections = connectionHandler->Connections(group); + + for (auto connection : connections) { + auto connectionItem = new QTreeWidgetItem(); + groupItem->addChild(connectionItem); + connectionListWidget->setItemWidget(connectionItem, 0, new ConnectionWidget(connection, connectionListWidget)); + } + } + + auto subscriptions = connectionHandler->Subscriptions(); + + for (auto subscription : subscriptions) { + auto subscriptionItem = new QTreeWidgetItem(); + connectionListWidget->addTopLevelItem(subscriptionItem); + connectionListWidget->setItemWidget(subscriptionItem, 0, new ConnectionWidget(subscription, connectionListWidget)); + auto connections = connectionHandler->Connections(subscription); + + for (auto connection : connections) { + auto connectionItem = new QTreeWidgetItem(); + subscriptionItem->addChild(connectionItem); + connectionListWidget->setItemWidget(connectionItem, 0, new ConnectionWidget(connection, connectionListWidget)); + } } //auto wasRunning = vinstance->KernelStarted && need_restart; diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 4b51a6b8..cd601f8a 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -6,8 +6,8 @@ 0 0 - 740 - 590 + 928 + 640 @@ -38,7 +38,7 @@ 530 - + @@ -143,9 +143,6 @@ QAbstractItemView::ScrollPerPixel - - true - true @@ -277,341 +274,345 @@ - - - Config Details - - - - - - - - Config Type - - - - - - - IBeamCursor - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Protocol - - - - - - - IBeamCursor - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Address - - - - - - - IBeamCursor - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Port Number - - - - - - - IBeamCursor - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Latency - - - - - - - IBeamCursor - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - - - Operations - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Edit connection as JSON - - - Edit JSON - - - - 22 - 22 - - - - - - - - true - - - Ping Test - - - - 22 - 22 - - - - - - - - Share - - - - 22 - 22 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - Log (click to switch log source) - - - - - - - Speed Graph - - - - - - - - - - - - - + - - - + + + Config Details + + + + + + + + Config Type + + + + + + + IBeamCursor + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Protocol + + + + + + + IBeamCursor + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Address + + + + + + + IBeamCursor + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Port Number + + + + + + + IBeamCursor + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Latency + + + + + + + IBeamCursor + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + Operations + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Edit connection as JSON + + + Edit JSON + + + + 22 + 22 + + + + + + + + true + + + Ping Test + + + + 22 + 22 + + + + + + + + Share + + + + 22 + 22 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + - Speed + Log (click to switch log source) - - - - - 32 - 32 - - - - - 25 - 25 - - - - - - - - - 8 - - + + - 0.00 B/s -0.00 B/s + Speed Graph - - - - Qt::Horizontal - - - - 40 - 20 - - - + + + + + - + - - - - 0 - 0 - - - - - 0 - 0 - - - - Data - - + + + + + Speed + + + + + + + + 32 + 32 + + + + + 25 + 25 + + + + + + + + + 8 + + + + 0.00 B/s +0.00 B/s + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - - - 32 - 32 - - - - - 25 - 25 - - - - - - - - - 8 - - - - 0.00 B + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Data + + + + + + + + 32 + 32 + + + + + 25 + 25 + + + + + + + + + 8 + + + + 0.00 B 0.00 B - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index 3610dc04..42489640 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -63,7 +63,7 @@ void MainWindow::MWFindAndStartAutoConfig() void MainWindow::MWClearSystemProxy(bool showMessage) { ClearSystemProxy(); - LOG(UI, "Clearing System Proxy") + LOG(MODULE_UI, "Clearing System Proxy") systemProxyEnabled = false; if (showMessage) { @@ -84,7 +84,7 @@ void MainWindow::MWSetSystemProxy() if (!isComplex) { // Is simple config and we will try to set system proxy. - LOG(UI, "Preparing to set system proxy") + LOG(MODULE_UI, "Preparing to set system proxy") // QString proxyAddress; bool canSetSystemProxy = true; @@ -92,13 +92,13 @@ void MainWindow::MWSetSystemProxy() if (usePAC) { if ((httpEnabled && !pacUseSocks) || (socksEnabled && pacUseSocks)) { // If we use PAC and socks/http are properly configured for PAC - LOG(PROXY, "System proxy uses PAC") + LOG(MODULE_PROXY, "System proxy uses PAC") proxyAddress = "http://" + GlobalConfig.inboundConfig.listenip + ":" + QSTRN(GlobalConfig.inboundConfig.pacConfig.port) + "/pac"; } else { // Not properly configured - LOG(PROXY, "Failed to process pac due to following reasons:") - LOG(PROXY, " --> PAC is configured to use socks but socks is not enabled.") - LOG(PROXY, " --> PAC is configuted to use http but http is not enabled.") + LOG(MODULE_PROXY, "Failed to process pac due to following reasons:") + LOG(MODULE_PROXY, " --> PAC is configured to use socks but socks is not enabled.") + LOG(MODULE_PROXY, " --> PAC is configuted to use http but http is not enabled.") QvMessageBoxWarn(this, tr("PAC Processing Failed"), tr("HTTP or SOCKS inbound is not properly configured for PAC") + NEWLINE + tr("Qv2ray will continue, but will not set system proxy.")); canSetSystemProxy = false; @@ -107,18 +107,18 @@ void MainWindow::MWSetSystemProxy() // Not using PAC if (httpEnabled || socksEnabled) { // Not use PAC, System proxy should use HTTP or SOCKS - LOG(PROXY, "Setting up system proxy.") + LOG(MODULE_PROXY, "Setting up system proxy.") // A 'proxy host' should be a host WITHOUT `http://` uri scheme proxyAddress = "localhost"; } else { - LOG(PROXY, "Neither of HTTP nor SOCKS is enabled, cannot set system proxy.") + LOG(MODULE_PROXY, "Neither of HTTP nor SOCKS is enabled, cannot set system proxy.") QvMessageBoxWarn(this, tr("Cannot set system proxy"), tr("Both HTTP and SOCKS inbounds are not enabled")); canSetSystemProxy = false; } } if (canSetSystemProxy) { - LOG(UI, "Setting system proxy for simple config.") + LOG(MODULE_UI, "Setting system proxy for simple config.") auto httpPort = GlobalConfig.inboundConfig.useHTTP ? GlobalConfig.inboundConfig.http_port : 0; auto socksPort = GlobalConfig.inboundConfig.useSocks ? GlobalConfig.inboundConfig.socks_port : 0; // @@ -234,13 +234,13 @@ void MainWindow::CheckSubscriptionsUpdate() // auto lastRenewDate = QDateTime::fromTime_t(subs.lastUpdated); auto renewTime = lastRenewDate.addSecs(subs.updateInterval * 86400); - LOG(SUBSCRIPTION, "Subscription \"" + key + "\": " + NEWLINE + + LOG(MODULE_SUBSCRIPTION, "Subscription \"" + key + "\": " + NEWLINE + " --> Last renewal time: " + lastRenewDate.toString() + NEWLINE + " --> Renew interval: " + QSTRN(subs.updateInterval) + NEWLINE + " --> Ideal renew time: " + renewTime.toString()) if (renewTime <= QDateTime::currentDateTime()) { - LOG(SUBSCRIPTION, "Subscription: " + key + " needs to be updated.") + LOG(MODULE_SUBSCRIPTION, "Subscription: " + key + " needs to be updated.") updateList.append(key); } } diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index 5af4d939..54edbf48 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -244,7 +244,7 @@ void PreferencesWindow::on_buttonBox_accepted() // Install translator if (!qApp->installTranslator(Qv2rayTranslator.get())) { - LOG(UI, "Failed to translate UI to: " + CurrentConfig.uiConfig.language) + LOG(MODULE_UI, "Failed to translate UI to: " + CurrentConfig.uiConfig.language) } else { messageBus.EmitGlobalSignal(QvMessage::RETRANSLATE); QApplication::processEvents(); @@ -421,48 +421,48 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) tr("If anything goes wrong after enabling this, please check issue #57 or the link below:") + NEWLINE + " https://github.com/Qv2ray/Qv2ray/wiki/FAQ ") != QMessageBox::Yes) { tProxyCheckBox->setChecked(false); - LOG(UI, "Canceled enabling tProxy feature.") + LOG(MODULE_UI, "Canceled enabling tProxy feature.") } else { - LOG(VCORE, "ENABLING tProxy Support") - LOG(FILEIO, " --> Origin V2ray core file is at: " + CurrentConfig.v2CorePath) + LOG(MODULE_VCORE, "ENABLING tProxy Support") + LOG(MODULE_FILEIO, " --> Origin V2ray core file is at: " + CurrentConfig.v2CorePath) auto v2ctlPath = QFileInfo(CurrentConfig.v2CorePath).absolutePath() + "/v2ctl"; auto newPath = QFileInfo(QV2RAY_TPROXY_VCORE_PATH).absolutePath(); QString mkPathResult = QDir().mkpath(newPath) ? "OK" : "FAILED"; - LOG(FILEIO, " --> mkPath result: " + mkPathResult) + LOG(MODULE_FILEIO, " --> mkPath result: " + mkPathResult) // - LOG(FILEIO, " --> Origin v2ctl file is at: " + v2ctlPath) - LOG(FILEIO, " --> New V2ray files will be placed in: " + newPath) + LOG(MODULE_FILEIO, " --> Origin v2ctl file is at: " + v2ctlPath) + LOG(MODULE_FILEIO, " --> New V2ray files will be placed in: " + newPath) // - LOG(FILEIO, " --> Copying files....") + LOG(MODULE_FILEIO, " --> Copying files....") if (QFileInfo(CurrentConfig.v2CorePath).absoluteFilePath() != QFileInfo(QV2RAY_TPROXY_VCORE_PATH).absoluteFilePath()) { // Only trying to remove file when they are not in the default dir. // (In other words...) Keep using the current files. // if (QFile(QV2RAY_TPROXY_VCORE_PATH).exists()) { - LOG(FILEIO, QString(QV2RAY_TPROXY_VCORE_PATH) + ": File already exists.") - LOG(FILEIO, QString(QV2RAY_TPROXY_VCORE_PATH) + ": Deleting file.") + LOG(MODULE_FILEIO, QString(QV2RAY_TPROXY_VCORE_PATH) + ": File already exists.") + LOG(MODULE_FILEIO, QString(QV2RAY_TPROXY_VCORE_PATH) + ": Deleting file.") QFile(QV2RAY_TPROXY_VCORE_PATH).remove(); } if (QFile(QV2RAY_TPROXY_VCTL_PATH).exists()) { - LOG(FILEIO, QV2RAY_TPROXY_VCTL_PATH + ": File already exists.") - LOG(FILEIO, QV2RAY_TPROXY_VCTL_PATH + ": Deleting file.") + LOG(MODULE_FILEIO, QV2RAY_TPROXY_VCTL_PATH + ": File already exists.") + LOG(MODULE_FILEIO, QV2RAY_TPROXY_VCTL_PATH + ": Deleting file.") QFile(QV2RAY_TPROXY_VCTL_PATH).remove(); } QString vCoreresult = QFile(CurrentConfig.v2CorePath).copy(QV2RAY_TPROXY_VCORE_PATH) ? "OK" : "FAILED"; - LOG(FILEIO, " --> V2ray Core: " + vCoreresult) + LOG(MODULE_FILEIO, " --> V2ray Core: " + vCoreresult) // QString vCtlresult = QFile(v2ctlPath).copy(QV2RAY_TPROXY_VCTL_PATH) ? "OK" : "FAILED"; - LOG(FILEIO, " --> V2ray Ctl: " + vCtlresult) + LOG(MODULE_FILEIO, " --> V2ray Ctl: " + vCtlresult) // if (vCoreresult == "OK" && vCtlresult == "OK") { - LOG(VCORE, " --> Done copying files.") + LOG(MODULE_VCORE, " --> Done copying files.") on_vCorePathTxt_textEdited(QV2RAY_TPROXY_VCORE_PATH); } else { - LOG(VCORE, "FAILED to copy V2ray files. Aborting.") + LOG(MODULE_VCORE, "FAILED to copy V2ray files. Aborting.") QvMessageBoxWarn(this, tr("Enable tProxy Support"), tr("Qv2ray cannot copy one or both V2ray files from: ") + NEWLINE + NEWLINE + CurrentConfig.v2CorePath + NEWLINE + v2ctlPath + NEWLINE + NEWLINE + @@ -470,15 +470,15 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) return; } } else { - LOG(VCORE, "Skipped removing files since the current V2ray core is in the default path.") - LOG(VCORE, " --> Actually because we don't know where else to obtain the files.") + LOG(MODULE_VCORE, "Skipped removing files since the current V2ray core is in the default path.") + LOG(MODULE_VCORE, " --> Actually because we don't know where else to obtain the files.") } - LOG(UI, "Calling pkexec and setcap...") + LOG(MODULE_UI, "Calling pkexec and setcap...") int ret = QProcess::execute("pkexec setcap CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip " + CurrentConfig.v2CorePath); if (ret != 0) { - LOG(UI, "WARN: setcap exits with code: " + QSTRN(ret)) + LOG(MODULE_UI, "WARN: setcap exits with code: " + QSTRN(ret)) QvMessageBoxWarn(this, tr("Preferences"), tr("Failed to setcap onto V2ray executable. You may need to run `setcap` manually.")); } @@ -489,7 +489,7 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) int ret = QProcess::execute("pkexec setcap -r " + CurrentConfig.v2CorePath); if (ret != 0) { - LOG(UI, "WARN: setcap exits with code: " + QSTRN(ret)) + LOG(MODULE_UI, "WARN: setcap exits with code: " + QSTRN(ret)) QvMessageBoxWarn(this, tr("Preferences"), tr("Failed to setcap onto V2ray executable. You may need to run `setcap` manually.")); } @@ -566,7 +566,7 @@ void PreferencesWindow::on_nsBarPageAddBTN_clicked() CurrentBarLineId = 0; nsBarPagesList->addItem(QSTRN(CurrentBarPageId)); ShowLineParameters(CurrentBarLine); - LOG(UI, "Adding new page Id: " + QSTRN(CurrentBarPageId)) + LOG(MODULE_UI, "Adding new page Id: " + QSTRN(CurrentBarPageId)) nsBarPageDelBTN->setEnabled(true); nsBarLineAddBTN->setEnabled(true); nsBarLineDelBTN->setEnabled(true); @@ -609,7 +609,7 @@ void PreferencesWindow::on_nsBarLineAddBTN_clicked() nsBarLinesList->addItem(QSTRN(CurrentBarLineId)); ShowLineParameters(CurrentBarLine); nsBarLineDelBTN->setEnabled(true); - LOG(UI, "Adding new line Id: " + QSTRN(CurrentBarLineId)) + LOG(MODULE_UI, "Adding new line Id: " + QSTRN(CurrentBarLineId)) nsBarLinesList->setCurrentRow(static_cast(CurrentBarPage.Lines.size() - 1)); } @@ -839,7 +839,7 @@ void PreferencesWindow::on_pacGoBtn_clicked() pacGoBtn->setEnabled(false); gfwListCB->setEnabled(false); QvHttpRequestHelper request; - LOG(PROXY, "Downloading GFWList file.") + LOG(MODULE_PROXY, "Downloading GFWList file.") bool withProxy = getGFWListWithProxyCB->isChecked(); switch (gfwListCB->currentIndex()) { @@ -885,7 +885,7 @@ void PreferencesWindow::on_pacGoBtn_clicked() break; } - LOG(NETWORK, "Fetched: " + gfwLocation) + LOG(MODULE_NETWORK, "Fetched: " + gfwLocation) QvMessageBoxInfo(this, tr("Download GFWList"), tr("Successfully downloaded GFWList.")); pacGoBtn->setEnabled(true); gfwListCB->setEnabled(true); diff --git a/src/ui/w_ScreenShot_Core.cpp b/src/ui/w_ScreenShot_Core.cpp index 87676891..598562ca 100644 --- a/src/ui/w_ScreenShot_Core.cpp +++ b/src/ui/w_ScreenShot_Core.cpp @@ -29,7 +29,7 @@ ScreenShotWindow::ScreenShotWindow() : QDialog(), rubber(new QRubberBand(QRubber QImage ScreenShotWindow::DoScreenShot() { - LOG(IMPORT, "We currently only support the current screen.") + LOG(MODULE_IMPORT, "We currently only support the current screen.") // The msleep is the only solution which prevent capturing our windows again. // It works on KDE, https://www.qtcentre.org/threads/55708-Get-Desktop-Screenshot-Without-Application-Window-Being-Shown?p=248993#post248993 QThread::msleep(100); diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 0ef41afc..8244f037 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -69,7 +69,7 @@ void SubscribeEditor::on_updateButton_clicked() if (currentSubName != newName) { // Rename needed. - LOG(SUBSCRIPTION, "Renaming a subscription, from " + currentSubName + " to: " + newName) + LOG(MODULE_SUBSCRIPTION, "Renaming a subscription, from " + currentSubName + " to: " + newName) bool canGo = true; if (newName.isEmpty() || !IsValidFileName(newName)) { @@ -114,7 +114,7 @@ void SubscribeEditor::on_updateButton_clicked() subscriptions[currentSubName].updateInterval = newUpdateInterval; if (subscriptions[currentSubName].address != newAddress) { - LOG(SUBSCRIPTION, "Setting new address, from " + subscriptions[currentSubName].address + " to: " + newAddress) + LOG(MODULE_SUBSCRIPTION, "Setting new address, from " + subscriptions[currentSubName].address + " to: " + newAddress) subscriptions[currentSubName].address = newAddress; } @@ -143,7 +143,7 @@ void SubscribeEditor::StartUpdateSubscription(const QString &subscriptionName) auto config = ConvertConfigFromString(vmess.trimmed(), &_alias, &errMessage); if (!errMessage.isEmpty()) { - LOG(SUBSCRIPTION, "Processing a subscription with following error: " + errMessage) + LOG(MODULE_SUBSCRIPTION, "Processing a subscription with following error: " + errMessage) } else { SaveSubscriptionConfig(config, subscriptionName, &_alias); connectionsList->addItem(_alias); @@ -154,7 +154,7 @@ void SubscribeEditor::StartUpdateSubscription(const QString &subscriptionName) lastUpdatedLabel->setText(timeToString(subscriptions[subscriptionName].lastUpdated)); isUpdateInProgress = false; } else { - LOG(NETWORK, "We have received an empty string from the URL.") + LOG(MODULE_NETWORK, "We have received an empty string from the URL.") QvMessageBoxWarn(this, tr("Updating subscriptions"), tr("Failed to process the result from the upstream, please check your Url.")); } @@ -194,7 +194,7 @@ void SubscribeEditor::on_subscriptionList_currentRowChanged(int currentRow) } currentSubName = subscriptionList->currentItem()->text(); - LOG(UI, "Subscription row changed, new name: " + currentSubName) + LOG(MODULE_UI, "Subscription row changed, new name: " + currentSubName) // subNameTxt->setText(currentSubName); subAddrTxt->setText(subscriptions[currentSubName].address); diff --git a/src/ui/widgets/ConnectionWidget.cpp b/src/ui/widgets/ConnectionWidget.cpp index 8e30be60..9dc833cb 100644 --- a/src/ui/widgets/ConnectionWidget.cpp +++ b/src/ui/widgets/ConnectionWidget.cpp @@ -1,22 +1,6 @@ #include "ConnectionWidget.hpp" #include "QMessageBox" -ConnectionWidget::ConnectionWidget(const ConnectionId &id, QWidget *parent): QWidget(parent), - _id(id), connection(connectionHandler->GetConnection(id)) -{ - setupUi(this); - connNameLabel->setText(connection.displayName); - latencyLabel->setText(tr("Latency: ") + QSTRN(connection.latency) + " " + tr("ms")); -} - ConnectionWidget::~ConnectionWidget() { } - -void ConnectionWidget::on_editBtn_clicked() -{ -} - -void ConnectionWidget::on_latencyBtn_clicked() -{ -} diff --git a/src/ui/widgets/ConnectionWidget.hpp b/src/ui/widgets/ConnectionWidget.hpp index cd6f8d81..8cf54ac3 100644 --- a/src/ui/widgets/ConnectionWidget.hpp +++ b/src/ui/widgets/ConnectionWidget.hpp @@ -4,20 +4,58 @@ #include "ui_ConnectionWidget.h" #include "core/handler/ConnectionHandler.hpp" +enum CONNECTION_ITEM_TYPE { + CONNECTION, + GROUP, + SUBSCRIPTION +}; + class ConnectionWidget : public QWidget, private Ui::ConnectionWidget { Q_OBJECT - public: - explicit ConnectionWidget(const ConnectionId &id, QWidget *parent = nullptr); + CONNECTION_ITEM_TYPE type; + explicit ConnectionWidget(const ConnectionId &id, QWidget *parent = nullptr): ConnectionWidget(parent) + { + type = CONNECTION; + connectionId = id; + // + auto connection = connectionHandler->GetConnection(id); + connNameLabel->setText(connection.displayName); + latencyLabel->setText(tr("Latency: ") + QSTRN(connection.latency) + " " + tr("ms")); + } + explicit ConnectionWidget(const GroupId &id, QWidget *parent = nullptr) : ConnectionWidget(parent) + { + type = GROUP; + groupId = id; + InitialiseForGroups(connectionHandler->GetGroup(id).displayName, connectionHandler->Connections(id).count()); + } + explicit ConnectionWidget(const SubscriptionId &id, QWidget *parent = nullptr) : ConnectionWidget(parent) + { + type = SUBSCRIPTION; + subscriptionId = id; + InitialiseForGroups(connectionHandler->GetSubscription(id).displayName, connectionHandler->Connections(id).count()); + } ~ConnectionWidget(); - - private slots: - void on_editBtn_clicked(); - - void on_latencyBtn_clicked(); + Q_DISABLE_COPY_MOVE(ConnectionWidget) private: - const ConnectionId _id; - const QvConnectionObject &connection; + ConnectionWidget(QWidget *parent = nullptr) : QWidget(parent), connectionId("null"), groupId("null"), subscriptionId("null") + { + setupUi(this); + } + void InitialiseForGroups(const QString &displayName, int connectionCount) + { + connNameLabel->setText(tr("Group: ") + displayName); + latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections"))); + // + layout()->removeWidget(connTypeLabel); + delete connTypeLabel; + layout()->removeWidget(dataLabel); + delete dataLabel; + } + // + ConnectionId connectionId; + GroupId groupId; + SubscriptionId subscriptionId; }; diff --git a/src/ui/widgets/ConnectionWidget.ui b/src/ui/widgets/ConnectionWidget.ui index 23690e81..97972f05 100644 --- a/src/ui/widgets/ConnectionWidget.ui +++ b/src/ui/widgets/ConnectionWidget.ui @@ -6,16 +6,16 @@ 0 0 - 474 + 283 84 Form - - - + + + @@ -29,53 +29,35 @@ - + - Type: vmess + tls + ws + Latency: 500ms - - - - - - - 8 - - - - 0KB/0KB + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - + + - Latency: 0ms - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Type: vmess + tls + ws - - - - - - Edit - - - - - - - Ping - - - - + + + + + 8 + + + + 0KB / 0KB + + From 0750e20a3bd54beb4e0bcc86bf8626241f0e5058 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 16 Feb 2020 21:30:26 +0800 Subject: [PATCH 010/332] wip: add: added some ui features --- src/base/models/QvConfigIdentifier.hpp | 5 +- src/main.cpp | 3 +- src/ui/w_MainWindow.cpp | 23 +- src/ui/w_MainWindow.ui | 829 ++++++++++++++++--------- src/ui/widgets/ConnectionWidget.cpp | 1 + src/ui/widgets/ConnectionWidget.hpp | 2 +- src/ui/widgets/ConnectionWidget.ui | 2 +- 7 files changed, 542 insertions(+), 323 deletions(-) diff --git a/src/base/models/QvConfigIdentifier.hpp b/src/base/models/QvConfigIdentifier.hpp index 2bb09fe9..0d3fb75f 100644 --- a/src/base/models/QvConfigIdentifier.hpp +++ b/src/base/models/QvConfigIdentifier.hpp @@ -28,10 +28,11 @@ namespace Qv2ray::base struct QvConnectionObject { QString displayName; int64_t importDate; + int64_t lastConnected; int64_t latency; int64_t upLinkData; int64_t downLinkData; - QvConnectionObject(): displayName(), importDate(system_clock::to_time_t(system_clock::now())), latency(0), upLinkData(0), downLinkData(0) { } - XTOSTRUCT(O(displayName, importDate, latency, upLinkData, downLinkData)) + QvConnectionObject(): displayName(), importDate(system_clock::to_time_t(system_clock::now())), lastConnected(), latency(0), upLinkData(0), downLinkData(0) { } + XTOSTRUCT(O(displayName, importDate, lastConnected, latency, upLinkData, downLinkData)) }; } diff --git a/src/main.cpp b/src/main.cpp index 40fc86a2..30961d7d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -447,6 +447,7 @@ int main(int argc, char *argv[]) } #endif + //_qApp.setAttribute(Qt::AA_DontUseNativeMenuBar); // Initialise Connection Handler InitialiseConnectionHandler(); // Show MainWindow @@ -455,7 +456,7 @@ int main(int argc, char *argv[]) try { #endif - QObject::connect(&_qApp, &SingleApplication::instanceStarted, [&w]() { + QObject::connect(&_qApp, &SingleApplication::instanceStarted, [&]() { // When a second instance is connected, show the mainwindow. w.show(); w.raise(); diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 03626716..30830c07 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -255,18 +255,17 @@ void MainWindow::SetEditWidgetEnable(bool enabled) void MainWindow::mouseReleaseEvent(QMouseEvent *e) { Q_UNUSED(e) - - // If mouse is on the logLabel, switch log source. - if (logLabel->underMouse()) { - //auto layout = masterLogBrowser->document()->setDocumentLayout() - currentLogBrowserId = (currentLogBrowserId + 1) % logTextBrowsers.count(); - masterLogBrowser->setDocument(currentLogBrowser->document()); - masterLogBrowser->document()->setDocumentMargin(4); - masterLogBrowser->document()->adjustSize(); - masterLogBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap); - auto bar = masterLogBrowser->verticalScrollBar(); - bar->setValue(bar->maximum()); - } + //// If mouse is on the logLabel, switch log source. + //if (logbox->underMouse()) { + // //auto layout = masterLogBrowser->document()->setDocumentLayout() + // currentLogBrowserId = (currentLogBrowserId + 1) % logTextBrowsers.count(); + // masterLogBrowser->setDocument(currentLogBrowser->document()); + // masterLogBrowser->document()->setDocumentMargin(4); + // masterLogBrowser->document()->adjustSize(); + // masterLogBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap); + // auto bar = masterLogBrowser->verticalScrollBar(); + // bar->setValue(bar->maximum()); + //} } void MainWindow::keyPressEvent(QKeyEvent *e) diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index cd601f8a..97468a5a 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -6,8 +6,8 @@ 0 0 - 928 - 640 + 865 + 659 @@ -38,9 +38,9 @@ 530 - + - + 5 @@ -105,30 +105,10 @@ - - - - IBeamCursor - - - Stopped - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - - Host List - - - + @@ -202,22 +182,6 @@ - - - - Duplicate connection - - - Duplicate - - - - 22 - 22 - - - - @@ -240,22 +204,6 @@ - - - - Edit connection - - - Edit - - - - 22 - 22 - - - - @@ -273,15 +221,158 @@ - - + + - - - Config Details + + + + 300 + 0 + - - + + Connection Status + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Speed + + + + + + + + 32 + 32 + + + + + 25 + 25 + + + + + + + + + 85 + 0 + + + + + 8 + + + + 0.00 B/s +0.00 B/s + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Data + + + + + + + + 32 + 32 + + + + + 25 + 25 + + + + + + + + + 85 + 0 + + + + + 8 + + + + 0.00 B +0.00 B + + + + + + + + + QFrame::NoFrame + + + true + + + + + 0 + 0 + 504 + 759 + + + + + 0 + + + + + Config Details + @@ -363,263 +454,272 @@ - - - - Latency - - - - - - - IBeamCursor - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - - Operations - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Edit connection as JSON - - - Edit JSON - - - - 22 - 22 - - - - - - - - true - - - Ping Test - - - - 22 - 22 - - - - - - - - Share - - - - 22 - 22 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - + + + + + + + 12 + + - Log (click to switch log source) + Operations - - + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Duplicate connection + + + Duplicate + + + + 22 + 22 + + + + + + + + Edit connection + + + Edit + + + + 22 + 22 + + + + + + + + Edit connection as JSON + + + Edit JSON + + + + 22 + 22 + + + + + + + + true + + + Ping Test + + + + 22 + 22 + + + + + + + + Share + + + + 22 + 22 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 12 + + Speed Graph - - - - - - - - - - - - - - - Speed - - - - - - - - 32 - 32 - - - - - 25 - 25 - - - - - - - - - 8 - - - - 0.00 B/s -0.00 B/s - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + + 0 + 250 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Data - - - - - - - - 32 - 32 - - - - - 25 - 25 - - - - - - - - - 8 - - - - 0.00 B -0.00 B - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + + 12 + + + + Log + + + + + + + + 0 + 250 + + + - - + + + + + + 0 + 0 + 865 + 22 + + + + + File + + + + Import Connection + + + + + + + + + + + + Export Connection + + + + + + + + + + + + + + + Subscriptions + + + + Update Subscriptions + + + + + + + + + + + + Tools + + + + + + + + Help + + + + + + + + + + + + + #ManuallyCreateConnection @@ -655,6 +755,126 @@ #Restart + + + Import from vmess:// + + + + + Import from QRCode File + + + + + Import from ScreenShot + + + + + Open Configuration Folder + + + + + Exit + + + + + From File + + + + + From Connection Link + + + + + From QRCode File + + + + + Take ScreenShot + + + + + Open Connection Editor + + + + + Manually Create Connection + + + + + Manually Create Complex Connection + + + + + Copy Connection Link + + + + + Copy QRCode + + + + + Save QRCode to File + + + + + Open Subscription Manager + + + + + Update All Subscriptions + + + + + Update All Subscriptions with System Proxy + + + + + Options + + + + + About Qt + + + + + About Qv2ray + + + + + Help + + + + + Save Qv2ray Log + + + + + Json Editor + + @@ -666,13 +886,10 @@ preferencesBtn connectionListWidget importConfigButton - duplicateBtn removeConfigButton - editConfigButton editJsonBtn pingTestBtn shareBtn - masterLogBrowser diff --git a/src/ui/widgets/ConnectionWidget.cpp b/src/ui/widgets/ConnectionWidget.cpp index 9dc833cb..ac74b3b8 100644 --- a/src/ui/widgets/ConnectionWidget.cpp +++ b/src/ui/widgets/ConnectionWidget.cpp @@ -3,4 +3,5 @@ ConnectionWidget::~ConnectionWidget() { + // } diff --git a/src/ui/widgets/ConnectionWidget.hpp b/src/ui/widgets/ConnectionWidget.hpp index 8cf54ac3..e02cffe6 100644 --- a/src/ui/widgets/ConnectionWidget.hpp +++ b/src/ui/widgets/ConnectionWidget.hpp @@ -46,7 +46,7 @@ class ConnectionWidget : public QWidget, private Ui::ConnectionWidget } void InitialiseForGroups(const QString &displayName, int connectionCount) { - connNameLabel->setText(tr("Group: ") + displayName); + connNameLabel->setText(displayName); latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections"))); // layout()->removeWidget(connTypeLabel); diff --git a/src/ui/widgets/ConnectionWidget.ui b/src/ui/widgets/ConnectionWidget.ui index 97972f05..069c0f59 100644 --- a/src/ui/widgets/ConnectionWidget.ui +++ b/src/ui/widgets/ConnectionWidget.ui @@ -20,7 +20,7 @@ - 13 + 12 From 17e302fd96e72b5dc805be965ead4609605c59dd Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 16 Feb 2020 22:45:15 +0800 Subject: [PATCH 011/332] wip: add: added some pre-connection checks --- Qv2ray.pro | 1 + src/core/CoreSafeTypes.hpp | 43 +++++++++++ src/core/connection/ConnectionIO.hpp | 20 ++--- src/core/handler/ConnectionHandler.cpp | 49 ++++++++++--- src/core/handler/ConnectionHandler.hpp | 62 ++++------------ src/core/handler/V2rayInstanceHandler.cpp | 56 ++++++++++++++ src/main.cpp | 4 +- src/ui/w_MainWindow.cpp | 89 ++++++----------------- src/ui/w_MainWindow.hpp | 8 +- src/ui/w_MainWindow_extra.cpp | 57 --------------- src/ui/widgets/ConnectionWidget.cpp | 6 -- src/ui/widgets/ConnectionWidget.hpp | 77 +++++++++++++++----- 12 files changed, 249 insertions(+), 223 deletions(-) create mode 100644 src/core/CoreSafeTypes.hpp diff --git a/Qv2ray.pro b/Qv2ray.pro index 174456fb..6bf108f6 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -90,6 +90,7 @@ Qv2rayAddSource(core, handler, ConnectionHandler, cpp, hpp) Qv2rayAddSource(core, handler, SubscriptionHandler, cpp) Qv2rayAddSource(core, handler, V2rayInstanceHandler, cpp, hpp) Qv2rayAddSource(core, _, CoreUtils, cpp, hpp) +Qv2rayAddSource(core, _, CoreSafeTypes, hpp) Qv2rayAddSource(ui, editors, w_InboundEditor, cpp, hpp, ui) Qv2rayAddSource(ui, editors, w_JsonEditor, cpp, hpp, ui) Qv2rayAddSource(ui, editors, w_OutboundEditor, cpp, hpp, ui) diff --git a/src/core/CoreSafeTypes.hpp b/src/core/CoreSafeTypes.hpp new file mode 100644 index 00000000..2ce6329b --- /dev/null +++ b/src/core/CoreSafeTypes.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include + +namespace Qv2ray::core +{ + template + class IDType + { + public: + IDType(const QString &id): m_id(id) {} + friend bool operator==(const IDType &lhs, const IDType &rhs) + { + return lhs.m_id == rhs.m_id; + } + const QString &toString() const + { + return m_id; + } + uint qHash(uint seed) const + { + return ::qHash(m_id, seed); + } + private: + QString m_id; + }; + + template uint qHash(const IDType &key, uint seed = 0) + { + return key.qHash(seed); + } + // + class __QvGroup; + class __QvConnection; + class __QvSubscription; + typedef IDType<__QvGroup> GroupId; + typedef IDType<__QvConnection> ConnectionId; + typedef IDType<__QvSubscription> SubscriptionId; +} + +using namespace Qv2ray::core; diff --git a/src/core/connection/ConnectionIO.hpp b/src/core/connection/ConnectionIO.hpp index 8d4f7d21..5a4bade2 100644 --- a/src/core/connection/ConnectionIO.hpp +++ b/src/core/connection/ConnectionIO.hpp @@ -1,28 +1,28 @@ #include "base/Qv2rayBase.hpp" +#include "core/CoreSafeTypes.hpp" namespace Qv2ray::core::connection { namespace ConnectionIO { - QMap GetRegularConnections(QStringList connections); - QMap GetSubscriptionConnection(QString subscription); - QMap> GetSubscriptionConnections(QStringList subscriptions); + QMap GetGroupConnections(const GroupId &group); + QMap GetSubscriptionConnections(const SubscriptionId &subscription); + QMap> GetSubscriptionConnections(const QList &subscriptions); // // Save Connection Config - bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool canOverrideExisting); - bool SaveSubscriptionConfig(CONFIGROOT obj, const QString &subscription, QString *name); + bool SaveConnectionConfig(CONFIGROOT obj, const ConnectionId &id, bool canOverrideExisting); + bool SaveSubscriptionConfig(CONFIGROOT obj, const SubscriptionId &subscription, const ConnectionId &name); // - bool RemoveConnection(const QString &alias); - bool RemoveSubscriptionConnection(const QString &subsName, const QString &name); + bool RemoveConnection(const SubscriptionId &id); + bool RemoveSubscriptionConnection(const SubscriptionId &id, const ConnectionId &name); // - bool RenameConnection(const QString &originalName, const QString &newName); - bool RenameSubscription(const QString &originalName, const QString &newName); + bool RenameConnection(const ConnectionId &id, const QString &newName); + bool RenameSubscription(const SubscriptionId &id, const QString &newName); // File Protocol CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool importComplex); } } -using namespace Qv2ray::core; using namespace Qv2ray::core::connection; using namespace Qv2ray::core::connection::ConnectionIO; diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index ba77a1aa..87fe3582 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -1,4 +1,5 @@ #include "ConnectionHandler.hpp" +#include "core/connection/ConnectionIO.hpp" namespace Qv2ray::core::handlers { @@ -14,7 +15,7 @@ namespace Qv2ray::core::handlers return list; } - ConnectionHandler::ConnectionHandler() + QvConnectionHandler::QvConnectionHandler() { DEBUG(MODULE_CORE_HANDLER, "ConnectionHandler Constructor.") @@ -34,28 +35,28 @@ namespace Qv2ray::core::handlers saveTimerId = startTimer(60000); } - const QList ConnectionHandler::Groups() const + const QList QvConnectionHandler::Groups() const { return groups.keys(); } - const QList ConnectionHandler::Subscriptions() const + const QList QvConnectionHandler::Subscriptions() const { return subscriptions.keys(); } - const QList ConnectionHandler::Connections() const + const QList QvConnectionHandler::Connections() const { return connections.keys(); } - const QList ConnectionHandler::Connections(const GroupId &groupId) const + const QList QvConnectionHandler::Connections(const GroupId &groupId) const { return StringsToIdList(groups[groupId].connections); } - const QList ConnectionHandler::Connections(const SubscriptionId &subscriptionId) const + const QList QvConnectionHandler::Connections(const SubscriptionId &subscriptionId) const { return StringsToIdList(subscriptions[subscriptionId].connections); } - const QvConnectionObject &ConnectionHandler::GetConnection(const ConnectionId &id) + const QvConnectionObject &QvConnectionHandler::GetConnection(const ConnectionId &id) { if (!connections.contains(id)) { LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); @@ -64,16 +65,44 @@ namespace Qv2ray::core::handlers return connections[id]; } - const QvGroupObject &ConnectionHandler::GetGroup(const GroupId &id) + const QvGroupObject &QvConnectionHandler::GetGroup(const GroupId &id) { return groups[id]; } - const QvSubscriptionObject &ConnectionHandler::GetSubscription(const SubscriptionId &id) + const QvSubscriptionObject &QvConnectionHandler::GetSubscription(const SubscriptionId &id) { return subscriptions[id]; } - ConnectionHandler::~ConnectionHandler() + optional QvConnectionHandler::StartConnection(const SubscriptionId &group, const ConnectionId &id) + { + // + return ""; + } + optional QvConnectionHandler::StartConnection(const GroupId &group, const ConnectionId &id) + { + //if (!kernelInstance->KernelStarted) { + // // Check Selection + // if (!connections.contains(id)) { + // return tr("No connection selected!") + NEWLINE + tr("Please select a config from the list."); + // } + // + // bool startFlag = CHTryStartConnection(); + // + // if (startFlag) { + // MWTryPingConnection(name); + // speedTimerId = startTimer(1000); + // pingTimerId = startTimer(60000); + // this->hTray.showMessage("Qv2ray", tr("Connected: ") + name, this->windowIcon()); + // hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + name); + // statusLabel->setText(tr("Connected: ") + name); + // } + //} else { + // this->hTray.showMessage("Qv2ray", tr("Already connected to: ") + CurrentConnectionIdentifier.IdentifierString(), this->windowIcon()); + //} + return ""; + } + QvConnectionHandler::~QvConnectionHandler() { } } diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 675a6ebb..5de93195 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -2,61 +2,27 @@ #include "base/Qv2rayBase.hpp" #include "core/kernel/KernelInteractions.hpp" -#include -#include - -template -class IDType -{ - public: - IDType(const QString &id): m_id(id) {} - friend bool operator==(const IDType &lhs, const IDType &rhs) - { - return lhs.m_id == rhs.m_id; - } - const QString &toString() const - { - return m_id; - } - uint qHash(uint seed) const - { - return ::qHash(m_id, seed); - } - private: - QString m_id; -}; - -template uint qHash(const IDType &key, uint seed = 0) -{ - return key.qHash(seed); -} +#include "core/CoreSafeTypes.hpp" namespace Qv2ray::core::handlers { - // - class __QvGroup; - class __QvConnection; - class __QvSubscription; - typedef IDType<__QvGroup> GroupId; - typedef IDType<__QvConnection> ConnectionId; - typedef IDType<__QvSubscription> SubscriptionId; - - class ConnectionHandler : public QObject + class QvConnectionHandler : public QObject { Q_OBJECT public: - explicit ConnectionHandler(); - ~ConnectionHandler(); + explicit QvConnectionHandler(); + ~QvConnectionHandler(); // const QList Groups() const; const QList Connections() const; + const QList Subscriptions() const; const QList Connections(const GroupId &groupId) const; const QList Connections(const SubscriptionId &subscriptionId) const; - const QList Subscriptions() const; - public: // - optional StartConnection(const ConnectionId &id); + optional StartConnection(const GroupId &group, const ConnectionId &id); + optional StartConnection(const SubscriptionId &subscription, const ConnectionId &id); optional StopConnection(const ConnectionId &id); + public: // // Connection Operations. const QvConnectionObject &GetConnection(const ConnectionId &id); @@ -70,6 +36,7 @@ namespace Qv2ray::core::handlers // Misc Connection Operations optional TestLatency(const ConnectionId &id); optional TestLatency(const GroupId &id); + optional TestLatency(const SubscriptionId &id); optional TestAllLatency(); // // Group Operations @@ -110,17 +77,20 @@ namespace Qv2ray::core::handlers QHash connections; QHash subscriptions; // - QHash kernelInstances; + unique_ptr kernelInstance = make_unique(); + // We only support one cuncurrent connection currently. + //QHash kernelInstances; + // + optional _CHTryStartConnection(const ConnectionId &id); }; // - inline unique_ptr connectionHandler = nullptr; + inline unique_ptr ConnectionHandler = nullptr; // inline void InitialiseConnectionHandler() { LOG(MODULE_CORE_HANDLER, "Initializing ConnectionHandler...") - connectionHandler = make_unique(); + ConnectionHandler = make_unique(); } - // } using namespace Qv2ray::core::handlers; diff --git a/src/core/handler/V2rayInstanceHandler.cpp b/src/core/handler/V2rayInstanceHandler.cpp index e69de29b..2e91518f 100644 --- a/src/core/handler/V2rayInstanceHandler.cpp +++ b/src/core/handler/V2rayInstanceHandler.cpp @@ -0,0 +1,56 @@ +#include "ConnectionHandler.hpp" +#include "core/connection/Generation.hpp" + +optional QvConnectionHandler::_CHTryStartConnection(const ConnectionId &id) +{ + auto connection = connections[id]; + //currentFullConfig = GenerateRuntimeConfig(connection); + //bool startFlag = this->vinstance->StartConnection(currentFullConfig); + //if (startFlag) { + // bool usePAC = GlobalConfig.inboundConfig.pacConfig.enablePAC; + // bool pacUseSocks = GlobalConfig.inboundConfig.pacConfig.useSocksProxy; + // bool httpEnabled = GlobalConfig.inboundConfig.useHTTP; + // bool socksEnabled = GlobalConfig.inboundConfig.useSocks; + // + // if (usePAC) { + // bool canStartPAC = true; + // QString pacProxyString; // Something like this --> SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT; http://proxy:8080 + // auto pacIP = GlobalConfig.inboundConfig.pacConfig.localIP; + // + // if (pacIP.isEmpty()) { + // LOG(MODULE_PROXY, "PAC Local IP is empty, default to 127.0.0.1") + // pacIP = "127.0.0.1"; + // } + // + // if (pacUseSocks) { + // if (socksEnabled) { + // pacProxyString = "SOCKS5 " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.socks_port); + // } else { + // LOG(MODULE_UI, "PAC is using SOCKS, but it is not enabled") + // QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use SOCKS, but it is not enabled")); + // canStartPAC = false; + // } + // } else { + // if (httpEnabled) { + // pacProxyString = "PROXY " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.http_port); + // } else { + // LOG(MODULE_UI, "PAC is using HTTP, but it is not enabled") + // QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use HTTP, but it is not enabled")); + // canStartPAC = false; + // } + // } + // + // if (canStartPAC) { + // pacServer.SetProxyString(pacProxyString); + // pacServer.StartListen(); + // } else { + // LOG(MODULE_PROXY, "Not starting PAC due to previous error.") + // } + // } + // + // if (GlobalConfig.inboundConfig.setSystemProxy) { + // MWSetSystemProxy(); + // } + //} + return "startFlag"; +} diff --git a/src/main.cpp b/src/main.cpp index 30961d7d..21d81ec7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -407,7 +407,7 @@ int main(int argc, char *argv[]) LOG(UI, "Using built-in theme.") if (confObject.uiConfig.useDarkTheme) { - LOG(UI, " --> Using built-in dark theme.") + LOG(MODULE_UI, " --> Using built-in dark theme.") // From https://forum.qt.io/topic/101391/windows-10-dark-theme/4 _qApp.setStyle("Fusion"); QPalette darkPalette; @@ -482,7 +482,7 @@ int main(int argc, char *argv[]) #ifndef QT_DEBUG } catch (...) { QvMessageBoxWarn(nullptr, "ERROR", "There's something wrong happened and Qv2ray will quit now."); - LOG(INIT, "EXCEPTION THROWN: " __FILE__) + LOG(MODULE_INIT, "EXCEPTION THROWN: " __FILE__) return -99; } diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 30830c07..2b4ee110 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -34,9 +34,7 @@ #define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING // -#define vCoreLogBrowser this->logTextBrowsers[0] -#define qvAppLogBrowser this->logTextBrowsers[1] -#define currentLogBrowser this->logTextBrowsers[currentLogBrowserId] +#define GetItemWidget(item) (static_cast(connectionListWidget->itemWidget(item, 0))) // //#define ItemConnectionIdentifier(__item__) (__item__->data(0, Qt::UserRole).value()) // @@ -106,20 +104,7 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr setupUi(this); QvMessageBusConnect(MainWindow); // - // Two browsers - logTextBrowsers.append(new QTextBrowser()); - logTextBrowsers.append(new QTextBrowser()); - vCoreLogBrowser->setFontPointSize(8); - vCoreLogBrowser->setReadOnly(true); - vCoreLogBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap); - qvAppLogBrowser->setFontPointSize(8); - qvAppLogBrowser->setReadOnly(true); - qvAppLogBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap); - // - vCoreLogHighlighter = new SyntaxHighlighter(GlobalConfig.uiConfig.useDarkTheme, vCoreLogBrowser->document()); - qvAppLogHighlighter = new SyntaxHighlighter(GlobalConfig.uiConfig.useDarkTheme, qvAppLogBrowser->document()); - currentLogBrowserId = 0; - masterLogBrowser->setDocument(currentLogBrowser->document()); + vCoreLogHighlighter = new SyntaxHighlighter(GlobalConfig.uiConfig.useDarkTheme, masterLogBrowser->document()); masterLogBrowser->document()->setDocumentMargin(8); masterLogBrowser->document()->adjustSize(); masterLogBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap); @@ -332,33 +317,33 @@ void MainWindow::VersionUpdate(QByteArray &data) void MainWindow::OnConfigListChanged(bool need_restart) { LOG(MODULE_UI, "Loading data...") - auto groups = connectionHandler->Groups(); + auto groups = ConnectionHandler->Groups(); for (auto group : groups) { auto groupItem = new QTreeWidgetItem(); connectionListWidget->addTopLevelItem(groupItem); connectionListWidget->setItemWidget(groupItem, 0, new ConnectionWidget(group, connectionListWidget)); - auto connections = connectionHandler->Connections(group); + auto connections = ConnectionHandler->Connections(group); for (auto connection : connections) { auto connectionItem = new QTreeWidgetItem(); groupItem->addChild(connectionItem); - connectionListWidget->setItemWidget(connectionItem, 0, new ConnectionWidget(connection, connectionListWidget)); + connectionListWidget->setItemWidget(connectionItem, 0, new ConnectionWidget(group, connection, connectionListWidget)); } } - auto subscriptions = connectionHandler->Subscriptions(); + auto subscriptions = ConnectionHandler->Subscriptions(); for (auto subscription : subscriptions) { auto subscriptionItem = new QTreeWidgetItem(); connectionListWidget->addTopLevelItem(subscriptionItem); connectionListWidget->setItemWidget(subscriptionItem, 0, new ConnectionWidget(subscription, connectionListWidget)); - auto connections = connectionHandler->Connections(subscription); + auto connections = ConnectionHandler->Connections(subscription); for (auto connection : connections) { auto connectionItem = new QTreeWidgetItem(); subscriptionItem->addChild(connectionItem); - connectionListWidget->setItemWidget(connectionItem, 0, new ConnectionWidget(connection, connectionListWidget)); + connectionListWidget->setItemWidget(connectionItem, 0, new ConnectionWidget(subscription, connection, connectionListWidget)); } } @@ -441,12 +426,8 @@ MainWindow::~MainWindow() } void MainWindow::UpdateVCoreLog(const QString &log) { - vCoreLogBrowser->append(log); - CleanUpLogs(vCoreLogBrowser) - setMasterLogHBar(); -} -void MainWindow::setMasterLogHBar() -{ + masterLogBrowser->append(log); + CleanUpLogs(masterLogBrowser) auto bar = masterLogBrowser->verticalScrollBar(); auto max = bar->maximum(); auto val = bar->value(); @@ -456,44 +437,6 @@ void MainWindow::setMasterLogHBar() } void MainWindow::on_startButton_clicked() { - //if (!vinstance->KernelStarted) { - // vCoreLogBrowser->clear(); - // speedChartView->Clear(); - // - // // Check Selection - // if (CurrentConnectionIdentifier.isEmpty()) { - // QvMessageBoxWarn(this, tr("No connection selected!"), tr("Please select a config from the list.")); - // return; - // } - // - // auto name = CurrentConnectionIdentifier.IdentifierString(); - // LOG(VCORE, "Connecting to: " + name) - // vCoreLogBrowser->clear(); - // bool startFlag = MWtryStartConnection(); - // - // if (startFlag) { - // MWTryPingConnection(name); - // speedTimerId = startTimer(1000); - // pingTimerId = startTimer(60000); - // this->hTray.showMessage("Qv2ray", tr("Connected: ") + name, this->windowIcon()); - // hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + name); - // statusLabel->setText(tr("Connected: ") + name); - // } else { - // // If failed, show mainwindow - // this->show(); - // } - // - // // Menu actions - // action_Tray_Start->setEnabled(!startFlag); - // action_Tray_Stop->setEnabled(startFlag); - // action_Tray_Reconnect->setEnabled(startFlag); - // tray_SystemProxyMenu->setEnabled(startFlag); - // // Buttons - // startButton->setEnabled(!startFlag); - // stopButton->setEnabled(startFlag); - //} else { - // this->hTray.showMessage("Qv2ray", tr("Already connected to: ") + CurrentConnectionIdentifier.IdentifierString(), this->windowIcon()); - //} } void MainWindow::on_stopButton_clicked() @@ -646,7 +589,7 @@ void MainWindow::on_connectionListWidget_doubleClicked(const QModelIndex &index) } void MainWindow::on_clearlogButton_clicked() { - vCoreLogBrowser->clear(); + masterLogBrowser->clear(); } void MainWindow::on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { @@ -1101,3 +1044,13 @@ void MainWindow::on_connectionListWidget_itemSelectionChanged() // } //} } + +void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column) +{ + Q_UNUSED(column) + auto widget = GetItemWidget(item); + + if (widget->IsConnection()) { + widget->BeginConnection(); + } +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index dc93c552..49487feb 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -59,7 +59,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow void on_subsButton_clicked(); // void ToggleVisibility(); - void setMasterLogHBar(); void VersionUpdate(QByteArray &data); void quit(); @@ -80,6 +79,8 @@ class MainWindow : public QMainWindow, Ui::MainWindow void on_action_RCM_RenameConnection_triggered(); void on_connectionListWidget_itemSelectionChanged(); + void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); + private: // void SetEditWidgetEnable(bool enabled); @@ -106,10 +107,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow //PACServer pacServer; //QvTCPingModel tcpingHelper; SyntaxHighlighter *vCoreLogHighlighter; - SyntaxHighlighter *qvAppLogHighlighter; - // - QList logTextBrowsers; - int currentLogBrowserId = 0; QTreeWidgetItem *CurrentSelectedItemPtr; // // Actions in the system tray menu @@ -130,7 +127,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow // ----------------------------------- Extra Headers For w_MainWindow_extra.cpp Handling V2ray Connectivities. bool systemProxyEnabled; void MWFindAndStartAutoConfig(); - bool MWtryStartConnection(); void MWStopConnection(); void MWSetSystemProxy(); void MWClearSystemProxy(bool); diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index 42489640..8e5c70fa 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -132,63 +132,6 @@ void MainWindow::MWSetSystemProxy() } } -bool MainWindow::MWtryStartConnection() -{ - //auto connectionRoot = connections[CurrentConnectionIdentifier].config; - //currentFullConfig = GenerateRuntimeConfig(connectionRoot); - //bool startFlag = this->vinstance->StartConnection(currentFullConfig); - // - //if (startFlag) { - // bool usePAC = GlobalConfig.inboundConfig.pacConfig.enablePAC; - // bool pacUseSocks = GlobalConfig.inboundConfig.pacConfig.useSocksProxy; - // bool httpEnabled = GlobalConfig.inboundConfig.useHTTP; - // bool socksEnabled = GlobalConfig.inboundConfig.useSocks; - // - // if (usePAC) { - // bool canStartPAC = true; - // QString pacProxyString; // Something like this --> SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT; http://proxy:8080 - // auto pacIP = GlobalConfig.inboundConfig.pacConfig.localIP; - // - // if (pacIP.isEmpty()) { - // LOG(PROXY, "PAC Local IP is empty, default to 127.0.0.1") - // pacIP = "127.0.0.1"; - // } - // - // if (pacUseSocks) { - // if (socksEnabled) { - // pacProxyString = "SOCKS5 " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.socks_port); - // } else { - // LOG(UI, "PAC is using SOCKS, but it is not enabled") - // QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use SOCKS, but it is not enabled")); - // canStartPAC = false; - // } - // } else { - // if (httpEnabled) { - // pacProxyString = "PROXY " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.http_port); - // } else { - // LOG(UI, "PAC is using HTTP, but it is not enabled") - // QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use HTTP, but it is not enabled")); - // canStartPAC = false; - // } - // } - // - // if (canStartPAC) { - // pacServer.SetProxyString(pacProxyString); - // pacServer.StartListen(); - // } else { - // LOG(PROXY, "Not starting PAC due to previous error.") - // } - // } - // - // if (GlobalConfig.inboundConfig.setSystemProxy) { - // MWSetSystemProxy(); - // } - //} - // - //return startFlag; - return false; -} - void MainWindow::MWStopConnection() { //if (systemProxyEnabled) { diff --git a/src/ui/widgets/ConnectionWidget.cpp b/src/ui/widgets/ConnectionWidget.cpp index ac74b3b8..16f1482f 100644 --- a/src/ui/widgets/ConnectionWidget.cpp +++ b/src/ui/widgets/ConnectionWidget.cpp @@ -1,7 +1 @@ #include "ConnectionWidget.hpp" -#include "QMessageBox" - -ConnectionWidget::~ConnectionWidget() -{ - // -} diff --git a/src/ui/widgets/ConnectionWidget.hpp b/src/ui/widgets/ConnectionWidget.hpp index e02cffe6..a198f1c1 100644 --- a/src/ui/widgets/ConnectionWidget.hpp +++ b/src/ui/widgets/ConnectionWidget.hpp @@ -5,7 +5,7 @@ #include "core/handler/ConnectionHandler.hpp" enum CONNECTION_ITEM_TYPE { - CONNECTION, + INVALID, GROUP, SUBSCRIPTION }; @@ -14,29 +14,58 @@ class ConnectionWidget : public QWidget, private Ui::ConnectionWidget { Q_OBJECT public: - CONNECTION_ITEM_TYPE type; - explicit ConnectionWidget(const ConnectionId &id, QWidget *parent = nullptr): ConnectionWidget(parent) - { - type = CONNECTION; - connectionId = id; - // - auto connection = connectionHandler->GetConnection(id); - connNameLabel->setText(connection.displayName); - latencyLabel->setText(tr("Latency: ") + QSTRN(connection.latency) + " " + tr("ms")); - } - explicit ConnectionWidget(const GroupId &id, QWidget *parent = nullptr) : ConnectionWidget(parent) + // + // ======================================= Initialisation for connection nodes. + // + explicit ConnectionWidget(const GroupId &group, const ConnectionId &id, QWidget *parent = nullptr): ConnectionWidget(parent) { type = GROUP; + connectionId = id; + groupId = group; + InitialiseForConnection(id); + } + explicit ConnectionWidget(const SubscriptionId &group, const ConnectionId &id, QWidget *parent = nullptr): ConnectionWidget(parent) + { + type = SUBSCRIPTION; + connectionId = id; + subscriptionId = group; + InitialiseForConnection(id); + } + // + // ======================================= Initialisation for root nodes. + // + explicit ConnectionWidget(const GroupId &id, QWidget *parent = nullptr) : ConnectionWidget(parent) + { + type = INVALID; groupId = id; - InitialiseForGroups(connectionHandler->GetGroup(id).displayName, connectionHandler->Connections(id).count()); + InitialiseForGroup(ConnectionHandler->GetGroup(id).displayName, ConnectionHandler->Connections(id).count()); } explicit ConnectionWidget(const SubscriptionId &id, QWidget *parent = nullptr) : ConnectionWidget(parent) { - type = SUBSCRIPTION; + type = INVALID; subscriptionId = id; - InitialiseForGroups(connectionHandler->GetSubscription(id).displayName, connectionHandler->Connections(id).count()); + InitialiseForGroup(ConnectionHandler->GetSubscription(id).displayName, ConnectionHandler->Connections(id).count()); + } + inline bool IsConnection() const + { + return isConnectionItem; + } + void BeginConnection() + { + if (isConnectionItem) { + if (type == GROUP) { + ConnectionHandler->StartConnection(groupId, connectionId); + } else { + ConnectionHandler->StartConnection(subscriptionId, connectionId); + } + } else { + LOG(MODULE_UI, "Trying to start a non-connection entry, this call is illegal.") + } + } + ~ConnectionWidget() + { + // } - ~ConnectionWidget(); Q_DISABLE_COPY_MOVE(ConnectionWidget) private: @@ -44,9 +73,18 @@ class ConnectionWidget : public QWidget, private Ui::ConnectionWidget { setupUi(this); } - void InitialiseForGroups(const QString &displayName, int connectionCount) + void InitialiseForConnection(const ConnectionId &id) { - connNameLabel->setText(displayName); + isConnectionItem = true; + auto connection = ConnectionHandler->GetConnection(id); + rawDisplayName = connection.displayName; + connNameLabel->setText(rawDisplayName); + latencyLabel->setText(tr("Latency: ") + QSTRN(connection.latency) + " " + tr("ms")); + } + void InitialiseForGroup(const QString &displayName, int connectionCount) + { + rawDisplayName = displayName; + connNameLabel->setText(rawDisplayName); latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections"))); // layout()->removeWidget(connTypeLabel); @@ -54,6 +92,9 @@ class ConnectionWidget : public QWidget, private Ui::ConnectionWidget layout()->removeWidget(dataLabel); delete dataLabel; } + CONNECTION_ITEM_TYPE type; + bool isConnectionItem = false; + QString rawDisplayName; // ConnectionId connectionId; GroupId groupId; From 3f265bb8a98334ad8b31e87ede1b497db5ef193f Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 16 Feb 2020 23:25:06 +0800 Subject: [PATCH 012/332] Update ConnectionWidget.hpp --- src/ui/widgets/ConnectionWidget.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ui/widgets/ConnectionWidget.hpp b/src/ui/widgets/ConnectionWidget.hpp index a198f1c1..f39ec320 100644 --- a/src/ui/widgets/ConnectionWidget.hpp +++ b/src/ui/widgets/ConnectionWidget.hpp @@ -66,7 +66,6 @@ class ConnectionWidget : public QWidget, private Ui::ConnectionWidget { // } - Q_DISABLE_COPY_MOVE(ConnectionWidget) private: ConnectionWidget(QWidget *parent = nullptr) : QWidget(parent), connectionId("null"), groupId("null"), subscriptionId("null") @@ -99,4 +98,6 @@ class ConnectionWidget : public QWidget, private Ui::ConnectionWidget ConnectionId connectionId; GroupId groupId; SubscriptionId subscriptionId; + + Q_DISABLE_COPY_MOVE(ConnectionWidget) }; From 1d679c7cdef326182c6be5d224c7b7153e61e3d9 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 17 Feb 2020 12:53:12 +0800 Subject: [PATCH 013/332] wip: add: one can finally start a connection --- makespec/BUILDVERSION | 2 +- src/core/config/ConfigUpgrade.cpp | 6 +- src/core/connection/ConnectionIO.cpp | 256 +++++++++------------- src/core/connection/ConnectionIO.hpp | 5 +- src/core/handler/ConnectionHandler.cpp | 38 +--- src/core/handler/ConnectionHandler.hpp | 30 ++- src/core/handler/V2rayInstanceHandler.cpp | 8 +- src/core/kernel/KernelInteractions.cpp | 8 +- src/core/kernel/KernelInteractions.hpp | 2 +- src/main.cpp | 11 +- src/ui/w_ImportConfig.cpp | 26 +-- src/ui/w_MainWindow.cpp | 13 ++ src/ui/w_SubscriptionManager.cpp | 153 +++++++------ src/ui/widgets/ConnectionWidget.hpp | 6 +- 14 files changed, 263 insertions(+), 301 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 29276907..0bc0e514 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3882 +3883 diff --git a/src/core/config/ConfigUpgrade.cpp b/src/core/config/ConfigUpgrade.cpp index 2e916b43..8342e6b8 100644 --- a/src/core/config/ConfigUpgrade.cpp +++ b/src/core/config/ConfigUpgrade.cpp @@ -114,8 +114,8 @@ namespace Qv2ray defaultGroup["displayName"] = QObject::tr("Default Group"); QString defaultGroupId = "000000000000"; - if (!QDir(QV2RAY_CONNECTIONS_DIR).exists()) { - QDir().mkpath(QV2RAY_CONNECTIONS_DIR); + if (!QDir(QV2RAY_CONNECTIONS_DIR + defaultGroupId).exists()) { + QDir().mkpath(QV2RAY_CONNECTIONS_DIR + defaultGroupId); } QString autoStartId; @@ -133,7 +133,7 @@ namespace Qv2ray DEBUG(MODULE_SETTINGS, "Generated new UUID: " + newUuid); if (configFile.exists()) { - auto newPath = QV2RAY_CONNECTIONS_DIR + newUuid + QV2RAY_CONFIG_FILE_EXTENSION; + auto newPath = QV2RAY_CONNECTIONS_DIR + defaultGroupId + "/" + newUuid + QV2RAY_CONFIG_FILE_EXTENSION; configFile.rename(newPath); UPGRADELOG("Moved: " + filePath + " to " + newPath); } else { diff --git a/src/core/connection/ConnectionIO.cpp b/src/core/connection/ConnectionIO.cpp index 0296c0e4..10a02431 100644 --- a/src/core/connection/ConnectionIO.cpp +++ b/src/core/connection/ConnectionIO.cpp @@ -5,7 +5,7 @@ namespace Qv2ray::core::connection { namespace ConnectionIO { - CONFIGROOT _ReadConnection(const QString &connection) + CONFIGROOT ReadConnectionInternal(const QString &connection) { QString jsonString = StringFromFile(connection); auto conf = CONFIGROOT(JsonFromString(jsonString)); @@ -17,158 +17,120 @@ namespace Qv2ray::core::connection return conf; } - QMap GetRegularConnections(QStringList connectionNames) + CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id) { - QMap list; - - for (auto conn : connectionNames) { - list.insert(conn, _ReadConnection(QV2RAY_CONFIG_DIR + conn + QV2RAY_CONFIG_FILE_EXTENSION)); - } - - return list; + return ReadConnectionInternal(QV2RAY_CONNECTIONS_DIR + group.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION); } - QMap GetSubscriptionConnection(QString subscription) + CONFIGROOT GetConnectionRoot(const SubscriptionId &subscription, const ConnectionId &id) { - auto _files = GetFileList(QV2RAY_SUBSCRIPTION_DIR + subscription); - QMap _config; - - for (auto _file : _files) { - // check if is proper connection file. - if (_file.endsWith(QV2RAY_CONFIG_FILE_EXTENSION)) { - auto confName = _file; - // Remove the extension - confName.chop(sizeof(QV2RAY_CONFIG_FILE_EXTENSION) - 1); - _config[confName] = _ReadConnection(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + _file); - } else { - LOG(MODULE_SUBSCRIPTION, "Found a file in subscription folder but without proper suffix: " + _file) - } - } - - if (_config.isEmpty()) { - LOG(MODULE_SUBSCRIPTION, "WARN: Maybe loading an empty subscrption: " + subscription) - } - - return _config; - } - - QMap> GetSubscriptionConnections(QStringList subscriptions) - { - // SUB-NAME CONN-NAME CONN-ROOT - QMap> list; - - for (auto singleSub : subscriptions) { - LOG(MODULE_SUBSCRIPTION, "Processing subscription: " + singleSub) - list[singleSub] = GetSubscriptionConnection(singleSub); - } - - return list; + return ReadConnectionInternal(QV2RAY_SUBSCRIPTION_DIR + subscription.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION); } + //// + //// Save Connection to a place, with checking if there's existing file. + //// If so, append "_N" to the name. + //bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool canOverrideExisting) + //{ + // auto str = JsonToString(obj); + // auto fullPath = QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION; // - // Save Connection to a place, with checking if there's existing file. - // If so, append "_N" to the name. - bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool canOverrideExisting) - { - auto str = JsonToString(obj); - auto fullPath = QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION; - - // If there's already a file AND we CANNOT override existing file. - if (QFile::exists(fullPath) && !canOverrideExisting) { - // Alias is a pointer to a QString. - DeducePossibleFileName(QV2RAY_CONFIG_DIR, alias, QV2RAY_CONFIG_FILE_EXTENSION); - fullPath = QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION; - } - - LOG(MODULE_SETTINGS, "Saving a config named: " + *alias) - QFile config(fullPath); - return StringToFile(&str, &config); - } - - bool SaveSubscriptionConfig(CONFIGROOT obj, const QString &subscription, QString *name) - { - auto str = JsonToString(obj); - auto fName = *name; - - if (!IsValidFileName(fName)) { - fName = RemoveInvalidFileName(fName); - } - - QFile config(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + fName + QV2RAY_CONFIG_FILE_EXTENSION); - - // If there's already a file. THIS IS EXTREMELY RARE - if (config.exists()) { - LOG(MODULE_FILEIO, "Trying to overrwrite an existing subscription config file. THIS IS RARE") - } - - LOG(MODULE_SETTINGS, "Saving a subscription named: " + fName) - bool result = StringToFile(&str, &config); - - if (!result) { - LOG(MODULE_FILEIO, "Failed to save a connection config from subscription: " + subscription + ", name: " + fName) - } - - *name = fName; - return result; - } - - bool RemoveConnection(const QString &alias) - { - QFile config(QV2RAY_CONFIG_DIR + alias + QV2RAY_CONFIG_FILE_EXTENSION); - - if (!config.exists()) { - LOG(MODULE_FILEIO, "Trying to remove a non-existing file?") - return false; - } else { - return config.remove(); - } - } - - bool RemoveSubscriptionConnection(const QString &subsName, const QString &name) - { - QFile config(QV2RAY_SUBSCRIPTION_DIR + subsName + "/" + name + QV2RAY_CONFIG_FILE_EXTENSION); - - if (!config.exists()) { - LOG(MODULE_FILEIO, "Trying to remove a non-existing file?") - return false; - } else { - return config.remove(); - } - } - - bool RenameConnection(const QString &originalName, const QString &newName) - { - LOG(MODULE_CONNECTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName) - return QFile::rename(QV2RAY_CONFIG_DIR + originalName + QV2RAY_CONFIG_FILE_EXTENSION, QV2RAY_CONFIG_DIR + newName + QV2RAY_CONFIG_FILE_EXTENSION); - } - - bool RenameSubscription(const QString &originalName, const QString &newName) - { - LOG(MODULE_SUBSCRIPTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName) - return QDir().rename(QV2RAY_SUBSCRIPTION_DIR + originalName, QV2RAY_SUBSCRIPTION_DIR + newName); - } - - CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool importComplex) - { - QFile source(sourceFilePath); - - if (!source.exists()) { - LOG(MODULE_FILEIO, "Trying to import from an non-existing file.") - return CONFIGROOT(); - } - - auto root = CONFIGROOT(JsonFromString(StringFromFile(&source))); - - if (!importComplex) { - JSON_ROOT_TRY_REMOVE("inbounds") - JSON_ROOT_TRY_REMOVE("routing") - } - - JSON_ROOT_TRY_REMOVE("log") - JSON_ROOT_TRY_REMOVE("api") - JSON_ROOT_TRY_REMOVE("stats") - JSON_ROOT_TRY_REMOVE("dns") - return root; - } + // // If there's already a file AND we CANNOT override existing file. + // if (QFile::exists(fullPath) && !canOverrideExisting) { + // // Alias is a pointer to a QString. + // DeducePossibleFileName(QV2RAY_CONFIG_DIR, alias, QV2RAY_CONFIG_FILE_EXTENSION); + // fullPath = QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION; + // } + // + // LOG(MODULE_SETTINGS, "Saving a config named: " + *alias) + // QFile config(fullPath); + // return StringToFile(&str, &config); + //} + // + //bool SaveSubscriptionConfig(CONFIGROOT obj, const QString &subscription, QString *name) + //{ + // auto str = JsonToString(obj); + // auto fName = *name; + // + // if (!IsValidFileName(fName)) { + // fName = RemoveInvalidFileName(fName); + // } + // + // QFile config(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + fName + QV2RAY_CONFIG_FILE_EXTENSION); + // + // // If there's already a file. THIS IS EXTREMELY RARE + // if (config.exists()) { + // LOG(MODULE_FILEIO, "Trying to overrwrite an existing subscription config file. THIS IS RARE") + // } + // + // LOG(MODULE_SETTINGS, "Saving a subscription named: " + fName) + // bool result = StringToFile(&str, &config); + // + // if (!result) { + // LOG(MODULE_FILEIO, "Failed to save a connection config from subscription: " + subscription + ", name: " + fName) + // } + // + // *name = fName; + // return result; + //} + // + //bool RemoveConnection(const QString &alias) + //{ + // QFile config(QV2RAY_CONFIG_DIR + alias + QV2RAY_CONFIG_FILE_EXTENSION); + // + // if (!config.exists()) { + // LOG(MODULE_FILEIO, "Trying to remove a non-existing file?") + // return false; + // } else { + // return config.remove(); + // } + //} + // + //bool RemoveSubscriptionConnection(const QString &subsName, const QString &name) + //{ + // QFile config(QV2RAY_SUBSCRIPTION_DIR + subsName + "/" + name + QV2RAY_CONFIG_FILE_EXTENSION); + // + // if (!config.exists()) { + // LOG(MODULE_FILEIO, "Trying to remove a non-existing file?") + // return false; + // } else { + // return config.remove(); + // } + //} + // + //bool RenameConnection(const QString &originalName, const QString &newName) + //{ + // LOG(MODULE_CONNECTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName) + // return QFile::rename(QV2RAY_CONFIG_DIR + originalName + QV2RAY_CONFIG_FILE_EXTENSION, QV2RAY_CONFIG_DIR + newName + QV2RAY_CONFIG_FILE_EXTENSION); + //} + // + //bool RenameSubscription(const QString &originalName, const QString &newName) + //{ + // LOG(MODULE_SUBSCRIPTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName) + // return QDir().rename(QV2RAY_SUBSCRIPTION_DIR + originalName, QV2RAY_SUBSCRIPTION_DIR + newName); + //} + // + //CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool importComplex) + //{ + // QFile source(sourceFilePath); + // + // if (!source.exists()) { + // LOG(MODULE_FILEIO, "Trying to import from an non-existing file.") + // return CONFIGROOT(); + // } + // + // auto root = CONFIGROOT(JsonFromString(StringFromFile(&source))); + // + // if (!importComplex) { + // JSON_ROOT_TRY_REMOVE("inbounds") + // JSON_ROOT_TRY_REMOVE("routing") + // } + // + // JSON_ROOT_TRY_REMOVE("log") + // JSON_ROOT_TRY_REMOVE("api") + // JSON_ROOT_TRY_REMOVE("stats") + // JSON_ROOT_TRY_REMOVE("dns") + // return root; + //} } } diff --git a/src/core/connection/ConnectionIO.hpp b/src/core/connection/ConnectionIO.hpp index 5a4bade2..9bb47f18 100644 --- a/src/core/connection/ConnectionIO.hpp +++ b/src/core/connection/ConnectionIO.hpp @@ -5,9 +5,8 @@ namespace Qv2ray::core::connection { namespace ConnectionIO { - QMap GetGroupConnections(const GroupId &group); - QMap GetSubscriptionConnections(const SubscriptionId &subscription); - QMap> GetSubscriptionConnections(const QList &subscriptions); + CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id); + CONFIGROOT GetConnectionRoot(const SubscriptionId &subscription, const ConnectionId &id); // // Save Connection Config bool SaveConnectionConfig(CONFIGROOT obj, const ConnectionId &id, bool canOverrideExisting); diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index 87fe3582..b2c61eab 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -1,6 +1,4 @@ #include "ConnectionHandler.hpp" -#include "core/connection/ConnectionIO.hpp" - namespace Qv2ray::core::handlers { template @@ -32,6 +30,7 @@ namespace Qv2ray::core::handlers groups[GroupId(GlobalConfig.groups.keys()[i])] = GlobalConfig.groups.values()[i]; } + kernelInstance = new V2rayKernelInstance(); saveTimerId = startTimer(60000); } @@ -74,35 +73,14 @@ namespace Qv2ray::core::handlers { return subscriptions[id]; } - optional QvConnectionHandler::StartConnection(const SubscriptionId &group, const ConnectionId &id) - { - // - return ""; - } - optional QvConnectionHandler::StartConnection(const GroupId &group, const ConnectionId &id) - { - //if (!kernelInstance->KernelStarted) { - // // Check Selection - // if (!connections.contains(id)) { - // return tr("No connection selected!") + NEWLINE + tr("Please select a config from the list."); - // } - // - // bool startFlag = CHTryStartConnection(); - // - // if (startFlag) { - // MWTryPingConnection(name); - // speedTimerId = startTimer(1000); - // pingTimerId = startTimer(60000); - // this->hTray.showMessage("Qv2ray", tr("Connected: ") + name, this->windowIcon()); - // hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + name); - // statusLabel->setText(tr("Connected: ") + name); - // } - //} else { - // this->hTray.showMessage("Qv2ray", tr("Already connected to: ") + CurrentConnectionIdentifier.IdentifierString(), this->windowIcon()); - //} - return ""; - } + QvConnectionHandler::~QvConnectionHandler() { + if (kernelInstance->KernelStarted) { + kernelInstance->StopConnection(); + LOG(MODULE_CORE_HANDLER, "Stopped connection from destructor.") + } + + delete kernelInstance; } } diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 5de93195..408784dc 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -3,6 +3,8 @@ #include "base/Qv2rayBase.hpp" #include "core/kernel/KernelInteractions.hpp" #include "core/CoreSafeTypes.hpp" +#include "core/connection/ConnectionIO.hpp" + namespace Qv2ray::core::handlers { @@ -19,9 +21,21 @@ namespace Qv2ray::core::handlers const QList Connections(const GroupId &groupId) const; const QList Connections(const SubscriptionId &subscriptionId) const; // - optional StartConnection(const GroupId &group, const ConnectionId &id); - optional StartConnection(const SubscriptionId &subscription, const ConnectionId &id); optional StopConnection(const ConnectionId &id); + // + template + optional StartConnection(const T &group, const ConnectionId &id) + { + if (!connections.contains(id)) { + return tr("No connection selected!") + NEWLINE + tr("Please select a config from the list."); + } + + auto root = GetConnectionRoot(group, id); + return _CHTryStartConnection_p(id, root); + } + template optional StartConnection(const GroupId &group, const ConnectionId &id); + template optional StartConnection(const SubscriptionId &group, const ConnectionId &id); + // public: // // Connection Operations. @@ -77,20 +91,14 @@ namespace Qv2ray::core::handlers QHash connections; QHash subscriptions; // - unique_ptr kernelInstance = make_unique(); // We only support one cuncurrent connection currently. //QHash kernelInstances; + V2rayKernelInstance *kernelInstance = nullptr; // - optional _CHTryStartConnection(const ConnectionId &id); + optional _CHTryStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); }; // - inline unique_ptr ConnectionHandler = nullptr; - // - inline void InitialiseConnectionHandler() - { - LOG(MODULE_CORE_HANDLER, "Initializing ConnectionHandler...") - ConnectionHandler = make_unique(); - } + inline QvConnectionHandler *ConnectionHandler = nullptr; } using namespace Qv2ray::core::handlers; diff --git a/src/core/handler/V2rayInstanceHandler.cpp b/src/core/handler/V2rayInstanceHandler.cpp index 2e91518f..6d48469b 100644 --- a/src/core/handler/V2rayInstanceHandler.cpp +++ b/src/core/handler/V2rayInstanceHandler.cpp @@ -1,11 +1,11 @@ #include "ConnectionHandler.hpp" #include "core/connection/Generation.hpp" -optional QvConnectionHandler::_CHTryStartConnection(const ConnectionId &id) +optional QvConnectionHandler::_CHTryStartConnection_p(const ConnectionId &id, const CONFIGROOT &root) { - auto connection = connections[id]; - //currentFullConfig = GenerateRuntimeConfig(connection); - //bool startFlag = this->vinstance->StartConnection(currentFullConfig); + auto &connectionMeta = connections[id]; + auto fullConfig = GenerateRuntimeConfig(root); + return kernelInstance->StartConnection(fullConfig); //if (startFlag) { // bool usePAC = GlobalConfig.inboundConfig.pacConfig.enablePAC; // bool pacUseSocks = GlobalConfig.inboundConfig.pacConfig.useSocksProxy; diff --git a/src/core/kernel/KernelInteractions.cpp b/src/core/kernel/KernelInteractions.cpp index 68d19a3c..f0691b17 100644 --- a/src/core/kernel/KernelInteractions.cpp +++ b/src/core/kernel/KernelInteractions.cpp @@ -137,11 +137,11 @@ namespace Qv2ray::core::kernel KernelStarted = false; } - bool V2rayKernelInstance::StartConnection(CONFIGROOT root) + optional V2rayKernelInstance::StartConnection(CONFIGROOT root) { if (KernelStarted) { LOG(MODULE_VCORE, "Status is invalid, expect STOPPED when calling StartConnection") - return false; + return tr("Invalid V2ray Instance Status."); } // Write the final configuration to the disk. @@ -188,10 +188,10 @@ namespace Qv2ray::core::kernel DEBUG(MODULE_VCORE, "Qv2ray API started") } - return true; + return {}; } else { KernelStarted = false; - return false; + return tr("V2ray kernel failed to start."); } } diff --git a/src/core/kernel/KernelInteractions.hpp b/src/core/kernel/KernelInteractions.hpp index d483d478..eb91b1f3 100644 --- a/src/core/kernel/KernelInteractions.hpp +++ b/src/core/kernel/KernelInteractions.hpp @@ -22,7 +22,7 @@ namespace Qv2ray::core::kernel qulonglong getAllSpeedUp(); qulonglong getAllSpeedDown(); // - bool StartConnection(CONFIGROOT root); + optional StartConnection(CONFIGROOT root); void StopConnection(); bool KernelStarted = false; // diff --git a/src/main.cpp b/src/main.cpp index 21d81ec7..a63d5d07 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -447,15 +447,15 @@ int main(int argc, char *argv[]) } #endif - //_qApp.setAttribute(Qt::AA_DontUseNativeMenuBar); - // Initialise Connection Handler - InitialiseConnectionHandler(); - // Show MainWindow - MainWindow w; #ifndef QT_DEBUG try { #endif + //_qApp.setAttribute(Qt::AA_DontUseNativeMenuBar); + // Initialise Connection Handler + ConnectionHandler = new QvConnectionHandler(); + // Show MainWindow + MainWindow w; QObject::connect(&_qApp, &SingleApplication::instanceStarted, [&]() { // When a second instance is connected, show the mainwindow. w.show(); @@ -477,6 +477,7 @@ int main(int argc, char *argv[]) }); #endif auto rcode = _qApp.exec(); + delete ConnectionHandler; LOG(MODULE_INIT, "Quitting normally") return rcode; #ifndef QT_DEBUG diff --git a/src/ui/w_ImportConfig.cpp b/src/ui/w_ImportConfig.cpp index 4e36489b..c3551b2e 100644 --- a/src/ui/w_ImportConfig.cpp +++ b/src/ui/w_ImportConfig.cpp @@ -101,19 +101,19 @@ void ImportConfigWindow::on_beginImportBtn_clicked() switch (tabWidget->currentIndex()) { case 0: { - // From File... - bool ImportAsComplex = keepImportedInboundCheckBox->isChecked(); - QString path = fileLineTxt->text(); - - if (!V2rayKernelInstance::ValidateConfig(path)) { - QvMessageBoxWarn(this, tr("Import config file"), tr("Failed to check the validity of the config file.")); - return; - } - - aliasPrefix += "_" + QFileInfo(path).fileName(); - CONFIGROOT config = ConvertConfigFromFile(path, ImportAsComplex); - connections[aliasPrefix] = config; - break; + //// From File... + //bool ImportAsComplex = keepImportedInboundCheckBox->isChecked(); + //QString path = fileLineTxt->text(); + // + //if (!V2rayKernelInstance::ValidateConfig(path)) { + // QvMessageBoxWarn(this, tr("Import config file"), tr("Failed to check the validity of the config file.")); + // return; + //} + // + //aliasPrefix += "_" + QFileInfo(path).fileName(); + ////CONFIGROOT config = ConvertConfigFromFile(path, ImportAsComplex); + //connections[aliasPrefix] = config; + //break; } case 1: { diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 2b4ee110..f8dd06d5 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -1054,3 +1054,16 @@ void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item widget->BeginConnection(); } } +/* + * //if (startFlag) { + // MWTryPingConnection(name); + // speedTimerId = startTimer(1000); + // pingTimerId = startTimer(60000); + // this->hTray.showMessage("Qv2ray", tr("Connected: ") + name, this->windowIcon()); + // hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + name); + // statusLabel->setText(tr("Connected: ") + name); + //} + //} else { + // this->hTray.showMessage("Qv2ray", tr("Already connected to: ") + CurrentConnectionIdentifier.IdentifierString(), this->windowIcon()); + //} + */ diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 8244f037..224de8c1 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -87,13 +87,12 @@ void SubscribeEditor::on_updateButton_clicked() return; } - bool result = RenameSubscription(currentSubName, newName); - - if (!result) { - QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("Failed to rename a subscription, this is an unknown error.")); - return; - } - + ////bool result = RenameSubscription(currentSubName, newName); + // + //if (!result) { + // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("Failed to rename a subscription, this is an unknown error.")); + // return; + //} subscriptions[newName] = subscriptions[currentSubName]; subscriptions.remove(currentSubName); subNameTxt->setText(newName); @@ -127,86 +126,86 @@ void SubscribeEditor::on_updateButton_clicked() void SubscribeEditor::StartUpdateSubscription(const QString &subscriptionName) { - this->setEnabled(false); - auto data = helper.syncget(subscriptions[subscriptionName].address, withProxyCB->isChecked()); - auto content = DecodeSubscriptionString(data).trimmed(); - - if (!content.isEmpty()) { - connectionsList->clear(); - auto vmessList = SplitLines(content); - QDir(QV2RAY_SUBSCRIPTION_DIR + subscriptionName).removeRecursively(); - QDir().mkpath(QV2RAY_SUBSCRIPTION_DIR + subscriptionName); - - for (auto vmess : vmessList) { - QString errMessage; - QString _alias; - auto config = ConvertConfigFromString(vmess.trimmed(), &_alias, &errMessage); - - if (!errMessage.isEmpty()) { - LOG(MODULE_SUBSCRIPTION, "Processing a subscription with following error: " + errMessage) - } else { - SaveSubscriptionConfig(config, subscriptionName, &_alias); - connectionsList->addItem(_alias); - } - } - - subscriptions[subscriptionName].lastUpdated = system_clock::to_time_t(system_clock::now()); - lastUpdatedLabel->setText(timeToString(subscriptions[subscriptionName].lastUpdated)); - isUpdateInProgress = false; - } else { - LOG(MODULE_NETWORK, "We have received an empty string from the URL.") - QvMessageBoxWarn(this, tr("Updating subscriptions"), tr("Failed to process the result from the upstream, please check your Url.")); - } - - this->setEnabled(true); + //this->setEnabled(false); + //auto data = helper.syncget(subscriptions[subscriptionName].address, withProxyCB->isChecked()); + //auto content = DecodeSubscriptionString(data).trimmed(); + // + //if (!content.isEmpty()) { + // connectionsList->clear(); + // auto vmessList = SplitLines(content); + // QDir(QV2RAY_SUBSCRIPTION_DIR + subscriptionName).removeRecursively(); + // QDir().mkpath(QV2RAY_SUBSCRIPTION_DIR + subscriptionName); + // + // for (auto vmess : vmessList) { + // QString errMessage; + // QString _alias; + // auto config = ConvertConfigFromString(vmess.trimmed(), &_alias, &errMessage); + // + // if (!errMessage.isEmpty()) { + // LOG(MODULE_SUBSCRIPTION, "Processing a subscription with following error: " + errMessage) + // } else { + // //SaveSubscriptionConfig(config, subscriptionName, &_alias); + // connectionsList->addItem(_alias); + // } + // } + // + // subscriptions[subscriptionName].lastUpdated = system_clock::to_time_t(system_clock::now()); + // lastUpdatedLabel->setText(timeToString(subscriptions[subscriptionName].lastUpdated)); + // isUpdateInProgress = false; + //} else { + // LOG(MODULE_NETWORK, "We have received an empty string from the URL.") + // QvMessageBoxWarn(this, tr("Updating subscriptions"), tr("Failed to process the result from the upstream, please check your Url.")); + //} + // + //this->setEnabled(true); } void SubscribeEditor::on_removeSubsButton_clicked() { - if (subscriptionList->currentRow() < 0) - return; - - auto name = subscriptionList->currentItem()->text(); - subscriptionList->takeItem(subscriptionList->currentRow()); - subscriptions.remove(name); - - if (!name.isEmpty()) { - QDir(QV2RAY_SUBSCRIPTION_DIR + name).removeRecursively(); - } - - //// If removed a whole subscription... - //if (GlobalConfig.autoStartConfig.subscriptionName == name) { - // GlobalConfig.autoStartConfig = QvConnectionObject(); - // SaveGlobalConfig(GlobalConfig); + //if (subscriptionList->currentRow() < 0) + // return; + // + //auto name = subscriptionList->currentItem()->text(); + //subscriptionList->takeItem(subscriptionList->currentRow()); + //subscriptions.remove(name); + // + //if (!name.isEmpty()) { + // QDir(QV2RAY_SUBSCRIPTION_DIR + name).removeRecursively(); //} - groupBox_2->setEnabled(subscriptionList->count() > 0); - SaveConfig(); + // + ////// If removed a whole subscription... + ////if (GlobalConfig.autoStartConfig.subscriptionName == name) { + //// GlobalConfig.autoStartConfig = QvConnectionObject(); + //// SaveGlobalConfig(GlobalConfig); + ////} + //groupBox_2->setEnabled(subscriptionList->count() > 0); + //SaveConfig(); } void SubscribeEditor::on_subscriptionList_currentRowChanged(int currentRow) { - if (subscriptionList->count() == 0) { - return; - } - - if (currentRow < 0 && subscriptionList->count() > 0) { - subscriptionList->setCurrentRow(0); - } - - currentSubName = subscriptionList->currentItem()->text(); - LOG(MODULE_UI, "Subscription row changed, new name: " + currentSubName) + //if (subscriptionList->count() == 0) { + // return; + //} // - subNameTxt->setText(currentSubName); - subAddrTxt->setText(subscriptions[currentSubName].address); - updateIntervalSB->setValue(subscriptions[currentSubName].updateInterval); - lastUpdatedLabel->setText(timeToString(subscriptions[currentSubName].lastUpdated)); + //if (currentRow < 0 && subscriptionList->count() > 0) { + // subscriptionList->setCurrentRow(0); + //} // - connectionsList->clear(); - auto _list = GetSubscriptionConnection(currentSubName); - - for (auto i = 0; i < _list.count(); i++) { - connectionsList->addItem(_list.keys()[i]); - } + //currentSubName = subscriptionList->currentItem()->text(); + //LOG(MODULE_UI, "Subscription row changed, new name: " + currentSubName) + //// + //subNameTxt->setText(currentSubName); + //subAddrTxt->setText(subscriptions[currentSubName].address); + //updateIntervalSB->setValue(subscriptions[currentSubName].updateInterval); + //lastUpdatedLabel->setText(timeToString(subscriptions[currentSubName].lastUpdated)); + //// + //connectionsList->clear(); + //auto _list = GetSubscriptionConnection(currentSubName); + // + //for (auto i = 0; i < _list.count(); i++) { + // connectionsList->addItem(_list.keys()[i]); + //} } void SubscribeEditor::SaveConfig() @@ -243,6 +242,6 @@ void SubscribeEditor::on_connectionsList_itemClicked(QListWidgetItem *item) if (item != nullptr) { auto name = item->text(); currentSelectedConfig.first = name; - currentSelectedConfig.second = GetSubscriptionConnection(currentSubName)[name]; + //currentSelectedConfig.second = GetSubscriptionConnection(currentSubName)[name]; } } diff --git a/src/ui/widgets/ConnectionWidget.hpp b/src/ui/widgets/ConnectionWidget.hpp index f39ec320..14ede824 100644 --- a/src/ui/widgets/ConnectionWidget.hpp +++ b/src/ui/widgets/ConnectionWidget.hpp @@ -55,8 +55,10 @@ class ConnectionWidget : public QWidget, private Ui::ConnectionWidget if (isConnectionItem) { if (type == GROUP) { ConnectionHandler->StartConnection(groupId, connectionId); - } else { + } else if (type == SUBSCRIPTION) { ConnectionHandler->StartConnection(subscriptionId, connectionId); + } else { + LOG(MODULE_UI, "Trying to start an INVALID non-connection entry, this call is illegal.") } } else { LOG(MODULE_UI, "Trying to start a non-connection entry, this call is illegal.") @@ -98,6 +100,6 @@ class ConnectionWidget : public QWidget, private Ui::ConnectionWidget ConnectionId connectionId; GroupId groupId; SubscriptionId subscriptionId; - + Q_DISABLE_COPY_MOVE(ConnectionWidget) }; From 92128bb0fbf6dad9edc463ce4bc11fb9c8f9f9eb Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Mon, 17 Feb 2020 13:04:46 +0800 Subject: [PATCH 014/332] qt 5.14.1 for snap and revert confinement to strict --- snap/snapcraft.yaml | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 5b9ebeb3..11ba4f0b 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -3,8 +3,8 @@ base: core18 adopt-info: qv2ray icon: assets/icons/qv2ray.png -grade: devel -confinement: devmode +grade: stable +confinement: strict plugs: gsettings: @@ -26,6 +26,20 @@ apps: command: bin/desktop-launch qv2ray environment: QT_QPA_PLATFORMTHEME: gtk3 + plugs: + - home + - x11 + - opengl + - network + - network-bind + - unity7 + - pulseaudio + - desktop + - desktop-legacy + - gsettings + - network-control + - network-manager + - system-observe common-id: com.github.Qv2ray desktop: "usr/share/applications/qv2ray.desktop" @@ -52,7 +66,6 @@ parts: - libqt5gui5 - libqt5network5 - libqt5widgets5 - - fonts-noto-cjk - libglib2.0-bin options: - PREFIX=/usr @@ -107,14 +120,11 @@ parts: plugin: nil build-packages: - dirmngr - override-pull: | + override-build: | echo 'deb http://archive.neon.kde.org/unstable bionic main' > /etc/apt/sources.list.d/neon.list echo 'deb http://ppa.launchpad.net/ymshenyu/grpc-1/ubuntu bionic main' >> /etc/apt/sources.list.d/tools.list sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E6D4736255751E5D sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 281f24e574404629aa3bda1a4f10c386c55cdb04 - sudo apt-get update - snapcraftctl pull - override-build: | - snapcraftctl build - sudo apt upgrade -y - sudo apt dist-upgrade -y \ No newline at end of file + sudo apt update + sudo apt dist-upgrade -y + snapcraftctl build \ No newline at end of file From 0160bdda58dc7b2e984d314a872ef48f27c3dd57 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Tue, 18 Feb 2020 05:37:51 +0800 Subject: [PATCH 015/332] Update StreamSettingsWidget.cpp --- src/ui/widgets/StreamSettingsWidget.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/ui/widgets/StreamSettingsWidget.cpp b/src/ui/widgets/StreamSettingsWidget.cpp index cc0b256d..c1e74945 100644 --- a/src/ui/widgets/StreamSettingsWidget.cpp +++ b/src/ui/widgets/StreamSettingsWidget.cpp @@ -18,19 +18,17 @@ void StreamSettingsWidget::SetStreamObject(StreamSettingsObject sso) stream = sso; // transportCombo->setCurrentText(stream.network); + // TLS tlsCB->setChecked(stream.security == "tls"); + serverNameTxt->setText(stream.tlsSettings.serverName); + allowInsecureCB->setChecked(stream.tlsSettings.allowInsecure); + alpnTxt->setPlainText(stream.tlsSettings.alpn.join(NEWLINE)); // TCP tcpHeaderTypeCB->setCurrentText(stream.tcpSettings.header.type); tcpRequestTxt->setPlainText(StructToJsonString(stream.tcpSettings.header.request)); tcpRespTxt->setPlainText(StructToJsonString(stream.tcpSettings.header.response)); // HTTP - QString allHosts; - - for (auto host : stream.httpSettings.host) { - allHosts = allHosts + host + "\r\n"; - } - - httpHostTxt->setPlainText(allHosts); + httpHostTxt->setPlainText(stream.httpSettings.host.join(NEWLINE)); httpPathTxt->setText(stream.httpSettings.path); // WS wsPathTxt->setText(stream.wsSettings.path); From 199b8926334b4e1a865018283b6c4513a0275e9f Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Wed, 19 Feb 2020 12:29:45 +0800 Subject: [PATCH 016/332] [cleanup] purging and updating * purging an unused function * updating to zero-alloc impl --- src/common/QvHelpers.hpp | 39 ------------------------------- src/ui/editors/w_RoutesEditor.cpp | 5 ++-- 2 files changed, 2 insertions(+), 42 deletions(-) diff --git a/src/common/QvHelpers.hpp b/src/common/QvHelpers.hpp index d1bcf09c..60954cfd 100644 --- a/src/common/QvHelpers.hpp +++ b/src/common/QvHelpers.hpp @@ -79,19 +79,6 @@ namespace Qv2ray::common return IsIPv4Address(addr) || IsIPv6Address(addr); } - /* - * Generic function to find if an element of any type exists in list - */ - template - bool contains(std::list &listOfElements, const T &element) - { - // Find the iterator if element in list - auto it = std::find(listOfElements.begin(), listOfElements.end(), element); - //return if iterator points to end or not. It points to end then it means element - // does not exists in list - return it != listOfElements.end(); - } - inline QString timeToString(const time_t &t) { auto _tm = std::localtime(&t); @@ -100,32 +87,6 @@ namespace Qv2ray::common strftime(MY_TIME, sizeof(MY_TIME), "%x - %I:%M%p", _tm); return QString(MY_TIME); } - - template - std::vector Keys(const myMap &m) - { - std::vector r; - r.reserve(m.size()); - - for (const auto &kvp : m) { - r.push_back(kvp.first); - } - - return r; - } - - template - std::vector Values(const myMap &m) - { - std::vector r; - r.reserve(m.size()); - - for (const auto &kvp : m) { - r.push_back(kvp.second); - } - - return r; - } } using namespace Qv2ray::common; diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index bd8a6f22..c35c8a61 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -184,7 +184,6 @@ void RouteEditor::onConnectionCreated(QtNodes::Connection const &c) // Connection Established auto const sourceNode = c.getNode(PortType::Out); auto const targetNode = c.getNode(PortType::In); - auto conns = Qv2ray::common::Values(nodeScene->connections()); if (inboundNodes.values().contains(sourceNode) && ruleNodes.values().contains(targetNode)) { // It's a inbound-rule connection @@ -195,7 +194,7 @@ void RouteEditor::onConnectionCreated(QtNodes::Connection const &c) // QStringList has an helper to let us remove duplicates, see below. QStringList _inbounds; - for (auto conn : conns) { + for (auto &&[_, conn] : nodeScene->connections()) { auto _connection = conn.get(); if (_connection->getNode(PortType::In) == targetNode && _connection->getNode(PortType::Out) == sourceNode && _connection->id() != c.id()) { @@ -581,7 +580,7 @@ void RouteEditor::on_enableBalancerCB_stateChanged(int arg1) LOG(MODULE_UI, "A rule has been set to use balancer, disconnect it to any outbound.") auto ruleNode = ruleNodes[currentRuleTag]; - for (auto conn : Qv2ray::common::Values(nodeScene->connections())) { + for (auto &&[_, conn] : nodeScene->connections()) { if (conn.get()->getNode(PortType::Out) == ruleNode) { nodeScene->deleteConnection(*conn); } From 083416cf2b9ed75c7e03e59039397f5dc3bb5b88 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Wed, 19 Feb 2020 12:51:51 +0800 Subject: [PATCH 017/332] [refactor] extract regexp objects making ipv4 & ipv6 validation regexps static, avoiding repetitive allocation cost --- src/common/QvHelpers.hpp | 31 ++++++++++++++++++++----------- src/ui/w_PreferencesWindow.cpp | 2 ++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/common/QvHelpers.hpp b/src/common/QvHelpers.hpp index 60954cfd..400f12a3 100644 --- a/src/common/QvHelpers.hpp +++ b/src/common/QvHelpers.hpp @@ -8,6 +8,7 @@ #define REGEX_PORT_NUMBER R"(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])*)" namespace Qv2ray::common + { QStringList GetFileList(QDir dir); QString Base64Encode(QString string); @@ -64,20 +65,28 @@ namespace Qv2ray::common return JsonFromString(json); } - inline bool IsIPv4Address(const QString &addr) + + namespace validation { - return QRegularExpression(REGEX_IPV4_ADDR "$").match(addr).hasMatch(); + static QRegularExpression __regex_ipv4_full(REGEX_IPV4_ADDR "$"); + static QRegularExpression __regex_ipv6_full(REGEX_IPV6_ADDR "$"); + + inline bool IsIPv4Address(const QString &addr) + { + return __regex_ipv4_full.match(addr).hasMatch(); + } + + inline bool IsIPv6Address(const QString &addr) + { + return __regex_ipv6_full.match(addr).hasMatch(); + } + + inline bool IsValidIPAddress(const QString &addr) + { + return IsIPv4Address(addr) || IsIPv6Address(addr); + } } - inline bool IsIPv6Address(const QString &addr) - { - return QRegularExpression(REGEX_IPV6_ADDR "$").match(addr).hasMatch(); - } - - inline bool IsValidIPAddress(const QString &addr) - { - return IsIPv4Address(addr) || IsIPv6Address(addr); - } inline QString timeToString(const time_t &t) { diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index 54edbf48..e5ff71ab 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -14,6 +14,8 @@ #include "components/autolaunch/QvAutoLaunch.hpp" #include +using Qv2ray::common::validation::IsValidIPAddress; + #define LOADINGCHECK if(!finishedLoading) return; #define NEEDRESTART if(finishedLoading) IsConnectionPropertyChanged = true; From 4d4a2b3ea2c9eb5f117852d0033dbe54dabf998a Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Wed, 19 Feb 2020 12:57:54 +0800 Subject: [PATCH 018/332] [cleanup] removing unused helpers removing two bad helpers --- src/common/QvHelpers.cpp | 22 ---------------------- src/common/QvHelpers.hpp | 3 +-- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 6a780fc5..978ad07a 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -186,26 +186,4 @@ namespace Qv2ray::common i++; } } - - QStringList ConvertQStringList(const QList &stdListString) - { - QStringList listQt; - listQt.reserve(stdListString.size()); - - for (const std::string &s : stdListString) { - listQt.append(QString::fromStdString(s)); - } - - return listQt; - } - std::list ConvertStdStringList(const QStringList &qStringList) - { - std::list stdList; - - for (auto &s : qStringList) { - stdList.push_back(s.toStdString()); - } - - return stdList; - } } diff --git a/src/common/QvHelpers.hpp b/src/common/QvHelpers.hpp index 400f12a3..e00ddb44 100644 --- a/src/common/QvHelpers.hpp +++ b/src/common/QvHelpers.hpp @@ -33,8 +33,7 @@ namespace Qv2ray::common // QString FormatBytes(long long bytes); void DeducePossibleFileName(const QString &baseDir, QString *fileName, const QString &extension); - QStringList ConvertQStringList(const QList &stdListString); - std::list ConvertStdStringList(const QStringList &qStringList); + // This function cannot be marked as inline. QString RemoveInvalidFileName(const QString &fileName); bool IsValidFileName(const QString &fileName); From 24a74a8381aba786c28ed6356970e354743c5136 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Wed, 19 Feb 2020 13:43:32 +0800 Subject: [PATCH 019/332] add wayland for snap --- snap/snapcraft.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 11ba4f0b..9f4f657e 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -29,6 +29,7 @@ apps: plugs: - home - x11 + - wayland - opengl - network - network-bind From fe9a518522bf880ad0d8a5be279c307e0b071fec Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 19 Feb 2020 22:27:01 +0800 Subject: [PATCH 020/332] wip: add: added some more ui functionalities, now support filtering against the connection list --- Qv2ray.pro | 1 + makespec/BUILDVERSION | 2 +- src/base/models/QvConfigIdentifier.hpp | 12 +- src/base/models/QvConfigModel.hpp | 6 +- src/components/tcping/QvTCPing.cpp | 2 +- src/components/tcping/QvTCPing.hpp | 4 +- src/core/config/ConfigUpgrade.cpp | 2 +- src/core/handler/ConnectionHandler.cpp | 94 +++++- src/core/handler/ConnectionHandler.hpp | 88 +++--- src/core/handler/V2rayInstanceHandler.cpp | 12 +- src/ui/w_MainWindow.cpp | 174 +++++------ src/ui/w_MainWindow.hpp | 37 +-- src/ui/w_MainWindow.ui | 344 ++++++++-------------- src/ui/w_SubscriptionManager.cpp | 4 +- src/ui/w_SubscriptionManager.hpp | 4 +- src/ui/widgets/ConnectionInfoWidget.cpp | 52 ++++ src/ui/widgets/ConnectionInfoWidget.hpp | 24 ++ src/ui/widgets/ConnectionInfoWidget.ui | 236 +++++++++++++++ src/ui/widgets/ConnectionWidget.cpp | 67 +++++ src/ui/widgets/ConnectionWidget.hpp | 111 +++---- 20 files changed, 804 insertions(+), 472 deletions(-) create mode 100644 src/ui/widgets/ConnectionInfoWidget.cpp create mode 100644 src/ui/widgets/ConnectionInfoWidget.hpp create mode 100644 src/ui/widgets/ConnectionInfoWidget.ui diff --git a/Qv2ray.pro b/Qv2ray.pro index 6bf108f6..8f29b9f5 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -111,6 +111,7 @@ Qv2rayAddSource(ui, _, w_ScreenShot_Core, cpp, hpp, ui) Qv2rayAddSource(ui, _, w_SubscriptionManager, cpp, hpp, ui) Qv2rayAddSource(ui, widgets, ConnectionWidget, cpp, hpp, ui) Qv2rayAddSource(ui, widgets, StreamSettingsWidget, cpp, hpp, ui) +Qv2rayAddSource(ui, widgets, ConnectionInfoWidget, cpp, hpp, ui) SOURCES += $$PWD/src/main.cpp HEADERS += diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 54b8bd86..8b6eff0e 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3885 +3887 diff --git a/src/base/models/QvConfigIdentifier.hpp b/src/base/models/QvConfigIdentifier.hpp index 0d3fb75f..c2254aad 100644 --- a/src/base/models/QvConfigIdentifier.hpp +++ b/src/base/models/QvConfigIdentifier.hpp @@ -12,27 +12,27 @@ namespace Qv2ray::base _QvGroupObjectBase(): displayName(), connections() { } }; - struct QvGroupObject : _QvGroupObjectBase { - QvGroupObject() { } + struct GroupObject : _QvGroupObjectBase { + GroupObject() { } XTOSTRUCT(O(displayName, connections)) }; - struct QvSubscriptionObject : _QvGroupObjectBase { + struct SubscriptionObject : _QvGroupObjectBase { QString address; int64_t lastUpdated; float updateInterval; - QvSubscriptionObject(): address(""), lastUpdated(system_clock::to_time_t(system_clock::now())), updateInterval(10) { } + SubscriptionObject(): address(""), lastUpdated(system_clock::to_time_t(system_clock::now())), updateInterval(10) { } XTOSTRUCT(O(lastUpdated, updateInterval, address, connections, displayName)) }; - struct QvConnectionObject { + struct ConnectionObject { QString displayName; int64_t importDate; int64_t lastConnected; int64_t latency; int64_t upLinkData; int64_t downLinkData; - QvConnectionObject(): displayName(), importDate(system_clock::to_time_t(system_clock::now())), lastConnected(), latency(0), upLinkData(0), downLinkData(0) { } + ConnectionObject(): displayName(), importDate(system_clock::to_time_t(system_clock::now())), lastConnected(), latency(0), upLinkData(0), downLinkData(0) { } XTOSTRUCT(O(displayName, importDate, lastConnected, latency, upLinkData, downLinkData)) }; } diff --git a/src/base/models/QvConfigModel.hpp b/src/base/models/QvConfigModel.hpp index b73a5a80..7bd3c10d 100644 --- a/src/base/models/QvConfigModel.hpp +++ b/src/base/models/QvConfigModel.hpp @@ -118,10 +118,10 @@ namespace Qv2ray::base::config QString autoStartId; // // Key = groupId, connectionId, subscriptionId - QMap groups; - QMap subscriptions; + QMap groups; + QMap subscriptions; /// Connections are used privately. - QMap connections; + QMap connections; // Qv2rayUIConfig uiConfig; Qv2rayAPIConfig apiConfig; diff --git a/src/components/tcping/QvTCPing.cpp b/src/components/tcping/QvTCPing.cpp index 62a0f144..6ed5344b 100644 --- a/src/components/tcping/QvTCPing.cpp +++ b/src/components/tcping/QvTCPing.cpp @@ -27,7 +27,7 @@ namespace Qv2ray::components::tcping worker->cancel(); } } - void QvTCPingModel::StartPing(const QvConnectionObject &connectionName, const QString &hostName, int port) + void QvTCPingModel::StartPing(const ConnectionObject &connectionName, const QString &hostName, int port) { QvTCPingData data; data.hostName = hostName; diff --git a/src/components/tcping/QvTCPing.hpp b/src/components/tcping/QvTCPing.hpp index d2cc76d9..5e08308a 100644 --- a/src/components/tcping/QvTCPing.hpp +++ b/src/components/tcping/QvTCPing.hpp @@ -5,7 +5,7 @@ namespace Qv2ray::components::tcping { struct QvTCPingData { - QvConnectionObject connectionIdentifier; + ConnectionObject connectionIdentifier; QString hostName; int port; QString errorMessage; @@ -19,7 +19,7 @@ namespace Qv2ray::components::tcping public: explicit QvTCPingModel(int defaultCount = 5, QObject *parent = nullptr); - void StartPing(const QvConnectionObject &connectionName, const QString &hostName, int port); + void StartPing(const ConnectionObject &connectionName, const QString &hostName, int port); void StopAllPing(); signals: void PingFinished(QvTCPingData data); diff --git a/src/core/config/ConfigUpgrade.cpp b/src/core/config/ConfigUpgrade.cpp index 8342e6b8..dc80017f 100644 --- a/src/core/config/ConfigUpgrade.cpp +++ b/src/core/config/ConfigUpgrade.cpp @@ -74,7 +74,7 @@ namespace Qv2ray for (auto item = subs.begin(); item != subs.end(); item++) { auto key = item.key(); - QvSubscriptionObject _conf; + SubscriptionObject _conf; _conf.address = item.value().toString(); _conf.lastUpdated = system_clock::to_time_t(system_clock::now()); _conf.updateInterval = 5; diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index b2c61eab..49a984c9 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -13,6 +13,44 @@ namespace Qv2ray::core::handlers return list; } + const QList QvConnectionHandler::IdentifierList(const SubscriptionId &subsId, const QList &idList) const + { + QList list; + + for (auto groupConnection : idList) { + auto connId = ConnectionId(groupConnection); + + if (connections.keys().contains(connId)) { + ConnectionIdentifier x; + x.isSubscription = true; + x.connectionId = connId; + x.subscriptionId = subsId; + list.push_back(x); + } + } + + return list; + } + + const QList QvConnectionHandler::IdentifierList(const GroupId &groupId, const QList &idList) const + { + QList list; + + for (auto groupConnection : idList) { + auto connId = ConnectionId(groupConnection); + + if (connections.keys().contains(connId)) { + ConnectionIdentifier x; + x.isSubscription = false; + x.connectionId = connId; + x.groupId = groupId; + list.push_back(x); + } + } + + return list; + } + QvConnectionHandler::QvConnectionHandler() { DEBUG(MODULE_CORE_HANDLER, "ConnectionHandler Constructor.") @@ -33,29 +71,46 @@ namespace Qv2ray::core::handlers kernelInstance = new V2rayKernelInstance(); saveTimerId = startTimer(60000); } + const QList QvConnectionHandler::Connections() const + { + QList list; + + for (auto i = 0; i < groups.count(); i++) { + auto key = groups.keys()[i]; + auto group = groups[key]; + list.append(IdentifierList(key, StringsToIdList(group.connections))); + } + + for (auto i = 0; i < subscriptions.count(); i++) { + auto key = subscriptions.keys()[i]; + auto subs = subscriptions[key]; + list.append(IdentifierList(key, StringsToIdList(subs.connections))); + } + + return list; + } const QList QvConnectionHandler::Groups() const { return groups.keys(); } + const QList QvConnectionHandler::Subscriptions() const { return subscriptions.keys(); } - const QList QvConnectionHandler::Connections() const + + const QList QvConnectionHandler::Connections(const GroupId &groupId) const { - return connections.keys(); - } - const QList QvConnectionHandler::Connections(const GroupId &groupId) const - { - return StringsToIdList(groups[groupId].connections); - } - const QList QvConnectionHandler::Connections(const SubscriptionId &subscriptionId) const - { - return StringsToIdList(subscriptions[subscriptionId].connections); + return IdentifierList(groupId, StringsToIdList(groups[groupId].connections)); } - const QvConnectionObject &QvConnectionHandler::GetConnection(const ConnectionId &id) + const QList QvConnectionHandler::Connections(const SubscriptionId &subscriptionId) const + { + return IdentifierList(subscriptionId, StringsToIdList(subscriptions[subscriptionId].connections)); + } + + const ConnectionObject &QvConnectionHandler::GetConnection(const ConnectionId &id) { if (!connections.contains(id)) { LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); @@ -64,12 +119,25 @@ namespace Qv2ray::core::handlers return connections[id]; } - const QvGroupObject &QvConnectionHandler::GetGroup(const GroupId &id) + const optional QvConnectionHandler::StartConnection(const ConnectionIdentifier &identifier) + { + if (!connections.contains(identifier.connectionId)) { + return tr("No connection selected!") + NEWLINE + tr("Please select a config from the list."); + } + + CONFIGROOT root = identifier.isSubscription + ? GetConnectionRoot(identifier.subscriptionId, identifier.connectionId) + : GetConnectionRoot(identifier.groupId, identifier.connectionId); + return _CHTryStartConnection_p(identifier.connectionId, root); + } + + + const GroupObject &QvConnectionHandler::GetGroup(const GroupId &id) { return groups[id]; } - const QvSubscriptionObject &QvConnectionHandler::GetSubscription(const SubscriptionId &id) + const SubscriptionObject &QvConnectionHandler::GetSubscription(const SubscriptionId &id) { return subscriptions[id]; } diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 408784dc..a7eaa820 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -5,9 +5,19 @@ #include "core/CoreSafeTypes.hpp" #include "core/connection/ConnectionIO.hpp" - namespace Qv2ray::core::handlers { + + struct ConnectionIdentifier { + bool isConnection; + bool isSubscription; + ConnectionId connectionId; + GroupId groupId; + SubscriptionId subscriptionId; + // + ConnectionIdentifier() : isSubscription(false), connectionId("null"), groupId("null"), subscriptionId("null") { } + }; + class QvConnectionHandler : public QObject { Q_OBJECT @@ -15,65 +25,61 @@ namespace Qv2ray::core::handlers explicit QvConnectionHandler(); ~QvConnectionHandler(); // + const QList Connections() const; + // const QList Groups() const; - const QList Connections() const; const QList Subscriptions() const; - const QList Connections(const GroupId &groupId) const; - const QList Connections(const SubscriptionId &subscriptionId) const; + const QList Connections(const GroupId &groupId) const; + const QList Connections(const SubscriptionId &subscriptionId) const; // - optional StopConnection(const ConnectionId &id); + bool IsConnectionConnected(const ConnectionId &id); // - template - optional StartConnection(const T &group, const ConnectionId &id) - { - if (!connections.contains(id)) { - return tr("No connection selected!") + NEWLINE + tr("Please select a config from the list."); - } - - auto root = GetConnectionRoot(group, id); - return _CHTryStartConnection_p(id, root); - } - template optional StartConnection(const GroupId &group, const ConnectionId &id); - template optional StartConnection(const SubscriptionId &group, const ConnectionId &id); + const optional StopConnection(const ConnectionId &id); + const optional StartConnection(const ConnectionIdentifier &identifier); // public: // // Connection Operations. - const QvConnectionObject &GetConnection(const ConnectionId &id); + const ConnectionObject &GetConnection(const ConnectionId &id); const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); - optional DeleteConnection(const ConnectionId &id); - optional UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); - optional RenameConnection(const ConnectionId &id, const QString &newName); - optional DuplicateConnection(const ConnectionId &id); - optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); + const optional DeleteConnection(const ConnectionId &id); + const optional UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); + const optional RenameConnection(const ConnectionId &id, const QString &newName); + const optional DuplicateConnection(const ConnectionId &id); + const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); // // Misc Connection Operations - optional TestLatency(const ConnectionId &id); - optional TestLatency(const GroupId &id); - optional TestLatency(const SubscriptionId &id); - optional TestAllLatency(); + const optional TestLatency(const ConnectionId &id); + const optional TestLatency(const GroupId &id); + const optional TestLatency(const SubscriptionId &id); + const optional TestAllLatency(); // // Group Operations - const QvGroupObject &GetGroup(const GroupId &id); - const GroupId CreateGroup(const QString displayName); - optional DeleteGroup(const GroupId &id); - optional DuplicateGroup(const GroupId &id); - optional RenameGroup(const GroupId &id, const QString &newName); + const GroupObject &GetGroup(const GroupId &id); + const GroupId &CreateGroup(const QString displayName); + const optional DeleteGroup(const GroupId &id); + const optional DuplicateGroup(const GroupId &id); + const optional RenameGroup(const GroupId &id, const QString &newName); // // Subscriptions - const QvSubscriptionObject &GetSubscription(const SubscriptionId &id); + const SubscriptionObject &GetSubscription(const SubscriptionId &id); const SubscriptionId &CreateSubscription(const QString &displayName, const QString &address); - optional RenameSubscription(const SubscriptionId &id, const QString &newName); - optional DeleteSubscription(const SubscriptionId &id); - optional UpdateSubscription(const SubscriptionId &id); - optional UpdateSubscriptionASync(const SubscriptionId &id); + const optional RenameSubscription(const SubscriptionId &id, const QString &newName); + const optional DeleteSubscription(const SubscriptionId &id); + const optional UpdateSubscription(const SubscriptionId &id); + const optional UpdateSubscriptionASync(const SubscriptionId &id); signals: + // + void OnConnected(const ConnectionId &id); + void OnDisConnected(const ConnectionId &id); + // void OnConnectionCreated(const ConnectionId &id, const QString &displayName); void OnConnectionRenamed(const ConnectionId &id, const QString &originalName, const QString &newName); void OnConnectionChanged(const ConnectionId &id); void OnConnectionGroupChanged(const ConnectionId &id, const QString &originalGroup, const QString &newGroup); // + void OnConnectionLatencyTestStart(const ConnectionId &id); void OnConnectionLatencyTestFinished(const ConnectionId &id); // void OnGroupCreated(const GroupId &id, const QString &displayName); @@ -87,15 +93,17 @@ namespace Qv2ray::core::handlers private: int saveTimerId; - QHash groups; - QHash connections; - QHash subscriptions; + QHash groups; + QHash connections; + QHash subscriptions; // // We only support one cuncurrent connection currently. //QHash kernelInstances; V2rayKernelInstance *kernelInstance = nullptr; // optional _CHTryStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); + const QList IdentifierList(const GroupId &groupId, const QList &idList) const; + const QList IdentifierList(const SubscriptionId &groupId, const QList &idList) const; }; // inline QvConnectionHandler *ConnectionHandler = nullptr; diff --git a/src/core/handler/V2rayInstanceHandler.cpp b/src/core/handler/V2rayInstanceHandler.cpp index 6d48469b..7c50c151 100644 --- a/src/core/handler/V2rayInstanceHandler.cpp +++ b/src/core/handler/V2rayInstanceHandler.cpp @@ -5,7 +5,15 @@ optional QvConnectionHandler::_CHTryStartConnection_p(const ConnectionI { auto &connectionMeta = connections[id]; auto fullConfig = GenerateRuntimeConfig(root); - return kernelInstance->StartConnection(fullConfig); + // + auto result = kernelInstance->StartConnection(fullConfig); + + if (!result.has_value()) { + emit OnConnected(id); + connectionMeta.lastConnected = system_clock::to_time_t(system_clock::now()); + } + + return result; //if (startFlag) { // bool usePAC = GlobalConfig.inboundConfig.pacConfig.enablePAC; // bool pacUseSocks = GlobalConfig.inboundConfig.pacConfig.useSocksProxy; @@ -52,5 +60,5 @@ optional QvConnectionHandler::_CHTryStartConnection_p(const ConnectionI // MWSetSystemProxy(); // } //} - return "startFlag"; + //return "startFlag"; } diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index f8dd06d5..41581bc7 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -26,9 +26,7 @@ #include "components/pac/QvPACHandler.hpp" #include "core/connection/ConnectionIO.hpp" - -// ========================================================================================== -#include "ui/widgets/ConnectionWidget.hpp" +#include "ui/widgets/ConnectionInfoWidget.hpp" // MainWindow.cpp --> Main MainWindow source file, handles mostly UI-related operations. @@ -90,6 +88,7 @@ QvMessageBusSlotImpl(MainWindow) MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTray(this), tcpingHelper(3, this) { + setupUi(this); MainWindow::mwInstance = this; //vinstance = new V2rayKernelInstance(); //connect(vinstance, &V2rayKernelInstance::onProcessOutputReadyRead, this, &MainWindow::UpdateVCoreLog); @@ -101,16 +100,16 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr // tr("To solve the problem, read the V2ray log in the log text browser.")); //}); // - setupUi(this); QvMessageBusConnect(MainWindow); // + infoWidget = new ConnectionInfoWidget(this); + connectionInfoLayout->addWidget(infoWidget); + // vCoreLogHighlighter = new SyntaxHighlighter(GlobalConfig.uiConfig.useDarkTheme, masterLogBrowser->document()); masterLogBrowser->document()->setDocumentMargin(8); masterLogBrowser->document()->adjustSize(); masterLogBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap); // - qvLogTimerId = startTimer(500); - // requestHelper = new QvHttpRequestHelper(); //connect(&tcpingHelper, &QvTCPingModel::PingFinished, this, &MainWindow::onPingFinished); // @@ -119,11 +118,11 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr importConfigButton->setIcon(QICON_R("import.png")); duplicateBtn->setIcon(QICON_R("duplicate.png")); removeConfigButton->setIcon(QICON_R("delete.png")); - editConfigButton->setIcon(QICON_R("edit.png")); - editJsonBtn->setIcon(QICON_R("json.png")); - // - pingTestBtn->setIcon(QICON_R("ping_gauge.png")); - shareBtn->setIcon(QICON_R("share.png")); + //editConfigButton->setIcon(QICON_R("edit.png")); + //editJsonBtn->setIcon(QICON_R("json.png")); + //// + //pingTestBtn->setIcon(QICON_R("ping_gauge.png")); + //shareBtn->setIcon(QICON_R("share.png")); updownImageBox->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); updownImageBox_2->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); // @@ -166,7 +165,7 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr connect(action_Tray_Start, &QAction::triggered, this, &MainWindow::on_startButton_clicked); connect(action_Tray_Stop, &QAction::triggered, this, &MainWindow::on_stopButton_clicked); connect(action_Tray_Reconnect, &QAction::triggered, this, &MainWindow::on_reconnectButton_clicked); - connect(action_Tray_Quit, &QAction::triggered, this, &MainWindow::quit); + connect(action_Tray_Quit, &QAction::triggered, this, &MainWindow::on_actionExit_triggered); connect(action_Tray_SetSystemProxy, &QAction::triggered, this, &MainWindow::MWSetSystemProxy); connect(action_Tray_ClearSystemProxy, &QAction::triggered, this, &MainWindow::MWClearSystemProxy); connect(&hTray, &QSystemTrayIcon::activated, this, &MainWindow::on_activatedTray); @@ -229,12 +228,12 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr void MainWindow::SetEditWidgetEnable(bool enabled) { removeConfigButton->setEnabled(enabled); - editConfigButton->setEnabled(enabled); + //editConfigButton->setEnabled(enabled); duplicateBtn->setEnabled(enabled); - editJsonBtn->setEnabled(enabled); - shareBtn->setEnabled(enabled); + //editJsonBtn->setEnabled(enabled); + //shareBtn->setEnabled(enabled); // Allow ping all. - pingTestBtn->setText(enabled ? tr("Ping") : tr("Ping All")); + //pingTestBtn->setText(enabled ? tr("Ping") : tr("Ping All")); } void MainWindow::mouseReleaseEvent(QMouseEvent *e) @@ -328,7 +327,9 @@ void MainWindow::OnConfigListChanged(bool need_restart) for (auto connection : connections) { auto connectionItem = new QTreeWidgetItem(); groupItem->addChild(connectionItem); - connectionListWidget->setItemWidget(connectionItem, 0, new ConnectionWidget(group, connection, connectionListWidget)); + auto widget = new ConnectionWidget(connection, connectionListWidget); + connect(widget, &ConnectionWidget::RequestWidgetFocus, this, &MainWindow::onConnectionWidgetFocusRequested); + connectionListWidget->setItemWidget(connectionItem, 0, widget); } } @@ -343,7 +344,9 @@ void MainWindow::OnConfigListChanged(bool need_restart) for (auto connection : connections) { auto connectionItem = new QTreeWidgetItem(); subscriptionItem->addChild(connectionItem); - connectionListWidget->setItemWidget(connectionItem, 0, new ConnectionWidget(subscription, connection, connectionListWidget)); + auto widget = new ConnectionWidget(connection, connectionListWidget); + connect(widget, &ConnectionWidget::RequestWidgetFocus, this, &MainWindow::onConnectionWidgetFocusRequested); + connectionListWidget->setItemWidget(connectionItem, 0, widget); } } @@ -420,9 +423,7 @@ void MainWindow::OnConfigListChanged(bool need_restart) } MainWindow::~MainWindow() { - killTimer(qvLogTimerId); hTray.hide(); - //delete this->vinstance; } void MainWindow::UpdateVCoreLog(const QString &log) { @@ -449,13 +450,13 @@ void MainWindow::on_stopButton_clicked() //// //hTray.setToolTip(TRAY_TOOLTIP_PREFIX); //statusLabel->setText(tr("Disconnected")); - //action_Tray_Start->setEnabled(true); - //action_Tray_Stop->setEnabled(false); - //action_Tray_Reconnect->setEnabled(false); - //// Set to false as the system proxy has been cleared in the StopConnection function. - //tray_SystemProxyMenu->setEnabled(false); - //startButton->setEnabled(true); - //stopButton->setEnabled(false); + action_Tray_Start->setEnabled(true); + action_Tray_Stop->setEnabled(false); + action_Tray_Reconnect->setEnabled(false); + // Set to false as the system proxy has been cleared in the StopConnection function. + tray_SystemProxyMenu->setEnabled(false); + startButton->setEnabled(true); + stopButton->setEnabled(false); //// //netspeedLabel->setText("0.00 B/s\r\n0.00 B/s"); //dataamountLabel->setText("0.00 B\r\n0.00 B"); @@ -466,7 +467,7 @@ void MainWindow::on_stopButton_clicked() void MainWindow::closeEvent(QCloseEvent *event) { this->hide(); - tray_RootMenu->actions()[0]->setText(tr("Show")); + tray_RootMenu->actions().first()->setText(tr("Show")); event->ignore(); } void MainWindow::on_activatedTray(QSystemTrayIcon::ActivationReason reason) @@ -481,15 +482,6 @@ void MainWindow::on_activatedTray(QSystemTrayIcon::ActivationReason reason) #endif break; - //case QSystemTrayIcon::MiddleClick: - // if (vinstance->KernelStarted) { - // on_stopButton_clicked(); - // } else { - // on_startButton_clicked(); - // } - // - // break; - case QSystemTrayIcon::DoubleClick: #ifdef __APPLE__ ToggleVisibility(); @@ -516,7 +508,8 @@ void MainWindow::ToggleVisibility() tray_RootMenu->actions()[0]->setText(tr("Show")); } } -void MainWindow::quit() + +void MainWindow::on_actionExit_triggered() { if (StartupOption.enableToolbarPlguin) { StopProcessingPlugins(); @@ -527,51 +520,6 @@ void MainWindow::quit() ExitQv2ray(); } -void MainWindow::on_actionExit_triggered() -{ - quit(); -} - -//void MainWindow::ShowAndSetConnection(QvConnectionObject fullIdentifier, bool SetConnection, bool ApplyConnection) -//{ -//// Check empty again... -//if (!connections.contains(fullIdentifier)) return; -// -//SetEditWidgetEnable(true); -//// -//// --------- BRGIN Show Connection -//auto conf = connections[fullIdentifier]; -//// -//auto isComplexConfig = IsComplexConfig(conf.config); -//routeCountLabel->setText(isComplexConfig ? tr("Complex") : tr("Simple")); -// -//if (conf.latency == 0.0) { -// latencyLabel->setText(tr("No data")); -//} else { -// latencyLabel->setText(QSTRN(conf.latency) + " " + tr("ms")); -//} -// -//if (conf.configType == CONNECTION_SUBSCRIPTION) { -// routeCountLabel->setText(routeCountLabel->text().append(" (" + tr("Subscription") + ":" + conf.subscriptionName + ")")); -//} -// -//// Get Connection info -//auto host_port = MWGetConnectionInfo(fullIdentifier.IdentifierString()); -//_hostLabel->setText(get<0>(host_port)); -//_portLabel->setText(QSTRN(get<1>(host_port))); -//_OutBoundTypeLabel->setText(get<2>(host_port)); -// -//// Set to currentConnection -//if (SetConnection) { -// CurrentSelectedItemPtr = FindItemByIdentifier(fullIdentifier); -// CurrentConnectionIdentifier = fullIdentifier; -//} -// -//// Restart Connection -//if (ApplyConnection) { -// on_reconnectButton_clicked(); -//} -//} void MainWindow::on_preferencesBtn_clicked() { PreferencesWindow w(this); @@ -593,7 +541,8 @@ void MainWindow::on_clearlogButton_clicked() } void MainWindow::on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { - //Q_UNUSED(previous) + Q_UNUSED(previous) + CurrentItem = current; //isRenamingInProgress = false; // //if (!IsConnectableItem(current)) return; @@ -1067,3 +1016,60 @@ void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item // this->hTray.showMessage("Qv2ray", tr("Already connected to: ") + CurrentConnectionIdentifier.IdentifierString(), this->windowIcon()); //} */ + +void MainWindow::OnConnected(const ConnectionId &id) +{ + Q_UNUSED(id) +} + + +void MainWindow::onConnectionWidgetFocusRequested(const ConnectionWidget *_widget) +{ + if (_widget == nullptr) { + return; + } + + for (auto _item_ : connectionListWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard | Qt::MatchRecursive)) { + auto myWidget = GetItemWidget(_item_); + + if (myWidget == _widget) { + LOG(MODULE_UI, "Setting current item.") + connectionListWidget->setCurrentItem(_item_); + } + } +} + +void MainWindow::on_connectionFilterTxt_textEdited(const QString &arg1) +{ + // No recursive since we only need top level item + for (auto _top_item_ : connectionListWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard)) { + //auto topWidget = GetItemWidget(_top_item_); + bool isTotallyHide = true; + + for (auto i = 0; i < _top_item_->childCount(); i++) { + auto _child_ = _top_item_->child(i); + auto childWidget = GetItemWidget(_child_); + + if (childWidget->NameMatched(arg1)) { + LOG(MODULE_UI, "Setting current item.") + // Show the child + _child_->setHidden(false); + isTotallyHide = false; + } else { + _child_->setHidden(true); + } + } + + _top_item_->setHidden(isTotallyHide); + + if (!isTotallyHide) { + connectionListWidget->expandItem(_top_item_); + } + } +} + +void MainWindow::on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column) +{ + Q_UNUSED(column) + infoWidget->ShowConnectionDetails(GetItemWidget(item)->Identifier()); +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 49487feb..b20cb239 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -7,20 +7,16 @@ #include "ui_w_MainWindow.h" -//#include "core/CoreUtils.hpp" -//#include "core/kernel/KernelInteractions.hpp" -//#include "core/connection/ConnectionIO.hpp" - #include "common/LogHighlighter.hpp" #include "common/HTTPRequestHelper.hpp" - - -//#include "components/tcping/QvTCPing.hpp" -//#include "components/pac/QvPACHandler.hpp" #include "components/speedchart/speedwidget.hpp" - +#include "core/handler/ConnectionHandler.hpp" #include "ui/messaging/QvMessageBus.hpp" +// ========================================================================================== +#include "ui/widgets/ConnectionWidget.hpp" +#include "ui/widgets/ConnectionInfoWidget.hpp" + class MainWindow : public QMainWindow, Ui::MainWindow { Q_OBJECT @@ -60,11 +56,11 @@ class MainWindow : public QMainWindow, Ui::MainWindow // void ToggleVisibility(); void VersionUpdate(QByteArray &data); - void quit(); + // + void OnConnected(const ConnectionId &id); public: static MainWindow *mwInstance; - //QvConnectionObject CurrentConnectionIdentifier; protected: void mouseReleaseEvent(QMouseEvent *e) override; @@ -73,18 +69,24 @@ class MainWindow : public QMainWindow, Ui::MainWindow void closeEvent(QCloseEvent *) override; private slots: + // + void onConnectionWidgetFocusRequested(const ConnectionWidget *widget); + // void on_action_StartThis_triggered(); void on_action_RCM_EditJson_triggered(); void on_action_RCM_ConvToComplex_triggered(); void on_action_RCM_RenameConnection_triggered(); void on_connectionListWidget_itemSelectionChanged(); - void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); + void on_connectionFilterTxt_textEdited(const QString &arg1); + + void on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column); + private: + QTreeWidgetItem *CurrentItem; // void SetEditWidgetEnable(bool enabled); - //void ShowAndSetConnection(QvConnectionObject fullIdentifier, bool SetConnection, bool Apply); //CONFIGROOT currentFullConfig; // // Charts @@ -95,19 +97,12 @@ class MainWindow : public QMainWindow, Ui::MainWindow //QvConnectionObject renameOriginalIdentifier; bool isRenamingInProgress; // - // ID for QTimers - // - int qvLogTimerId; - int speedTimerId; - int pingTimerId; - // - // QvHttpRequestHelper *requestHelper; QSystemTrayIcon hTray; //PACServer pacServer; //QvTCPingModel tcpingHelper; SyntaxHighlighter *vCoreLogHighlighter; - QTreeWidgetItem *CurrentSelectedItemPtr; + ConnectionInfoWidget *infoWidget; // // Actions in the system tray menu // diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 97468a5a..5096b276 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -6,19 +6,13 @@ 0 0 - 865 - 659 + 800 + 590 - - - 0 - 0 - - - 740 + 800 590 @@ -38,7 +32,7 @@ 530 - + @@ -109,6 +103,16 @@ + + + + Search + + + true + + + @@ -204,6 +208,22 @@ + + + + Duplicate connection + + + Duplicate + + + + 22 + 22 + + + + @@ -349,6 +369,12 @@ + + + 480 + 0 + + QFrame::NoFrame @@ -360,8 +386,8 @@ 0 0 - 504 - 759 + 459 + 848 @@ -369,218 +395,69 @@ 0 - - - Config Details + + + + 13 + - - - - - Config Type - - - - - - - IBeamCursor - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Protocol - - - - - - - IBeamCursor - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Address - - - - - - - IBeamCursor - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Port Number - - - - - - - IBeamCursor - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - + + Connection Info + + + + + + + Qt::Horizontal + + + + + + + + 0 + 250 + + + + + 0 + + + 0 + + + 0 + + + 0 + - - - - 12 - + + + Qt::Vertical - - Operations + + QSizePolicy::Minimum - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Duplicate connection - - - Duplicate - - - - 22 - 22 - - - - - - - - Edit connection - - - Edit - - - - 22 - 22 - - - - - - - - Edit connection as JSON - - - Edit JSON - - - - 22 - 22 - - - - - - - - true - - - Ping Test - - - - 22 - 22 - - - - - - - - Share - - - - 22 - 22 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + 20 + 30 + + + - 12 + 13 @@ -588,12 +465,19 @@ + + + + Qt::Horizontal + + + 0 - 250 + 200 @@ -612,11 +496,27 @@ + + + + Qt::Vertical + + + QSizePolicy::Minimum + + + + 20 + 30 + + + + - 12 + 13 @@ -624,12 +524,19 @@ + + + + Qt::Horizontal + + + 0 - 250 + 200 @@ -645,8 +552,8 @@ 0 0 - 865 - 22 + 800 + 29 @@ -887,9 +794,6 @@ connectionListWidget importConfigButton removeConfigButton - editJsonBtn - pingTestBtn - shareBtn diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 224de8c1..dc1ca117 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -34,7 +34,7 @@ QPair SubscribeEditor::GetSelectedConfig() return currentSelectedConfig; } -void SubscribeEditor::LoadSubscriptionList(QMap list) +void SubscribeEditor::LoadSubscriptionList(QMap list) { subscriptionList->clear(); @@ -210,7 +210,7 @@ void SubscribeEditor::on_subscriptionList_currentRowChanged(int currentRow) void SubscribeEditor::SaveConfig() { - QMap newConf; + QMap newConf; for (auto _ : subscriptions.toStdMap()) { if (!_.second.address.isEmpty()) { diff --git a/src/ui/w_SubscriptionManager.hpp b/src/ui/w_SubscriptionManager.hpp index 4116778e..edd3df9e 100644 --- a/src/ui/w_SubscriptionManager.hpp +++ b/src/ui/w_SubscriptionManager.hpp @@ -38,11 +38,11 @@ class SubscribeEditor : public QDialog, private Ui::w_SubscribeEditor private: void StartUpdateSubscription(const QString &subscriptionName); void SaveConfig(); - void LoadSubscriptionList(QMap list); + void LoadSubscriptionList(QMap list); bool isUpdateInProgress = false; QvHttpRequestHelper helper; QPair currentSelectedConfig; - QMap subscriptions; + QMap subscriptions; QString currentSubName; }; diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp new file mode 100644 index 00000000..4d8b5913 --- /dev/null +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -0,0 +1,52 @@ +#include "ConnectionInfoWidget.hpp" + +ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : + QWidget(parent) +{ + setupUi(this); +} + +void ConnectionInfoWidget::ShowConnectionDetails(const ConnectionIdentifier &_identifier) +{ + identifier = _identifier; + auto data = ConnectionHandler->GetConnection(identifier.connectionId); + connNameLabel->setText(data.displayName); + // + auto groupname = identifier.isSubscription + ? ConnectionHandler->GetSubscription(identifier.subscriptionId).displayName + : ConnectionHandler->GetGroup(identifier.groupId).displayName; + groupLabel->setText(groupname); + //auto isComplexConfig = IsComplexConfig(conf.config); + //routeCountLabel->setText(isComplexConfig ? tr("Complex") : tr("Simple")); + // + //if (conf.configType == CONNECTION_SUBSCRIPTION) { + // routeCountLabel->setText(routeCountLabel->text().append(" (" + tr("Subscription") + ":" + conf.subscriptionName + ")")); + //} + // + //// Get Connection info + //auto host_port = MWGetConnectionInfo(fullIdentifier.IdentifierString()); + //_hostLabel->setText(get<0>(host_port)); + //_portLabel->setText(QSTRN(get<1>(host_port))); + //_OutBoundTypeLabel->setText(get<2>(host_port)); +} + +ConnectionInfoWidget::~ConnectionInfoWidget() +{ +} + +void ConnectionInfoWidget::on_connectBtn_clicked() +{ +} + +void ConnectionInfoWidget::on_editBtn_clicked() +{ +} + +void ConnectionInfoWidget::on_editJsonBtn_clicked() +{ +} + +void ConnectionInfoWidget::on_pushButton_clicked() +{ + QGuiApplication::clipboard()->setText(shareLinkTxt->text()); +} diff --git a/src/ui/widgets/ConnectionInfoWidget.hpp b/src/ui/widgets/ConnectionInfoWidget.hpp new file mode 100644 index 00000000..499934ff --- /dev/null +++ b/src/ui/widgets/ConnectionInfoWidget.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include +#include "ui_ConnectionInfoWidget.h" +#include "core/handler/ConnectionHandler.hpp" + +class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget +{ + Q_OBJECT + + public: + explicit ConnectionInfoWidget(QWidget *parent = nullptr); + void ShowConnectionDetails(const ConnectionIdentifier &_identifier); + ~ConnectionInfoWidget(); + private slots: + void on_connectBtn_clicked(); + void on_editBtn_clicked(); + void on_editJsonBtn_clicked(); + void on_pushButton_clicked(); + + private: + ConnectionIdentifier identifier; +}; + diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui new file mode 100644 index 00000000..165155d9 --- /dev/null +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -0,0 +1,236 @@ + + + ConnectionInfoWidget + + + + 0 + 0 + 440 + 250 + + + + Form + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 150 + 150 + + + + QFrame::Box + + + TextLabel + + + true + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + Group + + + + + + + IBeamCursor + + + type + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Protocol + + + + + + + IBeamCursor + + + proto + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Address + + + + + + + IBeamCursor + + + addr + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Port Number + + + + + + + IBeamCursor + + + port + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + 11 + + + + Connection Name + + + + + + + + + Connect + + + + + + + Edit + + + + + + + Edit JSON + + + + + + + + + + + Share Link + + + + + + + true + + + + + + + Copy + + + + + + + + + Qt::Horizontal + + + + + + + + diff --git a/src/ui/widgets/ConnectionWidget.cpp b/src/ui/widgets/ConnectionWidget.cpp index 16f1482f..d71400c9 100644 --- a/src/ui/widgets/ConnectionWidget.cpp +++ b/src/ui/widgets/ConnectionWidget.cpp @@ -1 +1,68 @@ #include "ConnectionWidget.hpp" + +ConnectionWidget::ConnectionWidget(QWidget *parent) : QWidget(parent), groupId("null"), subscriptionId("null") +{ + setupUi(this); + connect(ConnectionHandler, &QvConnectionHandler::OnConnected, this, &ConnectionWidget::OnConnected); +} + +ConnectionWidget::ConnectionWidget(const ConnectionIdentifier &identifier, QWidget *parent): ConnectionWidget(parent) +{ + auto connection = ConnectionHandler->GetConnection(identifier.connectionId); + connectionIdentifier = identifier; + groupId = identifier.groupId; + subscriptionId = identifier.subscriptionId; + itemType = NODE_ITEM; + rawDisplayName = connection.displayName; + connNameLabel->setText(rawDisplayName); + latencyLabel->setText(tr("Latency: ") + QSTRN(connection.latency) + " " + tr("ms")); +} + +// ======================================= Initialisation for root nodes. +ConnectionWidget::ConnectionWidget(const GroupId &id, QWidget *parent) : ConnectionWidget(parent) +{ + groupId = id; + itemType = GROUP_HEADER_ITEM; + InitialiseForGroup(ConnectionHandler->GetGroup(id).displayName, ConnectionHandler->Connections(id).count()); +} + +ConnectionWidget::ConnectionWidget(const SubscriptionId &id, QWidget *parent) : ConnectionWidget(parent) +{ + subscriptionId = id; + itemType = SUBS_HEADER_ITEM; + InitialiseForGroup(ConnectionHandler->GetSubscription(id).displayName, ConnectionHandler->Connections(id).count()); +} + +void ConnectionWidget::InitialiseForGroup(const QString &displayName, int connectionCount) +{ + rawDisplayName = displayName; + connNameLabel->setText(rawDisplayName); + latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections"))); + // + layout()->removeWidget(connTypeLabel); + layout()->removeWidget(dataLabel); + delete connTypeLabel; + delete dataLabel; +} + +void ConnectionWidget::BeginConnection() +{ + if (itemType == NODE_ITEM) { + ConnectionHandler->StartConnection(connectionIdentifier); + } else { + LOG(MODULE_UI, "Trying to start a non-connection entry, this call is illegal.") + } +} + +void ConnectionWidget::OnConnected(const ConnectionId &id) +{ + if (id == connectionIdentifier.connectionId) { + LOG(MODULE_UI, "OnConnected signal received for: " + id.toString()) + emit RequestWidgetFocus(this); + } +} + +ConnectionWidget::~ConnectionWidget() +{ + // +} diff --git a/src/ui/widgets/ConnectionWidget.hpp b/src/ui/widgets/ConnectionWidget.hpp index 14ede824..0498e244 100644 --- a/src/ui/widgets/ConnectionWidget.hpp +++ b/src/ui/widgets/ConnectionWidget.hpp @@ -4,10 +4,10 @@ #include "ui_ConnectionWidget.h" #include "core/handler/ConnectionHandler.hpp" -enum CONNECTION_ITEM_TYPE { - INVALID, - GROUP, - SUBSCRIPTION +enum ITEM_TYPE { + GROUP_HEADER_ITEM, + SUBS_HEADER_ITEM, + NODE_ITEM }; class ConnectionWidget : public QWidget, private Ui::ConnectionWidget @@ -16,88 +16,51 @@ class ConnectionWidget : public QWidget, private Ui::ConnectionWidget public: // // ======================================= Initialisation for connection nodes. - // - explicit ConnectionWidget(const GroupId &group, const ConnectionId &id, QWidget *parent = nullptr): ConnectionWidget(parent) - { - type = GROUP; - connectionId = id; - groupId = group; - InitialiseForConnection(id); - } - explicit ConnectionWidget(const SubscriptionId &group, const ConnectionId &id, QWidget *parent = nullptr): ConnectionWidget(parent) - { - type = SUBSCRIPTION; - connectionId = id; - subscriptionId = group; - InitialiseForConnection(id); - } + explicit ConnectionWidget(const ConnectionIdentifier &identifier, QWidget *parent = nullptr); // // ======================================= Initialisation for root nodes. + explicit ConnectionWidget(const GroupId &id, QWidget *parent = nullptr); + explicit ConnectionWidget(const SubscriptionId &id, QWidget *parent = nullptr); // - explicit ConnectionWidget(const GroupId &id, QWidget *parent = nullptr) : ConnectionWidget(parent) + void BeginConnection(); + ~ConnectionWidget(); + // + inline bool NameMatched(const QString &arg) { - type = INVALID; - groupId = id; - InitialiseForGroup(ConnectionHandler->GetGroup(id).displayName, ConnectionHandler->Connections(id).count()); - } - explicit ConnectionWidget(const SubscriptionId &id, QWidget *parent = nullptr) : ConnectionWidget(parent) - { - type = INVALID; - subscriptionId = id; - InitialiseForGroup(ConnectionHandler->GetSubscription(id).displayName, ConnectionHandler->Connections(id).count()); - } - inline bool IsConnection() const - { - return isConnectionItem; - } - void BeginConnection() - { - if (isConnectionItem) { - if (type == GROUP) { - ConnectionHandler->StartConnection(groupId, connectionId); - } else if (type == SUBSCRIPTION) { - ConnectionHandler->StartConnection(subscriptionId, connectionId); - } else { - LOG(MODULE_UI, "Trying to start an INVALID non-connection entry, this call is illegal.") - } + auto searchString = arg.toLower(); + auto matchHeader = [&](const QString & arg1) { + return itemType == SUBS_HEADER_ITEM + ? ConnectionHandler->GetSubscription(subscriptionId).displayName.toLower().contains(arg1) + : ConnectionHandler->GetGroup(groupId).displayName.toLower().contains(arg1); + }; + + if (itemType != NODE_ITEM) { + return matchHeader(searchString); } else { - LOG(MODULE_UI, "Trying to start a non-connection entry, this call is illegal.") + return matchHeader(searchString) || ConnectionHandler->GetConnection(connectionIdentifier.connectionId).displayName.toLower().contains(searchString); } } - ~ConnectionWidget() + inline const ConnectionIdentifier Identifier() const { - // + return connectionIdentifier; } - + // + inline bool IsConnection() const + { + return itemType == NODE_ITEM; + } + signals: + void RequestWidgetFocus(const ConnectionWidget *me); + private slots: + void OnConnected(const ConnectionId &id); private: - ConnectionWidget(QWidget *parent = nullptr) : QWidget(parent), connectionId("null"), groupId("null"), subscriptionId("null") - { - setupUi(this); - } - void InitialiseForConnection(const ConnectionId &id) - { - isConnectionItem = true; - auto connection = ConnectionHandler->GetConnection(id); - rawDisplayName = connection.displayName; - connNameLabel->setText(rawDisplayName); - latencyLabel->setText(tr("Latency: ") + QSTRN(connection.latency) + " " + tr("ms")); - } - void InitialiseForGroup(const QString &displayName, int connectionCount) - { - rawDisplayName = displayName; - connNameLabel->setText(rawDisplayName); - latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections"))); - // - layout()->removeWidget(connTypeLabel); - delete connTypeLabel; - layout()->removeWidget(dataLabel); - delete dataLabel; - } - CONNECTION_ITEM_TYPE type; - bool isConnectionItem = false; + explicit ConnectionWidget(QWidget *parent = nullptr); + void InitialiseForGroup(const QString &displayName, int connectionCount); QString rawDisplayName; // - ConnectionId connectionId; + ITEM_TYPE itemType; + // + ConnectionIdentifier connectionIdentifier; GroupId groupId; SubscriptionId subscriptionId; From f917592818e5f9da449876c276ac1b3fff9c598b Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 20 Feb 2020 09:31:31 +0800 Subject: [PATCH 021/332] drop Qt 5.12 support --- .github/workflows/build-qv2ray.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray.yml b/.github/workflows/build-qv2ray.yml index 0869f26d..6d77a24b 100644 --- a/.github/workflows/build-qv2ray.yml +++ b/.github/workflows/build-qv2ray.yml @@ -9,7 +9,7 @@ jobs: build: strategy: matrix: - qt_version: [5.12.6, 5.13.2, 5.14.1] + qt_version: [5.13.2, 5.14.1] platform: [ubuntu-16.04, macos-latest, windows-latest] arch: [x86, x64] exclude: From 3c023ba02283b0fa4c5fd8bce0c8eff718c1c761 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 20 Feb 2020 23:05:35 +0800 Subject: [PATCH 022/332] wip: add: ... --- src/base/models/QvConfigIdentifier.hpp | 24 +-- src/base/models/QvConfigModel.hpp | 6 +- src/common/QvHelpers.cpp | 2 +- src/common/QvHelpers.hpp | 6 +- src/components/speedchart/speedplotview.cpp | 21 +-- src/components/tcping/QvTCPing.cpp | 2 +- src/components/tcping/QvTCPing.hpp | 4 +- src/core/CoreSafeTypes.hpp | 63 ++++++- src/core/config/ConfigUpgrade.cpp | 2 +- src/core/connection/ConnectionIO.cpp | 20 +-- src/core/connection/ConnectionIO.hpp | 13 -- src/core/handler/ConnectionHandler.cpp | 173 +++++++++----------- src/core/handler/ConnectionHandler.hpp | 69 +++----- src/core/handler/V2rayInstanceHandler.cpp | 2 +- src/ui/w_MainWindow.cpp | 26 +-- src/ui/w_MainWindow.hpp | 2 + src/ui/w_SubscriptionManager.cpp | 4 +- src/ui/w_SubscriptionManager.hpp | 4 +- src/ui/widgets/ConnectionInfoWidget.cpp | 21 ++- src/ui/widgets/ConnectionInfoWidget.hpp | 5 +- src/ui/widgets/ConnectionWidget.cpp | 41 ++--- src/ui/widgets/ConnectionWidget.hpp | 32 +--- src/ui/widgets/ConnectionWidget.ui | 4 +- 23 files changed, 252 insertions(+), 294 deletions(-) diff --git a/src/base/models/QvConfigIdentifier.hpp b/src/base/models/QvConfigIdentifier.hpp index c2254aad..a7d3d428 100644 --- a/src/base/models/QvConfigIdentifier.hpp +++ b/src/base/models/QvConfigIdentifier.hpp @@ -6,33 +6,37 @@ namespace Qv2ray::base { using namespace std::chrono; // Common struct for Groups and Subscriptions - struct _QvGroupObjectBase { + struct GroupObjectBase { QString displayName; QList connections; - _QvGroupObjectBase(): displayName(), connections() { } + int64_t importDate; + GroupObjectBase(): displayName(), connections(), importDate() { } }; - struct GroupObject : _QvGroupObjectBase { - GroupObject() { } - XTOSTRUCT(O(displayName, connections)) + struct GroupObject_Config : GroupObjectBase { + GroupObject_Config() { } + XTOSTRUCT(O(displayName, connections, importDate)) }; - struct SubscriptionObject : _QvGroupObjectBase { + struct SubscriptionObject_Config : GroupObjectBase { + // QString address; int64_t lastUpdated; float updateInterval; - SubscriptionObject(): address(""), lastUpdated(system_clock::to_time_t(system_clock::now())), updateInterval(10) { } - XTOSTRUCT(O(lastUpdated, updateInterval, address, connections, displayName)) + SubscriptionObject_Config(): address(""), lastUpdated(system_clock::to_time_t(system_clock::now())), updateInterval(10) { } + XTOSTRUCT(O(lastUpdated, updateInterval, address, connections, displayName, importDate)) }; - struct ConnectionObject { + struct ConnectionObject_Config { QString displayName; int64_t importDate; int64_t lastConnected; int64_t latency; int64_t upLinkData; int64_t downLinkData; - ConnectionObject(): displayName(), importDate(system_clock::to_time_t(system_clock::now())), lastConnected(), latency(0), upLinkData(0), downLinkData(0) { } + ConnectionObject_Config(): displayName(), importDate(system_clock::to_time_t(system_clock::now())), lastConnected(), latency(0), upLinkData(0), downLinkData(0) { } XTOSTRUCT(O(displayName, importDate, lastConnected, latency, upLinkData, downLinkData)) }; } + +using namespace Qv2ray::base; diff --git a/src/base/models/QvConfigModel.hpp b/src/base/models/QvConfigModel.hpp index 7bd3c10d..7ca44201 100644 --- a/src/base/models/QvConfigModel.hpp +++ b/src/base/models/QvConfigModel.hpp @@ -118,10 +118,10 @@ namespace Qv2ray::base::config QString autoStartId; // // Key = groupId, connectionId, subscriptionId - QMap groups; - QMap subscriptions; + QMap groups; + QMap subscriptions; /// Connections are used privately. - QMap connections; + QMap connections; // Qv2rayUIConfig uiConfig; Qv2rayAPIConfig apiConfig; diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 978ad07a..05728876 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -147,7 +147,7 @@ namespace Qv2ray::common dblByte = bytes / 1024.0; sprintf(str, "%.2f", dblByte); - return strcat(strcat(str, " "), sizes[i]); + return QString(str) + " " + QString(sizes[i]); } bool IsValidFileName(const QString &fileName) diff --git a/src/common/QvHelpers.hpp b/src/common/QvHelpers.hpp index e00ddb44..55d4372e 100644 --- a/src/common/QvHelpers.hpp +++ b/src/common/QvHelpers.hpp @@ -64,11 +64,10 @@ namespace Qv2ray::common return JsonFromString(json); } - namespace validation { - static QRegularExpression __regex_ipv4_full(REGEX_IPV4_ADDR "$"); - static QRegularExpression __regex_ipv6_full(REGEX_IPV6_ADDR "$"); + const inline QRegularExpression __regex_ipv4_full(REGEX_IPV4_ADDR "$"); + const inline QRegularExpression __regex_ipv6_full(REGEX_IPV6_ADDR "$"); inline bool IsIPv4Address(const QString &addr) { @@ -86,7 +85,6 @@ namespace Qv2ray::common } } - inline QString timeToString(const time_t &t) { auto _tm = std::localtime(&t); diff --git a/src/components/speedchart/speedplotview.cpp b/src/components/speedchart/speedplotview.cpp index 79faaa3e..07a70bb6 100644 --- a/src/components/speedchart/speedplotview.cpp +++ b/src/components/speedchart/speedplotview.cpp @@ -106,23 +106,6 @@ qlonglong sizeInBytes(qreal size, const SizeUnit unit) return size; } -template -constexpr typename std::add_const::type &asConst(T &t) noexcept -{ - return t; -} - -// Forward rvalue as const -template -constexpr typename std::add_const::type asConst(T &&t) noexcept -{ - return std::move(t); -} - -// Prevent const rvalue arguments -template -void asConst(const T &&) = delete; - namespace { // table of supposed nice steps for grid marks to get nice looking quarters of scale @@ -317,7 +300,7 @@ void SpeedPlotView::paintEvent(QPaintEvent *) double legendHeight = 0; int legendWidth = 0; - for (const auto &property : asConst(m_properties)) { + for (const auto &property : m_properties) { if (fontMetrics.horizontalAdvance(property.name) > legendWidth) legendWidth = fontMetrics.horizontalAdvance(property.name); @@ -330,7 +313,7 @@ void SpeedPlotView::paintEvent(QPaintEvent *) painter.fillRect(legendBackgroundRect, legendBackgroundColor); i = 0; - for (const auto &property : asConst(m_properties)) { + for (const auto &property : m_properties) { int nameSize = fontMetrics.horizontalAdvance(property.name); double indent = 1.5 * (i++) * fontMetrics.height(); painter.setPen(property.pen); diff --git a/src/components/tcping/QvTCPing.cpp b/src/components/tcping/QvTCPing.cpp index 6ed5344b..41a5711b 100644 --- a/src/components/tcping/QvTCPing.cpp +++ b/src/components/tcping/QvTCPing.cpp @@ -27,7 +27,7 @@ namespace Qv2ray::components::tcping worker->cancel(); } } - void QvTCPingModel::StartPing(const ConnectionObject &connectionName, const QString &hostName, int port) + void QvTCPingModel::StartPing(const ConnectionObject_Config &connectionName, const QString &hostName, int port) { QvTCPingData data; data.hostName = hostName; diff --git a/src/components/tcping/QvTCPing.hpp b/src/components/tcping/QvTCPing.hpp index 5e08308a..d3fe6ffd 100644 --- a/src/components/tcping/QvTCPing.hpp +++ b/src/components/tcping/QvTCPing.hpp @@ -5,7 +5,7 @@ namespace Qv2ray::components::tcping { struct QvTCPingData { - ConnectionObject connectionIdentifier; + ConnectionObject_Config connectionIdentifier; QString hostName; int port; QString errorMessage; @@ -19,7 +19,7 @@ namespace Qv2ray::components::tcping public: explicit QvTCPingModel(int defaultCount = 5, QObject *parent = nullptr); - void StartPing(const ConnectionObject &connectionName, const QString &hostName, int port); + void StartPing(const ConnectionObject_Config &connectionName, const QString &hostName, int port); void StopAllPing(); signals: void PingFinished(QvTCPingData data); diff --git a/src/core/CoreSafeTypes.hpp b/src/core/CoreSafeTypes.hpp index 2ce6329b..bcdb9916 100644 --- a/src/core/CoreSafeTypes.hpp +++ b/src/core/CoreSafeTypes.hpp @@ -4,6 +4,8 @@ #include #include +#include "base/models/QvConfigIdentifier.hpp" + namespace Qv2ray::core { template @@ -27,17 +29,72 @@ namespace Qv2ray::core QString m_id; }; + template + QList StringsToIdList(const QList &strings) + { + QList list; + + for (auto str : strings) { + list << IDType(str); + } + + return list; + } + template uint qHash(const IDType &key, uint seed = 0) { return key.qHash(seed); } - // + + // Define several safetypes to prevent misuse of QString. class __QvGroup; class __QvConnection; - class __QvSubscription; typedef IDType<__QvGroup> GroupId; typedef IDType<__QvConnection> ConnectionId; - typedef IDType<__QvSubscription> SubscriptionId; + // + /// Metadata object representing a connection. + struct ConnectionMetaObject : ConnectionObject_Config { + GroupId groupId; + ConnectionMetaObject(): ConnectionObject_Config(), groupId("null") { } + // Suger for down casting. + ConnectionMetaObject(const ConnectionObject_Config &base) : ConnectionMetaObject() + { + this->latency = base.latency; + this->lastConnected = base.lastConnected; + this->importDate = base.lastConnected; + this->upLinkData = base.upLinkData; + this->downLinkData = base.downLinkData; + this->displayName = base.displayName; + } + }; + + /// Metadata object representing a group. + struct GroupMetaObject: SubscriptionObject_Config { + // Implicit base of two types, since group object is actually the group base object. + bool isSubscription; + QList connections; + // Suger for down casting. + GroupMetaObject(): connections() {} + GroupMetaObject(const GroupObjectBase &base): GroupMetaObject() + { + this->displayName = base.displayName; + this->importDate = base.importDate; + this->connections = StringsToIdList(base.connections); + } + // Suger for down casting. + GroupMetaObject(const GroupObject_Config &base): GroupMetaObject((GroupObjectBase)base) + { + this->isSubscription = false; + } + // Suger for down casting. + GroupMetaObject(const SubscriptionObject_Config &base): GroupMetaObject((GroupObjectBase)base) + { + this->isSubscription = true; + this->address = base.address; + this->lastUpdated = base.lastUpdated; + this->updateInterval = base.updateInterval; + } + }; } using namespace Qv2ray::core; diff --git a/src/core/config/ConfigUpgrade.cpp b/src/core/config/ConfigUpgrade.cpp index dc80017f..c6fbc0b1 100644 --- a/src/core/config/ConfigUpgrade.cpp +++ b/src/core/config/ConfigUpgrade.cpp @@ -74,7 +74,7 @@ namespace Qv2ray for (auto item = subs.begin(); item != subs.end(); item++) { auto key = item.key(); - SubscriptionObject _conf; + SubscriptionObject_Config _conf; _conf.address = item.value().toString(); _conf.lastUpdated = system_clock::to_time_t(system_clock::now()); _conf.updateInterval = 5; diff --git a/src/core/connection/ConnectionIO.cpp b/src/core/connection/ConnectionIO.cpp index 10a02431..38c82518 100644 --- a/src/core/connection/ConnectionIO.cpp +++ b/src/core/connection/ConnectionIO.cpp @@ -5,27 +5,15 @@ namespace Qv2ray::core::connection { namespace ConnectionIO { - CONFIGROOT ReadConnectionInternal(const QString &connection) - { - QString jsonString = StringFromFile(connection); - auto conf = CONFIGROOT(JsonFromString(jsonString)); - - if (conf.count() == 0) { - LOG(MODULE_SETTINGS, "WARN: Possible file corruption, failed to load file: " + connection + " --> File might be empty.") - } - - return conf; - } CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id) { - return ReadConnectionInternal(QV2RAY_CONNECTIONS_DIR + group.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION); } - CONFIGROOT GetConnectionRoot(const SubscriptionId &subscription, const ConnectionId &id) - { - return ReadConnectionInternal(QV2RAY_SUBSCRIPTION_DIR + subscription.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION); - } + //CONFIGROOT GetConnectionRoot(const SubscriptionId &subscription, const ConnectionId &id) + //{ + // return ReadConnectionInternal(QV2RAY_SUBSCRIPTION_DIR + subscription.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION); + //} //// //// Save Connection to a place, with checking if there's existing file. diff --git a/src/core/connection/ConnectionIO.hpp b/src/core/connection/ConnectionIO.hpp index 9bb47f18..010f45fd 100644 --- a/src/core/connection/ConnectionIO.hpp +++ b/src/core/connection/ConnectionIO.hpp @@ -5,19 +5,6 @@ namespace Qv2ray::core::connection { namespace ConnectionIO { - CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id); - CONFIGROOT GetConnectionRoot(const SubscriptionId &subscription, const ConnectionId &id); - // - // Save Connection Config - bool SaveConnectionConfig(CONFIGROOT obj, const ConnectionId &id, bool canOverrideExisting); - bool SaveSubscriptionConfig(CONFIGROOT obj, const SubscriptionId &subscription, const ConnectionId &name); - // - bool RemoveConnection(const SubscriptionId &id); - bool RemoveSubscriptionConnection(const SubscriptionId &id, const ConnectionId &name); - // - bool RenameConnection(const ConnectionId &id, const QString &newName); - bool RenameSubscription(const SubscriptionId &id, const QString &newName); - // File Protocol CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool importComplex); } diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index 49a984c9..9d05346c 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -1,55 +1,8 @@ #include "ConnectionHandler.hpp" +#include "common/QvHelpers.hpp" + namespace Qv2ray::core::handlers { - template - QList StringsToIdList(const QList &strings) - { - QList list; - - for (auto str : strings) { - list << IDType(str); - } - - return list; - } - - const QList QvConnectionHandler::IdentifierList(const SubscriptionId &subsId, const QList &idList) const - { - QList list; - - for (auto groupConnection : idList) { - auto connId = ConnectionId(groupConnection); - - if (connections.keys().contains(connId)) { - ConnectionIdentifier x; - x.isSubscription = true; - x.connectionId = connId; - x.subscriptionId = subsId; - list.push_back(x); - } - } - - return list; - } - - const QList QvConnectionHandler::IdentifierList(const GroupId &groupId, const QList &idList) const - { - QList list; - - for (auto groupConnection : idList) { - auto connId = ConnectionId(groupConnection); - - if (connections.keys().contains(connId)) { - ConnectionIdentifier x; - x.isSubscription = false; - x.connectionId = connId; - x.groupId = groupId; - list.push_back(x); - } - } - - return list; - } QvConnectionHandler::QvConnectionHandler() { @@ -57,60 +10,59 @@ namespace Qv2ray::core::handlers // Do we need to check how many of them are loaded? for (auto i = 0; i < GlobalConfig.connections.count(); i++) { - connections[ConnectionId(GlobalConfig.connections.keys()[i])] = GlobalConfig.connections.values()[i]; + connections[GlobalConfig.connections.keys()[i]] = GlobalConfig.connections.values()[i]; } - for (auto i = 0; i < GlobalConfig.subscriptions.count(); i++) { - subscriptions[SubscriptionId(GlobalConfig.subscriptions.keys()[i])] = GlobalConfig.subscriptions.values()[i]; + for (auto key : GlobalConfig.subscriptions.keys()) { + auto val = GlobalConfig.subscriptions[key]; + groups[key] = val; + + for (auto conn : val.connections) { + connections[conn].groupId = key; + } } - for (auto i = 0; i < GlobalConfig.groups.count(); i++) { - groups[GroupId(GlobalConfig.groups.keys()[i])] = GlobalConfig.groups.values()[i]; + for (auto key : GlobalConfig.groups.keys()) { + auto val = GlobalConfig.groups[key]; + groups[key] = val; + + for (auto conn : val.connections) { + connections[conn].groupId = key; + } } kernelInstance = new V2rayKernelInstance(); saveTimerId = startTimer(60000); } - const QList QvConnectionHandler::Connections() const + const QList QvConnectionHandler::Connections() const { - QList list; - - for (auto i = 0; i < groups.count(); i++) { - auto key = groups.keys()[i]; - auto group = groups[key]; - list.append(IdentifierList(key, StringsToIdList(group.connections))); - } - - for (auto i = 0; i < subscriptions.count(); i++) { - auto key = subscriptions.keys()[i]; - auto subs = subscriptions[key]; - list.append(IdentifierList(key, StringsToIdList(subs.connections))); - } - - return list; + return connections.keys(); } - const QList QvConnectionHandler::Groups() const + const QList QvConnectionHandler::AllGroups() const { return groups.keys(); } - const QList QvConnectionHandler::Subscriptions() const + const QList QvConnectionHandler::Subscriptions() const { - return subscriptions.keys(); + QList subsList; + + for (auto group : groups.keys()) { + if (groups[group].isSubscription) { + subsList.push_back(group); + } + } + + return subsList; } - const QList QvConnectionHandler::Connections(const GroupId &groupId) const + const QList QvConnectionHandler::Connections(const GroupId &groupId) const { - return IdentifierList(groupId, StringsToIdList(groups[groupId].connections)); + return groups[groupId].connections; } - const QList QvConnectionHandler::Connections(const SubscriptionId &subscriptionId) const - { - return IdentifierList(subscriptionId, StringsToIdList(subscriptions[subscriptionId].connections)); - } - - const ConnectionObject &QvConnectionHandler::GetConnection(const ConnectionId &id) + const ConnectionMetaObject QvConnectionHandler::GetConnection(const ConnectionId &id) const { if (!connections.contains(id)) { LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); @@ -119,29 +71,57 @@ namespace Qv2ray::core::handlers return connections[id]; } - const optional QvConnectionHandler::StartConnection(const ConnectionIdentifier &identifier) + const optional QvConnectionHandler::StartConnection(const ConnectionId &identifier) { - if (!connections.contains(identifier.connectionId)) { + if (!connections.contains(identifier)) { return tr("No connection selected!") + NEWLINE + tr("Please select a config from the list."); } - CONFIGROOT root = identifier.isSubscription - ? GetConnectionRoot(identifier.subscriptionId, identifier.connectionId) - : GetConnectionRoot(identifier.groupId, identifier.connectionId); - return _CHTryStartConnection_p(identifier.connectionId, root); + CONFIGROOT root = CHGetConnectionRoot_p(connections[identifier].groupId, identifier); + return CHTryStartConnection_p(identifier, root); } - const GroupObject &QvConnectionHandler::GetGroup(const GroupId &id) + const QString QvConnectionHandler:: GetConnectionBasicInfo(const ConnectionId &id) const + { + QString result; + + if (!connections.contains(id)) { + result = tr("N/A"); + } + + CONFIGROOT root = CHGetConnectionRoot_p(connections[id].groupId, id); + bool isTLSEnabled = false; + + if (root.contains("inbounds") && !root["inbounds"].toArray().isEmpty()) { + QString inProtocol = tr("Inbounds: "); + + for (auto inbound : root["inbounds"].toArray()) { + inProtocol.append(inbound.toObject()["protocol"].toString()); + inProtocol.append("/"); + } + + inProtocol.chop(1); + result.append(inProtocol); + } + + QStringList protocols; + QStringList streamProtocols; + + for (auto outbound : root["outbounds"].toArray()) { + protocols.append(outbound.toObject()["protocol"].toString()); + } + + result.chop(1); + return result; + } + + + const GroupMetaObject QvConnectionHandler::GetGroup(const GroupId &id) const { return groups[id]; } - const SubscriptionObject &QvConnectionHandler::GetSubscription(const SubscriptionId &id) - { - return subscriptions[id]; - } - QvConnectionHandler::~QvConnectionHandler() { if (kernelInstance->KernelStarted) { @@ -151,4 +131,11 @@ namespace Qv2ray::core::handlers delete kernelInstance; } + + const CONFIGROOT QvConnectionHandler::CHGetConnectionRoot_p(const GroupId &group, const ConnectionId &id) const + { + auto path = QV2RAY_CONNECTIONS_DIR + group.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; + path.prepend(groups[group].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR); + return CONFIGROOT(JsonFromString(StringFromFile(path))); + } } diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index a7eaa820..7f864dfa 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -7,17 +7,6 @@ namespace Qv2ray::core::handlers { - - struct ConnectionIdentifier { - bool isConnection; - bool isSubscription; - ConnectionId connectionId; - GroupId groupId; - SubscriptionId subscriptionId; - // - ConnectionIdentifier() : isSubscription(false), connectionId("null"), groupId("null"), subscriptionId("null") { } - }; - class QvConnectionHandler : public QObject { Q_OBJECT @@ -25,22 +14,22 @@ namespace Qv2ray::core::handlers explicit QvConnectionHandler(); ~QvConnectionHandler(); // - const QList Connections() const; + const QList Connections() const; // - const QList Groups() const; - const QList Subscriptions() const; - const QList Connections(const GroupId &groupId) const; - const QList Connections(const SubscriptionId &subscriptionId) const; + const QList AllGroups() const; + const QList Subscriptions() const; + const QList Connections(const GroupId &groupId) const; // - bool IsConnectionConnected(const ConnectionId &id); + bool IsConnectionConnected(const ConnectionId &id) const; // const optional StopConnection(const ConnectionId &id); - const optional StartConnection(const ConnectionIdentifier &identifier); + const optional StartConnection(const ConnectionId &identifier); // public: // // Connection Operations. - const ConnectionObject &GetConnection(const ConnectionId &id); + const QString GetConnectionBasicInfo(const ConnectionId &id) const; + const ConnectionMetaObject GetConnection(const ConnectionId &id) const; const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); const optional DeleteConnection(const ConnectionId &id); const optional UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); @@ -51,28 +40,27 @@ namespace Qv2ray::core::handlers // Misc Connection Operations const optional TestLatency(const ConnectionId &id); const optional TestLatency(const GroupId &id); - const optional TestLatency(const SubscriptionId &id); - const optional TestAllLatency(); + const optional TestLatency(); // // Group Operations - const GroupObject &GetGroup(const GroupId &id); - const GroupId &CreateGroup(const QString displayName); + const GroupMetaObject GetGroup(const GroupId &id) const; + const GroupId &CreateGroup(const QString displayName, bool isSubscription); const optional DeleteGroup(const GroupId &id); const optional DuplicateGroup(const GroupId &id); const optional RenameGroup(const GroupId &id, const QString &newName); // // Subscriptions - const SubscriptionObject &GetSubscription(const SubscriptionId &id); - const SubscriptionId &CreateSubscription(const QString &displayName, const QString &address); - const optional RenameSubscription(const SubscriptionId &id, const QString &newName); - const optional DeleteSubscription(const SubscriptionId &id); - const optional UpdateSubscription(const SubscriptionId &id); - const optional UpdateSubscriptionASync(const SubscriptionId &id); + const GroupId &CreateSubscription(const QString &displayName, const QString &address); + const optional RenameSubscription(const GroupId &id, const QString &newName); + const optional DeleteSubscription(const GroupId &id); + const optional UpdateSubscription(const GroupId &id); + const optional UpdateSubscriptionASync(const GroupId &id); signals: // void OnConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id); + void OnNewConnectionStatsAvaliable(const ConnectionId &id, uint64_t totalUpload, uint64_t totalDownload); // void OnConnectionCreated(const ConnectionId &id, const QString &displayName); void OnConnectionRenamed(const ConnectionId &id, const QString &originalName, const QString &newName); @@ -86,26 +74,23 @@ namespace Qv2ray::core::handlers void OnGroupRenamed(const GroupId &id, const QString &oldName, const QString &newName); void OnGroupDeleted(const GroupId &id, const QString &displayName); // - void OnSubscriptionCreated(const SubscriptionId &id, const QString &displayName, const QString &address); - void OnSubscriptionDeleted(const SubscriptionId &id); - void OnSubscriptionRenamed(const SubscriptionId &id, const QString &oldName, const QString &newName); - void OnSubscriptionUpdateFinished(const SubscriptionId &id); + void OnSubscriptionCreated(const GroupId &id, const QString &displayName, const QString &address); + void OnSubscriptionDeleted(const GroupId &id, const QString &oldName, const QString &newName); + void OnSubscriptionUpdateFinished(const GroupId &id); private: - int saveTimerId; - QHash groups; - QHash connections; - QHash subscriptions; + optional CHTryStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); + const CONFIGROOT CHGetConnectionRoot_p(const GroupId &group, const ConnectionId &id) const; + bool CHSaveConnectionConfig(CONFIGROOT obj, const ConnectionId &id, bool override); // // We only support one cuncurrent connection currently. //QHash kernelInstances; V2rayKernelInstance *kernelInstance = nullptr; - // - optional _CHTryStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); - const QList IdentifierList(const GroupId &groupId, const QList &idList) const; - const QList IdentifierList(const SubscriptionId &groupId, const QList &idList) const; + int saveTimerId; + QHash groups; + QHash connections; }; - // + inline QvConnectionHandler *ConnectionHandler = nullptr; } diff --git a/src/core/handler/V2rayInstanceHandler.cpp b/src/core/handler/V2rayInstanceHandler.cpp index 7c50c151..e1786d86 100644 --- a/src/core/handler/V2rayInstanceHandler.cpp +++ b/src/core/handler/V2rayInstanceHandler.cpp @@ -1,7 +1,7 @@ #include "ConnectionHandler.hpp" #include "core/connection/Generation.hpp" -optional QvConnectionHandler::_CHTryStartConnection_p(const ConnectionId &id, const CONFIGROOT &root) +optional QvConnectionHandler::CHTryStartConnection_p(const ConnectionId &id, const CONFIGROOT &root) { auto &connectionMeta = connections[id]; auto fullConfig = GenerateRuntimeConfig(root); diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 41581bc7..27a250e0 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -214,8 +214,10 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr //if (!vinstance->KernelStarted) { // this->show(); //} +#ifndef DISABLE_AUTO_UPDATE connect(requestHelper, &QvHttpRequestHelper::httpRequestFinished, this, &MainWindow::VersionUpdate); requestHelper->get("https://api.github.com/repos/Qv2ray/Qv2ray/releases/latest"); +#endif if (StartupOption.enableToolbarPlguin) { LOG(MODULE_UI, "Plugin daemon is enabled.") @@ -279,6 +281,8 @@ void MainWindow::on_action_StartThis_triggered() //CurrentConnectionIdentifier = ItemConnectionIdentifier(CurrentSelectedItemPtr); //on_reconnectButton_clicked(); } + +#ifndef DISABLE_AUTO_UPDATE void MainWindow::VersionUpdate(QByteArray &data) { // Version update handler. @@ -312,11 +316,12 @@ void MainWindow::VersionUpdate(QByteArray &data) } } } +#endif void MainWindow::OnConfigListChanged(bool need_restart) { LOG(MODULE_UI, "Loading data...") - auto groups = ConnectionHandler->Groups(); + auto groups = ConnectionHandler->AllGroups(); for (auto group : groups) { auto groupItem = new QTreeWidgetItem(); @@ -333,23 +338,6 @@ void MainWindow::OnConfigListChanged(bool need_restart) } } - auto subscriptions = ConnectionHandler->Subscriptions(); - - for (auto subscription : subscriptions) { - auto subscriptionItem = new QTreeWidgetItem(); - connectionListWidget->addTopLevelItem(subscriptionItem); - connectionListWidget->setItemWidget(subscriptionItem, 0, new ConnectionWidget(subscription, connectionListWidget)); - auto connections = ConnectionHandler->Connections(subscription); - - for (auto connection : connections) { - auto connectionItem = new QTreeWidgetItem(); - subscriptionItem->addChild(connectionItem); - auto widget = new ConnectionWidget(connection, connectionListWidget); - connect(widget, &ConnectionWidget::RequestWidgetFocus, this, &MainWindow::onConnectionWidgetFocusRequested); - connectionListWidget->setItemWidget(connectionItem, 0, widget); - } - } - //auto wasRunning = vinstance->KernelStarted && need_restart; // //if (wasRunning) on_stopButton_clicked(); @@ -1071,5 +1059,5 @@ void MainWindow::on_connectionFilterTxt_textEdited(const QString &arg1) void MainWindow::on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column) { Q_UNUSED(column) - infoWidget->ShowConnectionDetails(GetItemWidget(item)->Identifier()); + infoWidget->ShowDetails(GetItemWidget(item)->Identifier()); } diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index b20cb239..3e4e1ee1 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -55,7 +55,9 @@ class MainWindow : public QMainWindow, Ui::MainWindow void on_subsButton_clicked(); // void ToggleVisibility(); +#ifndef DISABLE_AUTO_UPDATE void VersionUpdate(QByteArray &data); +#endif // void OnConnected(const ConnectionId &id); diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index dc1ca117..7db826a1 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -34,7 +34,7 @@ QPair SubscribeEditor::GetSelectedConfig() return currentSelectedConfig; } -void SubscribeEditor::LoadSubscriptionList(QMap list) +void SubscribeEditor::LoadSubscriptionList(QMap list) { subscriptionList->clear(); @@ -210,7 +210,7 @@ void SubscribeEditor::on_subscriptionList_currentRowChanged(int currentRow) void SubscribeEditor::SaveConfig() { - QMap newConf; + QMap newConf; for (auto _ : subscriptions.toStdMap()) { if (!_.second.address.isEmpty()) { diff --git a/src/ui/w_SubscriptionManager.hpp b/src/ui/w_SubscriptionManager.hpp index edd3df9e..e3443481 100644 --- a/src/ui/w_SubscriptionManager.hpp +++ b/src/ui/w_SubscriptionManager.hpp @@ -38,11 +38,11 @@ class SubscribeEditor : public QDialog, private Ui::w_SubscribeEditor private: void StartUpdateSubscription(const QString &subscriptionName); void SaveConfig(); - void LoadSubscriptionList(QMap list); + void LoadSubscriptionList(QMap list); bool isUpdateInProgress = false; QvHttpRequestHelper helper; QPair currentSelectedConfig; - QMap subscriptions; + QMap subscriptions; QString currentSubName; }; diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 4d8b5913..530ce965 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -1,21 +1,24 @@ #include "ConnectionInfoWidget.hpp" ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : - QWidget(parent) + QWidget(parent), connectionId("null"), groupId("null") { setupUi(this); } -void ConnectionInfoWidget::ShowConnectionDetails(const ConnectionIdentifier &_identifier) +void ConnectionInfoWidget::ShowDetails(const tuple &_identifier) { - identifier = _identifier; - auto data = ConnectionHandler->GetConnection(identifier.connectionId); - connNameLabel->setText(data.displayName); + groupId = get<0>(_identifier); + connectionId = get<1>(_identifier); + + if (connectionId.toString() != "null") { + connNameLabel->setText(ConnectionHandler->GetConnection(connectionId).displayName); + groupLabel->setText(ConnectionHandler->GetGroup(groupId).displayName); + } else { + connNameLabel->setText(ConnectionHandler->GetGroup(groupId).displayName); + } + // - auto groupname = identifier.isSubscription - ? ConnectionHandler->GetSubscription(identifier.subscriptionId).displayName - : ConnectionHandler->GetGroup(identifier.groupId).displayName; - groupLabel->setText(groupname); //auto isComplexConfig = IsComplexConfig(conf.config); //routeCountLabel->setText(isComplexConfig ? tr("Complex") : tr("Simple")); // diff --git a/src/ui/widgets/ConnectionInfoWidget.hpp b/src/ui/widgets/ConnectionInfoWidget.hpp index 499934ff..653bc465 100644 --- a/src/ui/widgets/ConnectionInfoWidget.hpp +++ b/src/ui/widgets/ConnectionInfoWidget.hpp @@ -10,7 +10,7 @@ class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget public: explicit ConnectionInfoWidget(QWidget *parent = nullptr); - void ShowConnectionDetails(const ConnectionIdentifier &_identifier); + void ShowDetails(const tuple &_identifier); ~ConnectionInfoWidget(); private slots: void on_connectBtn_clicked(); @@ -19,6 +19,7 @@ class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget void on_pushButton_clicked(); private: - ConnectionIdentifier identifier; + ConnectionId connectionId; + GroupId groupId; }; diff --git a/src/ui/widgets/ConnectionWidget.cpp b/src/ui/widgets/ConnectionWidget.cpp index d71400c9..6f1f0a6c 100644 --- a/src/ui/widgets/ConnectionWidget.cpp +++ b/src/ui/widgets/ConnectionWidget.cpp @@ -1,21 +1,22 @@ #include "ConnectionWidget.hpp" +#include "common/QvHelpers.hpp" -ConnectionWidget::ConnectionWidget(QWidget *parent) : QWidget(parent), groupId("null"), subscriptionId("null") +ConnectionWidget::ConnectionWidget(QWidget *parent) : QWidget(parent), connectionId("null"), groupId("null") { setupUi(this); connect(ConnectionHandler, &QvConnectionHandler::OnConnected, this, &ConnectionWidget::OnConnected); } -ConnectionWidget::ConnectionWidget(const ConnectionIdentifier &identifier, QWidget *parent): ConnectionWidget(parent) +ConnectionWidget::ConnectionWidget(const ConnectionId &identifier, QWidget *parent): ConnectionWidget(parent) { - auto connection = ConnectionHandler->GetConnection(identifier.connectionId); - connectionIdentifier = identifier; - groupId = identifier.groupId; - subscriptionId = identifier.subscriptionId; + auto connection = ConnectionHandler->GetConnection(identifier); + connectionId = identifier; + groupId = connection.groupId; itemType = NODE_ITEM; - rawDisplayName = connection.displayName; - connNameLabel->setText(rawDisplayName); - latencyLabel->setText(tr("Latency: ") + QSTRN(connection.latency) + " " + tr("ms")); + connNameLabel->setText(connection.displayName); + latencyLabel->setText(QSTRN(connection.latency) + " " + tr("ms")); + connTypeLabel->setText("DODO"); + dataLabel->setText(FormatBytes(connection.upLinkData + connection.downLinkData)); } // ======================================= Initialisation for root nodes. @@ -23,20 +24,9 @@ ConnectionWidget::ConnectionWidget(const GroupId &id, QWidget *parent) : Connect { groupId = id; itemType = GROUP_HEADER_ITEM; - InitialiseForGroup(ConnectionHandler->GetGroup(id).displayName, ConnectionHandler->Connections(id).count()); -} - -ConnectionWidget::ConnectionWidget(const SubscriptionId &id, QWidget *parent) : ConnectionWidget(parent) -{ - subscriptionId = id; - itemType = SUBS_HEADER_ITEM; - InitialiseForGroup(ConnectionHandler->GetSubscription(id).displayName, ConnectionHandler->Connections(id).count()); -} - -void ConnectionWidget::InitialiseForGroup(const QString &displayName, int connectionCount) -{ - rawDisplayName = displayName; - connNameLabel->setText(rawDisplayName); + auto displayName = ConnectionHandler->GetGroup(id).displayName; + auto connectionCount = ConnectionHandler->Connections(id).count(); + connNameLabel->setText(displayName); latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections"))); // layout()->removeWidget(connTypeLabel); @@ -45,10 +35,11 @@ void ConnectionWidget::InitialiseForGroup(const QString &displayName, int connec delete dataLabel; } + void ConnectionWidget::BeginConnection() { if (itemType == NODE_ITEM) { - ConnectionHandler->StartConnection(connectionIdentifier); + ConnectionHandler->StartConnection(connectionId); } else { LOG(MODULE_UI, "Trying to start a non-connection entry, this call is illegal.") } @@ -56,7 +47,7 @@ void ConnectionWidget::BeginConnection() void ConnectionWidget::OnConnected(const ConnectionId &id) { - if (id == connectionIdentifier.connectionId) { + if (id == connectionId) { LOG(MODULE_UI, "OnConnected signal received for: " + id.toString()) emit RequestWidgetFocus(this); } diff --git a/src/ui/widgets/ConnectionWidget.hpp b/src/ui/widgets/ConnectionWidget.hpp index 0498e244..c3c294ee 100644 --- a/src/ui/widgets/ConnectionWidget.hpp +++ b/src/ui/widgets/ConnectionWidget.hpp @@ -6,7 +6,6 @@ enum ITEM_TYPE { GROUP_HEADER_ITEM, - SUBS_HEADER_ITEM, NODE_ITEM }; @@ -14,13 +13,8 @@ class ConnectionWidget : public QWidget, private Ui::ConnectionWidget { Q_OBJECT public: - // - // ======================================= Initialisation for connection nodes. - explicit ConnectionWidget(const ConnectionIdentifier &identifier, QWidget *parent = nullptr); - // - // ======================================= Initialisation for root nodes. - explicit ConnectionWidget(const GroupId &id, QWidget *parent = nullptr); - explicit ConnectionWidget(const SubscriptionId &id, QWidget *parent = nullptr); + explicit ConnectionWidget(const ConnectionId &connecionId, QWidget *parent = nullptr); + explicit ConnectionWidget(const GroupId &groupId, QWidget *parent = nullptr); // void BeginConnection(); ~ConnectionWidget(); @@ -28,23 +22,18 @@ class ConnectionWidget : public QWidget, private Ui::ConnectionWidget inline bool NameMatched(const QString &arg) { auto searchString = arg.toLower(); - auto matchHeader = [&](const QString & arg1) { - return itemType == SUBS_HEADER_ITEM - ? ConnectionHandler->GetSubscription(subscriptionId).displayName.toLower().contains(arg1) - : ConnectionHandler->GetGroup(groupId).displayName.toLower().contains(arg1); - }; + auto headerMatched = ConnectionHandler->GetGroup(groupId).displayName.toLower().contains(arg); if (itemType != NODE_ITEM) { - return matchHeader(searchString); + return headerMatched; } else { - return matchHeader(searchString) || ConnectionHandler->GetConnection(connectionIdentifier.connectionId).displayName.toLower().contains(searchString); + return headerMatched || ConnectionHandler->GetConnection(connectionId).displayName.toLower().contains(searchString); } } - inline const ConnectionIdentifier Identifier() const + inline const tuple Identifier() const { - return connectionIdentifier; + return make_tuple(groupId, connectionId); } - // inline bool IsConnection() const { return itemType == NODE_ITEM; @@ -55,14 +44,9 @@ class ConnectionWidget : public QWidget, private Ui::ConnectionWidget void OnConnected(const ConnectionId &id); private: explicit ConnectionWidget(QWidget *parent = nullptr); - void InitialiseForGroup(const QString &displayName, int connectionCount); - QString rawDisplayName; - // ITEM_TYPE itemType; - // - ConnectionIdentifier connectionIdentifier; + ConnectionId connectionId; GroupId groupId; - SubscriptionId subscriptionId; Q_DISABLE_COPY_MOVE(ConnectionWidget) }; diff --git a/src/ui/widgets/ConnectionWidget.ui b/src/ui/widgets/ConnectionWidget.ui index 069c0f59..2d022d4b 100644 --- a/src/ui/widgets/ConnectionWidget.ui +++ b/src/ui/widgets/ConnectionWidget.ui @@ -31,7 +31,7 @@ - Latency: 500ms + 500ms Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -55,7 +55,7 @@ - 0KB / 0KB + 0KB From d42a3ca56a88f49f56a935a40465dac1135fc3b5 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 22 Feb 2020 18:17:04 +0800 Subject: [PATCH 023/332] wip: try to fix CI before continue -- stage 1 --- Qv2ray.pro | 2 +- makespec/BUILDVERSION | 2 +- src/core/handler/ConnectionHandler.cpp | 29 ++---- src/ui/w_MainWindow.cpp | 19 ++-- src/ui/w_MainWindow.hpp | 4 +- src/ui/w_MainWindow.ui | 9 +- ...ionWidget.cpp => ConnectionItemWidget.cpp} | 24 ++--- ...ionWidget.hpp => ConnectionItemWidget.hpp} | 16 ++-- src/ui/widgets/ConnectionItemWidget.ui | 93 +++++++++++++++++++ src/ui/widgets/ConnectionWidget.ui | 66 ------------- 10 files changed, 146 insertions(+), 118 deletions(-) rename src/ui/widgets/{ConnectionWidget.cpp => ConnectionItemWidget.cpp} (60%) rename src/ui/widgets/{ConnectionWidget.hpp => ConnectionItemWidget.hpp} (68%) create mode 100644 src/ui/widgets/ConnectionItemWidget.ui delete mode 100644 src/ui/widgets/ConnectionWidget.ui diff --git a/Qv2ray.pro b/Qv2ray.pro index 8f29b9f5..62900ead 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -109,8 +109,8 @@ Qv2rayAddSource(ui, _, w_MainWindow_extra, cpp) Qv2rayAddSource(ui, _, w_PreferencesWindow, cpp, hpp, ui) Qv2rayAddSource(ui, _, w_ScreenShot_Core, cpp, hpp, ui) Qv2rayAddSource(ui, _, w_SubscriptionManager, cpp, hpp, ui) -Qv2rayAddSource(ui, widgets, ConnectionWidget, cpp, hpp, ui) Qv2rayAddSource(ui, widgets, StreamSettingsWidget, cpp, hpp, ui) +Qv2rayAddSource(ui, widgets, ConnectionItemWidget, cpp, hpp, ui) Qv2rayAddSource(ui, widgets, ConnectionInfoWidget, cpp, hpp, ui) SOURCES += $$PWD/src/main.cpp diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 8b6eff0e..24b73993 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3887 +3889 diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index 9d05346c..63704d1b 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -82,7 +82,7 @@ namespace Qv2ray::core::handlers } - const QString QvConnectionHandler:: GetConnectionBasicInfo(const ConnectionId &id) const + const QString QvConnectionHandler::GetConnectionBasicInfo(const ConnectionId &id) const { QString result; @@ -91,28 +91,19 @@ namespace Qv2ray::core::handlers } CONFIGROOT root = CHGetConnectionRoot_p(connections[id].groupId, id); - bool isTLSEnabled = false; - - if (root.contains("inbounds") && !root["inbounds"].toArray().isEmpty()) { - QString inProtocol = tr("Inbounds: "); - - for (auto inbound : root["inbounds"].toArray()) { - inProtocol.append(inbound.toObject()["protocol"].toString()); - inProtocol.append("/"); - } - - inProtocol.chop(1); - result.append(inProtocol); - } - QStringList protocols; QStringList streamProtocols; + auto outbound = root["outbounds"].toArray().first().toObject(); + result.append(outbound["protocol"].toString()); - for (auto outbound : root["outbounds"].toArray()) { - protocols.append(outbound.toObject()["protocol"].toString()); + if (outbound.contains("streamSettings")) { + result.append(" + " + outbound["streamSettings"].toObject()["network"].toString()); + + if (outbound["streamSettings"].toObject().contains("tls")) { + result.append(outbound["streamSettings"].toObject()["tls"].toBool() ? " + tls" : ""); + } } - result.chop(1); return result; } @@ -134,7 +125,7 @@ namespace Qv2ray::core::handlers const CONFIGROOT QvConnectionHandler::CHGetConnectionRoot_p(const GroupId &group, const ConnectionId &id) const { - auto path = QV2RAY_CONNECTIONS_DIR + group.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; + auto path = group.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; path.prepend(groups[group].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR); return CONFIGROOT(JsonFromString(StringFromFile(path))); } diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 27a250e0..729f03c9 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -32,7 +32,7 @@ #define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING // -#define GetItemWidget(item) (static_cast(connectionListWidget->itemWidget(item, 0))) +#define GetItemWidget(item) (qobject_cast(connectionListWidget->itemWidget(item, 0))) // //#define ItemConnectionIdentifier(__item__) (__item__->data(0, Qt::UserRole).value()) // @@ -324,20 +324,25 @@ void MainWindow::OnConfigListChanged(bool need_restart) auto groups = ConnectionHandler->AllGroups(); for (auto group : groups) { - auto groupItem = new QTreeWidgetItem(); + auto groupItem = new QTreeWidgetItem(QStringList() << "" << ConnectionHandler->GetGroup(group).displayName); connectionListWidget->addTopLevelItem(groupItem); - connectionListWidget->setItemWidget(groupItem, 0, new ConnectionWidget(group, connectionListWidget)); + connectionListWidget->setItemWidget(groupItem, 0, new ConnectionItemWidget(group, connectionListWidget)); auto connections = ConnectionHandler->Connections(group); for (auto connection : connections) { - auto connectionItem = new QTreeWidgetItem(); + auto connectionItem = new QTreeWidgetItem(QStringList() << "" << ConnectionHandler->GetConnection(connection).displayName); groupItem->addChild(connectionItem); - auto widget = new ConnectionWidget(connection, connectionListWidget); - connect(widget, &ConnectionWidget::RequestWidgetFocus, this, &MainWindow::onConnectionWidgetFocusRequested); + auto widget = new ConnectionItemWidget(connection, connectionListWidget); + connect(widget, &ConnectionItemWidget::RequestWidgetFocus, this, &MainWindow::onConnectionWidgetFocusRequested); connectionListWidget->setItemWidget(connectionItem, 0, widget); } } + // Do not sort + //connectionListWidget->sortItems(1, Qt::SortOrder::AscendingOrder); + // + // ================================================================ + // //auto wasRunning = vinstance->KernelStarted && need_restart; // //if (wasRunning) on_stopButton_clicked(); @@ -1011,7 +1016,7 @@ void MainWindow::OnConnected(const ConnectionId &id) } -void MainWindow::onConnectionWidgetFocusRequested(const ConnectionWidget *_widget) +void MainWindow::onConnectionWidgetFocusRequested(const ConnectionItemWidget *_widget) { if (_widget == nullptr) { return; diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 3e4e1ee1..78f20914 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -14,7 +14,7 @@ #include "ui/messaging/QvMessageBus.hpp" // ========================================================================================== -#include "ui/widgets/ConnectionWidget.hpp" +#include "ui/widgets/ConnectionItemWidget.hpp" #include "ui/widgets/ConnectionInfoWidget.hpp" class MainWindow : public QMainWindow, Ui::MainWindow @@ -72,7 +72,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow private slots: // - void onConnectionWidgetFocusRequested(const ConnectionWidget *widget); + void onConnectionWidgetFocusRequested(const ConnectionItemWidget *widget); // void on_action_StartThis_triggered(); void on_action_RCM_EditJson_triggered(); diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 5096b276..2906d25a 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -127,6 +127,9 @@ QAbstractItemView::ScrollPerPixel + + 0 + true @@ -386,8 +389,8 @@ 0 0 - 459 - 848 + 480 + 851 @@ -553,7 +556,7 @@ 0 0 800 - 29 + 26 diff --git a/src/ui/widgets/ConnectionWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp similarity index 60% rename from src/ui/widgets/ConnectionWidget.cpp rename to src/ui/widgets/ConnectionItemWidget.cpp index 6f1f0a6c..f42899ce 100644 --- a/src/ui/widgets/ConnectionWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -1,32 +1,34 @@ -#include "ConnectionWidget.hpp" +#include "ConnectionItemWidget.hpp" #include "common/QvHelpers.hpp" -ConnectionWidget::ConnectionWidget(QWidget *parent) : QWidget(parent), connectionId("null"), groupId("null") +ConnectionItemWidget::ConnectionItemWidget(QWidget *parent) : QWidget(parent), connectionId("null"), groupId("null") { setupUi(this); - connect(ConnectionHandler, &QvConnectionHandler::OnConnected, this, &ConnectionWidget::OnConnected); + connect(ConnectionHandler, &QvConnectionHandler::OnConnected, this, &ConnectionItemWidget::OnConnected); } -ConnectionWidget::ConnectionWidget(const ConnectionId &identifier, QWidget *parent): ConnectionWidget(parent) +ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &identifier, QWidget *parent): ConnectionItemWidget(parent) { auto connection = ConnectionHandler->GetConnection(identifier); connectionId = identifier; groupId = connection.groupId; itemType = NODE_ITEM; - connNameLabel->setText(connection.displayName); + connNameLabel->setText("" + connection.displayName); latencyLabel->setText(QSTRN(connection.latency) + " " + tr("ms")); - connTypeLabel->setText("DODO"); + connTypeLabel->setText(tr("Type: ") + ConnectionHandler->GetConnectionBasicInfo(identifier)); dataLabel->setText(FormatBytes(connection.upLinkData + connection.downLinkData)); + // + indentSpacer->changeSize(10, indentSpacer->sizeHint().height()); } // ======================================= Initialisation for root nodes. -ConnectionWidget::ConnectionWidget(const GroupId &id, QWidget *parent) : ConnectionWidget(parent) +ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : ConnectionItemWidget(parent) { groupId = id; itemType = GROUP_HEADER_ITEM; auto displayName = ConnectionHandler->GetGroup(id).displayName; auto connectionCount = ConnectionHandler->Connections(id).count(); - connNameLabel->setText(displayName); + connNameLabel->setText(/*"• " +*/ displayName); latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections"))); // layout()->removeWidget(connTypeLabel); @@ -36,7 +38,7 @@ ConnectionWidget::ConnectionWidget(const GroupId &id, QWidget *parent) : Connect } -void ConnectionWidget::BeginConnection() +void ConnectionItemWidget::BeginConnection() { if (itemType == NODE_ITEM) { ConnectionHandler->StartConnection(connectionId); @@ -45,7 +47,7 @@ void ConnectionWidget::BeginConnection() } } -void ConnectionWidget::OnConnected(const ConnectionId &id) +void ConnectionItemWidget::OnConnected(const ConnectionId &id) { if (id == connectionId) { LOG(MODULE_UI, "OnConnected signal received for: " + id.toString()) @@ -53,7 +55,7 @@ void ConnectionWidget::OnConnected(const ConnectionId &id) } } -ConnectionWidget::~ConnectionWidget() +ConnectionItemWidget::~ConnectionItemWidget() { // } diff --git a/src/ui/widgets/ConnectionWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp similarity index 68% rename from src/ui/widgets/ConnectionWidget.hpp rename to src/ui/widgets/ConnectionItemWidget.hpp index c3c294ee..2771f312 100644 --- a/src/ui/widgets/ConnectionWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include "ui_ConnectionWidget.h" +#include "ui_ConnectionItemWidget.h" #include "core/handler/ConnectionHandler.hpp" enum ITEM_TYPE { @@ -9,15 +9,15 @@ enum ITEM_TYPE { NODE_ITEM }; -class ConnectionWidget : public QWidget, private Ui::ConnectionWidget +class ConnectionItemWidget : public QWidget, private Ui::ConnectionWidget { Q_OBJECT public: - explicit ConnectionWidget(const ConnectionId &connecionId, QWidget *parent = nullptr); - explicit ConnectionWidget(const GroupId &groupId, QWidget *parent = nullptr); + explicit ConnectionItemWidget(const ConnectionId &connecionId, QWidget *parent = nullptr); + explicit ConnectionItemWidget(const GroupId &groupId, QWidget *parent = nullptr); // void BeginConnection(); - ~ConnectionWidget(); + ~ConnectionItemWidget(); // inline bool NameMatched(const QString &arg) { @@ -39,14 +39,14 @@ class ConnectionWidget : public QWidget, private Ui::ConnectionWidget return itemType == NODE_ITEM; } signals: - void RequestWidgetFocus(const ConnectionWidget *me); + void RequestWidgetFocus(const ConnectionItemWidget *me); private slots: void OnConnected(const ConnectionId &id); private: - explicit ConnectionWidget(QWidget *parent = nullptr); + explicit ConnectionItemWidget(QWidget *parent = nullptr); ITEM_TYPE itemType; ConnectionId connectionId; GroupId groupId; - Q_DISABLE_COPY_MOVE(ConnectionWidget) + Q_DISABLE_COPY_MOVE(ConnectionItemWidget) }; diff --git a/src/ui/widgets/ConnectionItemWidget.ui b/src/ui/widgets/ConnectionItemWidget.ui new file mode 100644 index 00000000..2157258b --- /dev/null +++ b/src/ui/widgets/ConnectionItemWidget.ui @@ -0,0 +1,93 @@ + + + ConnectionWidget + + + + 0 + 0 + 277 + 66 + + + + Form + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 0 + 0 + + + + + + + + + + + + + 12 + + + + Connection Name + + + + + + + 500ms + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Type: vmess + tls + ws + + + + + + + + 8 + + + + 0KB + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + diff --git a/src/ui/widgets/ConnectionWidget.ui b/src/ui/widgets/ConnectionWidget.ui deleted file mode 100644 index 2d022d4b..00000000 --- a/src/ui/widgets/ConnectionWidget.ui +++ /dev/null @@ -1,66 +0,0 @@ - - - ConnectionWidget - - - - 0 - 0 - 283 - 84 - - - - Form - - - - - - - - - 12 - - - - Connection Name - - - - - - - 500ms - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - Type: vmess + tls + ws - - - - - - - - 8 - - - - 0KB - - - - - - - - From a6b28bf3ddab38433db85cd46eaa1c57688e995a Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 22 Feb 2020 18:20:18 +0800 Subject: [PATCH 024/332] wip: fix: fixed some log errors --- .../plugins/toolbar/QvToolbar_win.cpp | 2 +- src/components/proxy/QvProxyConfigurator.cpp | 28 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/components/plugins/toolbar/QvToolbar_win.cpp b/src/components/plugins/toolbar/QvToolbar_win.cpp index c9795d47..4662e77a 100644 --- a/src/components/plugins/toolbar/QvToolbar_win.cpp +++ b/src/components/plugins/toolbar/QvToolbar_win.cpp @@ -26,7 +26,7 @@ namespace Qv2ray::components::plugins::Toolbar auto hThread = CreateThread(nullptr, 0, NamedPipeMasterThread, nullptr, 0, nullptr); if (hThread == nullptr) { - LOG(PLUGIN, "CreateThread failed, GLE=" + QSTRN(GetLastError())) + LOG(MODULE_PLUGIN, "CreateThread failed, GLE=" + QSTRN(GetLastError())) return; } else CloseHandle(hThread); } diff --git a/src/components/proxy/QvProxyConfigurator.cpp b/src/components/proxy/QvProxyConfigurator.cpp index 14cb79db..392c99a3 100644 --- a/src/components/proxy/QvProxyConfigurator.cpp +++ b/src/components/proxy/QvProxyConfigurator.cpp @@ -30,7 +30,7 @@ namespace Qv2ray::components::proxy } } - LOG(PROXY, "Found " + QSTRN(result.size()) + " network services: " + result.join(";")) + LOG(MODULE_PROXY, "Found " + QSTRN(result.size()) + " network services: " + result.join(";")) return result; } #endif @@ -58,37 +58,37 @@ namespace Qv2ray::components::proxy List.pOptions = Option; if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) { - LOG(PROXY, "InternetQueryOption failed, GLE=" + QSTRN(GetLastError())) + LOG(MODULE_PROXY, "InternetQueryOption failed, GLE=" + QSTRN(GetLastError())) } LOG(PROXY, "System default proxy info:") if (Option[0].Value.pszValue != nullptr) { - LOG(PROXY, QString::fromWCharArray(Option[0].Value.pszValue)) + LOG(MODULE_PROXY, QString::fromWCharArray(Option[0].Value.pszValue)) } if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL) == PROXY_TYPE_AUTO_PROXY_URL) { - LOG(PROXY, "PROXY_TYPE_AUTO_PROXY_URL") + LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_PROXY_URL") } if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_DETECT) == PROXY_TYPE_AUTO_DETECT) { - LOG(PROXY, "PROXY_TYPE_AUTO_DETECT") + LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_DETECT") } if ((Option[2].Value.dwValue & PROXY_TYPE_DIRECT) == PROXY_TYPE_DIRECT) { - LOG(PROXY, "PROXY_TYPE_DIRECT") + LOG(MODULE_PROXY, "PROXY_TYPE_DIRECT") } if ((Option[2].Value.dwValue & PROXY_TYPE_PROXY) == PROXY_TYPE_PROXY) { - LOG(PROXY, "PROXY_TYPE_PROXY") + LOG(MODULE_PROXY, "PROXY_TYPE_PROXY") } if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) { - LOG(PROXY, "InternetQueryOption failed,GLE=" + QSTRN(GetLastError())) + LOG(MODULE_PROXY, "InternetQueryOption failed,GLE=" + QSTRN(GetLastError())) } if (Option[4].Value.pszValue != nullptr) { - LOG(PROXY, QString::fromStdWString(Option[4].Value.pszValue)) + LOG(MODULE_PROXY, QString::fromStdWString(Option[4].Value.pszValue)) } INTERNET_VERSION_INFO Version; @@ -120,7 +120,7 @@ namespace Qv2ray::components::proxy list.pszConnection = nullptr; if (isPAC) { - LOG(PROXY, "Setting system proxy for PAC") + LOG(MODULE_PROXY, "Setting system proxy for PAC") // list.dwOptionCount = 2; list.pOptions = new INTERNET_PER_CONN_OPTION[2]; @@ -138,7 +138,7 @@ namespace Qv2ray::components::proxy list.pOptions[1].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL; list.pOptions[1].Value.pszValue = proxy_full_addr; } else { - LOG(PROXY, "Setting system proxy for Global Proxy") + LOG(MODULE_PROXY, "Setting system proxy for Global Proxy") // list.dwOptionCount = 3; list.pOptions = new INTERNET_PER_CONN_OPTION[3]; @@ -199,14 +199,14 @@ namespace Qv2ray::components::proxy __a = (hasHTTP ? "http://" : "socks5://") + address + ":" + QSTRN(httpPort); } - LOG(PROXY, "Windows proxy string: " + __a) + LOG(MODULE_PROXY, "Windows proxy string: " + __a) auto proxyStrW = new WCHAR[__a.length() + 1]; wcscpy(proxyStrW, __a.toStdWString().c_str()); // __QueryProxyOptions(); if (!__SetProxyOptions(proxyStrW, usePAC)) { - LOG(PROXY, "Failed to set proxy.") + LOG(MODULE_PROXY, "Failed to set proxy.") } __QueryProxyOptions(); @@ -248,7 +248,7 @@ namespace Qv2ray::components::proxy #else for (auto service : macOSgetNetworkServices()) { - LOG(PROXY, "Setting proxy for interface: " + service) + LOG(MODULE_PROXY, "Setting proxy for interface: " + service) if (usePAC) { QProcess::execute("/usr/sbin/networksetup -setautoproxystate " + service + " on"); From 6684de4b0a8feb9159b2d314bb28c21310593408 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 22 Feb 2020 18:24:21 +0800 Subject: [PATCH 025/332] wip: fix: fixed some log errors - 2 --- src/components/proxy/QvProxyConfigurator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/proxy/QvProxyConfigurator.cpp b/src/components/proxy/QvProxyConfigurator.cpp index 392c99a3..597a4362 100644 --- a/src/components/proxy/QvProxyConfigurator.cpp +++ b/src/components/proxy/QvProxyConfigurator.cpp @@ -274,7 +274,7 @@ namespace Qv2ray::components::proxy void ClearSystemProxy() { #ifdef Q_OS_WIN - LOG(PROXY, "Cleaning system proxy settings.") + LOG(MODULE_PROXY, "Cleaning system proxy settings.") INTERNET_PER_CONN_OPTION_LIST list; BOOL bReturn; DWORD dwBufSize = sizeof(list); @@ -289,7 +289,7 @@ namespace Qv2ray::components::proxy // Make sure the memory was allocated. if (nullptr == list.pOptions) { // Return FALSE if the memory wasn't allocated. - LOG(PROXY, "Failed to allocat memory in DisableConnectionProxy()") + LOG(MODULE_PROXY, "Failed to allocat memory in DisableConnectionProxy()") } // Set flags. @@ -306,7 +306,7 @@ namespace Qv2ray::components::proxy #else for (auto service : macOSgetNetworkServices()) { - LOG(PROXY, "Clearing proxy for interface: " + service) + LOG(MODULE_PROXY, "Clearing proxy for interface: " + service) QProcess::execute("/usr/sbin/networksetup -setautoproxystate " + service + " off"); QProcess::execute("/usr/sbin/networksetup -setwebproxystate " + service + " off"); QProcess::execute("/usr/sbin/networksetup -setsecurewebproxystate " + service + " off"); From 38b4d01dd356bd7690dc9a8b1bbfcfc3fea5d77e Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 22 Feb 2020 18:26:50 +0800 Subject: [PATCH 026/332] wip: reduced include dependencies --- src/base/Qv2rayBase.hpp | 6 ------ src/base/Qv2rayLog.cpp | 3 ++- src/base/Qv2rayLog.hpp | 11 ++++++++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index 546789aa..f638af19 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -44,12 +44,6 @@ using namespace Qv2ray::base::objects::transfer; #define QV2RAY_BUILD_INFO QString(_QV2RAY_BUILD_INFO_STR_) #define QV2RAY_BUILD_EXTRA_INFO QString(_QV2RAY_BUILD_EXTRA_INFO_STR_) -#ifdef QT_DEBUG -inline const bool isDebugBuild = true; -#else -inline const bool isDebugBuild = false; -#endif - // Base folder suffix. #ifdef QT_DEBUG # define QV2RAY_CONFIG_DIR_SUFFIX "_debug/" diff --git a/src/base/Qv2rayLog.cpp b/src/base/Qv2rayLog.cpp index cc2fb552..925e3120 100644 --- a/src/base/Qv2rayLog.cpp +++ b/src/base/Qv2rayLog.cpp @@ -1,5 +1,6 @@ #include "Qv2rayLog.hpp" -#include "Qv2rayBase.hpp" +#include "base/GlobalInstances.hpp" +#include namespace Qv2ray::base { diff --git a/src/base/Qv2rayLog.hpp b/src/base/Qv2rayLog.hpp index e834ac77..cc6c0a4e 100644 --- a/src/base/Qv2rayLog.hpp +++ b/src/base/Qv2rayLog.hpp @@ -1,13 +1,18 @@ #pragma once -#include -#include -#include +#include using namespace std; /* * Tiny log module. */ + +#ifdef QT_DEBUG +inline const bool isDebugBuild = true; +#else +inline const bool isDebugBuild = false; +#endif + namespace Qv2ray::base { void __QV2RAY_LOG_FUNC__(int type, const std::string &func, int line, const QString &module, const QString &log); From 04e6aba071b272896b1ce559d19f494957d85eff Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 22 Feb 2020 18:55:24 +0800 Subject: [PATCH 027/332] using python 3.7 for github actions --- .github/workflows/build-qv2ray.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build-qv2ray.yml b/.github/workflows/build-qv2ray.yml index 0869f26d..e0658ad3 100644 --- a/.github/workflows/build-qv2ray.yml +++ b/.github/workflows/build-qv2ray.yml @@ -28,6 +28,11 @@ jobs: run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3) - name: Checking out sources uses: actions/checkout@master + - name: Install Python 3.7 version + uses: actions/setup-python@v1 + with: + python-version: '3.7' + architecture: ${{ matrix.arch }} - name: Restoring submodules run: git submodule update --init # -------------------------------------------------------- From 50adb3026894b4f6a03b24f728a725ecb033bfe8 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 22 Feb 2020 20:10:55 +0800 Subject: [PATCH 028/332] wip: fix: fixed main.cpp iostream issue --- makespec/BUILDVERSION | 2 +- src/base/Qv2rayBase.hpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 24b73993..c9a7382c 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3889 +3890 diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index f638af19..f2e0e059 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include // Base support. #include "base/Qv2rayLog.hpp" From 57e2d4660ea2d61e4fcaafb42431d6e102122cf1 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 22 Feb 2020 20:16:48 +0800 Subject: [PATCH 029/332] wip: fix: fixed LOG issue - 3 --- src/components/proxy/QvProxyConfigurator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/proxy/QvProxyConfigurator.cpp b/src/components/proxy/QvProxyConfigurator.cpp index 597a4362..f93d42a0 100644 --- a/src/components/proxy/QvProxyConfigurator.cpp +++ b/src/components/proxy/QvProxyConfigurator.cpp @@ -17,7 +17,7 @@ namespace Qv2ray::components::proxy p.start(); p.waitForStarted(); p.waitForFinished(); - LOG(PROXY, p.errorString()) + LOG(MODULE_PROXY, p.errorString()) auto str = p.readAllStandardOutput(); auto lines = SplitLines(str); QStringList result; From 9a15e7b7c37e6ad10b0a69d93b2d60467a19078f Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 22 Feb 2020 20:24:17 +0800 Subject: [PATCH 030/332] wip: fix: fixed LOG issue - 4 --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index a63d5d07..76d65ddb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -404,7 +404,7 @@ int main(int argc, char *argv[]) _qApp.setFont(font); #endif #ifdef QV2RAY_USE_BUILTIN_DARKTHEME - LOG(UI, "Using built-in theme.") + LOG(MODULE_UI, "Using built-in theme.") if (confObject.uiConfig.useDarkTheme) { LOG(MODULE_UI, " --> Using built-in dark theme.") From 414ce1b73988abbac28b4f74c3e5399b78b90b5c Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 22 Feb 2020 20:27:40 +0800 Subject: [PATCH 031/332] wip: fix: fixed unused function without return type issue - 5 --- src/core/connection/ConnectionIO.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/core/connection/ConnectionIO.cpp b/src/core/connection/ConnectionIO.cpp index 38c82518..6c14f0a3 100644 --- a/src/core/connection/ConnectionIO.cpp +++ b/src/core/connection/ConnectionIO.cpp @@ -6,10 +6,6 @@ namespace Qv2ray::core::connection namespace ConnectionIO { - CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id) - { - } - //CONFIGROOT GetConnectionRoot(const SubscriptionId &subscription, const ConnectionId &id) //{ // return ReadConnectionInternal(QV2RAY_SUBSCRIPTION_DIR + subscription.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION); From 5d1334b481f063febb05be7447919db9969a2471 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 22 Feb 2020 20:34:50 +0800 Subject: [PATCH 032/332] wip: fix: fixed windows build - 6 --- src/base/Qv2rayBase.hpp | 1 + .../proxy/QvProxyConfigurator.cpp.autosave | 318 ++++++++++++++++++ src/core/kernel/APIBackend.cpp | 2 +- 3 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 src/components/proxy/QvProxyConfigurator.cpp.autosave diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index f2e0e059..7d69798f 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -12,6 +12,7 @@ #include #include #include +#include // Base support. #include "base/Qv2rayLog.hpp" #include "base/Qv2rayFeatures.hpp" diff --git a/src/components/proxy/QvProxyConfigurator.cpp.autosave b/src/components/proxy/QvProxyConfigurator.cpp.autosave new file mode 100644 index 00000000..9c12000f --- /dev/null +++ b/src/components/proxy/QvProxyConfigurator.cpp.autosave @@ -0,0 +1,318 @@ +#include "QvProxyConfigurator.hpp" +#include "common/QvHelpers.hpp" +#ifdef Q_OS_WIN +#include "wininet.h" +#include +#endif + +namespace Qv2ray::components::proxy +{ + +#ifdef Q_OS_MACOS + QStringList macOSgetNetworkServices() + { + QProcess p; + p.setProgram("/usr/sbin/networksetup"); + p.setArguments(QStringList() << "-listallnetworkservices"); + p.start(); + p.waitForStarted(); + p.waitForFinished(); + LOG(MODULE_PROXY, p.errorString()) + auto str = p.readAllStandardOutput(); + auto lines = SplitLines(str); + QStringList result; + + // Start from 1 since first line is unneeded. + for (auto i = 1; i < lines.count(); i++) { + // * means disabled. + if (!lines[i].contains("*")) { + result << (lines[i].contains(" ") ? "\"" + lines[i] + "\"" : lines[i]); + } + } + + LOG(MODULE_PROXY, "Found " + QSTRN(result.size()) + " network services: " + result.join(";")) + return result; + } +#endif +#ifdef Q_OS_WIN +#define NO_CONST(expr) const_cast(expr) + //static auto DEFAULT_CONNECTION_NAME = NO_CONST(L"DefaultConnectionSettings"); + /// + /// INTERNAL FUNCTION + bool __QueryProxyOptions() + { + INTERNET_PER_CONN_OPTION_LIST List; + INTERNET_PER_CONN_OPTION Option[5]; + // + unsigned long nSize = sizeof(INTERNET_PER_CONN_OPTION_LIST); + Option[0].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL; + Option[1].dwOption = INTERNET_PER_CONN_AUTODISCOVERY_FLAGS; + Option[2].dwOption = INTERNET_PER_CONN_FLAGS; + Option[3].dwOption = INTERNET_PER_CONN_PROXY_BYPASS; + Option[4].dwOption = INTERNET_PER_CONN_PROXY_SERVER; + // + List.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LIST); + List.pszConnection = nullptr;// NO_CONST(DEFAULT_CONNECTION_NAME); + List.dwOptionCount = 5; + List.dwOptionError = 0; + List.pOptions = Option; + + if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) { + LOG(MODULE_PROXY, "InternetQueryOption failed, GLE=" + QSTRN(GetLastError())) + } + + LOG(MODULE_PROXY, "System default proxy info:") + + if (Option[0].Value.pszValue != nullptr) { + LOG(MODULE_PROXY, QString::fromWCharArray(Option[0].Value.pszValue)) + } + + if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL) == PROXY_TYPE_AUTO_PROXY_URL) { + LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_PROXY_URL") + } + + if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_DETECT) == PROXY_TYPE_AUTO_DETECT) { + LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_DETECT") + } + + if ((Option[2].Value.dwValue & PROXY_TYPE_DIRECT) == PROXY_TYPE_DIRECT) { + LOG(MODULE_PROXY, "PROXY_TYPE_DIRECT") + } + + if ((Option[2].Value.dwValue & PROXY_TYPE_PROXY) == PROXY_TYPE_PROXY) { + LOG(MODULE_PROXY, "PROXY_TYPE_PROXY") + } + + if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) { + LOG(MODULE_PROXY, "InternetQueryOption failed,GLE=" + QSTRN(GetLastError())) + } + + if (Option[4].Value.pszValue != nullptr) { + LOG(MODULE_PROXY, QString::fromStdWString(Option[4].Value.pszValue)) + } + + INTERNET_VERSION_INFO Version; + nSize = sizeof(INTERNET_VERSION_INFO); + InternetQueryOption(nullptr, INTERNET_OPTION_VERSION, &Version, &nSize); + + if (Option[0].Value.pszValue != nullptr) { + GlobalFree(Option[0].Value.pszValue); + } + + if (Option[3].Value.pszValue != nullptr) { + GlobalFree(Option[3].Value.pszValue); + } + + if (Option[4].Value.pszValue != nullptr) { + GlobalFree(Option[4].Value.pszValue); + } + + return false; + } + bool __SetProxyOptions(LPWSTR proxy_full_addr, bool isPAC) + { + INTERNET_PER_CONN_OPTION_LIST list; + BOOL bReturn; + DWORD dwBufSize = sizeof(list); + // Fill the list structure. + list.dwSize = sizeof(list); + // NULL == LAN, otherwise connectoid name. + list.pszConnection = nullptr; + + if (isPAC) { + LOG(MODULE_PROXY, "Setting system proxy for PAC") + // + list.dwOptionCount = 2; + list.pOptions = new INTERNET_PER_CONN_OPTION[2]; + + // Ensure that the memory was allocated. + if (nullptr == list.pOptions) { + // Return FALSE if the memory wasn't allocated. + return FALSE; + } + + // Set flags. + list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; + list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_AUTO_PROXY_URL; + // Set proxy name. + list.pOptions[1].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL; + list.pOptions[1].Value.pszValue = proxy_full_addr; + } else { + LOG(MODULE_PROXY, "Setting system proxy for Global Proxy") + // + list.dwOptionCount = 3; + list.pOptions = new INTERNET_PER_CONN_OPTION[3]; + + if (nullptr == list.pOptions) { + return false; + } + + // Set flags. + list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; + list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_PROXY; + // Set proxy name. + list.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER; + list.pOptions[1].Value.pszValue = proxy_full_addr; + // Set proxy override. + list.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS; + auto localhost = L"localhost"; + list.pOptions[2].Value.pszValue = NO_CONST(localhost); + } + + // Set the options on the connection. + bReturn = InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); + delete [] list.pOptions; + InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0); + InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0); + return bReturn; + } +#endif + + void SetSystemProxy(const QString &address, int httpPort, int socksPort, bool usePAC) + { + bool hasHTTP = (httpPort != 0); + bool hasSOCKS = (socksPort != 0); + + if (!(hasHTTP || hasSOCKS || usePAC)) { + LOG(MODULE_PROXY, "Nothing?") + return; + } + + if (usePAC) { + LOG(MODULE_PROXY, "Qv2ray will set system proxy to use PAC file") + } else { + if (hasHTTP) { + LOG(MODULE_PROXY, "Qv2ray will set system proxy to use HTTP") + } + + if (hasSOCKS) { + LOG(MODULE_PROXY, "Qv2ray will set system proxy to use SOCKS") + } + } + +#ifdef Q_OS_WIN + QString __a; + + if (usePAC) { + __a = address; + } else { + __a = (hasHTTP ? "http://" : "socks5://") + address + ":" + QSTRN(httpPort); + } + + LOG(MODULE_PROXY, "Windows proxy string: " + __a) + auto proxyStrW = new WCHAR[__a.length() + 1]; + wcscpy(proxyStrW, __a.toStdWString().c_str()); + // + __QueryProxyOptions(); + + if (!__SetProxyOptions(proxyStrW, usePAC)) { + LOG(MODULE_PROXY, "Failed to set proxy.") + } + + __QueryProxyOptions(); +#elif defined(Q_OS_LINUX) + QStringList actions; + auto proxyMode = usePAC ? "auto" : "manual"; + actions << QString("gsettings set org.gnome.system.proxy mode '%1'").arg(proxyMode); + + if (usePAC) { + actions << QString("gsettings set org.gnome.system.proxy autoconfig-url '%1'").arg(address); + } else { + if (hasHTTP) { + actions << QString("gsettings set org.gnome.system.proxy.http host '%1'").arg(address); + actions << QString("gsettings set org.gnome.system.proxy.http port %1").arg(httpPort); + // + actions << QString("gsettings set org.gnome.system.proxy.https host '%1'").arg(address); + actions << QString("gsettings set org.gnome.system.proxy.https port %1").arg(httpPort);; + } + + if (hasSOCKS) { + actions << QString("gsettings set org.gnome.system.proxy.socks host '%1'").arg(address); + actions << QString("gsettings set org.gnome.system.proxy.socks port %1").arg(socksPort); + } + } + + // note: do not use std::all_of / any_of / none_of, + // because those are short-circuit and cannot guarantee atomicity. + auto result = std::count_if(actions.cbegin(), actions.cend(), [](const QString & action) { + DEBUG(MODULE_PROXY, action) + return QProcess::execute(action) == QProcess::NormalExit; + }) == actions.size(); + + if (!result) { + LOG(MODULE_PROXY, "Something wrong happens when setting system proxy -> Gnome ONLY.") + LOG(MODULE_PROXY, "If you are using KDE Plasma and receiving this message, just simply ignore this.") + } + + Q_UNUSED(result); +#else + + for (auto service : macOSgetNetworkServices()) { + LOG(MODULE_PROXY, "Setting proxy for interface: " + service) + + if (usePAC) { + QProcess::execute("/usr/sbin/networksetup -setautoproxystate " + service + " on"); + QProcess::execute("/usr/sbin/networksetup -setautoproxyurl " + service + " " + address); + } else { + if (hasHTTP) { + QProcess::execute("/usr/sbin/networksetup -setwebproxystate " + 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 -setsecurewebproxy " + service + " " + address + " " + QSTRN(httpPort)); + } + + if (hasSOCKS) { + QProcess::execute("/usr/sbin/networksetup -setsocksfirewallproxystate " + service + " on"); + QProcess::execute("/usr/sbin/networksetup -setsocksfirewallproxy " + service + " " + address + " " + QSTRN(socksPort)); + } + } + } + +#endif + } + + void ClearSystemProxy() + { +#ifdef Q_OS_WIN + LOG(MODULE_PROXY, "Cleaning system proxy settings.") + INTERNET_PER_CONN_OPTION_LIST list; + BOOL bReturn; + DWORD dwBufSize = sizeof(list); + // Fill out list struct. + list.dwSize = sizeof(list); + // nullptr == LAN, otherwise connectoid name. + list.pszConnection = nullptr; + // Set three options. + list.dwOptionCount = 1; + list.pOptions = new INTERNET_PER_CONN_OPTION[list.dwOptionCount]; + + // Make sure the memory was allocated. + if (nullptr == list.pOptions) { + // Return FALSE if the memory wasn't allocated. + LOG(MODULE_PROXY, "Failed to allocat memory in DisableConnectionProxy()") + } + + // Set flags. + list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; + list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT; + // + // Set the options on the connection. + bReturn = InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); + delete [] list.pOptions; + InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0); + InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0); +#elif defined(Q_OS_LINUX) + QProcess::execute("gsettings set org.gnome.system.proxy mode 'none'"); +#else + + for (auto service : macOSgetNetworkServices()) { + LOG(MODULE_PROXY, "Clearing proxy for interface: " + service) + QProcess::execute("/usr/sbin/networksetup -setautoproxystate " + service + " off"); + QProcess::execute("/usr/sbin/networksetup -setwebproxystate " + service + " off"); + QProcess::execute("/usr/sbin/networksetup -setsecurewebproxystate " + service + " off"); + QProcess::execute("/usr/sbin/networksetup -setsocksfirewallproxystate " + service + " off"); + } + +#endif + } +} diff --git a/src/core/kernel/APIBackend.cpp b/src/core/kernel/APIBackend.cpp index 8b84840f..1fe8990f 100644 --- a/src/core/kernel/APIBackend.cpp +++ b/src/core/kernel/APIBackend.cpp @@ -125,7 +125,7 @@ namespace Qv2ray::core::kernel::api Status status = Stub->GetStats(&context, request, &response); if (!status.ok()) { - LOG(VCORE, "API call returns: " + QSTRN(status.error_code()) + " (" + QString::fromStdString(status.error_message()) + ")") + LOG(MODULE_VCORE, "API call returns: " + QSTRN(status.error_code()) + " (" + QString::fromStdString(status.error_message()) + ")") apiFailedCounter++; } From 681c5f648c2d0eb46b1244d7f56d6aaa562489bf Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 22 Feb 2020 20:36:57 +0800 Subject: [PATCH 033/332] wip: fix: fixed LOG issue - 7 --- src/components/proxy/QvProxyConfigurator.cpp | 2 +- .../proxy/QvProxyConfigurator.cpp.autosave | 318 ------------------ 2 files changed, 1 insertion(+), 319 deletions(-) delete mode 100644 src/components/proxy/QvProxyConfigurator.cpp.autosave diff --git a/src/components/proxy/QvProxyConfigurator.cpp b/src/components/proxy/QvProxyConfigurator.cpp index f93d42a0..9c12000f 100644 --- a/src/components/proxy/QvProxyConfigurator.cpp +++ b/src/components/proxy/QvProxyConfigurator.cpp @@ -61,7 +61,7 @@ namespace Qv2ray::components::proxy LOG(MODULE_PROXY, "InternetQueryOption failed, GLE=" + QSTRN(GetLastError())) } - LOG(PROXY, "System default proxy info:") + LOG(MODULE_PROXY, "System default proxy info:") if (Option[0].Value.pszValue != nullptr) { LOG(MODULE_PROXY, QString::fromWCharArray(Option[0].Value.pszValue)) diff --git a/src/components/proxy/QvProxyConfigurator.cpp.autosave b/src/components/proxy/QvProxyConfigurator.cpp.autosave deleted file mode 100644 index 9c12000f..00000000 --- a/src/components/proxy/QvProxyConfigurator.cpp.autosave +++ /dev/null @@ -1,318 +0,0 @@ -#include "QvProxyConfigurator.hpp" -#include "common/QvHelpers.hpp" -#ifdef Q_OS_WIN -#include "wininet.h" -#include -#endif - -namespace Qv2ray::components::proxy -{ - -#ifdef Q_OS_MACOS - QStringList macOSgetNetworkServices() - { - QProcess p; - p.setProgram("/usr/sbin/networksetup"); - p.setArguments(QStringList() << "-listallnetworkservices"); - p.start(); - p.waitForStarted(); - p.waitForFinished(); - LOG(MODULE_PROXY, p.errorString()) - auto str = p.readAllStandardOutput(); - auto lines = SplitLines(str); - QStringList result; - - // Start from 1 since first line is unneeded. - for (auto i = 1; i < lines.count(); i++) { - // * means disabled. - if (!lines[i].contains("*")) { - result << (lines[i].contains(" ") ? "\"" + lines[i] + "\"" : lines[i]); - } - } - - LOG(MODULE_PROXY, "Found " + QSTRN(result.size()) + " network services: " + result.join(";")) - return result; - } -#endif -#ifdef Q_OS_WIN -#define NO_CONST(expr) const_cast(expr) - //static auto DEFAULT_CONNECTION_NAME = NO_CONST(L"DefaultConnectionSettings"); - /// - /// INTERNAL FUNCTION - bool __QueryProxyOptions() - { - INTERNET_PER_CONN_OPTION_LIST List; - INTERNET_PER_CONN_OPTION Option[5]; - // - unsigned long nSize = sizeof(INTERNET_PER_CONN_OPTION_LIST); - Option[0].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL; - Option[1].dwOption = INTERNET_PER_CONN_AUTODISCOVERY_FLAGS; - Option[2].dwOption = INTERNET_PER_CONN_FLAGS; - Option[3].dwOption = INTERNET_PER_CONN_PROXY_BYPASS; - Option[4].dwOption = INTERNET_PER_CONN_PROXY_SERVER; - // - List.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LIST); - List.pszConnection = nullptr;// NO_CONST(DEFAULT_CONNECTION_NAME); - List.dwOptionCount = 5; - List.dwOptionError = 0; - List.pOptions = Option; - - if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) { - LOG(MODULE_PROXY, "InternetQueryOption failed, GLE=" + QSTRN(GetLastError())) - } - - LOG(MODULE_PROXY, "System default proxy info:") - - if (Option[0].Value.pszValue != nullptr) { - LOG(MODULE_PROXY, QString::fromWCharArray(Option[0].Value.pszValue)) - } - - if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL) == PROXY_TYPE_AUTO_PROXY_URL) { - LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_PROXY_URL") - } - - if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_DETECT) == PROXY_TYPE_AUTO_DETECT) { - LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_DETECT") - } - - if ((Option[2].Value.dwValue & PROXY_TYPE_DIRECT) == PROXY_TYPE_DIRECT) { - LOG(MODULE_PROXY, "PROXY_TYPE_DIRECT") - } - - if ((Option[2].Value.dwValue & PROXY_TYPE_PROXY) == PROXY_TYPE_PROXY) { - LOG(MODULE_PROXY, "PROXY_TYPE_PROXY") - } - - if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) { - LOG(MODULE_PROXY, "InternetQueryOption failed,GLE=" + QSTRN(GetLastError())) - } - - if (Option[4].Value.pszValue != nullptr) { - LOG(MODULE_PROXY, QString::fromStdWString(Option[4].Value.pszValue)) - } - - INTERNET_VERSION_INFO Version; - nSize = sizeof(INTERNET_VERSION_INFO); - InternetQueryOption(nullptr, INTERNET_OPTION_VERSION, &Version, &nSize); - - if (Option[0].Value.pszValue != nullptr) { - GlobalFree(Option[0].Value.pszValue); - } - - if (Option[3].Value.pszValue != nullptr) { - GlobalFree(Option[3].Value.pszValue); - } - - if (Option[4].Value.pszValue != nullptr) { - GlobalFree(Option[4].Value.pszValue); - } - - return false; - } - bool __SetProxyOptions(LPWSTR proxy_full_addr, bool isPAC) - { - INTERNET_PER_CONN_OPTION_LIST list; - BOOL bReturn; - DWORD dwBufSize = sizeof(list); - // Fill the list structure. - list.dwSize = sizeof(list); - // NULL == LAN, otherwise connectoid name. - list.pszConnection = nullptr; - - if (isPAC) { - LOG(MODULE_PROXY, "Setting system proxy for PAC") - // - list.dwOptionCount = 2; - list.pOptions = new INTERNET_PER_CONN_OPTION[2]; - - // Ensure that the memory was allocated. - if (nullptr == list.pOptions) { - // Return FALSE if the memory wasn't allocated. - return FALSE; - } - - // Set flags. - list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; - list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_AUTO_PROXY_URL; - // Set proxy name. - list.pOptions[1].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL; - list.pOptions[1].Value.pszValue = proxy_full_addr; - } else { - LOG(MODULE_PROXY, "Setting system proxy for Global Proxy") - // - list.dwOptionCount = 3; - list.pOptions = new INTERNET_PER_CONN_OPTION[3]; - - if (nullptr == list.pOptions) { - return false; - } - - // Set flags. - list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; - list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_PROXY; - // Set proxy name. - list.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER; - list.pOptions[1].Value.pszValue = proxy_full_addr; - // Set proxy override. - list.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS; - auto localhost = L"localhost"; - list.pOptions[2].Value.pszValue = NO_CONST(localhost); - } - - // Set the options on the connection. - bReturn = InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); - delete [] list.pOptions; - InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0); - InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0); - return bReturn; - } -#endif - - void SetSystemProxy(const QString &address, int httpPort, int socksPort, bool usePAC) - { - bool hasHTTP = (httpPort != 0); - bool hasSOCKS = (socksPort != 0); - - if (!(hasHTTP || hasSOCKS || usePAC)) { - LOG(MODULE_PROXY, "Nothing?") - return; - } - - if (usePAC) { - LOG(MODULE_PROXY, "Qv2ray will set system proxy to use PAC file") - } else { - if (hasHTTP) { - LOG(MODULE_PROXY, "Qv2ray will set system proxy to use HTTP") - } - - if (hasSOCKS) { - LOG(MODULE_PROXY, "Qv2ray will set system proxy to use SOCKS") - } - } - -#ifdef Q_OS_WIN - QString __a; - - if (usePAC) { - __a = address; - } else { - __a = (hasHTTP ? "http://" : "socks5://") + address + ":" + QSTRN(httpPort); - } - - LOG(MODULE_PROXY, "Windows proxy string: " + __a) - auto proxyStrW = new WCHAR[__a.length() + 1]; - wcscpy(proxyStrW, __a.toStdWString().c_str()); - // - __QueryProxyOptions(); - - if (!__SetProxyOptions(proxyStrW, usePAC)) { - LOG(MODULE_PROXY, "Failed to set proxy.") - } - - __QueryProxyOptions(); -#elif defined(Q_OS_LINUX) - QStringList actions; - auto proxyMode = usePAC ? "auto" : "manual"; - actions << QString("gsettings set org.gnome.system.proxy mode '%1'").arg(proxyMode); - - if (usePAC) { - actions << QString("gsettings set org.gnome.system.proxy autoconfig-url '%1'").arg(address); - } else { - if (hasHTTP) { - actions << QString("gsettings set org.gnome.system.proxy.http host '%1'").arg(address); - actions << QString("gsettings set org.gnome.system.proxy.http port %1").arg(httpPort); - // - actions << QString("gsettings set org.gnome.system.proxy.https host '%1'").arg(address); - actions << QString("gsettings set org.gnome.system.proxy.https port %1").arg(httpPort);; - } - - if (hasSOCKS) { - actions << QString("gsettings set org.gnome.system.proxy.socks host '%1'").arg(address); - actions << QString("gsettings set org.gnome.system.proxy.socks port %1").arg(socksPort); - } - } - - // note: do not use std::all_of / any_of / none_of, - // because those are short-circuit and cannot guarantee atomicity. - auto result = std::count_if(actions.cbegin(), actions.cend(), [](const QString & action) { - DEBUG(MODULE_PROXY, action) - return QProcess::execute(action) == QProcess::NormalExit; - }) == actions.size(); - - if (!result) { - LOG(MODULE_PROXY, "Something wrong happens when setting system proxy -> Gnome ONLY.") - LOG(MODULE_PROXY, "If you are using KDE Plasma and receiving this message, just simply ignore this.") - } - - Q_UNUSED(result); -#else - - for (auto service : macOSgetNetworkServices()) { - LOG(MODULE_PROXY, "Setting proxy for interface: " + service) - - if (usePAC) { - QProcess::execute("/usr/sbin/networksetup -setautoproxystate " + service + " on"); - QProcess::execute("/usr/sbin/networksetup -setautoproxyurl " + service + " " + address); - } else { - if (hasHTTP) { - QProcess::execute("/usr/sbin/networksetup -setwebproxystate " + 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 -setsecurewebproxy " + service + " " + address + " " + QSTRN(httpPort)); - } - - if (hasSOCKS) { - QProcess::execute("/usr/sbin/networksetup -setsocksfirewallproxystate " + service + " on"); - QProcess::execute("/usr/sbin/networksetup -setsocksfirewallproxy " + service + " " + address + " " + QSTRN(socksPort)); - } - } - } - -#endif - } - - void ClearSystemProxy() - { -#ifdef Q_OS_WIN - LOG(MODULE_PROXY, "Cleaning system proxy settings.") - INTERNET_PER_CONN_OPTION_LIST list; - BOOL bReturn; - DWORD dwBufSize = sizeof(list); - // Fill out list struct. - list.dwSize = sizeof(list); - // nullptr == LAN, otherwise connectoid name. - list.pszConnection = nullptr; - // Set three options. - list.dwOptionCount = 1; - list.pOptions = new INTERNET_PER_CONN_OPTION[list.dwOptionCount]; - - // Make sure the memory was allocated. - if (nullptr == list.pOptions) { - // Return FALSE if the memory wasn't allocated. - LOG(MODULE_PROXY, "Failed to allocat memory in DisableConnectionProxy()") - } - - // Set flags. - list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; - list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT; - // - // Set the options on the connection. - bReturn = InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); - delete [] list.pOptions; - InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0); - InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0); -#elif defined(Q_OS_LINUX) - QProcess::execute("gsettings set org.gnome.system.proxy mode 'none'"); -#else - - for (auto service : macOSgetNetworkServices()) { - LOG(MODULE_PROXY, "Clearing proxy for interface: " + service) - QProcess::execute("/usr/sbin/networksetup -setautoproxystate " + service + " off"); - QProcess::execute("/usr/sbin/networksetup -setwebproxystate " + service + " off"); - QProcess::execute("/usr/sbin/networksetup -setsecurewebproxystate " + service + " off"); - QProcess::execute("/usr/sbin/networksetup -setsocksfirewallproxystate " + service + " off"); - } - -#endif - } -} From ae85a8dcbb0f7ef199f9775bcdcb707648238f67 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 22 Feb 2020 23:08:06 +0800 Subject: [PATCH 034/332] wip: add: added somewhat more functionalities and UI --- assets/icons/ui_dark/connect.png | Bin 0 -> 1425 bytes assets/icons/ui_light/connect.png | Bin 0 -> 1441 bytes makespec/BUILDVERSION | 2 +- resources.qrc | 2 + src/common/QvHelpers.hpp | 1 - src/core/CoreUtils.cpp | 52 ---- src/core/CoreUtils.hpp | 13 +- src/core/connection/Serialization.cpp | 32 +- src/core/handler/ConnectionHandler.cpp | 64 ++++ src/core/handler/ConnectionHandler.hpp | 9 +- src/main.cpp | 4 +- src/ui/editors/w_RoutesEditor.cpp | 5 +- src/ui/w_MainWindow.cpp | 36 +-- src/ui/w_MainWindow.hpp | 1 - src/ui/w_MainWindow.ui | 168 ++-------- src/ui/w_SubscriptionManager.cpp | 3 +- src/ui/widgets/ConnectionInfoWidget.cpp | 42 +-- src/ui/widgets/ConnectionInfoWidget.hpp | 2 +- src/ui/widgets/ConnectionInfoWidget.ui | 387 ++++++++++++++---------- src/ui/widgets/ConnectionItemWidget.cpp | 12 +- src/ui/widgets/ConnectionItemWidget.hpp | 4 +- src/ui/widgets/ConnectionItemWidget.ui | 3 + 22 files changed, 400 insertions(+), 442 deletions(-) create mode 100644 assets/icons/ui_dark/connect.png create mode 100644 assets/icons/ui_light/connect.png diff --git a/assets/icons/ui_dark/connect.png b/assets/icons/ui_dark/connect.png new file mode 100644 index 0000000000000000000000000000000000000000..2a171df629cc81f9a60f06792f42063bb45ee9f7 GIT binary patch literal 1425 zcmZuxc~H`M6#s$;gd(EmS&AfGCAeZ=+juM#geOGHf711rDO@k9O5m#G703 zX5*8@ldAdaH5cPU2w+)d2h>?=Wy_I9>$7t}Mc9{5U{4?M+s529EV1$Mxx0KJ%5_%I zUK#WB_EPdA^K&TjTQ11jL8VjL9r1+}EpffTAfwT|XyJ7<-LArD9XFH2ic0HQ3 z{k9mknJEv>n}V%`nD7noDbaCpbMa?h)e6MAQZJ>pnyN77-4NnL=B0(t{B6Ze@c^}& zlWV~{kJT6jrK^v}s?wY4TJeY~+K|V!Aq2BA5{FdkG;EWC@b;=ih?HA0>S`O{EXb({FM-Rw z%Bea`g!EPv&9_fjdD$J#YGRqp7}|%0YSfL)->rc1G~q2d=Xhk8aSnUpzpBbS(&N;x zJ61piOQo%Adc8GqWGlBtNB+Fsp_jAQ1eQIi)*O#ZXuDWK z0Vr2OFm<$OfP#D}=u}qIo%Ftp&aQ275DYkjh0e-kalJW@FJ3S!eHEik_2-0#_l%~< zf*5X~pi+p$?U`t7Ju+WEu5BMk3zc~2(D&GUMMWJV>%}8{B=mPLmiXh)DBwcZ)H1odf z+yVUk%(iY=`c*|DZY0`C^d3M1`5@;zpJn`_WU0mR@X9st$;&el2K8X1Hk4a&DDuc9 z>B^s+z5?xn1!M3`VB1yW;S`P`D;o1GVA;NZrL6?c#RL2uj8wRkKg0YmrC+2SJc_@O~fMlJB%bVy6T_jp9SR~m>r-&K% z4O0!H1{t*BEd5I`k77E5@yBUBtk_KnVmt%nQY2!}L7}KrUn0F14fA^Rwqxo literal 0 HcmV?d00001 diff --git a/assets/icons/ui_light/connect.png b/assets/icons/ui_light/connect.png new file mode 100644 index 0000000000000000000000000000000000000000..bf489daeb24089eb8dda92be8bf9677498eb82b2 GIT binary patch literal 1441 zcmZuxdo%whJ#F12I-?w)h+{p)_tJ)irzpKKp5Hzj#(c>sVC$(`sc z>Bv^fq9pZq!ihcrWFkpKXG(JU(q!LtT|X@u5%bEjVOCYBNsHF4n#cDCXak`du@p5s z1?e5VMb>D_ic5)+netkeiP1dSM-4uiE;sGO@41oXp11?XYo+%_hAKuKuMP5iYoolt z>PT%A9!aP)=#P?G&)Ivfg3<7J+>`j-sO`j&KAW)e>lT8lBMQo(~>O5O*DVrtel^=$kfO*9fM3RU zsj^Sp?CY7rk?b=F%G-yVfuP%zrOu9blN|uunD7cD)98-Y7}USmxWV)E_U7$hiJ_M0 zR?715q#h*G*mWJoy6rMte`*YCLW>nN8jHZ5azErMmA?SEO8nfJM{$J$=>+}jxgi;# zl(rq20JKzQitFkW^^&*Y(`v+QZ zbSY7818$5d1f^ERL~z~@qf?&;1oDNw<27cF+ZVqDGpYu_sl6aE{0r)cLXS6Yxgiq8 zk=X((CQ`Qr;R^(&@w&Xgzbt>SqJXpDb3zdjT&g|&4@Ga)vwR4$39!gM!y+3YOo*89 z#!j^ijg)(n;5fQK3W*ld&sf@-1DY~Nk3p5?yMZKBS^S0FHXuA)!*$pSr_w1Iyg4^J z8!Nvj`o5hV*fU5?#;|WyN5tH%+s6L20rza-5T;w0_@pC~-r@Hijp%YRvn=f`awFsk38Kt8DgX`T?@1O z71;;!JbDI(Y{z1`n4Q&g7CM}9y-IK;+w$s+J|dC6>3Yj2fpoH=_<^(MN(V^OYkjDQ zjHiJ~^y}Qiz;PKC7K_f#paHL2Cf^a_4-c){lP9G4>#w+Bz`#?i*L~u>HmIC~C@YSw zHsF~zys5yyn{A!4BSs$Vqsvh^Kh`TjW+IA+MD@;)P*|o92Hl>aa87@=Tr!S~0`gtk zYyEr2YA!>fw4X$}9Dgx&UR!c9ae&Lu%XWnN&)6#HRRqwj~8S2gkY`M5mZJE&jS~x27{`3 zw0={nb4@&;W07)MhP#u9XOf~m+RpE8OQE!kwnlRi0aVn5YE0$rUs4*4^IOs-#~4m1 zt1s#~R@oQC-rSX>GT2_g3$sXBnvw^a{#=L8@l8&JIL|MOAc>*`O7^QgDVf7H+vv6Ghby9tLlgnjG7!ky4?v8;h$Uvt?=e( z#Ja|;Om53XjKNDPF2zP%?pq)+kG9vGOU#KShRVJ>6w4=^)o!XpGP4H;@pj}9aXeLF fbfV4ZyAdri2tTC=WeQyjCDsc_u3kijOGx^Ew`Yjn literal 0 HcmV?d00001 diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index c9a7382c..1b89d3ac 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3890 +3891 diff --git a/resources.qrc b/resources.qrc index 14a025bb..3ed9135b 100644 --- a/resources.qrc +++ b/resources.qrc @@ -24,5 +24,7 @@ assets/icons/qv2ray.ico assets/icons/qv2ray.png assets/credit.html + assets/icons/ui_dark/connect.png + assets/icons/ui_light/connect.png diff --git a/src/common/QvHelpers.hpp b/src/common/QvHelpers.hpp index 55d4372e..ca98043c 100644 --- a/src/common/QvHelpers.hpp +++ b/src/common/QvHelpers.hpp @@ -8,7 +8,6 @@ #define REGEX_PORT_NUMBER R"(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])*)" namespace Qv2ray::common - { QStringList GetFileList(QDir dir); QString Base64Encode(QString string); diff --git a/src/core/CoreUtils.cpp b/src/core/CoreUtils.cpp index 5e54924c..22a7f3c3 100644 --- a/src/core/CoreUtils.cpp +++ b/src/core/CoreUtils.cpp @@ -1,59 +1,7 @@ #include "CoreUtils.hpp" -#include "common/QvHelpers.hpp" -#include "QApplication" namespace Qv2ray::core { - tuple GetConnectionInfo(const CONFIGROOT &root) - { - bool validOutboundFound = false; - QString host; - int port; - - for (auto item : root["outbounds"].toArray()) { - OUTBOUND outBoundRoot = OUTBOUND(item.toObject()); - QString outboundType = ""; - validOutboundFound = GetOutboundData(outBoundRoot, &host, &port, &outboundType); - - if (validOutboundFound) { - return make_tuple(host, port, outboundType); - } else { - LOG(MODULE_UI, "Unknown outbound entry: " + outboundType + ", cannot deduce host and port.") - } - } - - return make_tuple(QObject::tr("N/A"), 0, QObject::tr("N/A")); - } - - bool GetOutboundData(const OUTBOUND &out, QString *host, int *port, QString *protocol) - { - // Set initial values. - *host = QObject::tr("N/A"); - *port = 0; - *protocol = out["protocol"].toString(QObject::tr("N/A")).toLower(); - - if (*protocol == "vmess") { - auto Server = StructFromJsonString(JsonToString(out["settings"].toObject()["vnext"].toArray().first().toObject())); - *host = Server.address; - *port = Server.port; - return true; - } else if (*protocol == "shadowsocks") { - auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject()); - auto Server = StructFromJsonString(x); - *host = Server.address; - *port = Server.port; - return true; - } else if (*protocol == "socks") { - auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject()); - auto Server = StructFromJsonString(x); - *host = Server.address; - *port = Server.port; - return true; - } else { - return false; - } - } - bool IsComplexConfig(CONFIGROOT root) { bool cRouting = root.contains("routing"); diff --git a/src/core/CoreUtils.hpp b/src/core/CoreUtils.hpp index 909d49bb..d0284b23 100644 --- a/src/core/CoreUtils.hpp +++ b/src/core/CoreUtils.hpp @@ -1,10 +1,14 @@ #pragma once - -#include "base/Qv2rayBase.hpp" -#include "core/config/ConfigBackend.hpp" +#include +#include +#include namespace Qv2ray::core { + using namespace Qv2ray::base; + using namespace Qv2ray::base::safetype; + using namespace Qv2ray::base::objects; + // inline QString getTag(const INBOUND &in) { return in["tag"].toString(); @@ -20,9 +24,6 @@ namespace Qv2ray::core return in.QV2RAY_RULE_TAG; } - /// Host, port, type - tuple GetConnectionInfo(const CONFIGROOT &alias); - bool GetOutboundData(const OUTBOUND &out, QString *host, int *port, QString *protocol); bool IsComplexConfig(CONFIGROOT root); } diff --git a/src/core/connection/Serialization.cpp b/src/core/connection/Serialization.cpp index 42ba4cb3..1fc175de 100644 --- a/src/core/connection/Serialization.cpp +++ b/src/core/connection/Serialization.cpp @@ -26,22 +26,22 @@ namespace Qv2ray::core::connection QString ConvertConfigToString(const CONFIGROOT &server, const QString &alias, bool isSip002) { OUTBOUND outbound = OUTBOUND(server["outbounds"].toArray().first().toObject()); - auto info = GetConnectionInfo(server); - auto type = get<2>(info); - QString sharelink = ""; - - if (type == "vmess") { - auto vmessServer = StructFromJsonString(JsonToString(outbound["settings"].toObject()["vnext"].toArray().first().toObject())); - auto transport = StructFromJsonString(JsonToString(outbound["streamSettings"].toObject())); - sharelink = ConvertConfigToVMessString(transport, vmessServer, alias); - } else if (type == "shadowsocks") { - auto ssServer = StructFromJsonString(JsonToString(outbound["settings"].toObject()["servers"].toArray().first().toObject())); - sharelink = ConvertConfigToSSString(ssServer, alias, isSip002); - } else { - LOG(MODULE_CONNECTION, "Unsupported outbound type: " + type) - } - - return sharelink; + //auto info = GetConnectionInfo(server); + //auto type = get<2>(info); + //QString sharelink = ""; + // + //if (type == "vmess") { + // auto vmessServer = StructFromJsonString(JsonToString(outbound["settings"].toObject()["vnext"].toArray().first().toObject())); + // auto transport = StructFromJsonString(JsonToString(outbound["streamSettings"].toObject())); + // sharelink = ConvertConfigToVMessString(transport, vmessServer, alias); + //} else if (type == "shadowsocks") { + // auto ssServer = StructFromJsonString(JsonToString(outbound["settings"].toObject()["servers"].toArray().first().toObject())); + // sharelink = ConvertConfigToSSString(ssServer, alias, isSip002); + //} else { + // LOG(MODULE_CONNECTION, "Unsupported outbound type: " + type) + //} + return "WIP"; + //return sharelink; } // From https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2) diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index 63704d1b..c6c39a97 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -71,6 +71,13 @@ namespace Qv2ray::core::handlers return connections[id]; } + const optional QvConnectionHandler::DeleteConnection(const ConnectionId &id) + { + // TODO + Q_UNUSED(id) + return ""; + } + const optional QvConnectionHandler::StartConnection(const ConnectionId &identifier) { if (!connections.contains(identifier)) { @@ -123,10 +130,67 @@ namespace Qv2ray::core::handlers delete kernelInstance; } + const CONFIGROOT QvConnectionHandler::CHGetConnectionRoot_p(const ConnectionId &id) const + { + return connections.contains(id) ? CHGetConnectionRoot_p(connections[id].groupId, id) : CONFIGROOT(); + } + const CONFIGROOT QvConnectionHandler::CHGetConnectionRoot_p(const GroupId &group, const ConnectionId &id) const { auto path = group.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; path.prepend(groups[group].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR); return CONFIGROOT(JsonFromString(StringFromFile(path))); } + // + + const tuple QvConnectionHandler::GetConnectionInfo(const ConnectionId &id) + { + auto root = CHGetConnectionRoot_p(id); + bool validOutboundFound = false; + QString host; + int port; + + for (auto item : root["outbounds"].toArray()) { + OUTBOUND outBoundRoot = OUTBOUND(item.toObject()); + QString outboundType = ""; + validOutboundFound = CHGetOutboundData_p(outBoundRoot, &host, &port); + + if (validOutboundFound) { + return make_tuple(host, port); + } else { + LOG(MODULE_CORE_HANDLER, "Unknown outbound entry: " + outboundType + ", cannot deduce host and port.") + } + } + + return make_tuple(QObject::tr("N/A"), 0); + } + + bool QvConnectionHandler::CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port) + { + // Set initial values. + *host = QObject::tr("N/A"); + *port = 0; + auto protocol = out["protocol"].toString(QObject::tr("N/A")).toLower(); + + if (protocol == "vmess") { + auto Server = StructFromJsonString(JsonToString(out["settings"].toObject()["vnext"].toArray().first().toObject())); + *host = Server.address; + *port = Server.port; + return true; + } else if (protocol == "shadowsocks") { + auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject()); + auto Server = StructFromJsonString(x); + *host = Server.address; + *port = Server.port; + return true; + } else if (protocol == "socks") { + auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject()); + auto Server = StructFromJsonString(x); + *host = Server.address; + *port = Server.port; + return true; + } else { + return false; + } + } } diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 7f864dfa..cdf84bfc 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -37,6 +37,9 @@ namespace Qv2ray::core::handlers const optional DuplicateConnection(const ConnectionId &id); const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); // + // Get Conncetion Property + const tuple GetConnectionInfo(const ConnectionId &connectionId); + // // Misc Connection Operations const optional TestLatency(const ConnectionId &id); const optional TestLatency(const GroupId &id); @@ -79,7 +82,9 @@ namespace Qv2ray::core::handlers void OnSubscriptionUpdateFinished(const GroupId &id); private: + bool CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port); optional CHTryStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); + const CONFIGROOT CHGetConnectionRoot_p(const ConnectionId &id) const; const CONFIGROOT CHGetConnectionRoot_p(const GroupId &group, const ConnectionId &id) const; bool CHSaveConnectionConfig(CONFIGROOT obj, const ConnectionId &id, bool override); // @@ -89,9 +94,11 @@ namespace Qv2ray::core::handlers int saveTimerId; QHash groups; QHash connections; + // + QHash connectionRootCache; }; - inline QvConnectionHandler *ConnectionHandler = nullptr; + inline ::Qv2ray::core::handlers::QvConnectionHandler *ConnectionManager = nullptr; } using namespace Qv2ray::core::handlers; diff --git a/src/main.cpp b/src/main.cpp index 76d65ddb..90547e69 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -453,7 +453,7 @@ int main(int argc, char *argv[]) #endif //_qApp.setAttribute(Qt::AA_DontUseNativeMenuBar); // Initialise Connection Handler - ConnectionHandler = new QvConnectionHandler(); + ConnectionManager = new QvConnectionHandler(); // Show MainWindow MainWindow w; QObject::connect(&_qApp, &SingleApplication::instanceStarted, [&]() { @@ -477,7 +477,7 @@ int main(int argc, char *argv[]) }); #endif auto rcode = _qApp.exec(); - delete ConnectionHandler; + delete ConnectionManager; LOG(MODULE_INIT, "Quitting normally") return rcode; #ifndef QT_DEBUG diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index c35c8a61..7d028706 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -156,8 +156,9 @@ void RouteEditor::onNodeClicked(Node &n) if (isOut) { alias = GetFirstNodeData(n, QvOutboundNodeModel, OutboundNodeData)->GetOutbound(); QJsonObject _root = outbounds[alias].raw(); - auto result = GetOutboundData(OUTBOUND(_root), &host, &port, &protocol); - Q_UNUSED(result) + throw new runtime_error("Not implemented"); + //auto result = GetOutboundData(OUTBOUND(_root), &host, &port, &protocol); + //Q_UNUSED(result) } else { alias = GetFirstNodeData(n, QvInboundNodeModel, InboundNodeData)->GetInbound(); QJsonObject _root = inbounds[alias].raw(); diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 729f03c9..60287bfe 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -116,8 +116,8 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr this->setWindowIcon(QIcon(":/assets/icons/qv2ray.png")); hTray.setIcon(QIcon(GlobalConfig.uiConfig.useDarkTrayIcon ? ":/assets/icons/ui_dark/tray.png" : ":/assets/icons/ui_light/tray.png")); importConfigButton->setIcon(QICON_R("import.png")); - duplicateBtn->setIcon(QICON_R("duplicate.png")); - removeConfigButton->setIcon(QICON_R("delete.png")); + //duplicateBtn->setIcon(QICON_R("duplicate.png")); + //removeConfigButton->setIcon(QICON_R("delete.png")); //editConfigButton->setIcon(QICON_R("edit.png")); //editJsonBtn->setIcon(QICON_R("json.png")); //// @@ -229,31 +229,15 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr void MainWindow::SetEditWidgetEnable(bool enabled) { - removeConfigButton->setEnabled(enabled); + //removeConfigButton->setEnabled(enabled); //editConfigButton->setEnabled(enabled); - duplicateBtn->setEnabled(enabled); + //duplicateBtn->setEnabled(enabled); //editJsonBtn->setEnabled(enabled); //shareBtn->setEnabled(enabled); // Allow ping all. //pingTestBtn->setText(enabled ? tr("Ping") : tr("Ping All")); } -void MainWindow::mouseReleaseEvent(QMouseEvent *e) -{ - Q_UNUSED(e) - //// If mouse is on the logLabel, switch log source. - //if (logbox->underMouse()) { - // //auto layout = masterLogBrowser->document()->setDocumentLayout() - // currentLogBrowserId = (currentLogBrowserId + 1) % logTextBrowsers.count(); - // masterLogBrowser->setDocument(currentLogBrowser->document()); - // masterLogBrowser->document()->setDocumentMargin(4); - // masterLogBrowser->document()->adjustSize(); - // masterLogBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap); - // auto bar = masterLogBrowser->verticalScrollBar(); - // bar->setValue(bar->maximum()); - //} -} - void MainWindow::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { @@ -321,16 +305,16 @@ void MainWindow::VersionUpdate(QByteArray &data) void MainWindow::OnConfigListChanged(bool need_restart) { LOG(MODULE_UI, "Loading data...") - auto groups = ConnectionHandler->AllGroups(); + auto groups = ConnectionManager->AllGroups(); for (auto group : groups) { - auto groupItem = new QTreeWidgetItem(QStringList() << "" << ConnectionHandler->GetGroup(group).displayName); + auto groupItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetGroup(group).displayName); connectionListWidget->addTopLevelItem(groupItem); connectionListWidget->setItemWidget(groupItem, 0, new ConnectionItemWidget(group, connectionListWidget)); - auto connections = ConnectionHandler->Connections(group); + auto connections = ConnectionManager->Connections(group); for (auto connection : connections) { - auto connectionItem = new QTreeWidgetItem(QStringList() << "" << ConnectionHandler->GetConnection(connection).displayName); + auto connectionItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetConnection(connection).displayName); groupItem->addChild(connectionItem); auto widget = new ConnectionItemWidget(connection, connectionListWidget); connect(widget, &ConnectionItemWidget::RequestWidgetFocus, this, &MainWindow::onConnectionWidgetFocusRequested); @@ -448,8 +432,8 @@ void MainWindow::on_stopButton_clicked() action_Tray_Reconnect->setEnabled(false); // Set to false as the system proxy has been cleared in the StopConnection function. tray_SystemProxyMenu->setEnabled(false); - startButton->setEnabled(true); - stopButton->setEnabled(false); + //startButton->setEnabled(true); + //stopButton->setEnabled(false); //// //netspeedLabel->setText("0.00 B/s\r\n0.00 B/s"); //dataamountLabel->setText("0.00 B\r\n0.00 B"); diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 78f20914..2b7ae7d8 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -65,7 +65,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow static MainWindow *mwInstance; protected: - void mouseReleaseEvent(QMouseEvent *e) override; void keyPressEvent(QKeyEvent *e) override; void timerEvent(QTimerEvent *event) override; void closeEvent(QCloseEvent *) override; diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 2906d25a..33c2d8b1 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -33,42 +33,14 @@ + + 0 + - + 5 - - - - Connect - - - - - - - false - - - Disconnect - - - - - - - Reconnect - - - - - - - Clear Log - - - @@ -189,44 +161,6 @@ - - - - - 0 - 0 - - - - Delete a connection - - - Delete - - - - 22 - 22 - - - - - - - - Duplicate connection - - - Duplicate - - - - 22 - 22 - - - - @@ -246,6 +180,12 @@ + + 2 + + + 2 + @@ -390,38 +330,28 @@ 0 0 480 - 851 + 716 + + 2 + 0 - - - - - 13 - - - - Connection Info - - - - - - - Qt::Horizontal - - - 0 - 250 + 215 + + + + + 16777215 + 215 @@ -437,25 +367,12 @@ 0 + + 0 + - - - - Qt::Vertical - - - QSizePolicy::Minimum - - - - 20 - 30 - - - - @@ -499,22 +416,6 @@ - - - - Qt::Vertical - - - QSizePolicy::Minimum - - - - 20 - 30 - - - - @@ -544,6 +445,13 @@ + + + + Clear Log + + + @@ -575,16 +483,7 @@ - - - Export Connection - - - - - - @@ -788,15 +687,10 @@ - startButton - stopButton - reconnectButton - clearlogButton subsButton preferencesBtn connectionListWidget importConfigButton - removeConfigButton diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 7db826a1..cb65164c 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -1,7 +1,6 @@ #include "w_SubscriptionManager.hpp" #include "common/QvHelpers.hpp" -#include "core/CoreUtils.hpp" - +#include "core/config/ConfigBackend.hpp" #include "core/connection/ConnectionIO.hpp" #include "core/connection/Serialization.hpp" diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 530ce965..d08034af 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -1,4 +1,5 @@ #include "ConnectionInfoWidget.hpp" +#include "core/CoreUtils.hpp" ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent), connectionId("null"), groupId("null") @@ -12,25 +13,27 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden connectionId = get<1>(_identifier); if (connectionId.toString() != "null") { - connNameLabel->setText(ConnectionHandler->GetConnection(connectionId).displayName); - groupLabel->setText(ConnectionHandler->GetGroup(groupId).displayName); + connNameLabel->setText(ConnectionManager->GetConnection(connectionId).displayName); + groupLabel->setText(ConnectionManager->GetGroup(groupId).displayName); + protocolLabel->setText(ConnectionManager->GetConnectionBasicInfo(connectionId)); + auto x = ConnectionManager->GetConnectionInfo(connectionId); + addressLabel->setText(get<0>(x)); + portLabel->setNum(get<1>(x)); + // + editJsonBtn->setEnabled(true); + connectBtn->setEnabled(true); + duplicateBtn->setEnabled(true); } else { - connNameLabel->setText(ConnectionHandler->GetGroup(groupId).displayName); + connNameLabel->setText(ConnectionManager->GetGroup(groupId).displayName); + groupLabel->setText(tr("N/A")); + protocolLabel->setText(tr("N/A")); + addressLabel->setText(tr("N/A")); + portLabel->setText(tr("N/A")); + // + editJsonBtn->setEnabled(false); + connectBtn->setEnabled(false); + duplicateBtn->setEnabled(false); } - - // - //auto isComplexConfig = IsComplexConfig(conf.config); - //routeCountLabel->setText(isComplexConfig ? tr("Complex") : tr("Simple")); - // - //if (conf.configType == CONNECTION_SUBSCRIPTION) { - // routeCountLabel->setText(routeCountLabel->text().append(" (" + tr("Subscription") + ":" + conf.subscriptionName + ")")); - //} - // - //// Get Connection info - //auto host_port = MWGetConnectionInfo(fullIdentifier.IdentifierString()); - //_hostLabel->setText(get<0>(host_port)); - //_portLabel->setText(QSTRN(get<1>(host_port))); - //_OutBoundTypeLabel->setText(get<2>(host_port)); } ConnectionInfoWidget::~ConnectionInfoWidget() @@ -39,6 +42,7 @@ ConnectionInfoWidget::~ConnectionInfoWidget() void ConnectionInfoWidget::on_connectBtn_clicked() { + ConnectionManager->StartConnection(connectionId); } void ConnectionInfoWidget::on_editBtn_clicked() @@ -49,7 +53,7 @@ void ConnectionInfoWidget::on_editJsonBtn_clicked() { } -void ConnectionInfoWidget::on_pushButton_clicked() +void ConnectionInfoWidget::on_deleteBtn_clicked() { - QGuiApplication::clipboard()->setText(shareLinkTxt->text()); + ConnectionManager->DeleteConnection(connectionId); } diff --git a/src/ui/widgets/ConnectionInfoWidget.hpp b/src/ui/widgets/ConnectionInfoWidget.hpp index 653bc465..6c8de10f 100644 --- a/src/ui/widgets/ConnectionInfoWidget.hpp +++ b/src/ui/widgets/ConnectionInfoWidget.hpp @@ -16,7 +16,7 @@ class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget void on_connectBtn_clicked(); void on_editBtn_clicked(); void on_editJsonBtn_clicked(); - void on_pushButton_clicked(); + void on_deleteBtn_clicked(); private: ConnectionId connectionId; diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index 165155d9..f2fd393e 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -6,15 +6,212 @@ 0 0 - 440 - 250 + 431 + 242 Form - - + + + 0 + + + + + + + + 14 + + + + Connection Name + + + + + + + Delete Connection + + + + + + + :/assets/icons/ui_light/delete.png:/assets/icons/ui_light/delete.png + + + + + + + Edit Connection + + + + + + + :/assets/icons/ui_light/edit.png:/assets/icons/ui_light/edit.png + + + + + + + Delete Connection + + + + + + + :/assets/icons/ui_light/duplicate.png:/assets/icons/ui_light/duplicate.png + + + + + + + Connect To This Connection + + + + + + + :/assets/icons/ui_light/connect.png:/assets/icons/ui_light/connect.png + + + + + + + + + + + Group + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + IBeamCursor + + + type + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Protocol + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + IBeamCursor + + + proto + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Address + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + IBeamCursor + + + addr + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Port + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + IBeamCursor + + + port + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Link + + + + + + + true + + + + + + @@ -46,150 +243,36 @@ 150 - - QFrame::Box + + + 150 + 150 + + + + QR Code - TextLabel + - - true + + :/assets/icons/qv2ray.ico Qt::AlignCenter - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - Group - - - - - - - IBeamCursor - - - type - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Protocol - - - - - - - IBeamCursor - - - proto - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Address - - - - - - - IBeamCursor - - - addr - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Port Number - - - - - - - IBeamCursor - - - port - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - - - - 11 - - - - Connection Name - - - - - - - - - Connect - - - - - - - Edit - - - + + + + Edit Connection Config as JSON + Edit JSON @@ -197,40 +280,10 @@ - - - - - - Share Link - - - - - - - true - - - - - - - Copy - - - - - - - - - Qt::Horizontal - - - - + + + diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index f42899ce..f2e00152 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -4,18 +4,18 @@ ConnectionItemWidget::ConnectionItemWidget(QWidget *parent) : QWidget(parent), connectionId("null"), groupId("null") { setupUi(this); - connect(ConnectionHandler, &QvConnectionHandler::OnConnected, this, &ConnectionItemWidget::OnConnected); + connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &ConnectionItemWidget::OnConnected); } ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &identifier, QWidget *parent): ConnectionItemWidget(parent) { - auto connection = ConnectionHandler->GetConnection(identifier); + auto connection = ConnectionManager->GetConnection(identifier); connectionId = identifier; groupId = connection.groupId; itemType = NODE_ITEM; connNameLabel->setText("" + connection.displayName); latencyLabel->setText(QSTRN(connection.latency) + " " + tr("ms")); - connTypeLabel->setText(tr("Type: ") + ConnectionHandler->GetConnectionBasicInfo(identifier)); + connTypeLabel->setText(tr("Type: ") + ConnectionManager->GetConnectionBasicInfo(identifier)); dataLabel->setText(FormatBytes(connection.upLinkData + connection.downLinkData)); // indentSpacer->changeSize(10, indentSpacer->sizeHint().height()); @@ -26,8 +26,8 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : { groupId = id; itemType = GROUP_HEADER_ITEM; - auto displayName = ConnectionHandler->GetGroup(id).displayName; - auto connectionCount = ConnectionHandler->Connections(id).count(); + auto displayName = ConnectionManager->GetGroup(id).displayName; + auto connectionCount = ConnectionManager->Connections(id).count(); connNameLabel->setText(/*"• " +*/ displayName); latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections"))); // @@ -41,7 +41,7 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : void ConnectionItemWidget::BeginConnection() { if (itemType == NODE_ITEM) { - ConnectionHandler->StartConnection(connectionId); + ConnectionManager->StartConnection(connectionId); } else { LOG(MODULE_UI, "Trying to start a non-connection entry, this call is illegal.") } diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index 2771f312..adea0b7b 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -22,12 +22,12 @@ class ConnectionItemWidget : public QWidget, private Ui::ConnectionWidget inline bool NameMatched(const QString &arg) { auto searchString = arg.toLower(); - auto headerMatched = ConnectionHandler->GetGroup(groupId).displayName.toLower().contains(arg); + auto headerMatched = ConnectionManager->GetGroup(groupId).displayName.toLower().contains(arg); if (itemType != NODE_ITEM) { return headerMatched; } else { - return headerMatched || ConnectionHandler->GetConnection(connectionId).displayName.toLower().contains(searchString); + return headerMatched || ConnectionManager->GetConnection(connectionId).displayName.toLower().contains(searchString); } } inline const tuple Identifier() const diff --git a/src/ui/widgets/ConnectionItemWidget.ui b/src/ui/widgets/ConnectionItemWidget.ui index 2157258b..f0ee95ff 100644 --- a/src/ui/widgets/ConnectionItemWidget.ui +++ b/src/ui/widgets/ConnectionItemWidget.ui @@ -32,6 +32,9 @@ + + 5 + From ca3799edc674936efd8ea5b71aba0c74c36f7b18 Mon Sep 17 00:00:00 2001 From: alluLinger Date: Sat, 22 Feb 2020 21:11:33 +0800 Subject: [PATCH 035/332] fix editor subAddress/subName/subInv same time the changing data will lose --- src/ui/w_SubscriptionManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 72f586d3..b00fb980 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -108,6 +108,10 @@ void SubscribeEditor::on_updateButton_clicked() SaveGlobalConfig(GlobalConfig); // This will set the name to the new name. LoadSubscriptionList(subscriptions); + // Keep subAddress && Interval changes + // Update thing still down + subAddrTxt->setText(newAddress); + updateIntervalSB->setValue(newUpdateInterval); QvMessageBoxInfo(this, tr("Renaming a subscription"), tr("Successfully renamed a subscription")); } From d1c8e1f8b348062c13a78d7f018dcf7900f95a11 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 23 Feb 2020 21:10:25 +0800 Subject: [PATCH 036/332] wip: add: added speed chart and log box functionality --- Qv2ray.pro | 5 +- makespec/BUILDVERSION | 2 +- src/core/handler/ConnectionHandler.cpp | 5 +- src/core/handler/ConnectionHandler.hpp | 22 +- src/core/handler/SubscriptionHandler.cpp | 1 - src/core/handler/V2rayInstanceHandler.cpp | 10 +- src/core/handler/V2rayInstanceHandler.hpp | 0 src/core/kernel/APIBackend.cpp | 41 ++- src/core/kernel/APIBackend.hpp | 23 +- src/core/kernel/KernelInteractions.cpp | 92 +------ src/core/kernel/KernelInteractions.hpp | 24 +- src/ui/w_MainWindow.cpp | 295 +++++++--------------- src/ui/w_MainWindow.hpp | 19 +- src/ui/w_MainWindow.ui | 232 +++++++++-------- src/ui/w_MainWindow_extra.cpp | 3 +- src/ui/widgets/ConnectionInfoWidget.cpp | 6 +- src/ui/widgets/ConnectionInfoWidget.ui | 154 +++++------ src/ui/widgets/ConnectionItemWidget.cpp | 2 +- 18 files changed, 405 insertions(+), 531 deletions(-) delete mode 100644 src/core/handler/SubscriptionHandler.cpp delete mode 100644 src/core/handler/V2rayInstanceHandler.hpp diff --git a/Qv2ray.pro b/Qv2ray.pro index 62900ead..b3494c0f 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -86,9 +86,10 @@ Qv2rayAddSource(core, connection, Generation, cpp, hpp) Qv2rayAddSource(core, connection, Serialization, cpp, hpp) Qv2rayAddSource(core, kernel, KernelInteractions, cpp, hpp) Qv2rayAddSource(core, kernel, APIBackend, cpp, hpp) +# Connection Handlers Qv2rayAddSource(core, handler, ConnectionHandler, cpp, hpp) -Qv2rayAddSource(core, handler, SubscriptionHandler, cpp) -Qv2rayAddSource(core, handler, V2rayInstanceHandler, cpp, hpp) +Qv2rayAddSource(core, handler, V2rayInstanceHandler, cpp) +# Qv2rayAddSource(core, _, CoreUtils, cpp, hpp) Qv2rayAddSource(core, _, CoreSafeTypes, hpp) Qv2rayAddSource(ui, editors, w_InboundEditor, cpp, hpp, ui) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 1b89d3ac..1547a983 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3891 +3894 diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index c6c39a97..c5688591 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -32,6 +32,8 @@ namespace Qv2ray::core::handlers } kernelInstance = new V2rayKernelInstance(); + connect(kernelInstance, &V2rayKernelInstance::OnNewStatsDataArrived, this, &QvConnectionHandler::OnStatsDataArrived); + connect(kernelInstance, &V2rayKernelInstance::OnProcessOutputReadyRead, this, &QvConnectionHandler::OnVCoreLogAvailable); saveTimerId = startTimer(60000); } const QList QvConnectionHandler::Connections() const @@ -88,8 +90,7 @@ namespace Qv2ray::core::handlers return CHTryStartConnection_p(identifier, root); } - - const QString QvConnectionHandler::GetConnectionBasicInfo(const ConnectionId &id) const + const QString QvConnectionHandler::GetConnectionProtocolString(const ConnectionId &id) const { QString result; diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index cdf84bfc..db596b4d 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -24,11 +24,13 @@ namespace Qv2ray::core::handlers // const optional StopConnection(const ConnectionId &id); const optional StartConnection(const ConnectionId &identifier); + + private slots: + void OnStatsDataArrived(const ConnectionId &id, const QString tag, const quint64 uploadSpeed, const quint64 downloadSpeed); // public: // // Connection Operations. - const QString GetConnectionBasicInfo(const ConnectionId &id) const; const ConnectionMetaObject GetConnection(const ConnectionId &id) const; const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); const optional DeleteConnection(const ConnectionId &id); @@ -38,18 +40,19 @@ namespace Qv2ray::core::handlers const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); // // Get Conncetion Property + const QString GetConnectionProtocolString(const ConnectionId &id) const; const tuple GetConnectionInfo(const ConnectionId &connectionId); // // Misc Connection Operations - const optional TestLatency(const ConnectionId &id); - const optional TestLatency(const GroupId &id); const optional TestLatency(); + const optional TestLatency(const GroupId &id); + const optional TestLatency(const ConnectionId &id); // // Group Operations const GroupMetaObject GetGroup(const GroupId &id) const; - const GroupId &CreateGroup(const QString displayName, bool isSubscription); const optional DeleteGroup(const GroupId &id); const optional DuplicateGroup(const GroupId &id); + const GroupId &CreateGroup(const QString displayName, bool isSubscription); const optional RenameGroup(const GroupId &id, const QString &newName); // // Subscriptions @@ -63,7 +66,8 @@ namespace Qv2ray::core::handlers // void OnConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id); - void OnNewConnectionStatsAvaliable(const ConnectionId &id, uint64_t totalUpload, uint64_t totalDownload); + void OnVCoreLogAvailable(const ConnectionId &id, const QString &log); + void OnStatsAvailable(const ConnectionId &id, uint64_t totalUpload, uint64_t totalDownload); // void OnConnectionCreated(const ConnectionId &id, const QString &displayName); void OnConnectionRenamed(const ConnectionId &id, const QString &originalName, const QString &newName); @@ -82,16 +86,22 @@ namespace Qv2ray::core::handlers void OnSubscriptionUpdateFinished(const GroupId &id); private: + // bool CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port); optional CHTryStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); const CONFIGROOT CHGetConnectionRoot_p(const ConnectionId &id) const; const CONFIGROOT CHGetConnectionRoot_p(const GroupId &group, const ConnectionId &id) const; bool CHSaveConnectionConfig(CONFIGROOT obj, const ConnectionId &id, bool override); // + // // We only support one cuncurrent connection currently. - //QHash kernelInstances; +#ifdef QV2RAY_MULTIPlE_ONNECTION + QHash kernelInstances; +#else V2rayKernelInstance *kernelInstance = nullptr; +#endif int saveTimerId; + int apiTimerId; QHash groups; QHash connections; // diff --git a/src/core/handler/SubscriptionHandler.cpp b/src/core/handler/SubscriptionHandler.cpp deleted file mode 100644 index 8337712e..00000000 --- a/src/core/handler/SubscriptionHandler.cpp +++ /dev/null @@ -1 +0,0 @@ -// diff --git a/src/core/handler/V2rayInstanceHandler.cpp b/src/core/handler/V2rayInstanceHandler.cpp index e1786d86..2e808731 100644 --- a/src/core/handler/V2rayInstanceHandler.cpp +++ b/src/core/handler/V2rayInstanceHandler.cpp @@ -6,7 +6,7 @@ optional QvConnectionHandler::CHTryStartConnection_p(const ConnectionId auto &connectionMeta = connections[id]; auto fullConfig = GenerateRuntimeConfig(root); // - auto result = kernelInstance->StartConnection(fullConfig); + auto result = kernelInstance->StartConnection(id, fullConfig); if (!result.has_value()) { emit OnConnected(id); @@ -62,3 +62,11 @@ optional QvConnectionHandler::CHTryStartConnection_p(const ConnectionId //} //return "startFlag"; } + +void QvConnectionHandler::OnStatsDataArrived(const ConnectionId &id, const QString tag, const quint64 uploadSpeed, const quint64 downloadSpeed) +{ + Q_UNUSED(tag) + emit OnStatsAvailable(id, uploadSpeed, downloadSpeed); + connections[id].upLinkData += uploadSpeed; + connections[id].downLinkData += downloadSpeed; +} diff --git a/src/core/handler/V2rayInstanceHandler.hpp b/src/core/handler/V2rayInstanceHandler.hpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/core/kernel/APIBackend.cpp b/src/core/kernel/APIBackend.cpp index 1fe8990f..d1a067fc 100644 --- a/src/core/kernel/APIBackend.cpp +++ b/src/core/kernel/APIBackend.cpp @@ -9,13 +9,13 @@ using grpc::Status; #include "libs/libqvb/build/libqvb.h" #endif -namespace Qv2ray::core::kernel::api +namespace Qv2ray::core::kernel { // To all contributors: // // --- CONSTRUCTOR --- - APIWorkder::APIWorkder() + APIWorker::APIWorker() { thread = new QThread(); this->moveToThread(thread); @@ -30,7 +30,7 @@ namespace Qv2ray::core::kernel::api DEBUG(MODULE_VCORE, "API Worker started.") } - void APIWorkder::StartAPI(QStringList tags) + void APIWorker::StartAPI(const QStringList &tags) { // Config API apiFailedCounter = 0; @@ -38,13 +38,13 @@ namespace Qv2ray::core::kernel::api running = true; } - void APIWorkder::StopAPI() + void APIWorker::StopAPI() { running = false; } // --- DECONSTRUCTOR --- - APIWorkder::~APIWorkder() + APIWorker::~APIWorker() { StopAPI(); // Set started signal to false and wait for API thread to stop. @@ -59,7 +59,7 @@ namespace Qv2ray::core::kernel::api // API Core Operations // Start processing data. - void APIWorkder::process() + void APIWorker::process() { while (started) { QThread::msleep(1000); @@ -75,16 +75,38 @@ namespace Qv2ray::core::kernel::api #else auto str = Dial(const_cast(channelAddress.toStdString().c_str()), 10000); LOG(MODULE_VCORE, QString(str)) + LOG(MODULE_VCORE, "Currently, libqvb does not support speed reporting, your stats might go wrong.") free(str); #endif dialed = true; } +#ifndef QV2RAY_STATS_PER_TAG + qint64 value_up = 0; + qint64 value_down = 0; + + for (auto tag : inboundTags) { + value_up += CallStatsAPIByName("inbound>>>" + tag + ">>>traffic>>>uplink"); + value_down += CallStatsAPIByName("inbound>>>" + tag + ">>>traffic>>>downlink"); + } + + if (value_up < 0 || value_down < 0) { + dialed = false; + break; + } + + if (running) { + apiFailedCounter = 0; + emit OnDataReady("", value_up, value_down); + } + +#else + for (auto tag : inboundTags) { auto valup = CallStatsAPIByName("inbound>>>" + tag + ">>>traffic>>>uplink"); auto valdown = CallStatsAPIByName("inbound>>>" + tag + ">>>traffic>>>downlink"); - if (valup < 0 && valdown < 0) { + if (valup < 0 || valdown < 0) { dialed = false; break; } @@ -98,6 +120,7 @@ namespace Qv2ray::core::kernel::api } } +#endif QThread::msleep(1000); } // end while running } // end while started @@ -105,7 +128,7 @@ namespace Qv2ray::core::kernel::api thread->exit(); } - qint64 APIWorkder::CallStatsAPIByName(QString name) + qint64 APIWorker::CallStatsAPIByName(const QString &name) { if (apiFailedCounter == QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD) { LOG(MODULE_VCORE, "API call failure threshold reached, cancelling further API aclls.") @@ -119,7 +142,7 @@ namespace Qv2ray::core::kernel::api #ifdef WITH_LIB_GRPCPP GetStatsRequest request; request.set_name(name.toStdString()); - request.set_reset(false); + request.set_reset(true); GetStatsResponse response; ClientContext context; Status status = Stub->GetStats(&context, request, &response); diff --git a/src/core/kernel/APIBackend.hpp b/src/core/kernel/APIBackend.hpp index d576540b..d314ae7e 100644 --- a/src/core/kernel/APIBackend.hpp +++ b/src/core/kernel/APIBackend.hpp @@ -1,6 +1,5 @@ #pragma once #include "base/Qv2rayBase.hpp" - #ifdef WITH_LIB_GRPCPP #include #include "libs/gen/v2ray_api.pb.h" @@ -8,35 +7,35 @@ #endif // Check 10 times before telling user that API has failed. -#define QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD 10 +constexpr auto QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD = 10; -namespace Qv2ray::core::kernel::api +namespace Qv2ray::core::kernel { - class APIWorkder : public QObject + class APIWorker : public QObject { Q_OBJECT public: - APIWorkder(); - ~APIWorkder(); - void StartAPI(QStringList tags); + APIWorker(); + ~APIWorker(); + void StartAPI(const QStringList &tags); void StopAPI(); public slots: void process(); signals: - void OnDataReady(QString tag, qint64 dataUp, qint64 dataDown); - void error(QString err); + void OnDataReady(const QString &tag, const quint64 _totalUp, const quint64 _totalDown); + void error(const QString &err); private: - qint64 CallStatsAPIByName(QString name); + qint64 CallStatsAPIByName(const QString &name); QStringList inboundTags; QThread *thread; // bool started = false; bool running = false; - int apiFailedCounter; + uint apiFailedCounter = 0; #ifdef WITH_LIB_GRPCPP std::shared_ptr<::grpc::Channel> Channel; std::unique_ptr<::v2ray::core::app::stats::command::StatsService::Stub> Stub; @@ -44,4 +43,4 @@ namespace Qv2ray::core::kernel::api }; } -using namespace Qv2ray::core::kernel::api; +using namespace Qv2ray::core::kernel; diff --git a/src/core/kernel/KernelInteractions.cpp b/src/core/kernel/KernelInteractions.cpp index f0691b17..e68d7284 100644 --- a/src/core/kernel/KernelInteractions.cpp +++ b/src/core/kernel/KernelInteractions.cpp @@ -4,6 +4,7 @@ #include "common/QvHelpers.hpp" #include "KernelInteractions.hpp" #include "core/connection/ConnectionIO.hpp" +#include "APIBackend.hpp" namespace Qv2ray::core::kernel { @@ -116,11 +117,11 @@ namespace Qv2ray::core::kernel } } - V2rayKernelInstance::V2rayKernelInstance() + V2rayKernelInstance::V2rayKernelInstance() : id("null") { vProcess = new QProcess(); - connect(vProcess, &QProcess::readyReadStandardOutput, this, [this]() { - emit onProcessOutputReadyRead(vProcess->readAllStandardOutput().trimmed()); + connect(vProcess, &QProcess::readyReadStandardOutput, this, [&]() { + emit OnProcessOutputReadyRead(id, vProcess->readAllStandardOutput().trimmed()); }); connect(vProcess, &QProcess::stateChanged, [this](QProcess::ProcessState state) { DEBUG(MODULE_VCORE, "V2ray kernel process status changed: " + QVariant::fromValue(state).toString()) @@ -129,15 +130,15 @@ namespace Qv2ray::core::kernel if (KernelStarted && state == QProcess::NotRunning) { LOG(MODULE_VCORE, "V2ray kernel crashed.") StopConnection(); - emit onProcessErrored(); + emit OnProcessErrored(); } }); - apiWorker = new APIWorkder(); - connect(apiWorker, &APIWorkder::OnDataReady, this, &V2rayKernelInstance::onAPIDataReady); + apiWorker = new APIWorker(); + connect(apiWorker, &APIWorker::OnDataReady, this, &V2rayKernelInstance::onAPIDataReady); KernelStarted = false; } - optional V2rayKernelInstance::StartConnection(CONFIGROOT root) + optional V2rayKernelInstance::StartConnection(const ConnectionId &id, const CONFIGROOT &root) { if (KernelStarted) { LOG(MODULE_VCORE, "Status is invalid, expect STOPPED when calling StartConnection") @@ -159,6 +160,8 @@ namespace Qv2ray::core::kernel vProcess->waitForStarted(); DEBUG(MODULE_VCORE, "V2ray core started.") KernelStarted = true; + // Set Connection ID + this->id = id; QStringList inboundTags; for (auto item : root["inbounds"].toArray()) { @@ -188,7 +191,7 @@ namespace Qv2ray::core::kernel DEBUG(MODULE_VCORE, "Qv2ray API started") } - return {}; + return { }; } else { KernelStarted = false; return tr("V2ray kernel failed to start."); @@ -208,11 +211,6 @@ namespace Qv2ray::core::kernel // Block until V2ray core exits // Should we use -1 instead of waiting for 30secs? vProcess->waitForFinished(); - // - transferDataUp.clear(); - transferDataDown.clear(); - transferSpeedUp.clear(); - transferSpeedDown.clear(); } V2rayKernelInstance::~V2rayKernelInstance() @@ -225,72 +223,8 @@ namespace Qv2ray::core::kernel delete vProcess; } - void V2rayKernelInstance::onAPIDataReady(QString tag, qulonglong totalUp, qulonglong totalDown) + void V2rayKernelInstance::onAPIDataReady(const QString &tag, const quint64 _totalUp, const quint64 _totalDown) { - auto dataup = totalUp - transferDataUp[tag]; - transferDataUp[tag] = totalUp; - transferSpeedUp[tag] = dataup; - // Download - auto datadown = totalDown - transferDataDown[tag]; - transferDataDown[tag] = totalDown; - transferSpeedDown[tag] = datadown; - } - - // ------------------------------------------------------------- API FUNCTIONS -------------------------- - qulonglong V2rayKernelInstance::getTagSpeedUp(const QString &tag) - { - return transferSpeedUp[tag]; - } - qulonglong V2rayKernelInstance::getTagSpeedDown(const QString &tag) - { - return transferSpeedDown[tag]; - } - qulonglong V2rayKernelInstance::getTagDataUp(const QString &tag) - { - return transferDataUp[tag]; - } - qulonglong V2rayKernelInstance::getTagDataDown(const QString &tag) - { - return transferDataDown[tag]; - } - qulonglong V2rayKernelInstance::getAllDataUp() - { - long val = 0; - - for (auto _val : transferDataUp.values()) { - val += _val; - } - - return val; - } - qulonglong V2rayKernelInstance::getAllDataDown() - { - long val = 0; - - for (auto _val : transferDataDown.values()) { - val += _val; - } - - return val; - } - qulonglong V2rayKernelInstance::getAllSpeedUp() - { - qulonglong val = 0; - - for (auto _val : transferSpeedUp.values()) { - val += _val; - } - - return val; - } - qulonglong V2rayKernelInstance::getAllSpeedDown() - { - qulonglong val = 0; - - for (auto _val : transferSpeedDown.values()) { - val += _val; - } - - return val; + emit OnNewStatsDataArrived(id, tag, _totalUp, _totalDown); } } diff --git a/src/core/kernel/KernelInteractions.hpp b/src/core/kernel/KernelInteractions.hpp index eb91b1f3..819e2896 100644 --- a/src/core/kernel/KernelInteractions.hpp +++ b/src/core/kernel/KernelInteractions.hpp @@ -1,10 +1,11 @@ #pragma once #include #include "base/Qv2rayBase.hpp" -#include "APIBackend.hpp" +#include "core/CoreSafeTypes.hpp" namespace Qv2ray::core::kernel { + class APIWorker; class V2rayKernelInstance : public QObject { Q_OBJECT @@ -15,14 +16,10 @@ namespace Qv2ray::core::kernel // Speed qulonglong getTagSpeedUp(const QString &tag); qulonglong getTagSpeedDown(const QString &tag); - qulonglong getTagDataUp(const QString &tag); - qulonglong getTagDataDown(const QString &tag); - qulonglong getAllDataUp(); - qulonglong getAllDataDown(); qulonglong getAllSpeedUp(); qulonglong getAllSpeedDown(); // - optional StartConnection(CONFIGROOT root); + optional StartConnection(const ConnectionId &id, const CONFIGROOT &root); void StopConnection(); bool KernelStarted = false; // @@ -30,20 +27,19 @@ namespace Qv2ray::core::kernel static bool ValidateKernel(const QString &vCorePath, const QString &vAssetsPath, QString *message); signals: - void onProcessErrored(); - void onProcessOutputReadyRead(QString); + void OnProcessErrored(); + void OnProcessOutputReadyRead(const ConnectionId &id, const QString &output); + void OnNewStatsDataArrived(const ConnectionId &id, const QString &tag, const quint64 _totalUp, const quint64 _totalDown); public slots: - void onAPIDataReady(QString tag, qulonglong totalUp, qulonglong totalDown); + void onAPIDataReady(const QString &tag, const quint64 _totalUp, const quint64 _totalDown); private: - APIWorkder *apiWorker; + APIWorker *apiWorker; QProcess *vProcess; bool apiEnabled; - QMap transferDataUp; - QMap transferDataDown; - QMap transferSpeedUp; - QMap transferSpeedDown; + // + ConnectionId id; }; } diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 60287bfe..3ed5ce70 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -90,7 +90,6 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr { setupUi(this); MainWindow::mwInstance = this; - //vinstance = new V2rayKernelInstance(); //connect(vinstance, &V2rayKernelInstance::onProcessOutputReadyRead, this, &MainWindow::UpdateVCoreLog); //connect(vinstance, &V2rayKernelInstance::onProcessErrored, [this] { // on_stopButton_clicked(); @@ -109,25 +108,23 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr masterLogBrowser->document()->setDocumentMargin(8); masterLogBrowser->document()->adjustSize(); masterLogBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap); - // - requestHelper = new QvHttpRequestHelper(); - //connect(&tcpingHelper, &QvTCPingModel::PingFinished, this, &MainWindow::onPingFinished); - // + // For charts + speedChartWidget = new SpeedWidget(this); + speedChart->addWidget(speedChartWidget); this->setWindowIcon(QIcon(":/assets/icons/qv2ray.png")); hTray.setIcon(QIcon(GlobalConfig.uiConfig.useDarkTrayIcon ? ":/assets/icons/ui_dark/tray.png" : ":/assets/icons/ui_light/tray.png")); importConfigButton->setIcon(QICON_R("import.png")); - //duplicateBtn->setIcon(QICON_R("duplicate.png")); - //removeConfigButton->setIcon(QICON_R("delete.png")); - //editConfigButton->setIcon(QICON_R("edit.png")); - //editJsonBtn->setIcon(QICON_R("json.png")); - //// //pingTestBtn->setIcon(QICON_R("ping_gauge.png")); //shareBtn->setIcon(QICON_R("share.png")); updownImageBox->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); updownImageBox_2->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); // - // Setup System tray icons and menus // + connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &MainWindow::OnConnected); + connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &MainWindow::onConnectionStatsArrived); + connect(ConnectionManager, &QvConnectionHandler::OnVCoreLogAvailable, this, &MainWindow::onVCoreLogArrived); + // + // Setup System tray icons and menus hTray.setToolTip(TRAY_TOOLTIP_PREFIX); // Basic actions action_Tray_ShowHide = new QAction(this->windowIcon(), tr("Hide"), this); @@ -162,9 +159,9 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr // connect(action_Tray_ShowHide, &QAction::triggered, this, &MainWindow::ToggleVisibility); connect(action_Tray_ShowPreferencesWindow, &QAction::triggered, this, &MainWindow::on_preferencesBtn_clicked); - connect(action_Tray_Start, &QAction::triggered, this, &MainWindow::on_startButton_clicked); - connect(action_Tray_Stop, &QAction::triggered, this, &MainWindow::on_stopButton_clicked); - connect(action_Tray_Reconnect, &QAction::triggered, this, &MainWindow::on_reconnectButton_clicked); + //connect(action_Tray_Start, &QAction::triggered, this, &MainWindow::on_startButton_clicked); + //connect(action_Tray_Stop, &QAction::triggered, this, &MainWindow::on_stopButton_clicked); + //connect(action_Tray_Reconnect, &QAction::triggered, this, &MainWindow::on_reconnectButton_clicked); connect(action_Tray_Quit, &QAction::triggered, this, &MainWindow::on_actionExit_triggered); connect(action_Tray_SetSystemProxy, &QAction::triggered, this, &MainWindow::MWSetSystemProxy); connect(action_Tray_ClearSystemProxy, &QAction::triggered, this, &MainWindow::MWClearSystemProxy); @@ -187,9 +184,9 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr connect(action_RCM_ShareQR, &QAction::triggered, this, &MainWindow::on_action_RCM_ShareQR_triggered); // // Globally invokable signals. - connect(this, &MainWindow::Connect, this, &MainWindow::on_startButton_clicked); - connect(this, &MainWindow::DisConnect, this, &MainWindow::on_stopButton_clicked); - connect(this, &MainWindow::ReConnect, this, &MainWindow::on_reconnectButton_clicked); + //connect(this, &MainWindow::Connect, this, &MainWindow::on_startButton_clicked); + //connect(this, &MainWindow::DisConnect, this, &MainWindow::on_stopButton_clicked); + //connect(this, &MainWindow::ReConnect, this, &MainWindow::on_reconnectButton_clicked); // hTray.setContextMenu(tray_RootMenu); hTray.show(); @@ -201,20 +198,33 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr connectionListMenu->addAction(action_RCM_EditJson); connectionListMenu->addAction(action_RCM_ConvToComplex); // - OnConfigListChanged(false); - // - // For charts - speedChartView = new SpeedWidget(this); - //speedChartView->setContentsMargins(1, 1, 1, 1); - speedChart->addWidget(speedChartView); + LOG(MODULE_UI, "Loading data...") + auto groups = ConnectionManager->AllGroups(); + + for (auto group : groups) { + auto groupItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetGroup(group).displayName); + connectionListWidget->addTopLevelItem(groupItem); + connectionListWidget->setItemWidget(groupItem, 0, new ConnectionItemWidget(group, connectionListWidget)); + auto connections = ConnectionManager->Connections(group); + + for (auto connection : connections) { + auto connectionItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetConnection(connection).displayName); + groupItem->addChild(connectionItem); + auto widget = new ConnectionItemWidget(connection, connectionListWidget); + connect(widget, &ConnectionItemWidget::RequestWidgetFocus, this, &MainWindow::onConnectionWidgetFocusRequested); + connectionListWidget->setItemWidget(connectionItem, 0, widget); + } + } + // // Find and start if there is an auto-connection - MWFindAndStartAutoConfig(); + if (!MWFindAndStartAutoConfig()) { + this->show(); + } + //// If we are not connected to anything, show the MainWindow. - //if (!vinstance->KernelStarted) { - // this->show(); - //} #ifndef DISABLE_AUTO_UPDATE + requestHelper = new QvHttpRequestHelper(); connect(requestHelper, &QvHttpRequestHelper::httpRequestFinished, this, &MainWindow::VersionUpdate); requestHelper->get("https://api.github.com/repos/Qv2ray/Qv2ray/releases/latest"); #endif @@ -225,18 +235,9 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr } CheckSubscriptionsUpdate(); + // } -void MainWindow::SetEditWidgetEnable(bool enabled) -{ - //removeConfigButton->setEnabled(enabled); - //editConfigButton->setEnabled(enabled); - //duplicateBtn->setEnabled(enabled); - //editJsonBtn->setEnabled(enabled); - //shareBtn->setEnabled(enabled); - // Allow ping all. - //pingTestBtn->setText(enabled ? tr("Ping") : tr("Ping All")); -} void MainWindow::keyPressEvent(QKeyEvent *e) { @@ -302,149 +303,33 @@ void MainWindow::VersionUpdate(QByteArray &data) } #endif -void MainWindow::OnConfigListChanged(bool need_restart) -{ - LOG(MODULE_UI, "Loading data...") - auto groups = ConnectionManager->AllGroups(); - - for (auto group : groups) { - auto groupItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetGroup(group).displayName); - connectionListWidget->addTopLevelItem(groupItem); - connectionListWidget->setItemWidget(groupItem, 0, new ConnectionItemWidget(group, connectionListWidget)); - auto connections = ConnectionManager->Connections(group); - - for (auto connection : connections) { - auto connectionItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetConnection(connection).displayName); - groupItem->addChild(connectionItem); - auto widget = new ConnectionItemWidget(connection, connectionListWidget); - connect(widget, &ConnectionItemWidget::RequestWidgetFocus, this, &MainWindow::onConnectionWidgetFocusRequested); - connectionListWidget->setItemWidget(connectionItem, 0, widget); - } - } - - // Do not sort - //connectionListWidget->sortItems(1, Qt::SortOrder::AscendingOrder); - // - // ================================================================ - // - //auto wasRunning = vinstance->KernelStarted && need_restart; - // - //if (wasRunning) on_stopButton_clicked(); - // - //LOG(UI, "Loading new GlobalConfig") - //SetEditWidgetEnable(false); - // - // Store the latency test value. - //QMap latencyValueCache; - //for (auto i = 0; i < connections.count(); i++) { - // latencyValueCache[connections.keys()[i]] = connections.values()[i].latency; - //} - //connections.clear(); - //connectionListWidget->clear(); - //QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP, only subscriptions are supported"); - ////auto _regularConnections = GetRegularConnections(GlobalConfig.configs); - //auto _subsConnections = GetSubscriptionConnections(GlobalConfig.subscriptions.keys()); - //for (auto i = 0; i < _regularConnections.count(); i++) { - // ConnectionObject _o; - // _o.configType = CONNECTION_REGULAR; - // _o.connectionName = _regularConnections.keys()[i]; - // _o.config = _regularConnections.values()[i]; - // auto name = _o.IdentifierString(); - // _o.latency = latencyValueCache[name]; // restore latency values - // connections[name] = _o; - // auto item = new QTreeWidgetItem(QStringList() << _o.connectionName); - // item->setData(0, Qt::UserRole, QVariant::fromValue(_o)); - // connectionListWidget->addTopLevelItem(item); - //} - //for (auto i = 0; i < _subsConnections.count(); i++) { - // auto subName = _subsConnections.keys()[i]; - // auto subTopLevelItem = new QTreeWidgetItem(QStringList() << tr("Subscription") + ": " + subName); - // connectionListWidget->addTopLevelItem(subTopLevelItem); - // - // for (auto j = 0; j < _subsConnections.values()[i].count(); j++) { - // ConnectionObject _o; - // _o.configType = CONNECTION_SUBSCRIPTION; - // _o.connectionName = _subsConnections.values()[i].keys()[j]; - // _o.subscriptionName = subName; - // _o.config = _subsConnections.values()[i].values()[j]; - // // connection name generated from subscription name and connection name. - // auto connName = _o.IdentifierString(); - // _o.latency = latencyValueCache[connName]; - // connections[connName] = _o; - // auto item = new QTreeWidgetItem(QStringList() << _o.connectionName); - // item->setData(0, Qt::UserRole, QVariant::fromValue(_o)); - // subTopLevelItem->addChild(item); - // } - //} - // - //// We set the current selected item back... - //if (connections.contains(CurrentConnectionIdentifier)) { - // auto item = FindItemByIdentifier(CurrentConnectionIdentifier); - // - // if (item != nullptr) { - // connectionListWidget->setCurrentItem(item); - // connectionListWidget->scrollToItem(item); - // } else if (connectionListWidget->topLevelItemCount() > 0) { - // item = connectionListWidget->topLevelItem(0); - // CurrentConnectionIdentifier = ItemConnectionIdentifier(item); - // } else { - // return; - // } - // - // ShowAndSetConnection(CurrentConnectionIdentifier, false, false); - //} - // - //connectionListWidget->sortItems(0, Qt::AscendingOrder); - // - //if (wasRunning) on_startButton_clicked(); -} MainWindow::~MainWindow() { hTray.hide(); } -void MainWindow::UpdateVCoreLog(const QString &log) -{ - masterLogBrowser->append(log); - CleanUpLogs(masterLogBrowser) - auto bar = masterLogBrowser->verticalScrollBar(); - auto max = bar->maximum(); - auto val = bar->value(); - if (val >= max * 0.8 || val >= max - 20) - bar->setValue(max); -} -void MainWindow::on_startButton_clicked() -{ -} - -void MainWindow::on_stopButton_clicked() -{ - //// Is running or starting - //killTimer(speedTimerId); - //killTimer(pingTimerId); - //// - //MWStopConnection(); - //// - //hTray.setToolTip(TRAY_TOOLTIP_PREFIX); - //statusLabel->setText(tr("Disconnected")); - action_Tray_Start->setEnabled(true); - action_Tray_Stop->setEnabled(false); - action_Tray_Reconnect->setEnabled(false); - // Set to false as the system proxy has been cleared in the StopConnection function. - tray_SystemProxyMenu->setEnabled(false); - //startButton->setEnabled(true); - //stopButton->setEnabled(false); - //// - //netspeedLabel->setText("0.00 B/s\r\n0.00 B/s"); - //dataamountLabel->setText("0.00 B\r\n0.00 B"); - //LOG(UI, "Stopped successfully.") - //this->hTray.showMessage("Qv2ray", tr("Disconnected from: ") + CurrentConnectionIdentifier.IdentifierString()); -} +//void MainWindow::on_stopButton_clicked() +//{ +// //hTray.setToolTip(TRAY_TOOLTIP_PREFIX); +// //statusLabel->setText(tr("Disconnected")); +// action_Tray_Start->setEnabled(true); +// action_Tray_Stop->setEnabled(false); +// action_Tray_Reconnect->setEnabled(false); +// // Set to false as the system proxy has been cleared in the StopConnection function. +// tray_SystemProxyMenu->setEnabled(false); +// //startButton->setEnabled(true); +// //stopButton->setEnabled(false); +// //// +// //netspeedLabel->setText("0.00 B/s\r\n0.00 B/s"); +// //dataamountLabel->setText("0.00 B\r\n0.00 B"); +// //LOG(UI, "Stopped successfully.") +// //this->hTray.showMessage("Qv2ray", tr("Disconnected from: ") + CurrentConnectionIdentifier.IdentifierString()); +//} void MainWindow::closeEvent(QCloseEvent *event) { this->hide(); - tray_RootMenu->actions().first()->setText(tr("Show")); + action_Tray_ShowHide->setText(tr("Show")); event->ignore(); } void MainWindow::on_activatedTray(QSystemTrayIcon::ActivationReason reason) @@ -492,25 +377,12 @@ void MainWindow::on_actionExit_triggered() StopProcessingPlugins(); } - //tcpingHelper.StopAllPing(); - on_stopButton_clicked(); ExitQv2ray(); } void MainWindow::on_preferencesBtn_clicked() { - PreferencesWindow w(this); - connect(&w, &PreferencesWindow::s_reload_config, this, &MainWindow::OnConfigListChanged); - w.exec(); -} -void MainWindow::on_connectionListWidget_doubleClicked(const QModelIndex &index) -{ - //Q_UNUSED(index) - // - //if (!IsSelectionConnectable) return; - // - //ShowAndSetConnection(ItemConnectionIdentifier(connectionListWidget->currentItem()), true, false); - //on_reconnectButton_clicked(); + PreferencesWindow(this).exec(); } void MainWindow::on_clearlogButton_clicked() { @@ -519,7 +391,7 @@ void MainWindow::on_clearlogButton_clicked() void MainWindow::on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { Q_UNUSED(previous) - CurrentItem = current; + //CurrentItem = current; //isRenamingInProgress = false; // //if (!IsConnectableItem(current)) return; @@ -530,13 +402,13 @@ void MainWindow::on_connectionListWidget_currentItemChanged(QTreeWidgetItem *cur } void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint &pos) { - //Q_UNUSED(pos) - //auto _pos = QCursor::pos(); - //auto item = connectionListWidget->itemAt(connectionListWidget->mapFromGlobal(_pos)); - // - //if (IsConnectableItem(item)) { - // connectionListMenu->popup(_pos); - //} + Q_UNUSED(pos) + auto _pos = QCursor::pos(); + auto item = connectionListWidget->itemAt(connectionListWidget->mapFromGlobal(_pos)); + + if (GetItemWidget(item)->IsConnection()) { + connectionListMenu->popup(_pos); + } } void MainWindow::on_action_RCM_RenameConnection_triggered() { @@ -762,11 +634,6 @@ void MainWindow::on_editConfigButton_clicked() // OnConfigListChanged(alias == CurrentConnectionIdentifier.connectionName); //} } -void MainWindow::on_reconnectButton_clicked() -{ - on_stopButton_clicked(); - on_startButton_clicked(); -} void MainWindow::on_action_RCM_ConvToComplex_triggered() { @@ -947,9 +814,7 @@ void MainWindow::on_duplicateBtn_clicked() void MainWindow::on_subsButton_clicked() { - SubscribeEditor w; - w.exec(); - OnConfigListChanged(false); + SubscribeEditor().exec(); } void MainWindow::on_connectionListWidget_itemSelectionChanged() @@ -1050,3 +915,31 @@ void MainWindow::on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int Q_UNUSED(column) infoWidget->ShowDetails(GetItemWidget(item)->Identifier()); } + +void MainWindow::onConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed) +{ + Q_UNUSED(id); + // This may not be, or may not precisely be, speed per second if low-level has "any" latency. + // (Hope not...) + speedChartWidget->AddPointData(upSpeed, downSpeed); +} + +void MainWindow::onVCoreLogArrived(const ConnectionId &id, const QString &log) +{ + Q_UNUSED(id); + // This may not be, or may not precisely be, speed per second if low-level has "any" latency. + // (Hope not...) + UpdateVCoreLog(log); +} + +void MainWindow::UpdateVCoreLog(const QString &log) +{ + masterLogBrowser->append(log); + CleanUpLogs(masterLogBrowser) + auto bar = masterLogBrowser->verticalScrollBar(); + auto max = bar->maximum(); + auto val = bar->value(); + + if (val >= max * 0.8 || val >= max - 20) + bar->setValue(max); +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 2b7ae7d8..f568dae3 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -31,16 +31,11 @@ class MainWindow : public QMainWindow, Ui::MainWindow QvMessageBusSlotHeader //void onPingFinished(QvTCPingData data); void UpdateVCoreLog(const QString &log); - void OnConfigListChanged(bool need_restart); private slots: void on_action_RCM_ShareQR_triggered(); - void on_startButton_clicked(); - void on_stopButton_clicked(); - void on_reconnectButton_clicked(); void on_activatedTray(QSystemTrayIcon::ActivationReason reason); void on_actionExit_triggered(); void on_preferencesBtn_clicked(); - void on_connectionListWidget_doubleClicked(const QModelIndex &index); void on_clearlogButton_clicked(); void on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); void on_connectionListWidget_customContextMenuRequested(const QPoint &pos); @@ -72,6 +67,10 @@ class MainWindow : public QMainWindow, Ui::MainWindow private slots: // void onConnectionWidgetFocusRequested(const ConnectionItemWidget *widget); + //void onConnectionConnected(const ConnectionId &id); + //void onConnectionDisConnected(const ConnectionId &id); + void onConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed); + void onVCoreLogArrived(const ConnectionId &id, const QString &log); // void on_action_StartThis_triggered(); void on_action_RCM_EditJson_triggered(); @@ -79,26 +78,24 @@ class MainWindow : public QMainWindow, Ui::MainWindow void on_action_RCM_RenameConnection_triggered(); void on_connectionListWidget_itemSelectionChanged(); void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); - void on_connectionFilterTxt_textEdited(const QString &arg1); - void on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column); private: QTreeWidgetItem *CurrentItem; - // - void SetEditWidgetEnable(bool enabled); //CONFIGROOT currentFullConfig; // // Charts - SpeedWidget *speedChartView; + SpeedWidget *speedChartWidget; // QMenu *connectionListMenu; // //QvConnectionObject renameOriginalIdentifier; bool isRenamingInProgress; // +#ifndef DISABLE_AUTO_UPDATE QvHttpRequestHelper *requestHelper; +#endif QSystemTrayIcon hTray; //PACServer pacServer; //QvTCPingModel tcpingHelper; @@ -122,7 +119,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow // // ----------------------------------- Extra Headers For w_MainWindow_extra.cpp Handling V2ray Connectivities. bool systemProxyEnabled; - void MWFindAndStartAutoConfig(); + bool MWFindAndStartAutoConfig(); void MWStopConnection(); void MWSetSystemProxy(); void MWClearSystemProxy(bool); diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 33c2d8b1..ea7b910f 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -6,8 +6,8 @@ 0 0 - 800 - 590 + 955 + 695 @@ -73,111 +73,6 @@ - - - - - - Search - - - true - - - - - - - Qt::CustomContextMenu - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::ExtendedSelection - - - QAbstractItemView::ScrollPerPixel - - - 0 - - - true - - - true - - - true - - - true - - - true - - - - 1 - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - Import connection - - - Add - - - - 22 - 22 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - @@ -329,8 +224,8 @@ 0 0 - 480 - 716 + 581 + 706 @@ -345,13 +240,13 @@ 0 - 215 + 205 16777215 - 215 + 205 @@ -456,6 +351,119 @@ + + + + + 350 + 16777215 + + + + + + + Search + + + true + + + + + + + Qt::CustomContextMenu + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::ScrollPerPixel + + + 0 + + + true + + + true + + + true + + + true + + + true + + + + 1 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Import connection + + + Add + + + + 22 + 22 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + @@ -463,7 +471,7 @@ 0 0 - 800 + 955 26 diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index 8e5c70fa..268ed0a7 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -30,7 +30,7 @@ // return nullptr; //} -void MainWindow::MWFindAndStartAutoConfig() +bool MainWindow::MWFindAndStartAutoConfig() { //if (!GlobalConfig.autoStartConfig.connectionName.isEmpty()) { // // User has auto start configured, we try to find that connection item. @@ -58,6 +58,7 @@ void MainWindow::MWFindAndStartAutoConfig() // connectionListWidget->setCurrentItem(connectionListWidget->topLevelItem(0)); // ShowAndSetConnection(ItemConnectionIdentifier(connectionListWidget->topLevelItem(0)), true, false); //} + return true; } void MainWindow::MWClearSystemProxy(bool showMessage) diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index d08034af..48d7ea5e 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -5,6 +5,10 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent), connectionId("null"), groupId("null") { setupUi(this); + duplicateBtn->setIcon(QICON_R("duplicate.png")); + deleteBtn->setIcon(QICON_R("delete.png")); + editBtn->setIcon(QICON_R("edit.png")); + editJsonBtn->setIcon(QICON_R("json.png")); } void ConnectionInfoWidget::ShowDetails(const tuple &_identifier) @@ -15,7 +19,7 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden if (connectionId.toString() != "null") { connNameLabel->setText(ConnectionManager->GetConnection(connectionId).displayName); groupLabel->setText(ConnectionManager->GetGroup(groupId).displayName); - protocolLabel->setText(ConnectionManager->GetConnectionBasicInfo(connectionId)); + protocolLabel->setText(ConnectionManager->GetConnectionProtocolString(connectionId)); auto x = ConnectionManager->GetConnectionInfo(connectionId); addressLabel->setText(get<0>(x)); portLabel->setNum(get<1>(x)); diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index f2fd393e..338ccdcc 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -7,7 +7,7 @@ 0 0 431 - 242 + 205 @@ -17,78 +17,6 @@ 0 - - - - - - - 14 - - - - Connection Name - - - - - - - Delete Connection - - - - - - - :/assets/icons/ui_light/delete.png:/assets/icons/ui_light/delete.png - - - - - - - Edit Connection - - - - - - - :/assets/icons/ui_light/edit.png:/assets/icons/ui_light/edit.png - - - - - - - Delete Connection - - - - - - - :/assets/icons/ui_light/duplicate.png:/assets/icons/ui_light/duplicate.png - - - - - - - Connect To This Connection - - - - - - - :/assets/icons/ui_light/connect.png:/assets/icons/ui_light/connect.png - - - - - @@ -266,15 +194,87 @@ - - + + - + + + + 14 + + + + Connection Name + + + + + + + Delete Connection + + + + + + + :/assets/icons/ui_light/delete.png:/assets/icons/ui_light/delete.png + + + + + Edit Connection Config as JSON - Edit JSON + + + + + :/assets/icons/ui_light/json.png:/assets/icons/ui_light/json.png + + + + + + + Edit Connection + + + + + + + :/assets/icons/ui_light/edit.png:/assets/icons/ui_light/edit.png + + + + + + + Delete Connection + + + + + + + :/assets/icons/ui_light/duplicate.png:/assets/icons/ui_light/duplicate.png + + + + + + + Connect To This Connection + + + + + + + :/assets/icons/ui_light/connect.png:/assets/icons/ui_light/connect.png diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index f2e00152..632c26db 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -15,7 +15,7 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &identifier, QWidg itemType = NODE_ITEM; connNameLabel->setText("" + connection.displayName); latencyLabel->setText(QSTRN(connection.latency) + " " + tr("ms")); - connTypeLabel->setText(tr("Type: ") + ConnectionManager->GetConnectionBasicInfo(identifier)); + connTypeLabel->setText(tr("Type: ") + ConnectionManager->GetConnectionProtocolString(identifier)); dataLabel->setText(FormatBytes(connection.upLinkData + connection.downLinkData)); // indentSpacer->changeSize(10, indentSpacer->sizeHint().height()); From f43e960820cfc2fe10e536aaf7e82816192cf323 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 24 Feb 2020 16:41:42 +0800 Subject: [PATCH 037/332] wip: add: share link textbox update, added live apply global themes --- makespec/BUILDVERSION | 2 +- src/ui/w_PreferencesWindow.cpp | 1 + src/ui/widgets/ConnectionInfoWidget.cpp | 21 +++++++++++++++++++++ src/ui/widgets/ConnectionInfoWidget.hpp | 3 +++ src/ui/widgets/ConnectionInfoWidget.ui | 6 ++++++ 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 1547a983..4a45c385 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3894 +3895 diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index e5ff71ab..8e3b935b 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -253,6 +253,7 @@ void PreferencesWindow::on_buttonBox_accepted() } } + qApp->setStyle(QStyleFactory::create(CurrentConfig.uiConfig.theme)); SaveGlobalConfig(CurrentConfig); emit s_reload_config(IsConnectionPropertyChanged); emit accept(); diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 48d7ea5e..5d5a6bc2 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -9,6 +9,11 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : deleteBtn->setIcon(QICON_R("delete.png")); editBtn->setIcon(QICON_R("edit.png")); editJsonBtn->setIcon(QICON_R("json.png")); + // + shareLinkTxt->setAutoFillBackground(true); + shareLinkTxt->setStyleSheet("border-bottom: 1px solid gray; border-radius: 0px; padding: 2px; background-color: " + this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); + shareLinkTxt->setCursor(QCursor(Qt::CursorShape::IBeamCursor)); + shareLinkTxt->installEventFilter(this); } void ConnectionInfoWidget::ShowDetails(const tuple &_identifier) @@ -27,6 +32,9 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden editJsonBtn->setEnabled(true); connectBtn->setEnabled(true); duplicateBtn->setEnabled(true); + // + shareLinkTxt->setText("scheme://user:pass@host:port/path/to/file?arg1=ARG1&arg2=ARG2#tag"); + shareLinkTxt->setCursorPosition(0); } else { connNameLabel->setText(ConnectionManager->GetGroup(groupId).displayName); groupLabel->setText(tr("N/A")); @@ -61,3 +69,16 @@ void ConnectionInfoWidget::on_deleteBtn_clicked() { ConnectionManager->DeleteConnection(connectionId); } + +bool ConnectionInfoWidget::eventFilter(QObject *object, QEvent *event) +{ + if (event->type() == QEvent::MouseButtonRelease) { + if (shareLinkTxt->underMouse()) { + if (!shareLinkTxt->hasSelectedText()) { + shareLinkTxt->selectAll(); + } + } + } + + return QWidget::eventFilter(object, event); +} diff --git a/src/ui/widgets/ConnectionInfoWidget.hpp b/src/ui/widgets/ConnectionInfoWidget.hpp index 6c8de10f..d8e10e9a 100644 --- a/src/ui/widgets/ConnectionInfoWidget.hpp +++ b/src/ui/widgets/ConnectionInfoWidget.hpp @@ -18,6 +18,9 @@ class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget void on_editJsonBtn_clicked(); void on_deleteBtn_clicked(); + protected: + bool eventFilter(QObject *object, QEvent *event) override; + private: ConnectionId connectionId; GroupId groupId; diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index 338ccdcc..6a59563b 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -10,6 +10,9 @@ 205 + + true + Form @@ -132,6 +135,9 @@ + + IBeamCursor + true From 0ba992b38fcf46c4b26d8fe08f821087d90d784e Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 24 Feb 2020 18:01:14 +0800 Subject: [PATCH 038/332] add: currently use-able --- assets/icons/ui_dark/stop.png | Bin 0 -> 508 bytes assets/icons/ui_light/stop.png | Bin 0 -> 511 bytes makespec/BUILDVERSION | 2 +- resources.qrc | 2 + src/components/speedchart/speedplotview.cpp | 2 +- src/core/handler/ConnectionHandler.cpp | 32 ++++++--- src/core/handler/ConnectionHandler.hpp | 21 +++--- src/core/handler/V2rayInstanceHandler.cpp | 70 ++++++-------------- src/core/kernel/KernelInteractions.cpp | 4 +- src/core/kernel/KernelInteractions.hpp | 2 +- src/ui/w_MainWindow.cpp | 45 +++++++++++++ src/ui/w_MainWindow.hpp | 3 - src/ui/widgets/ConnectionInfoWidget.cpp | 23 ++++++- src/ui/widgets/ConnectionInfoWidget.hpp | 5 ++ 14 files changed, 134 insertions(+), 77 deletions(-) create mode 100644 assets/icons/ui_dark/stop.png create mode 100644 assets/icons/ui_light/stop.png diff --git a/assets/icons/ui_dark/stop.png b/assets/icons/ui_dark/stop.png new file mode 100644 index 0000000000000000000000000000000000000000..981c24d2ad54d9f57a42faadb45be40501184f93 GIT binary patch literal 508 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7xzrU_9*U;uumf=k2wPy~2SKtrt}n zF|aJTz`Tg1#l=`)R)%WULQWS3T?W;PcRk5QlNL5?Rh3{r|IOBY*Uqp1{FU$DWds@p z1qYlz+wAxFR5xo`_3!VhH_v|lQ}yNVxk*oQCtW>vEANY}x%a21OmZJ?eXjn0zh~c5HP5=_Z_xo85&VRmqar>Po5ez`XrT^~M zySi&#fBrvig@(&40e%cmhX}DwsX=A_^2}Y^+r2-%j9@su$ws>Nw67ma!vCGoznLPu z87`aD%Koh|-(dfGmz@+)YSNya4eWcq)ymW!->h@`lhMici}f4U<$9KR#`W%#hXpwU cLxJu;rcG*oRVf!|@B4TAx77g!-0v4|efQ7m7vuJQtA5%3 z>RVm<{rpA#3f|ezf8Kl%y)GzpznlHNsc)VF*+ps%@^}B<^?Ua&gyFJ@t$gk2&~q#W z#=pvAS7pwcr&hzrQqab5h*M$C5FuPy0z%_={l4~Y{VKcpTnYQ{@0S31sfO{*|8m=S zhSOXRZnN6lyY@YO`)ylEpvGB+MOOZ4fyJJ6tNLph>o;xNk{a1}_ix&l gzpyX|#^>4}?9WSH@3Nl!_ZUdj)78&qol`;+0IZJF%m4rY literal 0 HcmV?d00001 diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 4a45c385..46f8bb17 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3895 +3896 diff --git a/resources.qrc b/resources.qrc index 3ed9135b..bb66fcd6 100644 --- a/resources.qrc +++ b/resources.qrc @@ -26,5 +26,7 @@ assets/credit.html assets/icons/ui_dark/connect.png assets/icons/ui_light/connect.png + assets/icons/ui_dark/stop.png + assets/icons/ui_light/stop.png diff --git a/src/components/speedchart/speedplotview.cpp b/src/components/speedchart/speedplotview.cpp index 07a70bb6..9dae7d5f 100644 --- a/src/components/speedchart/speedplotview.cpp +++ b/src/components/speedchart/speedplotview.cpp @@ -35,7 +35,7 @@ #include -#define VIEWABLE 60 +#define VIEWABLE 120 // use binary prefix standards from IEC 60027-2 // see http://en.wikipedia.org/wiki/Kilobyte diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index c5688591..1103d5be 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -4,7 +4,7 @@ namespace Qv2ray::core::handlers { - QvConnectionHandler::QvConnectionHandler() + QvConnectionHandler::QvConnectionHandler() : currentConnectionId("null") { DEBUG(MODULE_CORE_HANDLER, "ConnectionHandler Constructor.") @@ -31,9 +31,10 @@ namespace Qv2ray::core::handlers } } - kernelInstance = new V2rayKernelInstance(); - connect(kernelInstance, &V2rayKernelInstance::OnNewStatsDataArrived, this, &QvConnectionHandler::OnStatsDataArrived); - connect(kernelInstance, &V2rayKernelInstance::OnProcessOutputReadyRead, this, &QvConnectionHandler::OnVCoreLogAvailable); + vCoreInstance = new V2rayKernelInstance(); + connect(vCoreInstance, &V2rayKernelInstance::OnProcessErrored, this, &QvConnectionHandler::OnVCoreCrashed); + connect(vCoreInstance, &V2rayKernelInstance::OnNewStatsDataArrived, this, &QvConnectionHandler::OnStatsDataArrived); + connect(vCoreInstance, &V2rayKernelInstance::OnProcessOutputReadyRead, this, &QvConnectionHandler::OnVCoreLogAvailable); saveTimerId = startTimer(60000); } const QList QvConnectionHandler::Connections() const @@ -86,8 +87,23 @@ namespace Qv2ray::core::handlers return tr("No connection selected!") + NEWLINE + tr("Please select a config from the list."); } + StopConnection(); CONFIGROOT root = CHGetConnectionRoot_p(connections[identifier].groupId, identifier); - return CHTryStartConnection_p(identifier, root); + return CHStartConnection_p(identifier, root); + } + + void QvConnectionHandler::StopConnection() //const ConnectionId &id + { + // Currently just simply stop it. + //_UNUSED(id) + //if (currentConnectionId == id) { + //} + CHStopConnection_p(); + } + + bool QvConnectionHandler::IsConnected(const ConnectionId &id) const + { + return currentConnectionId == id; } const QString QvConnectionHandler::GetConnectionProtocolString(const ConnectionId &id) const @@ -123,12 +139,12 @@ namespace Qv2ray::core::handlers QvConnectionHandler::~QvConnectionHandler() { - if (kernelInstance->KernelStarted) { - kernelInstance->StopConnection(); + if (vCoreInstance->KernelStarted) { + vCoreInstance->StopConnection(); LOG(MODULE_CORE_HANDLER, "Stopped connection from destructor.") } - delete kernelInstance; + delete vCoreInstance; } const CONFIGROOT QvConnectionHandler::CHGetConnectionRoot_p(const ConnectionId &id) const diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index db596b4d..3fbb23b6 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -20,15 +20,10 @@ namespace Qv2ray::core::handlers const QList Subscriptions() const; const QList Connections(const GroupId &groupId) const; // - bool IsConnectionConnected(const ConnectionId &id) const; - // - const optional StopConnection(const ConnectionId &id); + // Connectivity Operationss + bool IsConnected(const ConnectionId &id) const; const optional StartConnection(const ConnectionId &identifier); - - private slots: - void OnStatsDataArrived(const ConnectionId &id, const QString tag, const quint64 uploadSpeed, const quint64 downloadSpeed); - // - public: + void StopConnection(); //const ConnectionId &id // // Connection Operations. const ConnectionMetaObject GetConnection(const ConnectionId &id) const; @@ -85,10 +80,15 @@ namespace Qv2ray::core::handlers void OnSubscriptionDeleted(const GroupId &id, const QString &oldName, const QString &newName); void OnSubscriptionUpdateFinished(const GroupId &id); + private slots: + void OnStatsDataArrived(const ConnectionId &id, const QString tag, const quint64 uploadSpeed, const quint64 downloadSpeed); + void OnVCoreCrashed(const ConnectionId &id); + private: // bool CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port); - optional CHTryStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); + optional CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); + void CHStopConnection_p(); const CONFIGROOT CHGetConnectionRoot_p(const ConnectionId &id) const; const CONFIGROOT CHGetConnectionRoot_p(const GroupId &group, const ConnectionId &id) const; bool CHSaveConnectionConfig(CONFIGROOT obj, const ConnectionId &id, bool override); @@ -98,7 +98,8 @@ namespace Qv2ray::core::handlers #ifdef QV2RAY_MULTIPlE_ONNECTION QHash kernelInstances; #else - V2rayKernelInstance *kernelInstance = nullptr; + ConnectionId currentConnectionId; + V2rayKernelInstance *vCoreInstance = nullptr; #endif int saveTimerId; int apiTimerId; diff --git a/src/core/handler/V2rayInstanceHandler.cpp b/src/core/handler/V2rayInstanceHandler.cpp index 2e808731..c525bf20 100644 --- a/src/core/handler/V2rayInstanceHandler.cpp +++ b/src/core/handler/V2rayInstanceHandler.cpp @@ -1,66 +1,30 @@ #include "ConnectionHandler.hpp" #include "core/connection/Generation.hpp" -optional QvConnectionHandler::CHTryStartConnection_p(const ConnectionId &id, const CONFIGROOT &root) +optional QvConnectionHandler::CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root) { auto &connectionMeta = connections[id]; auto fullConfig = GenerateRuntimeConfig(root); // - auto result = kernelInstance->StartConnection(id, fullConfig); + auto result = vCoreInstance->StartConnection(id, fullConfig); if (!result.has_value()) { - emit OnConnected(id); + currentConnectionId = id; + emit OnConnected(currentConnectionId); connectionMeta.lastConnected = system_clock::to_time_t(system_clock::now()); } return result; - //if (startFlag) { - // bool usePAC = GlobalConfig.inboundConfig.pacConfig.enablePAC; - // bool pacUseSocks = GlobalConfig.inboundConfig.pacConfig.useSocksProxy; - // bool httpEnabled = GlobalConfig.inboundConfig.useHTTP; - // bool socksEnabled = GlobalConfig.inboundConfig.useSocks; - // - // if (usePAC) { - // bool canStartPAC = true; - // QString pacProxyString; // Something like this --> SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT; http://proxy:8080 - // auto pacIP = GlobalConfig.inboundConfig.pacConfig.localIP; - // - // if (pacIP.isEmpty()) { - // LOG(MODULE_PROXY, "PAC Local IP is empty, default to 127.0.0.1") - // pacIP = "127.0.0.1"; - // } - // - // if (pacUseSocks) { - // if (socksEnabled) { - // pacProxyString = "SOCKS5 " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.socks_port); - // } else { - // LOG(MODULE_UI, "PAC is using SOCKS, but it is not enabled") - // QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use SOCKS, but it is not enabled")); - // canStartPAC = false; - // } - // } else { - // if (httpEnabled) { - // pacProxyString = "PROXY " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.http_port); - // } else { - // LOG(MODULE_UI, "PAC is using HTTP, but it is not enabled") - // QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use HTTP, but it is not enabled")); - // canStartPAC = false; - // } - // } - // - // if (canStartPAC) { - // pacServer.SetProxyString(pacProxyString); - // pacServer.StartListen(); - // } else { - // LOG(MODULE_PROXY, "Not starting PAC due to previous error.") - // } - // } - // - // if (GlobalConfig.inboundConfig.setSystemProxy) { - // MWSetSystemProxy(); - // } - //} - //return "startFlag"; +} + +void QvConnectionHandler::CHStopConnection_p() +{ + if (vCoreInstance->KernelStarted) { + vCoreInstance->StopConnection(); + emit OnDisConnected(currentConnectionId); + } else { + LOG(MODULE_CORE_HANDLER, "VCore is not started, not disconnecting") + } } void QvConnectionHandler::OnStatsDataArrived(const ConnectionId &id, const QString tag, const quint64 uploadSpeed, const quint64 downloadSpeed) @@ -70,3 +34,9 @@ void QvConnectionHandler::OnStatsDataArrived(const ConnectionId &id, const QStri connections[id].upLinkData += uploadSpeed; connections[id].downLinkData += downloadSpeed; } + +void QvConnectionHandler::OnVCoreCrashed(const ConnectionId &id) +{ + LOG(MODULE_CORE_HANDLER, "V2ray core crashed!") + emit OnDisConnected(id); +} diff --git a/src/core/kernel/KernelInteractions.cpp b/src/core/kernel/KernelInteractions.cpp index e68d7284..b00c3861 100644 --- a/src/core/kernel/KernelInteractions.cpp +++ b/src/core/kernel/KernelInteractions.cpp @@ -123,14 +123,14 @@ namespace Qv2ray::core::kernel connect(vProcess, &QProcess::readyReadStandardOutput, this, [&]() { emit OnProcessOutputReadyRead(id, vProcess->readAllStandardOutput().trimmed()); }); - connect(vProcess, &QProcess::stateChanged, [this](QProcess::ProcessState state) { + connect(vProcess, &QProcess::stateChanged, [&](QProcess::ProcessState state) { DEBUG(MODULE_VCORE, "V2ray kernel process status changed: " + QVariant::fromValue(state).toString()) // If V2ray crashed AFTER we start it. if (KernelStarted && state == QProcess::NotRunning) { LOG(MODULE_VCORE, "V2ray kernel crashed.") StopConnection(); - emit OnProcessErrored(); + emit OnProcessErrored(id); } }); apiWorker = new APIWorker(); diff --git a/src/core/kernel/KernelInteractions.hpp b/src/core/kernel/KernelInteractions.hpp index 819e2896..de9358cc 100644 --- a/src/core/kernel/KernelInteractions.hpp +++ b/src/core/kernel/KernelInteractions.hpp @@ -27,7 +27,7 @@ namespace Qv2ray::core::kernel static bool ValidateKernel(const QString &vCorePath, const QString &vAssetsPath, QString *message); signals: - void OnProcessErrored(); + void OnProcessErrored(const ConnectionId &id); void OnProcessOutputReadyRead(const ConnectionId &id, const QString &output); void OnNewStatsDataArrived(const ConnectionId &id, const QString &tag, const quint64 _totalUp, const quint64 _totalDown); diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 3ed5ce70..c689a6dc 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -862,6 +862,51 @@ void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item void MainWindow::OnConnected(const ConnectionId &id) { Q_UNUSED(id) + on_clearlogButton_clicked(); + bool usePAC = GlobalConfig.inboundConfig.pacConfig.enablePAC; + bool pacUseSocks = GlobalConfig.inboundConfig.pacConfig.useSocksProxy; + bool httpEnabled = GlobalConfig.inboundConfig.useHTTP; + bool socksEnabled = GlobalConfig.inboundConfig.useSocks; + + if (usePAC) { + bool canStartPAC = true; + QString pacProxyString; // Something like this --> SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT; http://proxy:8080 + auto pacIP = GlobalConfig.inboundConfig.pacConfig.localIP; + + if (pacIP.isEmpty()) { + LOG(MODULE_PROXY, "PAC Local IP is empty, default to 127.0.0.1") + pacIP = "127.0.0.1"; + } + + if (pacUseSocks) { + if (socksEnabled) { + pacProxyString = "SOCKS5 " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.socks_port); + } else { + LOG(MODULE_UI, "PAC is using SOCKS, but it is not enabled") + QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use SOCKS, but it is not enabled")); + canStartPAC = false; + } + } else { + if (httpEnabled) { + pacProxyString = "PROXY " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.http_port); + } else { + LOG(MODULE_UI, "PAC is using HTTP, but it is not enabled") + QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use HTTP, but it is not enabled")); + canStartPAC = false; + } + } + + if (canStartPAC) { + //pacServer.SetProxyString(pacProxyString); + //pacServer.StartListen(); + } else { + LOG(MODULE_PROXY, "Not starting PAC due to previous error.") + } + } + + if (GlobalConfig.inboundConfig.setSystemProxy) { + MWSetSystemProxy(); + } } diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index f568dae3..738f7620 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -90,9 +90,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow // QMenu *connectionListMenu; // - //QvConnectionObject renameOriginalIdentifier; - bool isRenamingInProgress; - // #ifndef DISABLE_AUTO_UPDATE QvHttpRequestHelper *requestHelper; #endif diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 5d5a6bc2..768a4e55 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -14,6 +14,9 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : shareLinkTxt->setStyleSheet("border-bottom: 1px solid gray; border-radius: 0px; padding: 2px; background-color: " + this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); shareLinkTxt->setCursor(QCursor(Qt::CursorShape::IBeamCursor)); shareLinkTxt->installEventFilter(this); + // + connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &ConnectionInfoWidget::OnConnected); + connect(ConnectionManager, &QvConnectionHandler::OnDisConnected, this, &ConnectionInfoWidget::OnDisConnected); } void ConnectionInfoWidget::ShowDetails(const tuple &_identifier) @@ -54,7 +57,11 @@ ConnectionInfoWidget::~ConnectionInfoWidget() void ConnectionInfoWidget::on_connectBtn_clicked() { - ConnectionManager->StartConnection(connectionId); + if (ConnectionManager->IsConnected(connectionId)) { + ConnectionManager->StartConnection(connectionId); + } else { + ConnectionManager->StopConnection(); + } } void ConnectionInfoWidget::on_editBtn_clicked() @@ -82,3 +89,17 @@ bool ConnectionInfoWidget::eventFilter(QObject *object, QEvent *event) return QWidget::eventFilter(object, event); } + +void ConnectionInfoWidget::OnConnected(const ConnectionId &id) +{ + if (connectionId == id) { + connectBtn->setIcon(QICON_R("stop.png")); + } +} + +void ConnectionInfoWidget::OnDisConnected(const ConnectionId &id) +{ + if (connectionId == id) { + connectBtn->setIcon(QICON_R("connect.png")); + } +} diff --git a/src/ui/widgets/ConnectionInfoWidget.hpp b/src/ui/widgets/ConnectionInfoWidget.hpp index d8e10e9a..475c3e8d 100644 --- a/src/ui/widgets/ConnectionInfoWidget.hpp +++ b/src/ui/widgets/ConnectionInfoWidget.hpp @@ -12,6 +12,7 @@ class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget explicit ConnectionInfoWidget(QWidget *parent = nullptr); void ShowDetails(const tuple &_identifier); ~ConnectionInfoWidget(); + private slots: void on_connectBtn_clicked(); void on_editBtn_clicked(); @@ -21,6 +22,10 @@ class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget protected: bool eventFilter(QObject *object, QEvent *event) override; + private slots: + void OnConnected(const ConnectionId &id); + void OnDisConnected(const ConnectionId &id); + private: ConnectionId connectionId; GroupId groupId; From e45a44f039236a48a35ce596e1ff1054213f5d63 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 24 Feb 2020 22:04:12 +0800 Subject: [PATCH 039/332] add: added auto connection support, save data usage support, check connected support, mainwindow partial ui support, disconnect support and a dot-indicator support on the connection list --- src/base/models/QvConfigIdentifier.hpp | 10 +-- src/core/CoreSafeTypes.hpp | 38 +++++++---- src/core/config/ConfigUpgrade.cpp | 17 +++++ src/core/handler/ConnectionHandler.cpp | 83 ++++++++++++++++++++--- src/core/handler/ConnectionHandler.hpp | 20 ++++-- src/core/handler/V2rayInstanceHandler.cpp | 5 +- src/ui/w_MainWindow.cpp | 32 +++++++-- src/ui/w_MainWindow.hpp | 7 +- src/ui/w_MainWindow.ui | 24 ++++--- src/ui/w_MainWindow_extra.cpp | 31 --------- src/ui/widgets/ConnectionInfoWidget.cpp | 13 ++-- src/ui/widgets/ConnectionItemWidget.cpp | 43 +++++++++--- src/ui/widgets/ConnectionItemWidget.hpp | 7 +- src/ui/widgets/ConnectionItemWidget.ui | 2 +- 14 files changed, 227 insertions(+), 105 deletions(-) diff --git a/src/base/models/QvConfigIdentifier.hpp b/src/base/models/QvConfigIdentifier.hpp index a7d3d428..8f871966 100644 --- a/src/base/models/QvConfigIdentifier.hpp +++ b/src/base/models/QvConfigIdentifier.hpp @@ -6,19 +6,15 @@ namespace Qv2ray::base { using namespace std::chrono; // Common struct for Groups and Subscriptions - struct GroupObjectBase { + struct GroupObject_Config { QString displayName; QList connections; int64_t importDate; - GroupObjectBase(): displayName(), connections(), importDate() { } - }; - - struct GroupObject_Config : GroupObjectBase { - GroupObject_Config() { } + GroupObject_Config(): displayName(), connections(), importDate() { } XTOSTRUCT(O(displayName, connections, importDate)) }; - struct SubscriptionObject_Config : GroupObjectBase { + struct SubscriptionObject_Config : GroupObject_Config { // QString address; int64_t lastUpdated; diff --git a/src/core/CoreSafeTypes.hpp b/src/core/CoreSafeTypes.hpp index bcdb9916..2bdb58ce 100644 --- a/src/core/CoreSafeTypes.hpp +++ b/src/core/CoreSafeTypes.hpp @@ -29,7 +29,14 @@ namespace Qv2ray::core QString m_id; }; + + // Define several safetypes to prevent misuse of QString. + class __QvGroup; + class __QvConnection; + typedef IDType<__QvGroup> GroupId; + typedef IDType<__QvConnection> ConnectionId; template + QList StringsToIdList(const QList &strings) { QList list; @@ -41,16 +48,21 @@ namespace Qv2ray::core return list; } + template + QList IdListToStrings(const QList &ids) + { + QList list; + + for (auto id : ids) { + list << id.toString(); + } + + return list; + } template uint qHash(const IDType &key, uint seed = 0) { return key.qHash(seed); } - - // Define several safetypes to prevent misuse of QString. - class __QvGroup; - class __QvConnection; - typedef IDType<__QvGroup> GroupId; - typedef IDType<__QvConnection> ConnectionId; // /// Metadata object representing a connection. struct ConnectionMetaObject : ConnectionObject_Config { @@ -69,30 +81,26 @@ namespace Qv2ray::core }; /// Metadata object representing a group. - struct GroupMetaObject: SubscriptionObject_Config { + struct GroupMetaObject: SubscriptionObject_Config { // Implicit base of two types, since group object is actually the group base object. bool isSubscription; QList connections; // Suger for down casting. GroupMetaObject(): connections() {} - GroupMetaObject(const GroupObjectBase &base): GroupMetaObject() + GroupMetaObject(const GroupObject_Config &base): GroupMetaObject() { + this->isSubscription = false; this->displayName = base.displayName; this->importDate = base.importDate; this->connections = StringsToIdList(base.connections); } // Suger for down casting. - GroupMetaObject(const GroupObject_Config &base): GroupMetaObject((GroupObjectBase)base) + GroupMetaObject(const SubscriptionObject_Config &base): GroupMetaObject((GroupObject_Config)base) { - this->isSubscription = false; - } - // Suger for down casting. - GroupMetaObject(const SubscriptionObject_Config &base): GroupMetaObject((GroupObjectBase)base) - { - this->isSubscription = true; this->address = base.address; this->lastUpdated = base.lastUpdated; this->updateInterval = base.updateInterval; + this->isSubscription = true; } }; } diff --git a/src/core/config/ConfigUpgrade.cpp b/src/core/config/ConfigUpgrade.cpp index c6fbc0b1..4b07e8cc 100644 --- a/src/core/config/ConfigUpgrade.cpp +++ b/src/core/config/ConfigUpgrade.cpp @@ -132,6 +132,13 @@ namespace Qv2ray auto newUuid = GenerateUuid(); DEBUG(MODULE_SETTINGS, "Generated new UUID: " + newUuid); + // Check Autostart Id + if (root["autoStartConfig"].toObject()["subscriptionName"].toString().isEmpty()) { + if (root["autoStartConfig"].toObject()["connectionName"].toString() == config.toString()) { + autoStartId = newUuid; + } + } + if (configFile.exists()) { auto newPath = QV2RAY_CONNECTIONS_DIR + defaultGroupId + "/" + newUuid + QV2RAY_CONFIG_FILE_EXTENSION; configFile.rename(newPath); @@ -188,6 +195,15 @@ namespace Qv2ray UPGRADELOG("Moved subscription file from: " + baseFilePath + " to: " + newFilePath); subsConnectionIds << subsConnectionId; rootConnections[subsConnectionId] = subsConnection; + + // + + // Check Autostart Id + if (root["autoStartConfig"].toObject()["subscriptionName"].toString() == key) { + if (root["autoStartConfig"].toObject()["connectionName"].toString() == subsConnection["displayName"].toString()) { + autoStartId = subsConnectionId; + } + } } subs["connections"] = QJsonArray::fromStringList(subsConnectionIds); @@ -198,6 +214,7 @@ namespace Qv2ray defaultGroup["connections"] = QJsonArray::fromStringList(defaultGroupConnectionId); QJsonObject groups; groups[defaultGroupId] = defaultGroup; + root["autoStartId"] = autoStartId; root["groups"] = groups; root["connections"] = rootConnections; root["subscriptions"] = newSubscriptions; diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index 1103d5be..cf0324fa 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -1,5 +1,6 @@ #include "ConnectionHandler.hpp" #include "common/QvHelpers.hpp" +#include "core/config/ConfigBackend.hpp" namespace Qv2ray::core::handlers { @@ -35,8 +36,45 @@ namespace Qv2ray::core::handlers connect(vCoreInstance, &V2rayKernelInstance::OnProcessErrored, this, &QvConnectionHandler::OnVCoreCrashed); connect(vCoreInstance, &V2rayKernelInstance::OnNewStatsDataArrived, this, &QvConnectionHandler::OnStatsDataArrived); connect(vCoreInstance, &V2rayKernelInstance::OnProcessOutputReadyRead, this, &QvConnectionHandler::OnVCoreLogAvailable); - saveTimerId = startTimer(60000); + saveTimerId = startTimer(10 * 1000); } + + void QvConnectionHandler::CHSaveConnectionData_p() + { + // Copy + auto newGlobalConfig = GlobalConfig; + newGlobalConfig.connections.clear(); + newGlobalConfig.groups.clear(); + newGlobalConfig.subscriptions.clear(); + + for (auto i = 0; i < connections.count(); i++) { + newGlobalConfig.connections[connections.keys()[i].toString()] = connections.values()[i]; + } + + for (auto i = 0; i < groups.count(); i++) { + QStringList connections = IdListToStrings(groups.values()[i].connections); + + if (groups.values()[i].isSubscription) { + SubscriptionObject_Config o = groups.values()[i]; + o.connections = connections; + newGlobalConfig.subscriptions[groups.keys()[i].toString()] = o; + } else { + GroupObject_Config o = groups.values()[i]; + o.connections = connections; + newGlobalConfig.groups[groups.keys()[i].toString()] = o; + } + } + + SaveGlobalConfig(newGlobalConfig); + } + + void QvConnectionHandler::timerEvent(QTimerEvent *event) + { + if (event->timerId() == saveTimerId) { + CHSaveConnectionData_p(); + } + } + const QList QvConnectionHandler::Connections() const { return connections.keys(); @@ -65,13 +103,32 @@ namespace Qv2ray::core::handlers return groups[groupId].connections; } - const ConnectionMetaObject QvConnectionHandler::GetConnection(const ConnectionId &id) const + const QString QvConnectionHandler::GetDisplayName(const ConnectionId &id) const + { + return connections[id].displayName; + } + + const QString QvConnectionHandler::GetDisplayName(const GroupId &id) const + { + return groups[id].displayName; + } + + const GroupId QvConnectionHandler::GetConnectionGroupId(const ConnectionId &id) const { if (!connections.contains(id)) { LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); } - return connections[id]; + return connections[id].groupId; + } + + int64_t QvConnectionHandler::GetConnectionLatency(const ConnectionId &id) const + { + if (!connections.contains(id)) { + LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); + } + + return connections[id].latency; } const optional QvConnectionHandler::DeleteConnection(const ConnectionId &id) @@ -131,14 +188,24 @@ namespace Qv2ray::core::handlers return result; } - - const GroupMetaObject QvConnectionHandler::GetGroup(const GroupId &id) const + const tuple QvConnectionHandler::GetConnectionUsageAmount(const ConnectionId &id) const { - return groups[id]; + if (!connections.contains(id)) { + return make_tuple(0, 0); + } + + return make_tuple(connections[id].upLinkData, connections[id].downLinkData); } + //const GroupMetaObject QvConnectionHandler::GetGroup(const GroupId &id) const + //{ + // return groups[id]; + //} + QvConnectionHandler::~QvConnectionHandler() { + CHSaveConnectionData_p(); + if (vCoreInstance->KernelStarted) { vCoreInstance->StopConnection(); LOG(MODULE_CORE_HANDLER, "Stopped connection from destructor.") @@ -160,7 +227,7 @@ namespace Qv2ray::core::handlers } // - const tuple QvConnectionHandler::GetConnectionInfo(const ConnectionId &id) + const tuple QvConnectionHandler::GetConnectionInfo(const ConnectionId &id) const { auto root = CHGetConnectionRoot_p(id); bool validOutboundFound = false; @@ -182,7 +249,7 @@ namespace Qv2ray::core::handlers return make_tuple(QObject::tr("N/A"), 0); } - bool QvConnectionHandler::CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port) + bool QvConnectionHandler::CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port) const { // Set initial values. *host = QObject::tr("N/A"); diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 3fbb23b6..593e8d1e 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -20,13 +20,18 @@ namespace Qv2ray::core::handlers const QList Subscriptions() const; const QList Connections(const GroupId &groupId) const; // + // Generic Get Options + const QString GetDisplayName(const ConnectionId &id) const; + const QString GetDisplayName(const GroupId &id) const; + // // Connectivity Operationss bool IsConnected(const ConnectionId &id) const; const optional StartConnection(const ConnectionId &identifier); void StopConnection(); //const ConnectionId &id // // Connection Operations. - const ConnectionMetaObject GetConnection(const ConnectionId &id) const; + const GroupId GetConnectionGroupId(const ConnectionId &id) const; + int64_t GetConnectionLatency(const ConnectionId &id) const; const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); const optional DeleteConnection(const ConnectionId &id); const optional UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); @@ -36,7 +41,8 @@ namespace Qv2ray::core::handlers // // Get Conncetion Property const QString GetConnectionProtocolString(const ConnectionId &id) const; - const tuple GetConnectionInfo(const ConnectionId &connectionId); + const tuple GetConnectionInfo(const ConnectionId &connectionId) const; + const tuple GetConnectionUsageAmount(const ConnectionId &id) const; // // Misc Connection Operations const optional TestLatency(); @@ -44,7 +50,7 @@ namespace Qv2ray::core::handlers const optional TestLatency(const ConnectionId &id); // // Group Operations - const GroupMetaObject GetGroup(const GroupId &id) const; + //const GroupMetaObject GetGroup(const GroupId &id) const; const optional DeleteGroup(const GroupId &id); const optional DuplicateGroup(const GroupId &id); const GroupId &CreateGroup(const QString displayName, bool isSubscription); @@ -84,14 +90,18 @@ namespace Qv2ray::core::handlers void OnStatsDataArrived(const ConnectionId &id, const QString tag, const quint64 uploadSpeed, const quint64 downloadSpeed); void OnVCoreCrashed(const ConnectionId &id); + protected: + void timerEvent(QTimerEvent *event) override; + private: + void CHSaveConnectionData_p(); // - bool CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port); + bool CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port) const; optional CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); void CHStopConnection_p(); const CONFIGROOT CHGetConnectionRoot_p(const ConnectionId &id) const; const CONFIGROOT CHGetConnectionRoot_p(const GroupId &group, const ConnectionId &id) const; - bool CHSaveConnectionConfig(CONFIGROOT obj, const ConnectionId &id, bool override); + bool CHSaveConnectionConfig_p(CONFIGROOT obj, const ConnectionId &id, bool override); // // // We only support one cuncurrent connection currently. diff --git a/src/core/handler/V2rayInstanceHandler.cpp b/src/core/handler/V2rayInstanceHandler.cpp index c525bf20..5087704a 100644 --- a/src/core/handler/V2rayInstanceHandler.cpp +++ b/src/core/handler/V2rayInstanceHandler.cpp @@ -21,7 +21,10 @@ void QvConnectionHandler::CHStopConnection_p() { if (vCoreInstance->KernelStarted) { vCoreInstance->StopConnection(); - emit OnDisConnected(currentConnectionId); + // Copy + ConnectionId id = currentConnectionId; + currentConnectionId = ConnectionId("null"); + emit OnDisConnected(id); } else { LOG(MODULE_CORE_HANDLER, "VCore is not started, not disconnecting") } diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index c689a6dc..4d60ca1a 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -105,9 +105,6 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr connectionInfoLayout->addWidget(infoWidget); // vCoreLogHighlighter = new SyntaxHighlighter(GlobalConfig.uiConfig.useDarkTheme, masterLogBrowser->document()); - masterLogBrowser->document()->setDocumentMargin(8); - masterLogBrowser->document()->adjustSize(); - masterLogBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap); // For charts speedChartWidget = new SpeedWidget(this); speedChart->addWidget(speedChartWidget); @@ -202,13 +199,13 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr auto groups = ConnectionManager->AllGroups(); for (auto group : groups) { - auto groupItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetGroup(group).displayName); + auto groupItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetDisplayName(group)); connectionListWidget->addTopLevelItem(groupItem); connectionListWidget->setItemWidget(groupItem, 0, new ConnectionItemWidget(group, connectionListWidget)); auto connections = ConnectionManager->Connections(group); for (auto connection : connections) { - auto connectionItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetConnection(connection).displayName); + auto connectionItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetDisplayName(connection)); groupItem->addChild(connectionItem); auto widget = new ConnectionItemWidget(connection, connectionListWidget); connect(widget, &ConnectionItemWidget::RequestWidgetFocus, this, &MainWindow::onConnectionWidgetFocusRequested); @@ -218,7 +215,17 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr // // Find and start if there is an auto-connection - if (!MWFindAndStartAutoConfig()) { + auto needShowWindow = true; + + if (!GlobalConfig.autoStartId.isEmpty()) { + auto id = ConnectionId(GlobalConfig.autoStartId); + ConnectionManager->StartConnection(id); + needShowWindow = ConnectionManager->IsConnected(id); + } else { + needShowWindow = true; + } + + if (needShowWindow) { this->show(); } @@ -922,6 +929,9 @@ void MainWindow::onConnectionWidgetFocusRequested(const ConnectionItemWidget *_w if (myWidget == _widget) { LOG(MODULE_UI, "Setting current item.") connectionListWidget->setCurrentItem(_item_); + connectionListWidget->scrollToItem(_item_); + // Click it to show details. + on_connectionListWidget_itemClicked(_item_, 0); } } } @@ -967,6 +977,16 @@ void MainWindow::onConnectionStatsArrived(const ConnectionId &id, const quint64 // This may not be, or may not precisely be, speed per second if low-level has "any" latency. // (Hope not...) speedChartWidget->AddPointData(upSpeed, downSpeed); + auto data = ConnectionManager->GetConnectionUsageAmount(id); + auto totalSpeedUp = FormatBytes(upSpeed) + "/s"; + auto totalSpeedDown = FormatBytes(downSpeed) + "/s"; + auto totalDataUp = FormatBytes(get<0>(data)); + auto totalDataDown = FormatBytes(get<1>(data)); + // + netspeedLabel->setText(totalSpeedUp + NEWLINE + totalSpeedDown); + dataamountLabel->setText(totalDataUp + NEWLINE + totalDataDown); + // + hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + id.toString() + NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); } void MainWindow::onVCoreLogArrived(const ConnectionId &id, const QString &log) diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 738f7620..2cc2845a 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -54,7 +54,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow void VersionUpdate(QByteArray &data); #endif // - void OnConnected(const ConnectionId &id); public: static MainWindow *mwInstance; @@ -66,6 +65,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow private slots: // + void OnConnected(const ConnectionId &id); void onConnectionWidgetFocusRequested(const ConnectionItemWidget *widget); //void onConnectionConnected(const ConnectionId &id); //void onConnectionDisConnected(const ConnectionId &id); @@ -83,13 +83,9 @@ class MainWindow : public QMainWindow, Ui::MainWindow private: QTreeWidgetItem *CurrentItem; - //CONFIGROOT currentFullConfig; - // // Charts SpeedWidget *speedChartWidget; - // QMenu *connectionListMenu; - // #ifndef DISABLE_AUTO_UPDATE QvHttpRequestHelper *requestHelper; #endif @@ -116,7 +112,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow // // ----------------------------------- Extra Headers For w_MainWindow_extra.cpp Handling V2ray Connectivities. bool systemProxyEnabled; - bool MWFindAndStartAutoConfig(); void MWStopConnection(); void MWSetSystemProxy(); void MWClearSystemProxy(bool); diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index ea7b910f..4470d7f2 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -6,14 +6,14 @@ 0 0 - 955 - 695 + 900 + 650 - 800 - 590 + 900 + 650 @@ -76,10 +76,10 @@ - 2 + 4 - 2 + 6 @@ -224,7 +224,7 @@ 0 0 - 581 + 526 706 @@ -338,6 +338,14 @@ 200 + + + 9 + + + + QTextEdit::NoWrap + @@ -471,7 +479,7 @@ 0 0 - 955 + 900 26 diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index 268ed0a7..90cbf865 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -30,37 +30,6 @@ // return nullptr; //} -bool MainWindow::MWFindAndStartAutoConfig() -{ - //if (!GlobalConfig.autoStartConfig.connectionName.isEmpty()) { - // // User has auto start configured, we try to find that connection item. - // auto name = GlobalConfig.autoStartConfig.subscriptionName.isEmpty() - // ? GlobalConfig.autoStartConfig.connectionName - // : GlobalConfig.autoStartConfig.connectionName + " (" + tr("Subscription:") + " " + GlobalConfig.autoStartConfig.subscriptionName + ")"; - // // - // LOG(UI, "Found auto start config: " + name) - // auto item = FindItemByIdentifier(GlobalConfig.autoStartConfig); - // - // if (item != nullptr) { - // // We found the item required and start it. - // connectionListWidget->setCurrentItem(item); - // on_connectionListWidget_currentItemChanged(item, nullptr); - // connectionListWidget->scrollToItem(item); - // tray_RootMenu->actions()[0]->setText(tr("Show")); - // on_startButton_clicked(); - // } else { - // QvMessageBoxWarn(this, tr("Autostarting a config"), tr("Could not find a specified config named: ") + NEWLINE + - // name + NEWLINE + NEWLINE + - // tr("Please reset the settings in Preference Window")); - // } - //} else if (connectionListWidget->topLevelItemCount() > 0) { - // // Make the first one our default selected item. - // connectionListWidget->setCurrentItem(connectionListWidget->topLevelItem(0)); - // ShowAndSetConnection(ItemConnectionIdentifier(connectionListWidget->topLevelItem(0)), true, false); - //} - return true; -} - void MainWindow::MWClearSystemProxy(bool showMessage) { ClearSystemProxy(); diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 768a4e55..28456b55 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -25,8 +25,8 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden connectionId = get<1>(_identifier); if (connectionId.toString() != "null") { - connNameLabel->setText(ConnectionManager->GetConnection(connectionId).displayName); - groupLabel->setText(ConnectionManager->GetGroup(groupId).displayName); + connNameLabel->setText(ConnectionManager->GetDisplayName(connectionId)); + groupLabel->setText(ConnectionManager->GetDisplayName(groupId)); protocolLabel->setText(ConnectionManager->GetConnectionProtocolString(connectionId)); auto x = ConnectionManager->GetConnectionInfo(connectionId); addressLabel->setText(get<0>(x)); @@ -38,8 +38,11 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden // shareLinkTxt->setText("scheme://user:pass@host:port/path/to/file?arg1=ARG1&arg2=ARG2#tag"); shareLinkTxt->setCursorPosition(0); + // + connectBtn->setIcon(ConnectionManager->IsConnected(connectionId) ? QICON_R("stop.png") : QICON_R("connect.png")); } else { - connNameLabel->setText(ConnectionManager->GetGroup(groupId).displayName); + connNameLabel->setText(ConnectionManager->GetDisplayName(groupId)); + connectBtn->setIcon(QICON_R("connect.png")); groupLabel->setText(tr("N/A")); protocolLabel->setText(tr("N/A")); addressLabel->setText(tr("N/A")); @@ -58,9 +61,9 @@ ConnectionInfoWidget::~ConnectionInfoWidget() void ConnectionInfoWidget::on_connectBtn_clicked() { if (ConnectionManager->IsConnected(connectionId)) { - ConnectionManager->StartConnection(connectionId); - } else { ConnectionManager->StopConnection(); + } else { + ConnectionManager->StartConnection(connectionId); } } diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index 632c26db..80208ea8 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -5,18 +5,22 @@ ConnectionItemWidget::ConnectionItemWidget(QWidget *parent) : QWidget(parent), c { setupUi(this); connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &ConnectionItemWidget::OnConnected); + connect(ConnectionManager, &QvConnectionHandler::OnDisConnected, this, &ConnectionItemWidget::OnDisConnected); + connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &ConnectionItemWidget::OnConnectionStatsArrived); } -ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &identifier, QWidget *parent): ConnectionItemWidget(parent) +ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *parent): ConnectionItemWidget(parent) { - auto connection = ConnectionManager->GetConnection(identifier); - connectionId = identifier; - groupId = connection.groupId; + connectionId = id; + groupId = ConnectionManager->GetConnectionGroupId(id); + originalConnectionName = ConnectionManager->GetDisplayName(id); itemType = NODE_ITEM; - connNameLabel->setText("" + connection.displayName); - latencyLabel->setText(QSTRN(connection.latency) + " " + tr("ms")); - connTypeLabel->setText(tr("Type: ") + ConnectionManager->GetConnectionProtocolString(identifier)); - dataLabel->setText(FormatBytes(connection.upLinkData + connection.downLinkData)); + connNameLabel->setText("" + originalConnectionName); + // TODO + latencyLabel->setText(QSTRN(ConnectionManager->GetConnectionLatency(id)) + " " + tr("ms")); + connTypeLabel->setText(tr("Type: ") + ConnectionManager->GetConnectionProtocolString(id)); + auto [uplink, downlink] = ConnectionManager->GetConnectionUsageAmount(connectionId); + dataLabel->setText(FormatBytes(uplink) + " / " + FormatBytes(downlink)); // indentSpacer->changeSize(10, indentSpacer->sizeHint().height()); } @@ -26,9 +30,9 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : { groupId = id; itemType = GROUP_HEADER_ITEM; - auto displayName = ConnectionManager->GetGroup(id).displayName; + originalConnectionName = ConnectionManager->GetDisplayName(id); auto connectionCount = ConnectionManager->Connections(id).count(); - connNameLabel->setText(/*"• " +*/ displayName); + connNameLabel->setText(originalConnectionName); latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections"))); // layout()->removeWidget(connTypeLabel); @@ -50,11 +54,30 @@ void ConnectionItemWidget::BeginConnection() void ConnectionItemWidget::OnConnected(const ConnectionId &id) { if (id == connectionId) { + connNameLabel->setText("• " + originalConnectionName); LOG(MODULE_UI, "OnConnected signal received for: " + id.toString()) emit RequestWidgetFocus(this); } } +void ConnectionItemWidget::OnDisConnected(const ConnectionId &id) +{ + if (id == connectionId) { + connNameLabel->setText(originalConnectionName); + } +} + +void ConnectionItemWidget::OnConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed) +{ + Q_UNUSED(upSpeed) + Q_UNUSED(downSpeed) + + if (id == connectionId) { + auto [uplink, downlink] = ConnectionManager->GetConnectionUsageAmount(id); + dataLabel->setText(FormatBytes(uplink) + " / " + FormatBytes(downlink)); + } +} + ConnectionItemWidget::~ConnectionItemWidget() { // diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index adea0b7b..79ab34ee 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -22,12 +22,12 @@ class ConnectionItemWidget : public QWidget, private Ui::ConnectionWidget inline bool NameMatched(const QString &arg) { auto searchString = arg.toLower(); - auto headerMatched = ConnectionManager->GetGroup(groupId).displayName.toLower().contains(arg); + auto headerMatched = ConnectionManager->GetDisplayName(groupId).toLower().contains(arg); if (itemType != NODE_ITEM) { return headerMatched; } else { - return headerMatched || ConnectionManager->GetConnection(connectionId).displayName.toLower().contains(searchString); + return headerMatched || ConnectionManager->GetDisplayName(connectionId).toLower().contains(searchString); } } inline const tuple Identifier() const @@ -41,8 +41,11 @@ class ConnectionItemWidget : public QWidget, private Ui::ConnectionWidget signals: void RequestWidgetFocus(const ConnectionItemWidget *me); private slots: + void OnConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed); void OnConnected(const ConnectionId &id); + void OnDisConnected(const ConnectionId &id); private: + QString originalConnectionName; explicit ConnectionItemWidget(QWidget *parent = nullptr); ITEM_TYPE itemType; ConnectionId connectionId; diff --git a/src/ui/widgets/ConnectionItemWidget.ui b/src/ui/widgets/ConnectionItemWidget.ui index f0ee95ff..97d0d5c0 100644 --- a/src/ui/widgets/ConnectionItemWidget.ui +++ b/src/ui/widgets/ConnectionItemWidget.ui @@ -78,7 +78,7 @@ - 0KB + 0KB / 0KB Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter From 82601b03e327b3a0cebb644de1c6e42fa2302b12 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 24 Feb 2020 22:08:11 +0800 Subject: [PATCH 040/332] fix: fixed a TINY MainWindow auto connection state & window visibility issue --- src/ui/w_MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 4d60ca1a..5b36fdc3 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -220,7 +220,7 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr if (!GlobalConfig.autoStartId.isEmpty()) { auto id = ConnectionId(GlobalConfig.autoStartId); ConnectionManager->StartConnection(id); - needShowWindow = ConnectionManager->IsConnected(id); + needShowWindow = !ConnectionManager->IsConnected(id); } else { needShowWindow = true; } From db9ac15f5a477480b33845f179ed39facfe72395 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 24 Feb 2020 23:32:00 +0800 Subject: [PATCH 041/332] add: added optional limit to the GetDisplayName function rvalue --- src/common/QvHelpers.hpp | 9 + src/core/handler/ConnectionHandler.cpp | 8 +- src/core/handler/ConnectionHandler.hpp | 4 +- src/ui/w_MainWindow.ui | 537 ++++++++++++------------ src/ui/widgets/ConnectionInfoWidget.cpp | 6 +- src/ui/widgets/ConnectionInfoWidget.ui | 322 +++++++------- 6 files changed, 461 insertions(+), 425 deletions(-) diff --git a/src/common/QvHelpers.hpp b/src/common/QvHelpers.hpp index ca98043c..c89cce37 100644 --- a/src/common/QvHelpers.hpp +++ b/src/common/QvHelpers.hpp @@ -63,6 +63,15 @@ namespace Qv2ray::common return JsonFromString(json); } + inline QString TruncateString(const QString &str, int limit = -1, const QString &suffix = "...") + { + QString t = str; + t.truncate(limit); + return (limit == -1 || str.length() < limit) + ? str + : (t + suffix); + } + namespace validation { const inline QRegularExpression __regex_ipv4_full(REGEX_IPV4_ADDR "$"); diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index cf0324fa..3033acd5 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -103,14 +103,14 @@ namespace Qv2ray::core::handlers return groups[groupId].connections; } - const QString QvConnectionHandler::GetDisplayName(const ConnectionId &id) const + const QString QvConnectionHandler::GetDisplayName(const ConnectionId &id, int limit) const { - return connections[id].displayName; + return TruncateString(connections[id].displayName, limit); } - const QString QvConnectionHandler::GetDisplayName(const GroupId &id) const + const QString QvConnectionHandler::GetDisplayName(const GroupId &id, int limit) const { - return groups[id].displayName; + return TruncateString(groups[id].displayName, limit); } const GroupId QvConnectionHandler::GetConnectionGroupId(const ConnectionId &id) const diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 593e8d1e..c0cce790 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -21,8 +21,8 @@ namespace Qv2ray::core::handlers const QList Connections(const GroupId &groupId) const; // // Generic Get Options - const QString GetDisplayName(const ConnectionId &id) const; - const QString GetDisplayName(const GroupId &id) const; + const QString GetDisplayName(const ConnectionId &id, int limit = -1) const; + const QString GetDisplayName(const GroupId &id, int limit = -1) const; // // Connectivity Operationss bool IsConnected(const ConnectionId &id) const; diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 4470d7f2..0b13e546 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -32,11 +32,8 @@ 530 - - - 0 - - + + 5 @@ -73,7 +70,268 @@ - + + + + Qt::Horizontal + + + true + + + + + + + Search + + + true + + + + + + + Qt::CustomContextMenu + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::ScrollPerPixel + + + 0 + + + true + + + true + + + true + + + true + + + true + + + + 1 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Import connection + + + Add + + + + 22 + 22 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 480 + 0 + + + + QFrame::NoFrame + + + true + + + + + 0 + 0 + 559 + 743 + + + + + + + + 0 + 0 + + + + + 0 + 205 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + 13 + + + + Speed Graph + + + + + + + Qt::Horizontal + + + + + + + + 0 + 200 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + 13 + + + + Log + + + + + + + Qt::Horizontal + + + + + + + + 0 + 200 + + + + + 9 + + + + QTextEdit::NoWrap + + + + + + + Clear Log + + + + + + + + + 4 @@ -205,273 +463,6 @@ - - - - - 480 - 0 - - - - QFrame::NoFrame - - - true - - - - - 0 - 0 - 526 - 706 - - - - - 2 - - - 0 - - - - - - 0 - 205 - - - - - 16777215 - 205 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - 13 - - - - Speed Graph - - - - - - - Qt::Horizontal - - - - - - - - 0 - 200 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - 13 - - - - Log - - - - - - - Qt::Horizontal - - - - - - - - 0 - 200 - - - - - 9 - - - - QTextEdit::NoWrap - - - - - - - Clear Log - - - - - - - - - - - - 350 - 16777215 - - - - - - - Search - - - true - - - - - - - Qt::CustomContextMenu - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::ExtendedSelection - - - QAbstractItemView::ScrollPerPixel - - - 0 - - - true - - - true - - - true - - - true - - - true - - - - 1 - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - Import connection - - - Add - - - - 22 - 22 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 28456b55..9d46dd19 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -25,8 +25,8 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden connectionId = get<1>(_identifier); if (connectionId.toString() != "null") { - connNameLabel->setText(ConnectionManager->GetDisplayName(connectionId)); - groupLabel->setText(ConnectionManager->GetDisplayName(groupId)); + //connNameLabel->setText(ConnectionManager->GetDisplayName(connectionId)); + groupLabel->setText(ConnectionManager->GetDisplayName(groupId, 175)); protocolLabel->setText(ConnectionManager->GetConnectionProtocolString(connectionId)); auto x = ConnectionManager->GetConnectionInfo(connectionId); addressLabel->setText(get<0>(x)); @@ -41,7 +41,7 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden // connectBtn->setIcon(ConnectionManager->IsConnected(connectionId) ? QICON_R("stop.png") : QICON_R("connect.png")); } else { - connNameLabel->setText(ConnectionManager->GetDisplayName(groupId)); + //connNameLabel->setText(ConnectionManager->GetDisplayName(groupId)); connectBtn->setIcon(QICON_R("connect.png")); groupLabel->setText(tr("N/A")); protocolLabel->setText(tr("N/A")); diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index 6a59563b..e325853b 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -6,22 +6,189 @@ 0 0 - 431 - 205 + 378 + 215 + + + 0 + 0 + + true Form - + 0 - + + + + + + + 14 + + + + Configuration Details + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Delete Connection + + + + + + + :/assets/icons/ui_light/delete.png:/assets/icons/ui_light/delete.png + + + + + + + Edit Connection Config as JSON + + + + + + + :/assets/icons/ui_light/json.png:/assets/icons/ui_light/json.png + + + + + + + Edit Connection + + + + + + + :/assets/icons/ui_light/edit.png:/assets/icons/ui_light/edit.png + + + + + + + Delete Connection + + + + + + + :/assets/icons/ui_light/duplicate.png:/assets/icons/ui_light/duplicate.png + + + + + + + Connect To This Connection + + + + + + + :/assets/icons/ui_light/connect.png:/assets/icons/ui_light/connect.png + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 150 + 150 + + + + + 150 + 150 + + + + QR Code + + + + + + :/assets/icons/qv2ray.ico + + + Qt::AlignCenter + + + + + + + + + 6 + @@ -43,6 +210,9 @@ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + true + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse @@ -145,147 +315,13 @@ - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 150 - 150 - - - - - 150 - 150 - - - - QR Code - - - - - - :/assets/icons/qv2ray.ico - - - Qt::AlignCenter - - - - + + + + Qt::Horizontal + - - - - - - - 14 - - - - Connection Name - - - - - - - Delete Connection - - - - - - - :/assets/icons/ui_light/delete.png:/assets/icons/ui_light/delete.png - - - - - - - Edit Connection Config as JSON - - - - - - - :/assets/icons/ui_light/json.png:/assets/icons/ui_light/json.png - - - - - - - Edit Connection - - - - - - - :/assets/icons/ui_light/edit.png:/assets/icons/ui_light/edit.png - - - - - - - Delete Connection - - - - - - - :/assets/icons/ui_light/duplicate.png:/assets/icons/ui_light/duplicate.png - - - - - - - Connect To This Connection - - - - - - - :/assets/icons/ui_light/connect.png:/assets/icons/ui_light/connect.png - - - - - From 315c38941e4956b34f8292b5040e9ba0e3c278f9 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Tue, 25 Feb 2020 11:32:52 +0800 Subject: [PATCH 042/332] using jom for windows --- .github/workflows/build-qv2ray.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray.yml b/.github/workflows/build-qv2ray.yml index e0658ad3..1566b544 100644 --- a/.github/workflows/build-qv2ray.yml +++ b/.github/workflows/build-qv2ray.yml @@ -61,6 +61,10 @@ jobs: - name: macOS - Install Packages if: matrix.platform == 'macos-latest' run: brew install protobuf + + - name: Windows - Install Packages + if: matrix.platform == 'windows-latest' + run: choco install jom -y # -------------------------------------------------------- - name: Cross-platform - Download libraries shell: bash @@ -93,7 +97,7 @@ jobs: if: matrix.platform == 'windows-latest' run: | cd build - nmake release + jom # -------------------------------------------------------- Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage if: matrix.platform == 'ubuntu-16.04' From 6db0dd5ba0b595f43333ab52bec0b19dc8259b20 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 25 Feb 2020 16:31:47 +0800 Subject: [PATCH 043/332] add: added auto-connect settings support --- makespec/BUILDVERSION | 2 +- src/common/HTTPRequestHelper.cpp | 17 +++++--- src/common/HTTPRequestHelper.hpp | 2 +- src/core/CoreSafeTypes.hpp | 3 +- src/core/handler/ConnectionHandler.cpp | 32 ++++++++++++--- src/core/handler/ConnectionHandler.hpp | 10 ++--- src/ui/w_PreferencesWindow.cpp | 56 +++++++++++--------------- 7 files changed, 70 insertions(+), 52 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 46f8bb17..d82978de 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3896 +3898 diff --git a/src/common/HTTPRequestHelper.cpp b/src/common/HTTPRequestHelper.cpp index 68fd06f9..467a2a82 100644 --- a/src/common/HTTPRequestHelper.cpp +++ b/src/common/HTTPRequestHelper.cpp @@ -40,14 +40,15 @@ namespace Qv2ray::common if (useProxy) { auto proxy = QNetworkProxyFactory::systemProxyForQuery(); accessManager.setProxy(proxy.first()); + LOG(MODULE_NETWORK, "Sync get is using system proxy settings") } else { accessManager.setProxy(QNetworkProxy(QNetworkProxy::ProxyType::NoProxy)); } - LOG(MODULE_NETWORK, "Sync get is using system proxy settings") request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); + request.setHeader(QNetworkRequest::KnownHeaders::UserAgentHeader, "Mozilla/5.0 (rv:71.0) Gecko/20100101 Firefox/71.0"); reply = accessManager.get(request); - connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished); + connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished_p); // QEventLoop loop; connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); @@ -62,7 +63,7 @@ namespace Qv2ray::common this->setUrl(url); // request.setRawHeader("Content-Type", "application/x-www-form-urlencoded"); reply = accessManager.get(request); - connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished); + connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished_p); connect(reply, &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead); } @@ -102,9 +103,15 @@ namespace Qv2ray::common // connect(reply, &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead); // } - void QvHttpRequestHelper::onRequestFinished() + void QvHttpRequestHelper::onRequestFinished_p() { - LOG(MODULE_NETWORK, "Network request errcode: " + QSTRN(reply->error())) + if (reply->error() != QNetworkReply::NoError) { + QString error = QMetaEnum::fromType().key(reply->error()); + LOG(MODULE_NETWORK, "Network request error string: " + error) + QByteArray empty; + emit httpRequestFinished(empty); + } + emit httpRequestFinished(this->data); } diff --git a/src/common/HTTPRequestHelper.hpp b/src/common/HTTPRequestHelper.hpp index f67221dc..73c08d3b 100644 --- a/src/common/HTTPRequestHelper.hpp +++ b/src/common/HTTPRequestHelper.hpp @@ -47,7 +47,7 @@ namespace Qv2ray::common void httpRequestFinished(QByteArray &data); public slots: - void onRequestFinished(); + void onRequestFinished_p(); private slots: void onReadyRead(); private: diff --git a/src/core/CoreSafeTypes.hpp b/src/core/CoreSafeTypes.hpp index 2bdb58ce..95091aec 100644 --- a/src/core/CoreSafeTypes.hpp +++ b/src/core/CoreSafeTypes.hpp @@ -12,7 +12,8 @@ namespace Qv2ray::core class IDType { public: - IDType(const QString &id): m_id(id) {} + //explicit IDType(): m_id("null") {} + explicit IDType(const QString &id): m_id(id) {} friend bool operator==(const IDType &lhs, const IDType &rhs) { return lhs.m_id == rhs.m_id; diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index 3033acd5..3748add4 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -11,24 +11,24 @@ namespace Qv2ray::core::handlers // Do we need to check how many of them are loaded? for (auto i = 0; i < GlobalConfig.connections.count(); i++) { - connections[GlobalConfig.connections.keys()[i]] = GlobalConfig.connections.values()[i]; + connections[ConnectionId(GlobalConfig.connections.keys()[i])] = GlobalConfig.connections.values()[i]; } for (auto key : GlobalConfig.subscriptions.keys()) { auto val = GlobalConfig.subscriptions[key]; - groups[key] = val; + groups[GroupId(key)] = val; for (auto conn : val.connections) { - connections[conn].groupId = key; + connections[ConnectionId(conn)].groupId = GroupId(key); } } for (auto key : GlobalConfig.groups.keys()) { auto val = GlobalConfig.groups[key]; - groups[key] = val; + groups[GroupId(key)] = val; for (auto conn : val.connections) { - connections[conn].groupId = key; + connections[ConnectionId(conn)].groupId = GroupId(key); } } @@ -113,6 +113,28 @@ namespace Qv2ray::core::handlers return TruncateString(groups[id].displayName, limit); } + const ConnectionId QvConnectionHandler::GetConnectionIdByDisplayName(const QString &displayName) const + { + for (auto conn : connections.keys()) { + if (connections[conn].displayName == displayName) { + return conn; + } + } + + return ConnectionId("null"); + } + + const GroupId QvConnectionHandler::GetGroupIdByDisplayName(const QString &displayName) const + { + for (auto group : groups.keys()) { + if (groups[group].displayName == displayName) { + return group; + } + } + + return GroupId("null"); + } + const GroupId QvConnectionHandler::GetConnectionGroupId(const ConnectionId &id) const { if (!connections.contains(id)) { diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index c0cce790..5d9ddc57 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -21,8 +21,10 @@ namespace Qv2ray::core::handlers const QList Connections(const GroupId &groupId) const; // // Generic Get Options - const QString GetDisplayName(const ConnectionId &id, int limit = -1) const; const QString GetDisplayName(const GroupId &id, int limit = -1) const; + const QString GetDisplayName(const ConnectionId &id, int limit = -1) const; + const GroupId GetGroupIdByDisplayName(const QString &displayName) const; + const ConnectionId GetConnectionIdByDisplayName(const QString &displayName) const; // // Connectivity Operationss bool IsConnected(const ConnectionId &id) const; @@ -36,7 +38,7 @@ namespace Qv2ray::core::handlers const optional DeleteConnection(const ConnectionId &id); const optional UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); const optional RenameConnection(const ConnectionId &id, const QString &newName); - const optional DuplicateConnection(const ConnectionId &id); + const ConnectionId DuplicateConnection(const ConnectionId &id); const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); // // Get Conncetion Property @@ -50,16 +52,12 @@ namespace Qv2ray::core::handlers const optional TestLatency(const ConnectionId &id); // // Group Operations - //const GroupMetaObject GetGroup(const GroupId &id) const; const optional DeleteGroup(const GroupId &id); const optional DuplicateGroup(const GroupId &id); const GroupId &CreateGroup(const QString displayName, bool isSubscription); const optional RenameGroup(const GroupId &id, const QString &newName); // // Subscriptions - const GroupId &CreateSubscription(const QString &displayName, const QString &address); - const optional RenameSubscription(const GroupId &id, const QString &newName); - const optional DeleteSubscription(const GroupId &id); const optional UpdateSubscription(const GroupId &id); const optional UpdateSubscriptionASync(const GroupId &id); diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index 8e3b935b..3345d5f8 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -10,9 +10,10 @@ #include "core/config/ConfigBackend.hpp" #include "core/connection/ConnectionIO.hpp" #include "core/kernel/KernelInteractions.hpp" +#include "core/handler/ConnectionHandler.hpp" #include "components/plugins/toolbar/QvToolbar.hpp" #include "components/autolaunch/QvAutoLaunch.hpp" -#include +#include "common/QvTranslator.hpp" using Qv2ray::common::validation::IsValidIPAddress; @@ -149,26 +150,20 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), CurrentBarPageId = 0; // // Empty for global config. - //auto autoSub = CurrentConfig.autoStartConfig.subscriptionName; - //auto autoCon = CurrentConfig.autoStartConfig.connectionName; - //autoStartConnCombo->addItem(""); - QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); + auto autoStartConnId = ConnectionId(CurrentConfig.autoStartId); + auto autoStartGroupId = ConnectionManager->GetConnectionGroupId(autoStartConnId); - // TODO: Now use grouping, subscriptions are the special type of group - //autoStartConnCombo->setCurrentText(autoCon);for (auto item : CurrentConfig.subscriptions.keys()) { - // autoStartSubsCombo->addItem(item); - //} - // - //autoStartSubsCombo->setCurrentText(autoSub); - // - //if (CurrentConfig.autoStartConfig.subscriptionName.isEmpty()) { - // autoStartConnCombo->addItems(CurrentConfig.configs); - //} else { - // auto list = GetSubscriptionConnection(autoSub); - // autoStartConnCombo->addItems(list.keys()); - //} - // - // + for (auto group : ConnectionManager->AllGroups()) { + autoStartSubsCombo->addItem(ConnectionManager->GetDisplayName(group)); + } + + autoStartSubsCombo->setCurrentText(ConnectionManager->GetDisplayName(autoStartGroupId)); + + for (auto conn : ConnectionManager->Connections(autoStartGroupId)) { + autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(conn)); + } + + autoStartConnCombo->setCurrentText(ConnectionManager->GetDisplayName(autoStartConnId)); // FP Settings if (CurrentConfig.connectionConfig.forwardProxyConfig.type.trimmed().isEmpty()) { @@ -941,24 +936,19 @@ void PreferencesWindow::on_pacProxyTxt_textEdited(const QString &arg1) void PreferencesWindow::on_autoStartSubsCombo_currentIndexChanged(const QString &arg1) { LOADINGCHECK - QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - //CurrentConfig.autoStartConfig.subscriptionName = arg1; - //autoStartConnCombo->clear(); - // - //if (arg1.isEmpty()) { - // autoStartConnCombo->addItem(""); - // autoStartConnCombo->addItems(CurrentConfig.configs); - //} else { - // auto list = GetSubscriptionConnection(arg1); - // autoStartConnCombo->addItems(list.keys()); - //} + auto groupId = ConnectionManager->GetGroupIdByDisplayName(arg1); + auto list = ConnectionManager->Connections(groupId); + autoStartConnCombo->clear(); + + for (auto id : list) { + autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(id)); + } } void PreferencesWindow::on_autoStartConnCombo_currentIndexChanged(const QString &arg1) { LOADINGCHECK - QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - //CurrentConfig.autoStartConfig.connectionName = arg1; + CurrentConfig.autoStartId = ConnectionManager->GetConnectionIdByDisplayName(arg1).toString(); } void PreferencesWindow::on_startWithLoginCB_stateChanged(int arg1) From 0bea5d0f156451762424a26f2e2ce80b1cc10c63 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 25 Feb 2020 21:47:46 +0800 Subject: [PATCH 044/332] add: added tcping latency support --- Qv2ray.pro | 3 +- makespec/BUILDVERSION | 2 +- src/base/Qv2rayBase.hpp | 2 +- src/base/Qv2rayLog.hpp | 2 +- src/components/tcping/QvTCPing.hpp | 33 -- src/core/CoreSafeTypes.hpp | 14 +- src/core/handler/ConnectionHandler.cpp | 57 +++- src/core/handler/ConnectionHandler.hpp | 47 +-- src/core/handler/V2rayInstanceHandler.cpp | 14 +- src/core/kernel/APIBackend.cpp | 2 +- src/core/kernel/APIBackend.hpp | 2 +- src/core/kernel/KernelInteractions.cpp | 6 +- src/core/kernel/KernelInteractions.hpp | 6 +- src/{components => core}/tcping/QvTCPing.cpp | 53 ++-- src/core/tcping/QvTCPing.hpp | 31 ++ src/ui/models/ConnectionTreeModel.cpp | 0 src/ui/models/ConnectionTreeModel.hpp | 0 src/ui/w_MainWindow.cpp | 299 +++++-------------- src/ui/w_MainWindow.hpp | 13 +- src/ui/w_MainWindow.ui | 10 +- src/ui/w_MainWindow_extra.cpp | 35 --- src/ui/widgets/ConnectionInfoWidget.cpp | 64 +++- src/ui/widgets/ConnectionInfoWidget.hpp | 8 +- src/ui/widgets/ConnectionInfoWidget.ui | 11 + src/ui/widgets/ConnectionItemWidget.cpp | 36 ++- src/ui/widgets/ConnectionItemWidget.hpp | 4 +- 26 files changed, 366 insertions(+), 388 deletions(-) delete mode 100644 src/components/tcping/QvTCPing.hpp rename src/{components => core}/tcping/QvTCPing.cpp (73%) create mode 100644 src/core/tcping/QvTCPing.hpp delete mode 100644 src/ui/models/ConnectionTreeModel.cpp delete mode 100644 src/ui/models/ConnectionTreeModel.hpp diff --git a/Qv2ray.pro b/Qv2ray.pro index b3494c0f..435562ca 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -75,7 +75,6 @@ Qv2rayAddSource(components, plugins/toolbar, QvToolbar, cpp, hpp) Qv2rayAddSource(components, plugins/toolbar, QvToolbar_linux, cpp) Qv2rayAddSource(components, plugins/toolbar, QvToolbar_win, cpp) Qv2rayAddSource(components, proxy, QvProxyConfigurator, cpp, hpp) -Qv2rayAddSource(components, tcping, QvTCPing, cpp, hpp) Qv2rayAddSource(components, speedchart, speedwidget, cpp, hpp) Qv2rayAddSource(components, speedchart, speedplotview, cpp, hpp) Qv2rayAddSource(components, geosite, QvGeositeReader, cpp, hpp) @@ -86,6 +85,7 @@ Qv2rayAddSource(core, connection, Generation, cpp, hpp) Qv2rayAddSource(core, connection, Serialization, cpp, hpp) Qv2rayAddSource(core, kernel, KernelInteractions, cpp, hpp) Qv2rayAddSource(core, kernel, APIBackend, cpp, hpp) +Qv2rayAddSource(core, tcping, QvTCPing, cpp, hpp) # Connection Handlers Qv2rayAddSource(core, handler, ConnectionHandler, cpp, hpp) Qv2rayAddSource(core, handler, V2rayInstanceHandler, cpp) @@ -101,7 +101,6 @@ Qv2rayAddSource(ui, models, InboundNodeModel, cpp, hpp) Qv2rayAddSource(ui, models, OutboundNodeModel, cpp, hpp) Qv2rayAddSource(ui, models, RuleNodeModel, cpp, hpp) Qv2rayAddSource(ui, models, NodeModelsBase, hpp) -Qv2rayAddSource(ui, models, ConnectionTreeModel, cpp, hpp) Qv2rayAddSource(ui, messaging, QvMessageBus, cpp, hpp) Qv2rayAddSource(ui, _, w_ExportConfig, cpp, hpp, ui) Qv2rayAddSource(ui, _, w_ImportConfig, cpp, hpp, ui) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index d82978de..2d2c4aa9 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3898 +3956 diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index 7d69798f..0180a0e4 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -101,7 +101,7 @@ using namespace Qv2ray::base::objects::transfer; obj->setPalette(_temp); #define BLACK(obj) \ - obj->setPalette(this->palette()); + obj->setPalette(QWidget::palette()); #define QV2RAY_UI_RESOURCES_ROOT ((GlobalConfig.uiConfig.useDarkTheme) ? QStringLiteral(":/assets/icons/ui_dark/") : QStringLiteral(":/assets/icons/ui_light/")) #define QICON_R(file) QIcon(QV2RAY_UI_RESOURCES_ROOT + file) diff --git a/src/base/Qv2rayLog.hpp b/src/base/Qv2rayLog.hpp index cc6c0a4e..a06c20e5 100644 --- a/src/base/Qv2rayLog.hpp +++ b/src/base/Qv2rayLog.hpp @@ -55,4 +55,4 @@ const inline QString MODULE_PROXY = "COMPONENT-PROXY" ; const inline QString MODULE_UPDATE = "COMPONENT-UPDATE" ; const inline QString MODULE_PLUGIN = "COMPONENT-PLUGIN" ; // ================================================================ -const inline QString MODULE_CORE_HANDLER = "libQv2ray: ConnectionHandler"; +const inline QString MODULE_CORE_HANDLER = "QV2RAY-CORE"; diff --git a/src/components/tcping/QvTCPing.hpp b/src/components/tcping/QvTCPing.hpp deleted file mode 100644 index d3fe6ffd..00000000 --- a/src/components/tcping/QvTCPing.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include "base/Qv2rayBase.hpp" -#include - -namespace Qv2ray::components::tcping -{ - struct QvTCPingData { - ConnectionObject_Config connectionIdentifier; - QString hostName; - int port; - QString errorMessage; - int total, succeed, failed; - double min = numeric_limits::max(), max = 0.0, avg = 0.0; - }; - - class QvTCPingModel : public QObject - { - Q_OBJECT - - public: - explicit QvTCPingModel(int defaultCount = 5, QObject *parent = nullptr); - void StartPing(const ConnectionObject_Config &connectionName, const QString &hostName, int port); - void StopAllPing(); - signals: - void PingFinished(QvTCPingData data); - private: - static QvTCPingData startTestLatency(QvTCPingData data, const int count); - int count; - QQueue*> pingWorkingThreads; - }; -} - -using namespace Qv2ray::components::tcping; diff --git a/src/core/CoreSafeTypes.hpp b/src/core/CoreSafeTypes.hpp index 95091aec..824d1ca9 100644 --- a/src/core/CoreSafeTypes.hpp +++ b/src/core/CoreSafeTypes.hpp @@ -12,12 +12,15 @@ namespace Qv2ray::core class IDType { public: - //explicit IDType(): m_id("null") {} explicit IDType(const QString &id): m_id(id) {} friend bool operator==(const IDType &lhs, const IDType &rhs) { return lhs.m_id == rhs.m_id; } + friend bool operator!=(const IDType &lhs, const IDType &rhs) + { + return lhs.toString() != rhs.toString(); + } const QString &toString() const { return m_id; @@ -36,8 +39,11 @@ namespace Qv2ray::core class __QvConnection; typedef IDType<__QvGroup> GroupId; typedef IDType<__QvConnection> ConnectionId; - template + inline const static ConnectionId NullConnectionId = ConnectionId("null"); + inline const static GroupId NullGroupId = GroupId("null"); + + template QList StringsToIdList(const QList &strings) { QList list; @@ -67,8 +73,8 @@ namespace Qv2ray::core // /// Metadata object representing a connection. struct ConnectionMetaObject : ConnectionObject_Config { - GroupId groupId; - ConnectionMetaObject(): ConnectionObject_Config(), groupId("null") { } + GroupId groupId = NullGroupId; + ConnectionMetaObject(): ConnectionObject_Config() { } // Suger for down casting. ConnectionMetaObject(const ConnectionObject_Config &base) : ConnectionMetaObject() { diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index 3748add4..1acf03a5 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -5,7 +5,7 @@ namespace Qv2ray::core::handlers { - QvConnectionHandler::QvConnectionHandler() : currentConnectionId("null") + QvConnectionHandler::QvConnectionHandler() { DEBUG(MODULE_CORE_HANDLER, "ConnectionHandler Constructor.") @@ -35,8 +35,16 @@ namespace Qv2ray::core::handlers vCoreInstance = new V2rayKernelInstance(); connect(vCoreInstance, &V2rayKernelInstance::OnProcessErrored, this, &QvConnectionHandler::OnVCoreCrashed); connect(vCoreInstance, &V2rayKernelInstance::OnNewStatsDataArrived, this, &QvConnectionHandler::OnStatsDataArrived); + // Directly connected to a signal. connect(vCoreInstance, &V2rayKernelInstance::OnProcessOutputReadyRead, this, &QvConnectionHandler::OnVCoreLogAvailable); + // + // + tcpingHelper = new QvTCPingHelper(5, this); + connect(tcpingHelper, &QvTCPingHelper::OnLatencyTestCompleted, this, &QvConnectionHandler::OnLatencyDataArrived); + // saveTimerId = startTimer(10 * 1000); + pingAllTimerId = startTimer(5 * 60 * 1000); + pingConnectionTimerId = startTimer(60 * 1000); } void QvConnectionHandler::CHSaveConnectionData_p() @@ -72,9 +80,35 @@ namespace Qv2ray::core::handlers { if (event->timerId() == saveTimerId) { CHSaveConnectionData_p(); + } else if (event->timerId() == pingAllTimerId) { + StartLatencyTest(); + } else if (event->timerId() == pingConnectionTimerId) { + if (currentConnectionId != NullConnectionId) { + StartLatencyTest(currentConnectionId); + } } } + void QvConnectionHandler::StartLatencyTest() + { + for (auto connection : connections.keys()) { + StartLatencyTest(connection); + } + } + + void QvConnectionHandler::StartLatencyTest(const GroupId &id) + { + for (auto connection : groups[id].connections) { + StartLatencyTest(connection); + } + } + + void QvConnectionHandler::StartLatencyTest(const ConnectionId &id) + { + emit OnLatencyTestStarted(id); + tcpingHelper->TestLatency(id); + } + const QList QvConnectionHandler::Connections() const { return connections.keys(); @@ -121,7 +155,7 @@ namespace Qv2ray::core::handlers } } - return ConnectionId("null"); + return NullConnectionId; } const GroupId QvConnectionHandler::GetGroupIdByDisplayName(const QString &displayName) const @@ -132,7 +166,7 @@ namespace Qv2ray::core::handlers } } - return GroupId("null"); + return NullGroupId; } const GroupId QvConnectionHandler::GetConnectionGroupId(const ConnectionId &id) const @@ -144,7 +178,7 @@ namespace Qv2ray::core::handlers return connections[id].groupId; } - int64_t QvConnectionHandler::GetConnectionLatency(const ConnectionId &id) const + double QvConnectionHandler::GetConnectionLatency(const ConnectionId &id) const { if (!connections.contains(id)) { LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); @@ -166,7 +200,10 @@ namespace Qv2ray::core::handlers return tr("No connection selected!") + NEWLINE + tr("Please select a config from the list."); } - StopConnection(); + if (currentConnectionId != NullConnectionId) { + StopConnection(); + } + CONFIGROOT root = CHGetConnectionRoot_p(connections[identifier].groupId, identifier); return CHStartConnection_p(identifier, root); } @@ -299,4 +336,14 @@ namespace Qv2ray::core::handlers return false; } } + + void QvConnectionHandler::OnLatencyDataArrived(const QvTCPingResultObject &result) + { + if (connections.contains(result.connectionId)) { + connections[result.connectionId].latency = result.avg; + emit OnLatencyTestFinished(result.connectionId, result.avg); + } else { + LOG(MODULE_CORE_HANDLER, "Received a latecy result with non-exist connection id.") + } + } } diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 5d9ddc57..250663a7 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -2,6 +2,7 @@ #include "base/Qv2rayBase.hpp" #include "core/kernel/KernelInteractions.hpp" +#include "core/tcping/QvTCPing.hpp" #include "core/CoreSafeTypes.hpp" #include "core/connection/ConnectionIO.hpp" @@ -33,7 +34,7 @@ namespace Qv2ray::core::handlers // // Connection Operations. const GroupId GetConnectionGroupId(const ConnectionId &id) const; - int64_t GetConnectionLatency(const ConnectionId &id) const; + double GetConnectionLatency(const ConnectionId &id) const; const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); const optional DeleteConnection(const ConnectionId &id); const optional UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); @@ -47,9 +48,9 @@ namespace Qv2ray::core::handlers const tuple GetConnectionUsageAmount(const ConnectionId &id) const; // // Misc Connection Operations - const optional TestLatency(); - const optional TestLatency(const GroupId &id); - const optional TestLatency(const ConnectionId &id); + void StartLatencyTest(); + void StartLatencyTest(const GroupId &id); + void StartLatencyTest(const ConnectionId &id); // // Group Operations const optional DeleteGroup(const GroupId &id); @@ -62,19 +63,21 @@ namespace Qv2ray::core::handlers const optional UpdateSubscriptionASync(const GroupId &id); signals: - // + void OnCrashed(); void OnConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id); void OnVCoreLogAvailable(const ConnectionId &id, const QString &log); - void OnStatsAvailable(const ConnectionId &id, uint64_t totalUpload, uint64_t totalDownload); + void OnStatsAvailable(const ConnectionId &id, + const quint64 uploadSpeed, const quint64 downloadSpeed, + const quint64 totalUpload, const quint64 totalDownload); // void OnConnectionCreated(const ConnectionId &id, const QString &displayName); void OnConnectionRenamed(const ConnectionId &id, const QString &originalName, const QString &newName); void OnConnectionChanged(const ConnectionId &id); void OnConnectionGroupChanged(const ConnectionId &id, const QString &originalGroup, const QString &newGroup); // - void OnConnectionLatencyTestStart(const ConnectionId &id); - void OnConnectionLatencyTestFinished(const ConnectionId &id); + void OnLatencyTestStarted(const ConnectionId &id); + void OnLatencyTestFinished(const ConnectionId &id, const uint average); // void OnGroupCreated(const GroupId &id, const QString &displayName); void OnGroupRenamed(const GroupId &id, const QString &oldName, const QString &newName); @@ -85,8 +88,9 @@ namespace Qv2ray::core::handlers void OnSubscriptionUpdateFinished(const GroupId &id); private slots: - void OnStatsDataArrived(const ConnectionId &id, const QString tag, const quint64 uploadSpeed, const quint64 downloadSpeed); + void OnStatsDataArrived(const ConnectionId &id, const quint64 uploadSpeed, const quint64 downloadSpeed); void OnVCoreCrashed(const ConnectionId &id); + void OnLatencyDataArrived(const QvTCPingResultObject &data); protected: void timerEvent(QTimerEvent *event) override; @@ -100,21 +104,24 @@ namespace Qv2ray::core::handlers const CONFIGROOT CHGetConnectionRoot_p(const ConnectionId &id) const; const CONFIGROOT CHGetConnectionRoot_p(const GroupId &group, const ConnectionId &id) const; bool CHSaveConnectionConfig_p(CONFIGROOT obj, const ConnectionId &id, bool override); - // - // - // We only support one cuncurrent connection currently. -#ifdef QV2RAY_MULTIPlE_ONNECTION - QHash kernelInstances; -#else - ConnectionId currentConnectionId; - V2rayKernelInstance *vCoreInstance = nullptr; -#endif + + private: int saveTimerId; - int apiTimerId; + int pingAllTimerId; + int pingConnectionTimerId; QHash groups; QHash connections; - // QHash connectionRootCache; + + private: + QvTCPingHelper *tcpingHelper; + // We only support one cuncurrent connection currently. +#ifdef QV2RAY_MULTIPlE_ONNECTION + QHash kernelInstances; +#else + ConnectionId currentConnectionId = NullConnectionId; + V2rayKernelInstance *vCoreInstance = nullptr; +#endif }; inline ::Qv2ray::core::handlers::QvConnectionHandler *ConnectionManager = nullptr; diff --git a/src/core/handler/V2rayInstanceHandler.cpp b/src/core/handler/V2rayInstanceHandler.cpp index 5087704a..183ecfb7 100644 --- a/src/core/handler/V2rayInstanceHandler.cpp +++ b/src/core/handler/V2rayInstanceHandler.cpp @@ -3,15 +3,14 @@ optional QvConnectionHandler::CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root) { - auto &connectionMeta = connections[id]; - auto fullConfig = GenerateRuntimeConfig(root); + connections[id].lastConnected = system_clock::to_time_t(system_clock::now()); // + auto fullConfig = GenerateRuntimeConfig(root); auto result = vCoreInstance->StartConnection(id, fullConfig); if (!result.has_value()) { currentConnectionId = id; emit OnConnected(currentConnectionId); - connectionMeta.lastConnected = system_clock::to_time_t(system_clock::now()); } return result; @@ -23,23 +22,24 @@ void QvConnectionHandler::CHStopConnection_p() vCoreInstance->StopConnection(); // Copy ConnectionId id = currentConnectionId; - currentConnectionId = ConnectionId("null"); + currentConnectionId = NullConnectionId; emit OnDisConnected(id); } else { LOG(MODULE_CORE_HANDLER, "VCore is not started, not disconnecting") } } -void QvConnectionHandler::OnStatsDataArrived(const ConnectionId &id, const QString tag, const quint64 uploadSpeed, const quint64 downloadSpeed) +void QvConnectionHandler::OnStatsDataArrived(const ConnectionId &id, const quint64 uploadSpeed, const quint64 downloadSpeed) { - Q_UNUSED(tag) - emit OnStatsAvailable(id, uploadSpeed, downloadSpeed); connections[id].upLinkData += uploadSpeed; connections[id].downLinkData += downloadSpeed; + emit OnStatsAvailable(id, uploadSpeed, downloadSpeed, connections[id].upLinkData, connections[id].downLinkData); } void QvConnectionHandler::OnVCoreCrashed(const ConnectionId &id) { LOG(MODULE_CORE_HANDLER, "V2ray core crashed!") + currentConnectionId = NullConnectionId; emit OnDisConnected(id); + emit OnCrashed(); } diff --git a/src/core/kernel/APIBackend.cpp b/src/core/kernel/APIBackend.cpp index d1a067fc..bd40f437 100644 --- a/src/core/kernel/APIBackend.cpp +++ b/src/core/kernel/APIBackend.cpp @@ -97,7 +97,7 @@ namespace Qv2ray::core::kernel if (running) { apiFailedCounter = 0; - emit OnDataReady("", value_up, value_down); + emit OnDataReady(value_up, value_down); } #else diff --git a/src/core/kernel/APIBackend.hpp b/src/core/kernel/APIBackend.hpp index d314ae7e..a6147fc6 100644 --- a/src/core/kernel/APIBackend.hpp +++ b/src/core/kernel/APIBackend.hpp @@ -25,7 +25,7 @@ namespace Qv2ray::core::kernel void process(); signals: - void OnDataReady(const QString &tag, const quint64 _totalUp, const quint64 _totalDown); + void OnDataReady(const quint64 _totalUp, const quint64 _totalDown); void error(const QString &err); private: diff --git a/src/core/kernel/KernelInteractions.cpp b/src/core/kernel/KernelInteractions.cpp index b00c3861..5725d33b 100644 --- a/src/core/kernel/KernelInteractions.cpp +++ b/src/core/kernel/KernelInteractions.cpp @@ -117,7 +117,7 @@ namespace Qv2ray::core::kernel } } - V2rayKernelInstance::V2rayKernelInstance() : id("null") + V2rayKernelInstance::V2rayKernelInstance() { vProcess = new QProcess(); connect(vProcess, &QProcess::readyReadStandardOutput, this, [&]() { @@ -223,8 +223,8 @@ namespace Qv2ray::core::kernel delete vProcess; } - void V2rayKernelInstance::onAPIDataReady(const QString &tag, const quint64 _totalUp, const quint64 _totalDown) + void V2rayKernelInstance::onAPIDataReady(const quint64 _totalUp, const quint64 _totalDown) { - emit OnNewStatsDataArrived(id, tag, _totalUp, _totalDown); + emit OnNewStatsDataArrived(id, _totalUp, _totalDown); } } diff --git a/src/core/kernel/KernelInteractions.hpp b/src/core/kernel/KernelInteractions.hpp index de9358cc..dc291a61 100644 --- a/src/core/kernel/KernelInteractions.hpp +++ b/src/core/kernel/KernelInteractions.hpp @@ -29,17 +29,17 @@ namespace Qv2ray::core::kernel signals: void OnProcessErrored(const ConnectionId &id); void OnProcessOutputReadyRead(const ConnectionId &id, const QString &output); - void OnNewStatsDataArrived(const ConnectionId &id, const QString &tag, const quint64 _totalUp, const quint64 _totalDown); + void OnNewStatsDataArrived(const ConnectionId &id, const quint64 _totalUp, const quint64 _totalDown); public slots: - void onAPIDataReady(const QString &tag, const quint64 _totalUp, const quint64 _totalDown); + void onAPIDataReady(const quint64 _totalUp, const quint64 _totalDown); private: APIWorker *apiWorker; QProcess *vProcess; bool apiEnabled; // - ConnectionId id; + ConnectionId id = NullConnectionId; }; } diff --git a/src/components/tcping/QvTCPing.cpp b/src/core/tcping/QvTCPing.cpp similarity index 73% rename from src/components/tcping/QvTCPing.cpp rename to src/core/tcping/QvTCPing.cpp index 41a5711b..67964d77 100644 --- a/src/components/tcping/QvTCPing.cpp +++ b/src/core/tcping/QvTCPing.cpp @@ -8,18 +8,20 @@ #include #endif #include "QvTCPing.hpp" +#include "core/handler/ConnectionHandler.hpp" #include "QtConcurrent/QtConcurrent" -namespace Qv2ray::components::tcping +namespace Qv2ray::core::tcping { static int resolveHost(const std::string &host, int portnr, struct addrinfo **res); static int testLatency(struct addrinfo *addr, std::chrono::system_clock::time_point *start, std::chrono::system_clock::time_point *end); // - QvTCPingModel::QvTCPingModel(int defaultCount, QObject *parent) : QObject(parent) + QvTCPingHelper::QvTCPingHelper(const int defaultCount, QObject *parent) : QObject(parent) { count = defaultCount; } - void QvTCPingModel::StopAllPing() + + void QvTCPingHelper::StopAllLatenceTest() { while (!pingWorkingThreads.isEmpty()) { auto worker = pingWorkingThreads.dequeue(); @@ -27,38 +29,37 @@ namespace Qv2ray::components::tcping worker->cancel(); } } - void QvTCPingModel::StartPing(const ConnectionObject_Config &connectionName, const QString &hostName, int port) + void QvTCPingHelper::TestLatency(const ConnectionId &id) { - QvTCPingData data; - data.hostName = hostName; - data.port = port; - data.connectionIdentifier = connectionName; - auto watcher = new QFutureWatcher(this); - DEBUG(MODULE_NETWORK, "Start Ping: " + hostName + ":" + QSTRN(port)) - watcher->setFuture(QtConcurrent::run(&QvTCPingModel::startTestLatency, data, count)); + auto watcher = new QFutureWatcher(this); + watcher->setFuture(QtConcurrent::run(&QvTCPingHelper::TestLatency_p, id, count)); pingWorkingThreads.enqueue(watcher); - connect(watcher, &QFutureWatcher::finished, this, [this, watcher]() { - this->pingWorkingThreads.removeOne(watcher); + // + connect(watcher, &QFutureWatcher::finished, this, [ = ]() { auto result = watcher->result(); - DEBUG(MODULE_NETWORK, "Ping finished: " + result.hostName + ":" + QSTRN(result.port) + " --> " + QSTRN(result.avg) + "ms") + this->pingWorkingThreads.removeOne(watcher); if (!result.errorMessage.isEmpty()) { LOG(MODULE_NETWORK, "Ping --> " + result.errorMessage) } - emit this->PingFinished(result); + emit this->OnLatencyTestCompleted(result); }); } - QvTCPingData QvTCPingModel::startTestLatency(QvTCPingData data, const int count) + QvTCPingResultObject QvTCPingHelper::TestLatency_p(const ConnectionId &id, const int count) { - if (isExiting) return QvTCPingData(); + QvTCPingResultObject data; + data.connectionId = id; + if (isExiting) return data; + + auto [host, port] = ConnectionManager->GetConnectionInfo(id); double successCount = 0, errorCount = 0; addrinfo *resolved; int errcode; - if ((errcode = resolveHost(data.hostName.toStdString(), data.port, &resolved)) != 0) { + if ((errcode = resolveHost(host.toStdString(), port, &resolved)) != 0) { #ifdef _WIN32 data.errorMessage = QString::fromStdWString(gai_strerror(errcode)); #else @@ -71,14 +72,14 @@ namespace Qv2ray::components::tcping int currentCount = 0; while (currentCount < count) { - if (isExiting) return QvTCPingData(); + if (isExiting) return QvTCPingResultObject(); - std::chrono::system_clock::time_point start; - std::chrono::system_clock::time_point end; + system_clock::time_point start; + system_clock::time_point end; if ((errcode = testLatency(resolved, &start, &end)) != 0) { if (errcode != -EADDRNOTAVAIL) { - LOG(MODULE_NETWORK, "Error connecting to host: " + data.hostName + ":" + QSTRN(data.port) + " " + strerror(-errcode)) + //LOG(MODULE_NETWORK, "Error connecting to host: " + data.hostName + ":" + QSTRN(data.port) + " " + strerror(-errcode)) errorCount++; } else { if (noAddress) { @@ -93,13 +94,13 @@ namespace Qv2ray::components::tcping noAddress = false; successCount++; auto milliseconds = std::chrono::duration_cast(end - start); - double ms = milliseconds.count(); - ms = ms < 0 ? 0 : ms; + uint ms = milliseconds.count(); data.avg += ms; - data.min = min(data.min, ms); - data.max = max(data.max, ms); + data.worst = min(data.worst, ms); + data.best = max(data.best, ms); if (ms > 1000) { + LOG(MODULE_NETWORK, "Stop the test on the first long connect()") break; /* Stop the test on the first long connect() */ } } diff --git a/src/core/tcping/QvTCPing.hpp b/src/core/tcping/QvTCPing.hpp new file mode 100644 index 00000000..3e69ea20 --- /dev/null +++ b/src/core/tcping/QvTCPing.hpp @@ -0,0 +1,31 @@ +#pragma once +#include "base/Qv2rayBase.hpp" +#include "core/CoreSafeTypes.hpp" + +namespace Qv2ray::core::tcping +{ + struct QvTCPingResultObject { + ConnectionId connectionId = NullConnectionId; + QString errorMessage; + int total, succeed, failed; + uint worst = 0, best = 0, avg = 0; + }; + + class QvTCPingHelper : public QObject + { + Q_OBJECT + + public: + explicit QvTCPingHelper(const int defaultCount = 5, QObject *parent = nullptr); + void TestLatency(const ConnectionId &connectionId); + void StopAllLatenceTest(); + signals: + void OnLatencyTestCompleted(const QvTCPingResultObject &data); + private: + static QvTCPingResultObject TestLatency_p(const ConnectionId &id, const int count); + int count; + QQueue*> pingWorkingThreads; + }; +} + +using namespace Qv2ray::core::tcping; diff --git a/src/ui/models/ConnectionTreeModel.cpp b/src/ui/models/ConnectionTreeModel.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ui/models/ConnectionTreeModel.hpp b/src/ui/models/ConnectionTreeModel.hpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 5b36fdc3..4b4209ec 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -33,47 +33,31 @@ #define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING // #define GetItemWidget(item) (qobject_cast(connectionListWidget->itemWidget(item, 0))) -// -//#define ItemConnectionIdentifier(__item__) (__item__->data(0, Qt::UserRole).value()) -// -//#define CheckConfigType(_item_, TYPE) (connections.contains(ItemConnectionIdentifier(_item_)) && connections[ItemConnectionIdentifier(_item_)].configType == CONNECTION_ ## TYPE) -// -//#define SUBSCRIPTION_CONFIG_MODIFY_ASK(_item_) \ -// if (!CheckConfigType(_item_, REGULAR)) { \ -// if (QvMessageBoxAsk(this, QObject::tr("Editing a subscription config"), QObject::tr("You are trying to edit a config loaded from subscription.") + \ -// NEWLINE + QObject::tr("All changes will be overwritten when the subscriptions are updated next time.") + \ -// NEWLINE + QObject::tr("Are you still going to do so?")) != QMessageBox::Yes) { \ -// return; \ -// } \ -// } \ -// -// -//#define SUBSCRIPTION_CONFIG_MODIFY_DENY(_item_) \ -// if (!CheckConfigType(_item_, REGULAR)) { \ -// QvMessageBoxWarn(this, QObject::tr("Editing a subscription config"), QObject::tr("You should not modity this property of a config from a subscription")); \ -// return; \ -// } \ -// -//#define IsConnectableItem(item) (item != nullptr && item->childCount() == 0 && (CheckConfigType(item, REGULAR) || CheckConfigType(item, SUBSCRIPTION))) -#define IsSelectionConnectable (!connectionListWidget->selectedItems().empty() && IsConnectableItem(connectionListWidget->selectedItems().first())) -// From https://gist.github.com/jemyzhang/7130092 -#define CleanUpLogs(browser) \ - {\ - auto maxLines = GlobalConfig.uiConfig.maximumLogLines; \ - QTextBlock block = browser->document()->begin();\ - while (block.isValid()) {\ - if (browser->document()->blockCount() > maxLines) {\ - QTextCursor cursor(block);\ - block = block.next();\ - cursor.select(QTextCursor::BlockUnderCursor);\ - cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);\ - cursor.removeSelectedText();\ - } else {\ - break;\ - }\ - }\ - } +/* +#define ItemConnectionIdentifier(__item__) (__item__->data(0, Qt::UserRole).value()) + +#define CheckConfigType(_item_, TYPE) (connections.contains(ItemConnectionIdentifier(_item_)) && connections[ItemConnectionIdentifier(_item_)].configType == CONNECTION_ ## TYPE) + +#define SUBSCRIPTION_CONFIG_MODIFY_ASK(_item_) \ + if (!CheckConfigType(_item_, REGULAR)) { \ + if (QvMessageBoxAsk(this, QObject::tr("Editing a subscription config"), QObject::tr("You are trying to edit a config loaded from subscription.") + \ + NEWLINE + QObject::tr("All changes will be overwritten when the subscriptions are updated next time.") + \ + NEWLINE + QObject::tr("Are you still going to do so?")) != QMessageBox::Yes) { \ + return; \ + } \ + } \ + + +#define SUBSCRIPTION_CONFIG_MODIFY_DENY(_item_) \ + if (!CheckConfigType(_item_, REGULAR)) { \ + QvMessageBoxWarn(this, QObject::tr("Editing a subscription config"), QObject::tr("You should not modity this property of a config from a subscription")); \ + return; \ + } \ + +#define IsConnectableItem(item) (item != nullptr && item->childCount() == 0 && (CheckConfigType(item, REGULAR) || CheckConfigType(item, SUBSCRIPTION))) +#define IsSelectionConnectable (!connectionListWidget->selectedItems().empty() && IsConnectableItem(connectionListWidget->selectedItems().first())) +*/ MainWindow *MainWindow::mwInstance = nullptr; @@ -90,15 +74,12 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr { setupUi(this); MainWindow::mwInstance = this; - //connect(vinstance, &V2rayKernelInstance::onProcessOutputReadyRead, this, &MainWindow::UpdateVCoreLog); - //connect(vinstance, &V2rayKernelInstance::onProcessErrored, [this] { - // on_stopButton_clicked(); - // this->show(); - // QvMessageBoxWarn(this, tr("V2ray vcore terminated."), - // tr("V2ray vcore terminated unexpectedly.") + NEWLINE + NEWLINE + - // tr("To solve the problem, read the V2ray log in the log text browser.")); - //}); - // + connect(ConnectionManager, &QvConnectionHandler::OnCrashed, [&] { + this->show(); + QvMessageBoxWarn(this, tr("V2ray vcore terminated."), + tr("V2ray vcore terminated unexpectedly.") + NEWLINE + NEWLINE + + tr("To solve the problem, read the V2ray log in the log text browser.")); + }); QvMessageBusConnect(MainWindow); // infoWidget = new ConnectionInfoWidget(this); @@ -118,6 +99,7 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr // // connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &MainWindow::OnConnected); + connect(ConnectionManager, &QvConnectionHandler::OnDisConnected, this, &MainWindow::OnDisConnected); connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &MainWindow::onConnectionStatsArrived); connect(ConnectionManager, &QvConnectionHandler::OnVCoreLogAvailable, this, &MainWindow::onVCoreLogArrived); // @@ -243,6 +225,7 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr CheckSubscriptionsUpdate(); // + splitter->setSizes(QList() << 100 << 300); } @@ -696,127 +679,10 @@ void MainWindow::on_action_RCM_EditJson_triggered() // ShowAndSetConnection(CurrentConnectionIdentifier, false, false); //} } -void MainWindow::on_editJsonBtn_clicked() -{ - // See above. - on_action_RCM_EditJson_triggered(); -} -void MainWindow::on_pingTestBtn_clicked() -{ - //// Get data from UI - //QList aliases; - //auto selection = connectionListWidget->selectedItems(); - // - //if (selection.count() == 0) { - // // Ping ALL connections, warning. - // if (QvMessageBoxAsk(this, tr("Latency Test"), tr("You are about to run latency test on all servers, do you want to continue?")) == QMessageBox::Yes) { - // aliases.append(connections.keys()); - // } - //} else { - // for (auto i = 0; i < selection.count(); i++) { - // auto thisItem = selection[i]; - // - // if (thisItem->childCount() > 0) { - // // So we add another check to make sure the selected one is a subscription entry. - // // Loop to add all sub-connections to the list. - // for (auto j = 0; j < thisItem->childCount(); j++) { - // aliases.append(ItemConnectionIdentifier(thisItem->child(j))); - // } - // } else { - // aliases.append(ItemConnectionIdentifier(thisItem)); - // } - // } - //} - // - //LOG(UI, "Will perform latency test on " + QSTRN(aliases.count()) + " hosts.") - //latencyLabel->setText(tr("Testing...")); - // - //for (auto alias : aliases) { - // MWTryPingConnection(alias); - //} -} -void MainWindow::on_shareBtn_clicked() -{ - //// Share QR - //if (!IsSelectionConnectable) { - // return; - //} - // - //auto _identifier = ItemConnectionIdentifier(connectionListWidget->currentItem()); - //auto root = connections[_identifier].config; - //auto type = get<2>(GetConnectionInfo(root)); - // - //if (!IsComplexConfig(root) && (type == "vmess" || type == "shadowsocks")) { - // ConfigExporter v(root, _identifier, this); - // v.OpenExport(); - //} else { - // QvMessageBoxWarn(this, tr("Share Connection"), tr("There're no support of sharing configs other than vmess and shadowsocks")); - //} -} + void MainWindow::on_action_RCM_ShareQR_triggered() { - on_shareBtn_clicked(); -} -void MainWindow::timerEvent(QTimerEvent *event) -{ - //// Calling base class - //QMainWindow::timerEvent(event); - // - //if (event->timerId() == speedTimerId) { - // auto _totalSpeedUp = vinstance->getAllSpeedUp(); - // auto _totalSpeedDown = vinstance->getAllSpeedDown(); - // auto _totalDataUp = vinstance->getAllDataUp(); - // auto _totalDataDown = vinstance->getAllDataDown(); - // // - // speedChartView->AddPointData(_totalSpeedUp, _totalSpeedDown); - // // - // auto totalSpeedUp = FormatBytes(_totalSpeedUp) + "/s"; - // auto totalSpeedDown = FormatBytes(_totalSpeedDown) + "/s"; - // auto totalDataUp = FormatBytes(_totalDataUp); - // auto totalDataDown = FormatBytes(_totalDataDown); - // // - // netspeedLabel->setText(totalSpeedUp + NEWLINE + totalSpeedDown); - // dataamountLabel->setText(totalDataUp + NEWLINE + totalDataDown); - // // - // hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + CurrentConnectionIdentifier.IdentifierString() + NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); - //} else if (event->timerId() == qvLogTimerId) { - // QString lastLog = readLastLog(); - // - // if (!lastLog.isEmpty()) { - // qvAppLogBrowser->append(lastLog); - // } - // - // CleanUpLogs(vCoreLogBrowser) - //} else if (event->timerId() == pingTimerId) { - // MWTryPingConnection(CurrentConnectionIdentifier); - //} -} -void MainWindow::on_duplicateBtn_clicked() -{ - QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - //if (!IsSelectionConnectable) { - // return; - //} - // - //auto selectedFirst = connectionListWidget->currentItem(); - //auto _identifier = ItemConnectionIdentifier(selectedFirst); - //SUBSCRIPTION_CONFIG_MODIFY_ASK(selectedFirst) - //CONFIGROOT conf; - //// Alias may change. - //QString alias = _identifier.connectionName; - //bool isComplex = IsComplexConfig(connections[_identifier].config); - // - //if (connections[_identifier].configType == CONNECTION_REGULAR) { - // conf = ConvertConfigFromFile(QV2RAY_CONFIG_DIR + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex); - //} else { - // conf = ConvertConfigFromFile(QV2RAY_SUBSCRIPTION_DIR + _identifier.subscriptionName + "/" + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex); - // alias = _identifier.subscriptionName + "_" + _identifier.connectionName; - //} - // - //SaveConnectionConfig(conf, &alias, false); - //GlobalConfig.configs.push_back(alias); - //SaveGlobalConfig(GlobalConfig); - //this->OnConfigListChanged(false); + //on_shareBtn_clicked(); } void MainWindow::on_subsButton_clicked() @@ -824,25 +690,6 @@ void MainWindow::on_subsButton_clicked() SubscribeEditor().exec(); } -void MainWindow::on_connectionListWidget_itemSelectionChanged() -{ - //if (!isRenamingInProgress && !IsSelectionConnectable) { - // // If renaming is not in progress AND our selection is invalid. - // CurrentSelectedItemPtr = nullptr; - // SetEditWidgetEnable(false); - // routeCountLabel->setText(tr("N/A")); - // _OutBoundTypeLabel->setText(tr("N/A")); - // _hostLabel->setText(tr("N/A")); - // _portLabel->setText(tr("N/A")); - // latencyLabel->setText(tr("N/A")); - //} else { - // if (!connectionListWidget->selectedItems().isEmpty()) { - // on_connectionListWidget_currentItemChanged(connectionListWidget->selectedItems().first(), nullptr); - // CurrentSelectedItemPtr = connectionListWidget->selectedItems().first(); - // } - //} -} - void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column) { Q_UNUSED(column) @@ -852,24 +699,36 @@ void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item widget->BeginConnection(); } } -/* - * //if (startFlag) { - // MWTryPingConnection(name); - // speedTimerId = startTimer(1000); - // pingTimerId = startTimer(60000); - // this->hTray.showMessage("Qv2ray", tr("Connected: ") + name, this->windowIcon()); - // hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + name); - // statusLabel->setText(tr("Connected: ") + name); - //} - //} else { - // this->hTray.showMessage("Qv2ray", tr("Already connected to: ") + CurrentConnectionIdentifier.IdentifierString(), this->windowIcon()); - //} - */ + +void MainWindow::OnDisConnected(const ConnectionId &id) +{ + Q_UNUSED(id) + this->hTray.showMessage("Qv2ray", tr("Disonnected"), this->windowIcon()); + hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE); + connetionStatusLabel->setText(tr("Disconnected")); + + if (systemProxyEnabled) { + MWClearSystemProxy(false); + } + + //QFile(QV2RAY_GENERATED_FILE_PATH).remove(); + + if (GlobalConfig.inboundConfig.pacConfig.enablePAC) { + //pacServer.StopServer(); + LOG(MODULE_UI, "Stopping PAC server") + } +} void MainWindow::OnConnected(const ConnectionId &id) { Q_UNUSED(id) on_clearlogButton_clicked(); + auto name = ConnectionManager->GetDisplayName(id); + this->hTray.showMessage("Qv2ray", tr("Connected: ") + name, this->windowIcon()); + hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + name); + connetionStatusLabel->setText(tr("Connected: ") + name); + // + ConnectionManager->StartLatencyTest(id); bool usePAC = GlobalConfig.inboundConfig.pacConfig.enablePAC; bool pacUseSocks = GlobalConfig.inboundConfig.pacConfig.useSocksProxy; bool httpEnabled = GlobalConfig.inboundConfig.useHTTP; @@ -924,9 +783,7 @@ void MainWindow::onConnectionWidgetFocusRequested(const ConnectionItemWidget *_w } for (auto _item_ : connectionListWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard | Qt::MatchRecursive)) { - auto myWidget = GetItemWidget(_item_); - - if (myWidget == _widget) { + if (GetItemWidget(_item_) == _widget) { LOG(MODULE_UI, "Setting current item.") connectionListWidget->setCurrentItem(_item_); connectionListWidget->scrollToItem(_item_); @@ -945,9 +802,8 @@ void MainWindow::on_connectionFilterTxt_textEdited(const QString &arg1) for (auto i = 0; i < _top_item_->childCount(); i++) { auto _child_ = _top_item_->child(i); - auto childWidget = GetItemWidget(_child_); - if (childWidget->NameMatched(arg1)) { + if (GetItemWidget(_child_)->NameMatched(arg1)) { LOG(MODULE_UI, "Setting current item.") // Show the child _child_->setHidden(false); @@ -971,17 +827,17 @@ void MainWindow::on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int infoWidget->ShowDetails(GetItemWidget(item)->Identifier()); } -void MainWindow::onConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed) +void MainWindow::onConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, const quint64 totalDown) { Q_UNUSED(id); // This may not be, or may not precisely be, speed per second if low-level has "any" latency. // (Hope not...) speedChartWidget->AddPointData(upSpeed, downSpeed); - auto data = ConnectionManager->GetConnectionUsageAmount(id); + // auto totalSpeedUp = FormatBytes(upSpeed) + "/s"; auto totalSpeedDown = FormatBytes(downSpeed) + "/s"; - auto totalDataUp = FormatBytes(get<0>(data)); - auto totalDataDown = FormatBytes(get<1>(data)); + auto totalDataUp = FormatBytes(totalUp); + auto totalDataDown = FormatBytes(totalDown); // netspeedLabel->setText(totalSpeedUp + NEWLINE + totalSpeedDown); dataamountLabel->setText(totalDataUp + NEWLINE + totalDataDown); @@ -992,18 +848,25 @@ void MainWindow::onConnectionStatsArrived(const ConnectionId &id, const quint64 void MainWindow::onVCoreLogArrived(const ConnectionId &id, const QString &log) { Q_UNUSED(id); - // This may not be, or may not precisely be, speed per second if low-level has "any" latency. - // (Hope not...) - UpdateVCoreLog(log); -} - -void MainWindow::UpdateVCoreLog(const QString &log) -{ - masterLogBrowser->append(log); - CleanUpLogs(masterLogBrowser) auto bar = masterLogBrowser->verticalScrollBar(); auto max = bar->maximum(); auto val = bar->value(); + masterLogBrowser->append(log); + // From https://gist.github.com/jemyzhang/7130092 + auto maxLines = GlobalConfig.uiConfig.maximumLogLines; + QTextBlock block = masterLogBrowser->document()->begin(); + + while (block.isValid()) { + if (masterLogBrowser->document()->blockCount() > maxLines) { + QTextCursor cursor(block); + block = block.next(); + cursor.select(QTextCursor::BlockUnderCursor); + cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); + cursor.removeSelectedText(); + } else { + break; + } + } if (val >= max * 0.8 || val >= max - 20) bar->setValue(max); diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 2cc2845a..650db1cf 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -29,8 +29,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow void ReConnect() const; public slots: QvMessageBusSlotHeader - //void onPingFinished(QvTCPingData data); - void UpdateVCoreLog(const QString &log); private slots: void on_action_RCM_ShareQR_triggered(); void on_activatedTray(QSystemTrayIcon::ActivationReason reason); @@ -43,10 +41,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow void on_removeConfigButton_clicked(); void on_importConfigButton_clicked(); void on_editConfigButton_clicked(); - void on_editJsonBtn_clicked(); - void on_pingTestBtn_clicked(); - void on_shareBtn_clicked(); - void on_duplicateBtn_clicked(); void on_subsButton_clicked(); // void ToggleVisibility(); @@ -60,23 +54,23 @@ class MainWindow : public QMainWindow, Ui::MainWindow protected: void keyPressEvent(QKeyEvent *e) override; - void timerEvent(QTimerEvent *event) override; void closeEvent(QCloseEvent *) override; private slots: // void OnConnected(const ConnectionId &id); + void OnDisConnected(const ConnectionId &id); + void onConnectionWidgetFocusRequested(const ConnectionItemWidget *widget); //void onConnectionConnected(const ConnectionId &id); //void onConnectionDisConnected(const ConnectionId &id); - void onConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed); + void onConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, const quint64 totalDown); void onVCoreLogArrived(const ConnectionId &id, const QString &log); // void on_action_StartThis_triggered(); void on_action_RCM_EditJson_triggered(); void on_action_RCM_ConvToComplex_triggered(); void on_action_RCM_RenameConnection_triggered(); - void on_connectionListWidget_itemSelectionChanged(); void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); void on_connectionFilterTxt_textEdited(const QString &arg1); void on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column); @@ -112,7 +106,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow // // ----------------------------------- Extra Headers For w_MainWindow_extra.cpp Handling V2ray Connectivities. bool systemProxyEnabled; - void MWStopConnection(); void MWSetSystemProxy(); void MWClearSystemProxy(bool); void CheckSubscriptionsUpdate(); diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 0b13e546..c5dad60b 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -79,6 +79,12 @@ true + + + 0 + 0 + + @@ -201,7 +207,7 @@ 0 0 - 559 + 480 743 @@ -340,7 +346,7 @@ 6 - + 300 diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index 90cbf865..5604bd15 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -102,41 +102,6 @@ void MainWindow::MWSetSystemProxy() } } -void MainWindow::MWStopConnection() -{ - //if (systemProxyEnabled) { - // MWClearSystemProxy(false); - //} - // - //this->vinstance->StopConnection(); - //QFile(QV2RAY_GENERATED_FILE_PATH).remove(); - // - //if (GlobalConfig.inboundConfig.pacConfig.enablePAC) { - // pacServer.StopServer(); - // LOG(UI, "Stopping PAC server") - //} -} - -//void MainWindow::MWTryPingConnection(const QvConnectionObject &alias) -//{ -// //try { -// // auto info = MWGetConnectionInfo(alias); -// // QString host = get<0>(info); -// // int port = get<1>(info); -// // tcpingHelper.StartPing(alias, host, port); -// //} catch (...) { -// // QvMessageBoxWarn(this, tr("Latency Test"), tr("Failed to test latency for this connection.")); -// //} -//} -// -//tuple MainWindow::MWGetConnectionInfo(const QvConnectionObject &alias) -//{ -// //if (!connections.contains(alias)) -// // return make_tuple(tr("N/A"), 0, tr("N/A")); -// // -// //return GetConnectionInfo(connections[alias].config); -//} - void MainWindow::CheckSubscriptionsUpdate() { QStringList updateList; diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 9d46dd19..fba08c72 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -1,8 +1,7 @@ #include "ConnectionInfoWidget.hpp" #include "core/CoreUtils.hpp" -ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : - QWidget(parent), connectionId("null"), groupId("null") +ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent): QWidget(parent) { setupUi(this); duplicateBtn->setIcon(QICON_R("duplicate.png")); @@ -24,13 +23,13 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden groupId = get<0>(_identifier); connectionId = get<1>(_identifier); - if (connectionId.toString() != "null") { + if (connectionId != NullConnectionId) { //connNameLabel->setText(ConnectionManager->GetDisplayName(connectionId)); groupLabel->setText(ConnectionManager->GetDisplayName(groupId, 175)); protocolLabel->setText(ConnectionManager->GetConnectionProtocolString(connectionId)); - auto x = ConnectionManager->GetConnectionInfo(connectionId); - addressLabel->setText(get<0>(x)); - portLabel->setNum(get<1>(x)); + auto [host, port] = ConnectionManager->GetConnectionInfo(connectionId); + addressLabel->setText(host); + portLabel->setNum(port); // editJsonBtn->setEnabled(true); connectBtn->setEnabled(true); @@ -66,7 +65,21 @@ void ConnectionInfoWidget::on_connectBtn_clicked() ConnectionManager->StartConnection(connectionId); } } - +//// Share QR +//if (!IsSelectionConnectable) { +// return; +//} +// +//auto _identifier = ItemConnectionIdentifier(connectionListWidget->currentItem()); +//auto root = connections[_identifier].config; +//auto type = get<2>(GetConnectionInfo(root)); +// +//if (!IsComplexConfig(root) && (type == "vmess" || type == "shadowsocks")) { +// ConfigExporter v(root, _identifier, this); +// v.OpenExport(); +//} else { +// QvMessageBoxWarn(this, tr("Share Connection"), tr("There're no support of sharing configs other than vmess and shadowsocks")); +//} void ConnectionInfoWidget::on_editBtn_clicked() { } @@ -106,3 +119,40 @@ void ConnectionInfoWidget::OnDisConnected(const ConnectionId &id) connectBtn->setIcon(QICON_R("connect.png")); } } +//MWTryPingConnection(CurrentConnectionIdentifier); +void ConnectionInfoWidget::on_duplicateBtn_clicked() +{ + //QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); + //if (!IsSelectionConnectable) { + // return; + //} + // + //auto selectedFirst = connectionListWidget->currentItem(); + //auto _identifier = ItemConnectionIdentifier(selectedFirst); + //SUBSCRIPTION_CONFIG_MODIFY_ASK(selectedFirst) + //CONFIGROOT conf; + //// Alias may change. + //QString alias = _identifier.connectionName; + //bool isComplex = IsComplexConfig(connections[_identifier].config); + // + //if (connections[_identifier].configType == CONNECTION_REGULAR) { + // conf = ConvertConfigFromFile(QV2RAY_CONFIG_DIR + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex); + //} else { + // conf = ConvertConfigFromFile(QV2RAY_SUBSCRIPTION_DIR + _identifier.subscriptionName + "/" + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex); + // alias = _identifier.subscriptionName + "_" + _identifier.connectionName; + //} + // + //SaveConnectionConfig(conf, &alias, false); + //GlobalConfig.configs.push_back(alias); + //SaveGlobalConfig(GlobalConfig); + //this->OnConfigListChanged(false);} +} + +void ConnectionInfoWidget::on_latencyBtn_clicked() +{ + if (connectionId != NullConnectionId) { + ConnectionManager->StartLatencyTest(connectionId); + } else { + ConnectionManager->StartLatencyTest(groupId); + } +} diff --git a/src/ui/widgets/ConnectionInfoWidget.hpp b/src/ui/widgets/ConnectionInfoWidget.hpp index 475c3e8d..00b5f5c6 100644 --- a/src/ui/widgets/ConnectionInfoWidget.hpp +++ b/src/ui/widgets/ConnectionInfoWidget.hpp @@ -26,8 +26,12 @@ class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget void OnConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id); + void on_duplicateBtn_clicked(); + + void on_latencyBtn_clicked(); + private: - ConnectionId connectionId; - GroupId groupId; + ConnectionId connectionId = NullConnectionId; + GroupId groupId = NullGroupId; }; diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index e325853b..e5976bc5 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -55,6 +55,17 @@ + + + + + + + + :/assets/icons/ui_light/ping_gauge.png:/assets/icons/ui_light/ping_gauge.png + + + diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index 80208ea8..6e52bffc 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -7,6 +7,8 @@ ConnectionItemWidget::ConnectionItemWidget(QWidget *parent) : QWidget(parent), c connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &ConnectionItemWidget::OnConnected); connect(ConnectionManager, &QvConnectionHandler::OnDisConnected, this, &ConnectionItemWidget::OnDisConnected); connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &ConnectionItemWidget::OnConnectionStatsArrived); + connect(ConnectionManager, &QvConnectionHandler::OnLatencyTestStarted, this, &ConnectionItemWidget::OnLatencyTestStart); + connect(ConnectionManager, &QvConnectionHandler::OnLatencyTestFinished, this, &ConnectionItemWidget::OnLatencyTestFinished); } ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *parent): ConnectionItemWidget(parent) @@ -17,7 +19,14 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare itemType = NODE_ITEM; connNameLabel->setText("" + originalConnectionName); // TODO - latencyLabel->setText(QSTRN(ConnectionManager->GetConnectionLatency(id)) + " " + tr("ms")); + auto latency = ConnectionManager->GetConnectionLatency(id); + + if (latency == 0) { + latencyLabel->setText(tr("Not Tested")); + } else { + latencyLabel->setText(QSTRN(latency) + " " + tr("ms")); + } + connTypeLabel->setText(tr("Type: ") + ConnectionManager->GetConnectionProtocolString(id)); auto [uplink, downlink] = ConnectionManager->GetConnectionUsageAmount(connectionId); dataLabel->setText(FormatBytes(uplink) + " / " + FormatBytes(downlink)); @@ -41,7 +50,6 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : delete dataLabel; } - void ConnectionItemWidget::BeginConnection() { if (itemType == NODE_ITEM) { @@ -67,14 +75,32 @@ void ConnectionItemWidget::OnDisConnected(const ConnectionId &id) } } -void ConnectionItemWidget::OnConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed) +void ConnectionItemWidget::OnConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, const quint64 totalDown) { Q_UNUSED(upSpeed) Q_UNUSED(downSpeed) if (id == connectionId) { - auto [uplink, downlink] = ConnectionManager->GetConnectionUsageAmount(id); - dataLabel->setText(FormatBytes(uplink) + " / " + FormatBytes(downlink)); + dataLabel->setText(FormatBytes(totalUp) + " / " + FormatBytes(totalDown)); + } +} + +void ConnectionItemWidget::OnLatencyTestStart(const ConnectionId &id) +{ + if (id == connectionId) { + latencyLabel->setText(tr("Testing...")); + } +} +void ConnectionItemWidget::OnLatencyTestFinished(const ConnectionId &id, const uint average) +{ + if (id == connectionId) { + if (average == 0) { + latencyLabel->setText(tr("Error")); + RED(latencyLabel) + } else { + latencyLabel->setText(QSTRN(average) + tr("ms")); + BLACK(latencyLabel) + } } } diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index 79ab34ee..9aad5c8c 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -41,9 +41,11 @@ class ConnectionItemWidget : public QWidget, private Ui::ConnectionWidget signals: void RequestWidgetFocus(const ConnectionItemWidget *me); private slots: - void OnConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed); + void OnConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, const quint64 totalDown); void OnConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id); + void OnLatencyTestStart(const ConnectionId &id); + void OnLatencyTestFinished(const ConnectionId &id, const uint average); private: QString originalConnectionName; explicit ConnectionItemWidget(QWidget *parent = nullptr); From adb7bc4c1e6032eb90cf97a7d90c57196cd2ea11 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 25 Feb 2020 22:16:32 +0800 Subject: [PATCH 045/332] add: added export sharelink and qr support, ssd:// WIP --- makespec/BUILDVERSION | 2 +- src/core/connection/Serialization.cpp | 37 +++++++++++++------------ src/core/connection/Serialization.hpp | 3 +- src/core/handler/ConnectionHandler.cpp | 12 ++++---- src/core/handler/ConnectionHandler.hpp | 5 ++-- src/ui/w_MainWindow_extra.cpp | 1 - src/ui/widgets/ConnectionInfoWidget.cpp | 15 ++++++++-- 7 files changed, 44 insertions(+), 31 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 2d2c4aa9..0130643d 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3956 +3961 diff --git a/src/core/connection/Serialization.cpp b/src/core/connection/Serialization.cpp index 1fc175de..ab47b53e 100644 --- a/src/core/connection/Serialization.cpp +++ b/src/core/connection/Serialization.cpp @@ -2,6 +2,7 @@ #include "Generation.hpp" #include "common/QvHelpers.hpp" #include "core/CoreUtils.hpp" +#include "core/handler/ConnectionHandler.hpp" namespace Qv2ray::core::connection { @@ -22,26 +23,26 @@ namespace Qv2ray::core::connection return config; } - - QString ConvertConfigToString(const CONFIGROOT &server, const QString &alias, bool isSip002) + const QString ConvertConfigToString(const ConnectionId &id, bool isSip002) { + auto server = ConnectionManager->GetConnectionRoot(id); + auto alias = ConnectionManager->GetDisplayName(id); OUTBOUND outbound = OUTBOUND(server["outbounds"].toArray().first().toObject()); - //auto info = GetConnectionInfo(server); - //auto type = get<2>(info); - //QString sharelink = ""; - // - //if (type == "vmess") { - // auto vmessServer = StructFromJsonString(JsonToString(outbound["settings"].toObject()["vnext"].toArray().first().toObject())); - // auto transport = StructFromJsonString(JsonToString(outbound["streamSettings"].toObject())); - // sharelink = ConvertConfigToVMessString(transport, vmessServer, alias); - //} else if (type == "shadowsocks") { - // auto ssServer = StructFromJsonString(JsonToString(outbound["settings"].toObject()["servers"].toArray().first().toObject())); - // sharelink = ConvertConfigToSSString(ssServer, alias, isSip002); - //} else { - // LOG(MODULE_CONNECTION, "Unsupported outbound type: " + type) - //} - return "WIP"; - //return sharelink; + auto type = outbound["protocol"].toString(); + QString sharelink = ""; + + if (type == "vmess") { + auto vmessServer = StructFromJsonString(JsonToString(outbound["settings"].toObject()["vnext"].toArray().first().toObject())); + auto transport = StructFromJsonString(JsonToString(outbound["streamSettings"].toObject())); + sharelink = ConvertConfigToVMessString(transport, vmessServer, alias); + } else if (type == "shadowsocks") { + auto ssServer = StructFromJsonString(JsonToString(outbound["settings"].toObject()["servers"].toArray().first().toObject())); + sharelink = ConvertConfigToSSString(ssServer, alias, isSip002); + } else { + LOG(MODULE_CONNECTION, "Unsupported outbound type: " + type) + } + + return sharelink; } // From https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2) diff --git a/src/core/connection/Serialization.hpp b/src/core/connection/Serialization.hpp index f72059c3..fffb574d 100644 --- a/src/core/connection/Serialization.hpp +++ b/src/core/connection/Serialization.hpp @@ -1,4 +1,5 @@ #include "base/Qv2rayBase.hpp" +#include "core/CoreSafeTypes.hpp" namespace Qv2ray::core::connection { @@ -9,7 +10,7 @@ namespace Qv2ray::core::connection // General CONFIGROOT ConvertConfigFromString(const QString &link, QString *alias, QString *errMessage); - QString ConvertConfigToString(const CONFIGROOT &server, const QString &alias, bool isSip002 = false); + const QString ConvertConfigToString(const ConnectionId &id, bool isSip002 = false); // VMess URI Protocol CONFIGROOT ConvertConfigFromVMessString(const QString &vmess, QString *alias, QString *errMessage); diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index 1acf03a5..0436fd35 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -204,7 +204,7 @@ namespace Qv2ray::core::handlers StopConnection(); } - CONFIGROOT root = CHGetConnectionRoot_p(connections[identifier].groupId, identifier); + CONFIGROOT root = GetConnectionRoot(connections[identifier].groupId, identifier); return CHStartConnection_p(identifier, root); } @@ -230,7 +230,7 @@ namespace Qv2ray::core::handlers result = tr("N/A"); } - CONFIGROOT root = CHGetConnectionRoot_p(connections[id].groupId, id); + CONFIGROOT root = GetConnectionRoot(connections[id].groupId, id); QStringList protocols; QStringList streamProtocols; auto outbound = root["outbounds"].toArray().first().toObject(); @@ -273,12 +273,12 @@ namespace Qv2ray::core::handlers delete vCoreInstance; } - const CONFIGROOT QvConnectionHandler::CHGetConnectionRoot_p(const ConnectionId &id) const + const CONFIGROOT QvConnectionHandler::GetConnectionRoot(const ConnectionId &id) const { - return connections.contains(id) ? CHGetConnectionRoot_p(connections[id].groupId, id) : CONFIGROOT(); + return connections.contains(id) ? GetConnectionRoot(connections[id].groupId, id) : CONFIGROOT(); } - const CONFIGROOT QvConnectionHandler::CHGetConnectionRoot_p(const GroupId &group, const ConnectionId &id) const + const CONFIGROOT QvConnectionHandler::GetConnectionRoot(const GroupId &group, const ConnectionId &id) const { auto path = group.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; path.prepend(groups[group].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR); @@ -288,7 +288,7 @@ namespace Qv2ray::core::handlers const tuple QvConnectionHandler::GetConnectionInfo(const ConnectionId &id) const { - auto root = CHGetConnectionRoot_p(id); + auto root = GetConnectionRoot(id); bool validOutboundFound = false; QString host; int port; diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 250663a7..10456a30 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -42,6 +42,9 @@ namespace Qv2ray::core::handlers const ConnectionId DuplicateConnection(const ConnectionId &id); const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); // + const CONFIGROOT GetConnectionRoot(const ConnectionId &id) const; + const CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id) const; + // // Get Conncetion Property const QString GetConnectionProtocolString(const ConnectionId &id) const; const tuple GetConnectionInfo(const ConnectionId &connectionId) const; @@ -101,8 +104,6 @@ namespace Qv2ray::core::handlers bool CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port) const; optional CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); void CHStopConnection_p(); - const CONFIGROOT CHGetConnectionRoot_p(const ConnectionId &id) const; - const CONFIGROOT CHGetConnectionRoot_p(const GroupId &group, const ConnectionId &id) const; bool CHSaveConnectionConfig_p(CONFIGROOT obj, const ConnectionId &id, bool override); private: diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index 5604bd15..49bf3779 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -3,7 +3,6 @@ // We NEED to include the cpp file to define the macros. #include "w_MainWindow.cpp" #include "components/proxy/QvProxyConfigurator.hpp" -#include "core/connection/Generation.hpp" //QTreeWidgetItem *MainWindow::FindItemByIdentifier(QvConnectionObject identifier) //{ diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index fba08c72..7afdd5ea 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -1,5 +1,7 @@ #include "ConnectionInfoWidget.hpp" #include "core/CoreUtils.hpp" +#include "core/connection/Serialization.hpp" +#include "3rdparty/qzxing/src/QZXing.h" ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent): QWidget(parent) { @@ -35,12 +37,18 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden connectBtn->setEnabled(true); duplicateBtn->setEnabled(true); // - shareLinkTxt->setText("scheme://user:pass@host:port/path/to/file?arg1=ARG1&arg2=ARG2#tag"); + auto shareLink = ConvertConfigToString(connectionId); + shareLinkTxt->setText(shareLink); shareLinkTxt->setCursorPosition(0); // + QZXingEncoderConfig conf; + conf.border = true; + conf.imageSize = QSize(400, 400); + auto img = QZXing().encodeData(shareLink, conf); + qrLabel->setPixmap(QPixmap::fromImage(img)); + // connectBtn->setIcon(ConnectionManager->IsConnected(connectionId) ? QICON_R("stop.png") : QICON_R("connect.png")); } else { - //connNameLabel->setText(ConnectionManager->GetDisplayName(groupId)); connectBtn->setIcon(QICON_R("connect.png")); groupLabel->setText(tr("N/A")); protocolLabel->setText(tr("N/A")); @@ -50,6 +58,9 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden editJsonBtn->setEnabled(false); connectBtn->setEnabled(false); duplicateBtn->setEnabled(false); + // + shareLinkTxt->clear(); + qrLabel->clear(); } } From 2a0c4592029daff82fc3f5c7d803fa141dc14b21 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 10 Feb 2020 11:01:29 +0800 Subject: [PATCH 046/332] add: added settings ui for dokodemo --- src/ui/w_PreferencesWindow.cpp | 4 + src/ui/w_PreferencesWindow.hpp | 2 + src/ui/w_PreferencesWindow.ui | 792 ++++++++++++++++++--------------- 3 files changed, 427 insertions(+), 371 deletions(-) diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index 3345d5f8..c9b27315 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -1086,3 +1086,7 @@ void PreferencesWindow::on_enableAPI_stateChanged(int arg1) NEEDRESTART CurrentConfig.apiConfig.enableAPI = arg1 == Qt::Checked; } + +void PreferencesWindow::on_tProxyGroupBox_clicked(bool checked) +{ +} diff --git a/src/ui/w_PreferencesWindow.hpp b/src/ui/w_PreferencesWindow.hpp index 0d19960f..b1b7c06f 100644 --- a/src/ui/w_PreferencesWindow.hpp +++ b/src/ui/w_PreferencesWindow.hpp @@ -163,6 +163,8 @@ class PreferencesWindow : public QDialog, private Ui::PreferencesWindow void on_startWithLoginCB_stateChanged(int arg1); + void on_tProxyGroupBox_clicked(bool checked); + private: void SetAutoStartButtonsState(bool isAutoStart); // Set ui parameters for a line; diff --git a/src/ui/w_PreferencesWindow.ui b/src/ui/w_PreferencesWindow.ui index 2f2f83f8..29d57067 100644 --- a/src/ui/w_PreferencesWindow.ui +++ b/src/ui/w_PreferencesWindow.ui @@ -9,8 +9,8 @@ 0 0 - 1070 - 653 + 1100 + 672 @@ -43,26 +43,13 @@ 0 0 - 1030 - 555 + 1060 + 574 - + - - - - Qt::Vertical - - - - 0 - 0 - - - - @@ -70,19 +57,6 @@ - - - - Qt::Vertical - - - - 0 - 0 - - - - @@ -230,43 +204,6 @@ - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - Auto Connect - - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - @@ -318,19 +255,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -338,19 +262,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -465,19 +376,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -485,19 +383,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -557,7 +442,7 @@ - + Qt::Vertical @@ -570,6 +455,17 @@ + + + + + + Auto Connect + + + + + @@ -594,8 +490,8 @@ 0 0 - 1016 - 557 + 1060 + 574 @@ -611,7 +507,7 @@ - 0.0.0.0 + 'localhost', or IPv4 address, e.g. '127.0.0.1' or IPv6 address with brackets, e.g. [::1] @@ -632,8 +528,85 @@ - - + + + + + HTTP Settings + + + true + + + false + + + + + + Port + + + + + + + 1 + + + 65535 + + + 18001 + + + + + + + Authentication + + + + + + + Enabled + + + + + + + Username + + + + + + + user + + + + + + + Password + + + + + + + pass + + + + + + + SOCKS Settings @@ -738,10 +711,10 @@ - - + + - HTTP Settings + Transparent Proxy Settings true @@ -749,16 +722,199 @@ false - - - + + + + + + 75 + true + true + + + + All settings below will only be applied onto simple connection. + + + + + + + Add Docodemo-door inbound + + + + + + + + + Address + + + + + + + 127.0.0.1 + + + + + + + Port + + + + + + + 1 + + + 65535 + + + 12345 + + + + + + + TCP + + + + + + + UDP + + + + + + + Follow Redirect + + + + + + + + + Override Connection SockOpt Settings + + + true + + + false + + + + + + Enabled + + + + + + + TCP Fast Open + + + + + + + Mark + + + + + + + Match Contains + + + + + + + + + + TProxy Mode + + + + + + + + + + + 75 + true + true + + + + Settings will be added to the StreamSettings for matched connections. + + + + + + + + + + + + + + + + Qt::PreventContextMenu + + + PAC Settings + + + true + + + false + + + + + + + true + + + + The system proxy will be configured to use the PAC instead of HTTP and SOCKS. + + + + + Port - - + + 1 @@ -766,49 +922,140 @@ 65535 - 18001 - - - - - - - Authentication - - - - - - - Enabled + 8088 - + - Username + Local IP for PAC - + - user + 127.0.0.1 - + - Password + Use Proxy - - - pass + + + + HTTP + + + + + SOCKS + + + + + + + + Import GFWList + + + + + + + + + + Mirror: Gitlab + + + + + Github + + + + + Mirror: Pagure + + + + + Mirror: Repo.or.cz + + + + + Mirror: Bitbucket + + + + + Mirror: TuxFamily + + + + + GFWList File + + + + + + + + Download with System Proxy + + + + + + + Go + + + + + + + + + Edit PAC + + + + + + + Open PAC Folder + + + + + + + PAC Access Path + + + + + + + IBeamCursor + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse @@ -817,189 +1064,6 @@ - - - - Qt::PreventContextMenu - - - PAC Settings - - - true - - - false - - - - - - - true - - - - The system proxy will be configured to use the PAC instead of HTTP and SOCKS. - - - - - - - Port - - - - - - - 1 - - - 65535 - - - 8088 - - - - - - - Local IP for PAC - - - - - - - 127.0.0.1 - - - - - - - Use Proxy - - - - - - - - HTTP - - - - - SOCKS - - - - - - - - Import GFWList - - - - - - - - - - Mirror: Gitlab - - - - - Github - - - - - Mirror: Pagure - - - - - Mirror: Repo.or.cz - - - - - Mirror: Bitbucket - - - - - Mirror: TuxFamily - - - - - GFWList File - - - - - - - - Download with System Proxy - - - - - - - Go - - - - - - - - - Edit PAC - - - - - - - Open PAC Folder - - - - - - - PAC Access Path - - - - - - - IBeamCursor - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - @@ -1023,8 +1087,8 @@ Connection Settings - - + + @@ -1087,22 +1151,9 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - - + @@ -1211,21 +1262,21 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -1941,7 +1992,6 @@ p, li { white-space: pre-wrap; } httpAuthCB httpAuthUsernameTxt httpAuthPasswordTxt - pacGroupBox pacPortSB pacProxyTxt pacProxyCB From 1b7659a30ee76577ba059e7bb4dab88dacb8f51c Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sat, 8 Feb 2020 15:57:56 +0800 Subject: [PATCH 047/332] Create ICMPPinger.hpp --- src/components/icmping/win/ICMPPinger.hpp | 32 +++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/components/icmping/win/ICMPPinger.hpp diff --git a/src/components/icmping/win/ICMPPinger.hpp b/src/components/icmping/win/ICMPPinger.hpp new file mode 100644 index 00000000..f6382049 --- /dev/null +++ b/src/components/icmping/win/ICMPPinger.hpp @@ -0,0 +1,32 @@ +#pragma once + +/** + * ICMPPinger - An Implementation of ICMPPing on Windows Platform + * Required Windows Version: 2000 / XP / 7 / Vista+ + * License: WTFPL + */ + +#include +#include +#include + +#include +#include +#include + + +class ICMPPinger { + public: + ICMPPinger(UINT64 timeout = DEFAULT_TIMEOUT); + ~ICMPPinger(); + + public: + static const UINT64 DEFAULT_TIMEOUT = 10000U; + + public: + std::pair, std::optional> ping(const std::string& ipAddr); + + private: + HANDLE hIcmpFile; + UINT64 timeout = DEFAULT_TIMEOUT; +}; From 5d5b2285a94cae5dccba60928b4f2a741b706604 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sat, 8 Feb 2020 15:59:38 +0800 Subject: [PATCH 048/332] Create ICMPPinger.cpp --- src/components/icmping/win/ICMPPinger.cpp | 43 +++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/components/icmping/win/ICMPPinger.cpp diff --git a/src/components/icmping/win/ICMPPinger.cpp b/src/components/icmping/win/ICMPPinger.cpp new file mode 100644 index 00000000..39d9272f --- /dev/null +++ b/src/components/icmping/win/ICMPPinger.cpp @@ -0,0 +1,43 @@ +#include "ICMPPinger.hpp" + +ICMPPinger::ICMPPinger(UINT64 timeout = DEFAULT_TIMEOUT) { + // create icmp handle + if ((this->hIcmpFile = IcmpCreateFile()) == INVALID_HANDLE_VALUE) { + throw "IcmpCreateFile failed"; + } + + // remember the timeout + this->timeout = timeout; +} + +ICMPPinger::~ICMPPinger() { + // release the handle on destruction + IcmpCloseHandle(this->hIcmpFile); +} + +std::pair, std::optional> ICMPPinger::ping(const std::string& ipAddr) { + // convert network address + const auto addr = inet_addr(ipAddr.c_str()); + if (addr == INADDR_NONE) { + return std::pair(std::nullopt, "invalid ip address: " + ipAddr); + } + + // request buffer + const static char bufRequest[] = "echo test"; + + // response buffer + const auto responseSize = sizeof(ICMP_ECHO_REPLY) + sizeof(bufRequest); + const std::unique_ptr bufRecv(new(char[responseSize])); + + // send echo + auto ret = IcmpSendEcho(this->hIcmpFile, addr, (LPVOID)bufRequest, sizeof(bufRequest), NULL, bufRecv.get(), responseSize, this->timeout); + + // ret == 0: failed + if (ret == 0) { + return std::pair(std::nullopt, "IcmpSendEcho returned error"); + } + + // read round-trip time + PICMP_ECHO_REPLY pReply = (PICMP_ECHO_REPLY) bufRecv.get(); + return std::pair(pReply->RoundTripTime, std::nullopt); +} From b92e933007d29c93c2fb3d2e92de4f5f22b640bf Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sat, 22 Feb 2020 16:16:09 +0800 Subject: [PATCH 049/332] Create SSDConverter.hpp --- src/core/connection/SSDConverter.hpp | 211 +++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 src/core/connection/SSDConverter.hpp diff --git a/src/core/connection/SSDConverter.hpp b/src/core/connection/SSDConverter.hpp new file mode 100644 index 00000000..d03329d4 --- /dev/null +++ b/src/core/connection/SSDConverter.hpp @@ -0,0 +1,211 @@ +#pragma once + +#include "base/Qv2rayBase.hpp" +#include "common/QvHelpers.hpp" + +namespace Qv2ray::core::handlers +{ + /** + * A Naive SSD Decoder for Qv2ray + * + * @author DuckSoft + * @copyright Licensed under GPLv3. + */ + namespace ssd + { + /** + * pattern for the nodes in ssd links. + * + * %1: airport name + * %2: node name + * %3: rate + */ + inline auto DEFAULT_NAME_PATTERN = "%1 - %2 (rate %3)"; + + /** + * @brief decodeSSD + * @param uri the uri of ssd link. + * @param pattern the pattern for node names. + * @return tuple of: + * - tuple of: + * - airport name (for the sake of grouping) + * - shadowsocks configuration list + * - log list + * in case of error, no objects will be returned. + */ + std::pair >>>, QStringList> + decodeSSD(const QString &uri, const QString &pattern = DEFAULT_NAME_PATTERN); + } +} + +#define MUST_EXIST(fieldName) \ + if (obj[(fieldName)].isUndefined()) {\ + logList << QObject::tr("invalid ssd link: json: field %1 must exist").arg(fieldName);\ + return std::make_pair(std::nullopt, logList);\ + } +#define MUST_PORT(fieldName) MUST_EXIST(fieldName);\ + if (int value = obj[(fieldName)].toInt(-1); value < 0 || value > 65535) { \ + logList << QObject::tr("invalid ssd link: json: field %1 must be valid port number");\ + return std::make_pair(std::nullopt, logList);\ + } +#define MUST_STRING(fieldName) MUST_EXIST(fieldName);\ + if (!obj[(fieldName)].isString()) {\ + logList << QObject::tr("invalid ssd link: json: field %1 must be of type 'string'").arg(fieldName);\ + return std::make_pair(std::nullopt, logList);\ + } +#define MUST_ARRAY(fieldName) MUST_EXIST(fieldName);\ + if (!obj[(fieldName)].isArray()) {\ + logList << QObject::tr("invalid ssd link: json: field %1 must be an array").arg(fieldName);\ + return std::make_pair(std::nullopt, logList);\ + } + +#define SERVER_SHOULD_BE_OBJECT(server) \ + if (!server.isObject()) {\ + logList << QObject::tr("skipping invalid ssd server: server must be an object");\ + continue;\ + } +#define SHOULD_EXIST(fieldName) \ + if (serverObject[(fieldName)].isUndefined()) { \ + logList << QObject::tr("skipping invalid ssd server: missing required field %1").arg(fieldName);\ + continue;\ + } +#define SHOULD_STRING(fieldName) SHOULD_EXIST(fieldName); \ + if (!serverObject[(fieldName)].isString()) { \ + logList << QObject::tr("skipping invalid ssd server: field %1 should be of type 'string'").arg(fieldName);\ + continue; \ + } + + +std::pair >>>, QStringList> +Qv2ray::core::handlers::ssd::decodeSSD(const QString &uri, const QString &pattern) +{ + // The list for the parsing log. + QStringList logList; + + // ssd links should begin with "ssd://" + if (!uri.startsWith("ssd://")) { + logList << QObject::tr("invalid ssd link: should begin with ssd://"); + return std::make_pair(std::nullopt, logList); + } + + // decode base64 + const auto ssdURIBody = QStringRef(&uri, 5, uri.length() - 6); + const auto decodedJSON = QByteArray::fromBase64(ssdURIBody.toUtf8()); + + if (decodedJSON.length() == 0) { + logList << QObject::tr("invalid ssd link: base64 parse failed"); + return std::make_pair(std::nullopt, logList); + } + + // parse json + QJsonParseError err; + QJsonDocument document = QJsonDocument::fromJson(decodedJSON, &err); + + if (document.isNull()) { + logList << QObject::tr("invalid ssd link: json parse failed: ") % err.errorString(); + return std::make_pair(std::nullopt, logList); + } + + // json should be an object + if (!document.isObject()) { + logList << QObject::tr("invalid ssd link: found non-object json, aborting"); + return std::make_pair(std::nullopt, logList); + } + + // casting to object + QJsonObject obj = document.object(); + // + // obj.airport + MUST_STRING("airport"); + const QString airport = obj["airport"].toString(); + // obj.port + MUST_PORT("port"); + const int port = obj["port"].toInt(); + // obj.encryption + MUST_STRING("encryption"); + const QString encryption = obj["encryption"].toString(); + + // check: rc4-md5 is not supported by v2ray-core + // TODO: more checks, including all algorithms + if (encryption == "rc4-md5") { + logList << QObject::tr("invalid ssd link: rc4-md5 encryption is not supported by v2ray-core"); + return std::make_pair(std::nullopt, logList); + } + + // obj.password + MUST_STRING("password"); + const QString password = obj["password"].toString(); + // obj.servers + MUST_ARRAY("servers"); + // + QList> serverList; + // + + // iterate through the servers + for (QJsonValueRef server : obj["servers"].toArray()) { + SERVER_SHOULD_BE_OBJECT(server); + QJsonObject serverObject = server.toObject(); + ShadowSocksServerObject ssObject; + // encryption + ssObject.method = encryption; + // password + ssObject.password = password; + // address :-> "server" + SHOULD_STRING("server"); + const QString serverAddress = serverObject["server"].toString(); + ssObject.address = serverAddress; + + // port selection: + // normal: use global settings + // overriding: use current config + if (serverObject["port"].isUndefined()) { + ssObject.port = port; + } else if (auto currPort = serverObject["port"].toInt(-1); port >= 0 && port <= 65535) { + ssObject.port = currPort; + } else { + logList << QObject::tr("warning: invalid port encountered. using fallback value."); + ssObject.port = port; + } + + // name decision: + // untitled: using server:port as name + // entitled: using given name + QString nodeName; + + if (serverObject["remarks"].isUndefined()) { + nodeName = QString("%1:%2").arg(ssObject.address).arg(ssObject.port); + } else if (serverObject["remarks"].isString()) { + nodeName = serverObject["remarks"].toString(); + } else { + logList << QObject::tr("warning: invalid name encountered. using fallback value."); + nodeName = QString("%1:%2").arg(ssObject.address).arg(ssObject.port); + } + + // ratio decision: + // unspecified: ratio = 1 + // specified: use given value + double ratio = 1.0; + + if (auto currRatio = serverObject["ratio"].toDouble(-1.0); currRatio != -1.0) { + ratio = currRatio; + } else if (!serverObject["ratio"].isUndefined()) { + logList << QObject::tr("warning: invalid ratio encountered. using fallback value."); + } + + // format the total name of the node. + const QString totalName = pattern.arg(airport, nodeName).arg(ratio); + // appending to the total list + serverList.append(make_pair(totalName, ssObject)); + } + + // returns the current result + return std::make_pair(std::make_pair(airport, serverList), logList); +} + +#undef MUST_EXIST +#undef MUST_PORT +#undef MUST_ARRAY +#undef MUST_STRING +#undef SERVER_SHOULD_BE_OBJECT +#undef SHOULD_EXIST +#undef SHOULD_STRING From 784e995dbf5080d9fddf80eda75041478087e2a9 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sat, 22 Feb 2020 22:54:51 +0800 Subject: [PATCH 050/332] make default name pattern translatable --- src/core/connection/SSDConverter.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/connection/SSDConverter.hpp b/src/core/connection/SSDConverter.hpp index d03329d4..40d948e0 100644 --- a/src/core/connection/SSDConverter.hpp +++ b/src/core/connection/SSDConverter.hpp @@ -20,7 +20,7 @@ namespace Qv2ray::core::handlers * %2: node name * %3: rate */ - inline auto DEFAULT_NAME_PATTERN = "%1 - %2 (rate %3)"; + inline auto DEFAULT_NAME_PATTERN = QString::tr("%1 - %2 (rate %3)"); /** * @brief decodeSSD From 3430a2a1e1fdaf8b297cc306f3bab1adcbdd7607 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Wed, 26 Feb 2020 11:40:04 +0800 Subject: [PATCH 051/332] Enable destructive mode. --- .travis.yml | 23 +++++++++++++++-------- snap/snapcraft.yaml | 22 ++-------------------- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1a170a22..65abe4fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,11 @@ language: bash dist: bionic +arch: + - amd64 + - arm64 +os: linux + git: depth: false @@ -15,16 +20,18 @@ env: addons: snaps: - - name: snapcraft - channel: stable - confinement: classic - - name: lxd - channel: stable + - name: snapcraft + channel: stable + confinement: classic + apt: + update: true + sources: + - sourceline: 'ppa:ymshenyu/grpc-1' + - sourceline: 'deb http://archive.neon.kde.org/unstable bionic main' + key_url: 'http://archive.neon.kde.org/public.key' script: - - sudo apt autoremove lxd --purge - - sudo /snap/bin/lxd init --auto - - sudo snapcraft --use-lxd + - sudo snapcraft --destructive-mode after_failure: - sudo journalctl -u snapd diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 9f4f657e..84bc147d 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -80,7 +80,6 @@ parts: snapcraftctl set-version "$version" sed -i 's|^Icon=.*|Icon=/usr/share/icons/hicolor/256x256/apps/qv2ray.png|g' assets/qv2ray.desktop after: - - mytools - desktop-qt5 desktop-qt5: @@ -107,25 +106,8 @@ parts: - locales-all - xdg-user-dirs - fcitx-frontend-qt5 - after: - - mytools - + qt5-gtk-platform: plugin: nil stage-packages: - - qt5-gtk-platformtheme - after: - - mytools - - mytools: - plugin: nil - build-packages: - - dirmngr - override-build: | - echo 'deb http://archive.neon.kde.org/unstable bionic main' > /etc/apt/sources.list.d/neon.list - echo 'deb http://ppa.launchpad.net/ymshenyu/grpc-1/ubuntu bionic main' >> /etc/apt/sources.list.d/tools.list - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E6D4736255751E5D - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 281f24e574404629aa3bda1a4f10c386c55cdb04 - sudo apt update - sudo apt dist-upgrade -y - snapcraftctl build \ No newline at end of file + - qt5-gtk-platformtheme \ No newline at end of file From ae9a883076b0e18d8c7eb5e4bd974bcdda526626 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Wed, 26 Feb 2020 12:13:27 +0800 Subject: [PATCH 052/332] update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 65abe4fd..e1f632fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,7 @@ addons: key_url: 'http://archive.neon.kde.org/public.key' script: - - sudo snapcraft --destructive-mode + - snapcraft --destructive-mode after_failure: - sudo journalctl -u snapd From a4754eccdfc2585eb58c344a2c4cf3643ea935c7 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 26 Feb 2020 17:30:49 +0800 Subject: [PATCH 053/332] Resolved conflict... ...In a not only quite straightforward but also extremely hacky method. --- makespec/03-Windows.pri | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/makespec/03-Windows.pri b/makespec/03-Windows.pri index 524a2dba..b97605e8 100644 --- a/makespec/03-Windows.pri +++ b/makespec/03-Windows.pri @@ -3,6 +3,14 @@ message("Configuring for Windows environment") QMAKE_CXXFLAGS += /MP /wo4251 DEFINES += QHTTPSERVER_EXPORT +!has_std_byte { + message("WARN: c++17 std::byte is disabled") + DEFINES += _HAS_STD_BYTE=0 +} else { + message("WARN: You are playing with a conflict between c++17 std::byte and Windows.h typedef byte") + message(" --> Be careful and good luck") +} + CONFIG += Qv2ray_Windows use_grpc !contains(QMAKE_TARGET.arch, x86_64) { CONFIG+=Qv2ray_win32 From f339b814e10306423fb2b6d65e153b218a185c95 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 26 Feb 2020 17:42:18 +0800 Subject: [PATCH 054/332] fix: some minor fixes --- makespec/BUILDVERSION | 2 +- src/core/tcping/QvTCPing.cpp | 6 ++---- src/ui/w_MainWindow.cpp | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 0130643d..8af762b8 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3961 +3963 diff --git a/src/core/tcping/QvTCPing.cpp b/src/core/tcping/QvTCPing.cpp index 67964d77..d6cc9642 100644 --- a/src/core/tcping/QvTCPing.cpp +++ b/src/core/tcping/QvTCPing.cpp @@ -141,7 +141,6 @@ namespace Qv2ray::core::tcping #else int fd; #endif - int connect_result; const int on = 1; /* int flags; */ int rv = 0; @@ -169,12 +168,11 @@ namespace Qv2ray::core::tcping } *start = system_clock::now(); + /* connect to peer */ // Qt has its own connect() function in QObject.... // So we add "::" here - connect_result = ::connect(fd, addr->ai_addr, addr->ai_addrlen); - - if (connect_result == 0) { + if (::connect(fd, addr->ai_addr, addr->ai_addrlen) == 0) { *end = system_clock::now(); #ifdef _WIN32 closesocket(fd); diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 4b4209ec..435601f8 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -842,7 +842,7 @@ void MainWindow::onConnectionStatsArrived(const ConnectionId &id, const quint64 netspeedLabel->setText(totalSpeedUp + NEWLINE + totalSpeedDown); dataamountLabel->setText(totalDataUp + NEWLINE + totalDataDown); // - hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + id.toString() + NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); + hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + ConnectionManager->GetDisplayName(id) + NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); } void MainWindow::onVCoreLogArrived(const ConnectionId &id, const QString &log) From b03849d9dfff0f39edb360e09b11af574a6cb2cd Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 26 Feb 2020 20:21:57 +0800 Subject: [PATCH 055/332] add: added connection edit feature --- makespec/03-unix.pri | 6 +- makespec/BUILDVERSION | 2 +- src/common/HTTPRequestHelper.cpp | 5 + src/common/QvHelpers.cpp | 18 +-- src/common/QvHelpers.hpp | 3 +- src/core/CoreUtils.cpp | 32 ++++- src/core/CoreUtils.hpp | 3 +- src/core/config/ConfigBackend.cpp | 3 +- src/core/connection/ConnectionIO.cpp | 6 - src/core/handler/ConnectionHandler.cpp | 39 ++---- src/core/handler/ConnectionHandler.hpp | 6 +- src/core/kernel/KernelInteractions.cpp | 3 +- src/ui/editors/w_RoutesEditor.cpp | 3 +- src/ui/w_ImportConfig.cpp | 2 +- src/ui/w_MainWindow.cpp | 152 ++++++++++-------------- src/ui/w_MainWindow.hpp | 2 + src/ui/w_PreferencesWindow.cpp | 3 +- src/ui/w_SubscriptionManager.cpp | 31 +++-- src/ui/widgets/ConnectionInfoWidget.cpp | 34 ++---- src/ui/widgets/ConnectionInfoWidget.hpp | 6 +- 20 files changed, 164 insertions(+), 195 deletions(-) diff --git a/makespec/03-unix.pri b/makespec/03-unix.pri index 3102aaf6..097ff088 100644 --- a/makespec/03-unix.pri +++ b/makespec/03-unix.pri @@ -15,8 +15,10 @@ INCLUDEPATH += /usr/local/include/ message(" --> Linking against protobuf library.") LIBS += -L/usr/local/lib -lprotobuf -message(" --> Generating geosite headers for Unix") -system("$$PWD/../tools/unix-generate-geosite.sh $$PWD") +!no_generate_headers { + message(" --> Generating geosite headers for Unix") + system("$$PWD/../tools/unix-generate-geosite.sh $$PWD") +} use_grpc { no_generate_headers { diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 8af762b8..6b2af3f8 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3963 +3986 diff --git a/src/common/HTTPRequestHelper.cpp b/src/common/HTTPRequestHelper.cpp index 467a2a82..dbf2856d 100644 --- a/src/common/HTTPRequestHelper.cpp +++ b/src/common/HTTPRequestHelper.cpp @@ -46,6 +46,7 @@ namespace Qv2ray::common } request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); + request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true); request.setHeader(QNetworkRequest::KnownHeaders::UserAgentHeader, "Mozilla/5.0 (rv:71.0) Gecko/20100101 Firefox/71.0"); reply = accessManager.get(request); connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished_p); @@ -105,6 +106,10 @@ namespace Qv2ray::common void QvHttpRequestHelper::onRequestFinished_p() { + if (reply->attribute(QNetworkRequest::HTTP2WasUsedAttribute).toBool()) { + DEBUG(MODULE_NETWORK, "HTTP/2 was used.") + } + if (reply->error() != QNetworkReply::NoError) { QString error = QMetaEnum::fromType().key(reply->error()); LOG(MODULE_NETWORK, "Network request error string: " + error) diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 05728876..7df5bd45 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -31,15 +31,19 @@ namespace Qv2ray::common source->close(); return str; } - - bool StringToFile(const QString *text, QFile *targetFile) + bool StringToFile(const QString &text, const QString &targetpath) { - bool override = targetFile->exists(); - targetFile->open(QFile::WriteOnly); - QTextStream stream(targetFile); - stream << *text << endl; + auto file = QFile(targetpath); + return StringToFile(text, file); + } + bool StringToFile(const QString &text, QFile &targetFile) + { + bool override = targetFile.exists(); + targetFile.open(QFile::WriteOnly); + QTextStream stream(&targetFile); + stream << text << endl; stream.flush(); - targetFile->close(); + targetFile.close(); return override; } diff --git a/src/common/QvHelpers.hpp b/src/common/QvHelpers.hpp index c89cce37..6d8d818b 100644 --- a/src/common/QvHelpers.hpp +++ b/src/common/QvHelpers.hpp @@ -23,7 +23,8 @@ namespace Qv2ray::common // QString StringFromFile(const QString &filePath); QString StringFromFile(QFile *source); - bool StringToFile(const QString *text, QFile *target); + bool StringToFile(const QString &text, QFile &target); + bool StringToFile(const QString &text, const QString &targetpath); // QJsonObject JsonFromString(QString string); QString JsonToString(QJsonObject json, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented); diff --git a/src/core/CoreUtils.cpp b/src/core/CoreUtils.cpp index 22a7f3c3..ba9cd913 100644 --- a/src/core/CoreUtils.cpp +++ b/src/core/CoreUtils.cpp @@ -1,8 +1,9 @@ #include "CoreUtils.hpp" +#include "common/QvHelpers.hpp" namespace Qv2ray::core { - bool IsComplexConfig(CONFIGROOT root) + bool IsComplexConfig(const CONFIGROOT &root) { bool cRouting = root.contains("routing"); bool cRule = cRouting && root["routing"].toObject().contains("rules"); @@ -15,5 +16,34 @@ namespace Qv2ray::core bool cOutboundCount = cOutbounds && root["outbounds"].toArray().count() > 1; return cRules || cInboundCount || cOutboundCount; } + + bool GetOutboundData(const OUTBOUND &out, QString *host, int *port, QString *protocol) + { + // Set initial values. + *host = QObject::tr("N/A"); + *port = 0; + *protocol = out["protocol"].toString(QObject::tr("N/A")).toLower(); + + if (*protocol == "vmess") { + auto Server = StructFromJsonString(JsonToString(out["settings"].toObject()["vnext"].toArray().first().toObject())); + *host = Server.address; + *port = Server.port; + return true; + } else if (*protocol == "shadowsocks") { + auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject()); + auto Server = StructFromJsonString(x); + *host = Server.address; + *port = Server.port; + return true; + } else if (*protocol == "socks") { + auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject()); + auto Server = StructFromJsonString(x); + *host = Server.address; + *port = Server.port; + return true; + } else { + return false; + } + } } diff --git a/src/core/CoreUtils.hpp b/src/core/CoreUtils.hpp index d0284b23..06e59652 100644 --- a/src/core/CoreUtils.hpp +++ b/src/core/CoreUtils.hpp @@ -24,7 +24,8 @@ namespace Qv2ray::core return in.QV2RAY_RULE_TAG; } - bool IsComplexConfig(CONFIGROOT root); + bool GetOutboundData(const OUTBOUND &out, QString *host, int *port, QString *protocol); + bool IsComplexConfig(const CONFIGROOT &root); } using namespace Qv2ray::core; diff --git a/src/core/config/ConfigBackend.cpp b/src/core/config/ConfigBackend.cpp index 18cf0f35..b3406fd0 100644 --- a/src/core/config/ConfigBackend.cpp +++ b/src/core/config/ConfigBackend.cpp @@ -6,9 +6,8 @@ namespace Qv2ray::core::config void SaveGlobalConfig(const Qv2rayConfig &conf) { GlobalConfig = conf; - QFile config(QV2RAY_CONFIG_FILE); QString str = StructToJsonString(conf); - StringToFile(&str, &config); + StringToFile(str, QV2RAY_CONFIG_FILE); } void SetConfigDirPath(const QString &path) diff --git a/src/core/connection/ConnectionIO.cpp b/src/core/connection/ConnectionIO.cpp index 6c14f0a3..d153d653 100644 --- a/src/core/connection/ConnectionIO.cpp +++ b/src/core/connection/ConnectionIO.cpp @@ -5,12 +5,6 @@ namespace Qv2ray::core::connection { namespace ConnectionIO { - - //CONFIGROOT GetConnectionRoot(const SubscriptionId &subscription, const ConnectionId &id) - //{ - // return ReadConnectionInternal(QV2RAY_SUBSCRIPTION_DIR + subscription.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION); - //} - //// //// Save Connection to a place, with checking if there's existing file. //// If so, append "_N" to the name. diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index 0436fd35..234520a3 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -284,7 +284,6 @@ namespace Qv2ray::core::handlers path.prepend(groups[group].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR); return CONFIGROOT(JsonFromString(StringFromFile(path))); } - // const tuple QvConnectionHandler::GetConnectionInfo(const ConnectionId &id) const { @@ -296,7 +295,7 @@ namespace Qv2ray::core::handlers for (auto item : root["outbounds"].toArray()) { OUTBOUND outBoundRoot = OUTBOUND(item.toObject()); QString outboundType = ""; - validOutboundFound = CHGetOutboundData_p(outBoundRoot, &host, &port); + validOutboundFound = GetOutboundData(outBoundRoot, &host, &port, &outboundType); if (validOutboundFound) { return make_tuple(host, port); @@ -308,34 +307,7 @@ namespace Qv2ray::core::handlers return make_tuple(QObject::tr("N/A"), 0); } - bool QvConnectionHandler::CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port) const - { - // Set initial values. - *host = QObject::tr("N/A"); - *port = 0; - auto protocol = out["protocol"].toString(QObject::tr("N/A")).toLower(); - if (protocol == "vmess") { - auto Server = StructFromJsonString(JsonToString(out["settings"].toObject()["vnext"].toArray().first().toObject())); - *host = Server.address; - *port = Server.port; - return true; - } else if (protocol == "shadowsocks") { - auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject()); - auto Server = StructFromJsonString(x); - *host = Server.address; - *port = Server.port; - return true; - } else if (protocol == "socks") { - auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject()); - auto Server = StructFromJsonString(x); - *host = Server.address; - *port = Server.port; - return true; - } else { - return false; - } - } void QvConnectionHandler::OnLatencyDataArrived(const QvTCPingResultObject &result) { @@ -346,4 +318,13 @@ namespace Qv2ray::core::handlers LOG(MODULE_CORE_HANDLER, "Received a latecy result with non-exist connection id.") } } + + bool QvConnectionHandler::UpdateConnection(const ConnectionId &id, const CONFIGROOT &root) + { + auto groupId = connections[id].groupId; + auto path = (groups[groupId].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR) + + groupId.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; + auto content = JsonToString(root); + return StringToFile(content, path); + } } diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 10456a30..2ee80d61 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -5,6 +5,7 @@ #include "core/tcping/QvTCPing.hpp" #include "core/CoreSafeTypes.hpp" #include "core/connection/ConnectionIO.hpp" +#include "core/CoreUtils.hpp" namespace Qv2ray::core::handlers { @@ -37,7 +38,7 @@ namespace Qv2ray::core::handlers double GetConnectionLatency(const ConnectionId &id) const; const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); const optional DeleteConnection(const ConnectionId &id); - const optional UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); + bool UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); const optional RenameConnection(const ConnectionId &id, const QString &newName); const ConnectionId DuplicateConnection(const ConnectionId &id); const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); @@ -101,7 +102,6 @@ namespace Qv2ray::core::handlers private: void CHSaveConnectionData_p(); // - bool CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port) const; optional CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); void CHStopConnection_p(); bool CHSaveConnectionConfig_p(CONFIGROOT obj, const ConnectionId &id, bool override); @@ -112,7 +112,7 @@ namespace Qv2ray::core::handlers int pingConnectionTimerId; QHash groups; QHash connections; - QHash connectionRootCache; + //QHash connectionRootCache; private: QvTCPingHelper *tcpingHelper; diff --git a/src/core/kernel/KernelInteractions.cpp b/src/core/kernel/KernelInteractions.cpp index 5725d33b..ee08ce02 100644 --- a/src/core/kernel/KernelInteractions.cpp +++ b/src/core/kernel/KernelInteractions.cpp @@ -147,8 +147,7 @@ namespace Qv2ray::core::kernel // Write the final configuration to the disk. QString json = JsonToString(root); - QFile configFile(QV2RAY_GENERATED_FILE_PATH); - StringToFile(&json, &configFile); + StringToFile(json, QV2RAY_GENERATED_FILE_PATH); // auto filePath = QV2RAY_GENERATED_FILE_PATH; diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index 7d028706..a68b6586 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -157,8 +157,7 @@ void RouteEditor::onNodeClicked(Node &n) alias = GetFirstNodeData(n, QvOutboundNodeModel, OutboundNodeData)->GetOutbound(); QJsonObject _root = outbounds[alias].raw(); throw new runtime_error("Not implemented"); - //auto result = GetOutboundData(OUTBOUND(_root), &host, &port, &protocol); - //Q_UNUSED(result) + GetOutboundData(OUTBOUND(_root), &host, &port, &protocol); } else { alias = GetFirstNodeData(n, QvInboundNodeModel, InboundNodeData)->GetInbound(); QJsonObject _root = inbounds[alias].raw(); diff --git a/src/ui/w_ImportConfig.cpp b/src/ui/w_ImportConfig.cpp index c3551b2e..e9097a85 100644 --- a/src/ui/w_ImportConfig.cpp +++ b/src/ui/w_ImportConfig.cpp @@ -232,7 +232,7 @@ void ImportConfigWindow::on_editFileBtn_clicked() if (editor.result() == QDialog::Accepted) { auto str = JsonToString(json); - bool result = StringToFile(&str, &file); + bool result = StringToFile(str, file); if (!result) { QvMessageBoxWarn(this, tr("Edit file as JSON"), tr("Failed to save file, please check if you have proper permissions")); diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 435601f8..0542c86a 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -74,12 +74,6 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr { setupUi(this); MainWindow::mwInstance = this; - connect(ConnectionManager, &QvConnectionHandler::OnCrashed, [&] { - this->show(); - QvMessageBoxWarn(this, tr("V2ray vcore terminated."), - tr("V2ray vcore terminated unexpectedly.") + NEWLINE + NEWLINE + - tr("To solve the problem, read the V2ray log in the log text browser.")); - }); QvMessageBusConnect(MainWindow); // infoWidget = new ConnectionInfoWidget(this); @@ -98,11 +92,20 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr updownImageBox_2->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); // // + connect(ConnectionManager, &QvConnectionHandler::OnCrashed, [&] { + this->show(); + QvMessageBoxWarn(this, tr("V2ray vcore terminated."), + tr("V2ray vcore terminated unexpectedly.") + NEWLINE + NEWLINE + + tr("To solve the problem, read the V2ray log in the log text browser.")); + }); connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &MainWindow::OnConnected); connect(ConnectionManager, &QvConnectionHandler::OnDisConnected, this, &MainWindow::OnDisConnected); connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &MainWindow::onConnectionStatsArrived); connect(ConnectionManager, &QvConnectionHandler::OnVCoreLogAvailable, this, &MainWindow::onVCoreLogArrived); // + connect(infoWidget, &ConnectionInfoWidget::OnEditRequested, this, &MainWindow::OnEditRequested); + connect(infoWidget, &ConnectionInfoWidget::OnJsonEditRequested, this, &MainWindow::OnJsonEditRequested); + // // Setup System tray icons and menus hTray.setToolTip(TRAY_TOOLTIP_PREFIX); // Basic actions @@ -201,10 +204,7 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr if (!GlobalConfig.autoStartId.isEmpty()) { auto id = ConnectionId(GlobalConfig.autoStartId); - ConnectionManager->StartConnection(id); - needShowWindow = !ConnectionManager->IsConnected(id); - } else { - needShowWindow = true; + needShowWindow = ConnectionManager->StartConnection(id).has_value(); } if (needShowWindow) { @@ -212,6 +212,9 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr } //// If we are not connected to anything, show the MainWindow. + if (needShowWindow) { + } + #ifndef DISABLE_AUTO_UPDATE requestHelper = new QvHttpRequestHelper(); connect(requestHelper, &QvHttpRequestHelper::httpRequestFinished, this, &MainWindow::VersionUpdate); @@ -298,24 +301,6 @@ MainWindow::~MainWindow() hTray.hide(); } -//void MainWindow::on_stopButton_clicked() -//{ -// //hTray.setToolTip(TRAY_TOOLTIP_PREFIX); -// //statusLabel->setText(tr("Disconnected")); -// action_Tray_Start->setEnabled(true); -// action_Tray_Stop->setEnabled(false); -// action_Tray_Reconnect->setEnabled(false); -// // Set to false as the system proxy has been cleared in the StopConnection function. -// tray_SystemProxyMenu->setEnabled(false); -// //startButton->setEnabled(true); -// //stopButton->setEnabled(false); -// //// -// //netspeedLabel->setText("0.00 B/s\r\n0.00 B/s"); -// //dataamountLabel->setText("0.00 B\r\n0.00 B"); -// //LOG(UI, "Stopped successfully.") -// //this->hTray.showMessage("Qv2ray", tr("Disconnected from: ") + CurrentConnectionIdentifier.IdentifierString()); -//} - void MainWindow::closeEvent(QCloseEvent *event) { this->hide(); @@ -579,50 +564,6 @@ void MainWindow::on_importConfigButton_clicked() } void MainWindow::on_editConfigButton_clicked() { - //// Check if we have a connection selected... - //if (!IsSelectionConnectable) { - // QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a Config")); - // return; - //} - // - //auto firstSelected = connectionListWidget->selectedItems().first(); - //auto _identifier = ItemConnectionIdentifier(firstSelected); - //SUBSCRIPTION_CONFIG_MODIFY_ASK(firstSelected) - //// - //auto outBoundRoot = connections[_identifier].config; - //CONFIGROOT root; - //bool isChanged = false; - // - //if (IsComplexConfig(outBoundRoot)) { - // LOG(UI, "INFO: Opening route editor.") - // RouteEditor routeWindow(outBoundRoot, this); - // root = routeWindow.OpenEditor(); - // isChanged = routeWindow.result() == QDialog::Accepted; - //} else { - // LOG(UI, "INFO: Opening single connection edit window.") - // OutboundEditor w(OUTBOUND(outBoundRoot["outbounds"].toArray().first().toObject()), this); - // auto outboundEntry = w.OpenEditor(); - // isChanged = w.result() == QDialog::Accepted; - // QJsonArray outboundsList; - // outboundsList.push_back(outboundEntry); - // root.insert("outbounds", outboundsList); - //} - // - //QString alias = _identifier.connectionName; - // - //if (isChanged) { - // if (CheckConfigType(firstSelected, SUBSCRIPTION)) { - // auto name = connections[_identifier].connectionName; - // // Assume name will not change. - // SaveSubscriptionConfig(root, connections[_identifier].subscriptionName, &name); - // } else { - // connections[_identifier].config = root; - // // true indicates the alias will NOT change - // SaveConnectionConfig(root, &alias, true); - // } - // - // OnConfigListChanged(alias == CurrentConnectionIdentifier.connectionName); - //} } void MainWindow::on_action_RCM_ConvToComplex_triggered() @@ -658,26 +599,6 @@ void MainWindow::on_action_RCM_ConvToComplex_triggered() void MainWindow::on_action_RCM_EditJson_triggered() { - //// Check if we have a connection selected... - //if (!IsSelectionConnectable) { - // QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a Config")); - // return; - //} - // - //auto selectedFirst = connectionListWidget->currentItem(); - //auto _identifier = ItemConnectionIdentifier(selectedFirst); - //SUBSCRIPTION_CONFIG_MODIFY_DENY(selectedFirst) - //JsonEditor w(connections[_identifier].config, this); - //auto root = CONFIGROOT(w.OpenEditor()); - //bool isChanged = w.result() == QDialog::Accepted; - //QString alias = _identifier.connectionName; - // - //if (isChanged) { - // connections[_identifier].config = root; - // // Alias here will not change. - // SaveConnectionConfig(root, &alias, true); - // ShowAndSetConnection(CurrentConnectionIdentifier, false, false); - //} } void MainWindow::on_action_RCM_ShareQR_triggered() @@ -871,3 +792,50 @@ void MainWindow::onVCoreLogArrived(const ConnectionId &id, const QString &log) if (val >= max * 0.8 || val >= max - 20) bar->setValue(max); } + + +void MainWindow::OnEditRequested(const ConnectionId &id) +{ + auto outBoundRoot = ConnectionManager->GetConnectionRoot(id); + CONFIGROOT root; + bool isChanged = false; + + if (IsComplexConfig(outBoundRoot)) { + LOG(MODULE_UI, "INFO: Opening route editor.") + RouteEditor routeWindow(outBoundRoot, this); + root = routeWindow.OpenEditor(); + isChanged = routeWindow.result() == QDialog::Accepted; + } else { + LOG(MODULE_UI, "INFO: Opening single connection edit window.") + auto out = OUTBOUND(outBoundRoot["outbounds"].toArray().first().toObject()); + OutboundEditor w(out, this); + auto outboundEntry = w.OpenEditor(); + isChanged = w.result() == QDialog::Accepted; + QJsonArray outboundsList; + outboundsList.push_back(outboundEntry); + root.insert("outbounds", outboundsList); + } + + if (isChanged) { + //if (CheckConfigType(firstSelected, SUBSCRIPTION)) { + // auto name = connections[_identifier].connectionName; + // // Assume name will not change. + // SaveSubscriptionConfig(root, connections[_identifier].subscriptionName, &name); + //} else { + // connections[_identifier].config = root; + // // true indicates the alias will NOT change + // SaveConnectionConfig(root, &alias, true); + //} + ConnectionManager->UpdateConnection(id, root); + //OnConfigListChanged(alias == CurrentConnectionIdentifier.connectionName); + } +} +void MainWindow::OnJsonEditRequested(const ConnectionId &id) +{ + JsonEditor w(ConnectionManager->GetConnectionRoot(id), this); + auto root = CONFIGROOT(w.OpenEditor()); + + if (w.result() == QDialog::Accepted) { + ConnectionManager->UpdateConnection(id, root); + } +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 650db1cf..2f417718 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -60,6 +60,8 @@ class MainWindow : public QMainWindow, Ui::MainWindow // void OnConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id); + void OnEditRequested(const ConnectionId &id); + void OnJsonEditRequested(const ConnectionId &id); void onConnectionWidgetFocusRequested(const ConnectionItemWidget *widget); //void onConnectionConnected(const ConnectionId &id); diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index c9b27315..88f1ddff 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -892,8 +892,7 @@ void PreferencesWindow::on_pacGoBtn_clicked() QDir(QV2RAY_RULES_DIR).mkpath(QV2RAY_RULES_DIR); } - QFile privateGFWListFile(QV2RAY_RULES_GFWLIST_PATH); - StringToFile(&fileContent, &privateGFWListFile); + StringToFile(fileContent, QV2RAY_RULES_GFWLIST_PATH); } void PreferencesWindow::on_pacPortSB_valueChanged(int arg1) diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index db46a766..a30ccfd7 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -120,7 +120,7 @@ void SubscribeEditor::on_updateButton_clicked() subscriptions[currentSubName].address = newAddress; } - SaveConfig(); + //SaveConfig(); if (QvMessageBoxAsk(this, tr("Update Subscription"), tr("Would you like to reload this subscription from the Url?")) == QMessageBox::Yes) { StartUpdateSubscription(currentSubName); @@ -129,10 +129,9 @@ void SubscribeEditor::on_updateButton_clicked() void SubscribeEditor::StartUpdateSubscription(const QString &subscriptionName) { - //this->setEnabled(false); - //auto data = helper.syncget(subscriptions[subscriptionName].address, withProxyCB->isChecked()); - //auto content = DecodeSubscriptionString(data).trimmed(); - // + this->setEnabled(false); + auto data = helper.syncget(subscriptions[subscriptionName].address, withProxyCB->isChecked()); + auto content = DecodeSubscriptionString(data).trimmed(); //if (!content.isEmpty()) { // connectionsList->clear(); // auto vmessList = SplitLines(content); @@ -160,7 +159,7 @@ void SubscribeEditor::StartUpdateSubscription(const QString &subscriptionName) // QvMessageBoxWarn(this, tr("Updating subscriptions"), tr("Failed to process the result from the upstream, please check your Url.")); //} // - //this->setEnabled(true); + this->setEnabled(true); } void SubscribeEditor::on_removeSubsButton_clicked() @@ -213,16 +212,16 @@ void SubscribeEditor::on_subscriptionList_currentRowChanged(int currentRow) void SubscribeEditor::SaveConfig() { - QMap newConf; - - for (auto _ : subscriptions.toStdMap()) { - if (!_.second.address.isEmpty()) { - newConf[_.first] = _.second; - } - } - - GlobalConfig.subscriptions = newConf; - SaveGlobalConfig(GlobalConfig); + //QMap newConf; + // + //for (auto _ : subscriptions.toStdMap()) { + // if (!_.second.address.isEmpty()) { + // newConf[_.first] = _.second; + // } + //} + // + //GlobalConfig.subscriptions = newConf; + //SaveGlobalConfig(GlobalConfig); } void SubscribeEditor::on_buttonBox_accepted() diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 7afdd5ea..5e3143b7 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -24,19 +24,19 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden { groupId = get<0>(_identifier); connectionId = get<1>(_identifier); + bool isConnection = connectionId != NullConnectionId; + editJsonBtn->setEnabled(isConnection); + connectBtn->setEnabled(isConnection); + duplicateBtn->setEnabled(isConnection); + editBtn->setEnabled(isConnection); - if (connectionId != NullConnectionId) { - //connNameLabel->setText(ConnectionManager->GetDisplayName(connectionId)); + if (isConnection) { groupLabel->setText(ConnectionManager->GetDisplayName(groupId, 175)); protocolLabel->setText(ConnectionManager->GetConnectionProtocolString(connectionId)); auto [host, port] = ConnectionManager->GetConnectionInfo(connectionId); addressLabel->setText(host); portLabel->setNum(port); // - editJsonBtn->setEnabled(true); - connectBtn->setEnabled(true); - duplicateBtn->setEnabled(true); - // auto shareLink = ConvertConfigToString(connectionId); shareLinkTxt->setText(shareLink); shareLinkTxt->setCursorPosition(0); @@ -55,10 +55,6 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden addressLabel->setText(tr("N/A")); portLabel->setText(tr("N/A")); // - editJsonBtn->setEnabled(false); - connectBtn->setEnabled(false); - duplicateBtn->setEnabled(false); - // shareLinkTxt->clear(); qrLabel->clear(); } @@ -76,27 +72,15 @@ void ConnectionInfoWidget::on_connectBtn_clicked() ConnectionManager->StartConnection(connectionId); } } -//// Share QR -//if (!IsSelectionConnectable) { -// return; -//} -// -//auto _identifier = ItemConnectionIdentifier(connectionListWidget->currentItem()); -//auto root = connections[_identifier].config; -//auto type = get<2>(GetConnectionInfo(root)); -// -//if (!IsComplexConfig(root) && (type == "vmess" || type == "shadowsocks")) { -// ConfigExporter v(root, _identifier, this); -// v.OpenExport(); -//} else { -// QvMessageBoxWarn(this, tr("Share Connection"), tr("There're no support of sharing configs other than vmess and shadowsocks")); -//} + void ConnectionInfoWidget::on_editBtn_clicked() { + emit OnEditRequested(connectionId); } void ConnectionInfoWidget::on_editJsonBtn_clicked() { + emit OnJsonEditRequested(connectionId); } void ConnectionInfoWidget::on_deleteBtn_clicked() diff --git a/src/ui/widgets/ConnectionInfoWidget.hpp b/src/ui/widgets/ConnectionInfoWidget.hpp index 00b5f5c6..968b88e1 100644 --- a/src/ui/widgets/ConnectionInfoWidget.hpp +++ b/src/ui/widgets/ConnectionInfoWidget.hpp @@ -13,6 +13,10 @@ class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget void ShowDetails(const tuple &_identifier); ~ConnectionInfoWidget(); + signals: + void OnEditRequested(const ConnectionId &id); + void OnJsonEditRequested(const ConnectionId &id); + private slots: void on_connectBtn_clicked(); void on_editBtn_clicked(); @@ -25,9 +29,7 @@ class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget private slots: void OnConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id); - void on_duplicateBtn_clicked(); - void on_latencyBtn_clicked(); private: From 54c4475fa9383e97c672c30494268c9a545fca12 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 26 Feb 2020 21:02:58 +0800 Subject: [PATCH 056/332] wip: add: added subscription display... --- makespec/BUILDVERSION | 2 +- src/core/handler/ConnectionHandler.cpp | 12 ++ src/core/handler/ConnectionHandler.hpp | 11 +- src/ui/w_SubscriptionManager.cpp | 218 +++++++++++-------------- src/ui/w_SubscriptionManager.hpp | 14 +- src/ui/w_SubscriptionManager.ui | 11 +- 6 files changed, 125 insertions(+), 143 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 6b2af3f8..622a0fae 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3986 +3993 diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index 234520a3..a4a4608b 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -325,6 +325,18 @@ namespace Qv2ray::core::handlers auto path = (groups[groupId].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR) + groupId.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; auto content = JsonToString(root); + emit OnConnectionChanged(id); return StringToFile(content, path); } + + const tuple QvConnectionHandler::GetSubscriptionData(const GroupId &id) + { + tuple result; + + if (!groups[id].isSubscription) { + return result; + } + + return make_tuple(groups[id].address, groups[id].lastUpdated, groups[id].updateInterval); + } } diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 2ee80d61..263ed509 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -6,6 +6,7 @@ #include "core/CoreSafeTypes.hpp" #include "core/connection/ConnectionIO.hpp" #include "core/CoreUtils.hpp" +#include "common/HTTPRequestHelper.hpp" namespace Qv2ray::core::handlers { @@ -63,8 +64,9 @@ namespace Qv2ray::core::handlers const optional RenameGroup(const GroupId &id, const QString &newName); // // Subscriptions - const optional UpdateSubscription(const GroupId &id); - const optional UpdateSubscriptionASync(const GroupId &id); + const optional UpdateSubscription(const GroupId &id, bool useSystemProxy); + const optional UpdateSubscriptionASync(const GroupId &id, bool useSystemProxy); + const tuple GetSubscriptionData(const GroupId &id); signals: void OnCrashed(); @@ -87,8 +89,8 @@ namespace Qv2ray::core::handlers void OnGroupRenamed(const GroupId &id, const QString &oldName, const QString &newName); void OnGroupDeleted(const GroupId &id, const QString &displayName); // - void OnSubscriptionCreated(const GroupId &id, const QString &displayName, const QString &address); - void OnSubscriptionDeleted(const GroupId &id, const QString &oldName, const QString &newName); + //void OnSubscriptionCreated(const GroupId &id, const QString &displayName, const QString &address); + //void OnSubscriptionDeleted(const GroupId &id, const QString &oldName, const QString &newName); void OnSubscriptionUpdateFinished(const GroupId &id); private slots: @@ -115,6 +117,7 @@ namespace Qv2ray::core::handlers //QHash connectionRootCache; private: + QvHttpRequestHelper *httpHelper; QvTCPingHelper *tcpingHelper; // We only support one cuncurrent connection currently. #ifdef QV2RAY_MULTIPlE_ONNECTION diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index a30ccfd7..2952edc4 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -1,8 +1,7 @@ #include "w_SubscriptionManager.hpp" #include "common/QvHelpers.hpp" #include "core/config/ConfigBackend.hpp" -#include "core/connection/ConnectionIO.hpp" -#include "core/connection/Serialization.hpp" +#include "core/handler/ConnectionHandler.hpp" SubscribeEditor::SubscribeEditor(QWidget *parent) : QDialog(parent) @@ -12,11 +11,9 @@ SubscribeEditor::SubscribeEditor(QWidget *parent) : addSubsButton->setIcon(QICON_R("add.png")); removeSubsButton->setIcon(QICON_R("delete.png")); - for (auto i = GlobalConfig.subscriptions.begin(); i != GlobalConfig.subscriptions.end(); i++) { - subscriptions[i.key()] = i.value(); + for (auto subs : ConnectionManager->Subscriptions()) { + subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList() << ConnectionManager->GetDisplayName(subs) << subs.toString())); } - - LoadSubscriptionList(subscriptions); } QvMessageBusSlotImpl(SubscribeEditor) @@ -30,20 +27,7 @@ QvMessageBusSlotImpl(SubscribeEditor) QPair SubscribeEditor::GetSelectedConfig() { - return currentSelectedConfig; -} - -void SubscribeEditor::LoadSubscriptionList(QMap list) -{ - subscriptionList->clear(); - - for (auto i = 0; i < list.count(); i++) { - subscriptionList->addItem(list.keys()[i]); - } - - if (subscriptionList->count() > 0) { - subscriptionList->setCurrentRow(0); - } + return QPair (); } SubscribeEditor::~SubscribeEditor() @@ -52,86 +36,85 @@ SubscribeEditor::~SubscribeEditor() void SubscribeEditor::on_addSubsButton_clicked() { - auto const key = QSTRN(QTime::currentTime().msecsSinceStartOfDay()); - subscriptionList->addItem(key); - subscriptions[key].address = "http://example.com/myfile"; - QDir().mkpath(QV2RAY_SUBSCRIPTION_DIR + key); - subscriptionList->setCurrentRow(subscriptions.count() - 1); - SaveConfig(); + // auto const key = QSTRN(QTime::currentTime().msecsSinceStartOfDay()); + // subscriptionList->addItem(key); + // subscriptions[key].address = "https://example.com/myfile"; + // QDir().mkpath(QV2RAY_SUBSCRIPTION_DIR + key); + // subscriptionList->setCurrentRow(subscriptions.count() - 1); + // SaveConfig(); } void SubscribeEditor::on_updateButton_clicked() { - auto newName = subNameTxt->text().trimmed(); - auto newAddress = subAddrTxt->text().trimmed(); - auto newUpdateInterval = updateIntervalSB->value(); - - if (currentSubName != newName) { - // Rename needed. - LOG(MODULE_SUBSCRIPTION, "Renaming a subscription, from " + currentSubName + " to: " + newName) - bool canGo = true; - - if (newName.isEmpty() || !IsValidFileName(newName)) { - QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("The subscription name is invalid, please try another.")); - canGo = false; - } - - if (subscriptionList->findItems(newName, Qt::MatchExactly).count() > 0) { - QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("New name of this subscription has been used already, please suggest another one")); - canGo = false; - } - - if (!canGo) { - subNameTxt->setText(currentSubName); - return; - } - - ////bool result = RenameSubscription(currentSubName, newName); - // - //if (!result) { - // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("Failed to rename a subscription, this is an unknown error.")); - // return; - //} - subscriptions[newName] = subscriptions[currentSubName]; - subscriptions.remove(currentSubName); - subNameTxt->setText(newName); - // - QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - // Update auto-start config if possible - //auto ASsetting = GlobalConfig.autoStartConfig.subscriptionName; - // - //if (ASsetting == currentSubName) { - // GlobalConfig.autoStartConfig.subscriptionName = newName; - //} - SaveGlobalConfig(GlobalConfig); - // This will set the name to the new name. - LoadSubscriptionList(subscriptions); - // Keep subAddress && Interval changes - // Update thing still down - subAddrTxt->setText(newAddress); - updateIntervalSB->setValue(newUpdateInterval); - QvMessageBoxInfo(this, tr("Renaming a subscription"), tr("Successfully renamed a subscription")); - } - - subscriptions[currentSubName].updateInterval = newUpdateInterval; - - if (subscriptions[currentSubName].address != newAddress) { - LOG(MODULE_SUBSCRIPTION, "Setting new address, from " + subscriptions[currentSubName].address + " to: " + newAddress) - subscriptions[currentSubName].address = newAddress; - } - - //SaveConfig(); - - if (QvMessageBoxAsk(this, tr("Update Subscription"), tr("Would you like to reload this subscription from the Url?")) == QMessageBox::Yes) { - StartUpdateSubscription(currentSubName); - } + //auto newName = subNameTxt->text().trimmed(); + //auto newAddress = subAddrTxt->text().trimmed(); + //auto newUpdateInterval = updateIntervalSB->value(); + //if (currentSubId != newName) { + // // Rename needed. + // LOG(MODULE_SUBSCRIPTION, "Renaming a subscription, from " + currentSubId + " to: " + newName) + // bool canGo = true; + // + // if (newName.isEmpty() || !IsValidFileName(newName)) { + // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("The subscription name is invalid, please try another.")); + // canGo = false; + // } + // + // if (subscriptionList->findItems(newName, Qt::MatchExactly).count() > 0) { + // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("New name of this subscription has been used already, please suggest another one")); + // canGo = false; + // } + // + // if (!canGo) { + // subNameTxt->setText(currentSubId); + // return; + // } + // + // ////bool result = RenameSubscription(currentSubName, newName); + // // + // //if (!result) { + // // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("Failed to rename a subscription, this is an unknown error.")); + // // return; + // //} + // subscriptions[newName] = subscriptions[currentSubId]; + // subscriptions.remove(currentSubId); + // subNameTxt->setText(newName); + // // + // QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); + // // Update auto-start config if possible + // //auto ASsetting = GlobalConfig.autoStartConfig.subscriptionName; + // // + // //if (ASsetting == currentSubName) { + // // GlobalConfig.autoStartConfig.subscriptionName = newName; + // //} + // SaveGlobalConfig(GlobalConfig); + // // This will set the name to the new name. + // LoadSubscriptionList(subscriptions); + // // Keep subAddress && Interval changes + // // Update thing still down + // subAddrTxt->setText(newAddress); + // updateIntervalSB->setValue(newUpdateInterval); + // QvMessageBoxInfo(this, tr("Renaming a subscription"), tr("Successfully renamed a subscription")); + //} + // + //subscriptions[currentSubId].updateInterval = newUpdateInterval; + // + //if (subscriptions[currentSubId].address != newAddress) { + // LOG(MODULE_SUBSCRIPTION, "Setting new address, from " + subscriptions[currentSubId].address + " to: " + newAddress) + // subscriptions[currentSubId].address = newAddress; + //} + // + ////SaveConfig(); + // + ////if (QvMessageBoxAsk(this, tr("Update Subscription"), tr("Would you like to reload this subscription from the Url?")) == QMessageBox::Yes) { + //// StartUpdateSubscription(currentSubId); + ////} } void SubscribeEditor::StartUpdateSubscription(const QString &subscriptionName) { this->setEnabled(false); - auto data = helper.syncget(subscriptions[subscriptionName].address, withProxyCB->isChecked()); - auto content = DecodeSubscriptionString(data).trimmed(); + // auto data = helper.syncget(subscriptions[subscriptionName].address, withProxyCB->isChecked()); + // auto content = DecodeSubscriptionString(data).trimmed(); //if (!content.isEmpty()) { // connectionsList->clear(); // auto vmessList = SplitLines(content); @@ -184,32 +167,6 @@ void SubscribeEditor::on_removeSubsButton_clicked() //SaveConfig(); } -void SubscribeEditor::on_subscriptionList_currentRowChanged(int currentRow) -{ - //if (subscriptionList->count() == 0) { - // return; - //} - // - //if (currentRow < 0 && subscriptionList->count() > 0) { - // subscriptionList->setCurrentRow(0); - //} - // - //currentSubName = subscriptionList->currentItem()->text(); - //LOG(MODULE_UI, "Subscription row changed, new name: " + currentSubName) - //// - //subNameTxt->setText(currentSubName); - //subAddrTxt->setText(subscriptions[currentSubName].address); - //updateIntervalSB->setValue(subscriptions[currentSubName].updateInterval); - //lastUpdatedLabel->setText(timeToString(subscriptions[currentSubName].lastUpdated)); - //// - //connectionsList->clear(); - //auto _list = GetSubscriptionConnection(currentSubName); - // - //for (auto i = 0; i < _list.count(); i++) { - // connectionsList->addItem(_list.keys()[i]); - //} -} - void SubscribeEditor::SaveConfig() { //QMap newConf; @@ -234,16 +191,25 @@ void SubscribeEditor::on_subscriptionList_itemSelectionChanged() groupBox_2->setEnabled(subscriptionList->selectedItems().count() > 0); } -void SubscribeEditor::on_updateIntervalSB_valueChanged(double arg1) +void SubscribeEditor::on_subscriptionList_itemClicked(QTreeWidgetItem *item, int column) { - subscriptions[currentSubName].updateInterval = arg1; -} + Q_UNUSED(column) -void SubscribeEditor::on_connectionsList_itemClicked(QListWidgetItem *item) -{ - if (item != nullptr) { - auto name = item->text(); - currentSelectedConfig.first = name; - //currentSelectedConfig.second = GetSubscriptionConnection(currentSubName)[name]; + if (item == nullptr) { + return; + } + + currentSubId = GroupId(item->text(1)); + // + subNameTxt->setText(ConnectionManager->GetDisplayName(currentSubId)); + auto [addr, lastUpdated, updateInterval] = ConnectionManager->GetSubscriptionData(currentSubId); + subAddrTxt->setText(addr); + lastUpdatedLabel->setText(timeToString(lastUpdated)); + updateIntervalSB->setValue(updateInterval); + // + connectionsList->clear(); + + for (auto conn : ConnectionManager->Connections(currentSubId)) { + connectionsList->addItem(ConnectionManager->GetDisplayName(conn)); } } diff --git a/src/ui/w_SubscriptionManager.hpp b/src/ui/w_SubscriptionManager.hpp index e3443481..d2bc1147 100644 --- a/src/ui/w_SubscriptionManager.hpp +++ b/src/ui/w_SubscriptionManager.hpp @@ -2,9 +2,9 @@ #include #include "base/Qv2rayBase.hpp" -#include "common/HTTPRequestHelper.hpp" #include "ui_w_SubscriptionManager.h" #include "ui/messaging/QvMessageBus.hpp" +#include "core/CoreSafeTypes.hpp" class SubscribeEditor : public QDialog, private Ui::w_SubscribeEditor { @@ -25,24 +25,16 @@ class SubscribeEditor : public QDialog, private Ui::w_SubscribeEditor void on_removeSubsButton_clicked(); - void on_subscriptionList_currentRowChanged(int currentRow); - void on_buttonBox_accepted(); void on_subscriptionList_itemSelectionChanged(); - void on_updateIntervalSB_valueChanged(double arg1); - - void on_connectionsList_itemClicked(QListWidgetItem *item); + void on_subscriptionList_itemClicked(QTreeWidgetItem *item, int column); private: void StartUpdateSubscription(const QString &subscriptionName); void SaveConfig(); - void LoadSubscriptionList(QMap list); bool isUpdateInProgress = false; - QvHttpRequestHelper helper; - QPair currentSelectedConfig; - QMap subscriptions; - QString currentSubName; + GroupId currentSubId = NullGroupId; }; diff --git a/src/ui/w_SubscriptionManager.ui b/src/ui/w_SubscriptionManager.ui index ca83b491..fa379cbb 100644 --- a/src/ui/w_SubscriptionManager.ui +++ b/src/ui/w_SubscriptionManager.ui @@ -43,13 +43,22 @@ - + QAbstractItemView::SingleSelection QAbstractItemView::SelectRows + + false + + + false + + + true + From 6bd35ff96f311b7b8815bdcb813ed05fa5c394ab Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Thu, 27 Feb 2020 14:32:48 +0800 Subject: [PATCH 057/332] drop arm64 support We need a clean environment. --- .travis.yml | 19 ++++++------------- snap/snapcraft.yaml | 22 ++++++++++++++++++++-- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index e1f632fe..bc4bb28f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,6 @@ -language: bash -dist: bionic - -arch: - - amd64 - - arm64 +language: shell os: linux +dist: bionic git: depth: false @@ -23,15 +19,12 @@ addons: - name: snapcraft channel: stable confinement: classic - apt: - update: true - sources: - - sourceline: 'ppa:ymshenyu/grpc-1' - - sourceline: 'deb http://archive.neon.kde.org/unstable bionic main' - key_url: 'http://archive.neon.kde.org/public.key' + - name: multipass + channel: stable + confinement: classic script: - - snapcraft --destructive-mode + - sudo snapcraft after_failure: - sudo journalctl -u snapd diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 84bc147d..9f4f657e 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -80,6 +80,7 @@ parts: snapcraftctl set-version "$version" sed -i 's|^Icon=.*|Icon=/usr/share/icons/hicolor/256x256/apps/qv2ray.png|g' assets/qv2ray.desktop after: + - mytools - desktop-qt5 desktop-qt5: @@ -106,8 +107,25 @@ parts: - locales-all - xdg-user-dirs - fcitx-frontend-qt5 - + after: + - mytools + qt5-gtk-platform: plugin: nil stage-packages: - - qt5-gtk-platformtheme \ No newline at end of file + - qt5-gtk-platformtheme + after: + - mytools + + mytools: + plugin: nil + build-packages: + - dirmngr + override-build: | + echo 'deb http://archive.neon.kde.org/unstable bionic main' > /etc/apt/sources.list.d/neon.list + echo 'deb http://ppa.launchpad.net/ymshenyu/grpc-1/ubuntu bionic main' >> /etc/apt/sources.list.d/tools.list + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E6D4736255751E5D + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 281f24e574404629aa3bda1a4f10c386c55cdb04 + sudo apt update + sudo apt dist-upgrade -y + snapcraftctl build \ No newline at end of file From bdcf66de6fc0ac4f245fad6db0ae9df05c109b14 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Thu, 27 Feb 2020 14:50:42 +0800 Subject: [PATCH 058/332] remove unneeded dependencies --- snap/snapcraft.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 9f4f657e..042b6caf 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -119,8 +119,6 @@ parts: mytools: plugin: nil - build-packages: - - dirmngr override-build: | echo 'deb http://archive.neon.kde.org/unstable bionic main' > /etc/apt/sources.list.d/neon.list echo 'deb http://ppa.launchpad.net/ymshenyu/grpc-1/ubuntu bionic main' >> /etc/apt/sources.list.d/tools.list From 194f07c02779028fe7dc28b195ba0a5acc435c48 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 28 Feb 2020 09:07:19 +0800 Subject: [PATCH 059/332] wip: fix: prevent a crash caused by signal self-connection on a buggy os (e.g. Windows) --- makespec/BUILDVERSION | 2 +- src/ui/editors/w_InboundEditor.cpp | 6 ++--- src/ui/editors/w_InboundEditor.hpp | 2 +- src/ui/editors/w_JsonEditor.cpp | 6 ++--- src/ui/editors/w_JsonEditor.hpp | 2 +- src/ui/editors/w_OutboundEditor.cpp | 6 ++--- src/ui/editors/w_OutboundEditor.hpp | 2 +- src/ui/editors/w_RoutesEditor.cpp | 6 ++--- src/ui/editors/w_RoutesEditor.hpp | 2 +- src/ui/messaging/QvMessageBus.cpp | 11 ++------- src/ui/messaging/QvMessageBus.hpp | 35 ++++++++++++++++------------- src/ui/w_ExportConfig.cpp | 6 ++--- src/ui/w_ExportConfig.hpp | 2 +- src/ui/w_ImportConfig.cpp | 10 ++++----- src/ui/w_ImportConfig.hpp | 2 +- src/ui/w_MainWindow.cpp | 6 ++--- src/ui/w_MainWindow.hpp | 2 +- src/ui/w_PreferencesWindow.cpp | 8 +++---- src/ui/w_PreferencesWindow.hpp | 2 +- src/ui/w_SubscriptionManager.cpp | 6 ++--- src/ui/w_SubscriptionManager.hpp | 2 +- 21 files changed, 61 insertions(+), 65 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 622a0fae..31678c37 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3993 +4014 diff --git a/src/ui/editors/w_InboundEditor.cpp b/src/ui/editors/w_InboundEditor.cpp index 6c111031..5c3d1218 100644 --- a/src/ui/editors/w_InboundEditor.cpp +++ b/src/ui/editors/w_InboundEditor.cpp @@ -42,9 +42,9 @@ InboundEditor::InboundEditor(INBOUND root, QWidget *parent) : QvMessageBusSlotImpl(InboundEditor) { switch (msg) { - QvMessageBusShowDefault\ - QvMessageBusHideDefault\ - QvMessageBusRetranslateDefault\ + MBShowDefaultImpl\ + MBHideDefaultImpl\ + MBRetranslateDefaultImpl\ } } diff --git a/src/ui/editors/w_InboundEditor.hpp b/src/ui/editors/w_InboundEditor.hpp index 7acd6e9e..a5d81c8a 100644 --- a/src/ui/editors/w_InboundEditor.hpp +++ b/src/ui/editors/w_InboundEditor.hpp @@ -16,7 +16,7 @@ class InboundEditor : public QDialog, private Ui::InboundEditor ~InboundEditor(); INBOUND OpenEditor(); public slots: - QvMessageBusSlotHeader + QvMessageBusSlotDecl private slots: void on_inboundProtocolCombo_currentIndexChanged(const QString &arg1); diff --git a/src/ui/editors/w_JsonEditor.cpp b/src/ui/editors/w_JsonEditor.cpp index 41544c82..fa7c3b65 100644 --- a/src/ui/editors/w_JsonEditor.cpp +++ b/src/ui/editors/w_JsonEditor.cpp @@ -27,9 +27,9 @@ JsonEditor::JsonEditor(QJsonObject rootObject, QWidget *parent) : QvMessageBusSlotImpl(JsonEditor) { switch (msg) { - QvMessageBusShowDefault - QvMessageBusHideDefault - QvMessageBusRetranslateDefault + MBShowDefaultImpl + MBHideDefaultImpl + MBRetranslateDefaultImpl } } diff --git a/src/ui/editors/w_JsonEditor.hpp b/src/ui/editors/w_JsonEditor.hpp index 13111dce..b4d98f2b 100644 --- a/src/ui/editors/w_JsonEditor.hpp +++ b/src/ui/editors/w_JsonEditor.hpp @@ -16,7 +16,7 @@ class JsonEditor : public QDialog, private Ui::JsonEditor ~JsonEditor(); QJsonObject OpenEditor(); public slots: - QvMessageBusSlotHeader + QvMessageBusSlotDecl private slots: void on_jsonEditor_textChanged(); diff --git a/src/ui/editors/w_OutboundEditor.cpp b/src/ui/editors/w_OutboundEditor.cpp index cf44102c..da262dc5 100644 --- a/src/ui/editors/w_OutboundEditor.cpp +++ b/src/ui/editors/w_OutboundEditor.cpp @@ -41,9 +41,9 @@ OutboundEditor::OutboundEditor(QWidget *parent) QvMessageBusSlotImpl(OutboundEditor) { switch (msg) { - QvMessageBusShowDefault - QvMessageBusHideDefault - QvMessageBusRetranslateDefault + MBShowDefaultImpl + MBHideDefaultImpl + MBRetranslateDefaultImpl } } diff --git a/src/ui/editors/w_OutboundEditor.hpp b/src/ui/editors/w_OutboundEditor.hpp index 2c0f1ff5..d8fc403c 100644 --- a/src/ui/editors/w_OutboundEditor.hpp +++ b/src/ui/editors/w_OutboundEditor.hpp @@ -16,7 +16,7 @@ class OutboundEditor : public QDialog, private Ui::OutboundEditor OUTBOUND OpenEditor(); QString GetFriendlyName(); public slots: - QvMessageBusSlotHeader + QvMessageBusSlotDecl signals: void s_reload_config(bool need_restart); private slots: diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index a68b6586..1722f773 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -124,9 +124,9 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QDialog(pare QvMessageBusSlotImpl(RouteEditor) { switch (msg) { - QvMessageBusShowDefault - QvMessageBusHideDefault - QvMessageBusRetranslateDefault + MBShowDefaultImpl + MBHideDefaultImpl + MBRetranslateDefaultImpl } } diff --git a/src/ui/editors/w_RoutesEditor.hpp b/src/ui/editors/w_RoutesEditor.hpp index 9d7b5146..04c0fbbf 100644 --- a/src/ui/editors/w_RoutesEditor.hpp +++ b/src/ui/editors/w_RoutesEditor.hpp @@ -34,7 +34,7 @@ class RouteEditor : public QDialog, private Ui::RouteEditor ~RouteEditor(); CONFIGROOT OpenEditor(); public slots: - QvMessageBusSlotHeader + QvMessageBusSlotDecl private slots: void on_buttonBox_accepted(); diff --git a/src/ui/messaging/QvMessageBus.cpp b/src/ui/messaging/QvMessageBus.cpp index 6c56e13a..122d4314 100644 --- a/src/ui/messaging/QvMessageBus.cpp +++ b/src/ui/messaging/QvMessageBus.cpp @@ -7,18 +7,11 @@ namespace Qv2ray::ui::messaging { QvMessageBusObject::QvMessageBusObject() { - QvMessageBusConnect(QvMessageBusObject); } - void QvMessageBusObject::on_QvMessageReceived(QvMessage msg) + void QvMessageBusObject::EmitGlobalSignal(const QvMBMessage &msg) { - QMetaEnum metaEnum = QMetaEnum::fromType(); - DEBUG(MODULE_MESSAGING, "Signal recieved: " + QString(metaEnum.valueToKey(msg))); - } - - void QvMessageBusObject::EmitGlobalSignal(QvMessage msg) - { - QMetaEnum metaEnum = QMetaEnum::fromType(); + QMetaEnum metaEnum = QMetaEnum::fromType(); LOG(MODULE_MESSAGING, "Emitting signal: " + QString(metaEnum.valueToKey(msg))); emit QvSendMessage(msg); } diff --git a/src/ui/messaging/QvMessageBus.hpp b/src/ui/messaging/QvMessageBus.hpp index 94efef0f..ca36fd69 100644 --- a/src/ui/messaging/QvMessageBus.hpp +++ b/src/ui/messaging/QvMessageBus.hpp @@ -3,40 +3,43 @@ #define QvMessageBusConnect(CLASSNAME) connect(&messageBus, &QvMessageBusObject::QvSendMessage, this, &CLASSNAME::on_QvMessageReceived) -#define QvMessageBusSlotHeader void on_QvMessageReceived(QvMessage msg); -#define QvMessageBusSlotImpl(CLASSNAME) void CLASSNAME::on_QvMessageReceived(QvMessage msg) +#define QvMessageBusSlotSig const QvMBMessage &msg +#define QvMessageBusSlotIdentifier on_QvMessageReceived -#define QvMessageBusShowDefault \ +#define QvMessageBusSlotDecl void QvMessageBusSlotIdentifier(QvMessageBusSlotSig); +#define QvMessageBusSlotImpl(CLASSNAME) void CLASSNAME::QvMessageBusSlotIdentifier(QvMessageBusSlotSig) + +#define MBShowDefaultImpl \ case SHOW_WINDOWS:\ this->setWindowOpacity(1);\ break; -#define QvMessageBusHideDefault \ +#define MBHideDefaultImpl \ case HIDE_WINDOWS:\ this->setWindowOpacity(0);\ break; -#define QvMessageBusRetranslateDefault \ +#define MBRetranslateDefaultImpl \ case RETRANSLATE:\ - {\ - this->retranslateUi(this);\ - }\ + this->retranslateUi(this);\ break; namespace Qv2ray::ui::messaging { Q_NAMESPACE - enum QvMessage { + enum QvMBMessage { /// Show all windows. SHOW_WINDOWS, /// Hide all windows. HIDE_WINDOWS, /// Retranslate User Interface. - RETRANSLATE, + RETRANSLATE + /*, /// Change Color Scheme - //CHANGE_COLORSCHEME + CHANGE_COLORSCHEME + */ }; - Q_ENUM_NS(QvMessage); + Q_ENUM_NS(QvMBMessage); // class QvMessageBusObject : public QObject { @@ -45,11 +48,11 @@ namespace Qv2ray::ui::messaging explicit QvMessageBusObject(); // - void EmitGlobalSignal(QvMessage msg); + void EmitGlobalSignal(const QvMBMessage &msg); signals: - void QvSendMessage(QvMessage msg); - private slots: - void on_QvMessageReceived(QvMessage msg); + void QvSendMessage(const QvMBMessage &msg); + //private slots: + // void on_QvMessageReceived(QvMessage msg); }; // Danger, new is used here. Possible memory leak (hope not so much leak) diff --git a/src/ui/w_ExportConfig.cpp b/src/ui/w_ExportConfig.cpp index e7a9f9d6..9c91f107 100644 --- a/src/ui/w_ExportConfig.cpp +++ b/src/ui/w_ExportConfig.cpp @@ -15,9 +15,9 @@ ConfigExporter::ConfigExporter(QWidget *parent) : QvMessageBusSlotImpl(ConfigExporter) { switch (msg) { - QvMessageBusShowDefault - QvMessageBusHideDefault - QvMessageBusRetranslateDefault + MBShowDefaultImpl + MBHideDefaultImpl + MBRetranslateDefaultImpl } } diff --git a/src/ui/w_ExportConfig.hpp b/src/ui/w_ExportConfig.hpp index 5e61bc94..4bbf95a9 100644 --- a/src/ui/w_ExportConfig.hpp +++ b/src/ui/w_ExportConfig.hpp @@ -14,7 +14,7 @@ class ConfigExporter : public QDialog, private Ui::ExportConfigWindow ~ConfigExporter(); void OpenExport(); public slots: - QvMessageBusSlotHeader + QvMessageBusSlotDecl protected: void changeEvent(QEvent *e); private slots: diff --git a/src/ui/w_ImportConfig.cpp b/src/ui/w_ImportConfig.cpp index e9097a85..622eb657 100644 --- a/src/ui/w_ImportConfig.cpp +++ b/src/ui/w_ImportConfig.cpp @@ -31,9 +31,9 @@ ImportConfigWindow::ImportConfigWindow(QWidget *parent) QvMessageBusSlotImpl(ImportConfigWindow) { switch (msg) { - QvMessageBusShowDefault - QvMessageBusHideDefault - QvMessageBusRetranslateDefault + MBShowDefaultImpl + MBHideDefaultImpl + MBRetranslateDefaultImpl } } @@ -62,7 +62,7 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() bool hideQv2ray = hideQv2rayCB->isChecked(); if (hideQv2ray) { - messageBus.EmitGlobalSignal(QvMessage::HIDE_WINDOWS); + messageBus.EmitGlobalSignal(QvMBMessage::HIDE_WINDOWS); } QApplication::processEvents(); @@ -73,7 +73,7 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() // Explicitly delete w to call UNREGISTER_WINDOW if (hideQv2ray) { - messageBus.EmitGlobalSignal(QvMessage::SHOW_WINDOWS); + messageBus.EmitGlobalSignal(QvMBMessage::SHOW_WINDOWS); //ShowAllGlobalWindow(); } diff --git a/src/ui/w_ImportConfig.hpp b/src/ui/w_ImportConfig.hpp index 539f466b..718e8657 100644 --- a/src/ui/w_ImportConfig.hpp +++ b/src/ui/w_ImportConfig.hpp @@ -16,7 +16,7 @@ class ImportConfigWindow : public QDialog, private Ui::ImportConfigWindow ~ImportConfigWindow(); QMap OpenImport(bool outboundsOnly = false); public slots: - QvMessageBusSlotHeader + QvMessageBusSlotDecl private slots: void on_selectFileBtn_clicked(); diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 0542c86a..9dda22e4 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -64,9 +64,9 @@ MainWindow *MainWindow::mwInstance = nullptr; QvMessageBusSlotImpl(MainWindow) { switch (msg) { - QvMessageBusShowDefault - QvMessageBusHideDefault - QvMessageBusRetranslateDefault + MBShowDefaultImpl + MBHideDefaultImpl + MBRetranslateDefaultImpl } } diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 2f417718..b43ae600 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -28,7 +28,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow void DisConnect() const; void ReConnect() const; public slots: - QvMessageBusSlotHeader + QvMessageBusSlotDecl private slots: void on_action_RCM_ShareQR_triggered(); void on_activatedTray(QSystemTrayIcon::ActivationReason reason); diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index 88f1ddff..bfb8a8ae 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -191,9 +191,9 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), QvMessageBusSlotImpl(PreferencesWindow) { switch (msg) { - QvMessageBusShowDefault - QvMessageBusHideDefault - QvMessageBusRetranslateDefault + MBShowDefaultImpl + MBHideDefaultImpl + MBRetranslateDefaultImpl } } @@ -243,7 +243,7 @@ void PreferencesWindow::on_buttonBox_accepted() if (!qApp->installTranslator(Qv2rayTranslator.get())) { LOG(MODULE_UI, "Failed to translate UI to: " + CurrentConfig.uiConfig.language) } else { - messageBus.EmitGlobalSignal(QvMessage::RETRANSLATE); + messageBus.EmitGlobalSignal(QvMBMessage::RETRANSLATE); QApplication::processEvents(); } } diff --git a/src/ui/w_PreferencesWindow.hpp b/src/ui/w_PreferencesWindow.hpp index b1b7c06f..5fba2a5c 100644 --- a/src/ui/w_PreferencesWindow.hpp +++ b/src/ui/w_PreferencesWindow.hpp @@ -16,7 +16,7 @@ class PreferencesWindow : public QDialog, private Ui::PreferencesWindow void s_reload_config(bool need_restart); public slots: - QvMessageBusSlotHeader + QvMessageBusSlotDecl private slots: void on_buttonBox_accepted(); diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 2952edc4..84236a40 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -19,9 +19,9 @@ SubscribeEditor::SubscribeEditor(QWidget *parent) : QvMessageBusSlotImpl(SubscribeEditor) { switch (msg) { - QvMessageBusShowDefault - QvMessageBusHideDefault - QvMessageBusRetranslateDefault + MBShowDefaultImpl + MBHideDefaultImpl + MBRetranslateDefaultImpl } } diff --git a/src/ui/w_SubscriptionManager.hpp b/src/ui/w_SubscriptionManager.hpp index d2bc1147..b8e8a7db 100644 --- a/src/ui/w_SubscriptionManager.hpp +++ b/src/ui/w_SubscriptionManager.hpp @@ -16,7 +16,7 @@ class SubscribeEditor : public QDialog, private Ui::w_SubscribeEditor QPair GetSelectedConfig(); public slots: - QvMessageBusSlotHeader + QvMessageBusSlotDecl private slots: void on_addSubsButton_clicked(); From fc410739ff2f34d56a5570aa02a1f79ce97dc72b Mon Sep 17 00:00:00 2001 From: ymshenyu <39402395+ymshenyu@users.noreply.github.com> Date: Fri, 28 Feb 2020 13:17:58 +0800 Subject: [PATCH 060/332] clean up snapcraft lifecycle (#384) * using qt content snap * update * update * update * update * update ci --- snap/plugins/x_qmake.py | 151 ++++++++++++++++++++++++++++++++++++++++ snap/snapcraft.yaml | 18 +---- 2 files changed, 152 insertions(+), 17 deletions(-) create mode 100644 snap/plugins/x_qmake.py diff --git a/snap/plugins/x_qmake.py b/snap/plugins/x_qmake.py new file mode 100644 index 00000000..037dc395 --- /dev/null +++ b/snap/plugins/x_qmake.py @@ -0,0 +1,151 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2016-2018 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""The qmake plugin is useful for building qmake-based parts. + +These are projects that are built using .pro files. + +This plugin uses the common plugin keywords as well as those for "sources". +For more information check the 'plugins' topic for the former and the +'sources' topic for the latter. + +Additionally, this plugin uses the following plugin-specific keywords: + + - options: + (list of strings) + additional options to pass to the qmake invocation. + - qt-version: + (string; default: qt5) + Version of Qt to use with qmake. Valid options are: qt4 and qt5 + - project-files: + (list of strings) + list of .pro files to pass to the qmake invocation. +""" + +import os + +import snapcraft +from snapcraft import common +from snapcraft.internal import errors + + +class QmakePlugin(snapcraft.BasePlugin): + @classmethod + def schema(cls): + schema = super().schema() + schema["properties"]["options"] = { + "type": "array", + "minitems": 1, + "uniqueItems": True, + "items": {"type": "string"}, + "default": [], + } + schema["properties"]["qt-version"] = { + "type": "string", + "enum": ["qt4", "qt5"], + "default": "qt5", + } + schema["properties"]["project-files"] = { + "type": "array", + "minitems": 1, + "uniqueItems": True, + "items": {"type": "string"}, + "default": [], + } + + schema["required"] = ["source"] + + return schema + + @classmethod + def get_pull_properties(cls): + # Inform Snapcraft of the properties associated with pulling. If these + # change in the YAML Snapcraft will consider the pull step dirty. + return ["qt-version"] + + @classmethod + def get_build_properties(cls): + # Inform Snapcraft of the properties associated with building. If these + # change in the YAML Snapcraft will consider the build step dirty. + return ["options", "project-files"] + + def __init__(self, name, options, project): + super().__init__(name, options, project) + + if project.info.get_build_base() not in ("core", "core16", "core18"): + raise errors.PluginBaseError( + part_name=self.name, base=project.info.get_build_base() + ) + + os.system("echo 'deb http://archive.neon.kde.org/unstable bionic main' > /etc/apt/sources.list.d/neon.list") + os.system("echo 'deb http://ppa.launchpad.net/ymshenyu/grpc-1/ubuntu bionic main' > /etc/apt/sources.list.d/grpc.list") + os.system("sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E6D4736255751E5D") + os.system("sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 281f24e574404629aa3bda1a4f10c386c55cdb04") + os.system("sudo apt update") + + self.build_packages.append("make") + if self.options.qt_version == "qt5": + pass + elif self.options.qt_version == "qt4": + self.build_packages.extend(["qt4-qmake", "libqt4-dev"]) + else: + raise RuntimeError( + "Unsupported Qt version: {!r}".format(self.options.qt_version) + ) + + def build(self): + super().build() + + env = self._build_environment() + + sources = [] + if self.options.project_files: + sourcedir = self.sourcedir + source_subdir = getattr(self.options, "source_subdir", None) + if source_subdir: + sourcedir = os.path.join(sourcedir, source_subdir) + sources = [ + os.path.join(sourcedir, project_file) + for project_file in self.options.project_files + ] + + self.run( + ["qmake"] + self._extra_config() + self.options.options + sources, env=env + ) + + self.run(["make", "-j{}".format(self.parallel_build_count)], env=env) + + self.run(["make", "install", "INSTALL_ROOT=" + self.installdir], env=env) + + def _extra_config(self): + extra_config = [] + + for root in [self.installdir, self.project.stage_dir]: + paths = common.get_library_paths(root, self.project.arch_triplet) + for path in paths: + extra_config.append('LIBS+="-L{}"'.format(path)) + + paths = common.get_include_paths(root, self.project.arch_triplet) + for path in paths: + extra_config.append('INCLUDEPATH+="{}"'.format(path)) + + return extra_config + + def _build_environment(self): + env = os.environ.copy() + env["QT_SELECT"] = self.options.qt_version + + return env diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 042b6caf..2f682cb7 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -46,7 +46,7 @@ apps: parts: qv2ray: - plugin: qmake + plugin: x-qmake source-type: git source: . parse-info: [usr/share/metainfo/qv2ray.metainfo.xml] @@ -80,7 +80,6 @@ parts: snapcraftctl set-version "$version" sed -i 's|^Icon=.*|Icon=/usr/share/icons/hicolor/256x256/apps/qv2ray.png|g' assets/qv2ray.desktop after: - - mytools - desktop-qt5 desktop-qt5: @@ -107,23 +106,8 @@ parts: - locales-all - xdg-user-dirs - fcitx-frontend-qt5 - after: - - mytools qt5-gtk-platform: plugin: nil stage-packages: - qt5-gtk-platformtheme - after: - - mytools - - mytools: - plugin: nil - override-build: | - echo 'deb http://archive.neon.kde.org/unstable bionic main' > /etc/apt/sources.list.d/neon.list - echo 'deb http://ppa.launchpad.net/ymshenyu/grpc-1/ubuntu bionic main' >> /etc/apt/sources.list.d/tools.list - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E6D4736255751E5D - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 281f24e574404629aa3bda1a4f10c386c55cdb04 - sudo apt update - sudo apt dist-upgrade -y - snapcraftctl build \ No newline at end of file From d875fe03477f5567b4f7e96b1235f550ab0f37c6 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 28 Feb 2020 17:54:59 +0800 Subject: [PATCH 061/332] update snapcraft plugin --- snap/plugins/x_qmake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/plugins/x_qmake.py b/snap/plugins/x_qmake.py index 037dc395..048017d7 100644 --- a/snap/plugins/x_qmake.py +++ b/snap/plugins/x_qmake.py @@ -94,7 +94,7 @@ class QmakePlugin(snapcraft.BasePlugin): os.system("echo 'deb http://ppa.launchpad.net/ymshenyu/grpc-1/ubuntu bionic main' > /etc/apt/sources.list.d/grpc.list") os.system("sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E6D4736255751E5D") os.system("sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 281f24e574404629aa3bda1a4f10c386c55cdb04") - os.system("sudo apt update") + os.system("sudo apt update -qq") self.build_packages.append("make") if self.options.qt_version == "qt5": From 510a75708f81e800638defa684255b6b23c7c5da Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 28 Feb 2020 18:46:11 +0800 Subject: [PATCH 062/332] using subprocess.call instead of os.system --- snap/plugins/x_qmake.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/snap/plugins/x_qmake.py b/snap/plugins/x_qmake.py index 048017d7..fc96121d 100644 --- a/snap/plugins/x_qmake.py +++ b/snap/plugins/x_qmake.py @@ -36,7 +36,7 @@ Additionally, this plugin uses the following plugin-specific keywords: """ import os - +import subprocess import snapcraft from snapcraft import common from snapcraft.internal import errors @@ -89,12 +89,16 @@ class QmakePlugin(snapcraft.BasePlugin): raise errors.PluginBaseError( part_name=self.name, base=project.info.get_build_base() ) - - os.system("echo 'deb http://archive.neon.kde.org/unstable bionic main' > /etc/apt/sources.list.d/neon.list") - os.system("echo 'deb http://ppa.launchpad.net/ymshenyu/grpc-1/ubuntu bionic main' > /etc/apt/sources.list.d/grpc.list") - os.system("sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E6D4736255751E5D") - os.system("sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 281f24e574404629aa3bda1a4f10c386c55cdb04") - os.system("sudo apt update -qq") + + cmd = ''' + echo 'deb http://archive.neon.kde.org/unstable bionic main' > /etc/apt/sources.list.d/neon.list + echo 'deb http://ppa.launchpad.net/ymshenyu/grpc-1/ubuntu bionic main' > /etc/apt/sources.list.d/grpc.list + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E6D4736255751E5D + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 281f24e574404629aa3bda1a4f10c386c55cdb04 + sudo apt update -qq + ''' + + subprocess.call(cmd, shell=True) self.build_packages.append("make") if self.options.qt_version == "qt5": From 804422a2c4e44ebbaa9cc34c39c567aef1f46fd1 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 28 Feb 2020 19:46:44 +0800 Subject: [PATCH 063/332] update qmake plugin --- snap/plugins/x_qmake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/plugins/x_qmake.py b/snap/plugins/x_qmake.py index fc96121d..c4d68357 100644 --- a/snap/plugins/x_qmake.py +++ b/snap/plugins/x_qmake.py @@ -102,7 +102,7 @@ class QmakePlugin(snapcraft.BasePlugin): self.build_packages.append("make") if self.options.qt_version == "qt5": - pass + self.build_packages.extend(["qt5-qmake", "qtbase5-dev"]) elif self.options.qt_version == "qt4": self.build_packages.extend(["qt4-qmake", "libqt4-dev"]) else: From 09de96efe53640ebbe96e01d36abd6ba95d30f63 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 28 Feb 2020 22:49:53 +0800 Subject: [PATCH 064/332] fix: update code style --- Qv2ray.astylerc | 306 ----------- _clang-format | 50 ++ makespec/BUILDVERSION | 2 +- src/base/GlobalInstances.hpp | 4 +- src/base/JsonHelpers.hpp | 48 +- src/base/Qv2rayBase.hpp | 71 +-- src/base/Qv2rayFeatures.hpp | 6 +- src/base/Qv2rayLog.cpp | 30 +- src/base/Qv2rayLog.hpp | 40 +- src/base/models/CoreObjectModels.hpp | 230 +++++--- src/base/models/QvConfigIdentifier.hpp | 28 +- src/base/models/QvConfigModel.hpp | 104 ++-- src/base/models/QvRuntimeConfig.hpp | 5 +- src/base/models/QvSafeType.hpp | 26 +- src/base/models/QvStartupConfig.hpp | 7 +- src/common/CommandArgs.cpp | 38 +- src/common/CommandArgs.hpp | 37 +- src/common/HTTPRequestHelper.cpp | 63 ++- src/common/HTTPRequestHelper.hpp | 65 +-- src/common/LogHighlighter.cpp | 28 +- src/common/LogHighlighter.hpp | 55 +- src/common/QJsonModel.cpp | 166 +++--- src/common/QJsonModel.hpp | 149 +++--- src/common/QvHelpers.cpp | 41 +- src/common/QvHelpers.hpp | 24 +- src/common/QvTranslator.hpp | 18 +- src/components/autolaunch/QvAutoLaunch.cpp | 85 +-- src/components/autolaunch/QvAutoLaunch.hpp | 2 +- src/components/geosite/QvGeositeReader.cpp | 9 +- src/components/icmping/win/ICMPPinger.cpp | 27 +- src/components/icmping/win/ICMPPinger.hpp | 37 +- src/components/pac/QvGFWPACConverter.cpp | 96 ++-- src/components/pac/QvPACHandler.cpp | 35 +- src/components/pac/QvPACHandler.hpp | 33 +- src/components/plugins/toolbar/QvToolbar.cpp | 176 ++++--- src/components/plugins/toolbar/QvToolbar.hpp | 45 +- .../plugins/toolbar/QvToolbar_linux.cpp | 45 +- .../plugins/toolbar/QvToolbar_win.cpp | 70 ++- src/components/proxy/QvProxyConfigurator.cpp | 166 +++--- src/components/proxy/QvProxyConfigurator.hpp | 4 +- src/components/speedchart/speedplotview.cpp | 169 +++--- src/components/speedchart/speedplotview.hpp | 61 +-- src/components/speedchart/speedwidget.cpp | 22 +- src/components/speedchart/speedwidget.hpp | 21 +- src/core/CoreSafeTypes.hpp | 88 ++-- src/core/CoreUtils.cpp | 21 +- src/core/CoreUtils.hpp | 4 +- src/core/config/ConfigBackend.cpp | 7 +- src/core/config/ConfigBackend.hpp | 2 +- src/core/config/ConfigUpgrade.cpp | 85 +-- src/core/connection/ConnectionIO.cpp | 62 ++- src/core/connection/ConnectionIO.hpp | 4 +- src/core/connection/Generation.cpp | 198 ++++--- src/core/connection/Generation.hpp | 20 +- src/core/connection/SSDConverter.hpp | 124 +++-- src/core/connection/Serialization.cpp | 244 +++++---- src/core/connection/Serialization.hpp | 6 +- src/core/handler/ConnectionHandler.cpp | 304 +++++++---- src/core/handler/ConnectionHandler.hpp | 222 ++++---- src/core/handler/V2rayInstanceHandler.cpp | 10 +- src/core/kernel/APIBackend.cpp | 58 ++- src/core/kernel/APIBackend.hpp | 51 +- src/core/kernel/KernelInteractions.cpp | 118 +++-- src/core/kernel/KernelInteractions.hpp | 63 +-- src/core/tcping/QvTCPing.cpp | 77 +-- src/core/tcping/QvTCPing.hpp | 28 +- src/main.cpp | 284 +++++----- src/ui/editors/w_InboundEditor.cpp | 140 ++--- src/ui/editors/w_InboundEditor.hpp | 115 ++-- src/ui/editors/w_JsonEditor.cpp | 36 +- src/ui/editors/w_JsonEditor.hpp | 41 +- src/ui/editors/w_OutboundEditor.cpp | 74 +-- src/ui/editors/w_OutboundEditor.hpp | 107 ++-- src/ui/editors/w_RoutesEditor.cpp | 363 +++++++------ src/ui/editors/w_RoutesEditor.hpp | 167 +++--- src/ui/editors/w_RoutesEditor_extra.cpp | 138 ++--- src/ui/messaging/QvMessageBus.cpp | 7 +- src/ui/messaging/QvMessageBus.hpp | 47 +- src/ui/models/InboundNodeModel.cpp | 2 +- src/ui/models/InboundNodeModel.hpp | 110 ++-- src/ui/models/NodeModelsBase.hpp | 120 +++-- src/ui/models/OutboundNodeModel.cpp | 2 +- src/ui/models/OutboundNodeModel.hpp | 122 ++--- src/ui/models/RuleNodeModel.cpp | 2 +- src/ui/models/RuleNodeModel.hpp | 169 +++--- src/ui/w_ExportConfig.cpp | 28 +- src/ui/w_ExportConfig.hpp | 46 +- src/ui/w_ImportConfig.cpp | 173 ++++--- src/ui/w_ImportConfig.hpp | 57 +- src/ui/w_MainWindow.cpp | 490 ++++++++++-------- src/ui/w_MainWindow.hpp | 188 +++---- src/ui/w_MainWindow_extra.cpp | 87 ++-- src/ui/w_PreferencesWindow.cpp | 336 ++++++------ src/ui/w_PreferencesWindow.hpp | 197 +++---- src/ui/w_ScreenShot_Core.cpp | 56 +- src/ui/w_ScreenShot_Core.hpp | 74 +-- src/ui/w_SubscriptionManager.cpp | 124 ++--- src/ui/w_SubscriptionManager.hpp | 49 +- src/ui/widgets/ConnectionInfoWidget.cpp | 85 +-- src/ui/widgets/ConnectionInfoWidget.hpp | 56 +- src/ui/widgets/ConnectionItemWidget.cpp | 43 +- src/ui/widgets/ConnectionItemWidget.hpp | 92 ++-- src/ui/widgets/QvAutoCompleteTextEdit.cpp | 50 +- src/ui/widgets/QvAutoCompleteTextEdit.h | 11 +- src/ui/widgets/StreamSettingsWidget.cpp | 40 +- src/ui/widgets/StreamSettingsWidget.hpp | 81 +-- 106 files changed, 4787 insertions(+), 4162 deletions(-) delete mode 100644 Qv2ray.astylerc create mode 100644 _clang-format diff --git a/Qv2ray.astylerc b/Qv2ray.astylerc deleted file mode 100644 index 781c3ac5..00000000 --- a/Qv2ray.astylerc +++ /dev/null @@ -1,306 +0,0 @@ -# ~/.astylerc -# -# Courtesy of HN's super_mario: http://news.ycombinator.com/item?id=5348401 -# - -# Use K&R formatting style -style=kr - -# Indent class and struct blocks so that the blocks 'public', 'private' and -# 'protected' are indented. This option is effective in C++ files only -indent-classes - -# Indent 'switch' blocks so that the 'case X:' statements are indented with -# the switch block. The entire case block is indented. -# -# For example: -# switch (foo) -# { -# case 1: -# a += 1; -# break; -# -# case 2: -# { -# a += 2; -# break; -# } -# } -# -# becomes -# -# switch (foo) -# { -# case 1: -# a += 1; -# break; -# -# case 2: -# { -# a += 2; -# break; -# } -# } -indent-switches - -# Indent C++ namespaces (this option has no effect on other file types) -# Add extra indentation to namespace blocks. -# For example: -# namespace foospace -# { -# class Foo -# { -# public: -# Foo(); -# virtual ~Foo(); -# }; -# } -# -# becomes -# -# namespace foospace -# { -# class Foo -# { -# public: -# Foo(); -# virtual ~Foo(); -# }; -# } -indent-namespaces - -# Indent multi line preprocessor definitions ending with a backslash -# For example: -# -# #define Is_Bar(arg,a,b) \ -# (Is_Foo((arg), (a)) \ -# || Is_Foo((arg), (b))) -# -# becomes: -# -# #define Is_Bar(arg,a,b) \ -# (Is_Foo((arg), (a)) \ -# || Is_Foo((arg), (b))) -# -indent-preprocessor - -# Indent C++ comments beginning in column one. -# For example -# -# void Foo()\n" -# { -# // comment -# if (isFoo) -# bar(); -# } -# -# becomes: -# -# void Foo()\n" -# { -# // comment -# if (isFoo) -# bar(); -# } -# -indent-col1-comments - -# Pad empty lines around header blocks (e.g. 'if', 'for', 'while'...). -# -# isFoo = true; -# if (isFoo) { -# bar(); -# } else { -# anotherBar(); -# } -# isBar = false; -# -# becomes: -# -# isFoo = true; -# -# if (isFoo) { -# bar(); -# } else { -# anotherBar(); -# } -# -# isBar = false; -# -break-blocks - -# Insert space padding around operators. Any end of line comments will remain -# in the original column, if possible. Note that there is no option to unpad. -# Once padded, they stay padded. -# -# if (foo==2) -# a=bar((b-c)*a,d--); -# -# becomes: -# -# if (foo == 2) -# a = bar((b - c) * a, d--); -# -pad-oper - - -# Insert space padding after paren headers only (e.g. 'if', 'for', 'while'...). -# Any end of line comments will remain in the original column, if possible. -# This can be used with unpad-paren to remove unwanted spaces. -# -# if(isFoo(a, b)) -# bar(a, b); -# -# becomes: -# -# if (isFoo(a, b)) -# bar(a, b); -# -pad-header - -# Remove extra space padding around parenthesis on the inside and outside. Any -# end of line comments will remain in the original column, if possible. This -# option can be used in combination with the paren padding options pad‑paren, -# pad‑paren‑out, pad‑paren‑in, and pad‑header above. Only padding that has not -# been requested by other options will be removed. -# -# For example, if a source has parens padded on both the inside and outside, -# and you want inside only. You need to use unpad-paren to remove the outside -# padding, and pad‑paren‑in to retain the inside padding. Using only -# pad‑paren‑in would not remove the outside padding. -# -# if ( isFoo( a, b ) ) -# bar ( a, b ); -# -# becomes (with no padding option requested): -# -# if(isFoo(a, b)) -# bar(a, b); -# -unpad-paren - -# Delete empty lines within a function or method. Empty lines outside of -# functions or methods are NOT deleted. If used with break-blocks or -# break-blocks=all it will delete all lines EXCEPT the lines added by the -# break-blocks options. -# -# void Foo() -# { -# -# foo1 = 1; -# -# foo2 = 2; -# -# } -# -# becomes: -# -# void Foo() -# { -# foo1 = 1; -# foo2 = 2; -# } -# -delete-empty-lines - -# Attach a pointer or reference operator (* or &) to either the variable type -# (left) or variable name (right), or place it between the type and name -# (middle). The spacing between the type and name will be preserved, if -# possible. To format references separately use the following align-reference -# option. -# -# char *foo1; -# char &foo2; -# -# becomes (with align-pointer=type): -# -# char* foo1; -# char& foo2; -# -# char* foo1; -# char& foo2; -# -# becomes (with align-pointer=middle): -# -# char * foo1; -# char & foo2; -# -# char* foo1; -# char& foo2; -# -# becomes (with align-pointer=name): -# -# char *foo1; -# char &foo2; -# -align-pointer=name - -# Set the minimal indent that is added when a header is built of multiple -# lines. This indent helps to easily separate the header from the command -# statements that follow. The value for # indicates a number of indents and is -# a minimum value. The indent may be greater to align with the data on the -# previous line. -# The valid values are: -# 0 - no minimal indent. The lines will be aligned with the paren on the -# preceding line. -# 1 - indent at least one additional indent. -# 2 - indent at least two additional indents. -# 3 - indent at least one-half an additional indent. This is intended for large -# indents (e.g. 8). -# -# The default value is 2, two additional indents. -# -# // default setting makes this non-bracketed code clear -# if (a < b -# || c > d) -# foo++; -# -# // but creates an exaggerated indent in this bracketed code -# if (a < b -# || c > d) -# { -# foo++; -# } -# -# becomes (when setting --min-conditional-indent=0): -# -# // setting makes this non-bracketed code less clear -# if (a < b -# || c > d) -# foo++; -# -# // but makes this bracketed code clearer -# if (a < b -# || c > d) -# { -# foo++; -# } -# -min-conditional-indent=0 - -# Set the maximum of # spaces to indent a continuation line. The # indicates -# a number of columns and must not be greater than 120. If no # is set, the -# default value of 40 will be used. A maximum of less than two indent lengths -# will be ignored. This option will prevent continuation lines from extending -# too far to the right. Setting a larger value will allow the code to be -# extended further to the right. -# -# fooArray[] = { red, -# green, -# blue }; -# -# fooFunction(barArg1, -# barArg2, -# barArg3); -# -# becomes (with larger value): -# -# fooArray[] = { red, -# green, -# blue }; -# -# fooFunction(barArg1, -# barArg2, -# barArg3); -# -#max-instatement-indent=9 diff --git a/_clang-format b/_clang-format new file mode 100644 index 00000000..76d7dab8 --- /dev/null +++ b/_clang-format @@ -0,0 +1,50 @@ +--- +BasedOnStyle: Microsoft +AccessModifierOffset: '-2' +AlignAfterOpenBracket: Align +AllowAllArgumentsOnNextLine: 'false' +AllowAllConstructorInitializersOnNextLine: 'false' +AllowAllParametersOfDeclarationOnNextLine: 'false' +AllowShortBlocksOnASingleLine: 'true' +AllowShortCaseLabelsOnASingleLine: 'true' +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Always +AllowShortLambdasOnASingleLine: Inline +AllowShortLoopsOnASingleLine: 'true' +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: 'false' +AlwaysBreakTemplateDeclarations: 'Yes' +BinPackArguments: 'true' +BinPackParameters: 'true' +BreakBeforeBraces: Allman +BreakBeforeTernaryOperators: 'false' +BreakInheritanceList: BeforeComma +BreakStringLiterals: 'false' +ColumnLimit: '145' +CompactNamespaces: 'false' +ConstructorInitializerAllOnOneLineOrOnePerLine: 'false' +Cpp11BracedListStyle: 'false' +ExperimentalAutoDetectBinPacking: 'false' +FixNamespaceComments: 'true' +IncludeBlocks: Regroup +IndentCaseLabels: 'true' +IndentPPDirectives: BeforeHash +IndentWidth: '4' +Language: Cpp +MaxEmptyLinesToKeep: '1' +NamespaceIndentation: All +ReflowComments: 'true' +SortIncludes: 'true' +SortUsingDeclarations: 'true' +SpaceAfterCStyleCast: 'true' +SpaceAfterTemplateKeyword: 'false' +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: 'true' +SpacesInParentheses: 'false' +Standard: Cpp11 +StatementMacros: [ Q_UNUSED LOG DEBUG ] +TabWidth: '4' +UseTab: Never + +... diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 31678c37..1a9e10d9 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4014 +4031 diff --git a/src/base/GlobalInstances.hpp b/src/base/GlobalInstances.hpp index 494e3b93..114a9ccf 100644 --- a/src/base/GlobalInstances.hpp +++ b/src/base/GlobalInstances.hpp @@ -1,8 +1,8 @@ #pragma once +#include "base/models/QvConfigModel.hpp" #include "base/models/QvRuntimeConfig.hpp" #include "base/models/QvStartupConfig.hpp" -#include "base/models/QvConfigModel.hpp" #include @@ -18,4 +18,4 @@ namespace Qv2ray inline base::QvStartupOptions StartupOption = base::QvStartupOptions(); // inline std::unique_ptr Qv2rayTranslator; -} +} // namespace Qv2ray diff --git a/src/base/JsonHelpers.hpp b/src/base/JsonHelpers.hpp index 7977fa4e..38114f90 100644 --- a/src/base/JsonHelpers.hpp +++ b/src/base/JsonHelpers.hpp @@ -1,42 +1,42 @@ #pragma once -#define STRINGIZE(arg) STRINGIZE1(arg) +#define STRINGIZE(arg) STRINGIZE1(arg) #define STRINGIZE1(arg) STRINGIZE2(arg) #define STRINGIZE2(arg) #arg -#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2) -#define CONCATENATE2(arg1, arg2) arg1##arg2 +#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2) +#define CONCATENATE2(arg1, arg2) arg1##arg2 #define EXPAND(x) x #define FOR_EACH_1(what, x, ...) what(x) -#define FOR_EACH_2(what, x, ...)\ - what(x);\ - EXPAND(FOR_EACH_1(what, __VA_ARGS__)) -#define FOR_EACH_3(what, x, ...)\ - what(x);\ +#define FOR_EACH_2(what, x, ...) \ + what(x); \ + EXPAND(FOR_EACH_1(what, __VA_ARGS__)) +#define FOR_EACH_3(what, x, ...) \ + what(x); \ EXPAND(FOR_EACH_2(what, __VA_ARGS__)) -#define FOR_EACH_4(what, x, ...)\ - what(x);\ - EXPAND(FOR_EACH_3(what, __VA_ARGS__)) -#define FOR_EACH_5(what, x, ...)\ - what(x);\ - EXPAND(FOR_EACH_4(what, __VA_ARGS__)) -#define FOR_EACH_6(what, x, ...)\ - what(x);\ - EXPAND(FOR_EACH_5(what, __VA_ARGS__)) -#define FOR_EACH_7(what, x, ...)\ - what(x);\ - EXPAND(FOR_EACH_6(what, __VA_ARGS__)) -#define FOR_EACH_8(what, x, ...)\ - what(x);\ - EXPAND(FOR_EACH_7(what, __VA_ARGS__)) +#define FOR_EACH_4(what, x, ...) \ + what(x); \ + EXPAND(FOR_EACH_3(what, __VA_ARGS__)) +#define FOR_EACH_5(what, x, ...) \ + what(x); \ + EXPAND(FOR_EACH_4(what, __VA_ARGS__)) +#define FOR_EACH_6(what, x, ...) \ + what(x); \ + EXPAND(FOR_EACH_5(what, __VA_ARGS__)) +#define FOR_EACH_7(what, x, ...) \ + what(x); \ + EXPAND(FOR_EACH_6(what, __VA_ARGS__)) +#define FOR_EACH_8(what, x, ...) \ + what(x); \ + EXPAND(FOR_EACH_7(what, __VA_ARGS__)) #define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N()) #define FOR_EACH_NARG_(...) EXPAND(FOR_EACH_ARG_N(__VA_ARGS__)) #define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N #define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0 -#define CONCATENATE(x,y) x##y +#define CONCATENATE(x, y) x##y #define FOR_EACH_(N, what, ...) EXPAND(CONCATENATE(FOR_EACH_, N)(what, __VA_ARGS__)) #define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__) #define JADDEx_(jsonObj, field) jsonObj.insert(#field, field); diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index 0180a0e4..0cbfda18 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -1,30 +1,30 @@ #pragma once // #ifndef XTOSTRUCT_QT -# define XTOSTRUCT_QT + #define XTOSTRUCT_QT #endif // -#include -#include #include #include -#include +#include +#include #include -#include #include +#include #include +#include // Base support. -#include "base/Qv2rayLog.hpp" -#include "base/Qv2rayFeatures.hpp" -#include "base/JsonHelpers.hpp" #include "base/GlobalInstances.hpp" +#include "base/JsonHelpers.hpp" +#include "base/Qv2rayFeatures.hpp" +#include "base/Qv2rayLog.hpp" // Code Models -#include "base/models/QvSafeType.hpp" #include "base/models/CoreObjectModels.hpp" -#include "base/models/QvConfigModel.hpp" #include "base/models/QvConfigIdentifier.hpp" -#include "base/models/QvStartupConfig.hpp" +#include "base/models/QvConfigModel.hpp" #include "base/models/QvRuntimeConfig.hpp" +#include "base/models/QvSafeType.hpp" +#include "base/models/QvStartupConfig.hpp" using namespace std; using namespace std::chrono; @@ -38,9 +38,9 @@ using namespace Qv2ray::base::objects::transfer; // Linux users and DEs should handle the darkMode UI themselves. #ifndef QV2RAY_USE_BUILTIN_DARKTHEME -# ifndef Q_OS_LINUX -# define QV2RAY_USE_BUILTIN_DARKTHEME -# endif + #ifndef Q_OS_LINUX + #define QV2RAY_USE_BUILTIN_DARKTHEME + #endif #endif #define QV2RAY_BUILD_INFO QString(_QV2RAY_BUILD_INFO_STR_) @@ -48,9 +48,9 @@ using namespace Qv2ray::base::objects::transfer; // Base folder suffix. #ifdef QT_DEBUG -# define QV2RAY_CONFIG_DIR_SUFFIX "_debug/" + #define QV2RAY_CONFIG_DIR_SUFFIX "_debug/" #else -# define QV2RAY_CONFIG_DIR_SUFFIX "/" + #define QV2RAY_CONFIG_DIR_SUFFIX "/" #endif // Get Configured Config Dir Path @@ -68,17 +68,17 @@ using namespace Qv2ray::base::objects::transfer; #define QV2RAY_GENERATED_DIR (QV2RAY_CONFIG_DIR + "generated/") #define QV2RAY_GENERATED_FILE_PATH (QV2RAY_GENERATED_DIR + "config.gen.json") -#if ! defined (QV2RAY_DEFAULT_VCORE_PATH) && ! defined (QV2RAY_DEFAULT_VASSETS_PATH) -# define QV2RAY_DEFAULT_VASSETS_PATH (QV2RAY_CONFIG_DIR + "vcore/") -# ifdef Q_OS_WIN -# define QV2RAY_DEFAULT_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray.exe") -# else -# define QV2RAY_DEFAULT_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray") -# endif -#elif defined (QV2RAY_DEFAULT_VCORE_PATH) && defined (QV2RAY_DEFAULT_VASSETS_PATH) +#if !defined(QV2RAY_DEFAULT_VCORE_PATH) && !defined(QV2RAY_DEFAULT_VASSETS_PATH) + #define QV2RAY_DEFAULT_VASSETS_PATH (QV2RAY_CONFIG_DIR + "vcore/") + #ifdef Q_OS_WIN + #define QV2RAY_DEFAULT_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray.exe") + #else + #define QV2RAY_DEFAULT_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray") + #endif +#elif defined(QV2RAY_DEFAULT_VCORE_PATH) && defined(QV2RAY_DEFAULT_VASSETS_PATH) // ---- Using user-specified VCore and VAssets path #else -# error Both QV2RAY_DEFAULT_VCORE_PATH and QV2RAY_DEFAULT_VASSETS_PATH need to be presented when using manually specify the paths. + #error Both QV2RAY_DEFAULT_VCORE_PATH and QV2RAY_DEFAULT_VASSETS_PATH need to be presented when using manually specify the paths. #endif #ifdef Q_OS_WIN @@ -86,8 +86,8 @@ using namespace Qv2ray::base::objects::transfer; //# define QV2RAY_TPROXY_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray.exe") //# define QV2RAY_TPROXY_VCTL_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ctl.exe") #else -# define QV2RAY_TPROXY_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray") -# define QV2RAY_TPROXY_VCTL_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ctl") + #define QV2RAY_TPROXY_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray") + #define QV2RAY_TPROXY_VCTL_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ctl") #endif #define QV2RAY_VCORE_LOG_DIRNAME "logs/" @@ -95,15 +95,15 @@ using namespace Qv2ray::base::objects::transfer; #define QV2RAY_VCORE_ERROR_LOG_FILENAME "error.log" // GUI TOOLS -#define RED(obj) \ - auto _temp = obj->palette(); \ - _temp.setColor(QPalette::Text, Qt::red); \ +#define RED(obj) \ + auto _temp = obj->palette(); \ + _temp.setColor(QPalette::Text, Qt::red); \ obj->setPalette(_temp); -#define BLACK(obj) \ - obj->setPalette(QWidget::palette()); +#define BLACK(obj) obj->setPalette(QWidget::palette()); -#define QV2RAY_UI_RESOURCES_ROOT ((GlobalConfig.uiConfig.useDarkTheme) ? QStringLiteral(":/assets/icons/ui_dark/") : QStringLiteral(":/assets/icons/ui_light/")) +#define QV2RAY_UI_RESOURCES_ROOT \ + ((GlobalConfig.uiConfig.useDarkTheme) ? QStringLiteral(":/assets/icons/ui_dark/") : QStringLiteral(":/assets/icons/ui_light/")) #define QICON_R(file) QIcon(QV2RAY_UI_RESOURCES_ROOT + file) #define QSTRN(num) QString::number(num) @@ -117,7 +117,8 @@ using namespace Qv2ray::base::objects::transfer; #define QV2RAY_USE_FPROXY_KEY "_QV2RAY_USE_GLOBAL_FORWARD_PROXY_" -#define JSON_ROOT_TRY_REMOVE(obj) if (root.contains(obj)) { root.remove(obj); } +#define JSON_ROOT_TRY_REMOVE(obj) \ + if (root.contains(obj)) { root.remove(obj); } namespace Qv2ray { @@ -129,4 +130,4 @@ namespace Qv2ray isExiting = true; QApplication::quit(); } -} +} // namespace Qv2ray diff --git a/src/base/Qv2rayFeatures.hpp b/src/base/Qv2rayFeatures.hpp index ba731ebb..9de9ecf7 100644 --- a/src/base/Qv2rayFeatures.hpp +++ b/src/base/Qv2rayFeatures.hpp @@ -3,7 +3,7 @@ // // Always use libgRPC++ on windows platform. #ifndef WITH_LIB_GRPCPP -# ifdef _WIN32 -# define WITH_LIB_GRPCPP -# endif + #ifdef _WIN32 + #define WITH_LIB_GRPCPP + #endif #endif diff --git a/src/base/Qv2rayLog.cpp b/src/base/Qv2rayLog.cpp index 925e3120..560c7e57 100644 --- a/src/base/Qv2rayLog.cpp +++ b/src/base/Qv2rayLog.cpp @@ -1,5 +1,7 @@ #include "Qv2rayLog.hpp" + #include "base/GlobalInstances.hpp" + #include namespace Qv2ray::base @@ -15,18 +17,22 @@ namespace Qv2ray::base auto logString = "[" + module + "]: " + log; auto funcPrepend = QString::fromStdString(func + ":" + to_string(line) + " "); - if (isDebugBuild) { - // Debug build version, we only print info for DEBUG logs and print ALL info when debugLog presents, - if (type == QV2RAY_LOG_DEBUG || StartupOption.debugLog) { - logString = logString.prepend(funcPrepend); - } - } else { + if (isDebugBuild) + { + // Debug build version, we only print info for DEBUG logs and print + // ALL info when debugLog presents, + if (type == QV2RAY_LOG_DEBUG || StartupOption.debugLog) { logString = logString.prepend(funcPrepend); } + } + else + { // We only process DEBUG log in Release mode - if (type == QV2RAY_LOG_DEBUG) { - if (StartupOption.debugLog) { - logString = logString.prepend(funcPrepend); - } else { - // Discard debug log in non-debug Qv2ray version with no-debugLog mode. + if (type == QV2RAY_LOG_DEBUG) + { + if (StartupOption.debugLog) { logString = logString.prepend(funcPrepend); } + else + { + // Discard debug log in non-debug Qv2ray version with + // no-debugLog mode. return; } } @@ -50,4 +56,4 @@ namespace Qv2ray::base __purgerBuffer->clear(); return result; } -} +} // namespace Qv2ray::base diff --git a/src/base/Qv2rayLog.hpp b/src/base/Qv2rayLog.hpp index a06c20e5..2043403a 100644 --- a/src/base/Qv2rayLog.hpp +++ b/src/base/Qv2rayLog.hpp @@ -17,17 +17,17 @@ namespace Qv2ray::base { void __QV2RAY_LOG_FUNC__(int type, const std::string &func, int line, const QString &module, const QString &log); const QString readLastLog(); -} +} // namespace Qv2ray::base #define NEWLINE "\r\n" #define QV2RAY_LOG_NORMAL 0 -#define QV2RAY_LOG_DEBUG 1 +#define QV2RAY_LOG_DEBUG 1 #ifndef Q_OS_WIN -#define Qv2ray_PRETTY_FUNCTION __PRETTY_FUNCTION__ + #define Qv2ray_PRETTY_FUNCTION __PRETTY_FUNCTION__ #else -#define Qv2ray_PRETTY_FUNCTION __FUNCSIG__ + #define Qv2ray_PRETTY_FUNCTION __FUNCSIG__ #endif #define __LOG_IMPL(LEVEL, MODULE, MSG) __QV2RAY_LOG_FUNC__(LEVEL, Qv2ray_PRETTY_FUNCTION, __LINE__, MODULE, MSG); @@ -36,23 +36,23 @@ namespace Qv2ray::base #define DEBUG(MODULE, MSG) __LOG_IMPL(QV2RAY_LOG_DEBUG, (MODULE), (MSG)); // Log modules used by Qv2ray -const inline QString MODULE_INIT = "INIT" ; -const inline QString MODULE_MESSAGING = "BASE-MESSAGING" ; -const inline QString MODULE_UI = "CORE-UI" ; -const inline QString MODULE_GRAPH = "CORE-UI-GRAPH" ; -const inline QString MODULE_SETTINGS = "CORE-SETTINGS" ; -const inline QString MODULE_VCORE = "CORE-VCORE" ; +const inline QString MODULE_INIT = "INIT"; +const inline QString MODULE_MESSAGING = "BASE-MESSAGING"; +const inline QString MODULE_UI = "CORE-UI"; +const inline QString MODULE_GRAPH = "CORE-UI-GRAPH"; +const inline QString MODULE_SETTINGS = "CORE-SETTINGS"; +const inline QString MODULE_VCORE = "CORE-VCORE"; // -const inline QString MODULE_CONNECTION = "CORE-CONNECTION" ; -const inline QString MODULE_SUBSCRIPTION = "CORE-SUBSCRIPTION" ; -const inline QString MODULE_IMPORT = "CORE-IMPORT" ; -const inline QString MODULE_EXPORT = "CORE-EXPORT" ; +const inline QString MODULE_CONNECTION = "CORE-CONNECTION"; +const inline QString MODULE_SUBSCRIPTION = "CORE-SUBSCRIPTION"; +const inline QString MODULE_IMPORT = "CORE-IMPORT"; +const inline QString MODULE_EXPORT = "CORE-EXPORT"; // -const inline QString MODULE_NETWORK = "COMMON-NETWORK" ; -const inline QString MODULE_FILEIO = "COMMON-FILEIO" ; +const inline QString MODULE_NETWORK = "COMMON-NETWORK"; +const inline QString MODULE_FILEIO = "COMMON-FILEIO"; // -const inline QString MODULE_PROXY = "COMPONENT-PROXY" ; -const inline QString MODULE_UPDATE = "COMPONENT-UPDATE" ; -const inline QString MODULE_PLUGIN = "COMPONENT-PLUGIN" ; +const inline QString MODULE_PROXY = "COMPONENT-PROXY"; +const inline QString MODULE_UPDATE = "COMPONENT-UPDATE"; +const inline QString MODULE_PLUGIN = "COMPONENT-PLUGIN"; // ================================================================ -const inline QString MODULE_CORE_HANDLER = "QV2RAY-CORE"; +const inline QString MODULE_CORE_HANDLER = "QV2RAY-CORE"; diff --git a/src/base/models/CoreObjectModels.hpp b/src/base/models/CoreObjectModels.hpp index c8294b9b..7500273e 100644 --- a/src/base/models/CoreObjectModels.hpp +++ b/src/base/models/CoreObjectModels.hpp @@ -1,37 +1,46 @@ #pragma once -#include +#include "3rdparty/x2struct/x2struct.hpp" + #include #include -#include "3rdparty/x2struct/x2struct.hpp" +#include namespace Qv2ray::base::objects { // // Used in config generation - struct AccountObject { + struct AccountObject + { QString user; QString pass; XTOSTRUCT(O(user, pass)) }; // // - struct ApiObject { + struct ApiObject + { QString tag; QList services; - ApiObject() : tag("api"), services() {} + ApiObject() : tag("api"), services() + { + } XTOSTRUCT(O(tag, services)) }; // // - struct SystemPolicyObject { + struct SystemPolicyObject + { bool statsInboundUplink; bool statsInboundDownlink; - SystemPolicyObject() : statsInboundUplink(), statsInboundDownlink() {} + SystemPolicyObject() : statsInboundUplink(), statsInboundDownlink() + { + } XTOSTRUCT(O(statsInboundUplink, statsInboundDownlink)) }; // // - struct LevelPolicyObject { + struct LevelPolicyObject + { int handshake; int connIdle; int uplinkOnly; @@ -39,20 +48,26 @@ namespace Qv2ray::base::objects bool statsUserUplink; bool statsUserDownlink; int bufferSize; - LevelPolicyObject(): handshake(), connIdle(), uplinkOnly(), downlinkOnly(), statsUserUplink(), statsUserDownlink(), bufferSize() {} + LevelPolicyObject() : handshake(), connIdle(), uplinkOnly(), downlinkOnly(), statsUserUplink(), statsUserDownlink(), bufferSize() + { + } XTOSTRUCT(O(handshake, connIdle, uplinkOnly, downlinkOnly, statsUserUplink, statsUserDownlink, bufferSize)) }; // // - struct PolicyObject { + struct PolicyObject + { QMap level; QList system; - PolicyObject(): level(), system() {} + PolicyObject() : level(), system() + { + } XTOSTRUCT(O(level, system)) }; // // - struct RuleObject { + struct RuleObject + { // Added due to the request of @aliyuchang33 bool QV2RAY_RULE_ENABLED; bool QV2RAY_RULE_USE_BALANCER; @@ -70,65 +85,89 @@ namespace Qv2ray::base::objects QString attrs; QString outboundTag; QString balancerTag; - RuleObject() : QV2RAY_RULE_ENABLED(true), QV2RAY_RULE_USE_BALANCER(false), QV2RAY_RULE_TAG("new rule"), type("field"), domain(), ip(), port("1-65535"), network(""), source(), user(), inboundTag(), protocol(), attrs(), outboundTag(""), balancerTag("") {} - XTOSTRUCT(O(QV2RAY_RULE_ENABLED, QV2RAY_RULE_USE_BALANCER, QV2RAY_RULE_TAG, type, domain, ip, port, network, source, user, inboundTag, protocol, attrs, outboundTag, balancerTag)) + RuleObject() + : QV2RAY_RULE_ENABLED(true), QV2RAY_RULE_USE_BALANCER(false), QV2RAY_RULE_TAG("new rule"), type("field"), domain(), ip(), + port("1-65535"), network(""), source(), user(), inboundTag(), protocol(), attrs(), outboundTag(""), balancerTag("") + { + } + XTOSTRUCT(O(QV2RAY_RULE_ENABLED, QV2RAY_RULE_USE_BALANCER, QV2RAY_RULE_TAG, type, domain, ip, port, network, source, user, inboundTag, + protocol, attrs, outboundTag, balancerTag)) }; // // - struct BalancerObject { - QString tag ; + struct BalancerObject + { + QString tag; QList selector; - BalancerObject() : tag(), selector() {} + BalancerObject() : tag(), selector() + { + } XTOSTRUCT(O(tag, selector)) }; // // namespace transfer { - struct HTTPRequestObject { + struct HTTPRequestObject + { QString version; QString method; QList path; QMap> headers; - HTTPRequestObject(): version("1.1"), method("GET"), path(), headers() {} + HTTPRequestObject() : version("1.1"), method("GET"), path(), headers() + { + } XTOSTRUCT(O(version, method, path, headers)) }; // // - struct HTTPResponseObject { + struct HTTPResponseObject + { QString version; QString status; QString reason; QMap> headers; - HTTPResponseObject(): version("1.1"), status("200"), reason("OK"), headers() {} + HTTPResponseObject() : version("1.1"), status("200"), reason("OK"), headers() + { + } XTOSTRUCT(O(version, status, reason, headers)) }; // // - struct TCPHeader_M_Object { + struct TCPHeader_M_Object + { QString type; HTTPRequestObject request; HTTPResponseObject response; - TCPHeader_M_Object(): type("none"), request(), response() {} + TCPHeader_M_Object() : type("none"), request(), response() + { + } XTOSTRUCT(O(type, request, response)) }; // // - struct HeaderObject { + struct HeaderObject + { QString type; - HeaderObject(): type("none") {} + HeaderObject() : type("none") + { + } XTOSTRUCT(O(type)) }; // // - struct TCPObject { + struct TCPObject + { TCPHeader_M_Object header; - TCPObject(): header() {} + TCPObject() : header() + { + } XTOSTRUCT(O(header)) }; // // - struct KCPObject { + struct KCPObject + { int mtu = 1350; int tti = 20; int uplinkCapacity = 5; @@ -137,84 +176,111 @@ namespace Qv2ray::base::objects int readBufferSize = 1; int writeBufferSize = 1; HeaderObject header; - KCPObject(): header() {} + KCPObject() : header() + { + } XTOSTRUCT(O(mtu, tti, uplinkCapacity, downlinkCapacity, congestion, readBufferSize, writeBufferSize, header)) }; // // - struct WebSocketObject { + struct WebSocketObject + { QString path; QMap headers; - WebSocketObject(): path("/"), headers() {} + WebSocketObject() : path("/"), headers() + { + } XTOSTRUCT(O(path, headers)) }; // // - struct HttpObject { + struct HttpObject + { QList host; QString path; - HttpObject() : host(), path("/") {} + HttpObject() : host(), path("/") + { + } XTOSTRUCT(O(host, path)) }; // // - struct DomainSocketObject { + struct DomainSocketObject + { QString path; - DomainSocketObject(): path("/") {} + DomainSocketObject() : path("/") + { + } XTOSTRUCT(O(path)) }; // // - struct QuicObject { + struct QuicObject + { QString security; QString key; HeaderObject header; - QuicObject(): security(""), key(""), header() {} + QuicObject() : security(""), key(""), header() + { + } XTOSTRUCT(O(security, key, header)) }; // // - struct SockoptObject { + struct SockoptObject + { int mark; bool tcpFastOpen; QString tproxy; - SockoptObject(): mark(0), tcpFastOpen(false), tproxy("off") {} + SockoptObject() : mark(0), tcpFastOpen(false), tproxy("off") + { + } XTOSTRUCT(O(mark, tcpFastOpen, tproxy)) }; // // - struct CertificateObject { + struct CertificateObject + { QString usage; QString certificateFile; QString keyFile; QList certificate; QList key; - CertificateObject(): usage(), certificateFile(), keyFile(), certificate(), key() {} + CertificateObject() : usage(), certificateFile(), keyFile(), certificate(), key() + { + } XTOSTRUCT(O(usage, certificateFile, keyFile, certificate, key)) }; // // - struct TLSObject { + struct TLSObject + { QString serverName; bool allowInsecure; QList alpn; QList certificates; bool disableSystemRoot; - TLSObject(): serverName(), allowInsecure(), certificates(), disableSystemRoot() {} + TLSObject() : serverName(), allowInsecure(), certificates(), disableSystemRoot() + { + } XTOSTRUCT(O(serverName, allowInsecure, alpn, certificates, disableSystemRoot)) }; - } + } // namespace transfer // // - struct SniffingObject { + struct SniffingObject + { bool enabled = false; QList destOverride; - SniffingObject(): enabled(), destOverride() {} + SniffingObject() : enabled(), destOverride() + { + } XTOSTRUCT(O(enabled, destOverride)) }; // // - struct StreamSettingsObject { + struct StreamSettingsObject + { QString network; QString security; transfer::SockoptObject sockopt; @@ -225,15 +291,22 @@ namespace Qv2ray::base::objects transfer::HttpObject httpSettings; transfer::DomainSocketObject dsSettings; transfer::QuicObject quicSettings; - StreamSettingsObject(): network("tcp"), security("none"), sockopt(), tlsSettings(), tcpSettings(), kcpSettings(), wsSettings(), httpSettings(), dsSettings(), quicSettings() {} + StreamSettingsObject() + : network("tcp"), security("none"), sockopt(), tlsSettings(), tcpSettings(), kcpSettings(), wsSettings(), httpSettings(), + dsSettings(), quicSettings() + { + } XTOSTRUCT(O(network, security, sockopt, tcpSettings, tlsSettings, kcpSettings, wsSettings, httpSettings, dsSettings, quicSettings)) }; // // - struct MuxObject { + struct MuxObject + { bool enabled; int concurrency; - MuxObject(): enabled(), concurrency() {} + MuxObject() : enabled(), concurrency() + { + } XTOSTRUCT(O(enabled, concurrency)) }; // @@ -241,21 +314,28 @@ namespace Qv2ray::base::objects namespace protocol { // DNS, OutBound - struct DNSOut { + struct DNSOut + { QString network; QString address; int port; - DNSOut(): network(""), address("0.0.0.0"), port(0) {} + DNSOut() : network(""), address("0.0.0.0"), port(0) + { + } XTOSTRUCT(O(network, address, port)) }; // // MTProto, InBound || OutBound - struct MTProtoIn { - struct UserObject { + struct MTProtoIn + { + struct UserObject + { QString email; int level; QString secret; - UserObject() : email("user@domain.com"), level(0), secret("") {} + UserObject() : email("user@domain.com"), level(0), secret("") + { + } XTOSTRUCT(O(email, level, secret)) }; QList users; @@ -263,42 +343,55 @@ namespace Qv2ray::base::objects }; // // Socks, OutBound - struct SocksServerObject { - struct UserObject { + struct SocksServerObject + { + struct UserObject + { QString user; QString pass; int level; - UserObject(): user("username"), pass("password"), level(0) {} + UserObject() : user("username"), pass("password"), level(0) + { + } XTOSTRUCT(O(user, pass, level)) }; QString address; int port; QList users; - SocksServerObject(): address("0.0.0.0"), port(0), users() {} + SocksServerObject() : address("0.0.0.0"), port(0), users() + { + } XTOSTRUCT(O(address, port, users)) }; // // VMess Server - struct VMessServerObject { - struct UserObject { + struct VMessServerObject + { + struct UserObject + { QString id; int alterId; QString security; int level; - UserObject() : id(""), alterId(64), security("auto"), level(0) {} + UserObject() : id(""), alterId(64), security("auto"), level(0) + { + } XTOSTRUCT(O(id, alterId, security, level)) }; QString address; int port; QList users; - VMessServerObject(): address(""), port(0), users() {} + VMessServerObject() : address(""), port(0), users() + { + } XTOSTRUCT(O(address, port, users)) }; // // ShadowSocks Server - struct ShadowSocksServerObject { + struct ShadowSocksServerObject + { QString email; QString address; QString method; @@ -306,8 +399,11 @@ namespace Qv2ray::base::objects bool ota; int level; int port; - ShadowSocksServerObject(): email("user@domain.com"), address("0.0.0.0"), method("aes-256-cfb"), password(""), ota(false), level(0), port(0) {} + ShadowSocksServerObject() + : email("user@domain.com"), address("0.0.0.0"), method("aes-256-cfb"), password(""), ota(false), level(0), port(0) + { + } XTOSTRUCT(O(email, address, port, method, password, ota, level)) }; - } -} + } // namespace protocol +} // namespace Qv2ray::base::objects diff --git a/src/base/models/QvConfigIdentifier.hpp b/src/base/models/QvConfigIdentifier.hpp index 8f871966..b35fd8f3 100644 --- a/src/base/models/QvConfigIdentifier.hpp +++ b/src/base/models/QvConfigIdentifier.hpp @@ -1,38 +1,50 @@ #pragma once +#include "3rdparty/x2struct/x2struct.hpp" + #include #include -#include "3rdparty/x2struct/x2struct.hpp" namespace Qv2ray::base { using namespace std::chrono; // Common struct for Groups and Subscriptions - struct GroupObject_Config { + struct GroupObject_Config + { QString displayName; QList connections; int64_t importDate; - GroupObject_Config(): displayName(), connections(), importDate() { } + GroupObject_Config() : displayName(), connections(), importDate() + { + } XTOSTRUCT(O(displayName, connections, importDate)) }; - struct SubscriptionObject_Config : GroupObject_Config { + struct SubscriptionObject_Config : GroupObject_Config + { // QString address; int64_t lastUpdated; float updateInterval; - SubscriptionObject_Config(): address(""), lastUpdated(system_clock::to_time_t(system_clock::now())), updateInterval(10) { } + SubscriptionObject_Config() : address(""), lastUpdated(system_clock::to_time_t(system_clock::now())), updateInterval(10) + { + } XTOSTRUCT(O(lastUpdated, updateInterval, address, connections, displayName, importDate)) }; - struct ConnectionObject_Config { + struct ConnectionObject_Config + { QString displayName; int64_t importDate; int64_t lastConnected; int64_t latency; int64_t upLinkData; int64_t downLinkData; - ConnectionObject_Config(): displayName(), importDate(system_clock::to_time_t(system_clock::now())), lastConnected(), latency(0), upLinkData(0), downLinkData(0) { } + ConnectionObject_Config() + : displayName(), importDate(system_clock::to_time_t(system_clock::now())), lastConnected(), latency(0), upLinkData(0), + downLinkData(0) + { + } XTOSTRUCT(O(displayName, importDate, lastConnected, latency, upLinkData, downLinkData)) }; -} +} // namespace Qv2ray::base using namespace Qv2ray::base; diff --git a/src/base/models/QvConfigModel.hpp b/src/base/models/QvConfigModel.hpp index 7ca44201..521fc4f1 100644 --- a/src/base/models/QvConfigModel.hpp +++ b/src/base/models/QvConfigModel.hpp @@ -2,46 +2,59 @@ #include "3rdparty/x2struct/x2struct.hpp" #include "base/models/CoreObjectModels.hpp" #include "base/models/QvConfigIdentifier.hpp" + #include const int QV2RAY_CONFIG_VERSION = 9; namespace Qv2ray::base::config { - struct QvBarLine { + struct QvBarLine + { QString Family; bool Bold, Italic; int ColorA, ColorR, ColorG, ColorB; int ContentType; double Size; QString Message; - QvBarLine(): Family("Consolas"), Bold(true), Italic(false), ColorA(255), ColorR(255), ColorG(255), ColorB(255), - ContentType(0), Size(9), Message("") { } + QvBarLine() + : Family("Consolas"), Bold(true), Italic(false), ColorA(255), ColorR(255), ColorG(255), ColorB(255), ContentType(0), Size(9), + Message("") + { + } XTOSTRUCT(O(Bold, Italic, ColorA, ColorR, ColorG, ColorB, Size, Family, Message, ContentType)) }; - struct QvBarPage { + struct QvBarPage + { int OffsetYpx; QList Lines; - QvBarPage(): OffsetYpx(5) { } + QvBarPage() : OffsetYpx(5) + { + } XTOSTRUCT(O(OffsetYpx, Lines)) }; - struct Qv2rayToolBarConfig { + struct Qv2rayToolBarConfig + { QList Pages; XTOSTRUCT(O(Pages)) }; - struct Qv2rayPACConfig { + struct Qv2rayPACConfig + { bool enablePAC; int port; QString localIP; bool useSocksProxy; - Qv2rayPACConfig(): enablePAC(false), port(8989), useSocksProxy(false) { } + Qv2rayPACConfig() : enablePAC(false), port(8989), useSocksProxy(false) + { + } XTOSTRUCT(O(enablePAC, port, localIP, useSocksProxy)) }; - struct Qv2rayForwardProxyConfig { + struct Qv2rayForwardProxyConfig + { bool enableForwardProxy; QString type; QString serverAddress; @@ -49,12 +62,15 @@ namespace Qv2ray::base::config bool useAuth; QString username; QString password; - Qv2rayForwardProxyConfig(): enableForwardProxy(false), type("http"), serverAddress("127.0.0.1"), port(8008), - useAuth(false), username(), password() { } + Qv2rayForwardProxyConfig() + : enableForwardProxy(false), type("http"), serverAddress("127.0.0.1"), port(8008), useAuth(false), username(), password() + { + } XTOSTRUCT(O(enableForwardProxy, type, serverAddress, port, useAuth, username, password)) }; - struct Qv2rayInboundsConfig { + struct Qv2rayInboundsConfig + { QString listenip; bool setSystemProxy; Qv2rayPACConfig pacConfig; @@ -72,42 +88,56 @@ namespace Qv2ray::base::config bool http_useAuth; objects::AccountObject httpAccount; - Qv2rayInboundsConfig(): - listenip("127.0.0.1"), setSystemProxy(false), pacConfig(), - useSocks(true), socks_port(1088), socks_useAuth(false), socksUDP(true), socksLocalIP("127.0.0.1"), socksAccount(), - useHTTP(true), http_port(8888), http_useAuth(false), httpAccount() {} + Qv2rayInboundsConfig() + : listenip("127.0.0.1"), setSystemProxy(false), pacConfig(), useSocks(true), socks_port(1088), socks_useAuth(false), socksUDP(true), + socksLocalIP("127.0.0.1"), socksAccount(), useHTTP(true), http_port(8888), http_useAuth(false), httpAccount() + { + } - XTOSTRUCT(O(setSystemProxy, pacConfig, listenip, useSocks, useHTTP, socks_port, socks_useAuth, socksAccount, socksUDP, socksLocalIP, http_port, http_useAuth, httpAccount)) + XTOSTRUCT(O(setSystemProxy, pacConfig, listenip, useSocks, useHTTP, socks_port, socks_useAuth, socksAccount, socksUDP, socksLocalIP, + http_port, http_useAuth, httpAccount)) }; - struct Qv2rayUIConfig { + struct Qv2rayUIConfig + { QString theme; QString language; bool useDarkTheme; bool useDarkTrayIcon; int maximumLogLines; - Qv2rayUIConfig() : theme("Fusion"), language("en_US"), useDarkTheme(false), useDarkTrayIcon(true), maximumLogLines(500) { } + Qv2rayUIConfig() : theme("Fusion"), language("en_US"), useDarkTheme(false), useDarkTrayIcon(true), maximumLogLines(500) + { + } XTOSTRUCT(O(theme, language, useDarkTheme, useDarkTrayIcon, maximumLogLines)) }; - struct Qv2rayConnectionConfig { + struct Qv2rayConnectionConfig + { bool bypassCN; bool enableProxy; bool withLocalDNS; QList dnsList; Qv2rayForwardProxyConfig forwardProxyConfig; - Qv2rayConnectionConfig() : bypassCN(true), enableProxy(true), withLocalDNS(false), dnsList(QStringList() << "8.8.4.4" << "1.1.1.1") { } + Qv2rayConnectionConfig() + : bypassCN(true), enableProxy(true), withLocalDNS(false), dnsList(QStringList() << "8.8.4.4" + << "1.1.1.1") + { + } XTOSTRUCT(O(bypassCN, enableProxy, withLocalDNS, dnsList, forwardProxyConfig)) }; - struct Qv2rayAPIConfig { + struct Qv2rayAPIConfig + { bool enableAPI; int statsPort; - Qv2rayAPIConfig(): enableAPI(true), statsPort(15490) { } + Qv2rayAPIConfig() : enableAPI(true), statsPort(15490) + { + } XTOSTRUCT(O(enableAPI, statsPort)) }; - struct Qv2rayConfig { + struct Qv2rayConfig + { int config_version; bool tProxySupport; int logLevel; @@ -129,23 +159,13 @@ namespace Qv2ray::base::config Qv2rayInboundsConfig inboundConfig; Qv2rayConnectionConfig connectionConfig; - Qv2rayConfig(): - config_version(QV2RAY_CONFIG_VERSION), - tProxySupport(false), - logLevel(), - v2CorePath(), - v2AssetsPath(), - ignoredVersion(), - groups(), - subscriptions(), - connections(), - uiConfig(), apiConfig(), toolBarConfig(), inboundConfig(), connectionConfig() { } + Qv2rayConfig() + : config_version(QV2RAY_CONFIG_VERSION), tProxySupport(false), logLevel(), v2CorePath(), v2AssetsPath(), ignoredVersion(), groups(), + subscriptions(), connections(), uiConfig(), apiConfig(), toolBarConfig(), inboundConfig(), connectionConfig() + { + } - XTOSTRUCT(O(config_version, ignoredVersion, - tProxySupport, - logLevel, uiConfig, - v2CorePath, v2AssetsPath, - groups, connections, subscriptions, - autoStartId, inboundConfig, connectionConfig, toolBarConfig, apiConfig)) + XTOSTRUCT(O(config_version, ignoredVersion, tProxySupport, logLevel, uiConfig, v2CorePath, v2AssetsPath, groups, connections, + subscriptions, autoStartId, inboundConfig, connectionConfig, toolBarConfig, apiConfig)) }; -} +} // namespace Qv2ray::base::config diff --git a/src/base/models/QvRuntimeConfig.hpp b/src/base/models/QvRuntimeConfig.hpp index 944dd4a1..8995e7f4 100644 --- a/src/base/models/QvRuntimeConfig.hpp +++ b/src/base/models/QvRuntimeConfig.hpp @@ -5,8 +5,9 @@ namespace Qv2ray::base { - struct Qv2rayRuntimeConfig { + struct Qv2rayRuntimeConfig + { // bool screenShotHideQv2ray = false; }; -} +} // namespace Qv2ray::base diff --git a/src/base/models/QvSafeType.hpp b/src/base/models/QvSafeType.hpp index 0244f8ed..adf17f6d 100644 --- a/src/base/models/QvSafeType.hpp +++ b/src/base/models/QvSafeType.hpp @@ -1,15 +1,22 @@ #pragma once -#include #include #include +#include -#define SAFE_TYPEDEF_EXTRA(Base, name, extra) \ - class name : public Base { \ - public: \ - template \ - explicit name (Args... args) : Base(args...) {} \ - const Base& raw() const { return *this; } \ - extra }; +#define SAFE_TYPEDEF_EXTRA(Base, name, extra) \ + class name : public Base \ + { \ + public: \ + template \ + explicit name(Args... args) : Base(args...) \ + { \ + } \ + const Base &raw() const \ + { \ + return *this; \ + } \ + extra \ + }; #define nothing #define SAFE_TYPEDEF(Base, name) SAFE_TYPEDEF_EXTRA(Base, name, nothing) @@ -31,5 +38,4 @@ namespace Qv2ray::base::safetype SAFE_TYPEDEF(QJsonObject, ROUTERULE) SAFE_TYPEDEF(INOUTLIST, OUTBOUNDS) SAFE_TYPEDEF(INOUTLIST, INBOUNDS) -} - +} // namespace Qv2ray::base::safetype diff --git a/src/base/models/QvStartupConfig.hpp b/src/base/models/QvStartupConfig.hpp index 224a9635..21c61b0e 100644 --- a/src/base/models/QvStartupConfig.hpp +++ b/src/base/models/QvStartupConfig.hpp @@ -4,7 +4,8 @@ namespace Qv2ray { namespace base { - struct QvStartupOptions { + struct QvStartupOptions + { /// No API subsystem bool noAPI; /// Explicitly run as root user. @@ -14,5 +15,5 @@ namespace Qv2ray /// Enable Network toolbar plugin. bool enableToolbarPlguin; }; - } -} + } // namespace base +} // namespace Qv2ray diff --git a/src/common/CommandArgs.cpp b/src/common/CommandArgs.cpp index 54081b41..b394c850 100644 --- a/src/common/CommandArgs.cpp +++ b/src/common/CommandArgs.cpp @@ -1,15 +1,16 @@ #include "CommandArgs.hpp" + #include "base/Qv2rayBase.hpp" namespace Qv2ray::common { - QvCommandArgParser::QvCommandArgParser() : QObject(), - noAPIOption("noAPI", QObject::tr("Disable gRPC API subsystems.")), - runAsRootOption("I-just-wanna-run-with-root", QObject::tr("Explicitly run Qv2ray as root.")), - debugOption("debug", QObject::tr("Enable Debug Output")), - withToolbarOption("withToolbarPlugin", QObject::tr("Enable Qv2ray network toolbar plugin")), - // - helpOption("FAKE"), versionOption("FAKE") + QvCommandArgParser::QvCommandArgParser() + : QObject(), noAPIOption("noAPI", QObject::tr("Disable gRPC API subsystems.")), + runAsRootOption("I-just-wanna-run-with-root", QObject::tr("Explicitly run Qv2ray as root.")), + debugOption("debug", QObject::tr("Enable Debug Output")), + withToolbarOption("withToolbarPlugin", QObject::tr("Enable Qv2ray network toolbar plugin")), + // + helpOption("FAKE"), versionOption("FAKE") { parser.setApplicationDescription(QObject::tr("Qv2ray - A cross-platform Qt frontend for V2ray.")); parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); @@ -24,33 +25,36 @@ namespace Qv2ray::common CommandLineParseResult QvCommandArgParser::ParseCommandLine(QString *errorMessage) { - if (!parser.parse(QCoreApplication::arguments())) { + if (!parser.parse(QCoreApplication::arguments())) + { *errorMessage = parser.errorText(); return CommandLineError; } - if (parser.isSet(versionOption)) - return CommandLineVersionRequested; + if (parser.isSet(versionOption)) return CommandLineVersionRequested; - if (parser.isSet(helpOption)) - return CommandLineHelpRequested; + if (parser.isSet(helpOption)) return CommandLineHelpRequested; - if (parser.isSet(noAPIOption)) { + if (parser.isSet(noAPIOption)) + { DEBUG(MODULE_INIT, "noAPIOption is set.") StartupOption.noAPI = true; } - if (parser.isSet(runAsRootOption)) { + if (parser.isSet(runAsRootOption)) + { DEBUG(MODULE_INIT, "runAsRootOption is set.") StartupOption.forceRunAsRootUser = true; } - if (parser.isSet(debugOption)) { + if (parser.isSet(debugOption)) + { DEBUG(MODULE_INIT, "debugOption is set.") StartupOption.debugLog = true; } - if (parser.isSet(withToolbarOption)) { + if (parser.isSet(withToolbarOption)) + { DEBUG(MODULE_INIT, "withToolbarOption is set.") StartupOption.enableToolbarPlguin = true; } @@ -58,4 +62,4 @@ namespace Qv2ray::common return CommandLineOk; } -} +} // namespace Qv2ray::common diff --git a/src/common/CommandArgs.hpp b/src/common/CommandArgs.hpp index 72092b52..d77444e7 100644 --- a/src/common/CommandArgs.hpp +++ b/src/common/CommandArgs.hpp @@ -4,7 +4,8 @@ namespace Qv2ray::common { - enum CommandLineParseResult { + enum CommandLineParseResult + { CommandLineOk, CommandLineError, CommandLineVersionRequested, @@ -12,24 +13,24 @@ namespace Qv2ray::common }; class QvCommandArgParser : public QObject { - Q_OBJECT - public: - QvCommandArgParser(); - CommandLineParseResult ParseCommandLine(QString *errorMessage); - const QCommandLineParser *Parser() - { - return &parser; - } + Q_OBJECT + public: + QvCommandArgParser(); + CommandLineParseResult ParseCommandLine(QString *errorMessage); + const QCommandLineParser *Parser() + { + return &parser; + } - private: - QCommandLineParser parser; - QCommandLineOption noAPIOption; - QCommandLineOption runAsRootOption; - QCommandLineOption debugOption; - QCommandLineOption withToolbarOption; - QCommandLineOption helpOption; - QCommandLineOption versionOption; + private: + QCommandLineParser parser; + QCommandLineOption noAPIOption; + QCommandLineOption runAsRootOption; + QCommandLineOption debugOption; + QCommandLineOption withToolbarOption; + QCommandLineOption helpOption; + QCommandLineOption versionOption; }; -} +} // namespace Qv2ray::common using namespace Qv2ray::common; diff --git a/src/common/HTTPRequestHelper.cpp b/src/common/HTTPRequestHelper.cpp index dbf2856d..eead1a0e 100644 --- a/src/common/HTTPRequestHelper.cpp +++ b/src/common/HTTPRequestHelper.cpp @@ -1,7 +1,9 @@ #include "HTTPRequestHelper.hpp" + +#include "base/Qv2rayBase.hpp" + #include #include -#include "base/Qv2rayBase.hpp" namespace Qv2ray::common { @@ -18,7 +20,8 @@ namespace Qv2ray::common { QUrl qUrl = QUrl(url); - if (!qUrl.isValid()) { + if (!qUrl.isValid()) + { LOG(MODULE_NETWORK, "Provided URL is invalid: " + url) return false; } @@ -37,11 +40,14 @@ namespace Qv2ray::common { this->setUrl(url); - if (useProxy) { + if (useProxy) + { auto proxy = QNetworkProxyFactory::systemProxyForQuery(); accessManager.setProxy(proxy.first()); LOG(MODULE_NETWORK, "Sync get is using system proxy settings") - } else { + } + else + { accessManager.setProxy(QNetworkProxy(QNetworkProxy::ProxyType::NoProxy)); } @@ -62,28 +68,34 @@ namespace Qv2ray::common void QvHttpRequestHelper::get(const QString &url) { this->setUrl(url); - // request.setRawHeader("Content-Type", "application/x-www-form-urlencoded"); + // request.setRawHeader("Content-Type", + // "application/x-www-form-urlencoded"); reply = accessManager.get(request); connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished_p); connect(reply, &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead); } - //void QvHttpRequestHelper::post(const QString &url, const QByteArray &data) + // void QvHttpRequestHelper::post(const QString &url, const QByteArray + // &data) //{ // this->setUrl(url); // request.setRawHeader("Content-Type", "application/json"); // reply = accessManager.post(request, data); - // connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished); - // connect(reply, &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead); + // connect(reply, &QNetworkReply::finished, this, + // &QvHttpRequestHelper::onRequestFinished); connect(reply, + // &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead); //} - // void QvHttpRequestHelper::put(const QString &url, const QByteArray &data) + // void QvHttpRequestHelper::put(const QString &url, const QByteArray + // &data) // { // this->setUrl(url); // request.setRawHeader("Content-Type", "application/json"); // reply = accessManager.put(request, data); - // connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished); - // connect(reply, &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead); + // connect(reply, &QNetworkReply::finished, this, + // &QvHttpRequestHelper::onRequestFinished); connect(reply, + // &QNetworkReply::readyRead, this, + // &QvHttpRequestHelper::onReadyRead); // } // void QvHttpRequestHelper::del(const QString &url) @@ -91,26 +103,31 @@ namespace Qv2ray::common // this->setUrl(url); // request.setRawHeader("Content-Type", "application/json"); // reply = accessManager.deleteResource(request); - // connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished); - // connect(reply, &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead); + // connect(reply, &QNetworkReply::finished, this, + // &QvHttpRequestHelper::onRequestFinished); connect(reply, + // &QNetworkReply::readyRead, this, + // &QvHttpRequestHelper::onReadyRead); // } - // void QvHttpRequestHelper::login(const QString &url, const QByteArray &data) + // void QvHttpRequestHelper::login(const QString &url, const QByteArray + // &data) // { // this->setUrl(url); - // request.setRawHeader("Content-Type", "application/x-www-form-urlencoded"); - // reply = accessManager.post(request, data); - // connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished); - // connect(reply, &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead); + // request.setRawHeader("Content-Type", + // "application/x-www-form-urlencoded"); reply = + // accessManager.post(request, data); connect(reply, + // &QNetworkReply::finished, this, + // &QvHttpRequestHelper::onRequestFinished); connect(reply, + // &QNetworkReply::readyRead, this, + // &QvHttpRequestHelper::onReadyRead); // } void QvHttpRequestHelper::onRequestFinished_p() { - if (reply->attribute(QNetworkRequest::HTTP2WasUsedAttribute).toBool()) { - DEBUG(MODULE_NETWORK, "HTTP/2 was used.") - } + if (reply->attribute(QNetworkRequest::HTTP2WasUsedAttribute).toBool()) { DEBUG(MODULE_NETWORK, "HTTP/2 was used.") } - if (reply->error() != QNetworkReply::NoError) { + if (reply->error() != QNetworkReply::NoError) + { QString error = QMetaEnum::fromType().key(reply->error()); LOG(MODULE_NETWORK, "Network request error string: " + error) QByteArray empty; @@ -125,4 +142,4 @@ namespace Qv2ray::common DEBUG(MODULE_NETWORK, "A request is now ready read") this->data += reply->readAll(); } -} +} // namespace Qv2ray::common diff --git a/src/common/HTTPRequestHelper.hpp b/src/common/HTTPRequestHelper.hpp index 73c08d3b..00b1c611 100644 --- a/src/common/HTTPRequestHelper.hpp +++ b/src/common/HTTPRequestHelper.hpp @@ -18,45 +18,46 @@ #pragma once -#include -#include -#include #include +#include +#include +#include namespace Qv2ray::common { class QvHttpRequestHelper : public QObject { - Q_OBJECT - public: - explicit QvHttpRequestHelper(); - ~QvHttpRequestHelper(); - bool setUrl(const QString &url); - void setHeader(const QByteArray &key, const QByteArray &value); - // get - QByteArray syncget(const QString &url, bool useProxy); - void get(const QString &url); - //// insert - //void post(const QString &url, const QByteArray &data); - //// update - //void put(const QString &url, const QByteArray &data); - //// delete - //void del(const QString &url); - //void login(const QString &url, const QByteArray &data); - signals: - void httpRequestFinished(QByteArray &data); + Q_OBJECT + public: + explicit QvHttpRequestHelper(); + ~QvHttpRequestHelper(); + bool setUrl(const QString &url); + void setHeader(const QByteArray &key, const QByteArray &value); + // get + QByteArray syncget(const QString &url, bool useProxy); + void get(const QString &url); + //// insert + // void post(const QString &url, const QByteArray &data); + //// update + // void put(const QString &url, const QByteArray &data); + //// delete + // void del(const QString &url); + // void login(const QString &url, const QByteArray &data); + signals: + void httpRequestFinished(QByteArray &data); - public slots: - void onRequestFinished_p(); - private slots: - void onReadyRead(); - private: - QByteArray data; - QUrl url; - QNetworkReply *reply; - QNetworkRequest request; - QNetworkAccessManager accessManager; + public slots: + void onRequestFinished_p(); + private slots: + void onReadyRead(); + + private: + QByteArray data; + QUrl url; + QNetworkReply *reply; + QNetworkRequest request; + QNetworkAccessManager accessManager; }; -} +} // namespace Qv2ray::common using namespace Qv2ray::common; diff --git a/src/common/LogHighlighter.cpp b/src/common/LogHighlighter.cpp index e4ba39ec..46c6f42f 100644 --- a/src/common/LogHighlighter.cpp +++ b/src/common/LogHighlighter.cpp @@ -1,30 +1,32 @@ #include "LogHighlighter.hpp" + #include "common/QvHelpers.hpp" #define TO_EOL "(([\\s\\S]*)|([\\d\\D]*)|([\\w\\W]*))$" namespace Qv2ray::common { - SyntaxHighlighter::SyntaxHighlighter(bool darkMode, QTextDocument *parent) - : QSyntaxHighlighter(parent) + SyntaxHighlighter::SyntaxHighlighter(bool darkMode, QTextDocument *parent) : QSyntaxHighlighter(parent) { HighlightingRule rule; keywordFormat.setForeground(darkMode ? Qt::darkMagenta : Qt::magenta); keywordFormat.setFontWeight(QFont::Bold); - const QString keywordPatterns[] = { - "tcp", "udp" - }; + const QString keywordPatterns[] = { "tcp", "udp" }; - for (const QString &pattern : keywordPatterns) { + for (const QString &pattern : keywordPatterns) + { rule.pattern = QRegularExpression(pattern); rule.format = keywordFormat; highlightingRules.append(rule); } - if (darkMode) { + if (darkMode) + { ipHostFormat.setForeground(Qt::yellow); warningFormat.setForeground(QColor(230, 180, 0)); - } else { + } + else + { ipHostFormat.setForeground(Qt::black); ipHostFormat.setFontWeight(QFont::Bold); warningFormat.setForeground(Qt::white); @@ -49,7 +51,7 @@ namespace Qv2ray::common rule.format = debugFormat; highlightingRules.append(rule); // - infoFormat.setForeground(darkMode ? Qt::lightGray : Qt::darkCyan); + infoFormat.setForeground(darkMode ? Qt::lightGray : Qt::darkCyan); rule.pattern = QRegularExpression("\\[[Ii]nfo\\]" TO_EOL); rule.format = infoFormat; highlightingRules.append(rule); @@ -119,10 +121,12 @@ namespace Qv2ray::common void SyntaxHighlighter::highlightBlock(const QString &text) { - for (const HighlightingRule &rule : qAsConst(highlightingRules)) { + for (const HighlightingRule &rule : qAsConst(highlightingRules)) + { QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); - while (matchIterator.hasNext()) { + while (matchIterator.hasNext()) + { QRegularExpressionMatch match = matchIterator.next(); setFormat(match.capturedStart(), match.capturedLength(), rule.format); } @@ -130,4 +134,4 @@ namespace Qv2ray::common setCurrentBlockState(0); } -} +} // namespace Qv2ray::common diff --git a/src/common/LogHighlighter.hpp b/src/common/LogHighlighter.hpp index ba8c6edf..7a4284e0 100644 --- a/src/common/LogHighlighter.hpp +++ b/src/common/LogHighlighter.hpp @@ -49,45 +49,46 @@ ****************************************************************************/ #pragma once +#include #include #include -#include #include namespace Qv2ray::common { class SyntaxHighlighter : public QSyntaxHighlighter { - Q_OBJECT + Q_OBJECT - public: - explicit SyntaxHighlighter(bool darkMode, QTextDocument *parent = nullptr); + public: + explicit SyntaxHighlighter(bool darkMode, QTextDocument *parent = nullptr); - protected: - void highlightBlock(const QString &text) override; + protected: + void highlightBlock(const QString &text) override; - private: - struct HighlightingRule { - QRegularExpression pattern; - QTextCharFormat format; - }; - QVector highlightingRules; + private: + struct HighlightingRule + { + QRegularExpression pattern; + QTextCharFormat format; + }; + QVector highlightingRules; - QTextCharFormat keywordFormat; - QTextCharFormat dateFormat; - QTextCharFormat acceptedFormat; - QTextCharFormat rejectedFormat; - QTextCharFormat failedFormat; - QTextCharFormat warningFormat; - QTextCharFormat infoFormat; - QTextCharFormat debugFormat; - QTextCharFormat timeFormat; - QTextCharFormat ipHostFormat; - QTextCharFormat v2rayComponentFormat; - // - QTextCharFormat qvAppLogFormat; - QTextCharFormat qvAppDebugLogFormat; + QTextCharFormat keywordFormat; + QTextCharFormat dateFormat; + QTextCharFormat acceptedFormat; + QTextCharFormat rejectedFormat; + QTextCharFormat failedFormat; + QTextCharFormat warningFormat; + QTextCharFormat infoFormat; + QTextCharFormat debugFormat; + QTextCharFormat timeFormat; + QTextCharFormat ipHostFormat; + QTextCharFormat v2rayComponentFormat; + // + QTextCharFormat qvAppLogFormat; + QTextCharFormat qvAppDebugLogFormat; }; -} +} // namespace Qv2ray::common using namespace Qv2ray::common; diff --git a/src/common/QJsonModel.cpp b/src/common/QJsonModel.cpp index 479723a5..7dafbe60 100644 --- a/src/common/QJsonModel.cpp +++ b/src/common/QJsonModel.cpp @@ -10,8 +10,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -23,10 +23,10 @@ */ #include "QJsonModel.hpp" -#include -#include -#include +#include +#include +#include QJsonTreeItem::QJsonTreeItem(QJsonTreeItem *parent) { @@ -60,8 +60,7 @@ int QJsonTreeItem::childCount() const int QJsonTreeItem::row() const { - if (mParent) - return mParent->mChilds.indexOf(const_cast(this)); + if (mParent) return mParent->mChilds.indexOf(const_cast(this)); return 0; } @@ -101,27 +100,34 @@ QJsonTreeItem *QJsonTreeItem::load(const QJsonValue &value, QJsonTreeItem *paren QJsonTreeItem *rootItem = new QJsonTreeItem(parent); rootItem->setKey("root"); - if (value.isObject()) { - //Get all QJsonValue childs - for (QString key : value.toObject().keys()) { + if (value.isObject()) + { + // Get all QJsonValue childs + for (QString key : value.toObject().keys()) + { QJsonValue v = value.toObject().value(key); QJsonTreeItem *child = load(v, rootItem); child->setKey(key); child->setType(v.type()); rootItem->appendChild(child); } - } else if (value.isArray()) { - //Get all QJsonValue childs + } + else if (value.isArray()) + { + // Get all QJsonValue childs int index = 0; - for (QJsonValue v : value.toArray()) { + for (QJsonValue v : value.toArray()) + { QJsonTreeItem *child = load(v, rootItem); child->setKey(QString::number(index)); child->setType(v.type()); rootItem->appendChild(child); ++index; } - } else { + } + else + { rootItem->setValue(value.toVariant().toString()); rootItem->setType(value.type()); } @@ -131,35 +137,27 @@ 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("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("value"); 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("value"); 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("value"); @@ -176,10 +174,13 @@ bool QJsonModel::load(const QString &fileName) QFile file(fileName); bool success = false; - if (file.open(QIODevice::ReadOnly)) { + if (file.open(QIODevice::ReadOnly)) + { success = load(&file); file.close(); - } else success = false; + } + else + success = false; return success; } @@ -193,14 +194,18 @@ bool QJsonModel::loadJson(const QByteArray &json) { auto const &jdoc = QJsonDocument::fromJson(json); - if (!jdoc.isNull()) { + if (!jdoc.isNull()) + { beginResetModel(); delete mRootItem; - if (jdoc.isArray()) { + if (jdoc.isArray()) + { mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.array())); mRootItem->setType(QJsonValue::Array); - } else { + } + else + { mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.object())); mRootItem->setType(QJsonValue::Object); } @@ -213,24 +218,21 @@ bool QJsonModel::loadJson(const QByteArray &json) return false; } - QVariant QJsonModel::data(const QModelIndex &index, int role) const { - if (!index.isValid()) - return QVariant(); + if (!index.isValid()) return QVariant(); QJsonTreeItem *item = static_cast(index.internalPointer()); - if (role == Qt::DisplayRole) { - if (index.column() == 0) - return QString("%1").arg(item->key()); + if (role == Qt::DisplayRole) + { + if (index.column() == 0) return QString("%1").arg(item->key()); - if (index.column() == 1) - return QString("%1").arg(item->value()); - } else if (Qt::EditRole == role) { - if (index.column() == 1) { - return QString("%1").arg(item->value()); - } + if (index.column() == 1) return QString("%1").arg(item->value()); + } + else if (Qt::EditRole == role) + { + if (index.column() == 1) { return QString("%1").arg(item->value()); } } return QVariant(); @@ -240,11 +242,13 @@ bool QJsonModel::setData(const QModelIndex &index, const QVariant &value, int ro { int col = index.column(); - if (Qt::EditRole == role) { - if (col == 1) { + if (Qt::EditRole == role) + { + if (col == 1) + { QJsonTreeItem *item = static_cast(index.internalPointer()); item->setValue(value.toString()); - emit dataChanged(index, index, {Qt::EditRole}); + emit dataChanged(index, index, { Qt::EditRole }); return true; } } @@ -252,49 +256,40 @@ bool QJsonModel::setData(const QModelIndex &index, const QVariant &value, int ro return false; } - - QVariant QJsonModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (role != Qt::DisplayRole) - return QVariant(); + if (role != Qt::DisplayRole) return QVariant(); - if (orientation == Qt::Horizontal) { - return mHeaders.value(section); - } else + if (orientation == Qt::Horizontal) { return mHeaders.value(section); } + else return QVariant(); } QModelIndex QJsonModel::index(int row, int column, const QModelIndex &parent) const { - if (!hasIndex(row, column, parent)) - return QModelIndex(); + if (!hasIndex(row, column, parent)) return QModelIndex(); QJsonTreeItem *parentItem; - if (!parent.isValid()) - parentItem = mRootItem; + if (!parent.isValid()) parentItem = mRootItem; else parentItem = static_cast(parent.internalPointer()); QJsonTreeItem *childItem = parentItem->child(row); - if (childItem) - return createIndex(row, column, childItem); + if (childItem) return createIndex(row, column, childItem); else return QModelIndex(); } QModelIndex QJsonModel::parent(const QModelIndex &index) const { - if (!index.isValid()) - return QModelIndex(); + if (!index.isValid()) return QModelIndex(); QJsonTreeItem *childItem = static_cast(index.internalPointer()); QJsonTreeItem *parentItem = childItem->parent(); - if (parentItem == mRootItem) - return QModelIndex(); + if (parentItem == mRootItem) return QModelIndex(); return createIndex(parentItem->row(), 0, parentItem); } @@ -303,11 +298,9 @@ int QJsonModel::rowCount(const QModelIndex &parent) const { QJsonTreeItem *parentItem; - if (parent.column() > 0) - return 0; + if (parent.column() > 0) return 0; - if (!parent.isValid()) - parentItem = mRootItem; + if (!parent.isValid()) parentItem = mRootItem; else parentItem = static_cast(parent.internalPointer()); @@ -322,14 +315,14 @@ int QJsonModel::columnCount(const QModelIndex &parent) const Qt::ItemFlags QJsonModel::flags(const QModelIndex &index) const { - int col = index.column(); + int col = index.column(); auto item = static_cast(index.internalPointer()); auto isArray = QJsonValue::Array == item->type(); auto isObject = QJsonValue::Object == item->type(); - if ((col == 1) && !(isArray || isObject)) { - return Qt::ItemIsEditable | QAbstractItemModel::flags(index); - } else { + if ((col == 1) && !(isArray || isObject)) { return Qt::ItemIsEditable | QAbstractItemModel::flags(index); } + else + { return QAbstractItemModel::flags(index); } } @@ -339,40 +332,47 @@ QJsonDocument QJsonModel::json() const auto v = genJson(mRootItem); QJsonDocument doc; - if (v.isObject()) { - doc = QJsonDocument(v.toObject()); - } else { + if (v.isObject()) { doc = QJsonDocument(v.toObject()); } + else + { doc = QJsonDocument(v.toArray()); } return doc; } -QJsonValue QJsonModel::genJson(QJsonTreeItem *item) const +QJsonValue QJsonModel::genJson(QJsonTreeItem *item) const { - auto type = item->type(); - int nchild = item->childCount(); + auto type = item->type(); + int nchild = item->childCount(); - if (QJsonValue::Object == type) { + if (QJsonValue::Object == type) + { QJsonObject jo; - for (int i = 0; i < nchild; ++i) { + for (int i = 0; i < nchild; ++i) + { auto ch = item->child(i); auto key = ch->key(); jo.insert(key, genJson(ch)); } - return jo; - } else if (QJsonValue::Array == type) { + return jo; + } + else if (QJsonValue::Array == type) + { QJsonArray arr; - for (int i = 0; i < nchild; ++i) { + for (int i = 0; i < nchild; ++i) + { auto ch = item->child(i); arr.append(genJson(ch)); } return arr; - } else { + } + else + { QJsonValue va(item->value()); return va; } diff --git a/src/common/QJsonModel.hpp b/src/common/QJsonModel.hpp index c88679ed..69bddec8 100644 --- a/src/common/QJsonModel.hpp +++ b/src/common/QJsonModel.hpp @@ -1,101 +1,94 @@ /* -* The MIT License (MIT) -* -* Copyright (c) 2011 SCHUTZ Sacha -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ + * The MIT License (MIT) + * + * Copyright (c) 2011 SCHUTZ Sacha + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ #pragma once #include -#include -#include -#include -#include #include +#include +#include +#include +#include class QJsonModel; class QJsonItem; class QJsonTreeItem { - public: - QJsonTreeItem(QJsonTreeItem *parent = nullptr); - ~QJsonTreeItem(); - void appendChild(QJsonTreeItem *item); - QJsonTreeItem *child(int row); - QJsonTreeItem *parent(); - int childCount() const; - int row() const; - void setKey(const QString &key); - void setValue(const QString &value); - void setType(const QJsonValue::Type &type); - QString key() const; - QString value() const; - QJsonValue::Type type() const; - - - static QJsonTreeItem *load(const QJsonValue &value, QJsonTreeItem *parent = 0); - - protected: - - - private: - QString mKey; - QString mValue; - QJsonValue::Type mType; - QList mChilds; - QJsonTreeItem *mParent; + public: + QJsonTreeItem(QJsonTreeItem *parent = nullptr); + ~QJsonTreeItem(); + void appendChild(QJsonTreeItem *item); + QJsonTreeItem *child(int row); + QJsonTreeItem *parent(); + int childCount() const; + int row() const; + void setKey(const QString &key); + void setValue(const QString &value); + void setType(const QJsonValue::Type &type); + QString key() const; + QString value() const; + QJsonValue::Type type() const; + static QJsonTreeItem *load(const QJsonValue &value, QJsonTreeItem *parent = 0); + protected: + private: + QString mKey; + QString mValue; + QJsonValue::Type mType; + QList mChilds; + QJsonTreeItem *mParent; }; //--------------------------------------------------- class QJsonModel : public QAbstractItemModel { - Q_OBJECT - public: - explicit QJsonModel(QObject *parent = nullptr); - QJsonModel(const QString &fileName, QObject *parent = nullptr); - QJsonModel(QIODevice *device, QObject *parent = nullptr); - QJsonModel(const QByteArray &json, QObject *parent = nullptr); - ~QJsonModel(); - bool load(const QString &fileName); - bool load(QIODevice *device); - bool loadJson(const QByteArray &json); - QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; - bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE; - QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; - int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE; - QJsonDocument json() const; - - private: - QJsonValue genJson(QJsonTreeItem *) const; - - QJsonTreeItem *mRootItem; - QStringList mHeaders; + Q_OBJECT + public: + explicit QJsonModel(QObject *parent = nullptr); + QJsonModel(const QString &fileName, QObject *parent = nullptr); + QJsonModel(QIODevice *device, QObject *parent = nullptr); + QJsonModel(const QByteArray &json, QObject *parent = nullptr); + ~QJsonModel(); + bool load(const QString &fileName); + bool load(QIODevice *device); + bool loadJson(const QByteArray &json); + QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE; + QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; + QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; + int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; + int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; + Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE; + QJsonDocument json() const; + private: + QJsonValue genJson(QJsonTreeItem *) const; + QJsonTreeItem *mRootItem; + QStringList mHeaders; }; diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 7df5bd45..33455bbd 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -1,4 +1,5 @@ #include "common/QvHelpers.hpp" + #include namespace Qv2ray::common @@ -8,7 +9,8 @@ namespace Qv2ray::common const QString possibleCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); QString randomString; - for (int i = 0; i < len; ++i) { + for (int i = 0; i < len; ++i) + { uint rand = QRandomGenerator::system()->generate(); uint max = static_cast(possibleCharacters.length()); QChar nextChar = possibleCharacters[rand % max]; @@ -73,9 +75,9 @@ namespace Qv2ray::common QJsonDocument doc = QJsonDocument::fromJson(source.toUtf8(), &error); Q_UNUSED(doc) - if (error.error == QJsonParseError::NoError) { - return ""; - } else { + if (error.error == QJsonParseError::NoError) { return ""; } + else + { LOG(MODULE_UI, "WARNING: Json parse returns: " + error.errorString()) return error.errorString(); } @@ -108,16 +110,16 @@ namespace Qv2ray::common { list list; - for (auto line : _string.split(QRegExp("[\r\n]"), QString::SkipEmptyParts)) { - list.push_back(line.toStdString()); - } + for (auto line : _string.split(QRegExp("[\r\n]"), QString::SkipEmptyParts)) { list.push_back(line.toStdString()); } return list; } QStringList GetFileList(QDir dir) { - return dir.entryList(QStringList() << "*" << "*.*", QDir::Hidden | QDir::Files); + return dir.entryList(QStringList() << "*" + << "*.*", + QDir::Hidden | QDir::Files); } bool FileExistsIn(QDir dir, QString fileName) @@ -147,8 +149,7 @@ namespace Qv2ray::common int i; double dblByte = bytes; - for (i = 0; i < 5 && bytes >= 1024; i++, bytes /= 1024) - dblByte = bytes / 1024.0; + for (i = 0; i < 5 && bytes >= 1024; i++, bytes /= 1024) dblByte = bytes / 1024.0; sprintf(str, "%.2f", dblByte); return QString(str) + " " + QString(sizes[i]); @@ -163,9 +164,8 @@ namespace Qv2ray::common QString RemoveInvalidFileName(const QString &fileName) { std::string _name = fileName.toStdString(); - std::replace_if(_name.begin(), _name.end(), [](char c) { - return std::string::npos != string(R"("/\?%&^*;:|><)").find(c); - }, '_'); + std::replace_if( + _name.begin(), _name.end(), [](char c) { return std::string::npos != string(R"("/\?%&^*;:|><)").find(c); }, '_'); return QString::fromStdString(_name); } @@ -174,20 +174,25 @@ namespace Qv2ray::common { int i = 1; - if (!QDir(baseDir).exists()) { + if (!QDir(baseDir).exists()) + { QDir(baseDir).mkpath(baseDir); LOG(MODULE_FILEIO, "Making path: " + baseDir) } - while (true) { - if (!QFile(baseDir + "/" + fileName + "_" + QSTRN(i) + extension).exists()) { + while (true) + { + if (!QFile(baseDir + "/" + fileName + "_" + QSTRN(i) + extension).exists()) + { *fileName = *fileName + "_" + QSTRN(i); return; - } else { + } + else + { DEBUG(MODULE_FILEIO, "File with name: " + *fileName + "_" + QSTRN(i) + extension + " already exists") } i++; } } -} +} // namespace Qv2ray::common diff --git a/src/common/QvHelpers.hpp b/src/common/QvHelpers.hpp index 6d8d818b..cca199d8 100644 --- a/src/common/QvHelpers.hpp +++ b/src/common/QvHelpers.hpp @@ -1,10 +1,13 @@ #pragma once #include "base/Qv2rayBase.hpp" + #include -#define REGEX_IPV6_ADDR R"(\[\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*\])" -#define REGEX_IPV4_ADDR R"((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]))" +#define REGEX_IPV6_ADDR \ + R"(\[\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*\])" +#define REGEX_IPV4_ADDR \ + R"((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]))" #define REGEX_PORT_NUMBER R"(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])*)" namespace Qv2ray::common @@ -19,7 +22,8 @@ namespace Qv2ray::common // void QvMessageBoxWarn(QWidget *parent, QString title, QString text); void QvMessageBoxInfo(QWidget *parent, QString title, QString text); - QMessageBox::StandardButton QvMessageBoxAsk(QWidget *parent, QString title, QString text, QMessageBox::StandardButton extraButtons = QMessageBox::NoButton); + QMessageBox::StandardButton QvMessageBoxAsk(QWidget *parent, QString title, QString text, + QMessageBox::StandardButton extraButtons = QMessageBox::NoButton); // QString StringFromFile(const QString &filePath); QString StringFromFile(QFile *source); @@ -40,16 +44,16 @@ namespace Qv2ray::common inline QString GenerateUuid() { return GenerateRandomString().toLower(); - //return QUuid::createUuid().toString(QUuid::WithoutBraces); + // return QUuid::createUuid().toString(QUuid::WithoutBraces); } // - template + template QString StructToJsonString(const TYPE t) { return QString::fromStdString(x2struct::X::tojson(t, "", 4, ' ')); } // - template + template TYPE StructFromJsonString(const QString &str) { TYPE v; @@ -68,9 +72,7 @@ namespace Qv2ray::common { QString t = str; t.truncate(limit); - return (limit == -1 || str.length() < limit) - ? str - : (t + suffix); + return (limit == -1 || str.length() < limit) ? str : (t + suffix); } namespace validation @@ -92,7 +94,7 @@ namespace Qv2ray::common { return IsIPv4Address(addr) || IsIPv6Address(addr); } - } + } // namespace validation inline QString timeToString(const time_t &t) { @@ -102,6 +104,6 @@ namespace Qv2ray::common strftime(MY_TIME, sizeof(MY_TIME), "%x - %I:%M%p", _tm); return QString(MY_TIME); } -} +} // namespace Qv2ray::common using namespace Qv2ray::common; diff --git a/src/common/QvTranslator.hpp b/src/common/QvTranslator.hpp index 23002b28..d632d55b 100644 --- a/src/common/QvTranslator.hpp +++ b/src/common/QvTranslator.hpp @@ -7,15 +7,15 @@ namespace Qv2ray::common { class QvTranslator { - public: - QvTranslator(const QString &lang) - { - QTranslator *translator = new QTranslator(); - translator->load(lang + ".qm", ":/translations/"); - this->pTranslator.reset(translator); - } + public: + QvTranslator(const QString &lang) + { + QTranslator *translator = new QTranslator(); + translator->load(lang + ".qm", ":/translations/"); + this->pTranslator.reset(translator); + } - public: - std::unique_ptr pTranslator; + public: + std::unique_ptr pTranslator; }; } // namespace Qv2ray::common diff --git a/src/components/autolaunch/QvAutoLaunch.cpp b/src/components/autolaunch/QvAutoLaunch.cpp index e441f7b1..475ce0c4 100644 --- a/src/components/autolaunch/QvAutoLaunch.cpp +++ b/src/components/autolaunch/QvAutoLaunch.cpp @@ -1,13 +1,14 @@ #include "QvAutoLaunch.hpp" -#include + #include #include +#include #include #include // macOS headers (possibly OBJ-c) #if defined(Q_OS_MAC) -#include -#include + #include + #include #endif namespace Qv2ray::components::autolaunch { @@ -34,8 +35,10 @@ namespace Qv2ray::components::autolaunch } #elif defined Q_OS_MAC - // From https://github.com/nextcloud/desktop/blob/master/src/common/utility_mac.cpp - // this is quite some duplicate code with setLaunchOnStartup, at some point we should fix this FIXME. + // From + // https://github.com/nextcloud/desktop/blob/master/src/common/utility_mac.cpp + // this is quite some duplicate code with setLaunchOnStartup, at some + // point we should fix this FIXME. bool returnValue = false; QString filePath = QDir(QCoreApplication::applicationDirPath() + QLatin1String("/../..")).absolutePath(); CFStringRef folderCFStr = CFStringCreateWithCString(0, filePath.toUtf8().data(), kCFStringEncodingUTF8); @@ -49,16 +52,16 @@ namespace Qv2ray::components::autolaunch CFArrayRef itemsArray = LSSharedFileListCopySnapshot(loginItems, &seedValue); CFStringRef appUrlRefString = CFURLGetString(urlRef); // no need for release - for (int i = 0; i < CFArrayGetCount(itemsArray); i++) { - LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(itemsArray, i); + for (int i = 0; i < CFArrayGetCount(itemsArray); i++) + { + LSSharedFileListItemRef item = (LSSharedFileListItemRef) CFArrayGetValueAtIndex(itemsArray, i); CFURLRef itemUrlRef = NULL; - if (LSSharedFileListItemResolve(item, 0, &itemUrlRef, NULL) == noErr && itemUrlRef) { + if (LSSharedFileListItemResolve(item, 0, &itemUrlRef, NULL) == noErr && itemUrlRef) + { CFStringRef itemUrlString = CFURLGetString(itemUrlRef); - if (CFStringCompare(itemUrlString, appUrlRefString, 0) == kCFCompareEqualTo) { - returnValue = true; - } + if (CFStringCompare(itemUrlString, appUrlRefString, 0) == kCFCompareEqualTo) { returnValue = true; } CFRelease(itemUrlRef); } @@ -86,16 +89,20 @@ namespace Qv2ray::components::autolaunch QString appName = QApplication::applicationName(); QSettings reg("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); - if (enable) { + if (enable) + { QString strAppPath = QDir::toNativeSeparators(QCoreApplication::applicationFilePath()); reg.setValue(appName, strAppPath); - } else { + } + else + { reg.remove(appName); } } #elif defined Q_OS_MAC - // From https://github.com/nextcloud/desktop/blob/master/src/common/utility_mac.cpp + // From + // https://github.com/nextcloud/desktop/blob/master/src/common/utility_mac.cpp QString filePath = QDir(QCoreApplication::applicationDirPath() + QLatin1String("/../..")).absolutePath(); CFStringRef folderCFStr = CFStringCreateWithCString(0, filePath.toUtf8().data(), kCFStringEncodingUTF8); CFURLRef urlRef = CFURLCreateWithFileSystemPath(0, folderCFStr, kCFURLPOSIXPathStyle, true); @@ -103,30 +110,31 @@ namespace Qv2ray::components::autolaunch if (loginItems && enable) { - //Insert an item to the list. - LSSharedFileListItemRef item = LSSharedFileListInsertItemURL(loginItems, - kLSSharedFileListItemLast, 0, 0, - urlRef, 0, 0); + // Insert an item to the list. + LSSharedFileListItemRef item = LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemLast, 0, 0, urlRef, 0, 0); - if (item) - CFRelease(item); + if (item) CFRelease(item); CFRelease(loginItems); - } else if (loginItems && !enable) + } + else if (loginItems && !enable) { // We need to iterate over the items and check which one is "ours". UInt32 seedValue; CFArrayRef itemsArray = LSSharedFileListCopySnapshot(loginItems, &seedValue); CFStringRef appUrlRefString = CFURLGetString(urlRef); - for (int i = 0; i < CFArrayGetCount(itemsArray); i++) { - LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(itemsArray, i); + for (int i = 0; i < CFArrayGetCount(itemsArray); i++) + { + LSSharedFileListItemRef item = (LSSharedFileListItemRef) CFArrayGetValueAtIndex(itemsArray, i); CFURLRef itemUrlRef = NULL; - if (LSSharedFileListItemResolve(item, 0, &itemUrlRef, NULL) == noErr && itemUrlRef) { + if (LSSharedFileListItemResolve(item, 0, &itemUrlRef, NULL) == noErr && itemUrlRef) + { CFStringRef itemUrlString = CFURLGetString(itemUrlRef); - if (CFStringCompare(itemUrlString, appUrlRefString, 0) == kCFCompareEqualTo) { + if (CFStringCompare(itemUrlString, appUrlRefString, 0) == kCFCompareEqualTo) + { LSSharedFileListItemRemove(loginItems, item); // remove it! } @@ -143,22 +151,27 @@ namespace Qv2ray::components::autolaunch } #elif defined Q_OS_LINUX - // From https://github.com/nextcloud/desktop/blob/master/src/common/utility_unix.cpp + // From + // https://github.com/nextcloud/desktop/blob/master/src/common/utility_unix.cpp QString appName = QApplication::applicationName(); QString userAutoStartPath = getUserAutostartDir_private(); QString desktopFileLocation = userAutoStartPath + appName + QLatin1String(".desktop"); if (enable) { - if (!QDir().exists(userAutoStartPath) && !QDir().mkpath(userAutoStartPath)) { - // qCWarning(lcUtility) << "Could not create autostart folder" << userAutoStartPath; + if (!QDir().exists(userAutoStartPath) && !QDir().mkpath(userAutoStartPath)) + { + // qCWarning(lcUtility) << "Could not create autostart folder" + // << userAutoStartPath; return; } QFile iniFile(desktopFileLocation); - if (!iniFile.open(QIODevice::WriteOnly)) { - // qCWarning(lcUtility) << "Could not write auto start entry" << desktopFileLocation; + if (!iniFile.open(QIODevice::WriteOnly)) + { + // qCWarning(lcUtility) << "Could not write auto start entry" << + // desktopFileLocation; return; } @@ -174,13 +187,15 @@ namespace Qv2ray::components::autolaunch << QLatin1String("Type=") << "Application" << endl << QLatin1String("StartupNotify=") << "false" << endl << QLatin1String("X-GNOME-Autostart-enabled=") << "true" << endl; - } else + } + else { - if (!QFile::remove(desktopFileLocation)) { - // qCWarning(lcUtility) << "Could not remove autostart desktop file"; + if (!QFile::remove(desktopFileLocation)) + { + // qCWarning(lcUtility) << "Could not remove autostart desktop + // file"; } } } #endif -} - +} // namespace Qv2ray::components::autolaunch diff --git a/src/components/autolaunch/QvAutoLaunch.hpp b/src/components/autolaunch/QvAutoLaunch.hpp index 1c9e6443..7311e01c 100644 --- a/src/components/autolaunch/QvAutoLaunch.hpp +++ b/src/components/autolaunch/QvAutoLaunch.hpp @@ -4,7 +4,7 @@ namespace Qv2ray::components::autolaunch { bool GetLaunchAtLoginStatus(); void SetLaunchAtLoginStatus(bool enable); -} +} // namespace Qv2ray::components::autolaunch using namespace Qv2ray::components; using namespace Qv2ray::components::autolaunch; diff --git a/src/components/geosite/QvGeositeReader.cpp b/src/components/geosite/QvGeositeReader.cpp index 83f78c50..6a6f2f2e 100644 --- a/src/components/geosite/QvGeositeReader.cpp +++ b/src/components/geosite/QvGeositeReader.cpp @@ -1,4 +1,5 @@ #include "QvGeositeReader.hpp" + #include "libs/gen/v2ray_geosite.pb.h" namespace Qv2ray::components::geosite @@ -13,7 +14,8 @@ namespace Qv2ray::components::geosite QFile f(filepath); bool opened = f.open(QFile::OpenModeFlag::ReadOnly); - if (!opened) { + if (!opened) + { LOG(MODULE_FILEIO, "File cannot be opened: " + filepath) return list; } @@ -24,7 +26,8 @@ namespace Qv2ray::components::geosite GeoSiteList sites; sites.ParseFromArray(content.data(), content.size()); - for (auto e : sites.entry()) { + for (auto e : sites.entry()) + { // We want to use lower string. list << QString::fromStdString(e.country_code()).toLower(); } @@ -34,4 +37,4 @@ namespace Qv2ray::components::geosite google::protobuf::ShutdownProtobufLibrary(); return list; } -} +} // namespace Qv2ray::components::geosite diff --git a/src/components/icmping/win/ICMPPinger.cpp b/src/components/icmping/win/ICMPPinger.cpp index 39d9272f..ccff38bb 100644 --- a/src/components/icmping/win/ICMPPinger.cpp +++ b/src/components/icmping/win/ICMPPinger.cpp @@ -1,41 +1,38 @@ #include "ICMPPinger.hpp" -ICMPPinger::ICMPPinger(UINT64 timeout = DEFAULT_TIMEOUT) { +ICMPPinger::ICMPPinger(UINT64 timeout = DEFAULT_TIMEOUT) +{ // create icmp handle - if ((this->hIcmpFile = IcmpCreateFile()) == INVALID_HANDLE_VALUE) { - throw "IcmpCreateFile failed"; - } + if ((this->hIcmpFile = IcmpCreateFile()) == INVALID_HANDLE_VALUE) { throw "IcmpCreateFile failed"; } // remember the timeout this->timeout = timeout; } -ICMPPinger::~ICMPPinger() { +ICMPPinger::~ICMPPinger() +{ // release the handle on destruction IcmpCloseHandle(this->hIcmpFile); } -std::pair, std::optional> ICMPPinger::ping(const std::string& ipAddr) { +std::pair, std::optional> ICMPPinger::ping(const std::string &ipAddr) +{ // convert network address const auto addr = inet_addr(ipAddr.c_str()); - if (addr == INADDR_NONE) { - return std::pair(std::nullopt, "invalid ip address: " + ipAddr); - } + if (addr == INADDR_NONE) { return std::pair(std::nullopt, "invalid ip address: " + ipAddr); } // request buffer const static char bufRequest[] = "echo test"; // response buffer const auto responseSize = sizeof(ICMP_ECHO_REPLY) + sizeof(bufRequest); - const std::unique_ptr bufRecv(new(char[responseSize])); + const std::unique_ptr bufRecv(new (char[responseSize])); // send echo - auto ret = IcmpSendEcho(this->hIcmpFile, addr, (LPVOID)bufRequest, sizeof(bufRequest), NULL, bufRecv.get(), responseSize, this->timeout); - + auto ret = IcmpSendEcho(this->hIcmpFile, addr, (LPVOID) bufRequest, sizeof(bufRequest), NULL, bufRecv.get(), responseSize, this->timeout); + // ret == 0: failed - if (ret == 0) { - return std::pair(std::nullopt, "IcmpSendEcho returned error"); - } + if (ret == 0) { return std::pair(std::nullopt, "IcmpSendEcho returned error"); } // read round-trip time PICMP_ECHO_REPLY pReply = (PICMP_ECHO_REPLY) bufRecv.get(); diff --git a/src/components/icmping/win/ICMPPinger.hpp b/src/components/icmping/win/ICMPPinger.hpp index f6382049..f0bfa39e 100644 --- a/src/components/icmping/win/ICMPPinger.hpp +++ b/src/components/icmping/win/ICMPPinger.hpp @@ -6,27 +6,26 @@ * License: WTFPL */ -#include -#include -#include +#include +#include +#include +#include +#include +#include -#include -#include -#include +class ICMPPinger +{ + public: + ICMPPinger(UINT64 timeout = DEFAULT_TIMEOUT); + ~ICMPPinger(); + public: + static const UINT64 DEFAULT_TIMEOUT = 10000U; -class ICMPPinger { - public: - ICMPPinger(UINT64 timeout = DEFAULT_TIMEOUT); - ~ICMPPinger(); + public: + std::pair, std::optional> ping(const std::string &ipAddr); - public: - static const UINT64 DEFAULT_TIMEOUT = 10000U; - - public: - std::pair, std::optional> ping(const std::string& ipAddr); - - private: - HANDLE hIcmpFile; - UINT64 timeout = DEFAULT_TIMEOUT; + private: + HANDLE hIcmpFile; + UINT64 timeout = DEFAULT_TIMEOUT; }; diff --git a/src/components/pac/QvGFWPACConverter.cpp b/src/components/pac/QvGFWPACConverter.cpp index efb1bf61..49fd1a02 100644 --- a/src/components/pac/QvGFWPACConverter.cpp +++ b/src/components/pac/QvGFWPACConverter.cpp @@ -21,29 +21,23 @@ namespace Qv2ray::components::pac bool passRule1 = originLine.find("|") != string::npos; // Proxy Lines bool passRule2 = originLine.find(".") != string::npos; // Link-Contained Lines - if (originLine[endPosition] == '\n') { - endPosition -= 1; - } + if (originLine[endPosition] == '\n') { endPosition -= 1; } - if (originLine.find("http://") != string::npos) { - startPosition += 8; - } else if (originLine.find("https://") != string::npos) { + if (originLine.find("http://") != string::npos) { startPosition += 8; } + else if (originLine.find("https://") != string::npos) + { startPosition += 9; } // Skip unrelated lines - if (skipRule1 || skipRule2 || skipRule3 || skipRule4) { - return ""; - } else if (passRule2) { - if (passRule1) { - startPosition += originLine.find_last_of("|") + 1; - } + if (skipRule1 || skipRule2 || skipRule3 || skipRule4) { return ""; } + else if (passRule2) + { + if (passRule1) { startPosition += originLine.find_last_of("|") + 1; } if (originLine[startPosition] == '\n') startPosition += 1; - for (size_t i = startPosition; i < endPosition; ++i) { - returnBuffer += originLine[i]; - } + for (size_t i = startPosition; i < endPosition; ++i) { returnBuffer += originLine[i]; } } return returnBuffer; @@ -52,19 +46,19 @@ namespace Qv2ray::components::pac QString ConvertGFWToPAC(const QString &rawContent, const QString &customProxyString) { auto rawFileContent = Base64Decode(rawContent).toStdString(); - string readBuffer = ""; //cleanup + string readBuffer = ""; // cleanup string writeBuffer; string domainListCache = ""; - for (size_t i = 0; i < rawFileContent.size(); ++i) { + for (size_t i = 0; i < rawFileContent.size(); ++i) + { readBuffer += rawFileContent[i]; - if (rawFileContent[i + 1] == '\n') { + if (rawFileContent[i + 1] == '\n') + { writeBuffer = getRawDomain(readBuffer); - if (writeBuffer != "") { - domainListCache += writeBuffer + "\n"; - } + if (writeBuffer != "") { domainListCache += writeBuffer + "\n"; } readBuffer = ""; i += 1; @@ -72,19 +66,22 @@ namespace Qv2ray::components::pac } size_t rotatorTwo = 0; - string readDomainBuffer = ""; + string readDomainBuffer = ""; bool isFirstLine = true; string outputContent = ""; - //Header + // Header outputContent += "var domains = {\n"; - //Read and process output content line by line - while (rotatorTwo < domainListCache.size()) { - while (true) { - //Get Domain + // Read and process output content line by line + while (rotatorTwo < domainListCache.size()) + { + while (true) + { + // Get Domain readDomainBuffer += domainListCache[rotatorTwo]; - if (domainListCache[rotatorTwo + 1] == '\n') { + if (domainListCache[rotatorTwo + 1] == '\n') + { rotatorTwo += 2; break; } @@ -92,9 +89,10 @@ namespace Qv2ray::components::pac rotatorTwo++; } - //Format + // Format if (!isFirstLine) outputContent += ",\n"; - else isFirstLine = false; + else + isFirstLine = false; outputContent += "\t\""; outputContent += readDomainBuffer; @@ -102,32 +100,18 @@ namespace Qv2ray::components::pac readDomainBuffer = ""; } - //End Message - outputContent += - NEWLINE "};" - NEWLINE "" - NEWLINE " var proxy = \"" + customProxyString.toStdString() + ";\";" + - NEWLINE " var direct = 'DIRECT;';" - NEWLINE " function FindProxyForURL(url, host) {" - NEWLINE " var suffix;" - NEWLINE " var pos = host.lastIndexOf('.');" - NEWLINE " pos = host.lastIndexOf('.', pos - 1);" - NEWLINE " //" - NEWLINE " while (1) {" - NEWLINE " if (domains[host] != undefined) {" - NEWLINE " return proxy;" - NEWLINE " }" - NEWLINE " else if (pos <= 0) {" - NEWLINE " return domains['.' + host] != undefined ? proxy : direct;" - NEWLINE " }" - NEWLINE " suffix = host.substring(pos);" - NEWLINE " if (domains[suffix] != undefined) {" - NEWLINE " return proxy;" - NEWLINE " }" - NEWLINE " pos = host.lastIndexOf('.', pos - 1);" - NEWLINE " }" - NEWLINE " }"; + // End Message + outputContent += NEWLINE "};" NEWLINE "" NEWLINE " var proxy = \"" + customProxyString.toStdString() + ";\";" + + NEWLINE " var direct = 'DIRECT;';" NEWLINE " function FindProxyForURL(url, host) {" NEWLINE + " var suffix;" NEWLINE " var pos = host.lastIndexOf('.');" NEWLINE + " pos = host.lastIndexOf('.', pos - 1);" NEWLINE " //" NEWLINE " while (1) {" NEWLINE + " if (domains[host] != undefined) {" NEWLINE " return proxy;" NEWLINE + " }" NEWLINE " else if (pos <= 0) {" NEWLINE + " return domains['.' + host] != undefined ? proxy : direct;" NEWLINE " }" NEWLINE + " suffix = host.substring(pos);" NEWLINE " if (domains[suffix] != undefined) {" NEWLINE + " return proxy;" NEWLINE " }" NEWLINE + " pos = host.lastIndexOf('.', pos - 1);" NEWLINE " }" NEWLINE " }"; // return QString::fromStdString(outputContent); } -} +} // namespace Qv2ray::components::pac diff --git a/src/components/pac/QvPACHandler.cpp b/src/components/pac/QvPACHandler.cpp index 033f1a32..456159b1 100644 --- a/src/components/pac/QvPACHandler.cpp +++ b/src/components/pac/QvPACHandler.cpp @@ -1,8 +1,9 @@ #include "QvPACHandler.hpp" + +#include "common/QvHelpers.hpp" +#include "core/CoreUtils.hpp" #include "qhttprequest.h" #include "qhttpresponse.h" -#include "core/CoreUtils.hpp" -#include "common/QvHelpers.hpp" namespace Qv2ray::components::pac { @@ -13,9 +14,7 @@ namespace Qv2ray::components::pac } PACServer::~PACServer() { - if (isStarted) { - pacServer.close(); - } + if (isStarted) { pacServer.close(); } } void PACServer::SetProxyString(const QString &proxyString) { @@ -36,10 +35,13 @@ namespace Qv2ray::components::pac // auto result = pacServer.listen(QHostAddress(address), static_cast(port)); - if (result) { + if (result) + { isStarted = true; DEBUG(MODULE_PROXY, "Started PAC handler") - } else { + } + else + { LOG(MODULE_PROXY, "Failed to listen on port " + QSTRN(port) + ", possible permission denied.") QvMessageBoxWarn(nullptr, tr("PAC Handler"), tr("Failed to listen PAC request on this port, please verify the permissions")); } @@ -47,7 +49,8 @@ namespace Qv2ray::components::pac void PACServer::StopServer() { - if (isStarted) { + if (isStarted) + { pacServer.close(); DEBUG(MODULE_PROXY, "PAC Handler stopped.") isStarted = false; @@ -58,22 +61,28 @@ namespace Qv2ray::components::pac { rsp->setHeader("Server", "Qv2ray/" QV2RAY_VERSION_STRING " PAC_Handler"); - if (req->method() == QHttpRequest::HTTP_GET) { + if (req->method() == QHttpRequest::HTTP_GET) + { // - if (req->path() == "/pac") { + if (req->path() == "/pac") + { DEBUG(MODULE_PROXY, "Serving PAC file request.") // rsp->setHeader("Content-Type", "application/javascript; charset=utf-8"); rsp->writeHead(QHttpResponse::StatusCode::STATUS_OK); rsp->end(pacContent.toUtf8()); DEBUG(MODULE_PROXY, "Serving a pac file...") - } else { + } + else + { rsp->writeHead(QHttpResponse::StatusCode::STATUS_NOT_FOUND); rsp->end("NOT FOUND"); } - } else { + } + else + { rsp->writeHead(QHttpResponse::StatusCode::STATUS_METHOD_NOT_ALLOWED); rsp->end("PAC ONLY SUPPORT GET"); } } -} +} // namespace Qv2ray::components::pac diff --git a/src/components/pac/QvPACHandler.hpp b/src/components/pac/QvPACHandler.hpp index 323da610..e739ae30 100644 --- a/src/components/pac/QvPACHandler.hpp +++ b/src/components/pac/QvPACHandler.hpp @@ -1,5 +1,6 @@ #pragma once #include "qhttpserver.h" + #include #include @@ -8,26 +9,26 @@ namespace Qv2ray::components::pac QString ConvertGFWToPAC(const QString &rawContent, const QString &customProxyString); class PACServer : public QObject { - Q_OBJECT - public: - explicit PACServer(); - ~PACServer(); - void SetProxyString(const QString &proxyString); - void StartListen(); - void StopServer(); + Q_OBJECT + public: + explicit PACServer(); + ~PACServer(); + void SetProxyString(const QString &proxyString); + void StartListen(); + void StopServer(); - QString gfwFilePath; + QString gfwFilePath; - public slots: - void onNewRequest(QHttpRequest *request, QHttpResponse *response); + public slots: + void onNewRequest(QHttpRequest *request, QHttpResponse *response); - private: - bool isStarted; - QHttpServer pacServer; - QString pacContent; - QString proxyString; + private: + bool isStarted; + QHttpServer pacServer; + QString pacContent; + QString proxyString; }; -} +} // namespace Qv2ray::components::pac using namespace Qv2ray::components; using namespace Qv2ray::components::pac; diff --git a/src/components/plugins/toolbar/QvToolbar.cpp b/src/components/plugins/toolbar/QvToolbar.cpp index 0ecdb877..7b8d7685 100644 --- a/src/components/plugins/toolbar/QvToolbar.cpp +++ b/src/components/plugins/toolbar/QvToolbar.cpp @@ -1,7 +1,8 @@ #include -#include "ui/w_MainWindow.hpp" #include "components/plugins/toolbar/QvToolbar.hpp" + #include "common/QvHelpers.hpp" +#include "ui/w_MainWindow.hpp" namespace Qv2ray::components::plugins { @@ -31,118 +32,137 @@ namespace Qv2ray::components::plugins QString GetAnswerToRequest(const QString &pchRequest) { auto instance = MainWindow::mwInstance; - //if (instance == nullptr || instance->vinstance == nullptr) { + // if (instance == nullptr || instance->vinstance == nullptr) { // LOG(PLUGIN, "MainWindow != nullptr Assertion failed!") // return "{}"; //} // - //auto vinstance = instance->vinstance; + // auto vinstance = instance->vinstance; // auto req = pchRequest.trimmed(); QString reply = "{}"; - if (req == "START") { - emit instance->Connect(); - } else if (req == "STOP") { + if (req == "START") { emit instance->Connect(); } + else if (req == "STOP") + { emit instance->DisConnect(); - } else if (req == "RESTART") { + } + else if (req == "RESTART") + { emit instance->ReConnect(); } auto BarConfig = GlobalConfig.toolBarConfig; - for (auto i = 0; i < BarConfig.Pages.size(); i++) { - for (auto j = 0; j < BarConfig.Pages[i].Lines.size(); j++) { + for (auto i = 0; i < BarConfig.Pages.size(); i++) + { + for (auto j = 0; j < BarConfig.Pages[i].Lines.size(); j++) + { #define CL BarConfig.Pages[i].Lines[j] - switch (CL.ContentType) { - case 0: { + switch (CL.ContentType) + { + case 0: + { // Custom Text // We do nothing... break; } - case 101: { + case 101: + { // Current Time CL.Message = QTime().currentTime().toString("hh:mm:ss"); break; } - case 102: { + case 102: + { // Current Date CL.Message = QDate().currentDate().toString("yyyy-MM-dd"); break; } - case 103: { + case 103: + { // Current Qv2ray Version CL.Message = QV2RAY_VERSION_STRING; break; } - //case 104: { - // // Current Connection Name - // CL.Message = instance->GetCurrentConnectedConfigName(); - // break; - //} - // - //case 105: { - // // Current Connection Status - // CL.Message = instance->vinstance->KernelStarted - // ? QObject::tr("Connected") - // : QObject::tr("Disconnected"); - // break; - //} - // - //case 201: { - // // Total upload speed; - // CL.Message = FormatBytes(vinstance->getAllSpeedUp()) + "/s"; - // break; - //} - // - //case 202: { - // // Total download speed; - // CL.Message = FormatBytes(vinstance->getAllSpeedDown()) + "/s"; - // break; - //} - // - //case 203: { - // // Upload speed for tag - // CL.Message = FormatBytes(vinstance->getTagSpeedUp(CL.Message)) + "/s"; - // break; - //} - // - //case 204: { - // // Download speed for tag - // CL.Message = FormatBytes(vinstance->getTagSpeedDown(CL.Message)) + "/s"; - // break; - //} - // - //case 301: { - // // Total Upload - // CL.Message = FormatBytes(vinstance->getAllDataUp()); - // break; - //} - // - //case 302: { - // // Total download - // CL.Message = FormatBytes(vinstance->getAllDataDown()); - // break; - //} - // - //case 303: { - // // Upload for tag - // CL.Message = FormatBytes(vinstance->getTagDataUp(CL.Message)); - // break; - //} - // - //case 304: { - // // Download for tag - // CL.Message = FormatBytes(vinstance->getTagDataDown(CL.Message)); - // break; - //} + // case 104: { + // // Current Connection Name + // CL.Message = + // instance->GetCurrentConnectedConfigName(); + // break; + //} + // + // case 105: { + // // Current Connection Status + // CL.Message = + // instance->vinstance->KernelStarted + // ? QObject::tr("Connected") + // : QObject::tr("Disconnected"); + // break; + //} + // + // case 201: { + // // Total upload speed; + // CL.Message = + // FormatBytes(vinstance->getAllSpeedUp()) + + // "/s"; break; + //} + // + // case 202: { + // // Total download speed; + // CL.Message = + // FormatBytes(vinstance->getAllSpeedDown()) + + // "/s"; break; + //} + // + // case 203: { + // // Upload speed for tag + // CL.Message = + // FormatBytes(vinstance->getTagSpeedUp(CL.Message)) + // + "/s"; break; + //} + // + // case 204: { + // // Download speed for tag + // CL.Message = + // FormatBytes(vinstance->getTagSpeedDown(CL.Message)) + // + "/s"; break; + //} + // + // case 301: { + // // Total Upload + // CL.Message = + // FormatBytes(vinstance->getAllDataUp()); break; + //} + // + // case 302: { + // // Total download + // CL.Message = + // FormatBytes(vinstance->getAllDataDown()); + // break; + //} + // + // case 303: { + // // Upload for tag + // CL.Message = + // FormatBytes(vinstance->getTagDataUp(CL.Message)); + // break; + //} + // + // case 304: { + // // Download for tag + // CL.Message = + // FormatBytes(vinstance->getTagDataDown(CL.Message)); + // break; + //} - default: { + default: + { CL.Message = "Not Supported?"; break; } @@ -153,5 +173,5 @@ namespace Qv2ray::components::plugins reply = StructToJsonString(BarConfig); return reply; } - } -} + } // namespace Toolbar +} // namespace Qv2ray::components::plugins diff --git a/src/components/plugins/toolbar/QvToolbar.hpp b/src/components/plugins/toolbar/QvToolbar.hpp index 84e45967..6dd2b563 100644 --- a/src/components/plugins/toolbar/QvToolbar.hpp +++ b/src/components/plugins/toolbar/QvToolbar.hpp @@ -9,25 +9,23 @@ namespace Qv2ray::components::plugins namespace Toolbar { /// NO NOT CHANGE THE ORDER - static const QMap NetSpeedPluginMessages { - { 0, QObject::tr("Custom Text")}, - // Current Status - { 101, QObject::tr("Current Time") }, - { 102, QObject::tr("Current Date") }, - { 103, QObject::tr("Current Qv2ray Version") }, - { 104, QObject::tr("Current Connection Name") }, - { 105, QObject::tr("Current Connection Status") }, - // Speeds - { 201, QObject::tr("Total Upload Speed") }, - { 202, QObject::tr("Total Download Speed") }, - { 203, QObject::tr("Upload Speed for Specific Tag") }, - { 204, QObject::tr("Download Speed for Specific Tag") }, - // Datas - { 301, QObject::tr("Total Uploaded Data") }, - { 302, QObject::tr("Total Downloaded Data") }, - { 303, QObject::tr("Uploaded Data for Specific Tag") }, - { 304, QObject::tr("Downloaded Data for Specific Tag") } - }; + static const QMap NetSpeedPluginMessages{ { 0, QObject::tr("Custom Text") }, + // Current Status + { 101, QObject::tr("Current Time") }, + { 102, QObject::tr("Current Date") }, + { 103, QObject::tr("Current Qv2ray Version") }, + { 104, QObject::tr("Current Connection Name") }, + { 105, QObject::tr("Current Connection Status") }, + // Speeds + { 201, QObject::tr("Total Upload Speed") }, + { 202, QObject::tr("Total Download Speed") }, + { 203, QObject::tr("Upload Speed for Specific Tag") }, + { 204, QObject::tr("Download Speed for Specific Tag") }, + // Datas + { 301, QObject::tr("Total Uploaded Data") }, + { 302, QObject::tr("Total Downloaded Data") }, + { 303, QObject::tr("Uploaded Data for Specific Tag") }, + { 304, QObject::tr("Downloaded Data for Specific Tag") } }; void StartProcessingPlugins(); void StopProcessingPlugins(); #ifdef Q_OS_WIN @@ -35,7 +33,7 @@ namespace Qv2ray::components::plugins { void StartNamedPipeThread(); void KillNamedPipeThread(); - } + } // namespace _win #endif #ifdef Q_OS_LINUX namespace _linux @@ -45,13 +43,12 @@ namespace Qv2ray::components::plugins void StartMessageQThread(); void StopMessageQThread(); - } + } // namespace _linux #endif QString GetAnswerToRequest(const QString &pchRequest); - } -} + } // namespace Toolbar +} // namespace Qv2ray::components::plugins using namespace Qv2ray::components; using namespace Qv2ray::components::plugins::Toolbar; - diff --git a/src/components/plugins/toolbar/QvToolbar_linux.cpp b/src/components/plugins/toolbar/QvToolbar_linux.cpp index 5ff3ec30..de82ec56 100644 --- a/src/components/plugins/toolbar/QvToolbar_linux.cpp +++ b/src/components/plugins/toolbar/QvToolbar_linux.cpp @@ -1,9 +1,10 @@ #include #ifdef Q_OS_LINUX -#include "components/plugins/toolbar/QvToolbar.hpp" -#include "common/QvHelpers.hpp" -#include -#include + #include "common/QvHelpers.hpp" + #include "components/plugins/toolbar/QvToolbar.hpp" + + #include + #include namespace Qv2ray::components::plugins::Toolbar { namespace _linux @@ -16,35 +17,43 @@ namespace Qv2ray::components::plugins::Toolbar { QLocalSocket *socket = server->nextPendingConnection(); - if (!socket->waitForConnected() || !socket->waitForReadyRead()) - return; + if (!socket->waitForConnected() || !socket->waitForReadyRead()) return; - try { - while (!isExiting && socket->isOpen() && socket->isValid() && socket->waitForReadyRead()) { + try + { + while (!isExiting && socket->isOpen() && socket->isValid() && socket->waitForReadyRead()) + { // CANNOT PROPERLY READ... // Temp-ly fixed (but why and how?) auto in = QString(socket->readAll()); - if (!isExiting && !in.isEmpty()) { + if (!isExiting && !in.isEmpty()) + { auto out = GetAnswerToRequest(in); // socket->write(out.toUtf8()); socket->flush(); - } else { + } + else + { QThread::msleep(200); } } - } catch (...) { + } + catch (...) + { LOG(MODULE_PLUGIN, "Closing a broken socket.") } } void DataMessageQThread() { server = new QLocalServer(); - // BUG Sometimes failed to listen due to improper close of last session. + // BUG Sometimes failed to listen due to improper close of last + // session. bool listening = server->listen(QV2RAY_NETSPEED_PLUGIN_PIPE_NAME_LINUX); - while (!isExiting && !listening) { + while (!isExiting && !listening) + { QThread::msleep(500); listening = server->listen(QV2RAY_NETSPEED_PLUGIN_PIPE_NAME_LINUX); } @@ -53,7 +62,8 @@ namespace Qv2ray::components::plugins::Toolbar server->setSocketOptions(QLocalServer::WorldAccessOption); QObject::connect(server, &QLocalServer::newConnection, &qobject_proxy); - while (!isExiting) { + while (!isExiting) + { bool result = server->waitForNewConnection(5000, &timeOut); DEBUG(MODULE_PLUGIN, "Plugin thread listening failed: " + server->errorString()) DEBUG(MODULE_PLUGIN, "waitForNewConnection: " + QString(result ? "true" : "false") + ", " + QString(timeOut ? "true" : "false")) @@ -72,13 +82,14 @@ namespace Qv2ray::components::plugins::Toolbar { isExiting = true; - if (linuxWorkerThread->isRunning()) { + if (linuxWorkerThread->isRunning()) + { LOG(MODULE_PLUGIN, "Waiting for linuxWorkerThread to stop.") linuxWorkerThread->wait(); } delete _linux::linuxWorkerThread; } - } -} + } // namespace _linux +} // namespace Qv2ray::components::plugins::Toolbar #endif diff --git a/src/components/plugins/toolbar/QvToolbar_win.cpp b/src/components/plugins/toolbar/QvToolbar_win.cpp index 4662e77a..f7553fb7 100644 --- a/src/components/plugins/toolbar/QvToolbar_win.cpp +++ b/src/components/plugins/toolbar/QvToolbar_win.cpp @@ -1,8 +1,9 @@ #include #ifdef Q_OS_WIN -#include "components/plugins/toolbar/QvToolbar.hpp" -#include "common/QvHelpers.hpp" -#include + #include "common/QvHelpers.hpp" + #include "components/plugins/toolbar/QvToolbar.hpp" + + #include namespace Qv2ray::components::plugins::Toolbar { namespace _win @@ -25,40 +26,53 @@ namespace Qv2ray::components::plugins::Toolbar { auto hThread = CreateThread(nullptr, 0, NamedPipeMasterThread, nullptr, 0, nullptr); - if (hThread == nullptr) { + if (hThread == nullptr) + { LOG(MODULE_PLUGIN, "CreateThread failed, GLE=" + QSTRN(GetLastError())) return; - } else CloseHandle(hThread); + } + else + CloseHandle(hThread); } DWORD WINAPI NamedPipeMasterThread(LPVOID lpvParam) { Q_UNUSED(lpvParam) - BOOL fConnected = FALSE; - DWORD dwThreadId = 0; + BOOL fConnected = FALSE; + DWORD dwThreadId = 0; HANDLE hPipe = INVALID_HANDLE_VALUE; auto lpszPipename = QString(QV2RAY_NETSPEED_PLUGIN_PIPE_NAME_WIN).toStdWString(); - while (!isExiting) { - //printf("Pipe Server: Main thread awaiting client connection on %s\n", lpszPipename.c_str()); - hPipe = CreateNamedPipe(lpszPipename.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, 0, nullptr); + while (!isExiting) + { + // printf("Pipe Server: Main thread awaiting client connection + // on %s\n", lpszPipename.c_str()); + hPipe = CreateNamedPipe(lpszPipename.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, + PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, 0, nullptr); - if (hPipe == INVALID_HANDLE_VALUE) { + if (hPipe == INVALID_HANDLE_VALUE) + { LOG(MODULE_PLUGIN, "CreateNamedPipe failed, GLE=" + QSTRN(GetLastError())) return static_cast(-1); } fConnected = ConnectNamedPipe(hPipe, nullptr) ? true : (GetLastError() == ERROR_PIPE_CONNECTED); - if (fConnected) { + if (fConnected) + { LOG(MODULE_PLUGIN, "Client connected, creating a processing thread") ThreadHandle = CreateThread(nullptr, 0, InstanceThread, hPipe, 0, &dwThreadId); - if (ThreadHandle == nullptr) { + if (ThreadHandle == nullptr) + { LOG(MODULE_PLUGIN, "CreateThread failed, GLE=" + QSTRN(GetLastError())) return static_cast(-1); - } else CloseHandle(ThreadHandle); - } else CloseHandle(hPipe); + } + else + CloseHandle(ThreadHandle); + } + else + CloseHandle(hPipe); } return 0; @@ -71,13 +85,16 @@ namespace Qv2ray::components::plugins::Toolbar HANDLE hPipe = static_cast(lpvParam); TCHAR pchRequest[BUFSIZE] = { 0 }; - while (!isExiting) { + while (!isExiting) + { fSuccess = ReadFile(hPipe, pchRequest, BUFSIZE * sizeof(TCHAR), &cbBytesRead, nullptr); - if (!fSuccess || cbBytesRead == 0) { - if (GetLastError() == ERROR_BROKEN_PIPE) { - LOG(MODULE_PLUGIN, "InstanceThread: client disconnected, GLE=" + QSTRN(GetLastError())) - } else { + if (!fSuccess || cbBytesRead == 0) + { + if (GetLastError() == ERROR_BROKEN_PIPE) + { LOG(MODULE_PLUGIN, "InstanceThread: client disconnected, GLE=" + QSTRN(GetLastError())) } + else + { LOG(MODULE_PLUGIN, "InstanceThread ReadFile failed, GLE=" + QSTRN(GetLastError())) } @@ -87,17 +104,20 @@ namespace Qv2ray::components::plugins::Toolbar auto req = QString::fromStdWString(pchRequest); QString replyQString = "{}"; - if (!isExiting) { + if (!isExiting) + { replyQString = GetAnswerToRequest(req); // // REPLY as std::string std::string pchReply = replyQString.toUtf8().constData(); cbReplyBytes = static_cast(pchReply.length() + 1) * sizeof(CHAR); - //cbReplyBytes = static_cast(replyQString.length() + 1) * sizeof(TCHAR); + // cbReplyBytes = static_cast(replyQString.length() + + // 1) * sizeof(TCHAR); // fSuccess = WriteFile(hPipe, pchReply.c_str(), cbReplyBytes, &cbWritten, nullptr); - if (!fSuccess || cbReplyBytes != cbWritten) { + if (!fSuccess || cbReplyBytes != cbWritten) + { LOG(MODULE_PLUGIN, "InstanceThread WriteFile failed, GLE=" + QSTRN(GetLastError())) break; } @@ -109,6 +129,6 @@ namespace Qv2ray::components::plugins::Toolbar CloseHandle(hPipe); return 1; } - } -} + } // namespace _win +} // namespace Qv2ray::components::plugins::Toolbar #endif diff --git a/src/components/proxy/QvProxyConfigurator.cpp b/src/components/proxy/QvProxyConfigurator.cpp index 9c12000f..84b85c3a 100644 --- a/src/components/proxy/QvProxyConfigurator.cpp +++ b/src/components/proxy/QvProxyConfigurator.cpp @@ -1,8 +1,10 @@ #include "QvProxyConfigurator.hpp" + #include "common/QvHelpers.hpp" #ifdef Q_OS_WIN -#include "wininet.h" -#include + #include "wininet.h" + + #include #endif namespace Qv2ray::components::proxy @@ -23,11 +25,10 @@ namespace Qv2ray::components::proxy QStringList result; // 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. - if (!lines[i].contains("*")) { - result << (lines[i].contains(" ") ? "\"" + lines[i] + "\"" : lines[i]); - } + if (!lines[i].contains("*")) { result << (lines[i].contains(" ") ? "\"" + lines[i] + "\"" : lines[i]); } } LOG(MODULE_PROXY, "Found " + QSTRN(result.size()) + " network services: " + result.join(";")) @@ -35,8 +36,9 @@ namespace Qv2ray::components::proxy } #endif #ifdef Q_OS_WIN -#define NO_CONST(expr) const_cast(expr) - //static auto DEFAULT_CONNECTION_NAME = NO_CONST(L"DefaultConnectionSettings"); + #define NO_CONST(expr) const_cast(expr) + // static auto DEFAULT_CONNECTION_NAME = + // NO_CONST(L"DefaultConnectionSettings"); /// /// INTERNAL FUNCTION bool __QueryProxyOptions() @@ -52,81 +54,64 @@ namespace Qv2ray::components::proxy Option[4].dwOption = INTERNET_PER_CONN_PROXY_SERVER; // List.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LIST); - List.pszConnection = nullptr;// NO_CONST(DEFAULT_CONNECTION_NAME); + List.pszConnection = nullptr; // NO_CONST(DEFAULT_CONNECTION_NAME); List.dwOptionCount = 5; List.dwOptionError = 0; List.pOptions = Option; - if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) { - LOG(MODULE_PROXY, "InternetQueryOption failed, GLE=" + QSTRN(GetLastError())) - } + if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) + { LOG(MODULE_PROXY, "InternetQueryOption failed, GLE=" + QSTRN(GetLastError())) } LOG(MODULE_PROXY, "System default proxy info:") - if (Option[0].Value.pszValue != nullptr) { - LOG(MODULE_PROXY, QString::fromWCharArray(Option[0].Value.pszValue)) - } + if (Option[0].Value.pszValue != nullptr) { LOG(MODULE_PROXY, QString::fromWCharArray(Option[0].Value.pszValue)) } - if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL) == PROXY_TYPE_AUTO_PROXY_URL) { - LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_PROXY_URL") - } + if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL) == PROXY_TYPE_AUTO_PROXY_URL) + { LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_PROXY_URL") } - if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_DETECT) == PROXY_TYPE_AUTO_DETECT) { - LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_DETECT") - } + if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_DETECT) == PROXY_TYPE_AUTO_DETECT) { LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_DETECT") } - if ((Option[2].Value.dwValue & PROXY_TYPE_DIRECT) == PROXY_TYPE_DIRECT) { - LOG(MODULE_PROXY, "PROXY_TYPE_DIRECT") - } + if ((Option[2].Value.dwValue & PROXY_TYPE_DIRECT) == PROXY_TYPE_DIRECT) { LOG(MODULE_PROXY, "PROXY_TYPE_DIRECT") } - if ((Option[2].Value.dwValue & PROXY_TYPE_PROXY) == PROXY_TYPE_PROXY) { - LOG(MODULE_PROXY, "PROXY_TYPE_PROXY") - } + if ((Option[2].Value.dwValue & PROXY_TYPE_PROXY) == PROXY_TYPE_PROXY) { LOG(MODULE_PROXY, "PROXY_TYPE_PROXY") } - if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) { - LOG(MODULE_PROXY, "InternetQueryOption failed,GLE=" + QSTRN(GetLastError())) - } + if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) + { LOG(MODULE_PROXY, "InternetQueryOption failed,GLE=" + QSTRN(GetLastError())) } - if (Option[4].Value.pszValue != nullptr) { - LOG(MODULE_PROXY, QString::fromStdWString(Option[4].Value.pszValue)) - } + if (Option[4].Value.pszValue != nullptr) { LOG(MODULE_PROXY, QString::fromStdWString(Option[4].Value.pszValue)) } INTERNET_VERSION_INFO Version; nSize = sizeof(INTERNET_VERSION_INFO); InternetQueryOption(nullptr, INTERNET_OPTION_VERSION, &Version, &nSize); - if (Option[0].Value.pszValue != nullptr) { - GlobalFree(Option[0].Value.pszValue); - } + if (Option[0].Value.pszValue != nullptr) { GlobalFree(Option[0].Value.pszValue); } - if (Option[3].Value.pszValue != nullptr) { - GlobalFree(Option[3].Value.pszValue); - } + if (Option[3].Value.pszValue != nullptr) { GlobalFree(Option[3].Value.pszValue); } - if (Option[4].Value.pszValue != nullptr) { - GlobalFree(Option[4].Value.pszValue); - } + if (Option[4].Value.pszValue != nullptr) { GlobalFree(Option[4].Value.pszValue); } return false; } bool __SetProxyOptions(LPWSTR proxy_full_addr, bool isPAC) { INTERNET_PER_CONN_OPTION_LIST list; - BOOL bReturn; - DWORD dwBufSize = sizeof(list); + BOOL bReturn; + DWORD dwBufSize = sizeof(list); // Fill the list structure. list.dwSize = sizeof(list); // NULL == LAN, otherwise connectoid name. list.pszConnection = nullptr; - if (isPAC) { + if (isPAC) + { LOG(MODULE_PROXY, "Setting system proxy for PAC") // list.dwOptionCount = 2; list.pOptions = new INTERNET_PER_CONN_OPTION[2]; // Ensure that the memory was allocated. - if (nullptr == list.pOptions) { + if (nullptr == list.pOptions) + { // Return FALSE if the memory wasn't allocated. return FALSE; } @@ -137,15 +122,15 @@ namespace Qv2ray::components::proxy // Set proxy name. list.pOptions[1].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL; list.pOptions[1].Value.pszValue = proxy_full_addr; - } else { + } + else + { LOG(MODULE_PROXY, "Setting system proxy for Global Proxy") // list.dwOptionCount = 3; list.pOptions = new INTERNET_PER_CONN_OPTION[3]; - if (nullptr == list.pOptions) { - return false; - } + if (nullptr == list.pOptions) { return false; } // Set flags. list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; @@ -161,7 +146,7 @@ namespace Qv2ray::components::proxy // Set the options on the connection. bReturn = InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); - delete [] list.pOptions; + delete[] list.pOptions; InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0); InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0); return bReturn; @@ -173,29 +158,26 @@ namespace Qv2ray::components::proxy bool hasHTTP = (httpPort != 0); bool hasSOCKS = (socksPort != 0); - if (!(hasHTTP || hasSOCKS || usePAC)) { + if (!(hasHTTP || hasSOCKS || usePAC)) + { LOG(MODULE_PROXY, "Nothing?") return; } - if (usePAC) { - LOG(MODULE_PROXY, "Qv2ray will set system proxy to use PAC file") - } else { - if (hasHTTP) { - LOG(MODULE_PROXY, "Qv2ray will set system proxy to use HTTP") - } + if (usePAC) { LOG(MODULE_PROXY, "Qv2ray will set system proxy to use PAC file") } + else + { + if (hasHTTP) { LOG(MODULE_PROXY, "Qv2ray will set system proxy to use HTTP") } - if (hasSOCKS) { - LOG(MODULE_PROXY, "Qv2ray will set system proxy to use SOCKS") - } + if (hasSOCKS) { LOG(MODULE_PROXY, "Qv2ray will set system proxy to use SOCKS") } } #ifdef Q_OS_WIN QString __a; - if (usePAC) { - __a = address; - } else { + if (usePAC) { __a = address; } + else + { __a = (hasHTTP ? "http://" : "socks5://") + address + ":" + QSTRN(httpPort); } @@ -205,9 +187,7 @@ namespace Qv2ray::components::proxy // __QueryProxyOptions(); - if (!__SetProxyOptions(proxyStrW, usePAC)) { - LOG(MODULE_PROXY, "Failed to set proxy.") - } + if (!__SetProxyOptions(proxyStrW, usePAC)) { LOG(MODULE_PROXY, "Failed to set proxy.") } __QueryProxyOptions(); #elif defined(Q_OS_LINUX) @@ -215,18 +195,21 @@ namespace Qv2ray::components::proxy auto proxyMode = usePAC ? "auto" : "manual"; actions << QString("gsettings set org.gnome.system.proxy mode '%1'").arg(proxyMode); - if (usePAC) { - actions << QString("gsettings set org.gnome.system.proxy autoconfig-url '%1'").arg(address); - } else { - if (hasHTTP) { + if (usePAC) { actions << QString("gsettings set org.gnome.system.proxy autoconfig-url '%1'").arg(address); } + else + { + if (hasHTTP) + { actions << QString("gsettings set org.gnome.system.proxy.http host '%1'").arg(address); actions << QString("gsettings set org.gnome.system.proxy.http port %1").arg(httpPort); // actions << QString("gsettings set org.gnome.system.proxy.https host '%1'").arg(address); - actions << QString("gsettings set org.gnome.system.proxy.https port %1").arg(httpPort);; + actions << QString("gsettings set org.gnome.system.proxy.https port %1").arg(httpPort); + ; } - if (hasSOCKS) { + if (hasSOCKS) + { actions << QString("gsettings set org.gnome.system.proxy.socks host '%1'").arg(address); actions << QString("gsettings set org.gnome.system.proxy.socks port %1").arg(socksPort); } @@ -234,12 +217,13 @@ namespace Qv2ray::components::proxy // note: do not use std::all_of / any_of / none_of, // because those are short-circuit and cannot guarantee atomicity. - auto result = std::count_if(actions.cbegin(), actions.cend(), [](const QString & action) { - DEBUG(MODULE_PROXY, action) - return QProcess::execute(action) == QProcess::NormalExit; - }) == actions.size(); + auto result = std::count_if(actions.cbegin(), actions.cend(), [](const QString &action) { + DEBUG(MODULE_PROXY, action) + return QProcess::execute(action) == QProcess::NormalExit; + }) == actions.size(); - if (!result) { + if (!result) + { LOG(MODULE_PROXY, "Something wrong happens when setting system proxy -> Gnome ONLY.") LOG(MODULE_PROXY, "If you are using KDE Plasma and receiving this message, just simply ignore this.") } @@ -247,21 +231,27 @@ namespace Qv2ray::components::proxy Q_UNUSED(result); #else - for (auto service : macOSgetNetworkServices()) { + for (auto service : macOSgetNetworkServices()) + { LOG(MODULE_PROXY, "Setting proxy for interface: " + service) - if (usePAC) { + if (usePAC) + { QProcess::execute("/usr/sbin/networksetup -setautoproxystate " + service + " on"); QProcess::execute("/usr/sbin/networksetup -setautoproxyurl " + service + " " + address); - } else { - if (hasHTTP) { + } + else + { + if (hasHTTP) + { QProcess::execute("/usr/sbin/networksetup -setwebproxystate " + 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 -setsecurewebproxy " + service + " " + address + " " + QSTRN(httpPort)); } - if (hasSOCKS) { + if (hasSOCKS) + { QProcess::execute("/usr/sbin/networksetup -setsocksfirewallproxystate " + service + " on"); QProcess::execute("/usr/sbin/networksetup -setsocksfirewallproxy " + service + " " + address + " " + QSTRN(socksPort)); } @@ -287,7 +277,8 @@ namespace Qv2ray::components::proxy list.pOptions = new INTERNET_PER_CONN_OPTION[list.dwOptionCount]; // Make sure the memory was allocated. - if (nullptr == list.pOptions) { + if (nullptr == list.pOptions) + { // Return FALSE if the memory wasn't allocated. LOG(MODULE_PROXY, "Failed to allocat memory in DisableConnectionProxy()") } @@ -298,14 +289,15 @@ namespace Qv2ray::components::proxy // // Set the options on the connection. bReturn = InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); - delete [] list.pOptions; + delete[] list.pOptions; InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0); InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0); #elif defined(Q_OS_LINUX) QProcess::execute("gsettings set org.gnome.system.proxy mode 'none'"); #else - for (auto service : macOSgetNetworkServices()) { + for (auto service : macOSgetNetworkServices()) + { LOG(MODULE_PROXY, "Clearing proxy for interface: " + service) QProcess::execute("/usr/sbin/networksetup -setautoproxystate " + service + " off"); QProcess::execute("/usr/sbin/networksetup -setwebproxystate " + service + " off"); @@ -315,4 +307,4 @@ namespace Qv2ray::components::proxy #endif } -} +} // namespace Qv2ray::components::proxy diff --git a/src/components/proxy/QvProxyConfigurator.hpp b/src/components/proxy/QvProxyConfigurator.hpp index 3eb9c91a..f8e071d8 100644 --- a/src/components/proxy/QvProxyConfigurator.hpp +++ b/src/components/proxy/QvProxyConfigurator.hpp @@ -1,12 +1,12 @@ #pragma once -#include #include +#include // namespace Qv2ray::components::proxy { void ClearSystemProxy(); void SetSystemProxy(const QString &address, int http_port, int socks_port, bool usePAC); -} +} // namespace Qv2ray::components::proxy using namespace Qv2ray::components; using namespace Qv2ray::components::proxy; diff --git a/src/components/speedchart/speedplotview.cpp b/src/components/speedchart/speedplotview.cpp index 9dae7d5f..848d4b32 100644 --- a/src/components/speedchart/speedplotview.cpp +++ b/src/components/speedchart/speedplotview.cpp @@ -14,39 +14,40 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. * * In addition, as a special exception, the copyright holders give permission to * link this program with the OpenSSL project's "OpenSSL" library (or with * modified versions of it that use the same license as the "OpenSSL" library), * and distribute the linked executables. You must obey the GNU General Public - * License in all respects for all of the code used other than "OpenSSL". If you - * modify file(s), you may extend this exception to your version of the file(s), - * but you are not obligated to do so. If you do not wish to do so, delete this - * exception statement from your version. + * License in all respects for all of the code used other than "OpenSSL". If + * you modify file(s), you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. */ #include "speedplotview.hpp" +#include #include #include #include #include -#include - #define VIEWABLE 120 // use binary prefix standards from IEC 60027-2 // see http://en.wikipedia.org/wiki/Kilobyte -enum class SizeUnit { - Byte, // 1024^0, - KibiByte, // 1024^1, - MebiByte, // 1024^2, - GibiByte, // 1024^3, - TebiByte, // 1024^4, - PebiByte, // 1024^5, - ExbiByte // 1024^6, +enum class SizeUnit +{ + Byte, // 1024^0, + KibiByte, // 1024^1, + MebiByte, // 1024^2, + GibiByte, // 1024^3, + TebiByte, // 1024^4, + PebiByte, // 1024^5, + ExbiByte // 1024^6, // int64 is used for sizes and thus the next units can not be handled // ZebiByte, // 1024^7, // YobiByte, // 1024^8 @@ -54,27 +55,25 @@ enum class SizeUnit { namespace { - const struct { + const struct + { const char *source; const char *comment; - } units[] = { - QT_TRANSLATE_NOOP3("misc", "B", "bytes"), - QT_TRANSLATE_NOOP3("misc", "KiB", "kibibytes (1024 bytes)"), - QT_TRANSLATE_NOOP3("misc", "MiB", "mebibytes (1024 kibibytes)"), - QT_TRANSLATE_NOOP3("misc", "GiB", "gibibytes (1024 mibibytes)"), - QT_TRANSLATE_NOOP3("misc", "TiB", "tebibytes (1024 gibibytes)"), - QT_TRANSLATE_NOOP3("misc", "PiB", "pebibytes (1024 tebibytes)"), - QT_TRANSLATE_NOOP3("misc", "EiB", "exbibytes (1024 pebibytes)") - }; -} + } units[] = { QT_TRANSLATE_NOOP3("misc", "B", "bytes"), + QT_TRANSLATE_NOOP3("misc", "KiB", "kibibytes (1024 bytes)"), + QT_TRANSLATE_NOOP3("misc", "MiB", "mebibytes (1024 kibibytes)"), + QT_TRANSLATE_NOOP3("misc", "GiB", "gibibytes (1024 mibibytes)"), + QT_TRANSLATE_NOOP3("misc", "TiB", "tebibytes (1024 gibibytes)"), + QT_TRANSLATE_NOOP3("misc", "PiB", "pebibytes (1024 tebibytes)"), + QT_TRANSLATE_NOOP3("misc", "EiB", "exbibytes (1024 pebibytes)") }; +} // namespace QString unitString(const SizeUnit unit, const bool isSpeed) { const auto &unitString = units[static_cast(unit)]; QString ret = QCoreApplication::translate("misc", unitString.source, unitString.comment); - if (isSpeed) - ret += QCoreApplication::translate("misc", "/s", "per second"); + if (isSpeed) ret += QCoreApplication::translate("misc", "/s", "per second"); return ret; } @@ -82,36 +81,34 @@ QString unitString(const SizeUnit unit, const bool isSpeed) int friendlyUnitPrecision(const SizeUnit unit) { // friendlyUnit's number of digits after the decimal point - switch (unit) { - case SizeUnit::Byte: - return 0; + switch (unit) + { + case SizeUnit::Byte: return 0; case SizeUnit::KibiByte: - case SizeUnit::MebiByte: - return 1; + case SizeUnit::MebiByte: return 1; - case SizeUnit::GibiByte: - return 2; + case SizeUnit::GibiByte: return 2; - default: - return 3; + default: return 3; } } qlonglong sizeInBytes(qreal size, const SizeUnit unit) { - for (int i = 0; i < static_cast(unit); ++i) - size *= 1024; + for (int i = 0; i < static_cast(unit); ++i) size *= 1024; return size; } namespace { - // table of supposed nice steps for grid marks to get nice looking quarters of scale - const double roundingTable[] = {1.2, 1.6, 2, 2.4, 2.8, 3.2, 4, 6, 8}; + // table of supposed nice steps for grid marks to get nice looking quarters + // of scale + const double roundingTable[] = { 1.2, 1.6, 2, 2.4, 2.8, 3.2, 4, 6, 8 }; - struct SplittedValue { + struct SplittedValue + { double arg; SizeUnit unit; qint64 sizeInBytes() const @@ -122,56 +119,53 @@ namespace SplittedValue getRoundedYScale(double value) { - if (value == 0.0) return {0, SizeUnit::Byte}; + if (value == 0.0) return { 0, SizeUnit::Byte }; - if (value <= 12.0) return {12, SizeUnit::Byte}; + if (value <= 12.0) return { 12, SizeUnit::Byte }; SizeUnit calculatedUnit = SizeUnit::Byte; - while (value > 1024) { + while (value > 1024) + { value /= 1024; calculatedUnit = static_cast(static_cast(calculatedUnit) + 1); } - if (value > 100.0) { + if (value > 100.0) + { int roundedValue = static_cast(value / 40) * 40; - while (roundedValue < value) - roundedValue += 40; + while (roundedValue < value) roundedValue += 40; - return {static_cast(roundedValue), calculatedUnit}; + return { static_cast(roundedValue), calculatedUnit }; } - if (value > 10.0) { + if (value > 10.0) + { int roundedValue = static_cast(value / 4) * 4; - while (roundedValue < value) - roundedValue += 4; + while (roundedValue < value) roundedValue += 4; - return {static_cast(roundedValue), calculatedUnit}; + return { static_cast(roundedValue), calculatedUnit }; } - for (const auto &roundedValue : roundingTable) { - if (value <= roundedValue) - return {roundedValue, calculatedUnit}; + for (const auto &roundedValue : roundingTable) + { + if (value <= roundedValue) return { roundedValue, calculatedUnit }; } - return {10.0, calculatedUnit}; + return { 10.0, calculatedUnit }; } QString formatLabel(const double argValue, const SizeUnit unit) { // check is there need for digits after decimal separator const int precision = (argValue < 10) ? friendlyUnitPrecision(unit) : 0; - return QLocale::system().toString(argValue, 'f', precision) - + QString::fromUtf8(" ") - + unitString(unit, true); + return QLocale::system().toString(argValue, 'f', precision) + QString::fromUtf8(" ") + unitString(unit, true); } -} +} // namespace -SpeedPlotView::SpeedPlotView(QWidget *parent) - : QGraphicsView(parent) - , m_currentData(&m_datahalfMin) +SpeedPlotView::SpeedPlotView(QWidget *parent) : QGraphicsView(parent), m_currentData(&m_datahalfMin) { QPen greenPen; greenPen.setWidthF(1.5); @@ -193,9 +187,7 @@ void SpeedPlotView::pushPoint(const SpeedPlotView::PointData &point) { m_datahalfMin.push_back(point); - while (m_datahalfMin.length() > VIEWABLE) { - m_datahalfMin.removeFirst(); - } + while (m_datahalfMin.length() > VIEWABLE) { m_datahalfMin.removeFirst(); } } void SpeedPlotView::replot() @@ -213,11 +205,12 @@ quint64 SpeedPlotView::maxYValue() auto &queue = getCurrentData(); quint64 maxYValue = 0; - for (int id = UP; id < NB_GRAPHS; ++id) { + for (int id = UP; id < NB_GRAPHS; ++id) + { // 30 is half min - for (int i = queue.size() - 1, j = 0; (i >= 0) && (j <= VIEWABLE); --i, ++j) { - if (queue[i].y[id] > maxYValue) - maxYValue = queue[i].y[id]; + for (int i = queue.size() - 1, j = 0; (i >= 0) && (j <= VIEWABLE); --i, ++j) + { + if (queue[i].y[id] > maxYValue) maxYValue = queue[i].y[id]; } } @@ -244,12 +237,12 @@ void SpeedPlotView::paintEvent(QPaintEvent *) int yAxisWidth = 0; for (const QString &label : speedLabels) - if (fontMetrics.horizontalAdvance(label) > yAxisWidth) - yAxisWidth = fontMetrics.horizontalAdvance(label); + if (fontMetrics.horizontalAdvance(label) > yAxisWidth) yAxisWidth = fontMetrics.horizontalAdvance(label); int i = 0; - for (const QString &label : speedLabels) { + for (const QString &label : speedLabels) + { QRectF labelRect(rect.topLeft() + QPointF(-yAxisWidth, (i++) * 0.25 * rect.height() - fontMetrics.height()), QSizeF(2 * yAxisWidth, fontMetrics.height())); painter.drawText(labelRect, label, Qt::AlignRight | Qt::AlignTop); @@ -269,7 +262,8 @@ void SpeedPlotView::paintEvent(QPaintEvent *) painter.drawLine(fullRect.left(), rect.bottom(), rect.right(), rect.bottom()); const int TIME_AXIS_DIVISIONS = 6; - for (int i = 0; i < TIME_AXIS_DIVISIONS; ++i) { + for (int i = 0; i < TIME_AXIS_DIVISIONS; ++i) + { const int x = rect.left() + (i * rect.width()) / TIME_AXIS_DIVISIONS; painter.drawLine(x, fullRect.top(), x, fullRect.bottom()); } @@ -282,10 +276,12 @@ void SpeedPlotView::paintEvent(QPaintEvent *) const double xTickSize = static_cast(rect.width()) / VIEWABLE; auto &queue = getCurrentData(); - for (int id = UP; id < NB_GRAPHS; ++id) { + for (int id = UP; id < NB_GRAPHS; ++id) + { QVector points; - for (int i = static_cast(queue.size()) - 1, j = 0; (i >= 0) && (j <= VIEWABLE); --i, ++j) { + for (int i = static_cast(queue.size()) - 1, j = 0; (i >= 0) && (j <= VIEWABLE); --i, ++j) + { int newX = rect.right() - j * xTickSize; int newY = rect.bottom() - queue[i].y[id] * yMultiplier; points.push_back(QPoint(newX, newY)); @@ -300,27 +296,28 @@ void SpeedPlotView::paintEvent(QPaintEvent *) double legendHeight = 0; int legendWidth = 0; - for (const auto &property : m_properties) { - if (fontMetrics.horizontalAdvance(property.name) > legendWidth) - legendWidth = fontMetrics.horizontalAdvance(property.name); + for (const auto &property : m_properties) + { + if (fontMetrics.horizontalAdvance(property.name) > legendWidth) legendWidth = fontMetrics.horizontalAdvance(property.name); legendHeight += 1.5 * fontMetrics.height(); } QRectF legendBackgroundRect(QPoint(legendTopLeft.x() - 4, legendTopLeft.y() - 4), QSizeF(legendWidth + 8, legendHeight + 8)); QColor legendBackgroundColor = QWidget::palette().color(QWidget::backgroundRole()); - legendBackgroundColor.setAlpha(128); // 50% transparent + legendBackgroundColor.setAlpha(128); // 50% transparent painter.fillRect(legendBackgroundRect, legendBackgroundColor); i = 0; - for (const auto &property : m_properties) { + for (const auto &property : m_properties) + { int nameSize = fontMetrics.horizontalAdvance(property.name); double indent = 1.5 * (i++) * fontMetrics.height(); painter.setPen(property.pen); painter.drawLine(legendTopLeft + QPointF(0, indent + fontMetrics.height()), legendTopLeft + QPointF(nameSize, indent + fontMetrics.height())); - painter.drawText(QRectF(legendTopLeft + QPointF(0, indent), QSizeF(2 * nameSize, fontMetrics.height())), - property.name, QTextOption(Qt::AlignVCenter)); + painter.drawText(QRectF(legendTopLeft + QPointF(0, indent), QSizeF(2 * nameSize, fontMetrics.height())), property.name, + QTextOption(Qt::AlignVCenter)); } } @@ -328,8 +325,6 @@ SpeedPlotView::GraphProperties::GraphProperties() { } -SpeedPlotView::GraphProperties::GraphProperties(const QString &name, const QPen &pen) - : name(name) - , pen(pen) +SpeedPlotView::GraphProperties::GraphProperties(const QString &name, const QPen &pen) : name(name), pen(pen) { } diff --git a/src/components/speedchart/speedplotview.hpp b/src/components/speedchart/speedplotview.hpp index a796b212..d1910bed 100644 --- a/src/components/speedchart/speedplotview.hpp +++ b/src/components/speedchart/speedplotview.hpp @@ -36,43 +36,46 @@ class QPen; class SpeedPlotView : public QGraphicsView { - Q_OBJECT + Q_OBJECT - public: - enum GraphID { - UP = 0, - DOWN, - NB_GRAPHS - }; + public: + enum GraphID + { + UP = 0, + DOWN, + NB_GRAPHS + }; - struct PointData { - qint64 x; - quint64 y[NB_GRAPHS]; - }; + struct PointData + { + qint64 x; + quint64 y[NB_GRAPHS]; + }; - explicit SpeedPlotView(QWidget *parent = nullptr); - void pushPoint(const PointData &point); - void Clear(); - void replot(); + explicit SpeedPlotView(QWidget *parent = nullptr); + void pushPoint(const PointData &point); + void Clear(); + void replot(); - protected: - void paintEvent(QPaintEvent *event) override; + protected: + void paintEvent(QPaintEvent *event) override; - private: - struct GraphProperties { - GraphProperties(); - GraphProperties(const QString &name, const QPen &pen); + private: + struct GraphProperties + { + GraphProperties(); + GraphProperties(const QString &name, const QPen &pen); - QString name; - QPen pen; - }; + QString name; + QPen pen; + }; - quint64 maxYValue(); - QList &getCurrentData(); - QList m_datahalfMin; - QList *m_currentData; + quint64 maxYValue(); + QList &getCurrentData(); + QList m_datahalfMin; + QList *m_currentData; - QMap m_properties; + QMap m_properties; }; #endif // SPEEDPLOTVIEW_H diff --git a/src/components/speedchart/speedwidget.cpp b/src/components/speedchart/speedwidget.cpp index 4e548bd2..13c119cf 100644 --- a/src/components/speedchart/speedwidget.cpp +++ b/src/components/speedchart/speedwidget.cpp @@ -14,20 +14,23 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. * * In addition, as a special exception, the copyright holders give permission to * link this program with the OpenSSL project's "OpenSSL" library (or with * modified versions of it that use the same license as the "OpenSSL" library), * and distribute the linked executables. You must obey the GNU General Public - * License in all respects for all of the code used other than "OpenSSL". If you - * modify file(s), you may extend this exception to your version of the file(s), - * but you are not obligated to do so. If you do not wish to do so, delete this - * exception statement from your version. + * License in all respects for all of the code used other than "OpenSSL". If + * you modify file(s), you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. */ #include "speedwidget.hpp" +#include "speedplotview.hpp" + #include #include #include @@ -35,10 +38,7 @@ #include #include -#include "speedplotview.hpp" - -SpeedWidget::SpeedWidget(QWidget *parent) - : QWidget(parent) +SpeedWidget::SpeedWidget(QWidget *parent) : QWidget(parent) { m_layout = new QVBoxLayout(this); m_layout->setContentsMargins(0, 0, 0, 0); @@ -52,7 +52,9 @@ SpeedWidget::SpeedWidget(QWidget *parent) m_plot->show(); } -SpeedWidget::~SpeedWidget() {} +SpeedWidget::~SpeedWidget() +{ +} void SpeedWidget::AddPointData(long up, long down) { diff --git a/src/components/speedchart/speedwidget.hpp b/src/components/speedchart/speedwidget.hpp index e6462332..cd3e1ece 100644 --- a/src/components/speedchart/speedwidget.hpp +++ b/src/components/speedchart/speedwidget.hpp @@ -41,17 +41,18 @@ class SpeedPlotView; class SpeedWidget : public QWidget { - Q_OBJECT + Q_OBJECT - public: - explicit SpeedWidget(QWidget *parent); - ~SpeedWidget(); - void AddPointData(long up, long down); - void Clear(); - private: - QVBoxLayout *m_layout; - QHBoxLayout *m_hlayout; - SpeedPlotView *m_plot; + public: + explicit SpeedWidget(QWidget *parent); + ~SpeedWidget(); + void AddPointData(long up, long down); + void Clear(); + + private: + QVBoxLayout *m_layout; + QHBoxLayout *m_hlayout; + SpeedPlotView *m_plot; }; #endif // SPEEDWIDGET_H diff --git a/src/core/CoreSafeTypes.hpp b/src/core/CoreSafeTypes.hpp index 824d1ca9..145624cd 100644 --- a/src/core/CoreSafeTypes.hpp +++ b/src/core/CoreSafeTypes.hpp @@ -1,38 +1,43 @@ #pragma once -#include -#include -#include - #include "base/models/QvConfigIdentifier.hpp" +#include +#include +#include + namespace Qv2ray::core { - template + template class IDType { - public: - explicit IDType(const QString &id): m_id(id) {} - friend bool operator==(const IDType &lhs, const IDType &rhs) - { - return lhs.m_id == rhs.m_id; - } - friend bool operator!=(const IDType &lhs, const IDType &rhs) - { - return lhs.toString() != rhs.toString(); - } - const QString &toString() const - { - return m_id; - } - uint qHash(uint seed) const - { - return ::qHash(m_id, seed); - } - private: - QString m_id; - }; + public: + explicit IDType() : m_id("null") + { + } + explicit IDType(const QString &id) : m_id(id) + { + } + friend bool operator==(const IDType &lhs, const IDType &rhs) + { + return lhs.m_id == rhs.m_id; + } + friend bool operator!=(const IDType &lhs, const IDType &rhs) + { + return lhs.toString() != rhs.toString(); + } + const QString &toString() const + { + return m_id; + } + uint qHash(uint seed) const + { + return ::qHash(m_id, seed); + } + private: + QString m_id; + }; // Define several safetypes to prevent misuse of QString. class __QvGroup; @@ -48,9 +53,7 @@ namespace Qv2ray::core { QList list; - for (auto str : strings) { - list << IDType(str); - } + for (auto str : strings) { list << IDType(str); } return list; } @@ -60,21 +63,23 @@ namespace Qv2ray::core { QList list; - for (auto id : ids) { - list << id.toString(); - } + for (auto id : ids) { list << id.toString(); } return list; } - template uint qHash(const IDType &key, uint seed = 0) + template + uint qHash(const IDType &key, uint seed = 0) { return key.qHash(seed); } // /// Metadata object representing a connection. - struct ConnectionMetaObject : ConnectionObject_Config { + struct ConnectionMetaObject : ConnectionObject_Config + { GroupId groupId = NullGroupId; - ConnectionMetaObject(): ConnectionObject_Config() { } + ConnectionMetaObject() : ConnectionObject_Config() + { + } // Suger for down casting. ConnectionMetaObject(const ConnectionObject_Config &base) : ConnectionMetaObject() { @@ -88,13 +93,16 @@ namespace Qv2ray::core }; /// Metadata object representing a group. - struct GroupMetaObject: SubscriptionObject_Config { + struct GroupMetaObject : SubscriptionObject_Config + { // Implicit base of two types, since group object is actually the group base object. bool isSubscription; QList connections; // Suger for down casting. - GroupMetaObject(): connections() {} - GroupMetaObject(const GroupObject_Config &base): GroupMetaObject() + GroupMetaObject() : connections() + { + } + GroupMetaObject(const GroupObject_Config &base) : GroupMetaObject() { this->isSubscription = false; this->displayName = base.displayName; @@ -102,7 +110,7 @@ namespace Qv2ray::core this->connections = StringsToIdList(base.connections); } // Suger for down casting. - GroupMetaObject(const SubscriptionObject_Config &base): GroupMetaObject((GroupObject_Config)base) + GroupMetaObject(const SubscriptionObject_Config &base) : GroupMetaObject((GroupObject_Config) base) { this->address = base.address; this->lastUpdated = base.lastUpdated; @@ -110,6 +118,6 @@ namespace Qv2ray::core this->isSubscription = true; } }; -} +} // namespace Qv2ray::core using namespace Qv2ray::core; diff --git a/src/core/CoreUtils.cpp b/src/core/CoreUtils.cpp index ba9cd913..72c0c98f 100644 --- a/src/core/CoreUtils.cpp +++ b/src/core/CoreUtils.cpp @@ -24,26 +24,33 @@ namespace Qv2ray::core *port = 0; *protocol = out["protocol"].toString(QObject::tr("N/A")).toLower(); - if (*protocol == "vmess") { - auto Server = StructFromJsonString(JsonToString(out["settings"].toObject()["vnext"].toArray().first().toObject())); + if (*protocol == "vmess") + { + auto Server = + StructFromJsonString(JsonToString(out["settings"].toObject()["vnext"].toArray().first().toObject())); *host = Server.address; *port = Server.port; return true; - } else if (*protocol == "shadowsocks") { + } + else if (*protocol == "shadowsocks") + { auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject()); auto Server = StructFromJsonString(x); *host = Server.address; *port = Server.port; return true; - } else if (*protocol == "socks") { + } + else if (*protocol == "socks") + { auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject()); auto Server = StructFromJsonString(x); *host = Server.address; *port = Server.port; return true; - } else { + } + else + { return false; } } -} - +} // namespace Qv2ray::core diff --git a/src/core/CoreUtils.hpp b/src/core/CoreUtils.hpp index 06e59652..4a93d64d 100644 --- a/src/core/CoreUtils.hpp +++ b/src/core/CoreUtils.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include #include +#include namespace Qv2ray::core { @@ -26,6 +26,6 @@ namespace Qv2ray::core bool GetOutboundData(const OUTBOUND &out, QString *host, int *port, QString *protocol); bool IsComplexConfig(const CONFIGROOT &root); -} +} // namespace Qv2ray::core using namespace Qv2ray::core; diff --git a/src/core/config/ConfigBackend.cpp b/src/core/config/ConfigBackend.cpp index b3406fd0..6ea686b5 100644 --- a/src/core/config/ConfigBackend.cpp +++ b/src/core/config/ConfigBackend.cpp @@ -1,4 +1,5 @@ #include "ConfigBackend.hpp" + #include "common/QvHelpers.hpp" namespace Qv2ray::core::config @@ -14,10 +15,8 @@ namespace Qv2ray::core::config { Qv2rayConfigPath = path; - if (!path.endsWith("/")) { - Qv2rayConfigPath += "/"; - } + if (!path.endsWith("/")) { Qv2rayConfigPath += "/"; } } -} +} // namespace Qv2ray::core::config using namespace Qv2ray::core::config; diff --git a/src/core/config/ConfigBackend.hpp b/src/core/config/ConfigBackend.hpp index 35966a29..6ea855b8 100644 --- a/src/core/config/ConfigBackend.hpp +++ b/src/core/config/ConfigBackend.hpp @@ -4,7 +4,7 @@ namespace Qv2ray::core::config { void SaveGlobalConfig(const Qv2rayConfig &conf); void SetConfigDirPath(const QString &path); -} +} // namespace Qv2ray::core::config using namespace Qv2ray::core; using namespace Qv2ray::core::config; diff --git a/src/core/config/ConfigUpgrade.cpp b/src/core/config/ConfigUpgrade.cpp index 4b07e8cc..54a02117 100644 --- a/src/core/config/ConfigUpgrade.cpp +++ b/src/core/config/ConfigUpgrade.cpp @@ -13,11 +13,14 @@ namespace Qv2ray // Private member QJsonObject UpgradeConfig_Inc(int fromVersion, QJsonObject root) { - switch (fromVersion) { + switch (fromVersion) + { // -------------------------------------------------------------------------------------- // Below is for Qv2ray version 2 - case 4: { - // We changed the "proxyCN" to "bypassCN" as it's easier to understand.... + case 4: + { + // We changed the "proxyCN" to "bypassCN" as it's easier to + // understand.... auto v2_oldProxyCN = root["proxyCN"].toBool(); // // From 3 to 4, we changed 'runAsRoot' to 'tProxySupport' @@ -38,7 +41,7 @@ namespace Qv2ray root.remove("inBoundSettings"); UPGRADELOG("Renamed inBoundSettings to inboundConfig.") // - //connectionConfig + // connectionConfig QJsonObject o; o["dnsList"] = root["dnsList"]; o["withLocalDNS"] = root["withLocalDNS"]; @@ -66,13 +69,15 @@ namespace Qv2ray } // Qv2ray version 2, RC 2 - case 5: { + case 5: + { // Added subscription auto update auto subs = root["subscribes"].toObject(); root.remove("subscribes"); QJsonObject newSubscriptions; - for (auto item = subs.begin(); item != subs.end(); item++) { + for (auto item = subs.begin(); item != subs.end(); item++) + { auto key = item.key(); SubscriptionObject_Config _conf; _conf.address = item.value().toString(); @@ -88,7 +93,8 @@ namespace Qv2ray } // Qv2ray version 2, RC 4 - case 6: { + case 6: + { // Moved API Stats port from connectionConfig to apiConfig QJsonObject apiConfig; apiConfig["enableAPI"] = true; @@ -97,7 +103,8 @@ namespace Qv2ray break; } - case 7: { + case 7: + { auto lang = root["uiConfig"].toObject()["language"].toString().replace("-", "_"); auto uiConfig = root["uiConfig"].toObject(); uiConfig["language"] = lang; @@ -106,23 +113,24 @@ namespace Qv2ray break; } - // From version 8 to 9, we introduced a lot of new connection metainfo(s) - case 8: { + // From version 8 to 9, we introduced a lot of new connection + // metainfo(s) + case 8: + { // Generate a default group QJsonObject defaultGroup; QStringList defaultGroupConnectionId; defaultGroup["displayName"] = QObject::tr("Default Group"); QString defaultGroupId = "000000000000"; - if (!QDir(QV2RAY_CONNECTIONS_DIR + defaultGroupId).exists()) { - QDir().mkpath(QV2RAY_CONNECTIONS_DIR + defaultGroupId); - } + if (!QDir(QV2RAY_CONNECTIONS_DIR + defaultGroupId).exists()) { QDir().mkpath(QV2RAY_CONNECTIONS_DIR + defaultGroupId); } QString autoStartId; UPGRADELOG("Upgrading connections...") QJsonObject rootConnections; - for (auto config : root["configs"].toArray()) { + for (auto config : root["configs"].toArray()) + { UPGRADELOG("Migrating: " + config.toString()) // // MOVE FILES. @@ -133,17 +141,19 @@ namespace Qv2ray DEBUG(MODULE_SETTINGS, "Generated new UUID: " + newUuid); // Check Autostart Id - if (root["autoStartConfig"].toObject()["subscriptionName"].toString().isEmpty()) { - if (root["autoStartConfig"].toObject()["connectionName"].toString() == config.toString()) { - autoStartId = newUuid; - } + if (root["autoStartConfig"].toObject()["subscriptionName"].toString().isEmpty()) + { + if (root["autoStartConfig"].toObject()["connectionName"].toString() == config.toString()) { autoStartId = newUuid; } } - if (configFile.exists()) { + if (configFile.exists()) + { auto newPath = QV2RAY_CONNECTIONS_DIR + defaultGroupId + "/" + newUuid + QV2RAY_CONFIG_FILE_EXTENSION; configFile.rename(newPath); UPGRADELOG("Moved: " + filePath + " to " + newPath); - } else { + } + else + { UPGRADELOG("WARNING! This file is not found, possible loss of data!") continue; } @@ -159,7 +169,8 @@ namespace Qv2ray QJsonObject rootSubscriptions = root.take("subscriptions").toObject(); QJsonObject newSubscriptions; - for (auto i = 0; i < rootSubscriptions.count(); i++) { + for (auto i = 0; i < rootSubscriptions.count(); i++) + { auto key = rootSubscriptions.keys()[i]; auto value = rootSubscriptions.value(key); // @@ -176,15 +187,14 @@ namespace Qv2ray auto newDirPath = QV2RAY_SUBSCRIPTION_DIR + subsUuid; QDir newDir(newDirPath); - if (!newDir.exists()) { - newDir.mkpath(newDirPath); - } + if (!newDir.exists()) { newDir.mkpath(newDirPath); } // With extensions auto fileList = GetFileList(baseDirPath); // Copy every file within a subscription. - for (auto fileName : fileList) { + for (auto fileName : fileList) + { auto subsConnectionId = GenerateUuid(); auto baseFilePath = baseDirPath + "/" + fileName; auto newFilePath = newDirPath + "/" + subsConnectionId + QV2RAY_CONFIG_FILE_EXTENSION; @@ -199,10 +209,10 @@ namespace Qv2ray // // Check Autostart Id - if (root["autoStartConfig"].toObject()["subscriptionName"].toString() == key) { - if (root["autoStartConfig"].toObject()["connectionName"].toString() == subsConnection["displayName"].toString()) { - autoStartId = subsConnectionId; - } + if (root["autoStartConfig"].toObject()["subscriptionName"].toString() == key) + { + if (root["autoStartConfig"].toObject()["connectionName"].toString() == subsConnection["displayName"].toString()) + { autoStartId = subsConnectionId; } } } @@ -222,12 +232,15 @@ namespace Qv2ray break; } - default: { - // Due to technical issue, we cannot maintain all of those upgrade processes anymore. - // Check https://github.com/Qv2ray/Qv2ray/issues/353#issuecomment-586117507 for more information + default: + { + // Due to technical issue, we cannot maintain all of those + // upgrade processes anymore. Check + // https://github.com/Qv2ray/Qv2ray/issues/353#issuecomment-586117507 + // for more information QvMessageBoxWarn(nullptr, QObject::tr("Configuration Upgrade Failed"), QObject::tr("Unsupported config version number: ") + QSTRN(fromVersion) + NEWLINE + NEWLINE + - QObject::tr("Please upgrade firstly up to Qv2ray v2.0/v2.1 and try again.")); + QObject::tr("Please upgrade firstly up to Qv2ray v2.0/v2.1 and try again.")); throw new runtime_error("The configuration version of your old Qv2ray installation is out-of-date and that" " version is not supported anymore, please try to update to an intermediate version of Qv2ray first."); } @@ -242,10 +255,8 @@ namespace Qv2ray { LOG(MODULE_SETTINGS, "Migrating config from version " + QSTRN(fromVersion) + " to " + QSTRN(toVersion)) - for (int i = fromVersion; i < toVersion; i++) { - root = UpgradeConfig_Inc(i, root); - } + for (int i = fromVersion; i < toVersion; i++) { root = UpgradeConfig_Inc(i, root); } return root; } -} +} // namespace Qv2ray diff --git a/src/core/connection/ConnectionIO.cpp b/src/core/connection/ConnectionIO.cpp index d153d653..4c4b528a 100644 --- a/src/core/connection/ConnectionIO.cpp +++ b/src/core/connection/ConnectionIO.cpp @@ -1,4 +1,5 @@ #include "ConnectionIO.hpp" + #include "common/QvHelpers.hpp" namespace Qv2ray::core::connection @@ -8,16 +9,19 @@ namespace Qv2ray::core::connection //// //// Save Connection to a place, with checking if there's existing file. //// If so, append "_N" to the name. - //bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool canOverrideExisting) + // bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool + // canOverrideExisting) //{ // auto str = JsonToString(obj); - // auto fullPath = QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION; + // auto fullPath = QV2RAY_CONFIG_DIR + *alias + + // QV2RAY_CONFIG_FILE_EXTENSION; // // // If there's already a file AND we CANNOT override existing file. // if (QFile::exists(fullPath) && !canOverrideExisting) { // // Alias is a pointer to a QString. - // DeducePossibleFileName(QV2RAY_CONFIG_DIR, alias, QV2RAY_CONFIG_FILE_EXTENSION); - // fullPath = QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION; + // DeducePossibleFileName(QV2RAY_CONFIG_DIR, alias, + // QV2RAY_CONFIG_FILE_EXTENSION); fullPath = QV2RAY_CONFIG_DIR + + // *alias + QV2RAY_CONFIG_FILE_EXTENSION; // } // // LOG(MODULE_SETTINGS, "Saving a config named: " + *alias) @@ -25,7 +29,8 @@ namespace Qv2ray::core::connection // return StringToFile(&str, &config); //} // - //bool SaveSubscriptionConfig(CONFIGROOT obj, const QString &subscription, QString *name) + // bool SaveSubscriptionConfig(CONFIGROOT obj, const QString + // &subscription, QString *name) //{ // auto str = JsonToString(obj); // auto fName = *name; @@ -34,27 +39,31 @@ namespace Qv2ray::core::connection // fName = RemoveInvalidFileName(fName); // } // - // QFile config(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + fName + QV2RAY_CONFIG_FILE_EXTENSION); + // QFile config(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + fName + // + QV2RAY_CONFIG_FILE_EXTENSION); // // // If there's already a file. THIS IS EXTREMELY RARE // if (config.exists()) { - // LOG(MODULE_FILEIO, "Trying to overrwrite an existing subscription config file. THIS IS RARE") + // LOG(MODULE_FILEIO, "Trying to overrwrite an existing + // subscription config file. THIS IS RARE") // } // // LOG(MODULE_SETTINGS, "Saving a subscription named: " + fName) // bool result = StringToFile(&str, &config); // // if (!result) { - // LOG(MODULE_FILEIO, "Failed to save a connection config from subscription: " + subscription + ", name: " + fName) + // LOG(MODULE_FILEIO, "Failed to save a connection config from + // subscription: " + subscription + ", name: " + fName) // } // // *name = fName; // return result; //} // - //bool RemoveConnection(const QString &alias) + // bool RemoveConnection(const QString &alias) //{ - // QFile config(QV2RAY_CONFIG_DIR + alias + QV2RAY_CONFIG_FILE_EXTENSION); + // QFile config(QV2RAY_CONFIG_DIR + alias + + // QV2RAY_CONFIG_FILE_EXTENSION); // // if (!config.exists()) { // LOG(MODULE_FILEIO, "Trying to remove a non-existing file?") @@ -64,9 +73,11 @@ namespace Qv2ray::core::connection // } //} // - //bool RemoveSubscriptionConnection(const QString &subsName, const QString &name) + // bool RemoveSubscriptionConnection(const QString &subsName, const + // QString &name) //{ - // QFile config(QV2RAY_SUBSCRIPTION_DIR + subsName + "/" + name + QV2RAY_CONFIG_FILE_EXTENSION); + // QFile config(QV2RAY_SUBSCRIPTION_DIR + subsName + "/" + name + + // QV2RAY_CONFIG_FILE_EXTENSION); // // if (!config.exists()) { // LOG(MODULE_FILEIO, "Trying to remove a non-existing file?") @@ -76,25 +87,32 @@ namespace Qv2ray::core::connection // } //} // - //bool RenameConnection(const QString &originalName, const QString &newName) + // bool RenameConnection(const QString &originalName, const QString + // &newName) //{ - // LOG(MODULE_CONNECTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName) - // return QFile::rename(QV2RAY_CONFIG_DIR + originalName + QV2RAY_CONFIG_FILE_EXTENSION, QV2RAY_CONFIG_DIR + newName + QV2RAY_CONFIG_FILE_EXTENSION); + // LOG(MODULE_CONNECTION, "[RENAME] --> ORIGINAL: " + originalName + + // ", NEW: " + newName) return QFile::rename(QV2RAY_CONFIG_DIR + + // originalName + QV2RAY_CONFIG_FILE_EXTENSION, QV2RAY_CONFIG_DIR + + // newName + QV2RAY_CONFIG_FILE_EXTENSION); //} // - //bool RenameSubscription(const QString &originalName, const QString &newName) + // bool RenameSubscription(const QString &originalName, const QString + // &newName) //{ - // LOG(MODULE_SUBSCRIPTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName) - // return QDir().rename(QV2RAY_SUBSCRIPTION_DIR + originalName, QV2RAY_SUBSCRIPTION_DIR + newName); + // LOG(MODULE_SUBSCRIPTION, "[RENAME] --> ORIGINAL: " + originalName + // + ", NEW: " + newName) return + // QDir().rename(QV2RAY_SUBSCRIPTION_DIR + originalName, + // QV2RAY_SUBSCRIPTION_DIR + newName); //} // - //CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool importComplex) + // CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool + // importComplex) //{ // QFile source(sourceFilePath); // // if (!source.exists()) { - // LOG(MODULE_FILEIO, "Trying to import from an non-existing file.") - // return CONFIGROOT(); + // LOG(MODULE_FILEIO, "Trying to import from an non-existing + // file.") return CONFIGROOT(); // } // // auto root = CONFIGROOT(JsonFromString(StringFromFile(&source))); @@ -111,4 +129,4 @@ namespace Qv2ray::core::connection // return root; //} } -} +} // namespace Qv2ray::core::connection diff --git a/src/core/connection/ConnectionIO.hpp b/src/core/connection/ConnectionIO.hpp index 010f45fd..c6114159 100644 --- a/src/core/connection/ConnectionIO.hpp +++ b/src/core/connection/ConnectionIO.hpp @@ -7,8 +7,8 @@ namespace Qv2ray::core::connection { // File Protocol CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool importComplex); - } -} + } // namespace ConnectionIO +} // namespace Qv2ray::core::connection using namespace Qv2ray::core::connection; using namespace Qv2ray::core::connection::ConnectionIO; diff --git a/src/core/connection/Generation.cpp b/src/core/connection/Generation.cpp index 28dc3c52..b4864c2c 100644 --- a/src/core/connection/Generation.cpp +++ b/src/core/connection/Generation.cpp @@ -1,12 +1,14 @@ #include "Generation.hpp" -#include "core/CoreUtils.hpp" + #include "common/QvHelpers.hpp" +#include "core/CoreUtils.hpp" namespace Qv2ray::core::connection { namespace Generation { - // -------------------------- BEGIN CONFIG GENERATIONS ---------------------------------------------------------------------------- + // -------------------------- BEGIN CONFIG GENERATIONS + // ---------------------------------------------------------------------------- ROUTING GenerateRoutes(bool enableProxy, bool proxyCN) { ROUTING root; @@ -15,8 +17,10 @@ namespace Qv2ray::core::connection // For Rules list ROUTERULELIST rulesList; - if (!enableProxy) { - // This is added to disable all proxies, as a alternative influence of #64 + if (!enableProxy) + { + // This is added to disable all proxies, as a alternative + // influence of #64 rulesList.append(GenerateSingleRouteRule(QStringList() << "regexp:.*", true, OUTBOUND_TAG_DIRECT)); } @@ -28,7 +32,8 @@ namespace Qv2ray::core::connection rulesList.append(GenerateSingleRouteRule(QStringList() << "geosite:cn", true, proxyCN ? OUTBOUND_TAG_DIRECT : OUTBOUND_TAG_PROXY)); // // As a bug fix of #64, this default rule has been disabled. - //rulesList.append(GenerateSingleRouteRule(QStringList({"regexp:.*"}), true, globalProxy ? OUTBOUND_TAG_PROXY : OUTBOUND_TAG_DIRECT)); + // rulesList.append(GenerateSingleRouteRule(QStringList({"regexp:.*"}), + // true, globalProxy ? OUTBOUND_TAG_PROXY : OUTBOUND_TAG_DIRECT)); root.insert("rules", rulesList); RROOT } @@ -56,20 +61,24 @@ namespace Qv2ray::core::connection RROOT } - OUTBOUNDSETTING GenerateShadowSocksOUT(QList servers) + OUTBOUNDSETTING + GenerateShadowSocksOUT(QList servers) { OUTBOUNDSETTING root; QJsonArray x; - foreach (auto server, servers) { - x.append(GenerateShadowSocksServerOUT(server.email, server.address, server.port, server.method, server.password, server.ota, server.level)); + foreach (auto server, servers) + { + x.append(GenerateShadowSocksServerOUT(server.email, server.address, server.port, server.method, server.password, server.ota, + server.level)); } root.insert("servers", x); RROOT } - OUTBOUNDSETTING GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, int level) + OUTBOUNDSETTING GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, + int level) { OUTBOUNDSETTING root; JADD(email, address, port, method, password, level, ota) @@ -81,7 +90,8 @@ namespace Qv2ray::core::connection QJsonObject root; QJsonArray servers(QJsonArray::fromStringList(dnsServers)); - if (withLocalhost) { + if (withLocalhost) + { // https://github.com/lhy0403/Qv2ray/issues/64 // The fix patch didn't touch this line below. // @@ -93,7 +103,7 @@ namespace Qv2ray::core::connection RROOT } - INBOUNDSETTING GenerateDokodemoIN(QString address, int port, QString network, int timeout, bool followRedirect, int userLevel) + INBOUNDSETTING GenerateDokodemoIN(QString address, int port, QString network, int timeout, bool followRedirect, int userLevel) { INBOUNDSETTING root; JADD(address, port, network, timeout, followRedirect, userLevel) @@ -105,17 +115,14 @@ namespace Qv2ray::core::connection INBOUNDSETTING root; QJsonArray accounts; - foreach (auto account, _accounts) { - if (account.user.isEmpty() && account.pass.isEmpty()) { - continue; - } + foreach (auto account, _accounts) + { + if (account.user.isEmpty() && account.pass.isEmpty()) { continue; } accounts.append(GetRootObject(account)); } - if (!accounts.isEmpty()) { - JADD(accounts) - } + if (!accounts.isEmpty()) { JADD(accounts) } JADD(timeout, allowTransparent, userLevel) RROOT @@ -130,7 +137,8 @@ namespace Qv2ray::core::connection oneServer["address"] = address; oneServer["port"] = port; - if (useAuth) { + if (useAuth) + { QJsonArray users; QJsonObject oneUser; oneUser["user"] = username; @@ -150,35 +158,34 @@ namespace Qv2ray::core::connection INBOUNDSETTING root; QJsonArray accounts; - foreach (auto acc, _accounts) { - if (acc.user.isEmpty() && acc.pass.isEmpty()) { - continue; - } + foreach (auto acc, _accounts) + { + if (acc.user.isEmpty() && acc.pass.isEmpty()) { continue; } accounts.append(GetRootObject(acc)); } - if (!accounts.isEmpty()) { - JADD(accounts) - } + if (!accounts.isEmpty()) { JADD(accounts) } - if (udp) { - JADD(auth, udp, ip, userLevel) - } else { + if (udp) { JADD(auth, udp, ip, userLevel) } + else + { JADD(auth, userLevel) } RROOT } - OUTBOUND GenerateOutboundEntry(QString protocol, OUTBOUNDSETTING settings, QJsonObject streamSettings, QJsonObject mux, QString sendThrough, QString tag) + OUTBOUND GenerateOutboundEntry(QString protocol, OUTBOUNDSETTING settings, QJsonObject streamSettings, QJsonObject mux, + QString sendThrough, QString tag) { OUTBOUND root; JADD(sendThrough, protocol, settings, tag, streamSettings, mux) RROOT } - INBOUND GenerateInboundEntry(QString listen, int port, QString protocol, INBOUNDSETTING settings, QString tag, QJsonObject sniffing, QJsonObject allocate) + INBOUND GenerateInboundEntry(QString listen, int port, QString protocol, INBOUNDSETTING settings, QString tag, QJsonObject sniffing, + QJsonObject allocate) { INBOUND root; LOG(MODULE_CONNECTION, "allocation is not used here.") @@ -192,20 +199,18 @@ namespace Qv2ray::core::connection QJsonObject root; QJsonArray services; - if (withHandler) - services << "HandlerService"; + if (withHandler) services << "HandlerService"; - if (withLogger) - services << "LoggerService"; + if (withLogger) services << "LoggerService"; - if (withStats) - services << "StatsService"; + if (withStats) services << "StatsService"; JADD(services, tag) RROOT } - // -------------------------- END CONFIG GENERATIONS ------------------------------------------------------------------------------ + // -------------------------- END CONFIG GENERATIONS + // ------------------------------------------------------------------------------ // BEGIN RUNTIME CONFIG GENERATION CONFIGROOT GenerateRuntimeConfig(CONFIGROOT root) @@ -213,8 +218,10 @@ namespace Qv2ray::core::connection bool isComplex = IsComplexConfig(root); QJsonObject logObject; // - //logObject.insert("access", QV2RAY_CONFIG_PATH + QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ACCESS_LOG_FILENAME); - //logObject.insert("error", QV2RAY_CONFIG_PATH + QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ERROR_LOG_FILENAME); + // logObject.insert("access", QV2RAY_CONFIG_PATH + + // QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ACCESS_LOG_FILENAME); + // logObject.insert("error", QV2RAY_CONFIG_PATH + + // QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ERROR_LOG_FILENAME); // logObject.insert("loglevel", vLogLevels[GlobalConfig.logLevel]); root.insert("log", logObject); @@ -225,20 +232,24 @@ namespace Qv2ray::core::connection // // - // If inbounds list is empty we append our global configured inbounds to the config. - if (!root.contains("inbounds") || root["inbounds"].toArray().empty()) { + // If inbounds list is empty we append our global configured + // inbounds to the config. + if (!root.contains("inbounds") || root["inbounds"].toArray().empty()) + { INBOUNDS inboundsList; // HTTP Inbound - if (GlobalConfig.inboundConfig.useHTTP) { + if (GlobalConfig.inboundConfig.useHTTP) + { INBOUND httpInBoundObject; httpInBoundObject.insert("listen", GlobalConfig.inboundConfig.listenip); httpInBoundObject.insert("port", GlobalConfig.inboundConfig.http_port); httpInBoundObject.insert("protocol", "http"); httpInBoundObject.insert("tag", "http_IN"); - if (GlobalConfig.inboundConfig.http_useAuth) { - auto httpInSettings = GenerateHTTPIN(QList() << GlobalConfig.inboundConfig.httpAccount); + if (GlobalConfig.inboundConfig.http_useAuth) + { + auto httpInSettings = GenerateHTTPIN(QList() << GlobalConfig.inboundConfig.httpAccount); httpInBoundObject.insert("settings", httpInSettings); } @@ -246,7 +257,8 @@ namespace Qv2ray::core::connection } // SOCKS Inbound - if (GlobalConfig.inboundConfig.useSocks) { + if (GlobalConfig.inboundConfig.useSocks) + { INBOUND socksInBoundObject; socksInBoundObject.insert("listen", GlobalConfig.inboundConfig.listenip); socksInBoundObject.insert("port", GlobalConfig.inboundConfig.socks_port); @@ -254,8 +266,7 @@ namespace Qv2ray::core::connection socksInBoundObject.insert("tag", "socks_IN"); auto socksInSettings = GenerateSocksIN(GlobalConfig.inboundConfig.socks_useAuth ? "password" : "noauth", QList() << GlobalConfig.inboundConfig.socksAccount, - GlobalConfig.inboundConfig.socksUDP, - GlobalConfig.inboundConfig.socksLocalIP); + GlobalConfig.inboundConfig.socksUDP, GlobalConfig.inboundConfig.socksLocalIP); socksInBoundObject.insert("settings", socksInSettings); inboundsList.append(socksInBoundObject); } @@ -264,14 +275,16 @@ namespace Qv2ray::core::connection DEBUG(MODULE_CONNECTION, "Added global config inbounds to the config") } - // Process every inbounds to make sure a tag is configured, fixed API 0 speed - // issue when no tag is configured. + // Process every inbounds to make sure a tag is configured, fixed + // API 0 speed issue when no tag is configured. INBOUNDS newTaggedInbounds = INBOUNDS(root["inbounds"].toArray()); - for (auto i = 0; i < newTaggedInbounds.count(); i++) { + for (auto i = 0; i < newTaggedInbounds.count(); i++) + { auto _inboundItem = newTaggedInbounds[i].toObject(); - if (!_inboundItem.contains("tag") || _inboundItem["tag"].toString().isEmpty()) { + if (!_inboundItem.contains("tag") || _inboundItem["tag"].toString().isEmpty()) + { LOG(MODULE_SETTINGS, "Adding a tag to an inbound.") _inboundItem["tag"] = GenerateRandomString(8); newTaggedInbounds[i] = _inboundItem; @@ -281,52 +294,66 @@ namespace Qv2ray::core::connection root["inbounds"] = newTaggedInbounds; // // - // Note: The part below always makes the whole functionality in trouble...... - // BE EXTREME CAREFUL when changing these code below... - // See: https://github.com/lhy0403/Qv2ray/issues/129 - // routeCountLabel in Mainwindow makes here failed to ENOUGH-ly check the routing tables + // Note: The part below always makes the whole functionality in + // trouble...... BE EXTREME CAREFUL when changing these code + // below... See: https://github.com/lhy0403/Qv2ray/issues/129 + // routeCountLabel in Mainwindow makes here failed to ENOUGH-ly + // check the routing tables - if (isComplex) { + if (isComplex) + { // For some config files that has routing entries already. // We DO NOT add extra routings. // // HOWEVER, we need to verify the QV2RAY_RULE_ENABLED entry. - // And what's more, process (by removing unused items) from a rule object. + // And what's more, process (by removing unused items) from a + // rule object. ROUTING routing = ROUTING(root["routing"].toObject()); ROUTERULELIST rules; LOG(MODULE_CONNECTION, "Processing an existing routing table.") - for (auto _rule : routing["rules"].toArray()) { + for (auto _rule : routing["rules"].toArray()) + { auto _b = _rule.toObject(); - if (_b.contains("QV2RAY_RULE_USE_BALANCER")) { - if (_b["QV2RAY_RULE_USE_BALANCER"].toBool()) { + if (_b.contains("QV2RAY_RULE_USE_BALANCER")) + { + if (_b["QV2RAY_RULE_USE_BALANCER"].toBool()) + { // We use balancer _b.remove("outboundTag"); - } else { + } + else + { // We only use the normal outbound _b.remove("balancerTag"); } - } else { + } + else + { LOG(MODULE_SETTINGS, "We found a rule without QV2RAY_RULE_USE_BALANCER, so don't process it.") } // If this entry has been disabled. - if (_b.contains("QV2RAY_RULE_ENABLED") && _b["QV2RAY_RULE_ENABLED"].toBool() == true) { - rules.append(_b); - } else { + if (_b.contains("QV2RAY_RULE_ENABLED") && _b["QV2RAY_RULE_ENABLED"].toBool() == true) { rules.append(_b); } + else + { LOG(MODULE_SETTINGS, "Discarded a rule as it's been set DISABLED") } } routing["rules"] = rules; root["routing"] = routing; - } else { + } + else + { // LOG(MODULE_CONNECTION, "Inserting default values to simple config") - if (root["outbounds"].toArray().count() != 1) { - // There are no ROUTING but 2 or more outbounds.... This is rare, but possible. + if (root["outbounds"].toArray().count() != 1) + { + // There are no ROUTING but 2 or more outbounds.... This is + // rare, but possible. LOG(MODULE_CONNECTION, "WARN: This message usually indicates the config file has logic errors:") LOG(MODULE_CONNECTION, "WARN: --> The config file has NO routing section, however more than 1 outbounds are detected.") } @@ -337,11 +364,13 @@ namespace Qv2ray::core::connection // Process forward proxy #define fpConf GlobalConfig.connectionConfig.forwardProxyConfig - if (fpConf.enableForwardProxy) { + if (fpConf.enableForwardProxy) + { auto outboundArray = root["outbounds"].toArray(); auto firstOutbound = outboundArray.first().toObject(); - if (firstOutbound[QV2RAY_USE_FPROXY_KEY].toBool(false)) { + if (firstOutbound[QV2RAY_USE_FPROXY_KEY].toBool(false)) + { LOG(MODULE_CONNECTION, "Applying forward proxy to current connection.") auto proxy = PROXYSETTING(); proxy["tag"] = OUTBOUND_TAG_FORWARD_PROXY; @@ -349,13 +378,20 @@ namespace Qv2ray::core::connection // FP Outbound. OUTBOUNDSETTING fpOutbound; - if (fpConf.type.toLower() == "http" || fpConf.type.toLower() == "socks") { - fpOutbound = GenerateHTTPSOCKSOut(fpConf.serverAddress, fpConf.port, fpConf.useAuth, fpConf.username, fpConf.password); - outboundArray.push_back(GenerateOutboundEntry(fpConf.type.toLower(), fpOutbound, QJsonObject(), QJsonObject(), "0.0.0.0", OUTBOUND_TAG_FORWARD_PROXY)); - } else { + if (fpConf.type.toLower() == "http" || fpConf.type.toLower() == "socks") + { + fpOutbound = + GenerateHTTPSOCKSOut(fpConf.serverAddress, fpConf.port, fpConf.useAuth, fpConf.username, fpConf.password); + outboundArray.push_back(GenerateOutboundEntry(fpConf.type.toLower(), fpOutbound, QJsonObject(), QJsonObject(), + "0.0.0.0", OUTBOUND_TAG_FORWARD_PROXY)); + } + else + { LOG(MODULE_CONNECTION, "WARNING: Unsupported outbound type: " + fpConf.type) } - } else { + } + else + { // Remove proxySettings from firstOutbound firstOutbound.remove("proxySettings"); } @@ -366,7 +402,8 @@ namespace Qv2ray::core::connection #undef fpConf OUTBOUNDS outbounds = OUTBOUNDS(root["outbounds"].toArray()); - outbounds.append(GenerateOutboundEntry("freedom", GenerateFreedomOUT("AsIs", ":0", 0), QJsonObject(), QJsonObject(), "0.0.0.0", OUTBOUND_TAG_DIRECT)); + outbounds.append(GenerateOutboundEntry("freedom", GenerateFreedomOUT("AsIs", ":0", 0), QJsonObject(), QJsonObject(), "0.0.0.0", + OUTBOUND_TAG_DIRECT)); root["outbounds"] = outbounds; } @@ -407,7 +444,8 @@ namespace Qv2ray::core::connection INBOUNDS inbounds = INBOUNDS(root["inbounds"].toArray()); INBOUNDSETTING fakeDocodemoDoor; fakeDocodemoDoor["address"] = "127.0.0.1"; - QJsonObject apiInboundsRoot = GenerateInboundEntry("127.0.0.1", GlobalConfig.apiConfig.statsPort, "dokodemo-door", fakeDocodemoDoor, API_TAG_INBOUND); + QJsonObject apiInboundsRoot = + GenerateInboundEntry("127.0.0.1", GlobalConfig.apiConfig.statsPort, "dokodemo-door", fakeDocodemoDoor, API_TAG_INBOUND); inbounds.push_front(apiInboundsRoot); root["inbounds"] = inbounds; // @@ -417,5 +455,5 @@ namespace Qv2ray::core::connection } return root; } - } -} + } // namespace Generation +} // namespace Qv2ray::core::connection diff --git a/src/core/connection/Generation.hpp b/src/core/connection/Generation.hpp index 0392180f..3fc7ebb8 100644 --- a/src/core/connection/Generation.hpp +++ b/src/core/connection/Generation.hpp @@ -5,7 +5,7 @@ namespace Qv2ray::core::connection namespace Generation { // Important config generation algorithms. - const QStringList vLogLevels = {"none", "debug", "info", "warning", "error"}; + const QStringList vLogLevels = { "none", "debug", "info", "warning", "error" }; ROUTING GenerateRoutes(bool enableProxy, bool cnProxy); ROUTERULE GenerateSingleRouteRule(QStringList list, bool isDomain, QString outboundTag, QString type = "field"); QJsonObject GenerateDNS(bool withLocalhost, QStringList dnsServers); @@ -15,20 +15,24 @@ namespace Qv2ray::core::connection OUTBOUNDSETTING GenerateFreedomOUT(QString domainStrategy, QString redirect, int userLevel); OUTBOUNDSETTING GenerateBlackHoleOUT(bool useHTTP); OUTBOUNDSETTING GenerateShadowSocksOUT(QList servers); - OUTBOUNDSETTING GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, int level); + OUTBOUNDSETTING GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, + int level); OUTBOUNDSETTING GenerateHTTPSOCKSOut(QString address, int port, bool useAuth, QString username, QString password); // // Inbounds Protocols - INBOUNDSETTING GenerateDokodemoIN(QString address, int port, QString network, int timeout, bool followRedirect, int userLevel); + INBOUNDSETTING GenerateDokodemoIN(QString address, int port, QString network, int timeout, bool followRedirect, int userLevel); INBOUNDSETTING GenerateHTTPIN(QList accounts, int timeout = 300, bool allowTransparent = true, int userLevel = 0); - INBOUNDSETTING GenerateSocksIN(QString auth, QList _accounts, bool udp = false, QString ip = "127.0.0.1", int userLevel = 0); + INBOUNDSETTING GenerateSocksIN(QString auth, QList _accounts, bool udp = false, QString ip = "127.0.0.1", + int userLevel = 0); // // Generate FINAL Configs CONFIGROOT GenerateRuntimeConfig(CONFIGROOT root); - OUTBOUND GenerateOutboundEntry(QString protocol, OUTBOUNDSETTING settings, QJsonObject streamSettings, QJsonObject mux = QJsonObject(), QString sendThrough = "0.0.0.0", QString tag = OUTBOUND_TAG_PROXY); - INBOUND GenerateInboundEntry(QString listen, int port, QString protocol, INBOUNDSETTING settings, QString tag, QJsonObject sniffing = QJsonObject(), QJsonObject allocate = QJsonObject()); - } -} + OUTBOUND GenerateOutboundEntry(QString protocol, OUTBOUNDSETTING settings, QJsonObject streamSettings, QJsonObject mux = QJsonObject(), + QString sendThrough = "0.0.0.0", QString tag = OUTBOUND_TAG_PROXY); + INBOUND GenerateInboundEntry(QString listen, int port, QString protocol, INBOUNDSETTING settings, QString tag, + QJsonObject sniffing = QJsonObject(), QJsonObject allocate = QJsonObject()); + } // namespace Generation +} // namespace Qv2ray::core::connection using namespace Qv2ray::core; using namespace Qv2ray::core::connection; diff --git a/src/core/connection/SSDConverter.hpp b/src/core/connection/SSDConverter.hpp index 40d948e0..9175957e 100644 --- a/src/core/connection/SSDConverter.hpp +++ b/src/core/connection/SSDConverter.hpp @@ -33,57 +33,68 @@ namespace Qv2ray::core::handlers * - log list * in case of error, no objects will be returned. */ - std::pair >>>, QStringList> - decodeSSD(const QString &uri, const QString &pattern = DEFAULT_NAME_PATTERN); - } -} + std::pair>>>, QStringList> decodeSSD( + const QString &uri, const QString &pattern = DEFAULT_NAME_PATTERN); + } // namespace ssd +} // namespace Qv2ray::core::handlers -#define MUST_EXIST(fieldName) \ - if (obj[(fieldName)].isUndefined()) {\ - logList << QObject::tr("invalid ssd link: json: field %1 must exist").arg(fieldName);\ - return std::make_pair(std::nullopt, logList);\ +#define MUST_EXIST(fieldName) \ + if (obj[(fieldName)].isUndefined()) \ + { \ + logList << QObject::tr("invalid ssd link: json: field %1 must exist").arg(fieldName); \ + return std::make_pair(std::nullopt, logList); \ } -#define MUST_PORT(fieldName) MUST_EXIST(fieldName);\ - if (int value = obj[(fieldName)].toInt(-1); value < 0 || value > 65535) { \ - logList << QObject::tr("invalid ssd link: json: field %1 must be valid port number");\ - return std::make_pair(std::nullopt, logList);\ +#define MUST_PORT(fieldName) \ + MUST_EXIST(fieldName); \ + if (int value = obj[(fieldName)].toInt(-1); value < 0 || value > 65535) \ + { \ + logList << QObject::tr("invalid ssd link: json: field %1 must be valid port number"); \ + return std::make_pair(std::nullopt, logList); \ } -#define MUST_STRING(fieldName) MUST_EXIST(fieldName);\ - if (!obj[(fieldName)].isString()) {\ - logList << QObject::tr("invalid ssd link: json: field %1 must be of type 'string'").arg(fieldName);\ - return std::make_pair(std::nullopt, logList);\ +#define MUST_STRING(fieldName) \ + MUST_EXIST(fieldName); \ + if (!obj[(fieldName)].isString()) \ + { \ + logList << QObject::tr("invalid ssd link: json: field %1 must be of type 'string'").arg(fieldName); \ + return std::make_pair(std::nullopt, logList); \ } -#define MUST_ARRAY(fieldName) MUST_EXIST(fieldName);\ - if (!obj[(fieldName)].isArray()) {\ - logList << QObject::tr("invalid ssd link: json: field %1 must be an array").arg(fieldName);\ - return std::make_pair(std::nullopt, logList);\ +#define MUST_ARRAY(fieldName) \ + MUST_EXIST(fieldName); \ + if (!obj[(fieldName)].isArray()) \ + { \ + logList << QObject::tr("invalid ssd link: json: field %1 must be an array").arg(fieldName); \ + return std::make_pair(std::nullopt, logList); \ } -#define SERVER_SHOULD_BE_OBJECT(server) \ - if (!server.isObject()) {\ - logList << QObject::tr("skipping invalid ssd server: server must be an object");\ - continue;\ +#define SERVER_SHOULD_BE_OBJECT(server) \ + if (!server.isObject()) \ + { \ + logList << QObject::tr("skipping invalid ssd server: server must be an object"); \ + continue; \ } -#define SHOULD_EXIST(fieldName) \ - if (serverObject[(fieldName)].isUndefined()) { \ - logList << QObject::tr("skipping invalid ssd server: missing required field %1").arg(fieldName);\ - continue;\ +#define SHOULD_EXIST(fieldName) \ + if (serverObject[(fieldName)].isUndefined()) \ + { \ + logList << QObject::tr("skipping invalid ssd server: missing required field %1").arg(fieldName); \ + continue; \ } -#define SHOULD_STRING(fieldName) SHOULD_EXIST(fieldName); \ - if (!serverObject[(fieldName)].isString()) { \ - logList << QObject::tr("skipping invalid ssd server: field %1 should be of type 'string'").arg(fieldName);\ - continue; \ +#define SHOULD_STRING(fieldName) \ + SHOULD_EXIST(fieldName); \ + if (!serverObject[(fieldName)].isString()) \ + { \ + logList << QObject::tr("skipping invalid ssd server: field %1 should be of type 'string'").arg(fieldName); \ + continue; \ } - -std::pair >>>, QStringList> -Qv2ray::core::handlers::ssd::decodeSSD(const QString &uri, const QString &pattern) +std::pair>>>, QStringList> Qv2ray::core::handlers::ssd:: + decodeSSD(const QString &uri, const QString &pattern) { // The list for the parsing log. QStringList logList; // ssd links should begin with "ssd://" - if (!uri.startsWith("ssd://")) { + if (!uri.startsWith("ssd://")) + { logList << QObject::tr("invalid ssd link: should begin with ssd://"); return std::make_pair(std::nullopt, logList); } @@ -92,7 +103,8 @@ Qv2ray::core::handlers::ssd::decodeSSD(const QString &uri, const QString &patter const auto ssdURIBody = QStringRef(&uri, 5, uri.length() - 6); const auto decodedJSON = QByteArray::fromBase64(ssdURIBody.toUtf8()); - if (decodedJSON.length() == 0) { + if (decodedJSON.length() == 0) + { logList << QObject::tr("invalid ssd link: base64 parse failed"); return std::make_pair(std::nullopt, logList); } @@ -101,13 +113,15 @@ Qv2ray::core::handlers::ssd::decodeSSD(const QString &uri, const QString &patter QJsonParseError err; QJsonDocument document = QJsonDocument::fromJson(decodedJSON, &err); - if (document.isNull()) { + if (document.isNull()) + { logList << QObject::tr("invalid ssd link: json parse failed: ") % err.errorString(); return std::make_pair(std::nullopt, logList); } // json should be an object - if (!document.isObject()) { + if (!document.isObject()) + { logList << QObject::tr("invalid ssd link: found non-object json, aborting"); return std::make_pair(std::nullopt, logList); } @@ -127,7 +141,8 @@ Qv2ray::core::handlers::ssd::decodeSSD(const QString &uri, const QString &patter // check: rc4-md5 is not supported by v2ray-core // TODO: more checks, including all algorithms - if (encryption == "rc4-md5") { + if (encryption == "rc4-md5") + { logList << QObject::tr("invalid ssd link: rc4-md5 encryption is not supported by v2ray-core"); return std::make_pair(std::nullopt, logList); } @@ -142,7 +157,8 @@ Qv2ray::core::handlers::ssd::decodeSSD(const QString &uri, const QString &patter // // iterate through the servers - for (QJsonValueRef server : obj["servers"].toArray()) { + for (QJsonValueRef server : obj["servers"].toArray()) + { SERVER_SHOULD_BE_OBJECT(server); QJsonObject serverObject = server.toObject(); ShadowSocksServerObject ssObject; @@ -158,11 +174,13 @@ Qv2ray::core::handlers::ssd::decodeSSD(const QString &uri, const QString &patter // port selection: // normal: use global settings // overriding: use current config - if (serverObject["port"].isUndefined()) { - ssObject.port = port; - } else if (auto currPort = serverObject["port"].toInt(-1); port >= 0 && port <= 65535) { + if (serverObject["port"].isUndefined()) { ssObject.port = port; } + else if (auto currPort = serverObject["port"].toInt(-1); port >= 0 && port <= 65535) + { ssObject.port = currPort; - } else { + } + else + { logList << QObject::tr("warning: invalid port encountered. using fallback value."); ssObject.port = port; } @@ -172,11 +190,13 @@ Qv2ray::core::handlers::ssd::decodeSSD(const QString &uri, const QString &patter // entitled: using given name QString nodeName; - if (serverObject["remarks"].isUndefined()) { - nodeName = QString("%1:%2").arg(ssObject.address).arg(ssObject.port); - } else if (serverObject["remarks"].isString()) { + if (serverObject["remarks"].isUndefined()) { nodeName = QString("%1:%2").arg(ssObject.address).arg(ssObject.port); } + else if (serverObject["remarks"].isString()) + { nodeName = serverObject["remarks"].toString(); - } else { + } + else + { logList << QObject::tr("warning: invalid name encountered. using fallback value."); nodeName = QString("%1:%2").arg(ssObject.address).arg(ssObject.port); } @@ -186,9 +206,9 @@ Qv2ray::core::handlers::ssd::decodeSSD(const QString &uri, const QString &patter // specified: use given value double ratio = 1.0; - if (auto currRatio = serverObject["ratio"].toDouble(-1.0); currRatio != -1.0) { - ratio = currRatio; - } else if (!serverObject["ratio"].isUndefined()) { + if (auto currRatio = serverObject["ratio"].toDouble(-1.0); currRatio != -1.0) { ratio = currRatio; } + else if (!serverObject["ratio"].isUndefined()) + { logList << QObject::tr("warning: invalid ratio encountered. using fallback value."); } diff --git a/src/core/connection/Serialization.cpp b/src/core/connection/Serialization.cpp index ab47b53e..25bb2433 100644 --- a/src/core/connection/Serialization.cpp +++ b/src/core/connection/Serialization.cpp @@ -1,4 +1,5 @@ #include "Serialization.hpp" + #include "Generation.hpp" #include "common/QvHelpers.hpp" #include "core/CoreUtils.hpp" @@ -12,11 +13,13 @@ namespace Qv2ray::core::connection { CONFIGROOT config; - if (link.startsWith("vmess://")) { - config = ConvertConfigFromVMessString(link, alias, errMessage); - } else if (link.startsWith("ss://")) { + if (link.startsWith("vmess://")) { config = ConvertConfigFromVMessString(link, alias, errMessage); } + else if (link.startsWith("ss://")) + { config = ConvertConfigFromSSString(link, alias, errMessage); - } else { + } + else + { *errMessage = QObject::tr("Unsupported share link format."); } @@ -31,21 +34,29 @@ namespace Qv2ray::core::connection auto type = outbound["protocol"].toString(); QString sharelink = ""; - if (type == "vmess") { - auto vmessServer = StructFromJsonString(JsonToString(outbound["settings"].toObject()["vnext"].toArray().first().toObject())); + if (type == "vmess") + { + auto vmessServer = + StructFromJsonString(JsonToString(outbound["settings"].toObject()["vnext"].toArray().first().toObject())); auto transport = StructFromJsonString(JsonToString(outbound["streamSettings"].toObject())); sharelink = ConvertConfigToVMessString(transport, vmessServer, alias); - } else if (type == "shadowsocks") { - auto ssServer = StructFromJsonString(JsonToString(outbound["settings"].toObject()["servers"].toArray().first().toObject())); + } + else if (type == "shadowsocks") + { + auto ssServer = StructFromJsonString( + JsonToString(outbound["settings"].toObject()["servers"].toArray().first().toObject())); sharelink = ConvertConfigToSSString(ssServer, alias, isSip002); - } else { + } + else + { LOG(MODULE_CONNECTION, "Unsupported outbound type: " + type) } return sharelink; } - // From https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2) + // From + // https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2) QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &serverConfig, const QString &alias) { QJsonObject vmessUriRoot; @@ -59,15 +70,19 @@ namespace Qv2ray::core::connection vmessUriRoot["net"] = transfer.network; vmessUriRoot["tls"] = transfer.security; - if (transfer.network == "tcp") { - vmessUriRoot["type"] = transfer.tcpSettings.header.type; - } else if (transfer.network == "kcp") { + if (transfer.network == "tcp") { vmessUriRoot["type"] = transfer.tcpSettings.header.type; } + else if (transfer.network == "kcp") + { vmessUriRoot["type"] = transfer.kcpSettings.header.type; - } else if (transfer.network == "quic") { + } + else if (transfer.network == "quic") + { vmessUriRoot["type"] = transfer.quicSettings.header.type; vmessUriRoot["host"] = transfer.quicSettings.security; vmessUriRoot["path"] = transfer.quicSettings.key; - } else if (transfer.network == "ws") { + } + else if (transfer.network == "ws") + { auto x = transfer.wsSettings.headers; auto host = x.contains("host"); auto CapHost = x.contains("Host"); @@ -75,7 +90,9 @@ namespace Qv2ray::core::connection // vmessUriRoot["host"] = realHost; vmessUriRoot["path"] = transfer.wsSettings.path; - } else if (transfer.network == "h2" || transfer.network == "http") { + } + else if (transfer.network == "h2" || transfer.network == "http") + { vmessUriRoot["host"] = transfer.httpSettings.host.join(","); vmessUriRoot["path"] = transfer.httpSettings.path; } @@ -89,8 +106,8 @@ namespace Qv2ray::core::connection { // String may start with: vmess:// and ss:// // We only process vmess:// here - // Some subscription providers may use plain vmess:// saperated by lines - // But others may use base64 of above. + // Some subscription providers may use plain vmess:// saperated by + // lines But others may use base64 of above. auto result = QString::fromUtf8(arr).trimmed(); return result.startsWith("vmess://") ? result : Base64Decode(result); } @@ -100,8 +117,9 @@ namespace Qv2ray::core::connection ShadowSocksServerObject server; QString d_name; - //auto ssUri = _ssUri.toStdString(); - if (ssUri.length() < 5) { + // auto ssUri = _ssUri.toStdString(); + if (ssUri.length() < 5) + { LOG(MODULE_CONNECTION, "ss:// string too short") *errMessage = QObject::tr("SS URI is too short"); } @@ -110,53 +128,51 @@ namespace Qv2ray::core::connection auto hashPos = uri.lastIndexOf("#"); DEBUG(MODULE_CONNECTION, "Hash sign position: " + QSTRN(hashPos)) - if (hashPos >= 0) { + if (hashPos >= 0) + { // Get the name/remark d_name = uri.mid(uri.lastIndexOf("#") + 1); uri.truncate(hashPos); } // No plugins for Qv2ray so disable those lnes.i - //size_t pluginPos = uri.find_first_of('/'); + // size_t pluginPos = uri.find_first_of('/'); // - //if (pluginPos != std::string::npos) { + // if (pluginPos != std::string::npos) { // // TODO: support plugins. For now, just ignore them // uri.erase(pluginPos); //} auto atPos = uri.indexOf('@'); DEBUG(MODULE_CONNECTION, "At sign position: " + QSTRN(atPos)) - if (atPos < 0) { + if (atPos < 0) + { // Old URI scheme QString decoded = QByteArray::fromBase64(uri.toUtf8(), QByteArray::Base64Option::OmitTrailingEquals); auto colonPos = decoded.indexOf(':'); DEBUG(MODULE_CONNECTION, "Colon position: " + QSTRN(colonPos)) - if (colonPos < 0) { - *errMessage = QObject::tr("Can't find the colon separator between method and password"); - } + if (colonPos < 0) { *errMessage = QObject::tr("Can't find the colon separator between method and password"); } server.method = decoded.left(colonPos); decoded.remove(0, colonPos + 1); atPos = decoded.lastIndexOf('@'); DEBUG(MODULE_CONNECTION, "At sign position: " + QSTRN(atPos)) - if (atPos < 0) { - *errMessage = QObject::tr("Can't find the at separator between password and hostname"); - } + if (atPos < 0) { *errMessage = QObject::tr("Can't find the at separator between password and hostname"); } server.password = decoded.mid(0, atPos); decoded.remove(0, atPos + 1); colonPos = decoded.lastIndexOf(':'); DEBUG(MODULE_CONNECTION, "Colon position: " + QSTRN(colonPos)) - if (colonPos < 0) { - *errMessage = QObject::tr("Can't find the colon separator between hostname and port"); - } + if (colonPos < 0) { *errMessage = QObject::tr("Can't find the colon separator between hostname and port"); } server.address = decoded.mid(0, colonPos); server.port = decoded.mid(colonPos + 1).toInt(); - } else { + } + else + { // SIP002 URI scheme auto x = QUrl::fromUserInput(uri); server.address = x.host(); @@ -166,9 +182,7 @@ namespace Qv2ray::core::connection // DEBUG(MODULE_CONNECTION, "Userinfo splitter position: " + QSTRN(userInfoSp)) - if (userInfoSp < 0) { - *errMessage = QObject::tr("Can't find the colon separator between method and password"); - } + if (userInfoSp < 0) { *errMessage = QObject::tr("Can't find the colon separator between method and password"); } QString method = userInfo.mid(0, userInfoSp); server.method = method; @@ -178,7 +192,8 @@ namespace Qv2ray::core::connection d_name = QUrl::fromPercentEncoding(d_name.toUtf8()); CONFIGROOT root; OUTBOUNDS outbounds; - outbounds.append(GenerateOutboundEntry("shadowsocks", GenerateShadowSocksOUT(QList() << server), QJsonObject())); + outbounds.append( + GenerateOutboundEntry("shadowsocks", GenerateShadowSocksOUT(QList() << server), QJsonObject())); JADD(outbounds) *alias = alias->isEmpty() ? d_name : *alias + "_" + d_name; LOG(MODULE_CONNECTION, "Deduced alias: " + *alias) @@ -189,12 +204,15 @@ namespace Qv2ray::core::connection { auto myAlias = QUrl::toPercentEncoding(alias); - if (isSip002) { + if (isSip002) + { LOG(MODULE_CONNECTION, "Converting an ss-server config to Sip002 ss:// format") QString plainUserInfo = server.method + ":" + server.password; QString userinfo(plainUserInfo.toUtf8().toBase64(QByteArray::Base64Option::Base64UrlEncoding).data()); return "ss://" + userinfo + "@" + server.address + ":" + QSTRN(server.port) + "#" + myAlias; - } else { + } + else + { LOG(MODULE_CONNECTION, "Converting an ss-server config to old ss:// string format") QString ssUri = server.method + ":" + server.password + "@" + server.address + ":" + QSTRN(server.port); return "ss://" + ssUri.toUtf8().toBase64(QByteArray::Base64Option::OmitTrailingEquals) + "#" + myAlias; @@ -209,7 +227,8 @@ namespace Qv2ray::core::connection LOG(MODULE_SETTINGS, "Trying to convert from a vmess string.") QString vmess = vmessStr; - if (vmess.trimmed() != vmess) { + if (vmess.trimmed() != vmess) + { LOG(MODULE_SETTINGS, "VMess string has some prefix/postfix spaces, trimming.") vmess = vmessStr.trimmed(); } @@ -217,16 +236,19 @@ namespace Qv2ray::core::connection // Reset errMessage *errMessage = ""; - if (!vmess.toLower().startsWith("vmess://")) { + if (!vmess.toLower().startsWith("vmess://")) + { *errMessage = QObject::tr("VMess string should start with 'vmess://'"); return default; } - try { + try + { QStringRef vmessJsonB64(&vmess, 8, vmess.length() - 8); auto b64Str = vmessJsonB64.toString(); - if (b64Str.isEmpty()) { + if (b64Str.isEmpty()) + { *errMessage = QObject::tr("VMess string should be a valid base64 string"); return default; } @@ -234,14 +256,16 @@ namespace Qv2ray::core::connection auto vmessString = Base64Decode(b64Str); auto jsonErr = VerifyJsonString(vmessString); - if (!jsonErr.isEmpty()) { + if (!jsonErr.isEmpty()) + { *errMessage = jsonErr; return default; } auto vmessConf = JsonFromString(vmessString); - if (vmessConf.isEmpty()) { + if (vmessConf.isEmpty()) + { *errMessage = QObject::tr("JSON should not be empty"); return default; } @@ -249,21 +273,23 @@ namespace Qv2ray::core::connection bool flag = true; // C is a quick hack... #define C(k) vmessConf.contains(k) - // id, aid, port and add are mandatory fields of a vmess:// link. + // id, aid, port and add are mandatory fields of a vmess:// + // link. flag = flag && C("id") && C("aid") && C("port") && C("add"); // Stream Settings auto net = C("net") ? vmessConf["net"].toString() : "tcp"; - if (net == "http" || net == "ws") - flag = flag && C("host") && C("path"); + if (net == "http" || net == "ws") flag = flag && C("host") && C("path"); else if (net == "domainsocket") flag = flag && C("path"); else if (net == "quic") flag = flag && C("host") && C("type") && C("path"); #undef C - //return flag ? 0 : 1; - } catch (exception *e) { + // return flag ? 0 : 1; + } + catch (exception *e) + { *errMessage = e->what(); LOG(MODULE_IMPORT, "Failed to decode vmess string: " + *errMessage) delete e; @@ -279,44 +305,62 @@ namespace Qv2ray::core::connection int port, aid; // // key = key in JSON and the variable name. - // values = Candidate variable list, if not match, the first one is used as default. - // [[val.size() <= 1]] is used when only the default value exists. - // - It can be empty, if so, if the key is not in the JSON, or the value is empty, it'll report an error. - // - Else if it contains one thing. if the key is not in the JSON, or the value is empty, it'll use that one. - // - Else if it contains many things, when the key IS in the JSON but not in those THINGS, it'll use the first one in the THINGS + // values = Candidate variable list, if not match, the first one is + // used as default. + // [[val.size() <= 1]] is used when only the default value + // exists. + // - It can be empty, if so, if the key is not in + // the JSON, or the value is empty, it'll report an error. + // - Else if it contains one thing. if the key is not in + // the JSON, or the value is empty, it'll use that one. + // - Else if it contains many things, when the key IS in + // the JSON but not in those THINGS, it'll use the first + // one in the THINGS // - Else, it'll use the value found from the JSON object. // #define empty_arg -#define __vmess_checker__func(key, values) \ - {\ - auto val = QStringList() values;\ - if (vmessConf.contains(#key) && !vmessConf[#key].toVariant().toString().trimmed().isEmpty() \ - && (val.size() <= 1 || val.contains(vmessConf[#key].toVariant().toString()))) {\ - key = vmessConf[#key].toVariant().toString();\ - DEBUG(MODULE_IMPORT, "Found key \"" #key "\" within the vmess object.")\ - } else if (!val.isEmpty()) {\ - key = val.first(); \ - DEBUG(MODULE_IMPORT, "Using key \"" #key "\" from the first candidate list: " + key)\ - } else{\ - *errMessage = QObject::tr(#key " does not exist."); \ - LOG(MODULE_IMPORT, "Cannot process \"" #key "\" since it's not included in the json object." ) \ - LOG(MODULE_IMPORT, " --> values: " + val.join(";")) \ - LOG(MODULE_IMPORT, " --> PS: " + ps) \ - }\ +#define __vmess_checker__func(key, values) \ + { \ + auto val = QStringList() values; \ + if (vmessConf.contains(#key) && !vmessConf[#key].toVariant().toString().trimmed().isEmpty() && \ + (val.size() <= 1 || val.contains(vmessConf[#key].toVariant().toString()))) \ + { \ + key = vmessConf[#key].toVariant().toString(); \ + DEBUG(MODULE_IMPORT, "Found key \"" #key "\" within the vmess object.") \ + } \ + else if (!val.isEmpty()) \ + { \ + key = val.first(); \ + DEBUG(MODULE_IMPORT, "Using key \"" #key "\" from the first candidate list: " + key) \ + } \ + else \ + { \ + *errMessage = QObject::tr(#key " does not exist."); \ + LOG(MODULE_IMPORT, "Cannot process \"" #key "\" since it's not included in the json object.") \ + LOG(MODULE_IMPORT, " --> values: " + val.join(";")) \ + LOG(MODULE_IMPORT, " --> PS: " + ps) \ + } \ } - // Strict check of VMess protocol, to check if the specified value is in the correct range. + // Strict check of VMess protocol, to check if the specified value + // is in the correct range. // // Get Alias (AKA ps) from address and port. __vmess_checker__func(ps, << vmessConf["add"].toVariant().toString() + ":" + vmessConf["port"].toVariant().toString()); - __vmess_checker__func(add, empty_arg) - __vmess_checker__func(id, empty_arg) - __vmess_checker__func(net, << "tcp" << "http" << "h2" << "ws" << "kcp" << "domainsocket" << "quic") - __vmess_checker__func(type, << "none" << "http" << "srtp" << "utp" << "wechat-video") - __vmess_checker__func(path, << "") - __vmess_checker__func(host, << "") - __vmess_checker__func(tls, << "") - // - port = vmessConf["port"].toVariant().toInt(); + __vmess_checker__func(add, empty_arg) __vmess_checker__func(id, empty_arg) __vmess_checker__func(net, << "tcp" + << "http" + << "h2" + << "ws" + << "kcp" + << "domainsocket" + << "quic") + __vmess_checker__func(type, << "none" + << "http" + << "srtp" + << "utp" + << "wechat-video") __vmess_checker__func(path, << "") __vmess_checker__func(host, << "") + __vmess_checker__func(tls, << "") + // + port = vmessConf["port"].toVariant().toInt(); aid = vmessConf["aid"].toVariant().toInt(); // Apply the settings. // @@ -340,23 +384,29 @@ namespace Qv2ray::core::connection // Stream Settings StreamSettingsObject streaming; - if (net == "tcp") { - streaming.tcpSettings.header.type = type; - } else if (net == "http" || net == "h2") { + if (net == "tcp") { streaming.tcpSettings.header.type = type; } + else if (net == "http" || net == "h2") + { // Fill hosts for HTTP - for (auto _host : host.split(',')) { - streaming.httpSettings.host.push_back(_host.trimmed()); - } + for (auto _host : host.split(',')) { streaming.httpSettings.host.push_back(_host.trimmed()); } streaming.httpSettings.path = path; - } else if (net == "ws") { + } + else if (net == "ws") + { streaming.wsSettings.headers["Host"] = host; streaming.wsSettings.path = path; - } else if (net == "kcp") { + } + else if (net == "kcp") + { streaming.kcpSettings.header.type = type; - } else if (net == "domainsocket") { + } + else if (net == "domainsocket") + { streaming.dsSettings.path = path; - } else if (net == "quic") { + } + else if (net == "quic") + { streaming.quicSettings.security = host; streaming.quicSettings.header.type = type; streaming.quicSettings.key = path; @@ -364,7 +414,8 @@ namespace Qv2ray::core::connection // FIXME: makeshift patch for #290. // to be rewritten after refactoring. - if (tls == "tls" && host != "" && (net == "tcp" || net == "ws")) { + if (tls == "tls" && host != "" && (net == "tcp" || net == "ws")) + { streaming.tlsSettings.serverName = host; streaming.tlsSettings.allowInsecure = false; } @@ -378,10 +429,11 @@ namespace Qv2ray::core::connection auto outbound = GenerateOutboundEntry("vmess", vConf, GetRootObject(streaming), QJsonObject(), "0.0.0.0", OUTBOUND_TAG_PROXY); // root["outbounds"] = QJsonArray() << outbound; - // If previous alias is empty, just the PS is needed, else, append a "_" + // If previous alias is empty, just the PS is needed, else, append a + // "_" *alias = alias->trimmed().isEmpty() ? ps : *alias + "_" + ps; #undef default return root; } - } -} + } // namespace Serialization +} // namespace Qv2ray::core::connection diff --git a/src/core/connection/Serialization.hpp b/src/core/connection/Serialization.hpp index fffb574d..99a03c24 100644 --- a/src/core/connection/Serialization.hpp +++ b/src/core/connection/Serialization.hpp @@ -5,7 +5,7 @@ namespace Qv2ray::core::connection { namespace Serialization { - //int VerifyVMessProtocolString(QString vmess); + // int VerifyVMessProtocolString(QString vmess); QString DecodeSubscriptionString(QByteArray arr); // General @@ -19,8 +19,8 @@ namespace Qv2ray::core::connection // SS URI Protocol CONFIGROOT ConvertConfigFromSSString(const QString &ss, QString *alias, QString *errMessage); QString ConvertConfigToSSString(const ShadowSocksServerObject &server, const QString &alias, bool isSip002); - } -} + } // namespace Serialization +} // namespace Qv2ray::core::connection using namespace Qv2ray::core; using namespace Qv2ray::core::connection; diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index a4a4608b..16eb6aa1 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -1,6 +1,8 @@ #include "ConnectionHandler.hpp" + #include "common/QvHelpers.hpp" #include "core/config/ConfigBackend.hpp" +#include "core/connection/Serialization.hpp" namespace Qv2ray::core::handlers { @@ -10,26 +12,23 @@ namespace Qv2ray::core::handlers DEBUG(MODULE_CORE_HANDLER, "ConnectionHandler Constructor.") // Do we need to check how many of them are loaded? - for (auto i = 0; i < GlobalConfig.connections.count(); i++) { - connections[ConnectionId(GlobalConfig.connections.keys()[i])] = GlobalConfig.connections.values()[i]; - } + for (auto i = 0; i < GlobalConfig.connections.count(); i++) + { connections[ConnectionId(GlobalConfig.connections.keys()[i])] = GlobalConfig.connections.values()[i]; } - for (auto key : GlobalConfig.subscriptions.keys()) { + for (auto key : GlobalConfig.subscriptions.keys()) + { auto val = GlobalConfig.subscriptions[key]; groups[GroupId(key)] = val; - for (auto conn : val.connections) { - connections[ConnectionId(conn)].groupId = GroupId(key); - } + for (auto conn : val.connections) { connections[ConnectionId(conn)].groupId = GroupId(key); } } - for (auto key : GlobalConfig.groups.keys()) { + for (auto key : GlobalConfig.groups.keys()) + { auto val = GlobalConfig.groups[key]; groups[GroupId(key)] = val; - for (auto conn : val.connections) { - connections[ConnectionId(conn)].groupId = GroupId(key); - } + for (auto conn : val.connections) { connections[ConnectionId(conn)].groupId = GroupId(key); } } vCoreInstance = new V2rayKernelInstance(); @@ -47,7 +46,7 @@ namespace Qv2ray::core::handlers pingConnectionTimerId = startTimer(60 * 1000); } - void QvConnectionHandler::CHSaveConnectionData_p() + void QvConnectionHandler::CHSaveConfigData_p() { // Copy auto newGlobalConfig = GlobalConfig; @@ -55,18 +54,21 @@ namespace Qv2ray::core::handlers newGlobalConfig.groups.clear(); newGlobalConfig.subscriptions.clear(); - for (auto i = 0; i < connections.count(); i++) { - newGlobalConfig.connections[connections.keys()[i].toString()] = connections.values()[i]; - } + for (auto i = 0; i < connections.count(); i++) + { newGlobalConfig.connections[connections.keys()[i].toString()] = connections.values()[i]; } - for (auto i = 0; i < groups.count(); i++) { + for (auto i = 0; i < groups.count(); i++) + { QStringList connections = IdListToStrings(groups.values()[i].connections); - if (groups.values()[i].isSubscription) { + if (groups.values()[i].isSubscription) + { SubscriptionObject_Config o = groups.values()[i]; o.connections = connections; newGlobalConfig.subscriptions[groups.keys()[i].toString()] = o; - } else { + } + else + { GroupObject_Config o = groups.values()[i]; o.connections = connections; newGlobalConfig.groups[groups.keys()[i].toString()] = o; @@ -78,29 +80,25 @@ namespace Qv2ray::core::handlers void QvConnectionHandler::timerEvent(QTimerEvent *event) { - if (event->timerId() == saveTimerId) { - CHSaveConnectionData_p(); - } else if (event->timerId() == pingAllTimerId) { + if (event->timerId() == saveTimerId) { CHSaveConfigData_p(); } + else if (event->timerId() == pingAllTimerId) + { StartLatencyTest(); - } else if (event->timerId() == pingConnectionTimerId) { - if (currentConnectionId != NullConnectionId) { - StartLatencyTest(currentConnectionId); - } + } + else if (event->timerId() == pingConnectionTimerId) + { + if (currentConnectionId != NullConnectionId) { StartLatencyTest(currentConnectionId); } } } void QvConnectionHandler::StartLatencyTest() { - for (auto connection : connections.keys()) { - StartLatencyTest(connection); - } + for (auto connection : connections.keys()) { StartLatencyTest(connection); } } void QvConnectionHandler::StartLatencyTest(const GroupId &id) { - for (auto connection : groups[id].connections) { - StartLatencyTest(connection); - } + for (auto connection : groups[id].connections) { StartLatencyTest(connection); } } void QvConnectionHandler::StartLatencyTest(const ConnectionId &id) @@ -123,10 +121,9 @@ namespace Qv2ray::core::handlers { QList subsList; - for (auto group : groups.keys()) { - if (groups[group].isSubscription) { - subsList.push_back(group); - } + for (auto group : groups.keys()) + { + if (groups[group].isSubscription) { subsList.push_back(group); } } return subsList; @@ -149,10 +146,9 @@ namespace Qv2ray::core::handlers const ConnectionId QvConnectionHandler::GetConnectionIdByDisplayName(const QString &displayName) const { - for (auto conn : connections.keys()) { - if (connections[conn].displayName == displayName) { - return conn; - } + for (auto conn : connections.keys()) + { + if (connections[conn].displayName == displayName) { return conn; } } return NullConnectionId; @@ -160,10 +156,9 @@ namespace Qv2ray::core::handlers const GroupId QvConnectionHandler::GetGroupIdByDisplayName(const QString &displayName) const { - for (auto group : groups.keys()) { - if (groups[group].displayName == displayName) { - return group; - } + for (auto group : groups.keys()) + { + if (groups[group].displayName == displayName) { return group; } } return NullGroupId; @@ -171,48 +166,57 @@ namespace Qv2ray::core::handlers const GroupId QvConnectionHandler::GetConnectionGroupId(const ConnectionId &id) const { - if (!connections.contains(id)) { - LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); - } + if (!connections.contains(id)) { LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); } return connections[id].groupId; } double QvConnectionHandler::GetConnectionLatency(const ConnectionId &id) const { - if (!connections.contains(id)) { - LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); - } + if (!connections.contains(id)) { LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); } return connections[id].latency; } const optional QvConnectionHandler::DeleteConnection(const ConnectionId &id) { - // TODO - Q_UNUSED(id) - return ""; + // + auto groupId = connections[id].groupId; + QFile connectionFile((groups[groupId].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR) + groupId.toString() + "/" + + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION); + // + bool exists = connectionFile.exists(); + if (exists) + { + bool removed = connectionFile.remove(); + if (removed) + { + connections.remove(id); + groups[groupId].connections.removeAll(id); + return {}; + } + else + return "Failed to remove file"; + } + else + return tr("File does not exist."); } const optional QvConnectionHandler::StartConnection(const ConnectionId &identifier) { - if (!connections.contains(identifier)) { - return tr("No connection selected!") + NEWLINE + tr("Please select a config from the list."); - } + if (!connections.contains(identifier)) { return tr("No connection selected!") + NEWLINE + tr("Please select a config from the list."); } - if (currentConnectionId != NullConnectionId) { - StopConnection(); - } + if (currentConnectionId != NullConnectionId) { StopConnection(); } CONFIGROOT root = GetConnectionRoot(connections[identifier].groupId, identifier); return CHStartConnection_p(identifier, root); } - void QvConnectionHandler::StopConnection() //const ConnectionId &id + void QvConnectionHandler::StopConnection() // const ConnectionId &id { // Currently just simply stop it. //_UNUSED(id) - //if (currentConnectionId == id) { + // if (currentConnectionId == id) { //} CHStopConnection_p(); } @@ -226,9 +230,7 @@ namespace Qv2ray::core::handlers { QString result; - if (!connections.contains(id)) { - result = tr("N/A"); - } + if (!connections.contains(id)) { result = tr("N/A"); } CONFIGROOT root = GetConnectionRoot(connections[id].groupId, id); QStringList protocols; @@ -236,12 +238,12 @@ namespace Qv2ray::core::handlers auto outbound = root["outbounds"].toArray().first().toObject(); result.append(outbound["protocol"].toString()); - if (outbound.contains("streamSettings")) { - result.append(" + " + outbound["streamSettings"].toObject()["network"].toString()); + if (outbound.contains("streamSettings")) + { + result.append(" / " + outbound["streamSettings"].toObject()["network"].toString()); - if (outbound["streamSettings"].toObject().contains("tls")) { - result.append(outbound["streamSettings"].toObject()["tls"].toBool() ? " + tls" : ""); - } + if (outbound["streamSettings"].toObject().contains("tls")) + { result.append(outbound["streamSettings"].toObject()["tls"].toBool() ? " / tls" : ""); } } return result; @@ -249,23 +251,23 @@ namespace Qv2ray::core::handlers const tuple QvConnectionHandler::GetConnectionUsageAmount(const ConnectionId &id) const { - if (!connections.contains(id)) { - return make_tuple(0, 0); - } + if (!connections.contains(id)) { return make_tuple(0, 0); } return make_tuple(connections[id].upLinkData, connections[id].downLinkData); } - //const GroupMetaObject QvConnectionHandler::GetGroup(const GroupId &id) const + // const GroupMetaObject QvConnectionHandler::GetGroup(const GroupId &id) + // const //{ // return groups[id]; //} QvConnectionHandler::~QvConnectionHandler() { - CHSaveConnectionData_p(); + CHSaveConfigData_p(); - if (vCoreInstance->KernelStarted) { + if (vCoreInstance->KernelStarted) + { vCoreInstance->StopConnection(); LOG(MODULE_CORE_HANDLER, "Stopped connection from destructor.") } @@ -285,36 +287,49 @@ namespace Qv2ray::core::handlers return CONFIGROOT(JsonFromString(StringFromFile(path))); } - const tuple QvConnectionHandler::GetConnectionInfo(const ConnectionId &id) const + const tuple QvConnectionHandler::GetConnectionData(const ConnectionId &id) const { + // TODO, what if is complex? auto root = GetConnectionRoot(id); - bool validOutboundFound = false; - QString host; - int port; - for (auto item : root["outbounds"].toArray()) { - OUTBOUND outBoundRoot = OUTBOUND(item.toObject()); - QString outboundType = ""; - validOutboundFound = GetOutboundData(outBoundRoot, &host, &port, &outboundType); - - if (validOutboundFound) { - return make_tuple(host, port); - } else { - LOG(MODULE_CORE_HANDLER, "Unknown outbound entry: " + outboundType + ", cannot deduce host and port.") - } - } - - return make_tuple(QObject::tr("N/A"), 0); + bool isSucceed = false; + auto result = CHGetOutboundData_p(root, &isSucceed); + return result; } + const tuple QvConnectionHandler::CHGetOutboundData_p(const CONFIGROOT &root, bool *ok) const + { + *ok = false; + for (auto item : root["outbounds"].toArray()) + { + OUTBOUND outBoundRoot = OUTBOUND(item.toObject()); + QString host; + int port; + QString outboundType = ""; + + if (GetOutboundData(outBoundRoot, &host, &port, &outboundType)) + { + *ok = true; + return make_tuple(outboundType, host, port); + } + else + { + LOG(MODULE_CORE_HANDLER, "Unknown outbound type: " + outboundType + ", cannot deduce host and port.") + } + } + return make_tuple(tr("N/A"), tr("N/A"), 0); + } void QvConnectionHandler::OnLatencyDataArrived(const QvTCPingResultObject &result) { - if (connections.contains(result.connectionId)) { + if (connections.contains(result.connectionId)) + { connections[result.connectionId].latency = result.avg; emit OnLatencyTestFinished(result.connectionId, result.avg); - } else { + } + else + { LOG(MODULE_CORE_HANDLER, "Received a latecy result with non-exist connection id.") } } @@ -322,8 +337,8 @@ namespace Qv2ray::core::handlers bool QvConnectionHandler::UpdateConnection(const ConnectionId &id, const CONFIGROOT &root) { auto groupId = connections[id].groupId; - auto path = (groups[groupId].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR) - + groupId.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; + auto path = (groups[groupId].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR) + groupId.toString() + "/" + + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; auto content = JsonToString(root); emit OnConnectionChanged(id); return StringToFile(content, path); @@ -333,10 +348,101 @@ namespace Qv2ray::core::handlers { tuple result; - if (!groups[id].isSubscription) { - return result; - } + if (!groups[id].isSubscription) { return result; } return make_tuple(groups[id].address, groups[id].lastUpdated, groups[id].updateInterval); } -} + + bool QvConnectionHandler::UpdateSubscription(const GroupId &id, bool useSystemProxy) + { + if (isHttpRequestInProgress) { return false; } + isHttpRequestInProgress = true; + auto data = httpHelper->syncget(groups[id].address, useSystemProxy); + isHttpRequestInProgress = false; + return CHUpdateSubscription_p(id, data); + } + + bool QvConnectionHandler::CHUpdateSubscription_p(const GroupId &id, const QByteArray &subscriptionData) + { + if (!groups.contains(id)) { return false; } + bool isAutoConnectionContainedWithin = groups[id].connections.contains(ConnectionId(GlobalConfig.autoStartId)); + Q_UNUSED(isAutoConnectionContainedWithin) + // + // Anyway, we try our best to preserve the connection id. + QMap nameMap; + QMap, ConnectionId> typeMap; + for (auto conn : groups[id].connections) + { + nameMap[GetDisplayName(conn)] = conn; + auto [protocol, host, port] = GetConnectionData(conn); + if (port != 0) { typeMap[make_tuple(protocol, host, port)] = conn; } + } + // + /// List that is holding connection IDs to be updated. + auto connectionsOrig = groups[id].connections; + auto str = DecodeSubscriptionString(subscriptionData); + if (str.isEmpty()) return false; + // + auto subsList = SplitLines(str); + QDir(QV2RAY_SUBSCRIPTION_DIR + id.toString()).removeRecursively(); + QDir().mkpath(QV2RAY_SUBSCRIPTION_DIR + id.toString()); + + bool hasErrorOccured = false; + for (auto vmess : subsList) + { + QString errMessage; + QString _alias; + auto config = ConvertConfigFromString(vmess.trimmed(), &_alias, &errMessage); + + if (!errMessage.isEmpty()) + { + LOG(MODULE_SUBSCRIPTION, "Processing a subscription with following error: " + errMessage) + hasErrorOccured = true; + continue; + } + bool canGetOutboundData = false; + auto outboundData = CHGetOutboundData_p(config, &canGetOutboundData); + // + // Begin guessing new ConnectionId + if (nameMap.contains(_alias)) + { + // Just go and save the connection... + LOG(MODULE_CORE_HANDLER, "Guessed id from name: " + _alias + ", connectionId: " + nameMap[_alias].toString()) + UpdateConnection(nameMap[_alias], config); + // Remove Connection Id from the list. + connectionsOrig.removeAll(nameMap[_alias]); + } + else if (canGetOutboundData && typeMap.contains(outboundData)) + { + LOG(MODULE_CORE_HANDLER, "Guessed id from protocol/host/port pair for connectionId: " + typeMap[outboundData].toString()) + UpdateConnection(typeMap[outboundData], config); + // Update displayName + connections[typeMap[outboundData]].displayName = _alias; + // Remove Connection Id from the list. + connectionsOrig.removeAll(typeMap[outboundData]); + } + else + { + // New connection id is required since nothing matched found... + ConnectionId newId(GenerateUuid()); + connections[newId].groupId = id; + connections[newId].importDate = system_clock::to_time_t(system_clock::now()); + connections[newId].displayName = _alias; + LOG(MODULE_CORE_HANDLER, "Generated new connectionId.") + UpdateConnection(newId, config); + } + // End guessing connectionId + } + + // Check if anything left behind (not being updated or changed significantly) + LOG(MODULE_CORE_HANDLER, "Removed old connections not have been matched.") + for (auto conn : connectionsOrig) + { + LOG(MODULE_CORE_HANDLER, "Removing: " + conn.toString()) + DeleteConnection(conn); + } + + return hasErrorOccured; + } + +} // namespace Qv2ray::core::handlers diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 263ed509..030c03e8 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -1,134 +1,136 @@ #pragma once #include "base/Qv2rayBase.hpp" +#include "common/HTTPRequestHelper.hpp" +#include "core/CoreSafeTypes.hpp" +#include "core/CoreUtils.hpp" +#include "core/connection/ConnectionIO.hpp" #include "core/kernel/KernelInteractions.hpp" #include "core/tcping/QvTCPing.hpp" -#include "core/CoreSafeTypes.hpp" -#include "core/connection/ConnectionIO.hpp" -#include "core/CoreUtils.hpp" -#include "common/HTTPRequestHelper.hpp" namespace Qv2ray::core::handlers { class QvConnectionHandler : public QObject { - Q_OBJECT - public: - explicit QvConnectionHandler(); - ~QvConnectionHandler(); - // - const QList Connections() const; - // - const QList AllGroups() const; - const QList Subscriptions() const; - const QList Connections(const GroupId &groupId) const; - // - // Generic Get Options - const QString GetDisplayName(const GroupId &id, int limit = -1) const; - const QString GetDisplayName(const ConnectionId &id, int limit = -1) const; - const GroupId GetGroupIdByDisplayName(const QString &displayName) const; - const ConnectionId GetConnectionIdByDisplayName(const QString &displayName) const; - // - // Connectivity Operationss - bool IsConnected(const ConnectionId &id) const; - const optional StartConnection(const ConnectionId &identifier); - void StopConnection(); //const ConnectionId &id - // - // Connection Operations. - const GroupId GetConnectionGroupId(const ConnectionId &id) const; - double GetConnectionLatency(const ConnectionId &id) const; - const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); - const optional DeleteConnection(const ConnectionId &id); - bool UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); - const optional RenameConnection(const ConnectionId &id, const QString &newName); - const ConnectionId DuplicateConnection(const ConnectionId &id); - const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); - // - const CONFIGROOT GetConnectionRoot(const ConnectionId &id) const; - const CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id) const; - // - // Get Conncetion Property - const QString GetConnectionProtocolString(const ConnectionId &id) const; - const tuple GetConnectionInfo(const ConnectionId &connectionId) const; - const tuple GetConnectionUsageAmount(const ConnectionId &id) const; - // - // Misc Connection Operations - void StartLatencyTest(); - void StartLatencyTest(const GroupId &id); - void StartLatencyTest(const ConnectionId &id); - // - // Group Operations - const optional DeleteGroup(const GroupId &id); - const optional DuplicateGroup(const GroupId &id); - const GroupId &CreateGroup(const QString displayName, bool isSubscription); - const optional RenameGroup(const GroupId &id, const QString &newName); - // - // Subscriptions - const optional UpdateSubscription(const GroupId &id, bool useSystemProxy); - const optional UpdateSubscriptionASync(const GroupId &id, bool useSystemProxy); - const tuple GetSubscriptionData(const GroupId &id); + Q_OBJECT + public: + explicit QvConnectionHandler(); + ~QvConnectionHandler(); + // + const QList Connections() const; + // + const QList AllGroups() const; + const QList Subscriptions() const; + const QList Connections(const GroupId &groupId) const; + // + // Generic Get Options + const QString GetDisplayName(const GroupId &id, int limit = -1) const; + const QString GetDisplayName(const ConnectionId &id, int limit = -1) const; + const GroupId GetGroupIdByDisplayName(const QString &displayName) const; + const ConnectionId GetConnectionIdByDisplayName(const QString &displayName) const; + // + // Connectivity Operationss + bool IsConnected(const ConnectionId &id) const; + const optional StartConnection(const ConnectionId &identifier); + void StopConnection(); // const ConnectionId &id + // + // Connection Operations. + const GroupId GetConnectionGroupId(const ConnectionId &id) const; + double GetConnectionLatency(const ConnectionId &id) const; + const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); + const optional DeleteConnection(const ConnectionId &id); + bool UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); + const optional RenameConnection(const ConnectionId &id, const QString &newName); + const ConnectionId DuplicateConnection(const ConnectionId &id); + const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); + // + const CONFIGROOT GetConnectionRoot(const ConnectionId &id) const; + const CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id) const; + // + // Get Conncetion Property + const QString GetConnectionProtocolString(const ConnectionId &id) const; + const tuple GetConnectionData(const ConnectionId &connectionId) const; + const tuple GetConnectionUsageAmount(const ConnectionId &id) const; + // + // Misc Connection Operations + void StartLatencyTest(); + void StartLatencyTest(const GroupId &id); + void StartLatencyTest(const ConnectionId &id); + // + // Group Operations + const optional DeleteGroup(const GroupId &id); + const optional DuplicateGroup(const GroupId &id); + const GroupId &CreateGroup(const QString displayName, bool isSubscription); + const optional RenameGroup(const GroupId &id, const QString &newName); + // + // Subscriptions + bool UpdateSubscription(const GroupId &id, bool useSystemProxy); + bool UpdateSubscriptionASync(const GroupId &id, bool useSystemProxy); + const tuple GetSubscriptionData(const GroupId &id); - signals: - void OnCrashed(); - void OnConnected(const ConnectionId &id); - void OnDisConnected(const ConnectionId &id); - void OnVCoreLogAvailable(const ConnectionId &id, const QString &log); - void OnStatsAvailable(const ConnectionId &id, - const quint64 uploadSpeed, const quint64 downloadSpeed, - const quint64 totalUpload, const quint64 totalDownload); - // - void OnConnectionCreated(const ConnectionId &id, const QString &displayName); - void OnConnectionRenamed(const ConnectionId &id, const QString &originalName, const QString &newName); - void OnConnectionChanged(const ConnectionId &id); - void OnConnectionGroupChanged(const ConnectionId &id, const QString &originalGroup, const QString &newGroup); - // - void OnLatencyTestStarted(const ConnectionId &id); - void OnLatencyTestFinished(const ConnectionId &id, const uint average); - // - void OnGroupCreated(const GroupId &id, const QString &displayName); - void OnGroupRenamed(const GroupId &id, const QString &oldName, const QString &newName); - void OnGroupDeleted(const GroupId &id, const QString &displayName); - // - //void OnSubscriptionCreated(const GroupId &id, const QString &displayName, const QString &address); - //void OnSubscriptionDeleted(const GroupId &id, const QString &oldName, const QString &newName); - void OnSubscriptionUpdateFinished(const GroupId &id); + signals: + void OnCrashed(); + void OnConnected(const ConnectionId &id); + void OnDisConnected(const ConnectionId &id); + void OnVCoreLogAvailable(const ConnectionId &id, const QString &log); + void OnStatsAvailable(const ConnectionId &id, const quint64 uploadSpeed, const quint64 downloadSpeed, const quint64 totalUpload, + const quint64 totalDownload); + // + void OnConnectionCreated(const ConnectionId &id, const QString &displayName); + void OnConnectionRenamed(const ConnectionId &id, const QString &originalName, const QString &newName); + void OnConnectionChanged(const ConnectionId &id); + void OnConnectionGroupChanged(const ConnectionId &id, const QString &originalGroup, const QString &newGroup); + // + void OnLatencyTestStarted(const ConnectionId &id); + void OnLatencyTestFinished(const ConnectionId &id, const uint average); + // + void OnGroupCreated(const GroupId &id, const QString &displayName); + void OnGroupRenamed(const GroupId &id, const QString &oldName, const QString &newName); + void OnGroupDeleted(const GroupId &id, const QString &displayName); + // + // void OnSubscriptionCreated(const GroupId &id, const QString &displayName, const QString &address); + // void OnSubscriptionDeleted(const GroupId &id, const QString &oldName, const QString &newName); + void OnSubscriptionUpdateFinished(const GroupId &id); - private slots: - void OnStatsDataArrived(const ConnectionId &id, const quint64 uploadSpeed, const quint64 downloadSpeed); - void OnVCoreCrashed(const ConnectionId &id); - void OnLatencyDataArrived(const QvTCPingResultObject &data); + private slots: + void OnStatsDataArrived(const ConnectionId &id, const quint64 uploadSpeed, const quint64 downloadSpeed); + void OnVCoreCrashed(const ConnectionId &id); + void OnLatencyDataArrived(const QvTCPingResultObject &data); - protected: - void timerEvent(QTimerEvent *event) override; + protected: + void timerEvent(QTimerEvent *event) override; - private: - void CHSaveConnectionData_p(); - // - optional CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); - void CHStopConnection_p(); - bool CHSaveConnectionConfig_p(CONFIGROOT obj, const ConnectionId &id, bool override); + private: + void CHSaveConfigData_p(); + // + optional CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); + void CHStopConnection_p(); + bool CHUpdateSubscription_p(const GroupId &id, const QByteArray &subscriptionData); + // bool CHSaveConnectionConfig_p(CONFIGROOT obj, const ConnectionId &id, bool override); + const tuple CHGetOutboundData_p(const CONFIGROOT &obj, bool *succeed) const; - private: - int saveTimerId; - int pingAllTimerId; - int pingConnectionTimerId; - QHash groups; - QHash connections; - //QHash connectionRootCache; + private: + int saveTimerId; + int pingAllTimerId; + int pingConnectionTimerId; + QHash groups; + QHash connections; + // QHash connectionRootCache; - private: - QvHttpRequestHelper *httpHelper; - QvTCPingHelper *tcpingHelper; - // We only support one cuncurrent connection currently. + private: + QvHttpRequestHelper *httpHelper; + bool isHttpRequestInProgress = false; + QvTCPingHelper *tcpingHelper; + // We only support one cuncurrent connection currently. #ifdef QV2RAY_MULTIPlE_ONNECTION - QHash kernelInstances; + QHash kernelInstances; #else - ConnectionId currentConnectionId = NullConnectionId; - V2rayKernelInstance *vCoreInstance = nullptr; + ConnectionId currentConnectionId = NullConnectionId; + V2rayKernelInstance *vCoreInstance = nullptr; #endif }; inline ::Qv2ray::core::handlers::QvConnectionHandler *ConnectionManager = nullptr; -} +} // namespace Qv2ray::core::handlers using namespace Qv2ray::core::handlers; diff --git a/src/core/handler/V2rayInstanceHandler.cpp b/src/core/handler/V2rayInstanceHandler.cpp index 183ecfb7..500f15cf 100644 --- a/src/core/handler/V2rayInstanceHandler.cpp +++ b/src/core/handler/V2rayInstanceHandler.cpp @@ -8,7 +8,8 @@ optional QvConnectionHandler::CHStartConnection_p(const ConnectionId &i auto fullConfig = GenerateRuntimeConfig(root); auto result = vCoreInstance->StartConnection(id, fullConfig); - if (!result.has_value()) { + if (!result.has_value()) + { currentConnectionId = id; emit OnConnected(currentConnectionId); } @@ -18,13 +19,16 @@ optional QvConnectionHandler::CHStartConnection_p(const ConnectionId &i void QvConnectionHandler::CHStopConnection_p() { - if (vCoreInstance->KernelStarted) { + if (vCoreInstance->KernelStarted) + { vCoreInstance->StopConnection(); // Copy ConnectionId id = currentConnectionId; currentConnectionId = NullConnectionId; emit OnDisConnected(id); - } else { + } + else + { LOG(MODULE_CORE_HANDLER, "VCore is not started, not disconnecting") } } diff --git a/src/core/kernel/APIBackend.cpp b/src/core/kernel/APIBackend.cpp index bd40f437..99d12cf6 100644 --- a/src/core/kernel/APIBackend.cpp +++ b/src/core/kernel/APIBackend.cpp @@ -6,7 +6,7 @@ using grpc::Channel; using grpc::ClientContext; using grpc::Status; #else -#include "libs/libqvb/build/libqvb.h" + #include "libs/libqvb/build/libqvb.h" #endif namespace Qv2ray::core::kernel @@ -22,9 +22,7 @@ namespace Qv2ray::core::kernel DEBUG(MODULE_VCORE, "API Worker initialised.") connect(this, SIGNAL(error(QString)), this, SLOT(errorString(QString))); connect(thread, SIGNAL(started()), this, SLOT(process())); - connect(thread, &QThread::finished, []() { - LOG(MODULE_VCORE, "API thread stopped") - }); + connect(thread, &QThread::finished, []() { LOG(MODULE_VCORE, "API thread stopped") }); started = true; thread->start(); DEBUG(MODULE_VCORE, "API Worker started.") @@ -52,21 +50,22 @@ namespace Qv2ray::core::kernel thread->wait(); // Although thread shouldnot be null, we'll add this check to be safe. - if (thread) { - delete thread; - } + if (thread) { delete thread; } } // API Core Operations // Start processing data. void APIWorker::process() { - while (started) { + while (started) + { QThread::msleep(1000); bool dialed = false; - while (running) { - if (!dialed) { + while (running) + { + if (!dialed) + { auto channelAddress = "127.0.0.1:" + QString::number(GlobalConfig.apiConfig.statsPort); #ifdef WITH_LIB_GRPCPP Channel = grpc::CreateChannel(channelAddress.toStdString(), grpc::InsecureChannelCredentials()); @@ -85,36 +84,44 @@ namespace Qv2ray::core::kernel qint64 value_up = 0; qint64 value_down = 0; - for (auto tag : inboundTags) { + for (auto tag : inboundTags) + { value_up += CallStatsAPIByName("inbound>>>" + tag + ">>>traffic>>>uplink"); value_down += CallStatsAPIByName("inbound>>>" + tag + ">>>traffic>>>downlink"); } - if (value_up < 0 || value_down < 0) { + if (value_up < 0 || value_down < 0) + { dialed = false; break; } - if (running) { + if (running) + { apiFailedCounter = 0; emit OnDataReady(value_up, value_down); } #else - for (auto tag : inboundTags) { + for (auto tag : inboundTags) + { auto valup = CallStatsAPIByName("inbound>>>" + tag + ">>>traffic>>>uplink"); auto valdown = CallStatsAPIByName("inbound>>>" + tag + ">>>traffic>>>downlink"); - if (valup < 0 || valdown < 0) { + if (valup < 0 || valdown < 0) + { dialed = false; break; } - if (running) { + if (running) + { apiFailedCounter = 0; emit OnDataReady(tag, valup, valdown); - } else { + } + else + { // If the connection has stopped, just quit. break; } @@ -123,19 +130,22 @@ namespace Qv2ray::core::kernel #endif QThread::msleep(1000); } // end while running - } // end while started + } // end while started thread->exit(); } qint64 APIWorker::CallStatsAPIByName(const QString &name) { - if (apiFailedCounter == QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD) { + if (apiFailedCounter == QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD) + { LOG(MODULE_VCORE, "API call failure threshold reached, cancelling further API aclls.") emit error("Failed to get statistics data, please check if V2ray is running properly"); apiFailedCounter++; return 0; - } else if (apiFailedCounter > QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD) { + } + else if (apiFailedCounter > QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD) + { return 0; } @@ -147,7 +157,8 @@ namespace Qv2ray::core::kernel ClientContext context; Status status = Stub->GetStats(&context, request, &response); - if (!status.ok()) { + if (!status.ok()) + { LOG(MODULE_VCORE, "API call returns: " + QSTRN(status.error_code()) + " (" + QString::fromStdString(status.error_message()) + ")") apiFailedCounter++; } @@ -157,7 +168,8 @@ namespace Qv2ray::core::kernel qint64 data = GetStats(const_cast(name.toStdString().c_str()), 1000); #endif - if (data < 0) { + if (data < 0) + { LOG(MODULE_VCORE, "API call returns: " + QSTRN(data)) apiFailedCounter++; return 0; @@ -165,4 +177,4 @@ namespace Qv2ray::core::kernel return data; } -} +} // namespace Qv2ray::core::kernel diff --git a/src/core/kernel/APIBackend.hpp b/src/core/kernel/APIBackend.hpp index a6147fc6..03e35c9d 100644 --- a/src/core/kernel/APIBackend.hpp +++ b/src/core/kernel/APIBackend.hpp @@ -1,9 +1,10 @@ #pragma once #include "base/Qv2rayBase.hpp" #ifdef WITH_LIB_GRPCPP -#include -#include "libs/gen/v2ray_api.pb.h" -#include "libs/gen/v2ray_api.grpc.pb.h" + #include "libs/gen/v2ray_api.grpc.pb.h" + #include "libs/gen/v2ray_api.pb.h" + + #include #endif // Check 10 times before telling user that API has failed. @@ -13,34 +14,34 @@ namespace Qv2ray::core::kernel { class APIWorker : public QObject { - Q_OBJECT + Q_OBJECT - public: - APIWorker(); - ~APIWorker(); - void StartAPI(const QStringList &tags); - void StopAPI(); + public: + APIWorker(); + ~APIWorker(); + void StartAPI(const QStringList &tags); + void StopAPI(); - public slots: - void process(); + public slots: + void process(); - signals: - void OnDataReady(const quint64 _totalUp, const quint64 _totalDown); - void error(const QString &err); + signals: + void OnDataReady(const quint64 _totalUp, const quint64 _totalDown); + void error(const QString &err); - private: - qint64 CallStatsAPIByName(const QString &name); - QStringList inboundTags; - QThread *thread; - // - bool started = false; - bool running = false; - uint apiFailedCounter = 0; + private: + qint64 CallStatsAPIByName(const QString &name); + QStringList inboundTags; + QThread *thread; + // + bool started = false; + bool running = false; + uint apiFailedCounter = 0; #ifdef WITH_LIB_GRPCPP - std::shared_ptr<::grpc::Channel> Channel; - std::unique_ptr<::v2ray::core::app::stats::command::StatsService::Stub> Stub; + std::shared_ptr<::grpc::Channel> Channel; + std::unique_ptr<::v2ray::core::app::stats::command::StatsService::Stub> Stub; #endif }; -} +} // namespace Qv2ray::core::kernel using namespace Qv2ray::core::kernel; diff --git a/src/core/kernel/KernelInteractions.cpp b/src/core/kernel/KernelInteractions.cpp index ee08ce02..3fd0ed72 100644 --- a/src/core/kernel/KernelInteractions.cpp +++ b/src/core/kernel/KernelInteractions.cpp @@ -1,10 +1,12 @@ +#include "KernelInteractions.hpp" + +#include "APIBackend.hpp" +#include "common/QvHelpers.hpp" +#include "core/connection/ConnectionIO.hpp" + +#include #include #include -#include -#include "common/QvHelpers.hpp" -#include "KernelInteractions.hpp" -#include "core/connection/ConnectionIO.hpp" -#include "APIBackend.hpp" namespace Qv2ray::core::kernel { @@ -12,14 +14,17 @@ namespace Qv2ray::core::kernel { QFile coreFile(vCorePath); - if (!coreFile.exists()) { + if (!coreFile.exists()) + { DEBUG(MODULE_VCORE, "V2ray core file cannot be found.") *message = tr("V2ray core executable not found."); return false; } - // Use open() here to prevent `executing` a folder, which may have the same name as the V2ray core. - if (!coreFile.open(QFile::ReadOnly)) { + // Use open() here to prevent `executing` a folder, which may have the + // same name as the V2ray core. + if (!coreFile.open(QFile::ReadOnly)) + { DEBUG(MODULE_VCORE, "V2ray core file cannot be opened, possibly be a folder?") *message = tr("V2ray core file cannot be opened, please ensure there's a file instead of a folder."); return false; @@ -33,28 +38,32 @@ namespace Qv2ray::core::kernel bool hasGeoIP = FileExistsIn(QDir(vAssetsPath), "geoip.dat"); bool hasGeoSite = FileExistsIn(QDir(vAssetsPath), "geosite.dat"); - if (!hasGeoIP && !hasGeoSite) { + if (!hasGeoIP && !hasGeoSite) + { DEBUG(MODULE_VCORE, "V2ray assets path contains none of those two files.") *message = tr("V2ray assets path is not valid."); return false; } - if (!hasGeoIP) { + if (!hasGeoIP) + { DEBUG(MODULE_VCORE, "No geoip.dat in assets path, aborting.") - *message = tr("No geoip.dat in assets path."); + *message = tr("No geoip.dat in assets path."); return false; } - if (!hasGeoSite) { + if (!hasGeoSite) + { DEBUG(MODULE_VCORE, "No geosite.dat in assets path, aborting.") - *message = tr("No geosite.dat in assets path."); + *message = tr("No geosite.dat in assets path."); return false; } // Check if V2ray core returns a version number correctly. QProcess proc; #ifdef Q_OS_WIN32 - // nativeArguments are required for Windows platform, without a reason... + // nativeArguments are required for Windows platform, without a + // reason... proc.setProcessChannelMode(QProcess::MergedChannels); proc.setProgram(vCorePath); proc.setNativeArguments("--version"); @@ -66,7 +75,8 @@ namespace Qv2ray::core::kernel proc.waitForFinished(); auto exitCode = proc.exitCode(); - if (exitCode != 0) { + if (exitCode != 0) + { DEBUG(MODULE_VCORE, "VCore failed with an exit code: " + QSTRN(exitCode)) *message = tr("V2ray core failed with an exit code: ") + QSTRN(exitCode); return false; @@ -75,7 +85,8 @@ namespace Qv2ray::core::kernel QString output = proc.readAllStandardOutput(); LOG(MODULE_VCORE, "V2ray output: " + SplitLines(output).join(";")) - if (SplitLines(output).isEmpty()) { + if (SplitLines(output).isEmpty()) + { *message = tr("V2ray core returns empty string."); return false; } @@ -84,12 +95,12 @@ namespace Qv2ray::core::kernel return true; } - bool V2rayKernelInstance::ValidateConfig(const QString &path) { QString v2rayCheckResult; - if (ValidateKernel(GlobalConfig.v2CorePath, GlobalConfig.v2AssetsPath, &v2rayCheckResult)) { + if (ValidateKernel(GlobalConfig.v2CorePath, GlobalConfig.v2AssetsPath, &v2rayCheckResult)) + { DEBUG(MODULE_VCORE, "V2ray version: " + v2rayCheckResult) // Append assets location env. QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); @@ -98,21 +109,28 @@ namespace Qv2ray::core::kernel QProcess process; process.setProcessEnvironment(env); DEBUG(MODULE_VCORE, "Starting V2ray core with test options") - process.start(GlobalConfig.v2CorePath, QStringList() << "-test" << "-config" << path, QIODevice::ReadWrite | QIODevice::Text); + process.start(GlobalConfig.v2CorePath, + QStringList() << "-test" + << "-config" << path, + QIODevice::ReadWrite | QIODevice::Text); process.waitForFinished(); - if (process.exitCode() != 0) { + if (process.exitCode() != 0) + { QString output = QString(process.readAllStandardOutput()); QvMessageBoxWarn(nullptr, tr("Configuration Error"), output.mid(output.indexOf("anti-censorship.") + 17)); return false; - } else { + } + else + { DEBUG(MODULE_VCORE, "Config file check passed.") return true; } - } else { + } + else + { QvMessageBoxWarn(nullptr, tr("Cannot start V2ray"), - tr("V2ray core settings is incorrect.") + NEWLINE + NEWLINE + - tr("The error is: ") + NEWLINE + v2rayCheckResult); + tr("V2ray core settings is incorrect.") + NEWLINE + NEWLINE + tr("The error is: ") + NEWLINE + v2rayCheckResult); return false; } } @@ -120,14 +138,14 @@ namespace Qv2ray::core::kernel V2rayKernelInstance::V2rayKernelInstance() { vProcess = new QProcess(); - connect(vProcess, &QProcess::readyReadStandardOutput, this, [&]() { - emit OnProcessOutputReadyRead(id, vProcess->readAllStandardOutput().trimmed()); - }); + connect(vProcess, &QProcess::readyReadStandardOutput, this, + [&]() { emit OnProcessOutputReadyRead(id, vProcess->readAllStandardOutput().trimmed()); }); connect(vProcess, &QProcess::stateChanged, [&](QProcess::ProcessState state) { DEBUG(MODULE_VCORE, "V2ray kernel process status changed: " + QVariant::fromValue(state).toString()) // If V2ray crashed AFTER we start it. - if (KernelStarted && state == QProcess::NotRunning) { + if (KernelStarted && state == QProcess::NotRunning) + { LOG(MODULE_VCORE, "V2ray kernel crashed.") StopConnection(); emit OnProcessErrored(id); @@ -140,7 +158,8 @@ namespace Qv2ray::core::kernel optional V2rayKernelInstance::StartConnection(const ConnectionId &id, const CONFIGROOT &root) { - if (KernelStarted) { + if (KernelStarted) + { LOG(MODULE_VCORE, "Status is invalid, expect STOPPED when calling StartConnection") return tr("Invalid V2ray Instance Status."); } @@ -151,7 +170,8 @@ namespace Qv2ray::core::kernel // auto filePath = QV2RAY_GENERATED_FILE_PATH; - if (ValidateConfig(filePath)) { + if (ValidateConfig(filePath)) + { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert("V2RAY_LOCATION_ASSET", GlobalConfig.v2AssetsPath); vProcess->setProcessEnvironment(env); @@ -163,10 +183,12 @@ namespace Qv2ray::core::kernel this->id = id; QStringList inboundTags; - for (auto item : root["inbounds"].toArray()) { + for (auto item : root["inbounds"].toArray()) + { auto tag = item.toObject()["tag"].toString(""); - if (tag.isEmpty() || tag == API_TAG_INBOUND) { + if (tag.isEmpty() || tag == API_TAG_INBOUND) + { // Ignore API tag and empty tags. continue; } @@ -178,20 +200,26 @@ namespace Qv2ray::core::kernel apiEnabled = false; // - if (StartupOption.noAPI) { - LOG(MODULE_VCORE, "API has been disabled by the command line argument \"-noAPI\"") - } else if (!GlobalConfig.apiConfig.enableAPI) { + if (StartupOption.noAPI) { LOG(MODULE_VCORE, "API has been disabled by the command line argument \"-noAPI\"") } + else if (!GlobalConfig.apiConfig.enableAPI) + { LOG(MODULE_VCORE, "API has been disabled by the global config option") - } else if (inboundTags.isEmpty()) { + } + else if (inboundTags.isEmpty()) + { LOG(MODULE_VCORE, "API is disabled since no inbound tags configured. This is probably caused by a bad complex config.") - } else { + } + else + { apiWorker->StartAPI(inboundTags); apiEnabled = true; DEBUG(MODULE_VCORE, "Qv2ray API started") } - return { }; - } else { + return {}; + } + else + { KernelStarted = false; return tr("V2ray kernel failed to start."); } @@ -199,12 +227,14 @@ namespace Qv2ray::core::kernel void V2rayKernelInstance::StopConnection() { - if (apiEnabled) { + if (apiEnabled) + { apiWorker->StopAPI(); apiEnabled = false; } - // Set this to false BEFORE close the Process, since we need this flag to capture the real kernel CRASH + // Set this to false BEFORE close the Process, since we need this flag + // to capture the real kernel CRASH KernelStarted = false; vProcess->close(); // Block until V2ray core exits @@ -214,9 +244,7 @@ namespace Qv2ray::core::kernel V2rayKernelInstance::~V2rayKernelInstance() { - if (KernelStarted) { - StopConnection(); - } + if (KernelStarted) { StopConnection(); } delete apiWorker; delete vProcess; @@ -226,4 +254,4 @@ namespace Qv2ray::core::kernel { emit OnNewStatsDataArrived(id, _totalUp, _totalDown); } -} +} // namespace Qv2ray::core::kernel diff --git a/src/core/kernel/KernelInteractions.hpp b/src/core/kernel/KernelInteractions.hpp index dc291a61..13f8187d 100644 --- a/src/core/kernel/KernelInteractions.hpp +++ b/src/core/kernel/KernelInteractions.hpp @@ -1,46 +1,47 @@ #pragma once -#include #include "base/Qv2rayBase.hpp" #include "core/CoreSafeTypes.hpp" +#include + namespace Qv2ray::core::kernel { class APIWorker; class V2rayKernelInstance : public QObject { - Q_OBJECT - public: - explicit V2rayKernelInstance(); - ~V2rayKernelInstance() override; - // - // Speed - qulonglong getTagSpeedUp(const QString &tag); - qulonglong getTagSpeedDown(const QString &tag); - qulonglong getAllSpeedUp(); - qulonglong getAllSpeedDown(); - // - optional StartConnection(const ConnectionId &id, const CONFIGROOT &root); - void StopConnection(); - bool KernelStarted = false; - // - static bool ValidateConfig(const QString &path); - static bool ValidateKernel(const QString &vCorePath, const QString &vAssetsPath, QString *message); + Q_OBJECT + public: + explicit V2rayKernelInstance(); + ~V2rayKernelInstance() override; + // + // Speed + qulonglong getTagSpeedUp(const QString &tag); + qulonglong getTagSpeedDown(const QString &tag); + qulonglong getAllSpeedUp(); + qulonglong getAllSpeedDown(); + // + optional StartConnection(const ConnectionId &id, const CONFIGROOT &root); + void StopConnection(); + bool KernelStarted = false; + // + static bool ValidateConfig(const QString &path); + static bool ValidateKernel(const QString &vCorePath, const QString &vAssetsPath, QString *message); - signals: - void OnProcessErrored(const ConnectionId &id); - void OnProcessOutputReadyRead(const ConnectionId &id, const QString &output); - void OnNewStatsDataArrived(const ConnectionId &id, const quint64 _totalUp, const quint64 _totalDown); + signals: + void OnProcessErrored(const ConnectionId &id); + void OnProcessOutputReadyRead(const ConnectionId &id, const QString &output); + void OnNewStatsDataArrived(const ConnectionId &id, const quint64 _totalUp, const quint64 _totalDown); - public slots: - void onAPIDataReady(const quint64 _totalUp, const quint64 _totalDown); + public slots: + void onAPIDataReady(const quint64 _totalUp, const quint64 _totalDown); - private: - APIWorker *apiWorker; - QProcess *vProcess; - bool apiEnabled; - // - ConnectionId id = NullConnectionId; + private: + APIWorker *apiWorker; + QProcess *vProcess; + bool apiEnabled; + // + ConnectionId id = NullConnectionId; }; -} +} // namespace Qv2ray::core::kernel using namespace Qv2ray::core::kernel; diff --git a/src/core/tcping/QvTCPing.cpp b/src/core/tcping/QvTCPing.cpp index d6cc9642..60c885a9 100644 --- a/src/core/tcping/QvTCPing.cpp +++ b/src/core/tcping/QvTCPing.cpp @@ -1,15 +1,15 @@ #ifdef _WIN32 -#include -#include + #include + #include #else -#include -#include -#include -#include + #include + #include + #include + #include #endif +#include "QtConcurrent/QtConcurrent" #include "QvTCPing.hpp" #include "core/handler/ConnectionHandler.hpp" -#include "QtConcurrent/QtConcurrent" namespace Qv2ray::core::tcping { @@ -23,7 +23,8 @@ namespace Qv2ray::core::tcping void QvTCPingHelper::StopAllLatenceTest() { - while (!pingWorkingThreads.isEmpty()) { + while (!pingWorkingThreads.isEmpty()) + { auto worker = pingWorkingThreads.dequeue(); worker->future().cancel(); worker->cancel(); @@ -35,13 +36,11 @@ namespace Qv2ray::core::tcping watcher->setFuture(QtConcurrent::run(&QvTCPingHelper::TestLatency_p, id, count)); pingWorkingThreads.enqueue(watcher); // - connect(watcher, &QFutureWatcher::finished, this, [ = ]() { + connect(watcher, &QFutureWatcher::finished, this, [=]() { auto result = watcher->result(); this->pingWorkingThreads.removeOne(watcher); - if (!result.errorMessage.isEmpty()) { - LOG(MODULE_NETWORK, "Ping --> " + result.errorMessage) - } + if (!result.errorMessage.isEmpty()) { LOG(MODULE_NETWORK, "Ping --> " + result.errorMessage) } emit this->OnLatencyTestCompleted(result); }); @@ -54,12 +53,14 @@ namespace Qv2ray::core::tcping if (isExiting) return data; - auto [host, port] = ConnectionManager->GetConnectionInfo(id); + auto [protocol, host, port] = ConnectionManager->GetConnectionData(id); + Q_UNUSED(protocol) double successCount = 0, errorCount = 0; addrinfo *resolved; int errcode; - if ((errcode = resolveHost(host.toStdString(), port, &resolved)) != 0) { + if ((errcode = resolveHost(host.toStdString(), port, &resolved)) != 0) + { #ifdef _WIN32 data.errorMessage = QString::fromStdWString(gai_strerror(errcode)); #else @@ -71,26 +72,35 @@ namespace Qv2ray::core::tcping bool noAddress = false; int currentCount = 0; - while (currentCount < count) { + while (currentCount < count) + { if (isExiting) return QvTCPingResultObject(); system_clock::time_point start; system_clock::time_point end; - if ((errcode = testLatency(resolved, &start, &end)) != 0) { - if (errcode != -EADDRNOTAVAIL) { - //LOG(MODULE_NETWORK, "Error connecting to host: " + data.hostName + ":" + QSTRN(data.port) + " " + strerror(-errcode)) + if ((errcode = testLatency(resolved, &start, &end)) != 0) + { + if (errcode != -EADDRNOTAVAIL) + { + // LOG(MODULE_NETWORK, "Error connecting to host: " + + // data.hostName + ":" + QSTRN(data.port) + " " + + // strerror(-errcode)) errorCount++; - } else { - if (noAddress) { - LOG(MODULE_NETWORK, ".") - } else { + } + else + { + if (noAddress) { LOG(MODULE_NETWORK, ".") } + else + { LOG(MODULE_NETWORK, "error connecting to host: " + QSTRN(-errcode) + " " + strerror(-errcode)) } noAddress = true; } - } else { + } + else + { noAddress = false; successCount++; auto milliseconds = std::chrono::duration_cast(end - start); @@ -99,7 +109,8 @@ namespace Qv2ray::core::tcping data.worst = min(data.worst, ms); data.best = max(data.best, ms); - if (ms > 1000) { + if (ms > 1000) + { LOG(MODULE_NETWORK, "Stop the test on the first long connect()") break; /* Stop the test on the first long connect() */ } @@ -146,20 +157,19 @@ namespace Qv2ray::core::tcping int rv = 0; /* try to connect for each of the entries: */ - while (addr != nullptr) { + while (addr != nullptr) + { if (isExiting) return 0; /* create socket */ fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); - if (!fd) { - goto next_addr0; - } + if (!fd) { goto next_addr0; } #ifdef _WIN32 // Windows needs special conversion. - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on)) < 0) + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on)) < 0) #else if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) #endif @@ -172,7 +182,8 @@ namespace Qv2ray::core::tcping /* connect to peer */ // Qt has its own connect() function in QObject.... // So we add "::" here - if (::connect(fd, addr->ai_addr, addr->ai_addrlen) == 0) { + if (::connect(fd, addr->ai_addr, addr->ai_addrlen) == 0) + { *end = system_clock::now(); #ifdef _WIN32 closesocket(fd); @@ -182,17 +193,17 @@ namespace Qv2ray::core::tcping return 0; } -next_addr1: + next_addr1: #ifdef _WIN32 closesocket(fd); #else close(fd); #endif -next_addr0: + next_addr0: addr = addr->ai_next; } rv = rv ? rv : -errno; return rv; } -} +} // namespace Qv2ray::core::tcping diff --git a/src/core/tcping/QvTCPing.hpp b/src/core/tcping/QvTCPing.hpp index 3e69ea20..1153ba61 100644 --- a/src/core/tcping/QvTCPing.hpp +++ b/src/core/tcping/QvTCPing.hpp @@ -4,7 +4,8 @@ namespace Qv2ray::core::tcping { - struct QvTCPingResultObject { + struct QvTCPingResultObject + { ConnectionId connectionId = NullConnectionId; QString errorMessage; int total, succeed, failed; @@ -13,19 +14,20 @@ namespace Qv2ray::core::tcping class QvTCPingHelper : public QObject { - Q_OBJECT + Q_OBJECT - public: - explicit QvTCPingHelper(const int defaultCount = 5, QObject *parent = nullptr); - void TestLatency(const ConnectionId &connectionId); - void StopAllLatenceTest(); - signals: - void OnLatencyTestCompleted(const QvTCPingResultObject &data); - private: - static QvTCPingResultObject TestLatency_p(const ConnectionId &id, const int count); - int count; - QQueue*> pingWorkingThreads; + public: + explicit QvTCPingHelper(const int defaultCount = 5, QObject *parent = nullptr); + void TestLatency(const ConnectionId &connectionId); + void StopAllLatenceTest(); + signals: + void OnLatencyTestCompleted(const QvTCPingResultObject &data); + + private: + static QvTCPingResultObject TestLatency_p(const ConnectionId &id, const int count); + int count; + QQueue *> pingWorkingThreads; }; -} +} // namespace Qv2ray::core::tcping using namespace Qv2ray::core::tcping; diff --git a/src/main.cpp b/src/main.cpp index 90547e69..9d4c2a11 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,37 +1,36 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ui/w_MainWindow.hpp" - +#include "common/CommandArgs.hpp" +#include "common/QvHelpers.hpp" +#include "common/QvTranslator.hpp" #include "core/config/ConfigBackend.hpp" #include "core/handler/ConnectionHandler.hpp" -#include "common/QvHelpers.hpp" -#include "common/CommandArgs.hpp" -#include "common/QvTranslator.hpp" +#include "ui/w_MainWindow.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef Q_OS_UNIX -// For unix root user check -#include "unistd.h" + // For unix root user check + #include "unistd.h" #endif void signalHandler(int signum) { cout << "Interrupt signal (" << signum << ") received." << endl; - //if (MainWindow::mwInstance && MainWindow::mwInstance->vinstance) { + // if (MainWindow::mwInstance && MainWindow::mwInstance->vinstance) { // cout << "Trying to stop connection..." << endl; // MainWindow::mwInstance->vinstance->StopConnection(); //} qApp->exit(-99); } - bool verifyConfigAvaliability(QString path, bool checkExistingConfig) { // Does not exist. @@ -41,17 +40,21 @@ bool verifyConfigAvaliability(QString path, bool checkExistingConfig) QFile testFile(path + ".qv2ray_file_write_test_file" + QSTRN(QTime::currentTime().msecsSinceStartOfDay())); bool opened = testFile.open(QFile::OpenModeFlag::ReadWrite); - if (!opened) { + if (!opened) + { LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.") LOG(MODULE_INIT, "---> Cannot create a new file or openwrite a file.") return false; - } else { + } + else + { testFile.write("Qv2ray test file, feel free to remove."); testFile.flush(); testFile.close(); bool removed = testFile.remove(); - if (!removed) { + if (!removed) + { // This is rare, as we can create a file but failed to remove it. LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.") LOG(MODULE_INIT, "---> Cannot remove a file.") @@ -59,7 +62,8 @@ bool verifyConfigAvaliability(QString path, bool checkExistingConfig) } } - if (checkExistingConfig) { + if (checkExistingConfig) + { // Check if an existing config is found. QFile configFile(path + "Qv2ray.conf"); @@ -68,37 +72,52 @@ bool verifyConfigAvaliability(QString path, bool checkExistingConfig) bool opened2 = configFile.open(QIODevice::ReadWrite); - try { - if (opened2) { + try + { + if (opened2) + { // Verify if the config can be loaded. // Failed to parse if we changed the file structure... // Original: - // -- auto conf = StructFromJsonString(configFile.readAll()); + // -- auto conf = + // StructFromJsonString(configFile.readAll()); // - // Verify JSON file format. (only) because this file version may not be upgraded and may contain unsupported structure. + // Verify JSON file format. (only) because this file version may + // not be upgraded and may contain unsupported structure. auto err = VerifyJsonString(StringFromFile(&configFile)); - if (!err.isEmpty()) { + if (!err.isEmpty()) + { LOG(MODULE_INIT, "Json parse returns: " + err) return false; - } else { + } + else + { // If the file format is valid. auto conf = JsonFromString(StringFromFile(&configFile)); - LOG(MODULE_SETTINGS, "Path: " + path + " contains a config file, in version " + conf["config_version"].toVariant().toString()) + LOG(MODULE_SETTINGS, + "Path: " + path + " contains a config file, in version " + conf["config_version"].toVariant().toString()) configFile.close(); return true; } - } else { - LOG(MODULE_SETTINGS, "File: " + configFile.fileName() + " cannot be opened!") + } + else + { + LOG(MODULE_SETTINGS, "File: " + configFile.fileName() + " cannot be opened!") return false; } - } catch (...) { + } + catch (...) + { LOG(MODULE_SETTINGS, "Exception raised when checking config: " + configFile.fileName()) - //LOG(INIT, e->what()) - QvMessageBoxWarn(nullptr, QObject::tr("Warning"), QObject::tr("Qv2ray cannot load the config file from here:") + NEWLINE + configFile.fileName()); + // LOG(INIT, e->what()) + QvMessageBoxWarn(nullptr, QObject::tr("Warning"), + QObject::tr("Qv2ray cannot load the config file from here:") + NEWLINE + configFile.fileName()); return false; } - } else return true; + } + else + return true; } bool initialiseQv2ray() @@ -109,12 +128,14 @@ bool initialiseQv2ray() const QString homeQv2ray = QDir::homePath() + "/.qv2ray" QV2RAY_CONFIG_DIR_SUFFIX; // // - // Some built-in search paths for Qv2ray to find configs. (load the first one if possible). + // Some built-in search paths for Qv2ray to find configs. (load the first + // one if possible). // QStringList configFilePaths; configFilePaths << currentPathConfig; #ifdef WITH_FLATHUB_CONFIG_PATH - // AppConfigLocation uses 'Q'v2ray instead of `q`v2ray. Keep here as backward compatibility. + // AppConfigLocation uses 'Q'v2ray instead of `q`v2ray. Keep here as + // backward compatibility. configFilePaths << QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + QV2RAY_CONFIG_DIR_SUFFIX; #endif configFilePaths << configQv2ray; @@ -123,31 +144,40 @@ bool initialiseQv2ray() QString configPath = ""; bool hasExistingConfig = false; - for (auto path : configFilePaths) { - // Verify the config path, check if the config file exists and in the correct JSON format. - // True means we check for config existance as well. --|HERE | + for (auto path : configFilePaths) + { + // Verify the config path, check if the config file exists and in the + // correct JSON format. True means we check for config existance as + // well. --|HERE | bool isValidConfigPath = verifyConfigAvaliability(path, true); // If we already found a valid config file. just simply load it... if (hasExistingConfig) break; - if (isValidConfigPath) { + if (isValidConfigPath) + { DEBUG(MODULE_INIT, "Path: " + path + " is valid.") configPath = path; hasExistingConfig = true; - } else { + } + else + { LOG(MODULE_INIT, "Path: " + path + " does not contain a valid config file.") } } // If there's no existing config. - if (hasExistingConfig) { + if (hasExistingConfig) + { // Use the config path found by the checks above SetConfigDirPath(configPath); LOG(MODULE_INIT, "Using " + QV2RAY_CONFIG_DIR + " as the config path.") - } else { + } + else + { // - // Create new config at these dirs, these are default values for each platform. + // Create new config at these dirs, these are default values for each + // platform. #ifdef Q_OS_WIN configPath = currentPathConfig; #else @@ -156,23 +186,26 @@ bool initialiseQv2ray() bool mkpathResult = QDir().mkpath(configPath); // Check if the dirs are write-able - if (mkpathResult && verifyConfigAvaliability(configPath, false)) { - // Found a valid config dir, with write permission, but assume no config is located in it. + if (mkpathResult && verifyConfigAvaliability(configPath, false)) + { + // Found a valid config dir, with write permission, but assume no + // config is located in it. LOG(MODULE_INIT, "Set " + configPath + " as the config path.") SetConfigDirPath(configPath); - if (QFile::exists(QV2RAY_CONFIG_FILE)) { + if (QFile::exists(QV2RAY_CONFIG_FILE)) + { // As we already tried to load config from every possible dir. - // This condition branch (!hasExistingConfig check) holds the fact that - // current config dir, should NOT contain any valid file (at least in the same name) - // It usually means that QV2RAY_CONFIG_FILE here is corrupted, in JSON format. - // Otherwise Qv2ray would have loaded this config already instead of notifying to - // create a new config in this folder. + // This condition branch (!hasExistingConfig check) holds the + // fact that current config dir, should NOT contain any valid + // file (at least in the same name) It usually means that + // QV2RAY_CONFIG_FILE here is corrupted, in JSON format. + // Otherwise Qv2ray would have loaded this config already + // instead of notifying to create a new config in this folder. LOG(MODULE_INIT, "This should not occur: Qv2ray config exists but failed to load.") QvMessageBoxWarn(nullptr, QObject::tr("Failed to initialise Qv2ray"), QObject::tr("Failed to determine the location of config file.") + NEWLINE + - QObject::tr("Qv2ray will now exit.") + NEWLINE + - QObject::tr("Please report if you think it's a bug.")); + QObject::tr("Qv2ray will now exit.") + NEWLINE + QObject::tr("Please report if you think it's a bug.")); return false; } @@ -184,7 +217,9 @@ bool initialiseQv2ray() // Save initial config. SaveGlobalConfig(conf); LOG(MODULE_INIT, "Created initial config file.") - } else { + } + else + { // None of the path above can be used as a dir for storing config. // Even the last folder failed to pass the check. LOG(MODULE_INIT, "FATAL") @@ -192,14 +227,14 @@ bool initialiseQv2ray() QString searchPath = configFilePaths.join(NEWLINE); QvMessageBoxWarn(nullptr, QObject::tr("Cannot Start Qv2ray"), QObject::tr("Cannot find a place to store config files.") + NEWLINE + - QObject::tr("Qv2ray has searched these paths below:") + - NEWLINE + NEWLINE + searchPath + NEWLINE + - QObject::tr("Qv2ray will now exit.")); + QObject::tr("Qv2ray has searched these paths below:") + NEWLINE + NEWLINE + searchPath + NEWLINE + + QObject::tr("Qv2ray will now exit.")); return false; } } - if (!QDir(QV2RAY_GENERATED_DIR).exists()) { + if (!QDir(QV2RAY_GENERATED_DIR).exists()) + { // The dir used to generate final config file, for V2ray interaction. QDir().mkdir(QV2RAY_GENERATED_DIR); LOG(MODULE_INIT, "Created config generation dir at: " + QV2RAY_GENERATED_DIR) @@ -208,7 +243,6 @@ bool initialiseQv2ray() return true; } - int main(int argc, char *argv[]) { #ifndef Q_OS_WIN @@ -228,9 +262,9 @@ int main(int argc, char *argv[]) QvCommandArgParser parser; QString errorMessage; - switch (parser.ParseCommandLine(&errorMessage)) { - case CommandLineOk: - break; + switch (parser.ParseCommandLine(&errorMessage)) + { + case CommandLineOk: break; case CommandLineError: cout << errorMessage.toStdString() << endl; @@ -243,16 +277,16 @@ int main(int argc, char *argv[]) LOG("QV2RAY_BUILD_EXTRA_INFO", QV2RAY_BUILD_EXTRA_INFO) return 0; - case CommandLineHelpRequested: - cout << parser.Parser()->helpText().toStdString() << endl; - return 0; + case CommandLineHelpRequested: cout << parser.Parser()->helpText().toStdString() << endl; return 0; } } #ifdef Q_OS_UNIX // Unix OS root user check. - // Do not use getuid() here since it's installed as owned by the root, someone may accidently setuid to it. - if (!StartupOption.forceRunAsRootUser && geteuid() == 0) { + // Do not use getuid() here since it's installed as owned by the root, + // someone may accidently setuid to it. + if (!StartupOption.forceRunAsRootUser && geteuid() == 0) + { LOG("ERROR", QObject::tr("You cannot run Qv2ray as root, please use --I-just-wanna-run-with-root if you REALLY want to do so.")) LOG("ERROR", QObject::tr(" --> USE IT AT YOUR OWN RISK!")) return 1; @@ -263,9 +297,11 @@ int main(int argc, char *argv[]) // finished: command line parsing LOG("QV2RAY_BUILD_INFO", QV2RAY_BUILD_INFO) LOG("QV2RAY_BUILD_EXTRA_INFO", QV2RAY_BUILD_EXTRA_INFO) - LOG(MODULE_INIT, "Qv2ray " QV2RAY_VERSION_STRING " running on " + QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture() + NEWLINE) + LOG(MODULE_INIT, + "Qv2ray " QV2RAY_VERSION_STRING " running on " + QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture() + NEWLINE) // - // This line must be called before any other ones, since we are using these values to identify instances. + // This line must be called before any other ones, since we are using these + // values to identify instances. SingleApplication::setApplicationName("Qv2ray"); SingleApplication::setApplicationVersion(QV2RAY_VERSION_STRING); SingleApplication::setApplicationDisplayName("Qv2ray"); @@ -275,7 +311,8 @@ int main(int argc, char *argv[]) // ----------------------------> For debug build... SingleApplication::setApplicationName("Qv2ray - DEBUG"); #endif - SingleApplication _qApp(argc, argv, false, SingleApplication::Mode::User | SingleApplication::Mode::ExcludeAppPath | SingleApplication::Mode::ExcludeAppVersion); + SingleApplication _qApp( + argc, argv, false, SingleApplication::Mode::User | SingleApplication::Mode::ExcludeAppPath | SingleApplication::Mode::ExcludeAppVersion); _qApp.setQuitOnLastWindowClosed(false); // Early initialisation // @@ -288,14 +325,11 @@ int main(int argc, char *argv[]) bool _result_ = _qApp.installTranslator(Qv2rayTranslator.get()); LOG(MODULE_UI, "Installing a tranlator from OS: " + _lang + " -- " + (_result_ ? "OK" : "Failed")) // - LOG("LICENCE", NEWLINE "This program comes with ABSOLUTELY NO WARRANTY." NEWLINE - "This is free software, and you are welcome to redistribute it" NEWLINE - "under certain conditions." NEWLINE NEWLINE - "Copyright (c) 2019-2020 Qv2ray Development Group." NEWLINE - NEWLINE NEWLINE + LOG("LICENCE", NEWLINE + "This program comes with ABSOLUTELY NO WARRANTY." NEWLINE "This is free software, and you are welcome to redistribute it" NEWLINE + "under certain conditions." NEWLINE NEWLINE "Copyright (c) 2019-2020 Qv2ray Development Group." NEWLINE NEWLINE NEWLINE "Libraries that have been used in Qv2ray are listed below (Sorted by date added):" NEWLINE - "Copyright (c) 2020 dridk (@dridk): X2Struct (Apache)" NEWLINE - "Copyright (c) 2011 SCHUTZ Sacha (@dridk): QJsonModel (MIT)" NEWLINE + "Copyright (c) 2020 dridk (@dridk): X2Struct (Apache)" NEWLINE "Copyright (c) 2011 SCHUTZ Sacha (@dridk): QJsonModel (MIT)" NEWLINE "Copyright (c) 2020 Nikolaos Ftylitakis (@ftylitak): QZXing (Apache2)" NEWLINE "Copyright (c) 2016 Singein (@Singein): ScreenShot (MIT)" NEWLINE "Copyright (c) 2016 Nikhil Marathe (@nikhilm): QHttpServer (MIT)" NEWLINE @@ -304,48 +338,50 @@ int main(int argc, char *argv[]) "Copyright (c) 2019 TheWanderingCoel (@TheWanderingCoel): ShadowClash (launchatlogin) (GPLv3)" NEWLINE "Copyright (c) 2020 Ram Pani (@DuckSoft): QvRPCBridge (WTFPL)" NEWLINE "Copyright (c) 2019 ShadowSocks (@shadowsocks): libQtShadowsocks (LGPLv3)" NEWLINE - "Copyright (c) 2015-2020 qBittorrent (Anton Lashkov) (@qBittorrent): speedplotview (GPLv2)" NEWLINE - NEWLINE) + "Copyright (c) 2015-2020 qBittorrent (Anton Lashkov) (@qBittorrent): speedplotview (GPLv2)" NEWLINE NEWLINE) // - LOG(MODULE_INIT, "Qv2ray Start Time: " + QSTRN(QTime::currentTime().msecsSinceStartOfDay())) + LOG(MODULE_INIT, "Qv2ray Start Time: " + QSTRN(QTime::currentTime().msecsSinceStartOfDay())) // #ifdef QT_DEBUG - cout << "WARNING: ============================== This is a debug build, many features are not stable enough. ==============================" << endl; + cout << "WARNING: ============================== This is a debug build, many features are not stable enough. ==============================" + << endl; #endif // // Load the language translation list. auto langs = GetFileList(QDir(":/translations")); - if (langs.empty()) { + if (langs.empty()) + { LOG(MODULE_INIT, "FAILED to find any translations. THIS IS A BUILD ERROR.") - QvMessageBoxWarn(nullptr, QObject::tr("Cannot load languages"), QObject::tr("Qv2ray will continue running, but you cannot change the UI language.")); - } else { - for (auto lang : langs) { - LOG(MODULE_INIT, "Found Translator: " + lang) - } + QvMessageBoxWarn(nullptr, QObject::tr("Cannot load languages"), + QObject::tr("Qv2ray will continue running, but you cannot change the UI language.")); + } + else + { + for (auto lang : langs) { LOG(MODULE_INIT, "Found Translator: " + lang) } } // Qv2ray Initialize, find possible config paths and verify them. - if (!initialiseQv2ray()) { - return -1; - } + if (!initialiseQv2ray()) { return -1; } // Load the config for upgrade, but do not parse it to the struct. auto conf = JsonFromString(StringFromFile(QV2RAY_CONFIG_FILE)); auto confVersion = conf["config_version"].toVariant().toString().toInt(); - if (confVersion > QV2RAY_CONFIG_VERSION) { + if (confVersion > QV2RAY_CONFIG_VERSION) + { // Config version is larger than the current version... // This is rare but it may happen.... QvMessageBoxWarn(nullptr, QObject::tr("Qv2ray Cannot Continue"), QObject::tr("You are running a lower version of Qv2ray compared to the current config file.") + NEWLINE + - QObject::tr("Please check if there's an issue explaining about it.") + NEWLINE + - QObject::tr("Or submit a new issue if you think this is an error.") + NEWLINE + NEWLINE + - QObject::tr("Qv2ray will now exit.")); + QObject::tr("Please check if there's an issue explaining about it.") + NEWLINE + + QObject::tr("Or submit a new issue if you think this is an error.") + NEWLINE + NEWLINE + + QObject::tr("Qv2ray will now exit.")); return -2; } - if (confVersion < QV2RAY_CONFIG_VERSION) { + if (confVersion < QV2RAY_CONFIG_VERSION) + { // That is, config file needs to be upgraded. conf = Qv2ray::UpgradeConfig(confVersion, QV2RAY_CONFIG_VERSION, conf); } @@ -356,7 +392,8 @@ int main(int argc, char *argv[]) qApp->removeTranslator(Qv2rayTranslator.get()); LOG(MODULE_INIT, "Removed system translations") - if (confObject.uiConfig.language.isEmpty()) { + if (confObject.uiConfig.language.isEmpty()) + { // Prevent empty. LOG(MODULE_UI, "Setting default UI language to en-US") confObject.uiConfig.language = "en-US"; @@ -364,15 +401,15 @@ int main(int argc, char *argv[]) Qv2rayTranslator = std::move(QvTranslator(confObject.uiConfig.language).pTranslator); - if (qApp->installTranslator(Qv2rayTranslator.get())) { - LOG(MODULE_INIT, "Successfully installed a translator for " + confObject.uiConfig.language) - } else { + if (qApp->installTranslator(Qv2rayTranslator.get())) + { LOG(MODULE_INIT, "Successfully installed a translator for " + confObject.uiConfig.language) } + else + { // Do not translate these..... // If a translator fails to load, pop up a message. - QvMessageBoxWarn( - nullptr, "Translation Failed", - "Cannot load translation for " + confObject.uiConfig.language + ", English is now used." + NEWLINE + NEWLINE + - "Please go to Preferences Window to change language or open an Issue"); + QvMessageBoxWarn(nullptr, "Translation Failed", + "Cannot load translation for " + confObject.uiConfig.language + ", English is now used." + NEWLINE + NEWLINE + + "Please go to Preferences Window to change language or open an Issue"); } // Let's save the config. @@ -383,16 +420,16 @@ int main(int argc, char *argv[]) auto osslCurVersion = QSslSocket::sslLibraryVersionString(); LOG(MODULE_NETWORK, "Current OpenSSL version: " + osslCurVersion) - if (!QSslSocket::supportsSsl()) { + if (!QSslSocket::supportsSsl()) + { LOG(MODULE_NETWORK, "Required OpenSSL version: " + osslReqVersion) LOG(MODULE_NETWORK, "OpenSSL library MISSING, Quitting.") QvMessageBoxWarn(nullptr, QObject::tr("Dependency Missing"), QObject::tr("Cannot find openssl libs") + NEWLINE + - QObject::tr("This could be caused by a missing of `openssl` package in your system.") + NEWLINE + - QObject::tr("If you are using an AppImage from Github Action, please report a bug.") + NEWLINE + NEWLINE + - QObject::tr("Technical Details") + NEWLINE + - "OSsl.Rq.V=" + osslReqVersion + NEWLINE + - "OSsl.Cr.V=" + osslCurVersion); + QObject::tr("This could be caused by a missing of `openssl` package in your system.") + NEWLINE + + QObject::tr("If you are using an AppImage from Github Action, please report a bug.") + NEWLINE + NEWLINE + + QObject::tr("Technical Details") + NEWLINE + "OSsl.Rq.V=" + osslReqVersion + NEWLINE + + "OSsl.Cr.V=" + osslCurVersion); return -3; } @@ -406,7 +443,8 @@ int main(int argc, char *argv[]) #ifdef QV2RAY_USE_BUILTIN_DARKTHEME LOG(MODULE_UI, "Using built-in theme.") - if (confObject.uiConfig.useDarkTheme) { + if (confObject.uiConfig.useDarkTheme) + { LOG(MODULE_UI, " --> Using built-in dark theme.") // From https://forum.qt.io/topic/101391/windows-10-dark-theme/4 _qApp.setStyle("Fusion"); @@ -441,7 +479,8 @@ int main(int argc, char *argv[]) QStringList themes = QStyleFactory::keys(); //_qApp.setDesktopFileName("qv2ray.desktop"); - if (themes.contains(confObject.uiConfig.theme)) { + if (themes.contains(confObject.uiConfig.theme)) + { _qApp.setStyle(confObject.uiConfig.theme); LOG(MODULE_INIT + " " + MODULE_UI, "Setting Qv2ray UI themes: " + confObject.uiConfig.theme) } @@ -449,7 +488,8 @@ int main(int argc, char *argv[]) #endif #ifndef QT_DEBUG - try { + try + { #endif //_qApp.setAttribute(Qt::AA_DontUseNativeMenuBar); // Initialise Connection Handler @@ -465,23 +505,19 @@ int main(int argc, char *argv[]) // Handler for session logout, shutdown, etc. // Will not block. QGuiApplication::setFallbackSessionManagementEnabled(false); - QObject::connect(&_qApp, &QGuiApplication::commitDataRequest, []() { - LOG(MODULE_INIT, "Quit triggered by session manager.") - }); + QObject::connect(&_qApp, &QGuiApplication::commitDataRequest, []() { LOG(MODULE_INIT, "Quit triggered by session manager.") }); #ifndef Q_OS_WIN - signal(SIGUSR1, [](int) { - emit MainWindow::mwInstance->Connect(); - }); - signal(SIGUSR2, [](int) { - emit MainWindow::mwInstance->DisConnect(); - }); + signal(SIGUSR1, [](int) { emit MainWindow::mwInstance->Connect(); }); + signal(SIGUSR2, [](int) { emit MainWindow::mwInstance->DisConnect(); }); #endif auto rcode = _qApp.exec(); delete ConnectionManager; LOG(MODULE_INIT, "Quitting normally") return rcode; #ifndef QT_DEBUG - } catch (...) { + } + catch (...) + { QvMessageBoxWarn(nullptr, "ERROR", "There's something wrong happened and Qv2ray will quit now."); LOG(MODULE_INIT, "EXCEPTION THROWN: " __FILE__) return -99; diff --git a/src/ui/editors/w_InboundEditor.cpp b/src/ui/editors/w_InboundEditor.cpp index 5c3d1218..2d95cfb8 100644 --- a/src/ui/editors/w_InboundEditor.cpp +++ b/src/ui/editors/w_InboundEditor.cpp @@ -1,36 +1,45 @@ #include "w_InboundEditor.hpp" -#include "core/CoreUtils.hpp" #include "common/QvHelpers.hpp" +#include "core/CoreUtils.hpp" #include "core/connection/ConnectionIO.hpp" static bool isLoading = false; -#define CHECKLOADING if(isLoading) return; +#define CHECKLOADING \ + if (isLoading) return; -InboundEditor::InboundEditor(INBOUND root, QWidget *parent) : - QDialog(parent), - original(root) +InboundEditor::InboundEditor(INBOUND root, QWidget *parent) : QDialog(parent), original(root) { QvMessageBusConnect(InboundEditor); setupUi(this); this->root = root; auto inboundType = root["protocol"].toString(); allocate = root["allocate"].toObject(); - sniffing = root["sniffing"].toObject(); + sniffing = root["sniffing"].toObject(); - if (inboundType == "http") { - httpSettings = root["settings"].toObject(); - } else if (inboundType == "socks") { + if (inboundType == "http") { httpSettings = root["settings"].toObject(); } + else if (inboundType == "socks") + { socksSettings = root["settings"].toObject(); - } else if (inboundType == "dokodemo-door") { + } + else if (inboundType == "dokodemo-door") + { dokoSettings = root["settings"].toObject(); - } else if (inboundType == "mtproto") { + } + else if (inboundType == "mtproto") + { mtSettings = root["settings"].toObject(); - } else { - if (!root["protocol"].toString().isEmpty()) { + } + else + { + if (!root["protocol"].toString().isEmpty()) + { LOG(MODULE_UI, "Unsupported inbound type: " + inboundType) - QvMessageBoxWarn(this, tr("Inbound type not supported"), tr("The inbound type is not supported by Qv2ray (yet). Please use JsonEditor to change the settings") + "\r\n" + - tr("Inbound: ") + inboundType); - } else { + QvMessageBoxWarn(this, tr("Inbound type not supported"), + tr("The inbound type is not supported by Qv2ray (yet). Please use JsonEditor to change the settings") + "\r\n" + + tr("Inbound: ") + inboundType); + } + else + { LOG(MODULE_UI, "Creating new inbound config") root["protocol"] = inboundType = "http"; } @@ -41,10 +50,9 @@ InboundEditor::InboundEditor(INBOUND root, QWidget *parent) : QvMessageBusSlotImpl(InboundEditor) { - switch (msg) { - MBShowDefaultImpl\ - MBHideDefaultImpl\ - MBRetranslateDefaultImpl\ + switch (msg) + { + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl } } @@ -59,27 +67,28 @@ INBOUND InboundEditor::GenerateNewRoot() INBOUND _newRoot = root; auto inboundType = root["protocol"].toString(); - if (inboundType.isNull() || inboundType.isEmpty()) { - inboundType = "http"; - } + if (inboundType.isNull() || inboundType.isEmpty()) { inboundType = "http"; } - if (inboundType == "http") { + if (inboundType == "http") + { // Remove useless, misleading 'accounts' array. - if (httpAccountListBox->count() == 0) { - httpSettings.remove("accounts"); - } + if (httpAccountListBox->count() == 0) { httpSettings.remove("accounts"); } _newRoot["settings"] = httpSettings; - } else if (inboundType == "socks") { + } + else if (inboundType == "socks") + { // See above - if (socksAccountListBox->count() == 0) { - socksSettings.remove("accounts"); - } + if (socksAccountListBox->count() == 0) { socksSettings.remove("accounts"); } _newRoot["settings"] = socksSettings; - } else if (inboundType == "dokodemo-door") { + } + else if (inboundType == "dokodemo-door") + { _newRoot["settings"] = dokoSettings; - } else if (inboundType == "mtproto") { + } + else if (inboundType == "mtproto") + { _newRoot["settings"] = mtSettings; } @@ -102,7 +111,8 @@ void InboundEditor::LoadUIData() // destOverrideList->setEnabled(sniffing["enabled"].toBool()); - for (auto item : sniffing["destOverride"].toArray()) { + for (auto item : sniffing["destOverride"].toArray()) + { if (item.toString().toLower() == "http") destOverrideList->item(0)->setCheckState(Qt::Checked); if (item.toString().toLower() == "tls") destOverrideList->item(1)->setCheckState(Qt::Checked); @@ -118,9 +128,8 @@ void InboundEditor::LoadUIData() httpUserLevelSB->setValue(httpSettings["userLevel"].toInt()); httpAccountListBox->clear(); - for (auto user : httpSettings["accounts"].toArray()) { - httpAccountListBox->addItem(user.toObject()["user"].toString() + ":" + user.toObject()["pass"].toString()); - } + for (auto user : httpSettings["accounts"].toArray()) + { httpAccountListBox->addItem(user.toObject()["user"].toString() + ":" + user.toObject()["pass"].toString()); } // SOCKS socksAuthCombo->setCurrentText(socksSettings["auth"].toString()); @@ -128,9 +137,8 @@ void InboundEditor::LoadUIData() socksUDPIPAddrTxt->setText(socksSettings["ip"].toString()); socksUserLevelSB->setValue(socksSettings["userLevel"].toInt()); - for (auto user : socksSettings["accounts"].toArray()) { - socksAccountListBox->addItem(user.toObject()["user"].toString() + ":" + user.toObject()["pass"].toString()); - } + for (auto user : socksSettings["accounts"].toArray()) + { socksAccountListBox->addItem(user.toObject()["user"].toString() + ":" + user.toObject()["pass"].toString()); } // Dokodemo-Door dokoFollowRedirectCB->setChecked(dokoSettings["followRedirect"].toBool()); @@ -190,15 +198,18 @@ void InboundEditor::on_httpRemoveUserBtn_clicked() { CHECKLOADING - if (httpAccountListBox->currentRow() != -1) { + if (httpAccountListBox->currentRow() != -1) + { auto item = httpAccountListBox->currentItem(); auto list = httpSettings["accounts"].toArray(); - for (int i = 0 ; i < list.count(); i++) { + for (int i = 0; i < list.count(); i++) + { auto user = list[i].toObject(); auto entry = user["user"].toString() + ":" + user["pass"].toString(); - if (entry == item->text().trimmed()) { + if (entry == item->text().trimmed()) + { list.removeAt(i); httpSettings["accounts"] = list; LOG(MODULE_UI, "Removed http inbound user " + entry) @@ -206,8 +217,11 @@ void InboundEditor::on_httpRemoveUserBtn_clicked() } } - //QvMessageBox(this, tr("Removing a user"), tr("No user has been removed. Why?")); - } else { + // QvMessageBox(this, tr("Removing a user"), tr("No user has been + // removed. Why?")); + } + else + { QvMessageBoxWarn(this, tr("Removing a user"), tr("You haven't selected a user yet.")); } } @@ -220,10 +234,12 @@ void InboundEditor::on_httpAddUserBtn_clicked() // auto list = httpSettings["accounts"].toArray(); - for (int i = 0 ; i < list.count(); i++) { + for (int i = 0; i < list.count(); i++) + { auto _user = list[i].toObject(); - if (_user["user"].toString() == user) { + if (_user["user"].toString() == user) + { QvMessageBoxWarn(this, tr("Add a user"), tr("This user exists already.")); return; } @@ -243,15 +259,18 @@ void InboundEditor::on_socksRemoveUserBtn_clicked() { CHECKLOADING - if (socksAccountListBox->currentRow() != -1) { + if (socksAccountListBox->currentRow() != -1) + { auto item = socksAccountListBox->currentItem(); auto list = socksSettings["accounts"].toArray(); - for (int i = 0 ; i < list.count(); i++) { + for (int i = 0; i < list.count(); i++) + { auto user = list[i].toObject(); auto entry = user["user"].toString() + ":" + user["pass"].toString(); - if (entry == item->text().trimmed()) { + if (entry == item->text().trimmed()) + { list.removeAt(i); socksSettings["accounts"] = list; LOG(MODULE_UI, "Removed http inbound user " + entry) @@ -259,7 +278,9 @@ void InboundEditor::on_socksRemoveUserBtn_clicked() return; } } - } else { + } + else + { QvMessageBoxWarn(this, tr("Removing a user"), tr("You haven't selected a user yet.")); } } @@ -272,10 +293,12 @@ void InboundEditor::on_socksAddUserBtn_clicked() // auto list = socksSettings["accounts"].toArray(); - for (int i = 0 ; i < list.count(); i++) { + for (int i = 0; i < list.count(); i++) + { auto _user = list[i].toObject(); - if (_user["user"].toString() == user) { + if (_user["user"].toString() == user) + { QvMessageBoxWarn(this, tr("Add a user"), tr("This user exists already.")); return; } @@ -322,12 +345,11 @@ void InboundEditor::on_destOverrideList_itemChanged(QListWidgetItem *item) Q_UNUSED(item) QJsonArray list; - for (int i = 0; i < destOverrideList->count(); i++) { + for (int i = 0; i < destOverrideList->count(); i++) + { auto _item = destOverrideList->item(i); - if (_item->checkState() == Qt::Checked) { - list.append(_item->text().toLower()); - } + if (_item->checkState() == Qt::Checked) { list.append(_item->text().toLower()); } } sniffing["destOverride"] = list; @@ -360,7 +382,7 @@ void InboundEditor::on_dokoIPAddrTxt_textEdited(const QString &arg1) void InboundEditor::on_dokoPortSB_valueChanged(int arg1) { CHECKLOADING - dokoSettings["port"] = arg1; + dokoSettings["port"] = arg1; } void InboundEditor::on_dokoTCPCB_stateChanged(int arg1) @@ -461,5 +483,5 @@ void InboundEditor::on_inboundPortTxt_textEdited(const QString &arg1) void InboundEditor::on_socksAuthCombo_currentIndexChanged(const QString &arg1) { CHECKLOADING - socksSettings["auth"] = arg1.toLower(); + socksSettings["auth"] = arg1.toLower(); } diff --git a/src/ui/editors/w_InboundEditor.hpp b/src/ui/editors/w_InboundEditor.hpp index a5d81c8a..be23aed7 100644 --- a/src/ui/editors/w_InboundEditor.hpp +++ b/src/ui/editors/w_InboundEditor.hpp @@ -1,97 +1,100 @@ #pragma once +#include "base/Qv2rayBase.hpp" +#include "ui/messaging/QvMessageBus.hpp" +#include "ui_w_InboundEditor.h" + #include #include #include -#include "ui_w_InboundEditor.h" -#include "base/Qv2rayBase.hpp" -#include "ui/messaging/QvMessageBus.hpp" -class InboundEditor : public QDialog, private Ui::InboundEditor +class InboundEditor + : public QDialog + , private Ui::InboundEditor { - Q_OBJECT + Q_OBJECT - public: - explicit InboundEditor(INBOUND root, QWidget *parent = nullptr); - ~InboundEditor(); - INBOUND OpenEditor(); - public slots: - QvMessageBusSlotDecl + public: + explicit InboundEditor(INBOUND root, QWidget *parent = nullptr); + ~InboundEditor(); + INBOUND OpenEditor(); + public slots: + QvMessageBusSlotDecl; - private slots: - void on_inboundProtocolCombo_currentIndexChanged(const QString &arg1); + private slots: + void on_inboundProtocolCombo_currentIndexChanged(const QString &arg1); - void on_inboundProtocolCombo_currentIndexChanged(int index); + void on_inboundProtocolCombo_currentIndexChanged(int index); - void on_inboundTagTxt_textEdited(const QString &arg1); + void on_inboundTagTxt_textEdited(const QString &arg1); - void on_httpTimeoutSpinBox_valueChanged(int arg1); + void on_httpTimeoutSpinBox_valueChanged(int arg1); - void on_httpTransparentCB_stateChanged(int arg1); + void on_httpTransparentCB_stateChanged(int arg1); - void on_httpUserLevelSB_valueChanged(int arg1); + void on_httpUserLevelSB_valueChanged(int arg1); - void on_httpRemoveUserBtn_clicked(); + void on_httpRemoveUserBtn_clicked(); - void on_httpAddUserBtn_clicked(); + void on_httpAddUserBtn_clicked(); - void on_strategyCombo_currentIndexChanged(const QString &arg1); + void on_strategyCombo_currentIndexChanged(const QString &arg1); - void on_refreshNumberBox_valueChanged(int arg1); + void on_refreshNumberBox_valueChanged(int arg1); - void on_concurrencyNumberBox_valueChanged(int arg1); + void on_concurrencyNumberBox_valueChanged(int arg1); - void on_enableSniffingCB_stateChanged(int arg1); + void on_enableSniffingCB_stateChanged(int arg1); - void on_destOverrideList_itemChanged(QListWidgetItem *item); + void on_destOverrideList_itemChanged(QListWidgetItem *item); - void on_socksUDPCB_stateChanged(int arg1); + void on_socksUDPCB_stateChanged(int arg1); - void on_socksUDPIPAddrTxt_textEdited(const QString &arg1); + void on_socksUDPIPAddrTxt_textEdited(const QString &arg1); - void on_socksUserLevelSB_valueChanged(int arg1); + void on_socksUserLevelSB_valueChanged(int arg1); - void on_socksRemoveUserBtn_clicked(); + void on_socksRemoveUserBtn_clicked(); - void on_socksAddUserBtn_clicked(); + void on_socksAddUserBtn_clicked(); - void on_dokoIPAddrTxt_textEdited(const QString &arg1); + void on_dokoIPAddrTxt_textEdited(const QString &arg1); - void on_dokoPortSB_valueChanged(int arg1); + void on_dokoPortSB_valueChanged(int arg1); - void on_dokoTCPCB_stateChanged(int arg1); + void on_dokoTCPCB_stateChanged(int arg1); - void on_dokoUDPCB_stateChanged(int arg1); + void on_dokoUDPCB_stateChanged(int arg1); - void on_dokoTimeoutSB_valueChanged(int arg1); + void on_dokoTimeoutSB_valueChanged(int arg1); - void on_dokoFollowRedirectCB_stateChanged(int arg1); + void on_dokoFollowRedirectCB_stateChanged(int arg1); - void on_dokoUserLevelSB_valueChanged(int arg1); + void on_dokoUserLevelSB_valueChanged(int arg1); - void on_mtEMailTxt_textEdited(const QString &arg1); + void on_mtEMailTxt_textEdited(const QString &arg1); - void on_mtSecretTxt_textEdited(const QString &arg1); + void on_mtSecretTxt_textEdited(const QString &arg1); - void on_mtUserLevelSB_valueChanged(int arg1); + void on_mtUserLevelSB_valueChanged(int arg1); - void on_inboundHostTxt_textEdited(const QString &arg1); + void on_inboundHostTxt_textEdited(const QString &arg1); - void on_inboundPortTxt_textEdited(const QString &arg1); + void on_inboundPortTxt_textEdited(const QString &arg1); - void on_socksAuthCombo_currentIndexChanged(const QString &arg1); + void on_socksAuthCombo_currentIndexChanged(const QString &arg1); - private: - INBOUND GenerateNewRoot(); - void LoadUIData(); - INBOUND original; - INBOUND root; - // - QJsonObject httpSettings; - QJsonObject socksSettings; - QJsonObject mtSettings; - QJsonObject dokoSettings; - // - QJsonObject sniffing; - QJsonObject allocate; + private: + INBOUND GenerateNewRoot(); + void LoadUIData(); + INBOUND original; + INBOUND root; + // + QJsonObject httpSettings; + QJsonObject socksSettings; + QJsonObject mtSettings; + QJsonObject dokoSettings; + // + QJsonObject sniffing; + QJsonObject allocate; }; diff --git a/src/ui/editors/w_JsonEditor.cpp b/src/ui/editors/w_JsonEditor.cpp index fa7c3b65..cf5c414d 100644 --- a/src/ui/editors/w_JsonEditor.cpp +++ b/src/ui/editors/w_JsonEditor.cpp @@ -2,20 +2,22 @@ #include "common/QvHelpers.hpp" -JsonEditor::JsonEditor(QJsonObject rootObject, QWidget *parent) : - QDialog(parent) +JsonEditor::JsonEditor(QJsonObject rootObject, QWidget *parent) : QDialog(parent) { QvMessageBusConnect(JsonEditor); setupUi(this); original = rootObject; final = rootObject; - QString jsonString = JsonToString(rootObject); + QString jsonString = JsonToString(rootObject); - if (VerifyJsonString(jsonString).isEmpty()) { + if (VerifyJsonString(jsonString).isEmpty()) + { LOG(MODULE_UI, "Begin loading Json Model") jsonTree->setModel(&model); model.loadJson(QJsonDocument(rootObject).toJson()); - } else { + } + else + { QvMessageBoxWarn(this, tr("Json Contains Syntax Errors"), tr("Original Json may contain syntax errors. Json tree is disabled.")); } @@ -26,10 +28,9 @@ JsonEditor::JsonEditor(QJsonObject rootObject, QWidget *parent) : QvMessageBusSlotImpl(JsonEditor) { - switch (msg) { - MBShowDefaultImpl - MBHideDefaultImpl - MBRetranslateDefaultImpl + switch (msg) + { + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl } } @@ -38,7 +39,8 @@ QJsonObject JsonEditor::OpenEditor() int resultCode = this->exec(); auto string = jsonEditor->toPlainText(); - while (resultCode == QDialog::Accepted && !VerifyJsonString(string).isEmpty()) { + while (resultCode == QDialog::Accepted && !VerifyJsonString(string).isEmpty()) + { QvMessageBoxWarn(this, tr("Json Contains Syntax Errors"), tr("You must correct these errors before continue.")); resultCode = this->exec(); string = jsonEditor->toPlainText(); @@ -57,13 +59,16 @@ void JsonEditor::on_jsonEditor_textChanged() auto VerifyResult = VerifyJsonString(string); jsonValidateStatus->setText(VerifyResult); - if (VerifyResult.isEmpty()) { + if (VerifyResult.isEmpty()) + { BLACK(jsonEditor) final = JsonFromString(string); model.loadJson(QJsonDocument(final).toJson()); jsonTree->expandAll(); jsonTree->resizeColumnToContents(0); - } else { + } + else + { RED(jsonEditor) } } @@ -74,10 +79,13 @@ void JsonEditor::on_formatJsonBtn_clicked() auto VerifyResult = VerifyJsonString(string); jsonValidateStatus->setText(VerifyResult); - if (VerifyResult.isEmpty()) { + if (VerifyResult.isEmpty()) + { BLACK(jsonEditor) jsonEditor->setPlainText(JsonToString(JsonFromString(string))); - } else { + } + else + { RED(jsonEditor) QvMessageBoxWarn(this, tr("Syntax Errors"), tr("Please fix the JSON errors before continue")); } diff --git a/src/ui/editors/w_JsonEditor.hpp b/src/ui/editors/w_JsonEditor.hpp index b4d98f2b..afdf0b5f 100644 --- a/src/ui/editors/w_JsonEditor.hpp +++ b/src/ui/editors/w_JsonEditor.hpp @@ -1,30 +1,33 @@ #pragma once +#include "base/Qv2rayBase.hpp" +#include "common/QJsonModel.hpp" +#include "ui/messaging/QvMessageBus.hpp" +#include "ui_w_JsonEditor.h" + #include #include -#include "common/QJsonModel.hpp" -#include "base/Qv2rayBase.hpp" -#include "ui_w_JsonEditor.h" -#include "ui/messaging/QvMessageBus.hpp" -class JsonEditor : public QDialog, private Ui::JsonEditor +class JsonEditor + : public QDialog + , private Ui::JsonEditor { - Q_OBJECT + Q_OBJECT - public: - explicit JsonEditor(QJsonObject rootObject, QWidget *parent = nullptr); - ~JsonEditor(); - QJsonObject OpenEditor(); - public slots: - QvMessageBusSlotDecl + public: + explicit JsonEditor(QJsonObject rootObject, QWidget *parent = nullptr); + ~JsonEditor(); + QJsonObject OpenEditor(); + public slots: + QvMessageBusSlotDecl; - private slots: - void on_jsonEditor_textChanged(); + private slots: + void on_jsonEditor_textChanged(); - void on_formatJsonBtn_clicked(); + void on_formatJsonBtn_clicked(); - private: - QJsonModel model; - QJsonObject original; - QJsonObject final; + private: + QJsonModel model; + QJsonObject original; + QJsonObject final; }; diff --git a/src/ui/editors/w_OutboundEditor.cpp b/src/ui/editors/w_OutboundEditor.cpp index da262dc5..14bacfa7 100644 --- a/src/ui/editors/w_OutboundEditor.cpp +++ b/src/ui/editors/w_OutboundEditor.cpp @@ -1,20 +1,16 @@ #include +#include "w_OutboundEditor.hpp" + +#include "core/connection/Generation.hpp" +#include "ui/editors/w_JsonEditor.hpp" +#include "ui/editors/w_RoutesEditor.hpp" +#include "ui/w_MainWindow.hpp" + #include #include #include -#include "w_OutboundEditor.hpp" -#include "ui/w_MainWindow.hpp" -#include "ui/editors/w_JsonEditor.hpp" -#include "ui/editors/w_RoutesEditor.hpp" -#include "core/connection/Generation.hpp" - -OutboundEditor::OutboundEditor(QWidget *parent) - : QDialog(parent), - Tag(""), - Mux(), - vmess(), - shadowsocks() +OutboundEditor::OutboundEditor(QWidget *parent) : QDialog(parent), Tag(""), Mux(), vmess(), shadowsocks() { QvMessageBusConnect(OutboundEditor); setupUi(this); @@ -40,10 +36,9 @@ OutboundEditor::OutboundEditor(QWidget *parent) QvMessageBusSlotImpl(OutboundEditor) { - switch (msg) { - MBShowDefaultImpl - MBHideDefaultImpl - MBRetranslateDefaultImpl + switch (msg) + { + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl } } @@ -57,20 +52,28 @@ OutboundEditor::OutboundEditor(OUTBOUND outboundEntry, QWidget *parent) : Outbou useFProxy = outboundEntry[QV2RAY_USE_FPROXY_KEY].toBool(false); ssWidget->SetStreamObject(StructFromJsonString(JsonToString(outboundEntry["streamSettings"].toObject()))); - if (OutboundType == "vmess") { - vmess = StructFromJsonString(JsonToString(outboundEntry["settings"].toObject()["vnext"].toArray().first().toObject())); + if (OutboundType == "vmess") + { + vmess = + StructFromJsonString(JsonToString(outboundEntry["settings"].toObject()["vnext"].toArray().first().toObject())); shadowsocks.port = vmess.port; shadowsocks.address = vmess.address; socks.address = vmess.address; socks.port = vmess.port; - } else if (OutboundType == "shadowsocks") { - shadowsocks = StructFromJsonString(JsonToString(outboundEntry["settings"].toObject()["servers"].toArray().first().toObject())); + } + else if (OutboundType == "shadowsocks") + { + shadowsocks = StructFromJsonString( + JsonToString(outboundEntry["settings"].toObject()["servers"].toArray().first().toObject())); vmess.address = shadowsocks.address; vmess.port = shadowsocks.port; socks.address = shadowsocks.address; socks.port = shadowsocks.port; - } else if (OutboundType == "socks") { - socks = StructFromJsonString(JsonToString(outboundEntry["settings"].toObject()["servers"].toArray().first().toObject())); + } + else if (OutboundType == "socks") + { + socks = + StructFromJsonString(JsonToString(outboundEntry["settings"].toObject()["servers"].toArray().first().toObject())); vmess.address = socks.address; vmess.port = socks.port; shadowsocks.address = socks.address; @@ -81,7 +84,6 @@ OutboundEditor::OutboundEditor(OUTBOUND outboundEntry, QWidget *parent) : Outbou Result = GenerateConnectionJson(); } - OutboundEditor::~OutboundEditor() { } @@ -106,18 +108,23 @@ OUTBOUND OutboundEditor::GenerateConnectionJson() OUTBOUNDSETTING settings; auto streaming = GetRootObject(ssWidget->GetStreamSettings()); - if (OutboundType == "vmess") { + if (OutboundType == "vmess") + { // VMess is only a ServerObject, and we need an array { "vnext": [] } QJsonArray vnext; vnext.append(GetRootObject(vmess)); settings.insert("vnext", vnext); - } else if (OutboundType == "shadowsocks") { + } + else if (OutboundType == "shadowsocks") + { streaming = QJsonObject(); LOG(MODULE_CONNECTION, "Shadowsocks outbound does not need StreamSettings.") QJsonArray servers; servers.append(GetRootObject(shadowsocks)); settings["servers"] = servers; - } else if (OutboundType == "socks") { + } + else if (OutboundType == "socks") + { streaming = QJsonObject(); LOG(MODULE_CONNECTION, "Socks outbound does not need StreamSettings.") QJsonArray servers; @@ -132,14 +139,17 @@ OUTBOUND OutboundEditor::GenerateConnectionJson() void OutboundEditor::ReloadGUI() { - if (OutboundType == "vmess") { + if (OutboundType == "vmess") + { outBoundTypeCombo->setCurrentIndex(0); ipLineEdit->setText(vmess.address); portLineEdit->setText(QSTRN(vmess.port)); idLineEdit->setText(vmess.users.front().id); alterLineEdit->setValue(vmess.users.front().alterId); securityCombo->setCurrentText(vmess.users.front().security); - } else if (OutboundType == "shadowsocks") { + } + else if (OutboundType == "shadowsocks") + { outBoundTypeCombo->setCurrentIndex(1); // ShadowSocks Configs ipLineEdit->setText(shadowsocks.address); @@ -149,7 +159,9 @@ void OutboundEditor::ReloadGUI() ss_otaCheckBox->setChecked(shadowsocks.ota); ss_passwordTxt->setText(shadowsocks.password); ss_encryptionMethod->setCurrentText(shadowsocks.method); - } else if (OutboundType == "socks") { + } + else if (OutboundType == "socks") + { outBoundTypeCombo->setCurrentIndex(2); ipLineEdit->setText(socks.address); portLineEdit->setText(QSTRN(socks.port)); @@ -165,7 +177,6 @@ void OutboundEditor::ReloadGUI() muxConcurrencyTxt->setValue(Mux["concurrency"].toInt()); } - void OutboundEditor::on_buttonBox_accepted() { Result = GenerateConnectionJson(); @@ -180,7 +191,8 @@ void OutboundEditor::on_ipLineEdit_textEdited(const QString &arg1) void OutboundEditor::on_portLineEdit_textEdited(const QString &arg1) { - if (arg1 != "") { + if (arg1 != "") + { vmess.port = arg1.toInt(); shadowsocks.port = arg1.toInt(); socks.port = arg1.toInt(); diff --git a/src/ui/editors/w_OutboundEditor.hpp b/src/ui/editors/w_OutboundEditor.hpp index d8fc403c..153076e0 100644 --- a/src/ui/editors/w_OutboundEditor.hpp +++ b/src/ui/editors/w_OutboundEditor.hpp @@ -1,76 +1,79 @@ #pragma once -#include -#include #include "base/Qv2rayBase.hpp" -#include "ui_w_OutboundEditor.h" -#include "ui/widgets/StreamSettingsWidget.hpp" #include "ui/messaging/QvMessageBus.hpp" +#include "ui/widgets/StreamSettingsWidget.hpp" +#include "ui_w_OutboundEditor.h" -class OutboundEditor : public QDialog, private Ui::OutboundEditor +#include +#include + +class OutboundEditor + : public QDialog + , private Ui::OutboundEditor { - Q_OBJECT - public: - explicit OutboundEditor(QWidget *parent = nullptr); - explicit OutboundEditor(OUTBOUND outboundEntry, QWidget *parent = nullptr); - ~OutboundEditor(); - OUTBOUND OpenEditor(); - QString GetFriendlyName(); - public slots: - QvMessageBusSlotDecl - signals: - void s_reload_config(bool need_restart); - private slots: - void on_buttonBox_accepted(); + Q_OBJECT + public: + explicit OutboundEditor(QWidget *parent = nullptr); + explicit OutboundEditor(OUTBOUND outboundEntry, QWidget *parent = nullptr); + ~OutboundEditor(); + OUTBOUND OpenEditor(); + QString GetFriendlyName(); + public slots: + QvMessageBusSlotDecl; + signals: + void s_reload_config(bool need_restart); + private slots: + void on_buttonBox_accepted(); - void on_ipLineEdit_textEdited(const QString &arg1); + void on_ipLineEdit_textEdited(const QString &arg1); - void on_portLineEdit_textEdited(const QString &arg1); + void on_portLineEdit_textEdited(const QString &arg1); - void on_idLineEdit_textEdited(const QString &arg1); + void on_idLineEdit_textEdited(const QString &arg1); - void on_tagTxt_textEdited(const QString &arg1); + void on_tagTxt_textEdited(const QString &arg1); - void on_muxEnabledCB_stateChanged(int arg1); + void on_muxEnabledCB_stateChanged(int arg1); - void on_muxConcurrencyTxt_valueChanged(int arg1); + void on_muxConcurrencyTxt_valueChanged(int arg1); - void on_alterLineEdit_valueChanged(int arg1); + void on_alterLineEdit_valueChanged(int arg1); - void on_useFPCB_stateChanged(int arg1); + void on_useFPCB_stateChanged(int arg1); - void on_outBoundTypeCombo_currentIndexChanged(int index); + void on_outBoundTypeCombo_currentIndexChanged(int index); - void on_ss_emailTxt_textEdited(const QString &arg1); + void on_ss_emailTxt_textEdited(const QString &arg1); - void on_ss_passwordTxt_textEdited(const QString &arg1); + void on_ss_passwordTxt_textEdited(const QString &arg1); - void on_ss_encryptionMethod_currentIndexChanged(const QString &arg1); + void on_ss_encryptionMethod_currentIndexChanged(const QString &arg1); - void on_ss_levelSpin_valueChanged(int arg1); + void on_ss_levelSpin_valueChanged(int arg1); - void on_ss_otaCheckBox_stateChanged(int arg1); + void on_ss_otaCheckBox_stateChanged(int arg1); - void on_socks_UserNameTxt_textEdited(const QString &arg1); + void on_socks_UserNameTxt_textEdited(const QString &arg1); - void on_socks_PasswordTxt_textEdited(const QString &arg1); + void on_socks_PasswordTxt_textEdited(const QString &arg1); - void on_securityCombo_currentIndexChanged(const QString &arg1); + void on_securityCombo_currentIndexChanged(const QString &arg1); - private: - QString Tag; - void ReloadGUI(); - bool useFProxy; - OUTBOUND GenerateConnectionJson(); - OUTBOUND Original; - OUTBOUND Result; - QJsonObject Mux; - // - // Connection Configs - QString OutboundType; - // - VMessServerObject vmess; - ShadowSocksServerObject shadowsocks; - SocksServerObject socks; - // - StreamSettingsWidget *ssWidget; + private: + QString Tag; + void ReloadGUI(); + bool useFProxy; + OUTBOUND GenerateConnectionJson(); + OUTBOUND Original; + OUTBOUND Result; + QJsonObject Mux; + // + // Connection Configs + QString OutboundType; + // + VMessServerObject vmess; + ShadowSocksServerObject shadowsocks; + SocksServerObject socks; + // + StreamSettingsWidget *ssWidget; }; diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index 1722f773..bd24045a 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -1,36 +1,40 @@ // WARNING -// Since it's required for *extra.cpp to know the content of those macros defined below. -// We include this CPP file instead of the proper HPP file. Adding #pragma once to prevent duplicate function instances +// Since it's required for *extra.cpp to know the content of those macros +// defined below. We include this CPP file instead of the proper HPP file. +// Adding #pragma once to prevent duplicate function instances #pragma once #include "w_RoutesEditor.hpp" -#include "core/connection/ConnectionIO.hpp" -#include "core/connection/Generation.hpp" -#include "w_OutboundEditor.hpp" -#include "w_JsonEditor.hpp" -#include "w_InboundEditor.hpp" -#include "ui/w_ImportConfig.hpp" -#include "core/CoreUtils.hpp" -#include "ui/models/RuleNodeModel.hpp" -#include "ui/models/InboundNodeModel.hpp" -#include "ui/models/OutboundNodeModel.hpp" - -#include "NodeStyle.hpp" #include "FlowView.hpp" #include "FlowViewStyle.hpp" +#include "NodeStyle.hpp" +#include "core/CoreUtils.hpp" +#include "core/connection/ConnectionIO.hpp" +#include "core/connection/Generation.hpp" +#include "ui/models/InboundNodeModel.hpp" +#include "ui/models/OutboundNodeModel.hpp" +#include "ui/models/RuleNodeModel.hpp" +#include "ui/w_ImportConfig.hpp" +#include "w_InboundEditor.hpp" +#include "w_JsonEditor.hpp" +#include "w_OutboundEditor.hpp" using QtNodes::FlowView; using namespace Qv2ray::ui::nodemodels; static bool isLoading = false; #define CurrentRule this->rules[this->currentRuleTag] -#define LOADINGCHECK if(isLoading) return; -#define GetFirstNodeData(node, nodeModel, dataModel) (static_cast(static_cast((node).nodeDataModel())->outData(0).get())) +#define LOADINGCHECK \ + if (isLoading) return; +#define GetFirstNodeData(node, nodeModel, dataModel) \ + (static_cast(static_cast((node).nodeDataModel())->outData(0).get())) -#define CHECKEMPTYRULES if (this->rules.isEmpty()) { \ - LOG(MODULE_UI, "No rules currently, we add one.") \ - AddNewRule(); \ +#define CHECKEMPTYRULES \ + if (this->rules.isEmpty()) \ + { \ + LOG(MODULE_UI, "No rules currently, we add one.") \ + AddNewRule(); \ } #define GRAPH_GLOBAL_OFFSET_X -80 @@ -41,18 +45,25 @@ static bool isLoading = false; void RouteEditor::SetupNodeWidget() { - if (GlobalConfig.uiConfig.useDarkTheme) { - ConnectionStyle::setConnectionStyle(R"({"ConnectionStyle": {"ConstructionColor": "gray","NormalColor": "black","SelectedColor": "gray", + if (GlobalConfig.uiConfig.useDarkTheme) + { + ConnectionStyle::setConnectionStyle( + R"({"ConnectionStyle": {"ConstructionColor": "gray","NormalColor": "black","SelectedColor": "gray", "SelectedHaloColor": "deepskyblue","HoveredColor": "deepskyblue","LineWidth": 3.0, "ConstructionLineWidth": 2.0,"PointDiameter": 10.0,"UseDataDefinedColors": true}})"); - } else { - QtNodes::NodeStyle::setNodeStyle(R"({"NodeStyle": {"NormalBoundaryColor": "darkgray","SelectedBoundaryColor": "deepskyblue", + } + else + { + QtNodes::NodeStyle::setNodeStyle( + R"({"NodeStyle": {"NormalBoundaryColor": "darkgray","SelectedBoundaryColor": "deepskyblue", "GradientColor0": "mintcream","GradientColor1": "mintcream","GradientColor2": "mintcream", "GradientColor3": "mintcream","ShadowColor": [200, 200, 200],"FontColor": [10, 10, 10], "FontColorFaded": [100, 100, 100],"ConnectionPointColor": "white","PenWidth": 2.0,"HoveredPenWidth": 2.5, "ConnectionPointDiameter": 10.0,"Opacity": 1.0}})"); - QtNodes::FlowViewStyle::setStyle(R"({"FlowViewStyle": {"BackgroundColor": [255, 255, 240],"FineGridColor": [245, 245, 230],"CoarseGridColor": [235, 235, 220]}})"); - ConnectionStyle::setConnectionStyle(R"({"ConnectionStyle": {"ConstructionColor": "gray","NormalColor": "black","SelectedColor": "gray", + QtNodes::FlowViewStyle::setStyle( + R"({"FlowViewStyle": {"BackgroundColor": [255, 255, 240],"FineGridColor": [245, 245, 230],"CoarseGridColor": [235, 235, 220]}})"); + ConnectionStyle::setConnectionStyle( + R"({"ConnectionStyle": {"ConstructionColor": "gray","NormalColor": "black","SelectedColor": "gray", "SelectedHaloColor": "deepskyblue","HoveredColor": "deepskyblue","LineWidth": 3.0,"ConstructionLineWidth": 2.0, "PointDiameter": 10.0,"UseDataDefinedColors": false}})"); } @@ -91,17 +102,20 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QDialog(pare domainStrategyCombo->setCurrentText(domainStrategy); // Show connections in the node graph - for (auto in : root["inbounds"].toArray()) { + for (auto in : root["inbounds"].toArray()) + { INBOUND _in = INBOUND(in.toObject()); AddInbound(_in); } - for (auto out : root["outbounds"].toArray()) { + for (auto out : root["outbounds"].toArray()) + { OUTBOUND _out = OUTBOUND(out.toObject()); AddOutbound(_out); } - for (auto item : root["routing"].toObject()["rules"].toArray()) { + for (auto item : root["routing"].toObject()["rules"].toArray()) + { auto _rule = StructFromJsonString(JsonToString(item.toObject())); AddRule(_rule); } @@ -110,12 +124,12 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QDialog(pare defaultOutboundCombo->setCurrentText(root["outbounds"].toArray().first().toObject()["tag"].toString()); // Find and add balancers. - for (auto _balancer : root["routing"].toObject()["balancers"].toArray()) { + for (auto _balancer : root["routing"].toObject()["balancers"].toArray()) + { auto _balancerObject = _balancer.toObject(); - if (!_balancerObject["tag"].toString().isEmpty()) { - balancers[_balancerObject["tag"].toString()] = _balancerObject["selector"].toVariant().toStringList(); - } + if (!_balancerObject["tag"].toString().isEmpty()) + { balancers[_balancerObject["tag"].toString()] = _balancerObject["selector"].toVariant().toStringList(); } } isLoading = false; @@ -123,10 +137,9 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QDialog(pare QvMessageBusSlotImpl(RouteEditor) { - switch (msg) { - MBShowDefaultImpl - MBHideDefaultImpl - MBRetranslateDefaultImpl + switch (msg) + { + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl } } @@ -140,25 +153,31 @@ void RouteEditor::onNodeClicked(Node &n) auto isIn = inboundNodes.values().contains(&n); auto isRule = ruleNodes.values().contains(&n); - if (isRule) { + if (isRule) + { // It's a rule object currentRuleTag = GetFirstNodeData(n, QvRuleNodeDataModel, RuleNodeData)->GetRuleTag(); DEBUG(MODULE_GRAPH, "Selecting rule: " + currentRuleTag) ShowCurrentRuleDetail(); toolBox->setCurrentIndex(1); - } else if (isOut || isIn) { + } + else if (isOut || isIn) + { // It's an inbound or an outbound. QString alias; QString host; int port; QString protocol; - if (isOut) { + if (isOut) + { alias = GetFirstNodeData(n, QvOutboundNodeModel, OutboundNodeData)->GetOutbound(); QJsonObject _root = outbounds[alias].raw(); throw new runtime_error("Not implemented"); GetOutboundData(OUTBOUND(_root), &host, &port, &protocol); - } else { + } + else + { alias = GetFirstNodeData(n, QvInboundNodeModel, InboundNodeData)->GetInbound(); QJsonObject _root = inbounds[alias].raw(); host = _root["listen"].toString(); @@ -170,7 +189,9 @@ void RouteEditor::onNodeClicked(Node &n) protocolLabel->setText(protocol); portLabel->setNum(port); hostLabel->setText(host); - } else { + } + else + { LOG(MODULE_GRAPH, "Selected an unknown node, RARE.") } } @@ -185,7 +206,8 @@ void RouteEditor::onConnectionCreated(QtNodes::Connection const &c) auto const sourceNode = c.getNode(PortType::Out); auto const targetNode = c.getNode(PortType::In); - if (inboundNodes.values().contains(sourceNode) && ruleNodes.values().contains(targetNode)) { + if (inboundNodes.values().contains(sourceNode) && ruleNodes.values().contains(targetNode)) + { // It's a inbound-rule connection onNodeClicked(*sourceNode); onNodeClicked(*targetNode); @@ -194,14 +216,16 @@ void RouteEditor::onConnectionCreated(QtNodes::Connection const &c) // QStringList has an helper to let us remove duplicates, see below. QStringList _inbounds; - for (auto &&[_, conn] : nodeScene->connections()) { + for (auto &&[_, conn] : nodeScene->connections()) + { auto _connection = conn.get(); - if (_connection->getNode(PortType::In) == targetNode && _connection->getNode(PortType::Out) == sourceNode && _connection->id() != c.id()) { - nodeScene->deleteConnection(*_connection); - } + if (_connection->getNode(PortType::In) == targetNode && _connection->getNode(PortType::Out) == sourceNode && + _connection->id() != c.id()) + { nodeScene->deleteConnection(*_connection); } // Append all inbounds - else if (_connection->getNode(PortType::In) == targetNode) { + else if (_connection->getNode(PortType::In) == targetNode) + { _inbounds.append(GetFirstNodeData(*_connection->getNode(PortType::Out), QvInboundNodeModel, InboundNodeData)->GetInbound()); } } @@ -209,7 +233,9 @@ void RouteEditor::onConnectionCreated(QtNodes::Connection const &c) // caused by multi-in connection _inbounds.removeDuplicates(); CurrentRule.inboundTag = _inbounds; - } else if (ruleNodes.values().contains(sourceNode) && outboundNodes.values().contains(targetNode)) { + } + else if (ruleNodes.values().contains(sourceNode) && outboundNodes.values().contains(targetNode)) + { // It's a rule-outbound connection onNodeClicked(*sourceNode); onNodeClicked(*targetNode); @@ -219,7 +245,9 @@ void RouteEditor::onConnectionCreated(QtNodes::Connection const &c) // Update balancer settings. ShowCurrentRuleDetail(); LOG(MODULE_GRAPH, "Updated outbound: " + CurrentRule.outboundTag) - } else { + } + else + { // It's an impossible connection LOG(MODULE_GRAPH, "Unrecognized connection, RARE.") } @@ -235,7 +263,8 @@ void RouteEditor::onConnectionDeleted(QtNodes::Connection const &c) auto const source = c.getNode(PortType::Out); auto const target = c.getNode(PortType::In); - if (inboundNodes.values().contains(source) && ruleNodes.values().contains(target)) { + if (inboundNodes.values().contains(source) && ruleNodes.values().contains(target)) + { // It's a inbound-rule connection onNodeClicked(*source); onNodeClicked(*target); @@ -243,19 +272,21 @@ void RouteEditor::onConnectionDeleted(QtNodes::Connection const &c) auto _inboundTag = GetFirstNodeData(*source, QvInboundNodeModel, InboundNodeData)->GetInbound(); LOG(MODULE_UI, "Removing inbound: " + _inboundTag + " from rule: " + currentRuleTag) CurrentRule.inboundTag.removeAll(_inboundTag); - } else if (ruleNodes.values().contains(source) && outboundNodes.values().contains(target)) { + } + else if (ruleNodes.values().contains(source) && outboundNodes.values().contains(target)) + { // It's a rule-outbound connection onNodeClicked(*source); onNodeClicked(*target); currentRuleTag = GetFirstNodeData(*source, QvRuleNodeDataModel, RuleNodeData)->GetRuleTag(); auto _outboundTag = GetFirstNodeData(*target, QvOutboundNodeModel, OutboundNodeData)->GetOutbound(); - if (!CurrentRule.QV2RAY_RULE_USE_BALANCER && CurrentRule.outboundTag == _outboundTag) { - CurrentRule.outboundTag.clear(); - } + if (!CurrentRule.QV2RAY_RULE_USE_BALANCER && CurrentRule.outboundTag == _outboundTag) { CurrentRule.outboundTag.clear(); } LOG(MODULE_GRAPH, "Removing an outbound: " + _outboundTag) - } else { + } + else + { // It's an impossible connection LOG(MODULE_GRAPH, "Selected an unknown node, RARE.") } @@ -265,30 +296,35 @@ CONFIGROOT RouteEditor::OpenEditor() { auto result = this->exec(); - if (rules.isEmpty()) { - // Prevent empty rule list causing mis-detection of config type to simple. + if (rules.isEmpty()) + { + // Prevent empty rule list causing mis-detection of config type to + // simple. on_addRouteBtn_clicked(); } // If clicking OK - if (result == QDialog::Accepted) { + if (result == QDialog::Accepted) + { QJsonArray rulesArray; QJsonArray _balancers; // Append rules by order - for (auto i = 0; i < ruleListWidget->count(); i++) { + for (auto i = 0; i < ruleListWidget->count(); i++) + { auto _rule = rules[ruleListWidget->item(i)->text()]; auto ruleJsonObject = GetRootObject(_rule); // Process balancer for a rule - if (_rule.QV2RAY_RULE_USE_BALANCER) { + if (_rule.QV2RAY_RULE_USE_BALANCER) + { // Do not use outbound tag. ruleJsonObject.remove("outboundTag"); // Find balancer list - if (!balancers.contains(_rule.balancerTag)) { - LOG(MODULE_UI, "Cannot find a balancer for tag: " + _rule.balancerTag) - } else { + if (!balancers.contains(_rule.balancerTag)) { LOG(MODULE_UI, "Cannot find a balancer for tag: " + _rule.balancerTag) } + else + { auto _balancerList = balancers[_rule.balancerTag]; QJsonObject balancerEntry; balancerEntry["tag"] = _rule.balancerTag; @@ -298,13 +334,9 @@ CONFIGROOT RouteEditor::OpenEditor() } // Remove some empty fields. - if (_rule.port.isEmpty()) { - ruleJsonObject.remove("port"); - } + if (_rule.port.isEmpty()) { ruleJsonObject.remove("port"); } - if (_rule.network.isEmpty()) { - ruleJsonObject.remove("network"); - } + if (_rule.network.isEmpty()) { ruleJsonObject.remove("network"); } rulesArray.append(ruleJsonObject); } @@ -318,22 +350,25 @@ CONFIGROOT RouteEditor::OpenEditor() QJsonArray _outbounds; // Convert our internal data format to QJsonArray - for (auto x : inbounds) { - if (x.isEmpty()) - continue; + for (auto x : inbounds) + { + if (x.isEmpty()) continue; _inbounds.append(x.raw()); } - for (auto x : outbounds) { - if (x.isEmpty()) - continue; + for (auto x : outbounds) + { + if (x.isEmpty()) continue; - if (getTag(x) == defaultOutbound) { + if (getTag(x) == defaultOutbound) + { LOG(MODULE_CONNECTION, "Pushing default outbound to the front.") // Put the default outbound to the first. _outbounds.push_front(x.raw()); - } else { + } + else + { _outbounds.push_back(x.raw()); } } @@ -342,7 +377,9 @@ CONFIGROOT RouteEditor::OpenEditor() root["outbounds"] = _outbounds; root["routing"] = routing; return root; - } else { + } + else + { return original; } } @@ -355,18 +392,22 @@ RouteEditor::~RouteEditor() disconnect(nodeScene, &FlowScene::connectionCreated, this, &RouteEditor::onConnectionCreated); disconnect(nodeScene, &FlowScene::nodeClicked, this, &RouteEditor::onNodeClicked); } -void RouteEditor::on_buttonBox_accepted() {} +void RouteEditor::on_buttonBox_accepted() +{ +} void RouteEditor::ShowCurrentRuleDetail() { LOADINGCHECK - if (currentRuleTag.isEmpty()) { + if (currentRuleTag.isEmpty()) + { LOG(MODULE_UI, "WARNING, trying to access a non-exist rule entry. return.") return; } - if (!rules.contains(currentRuleTag)) { + if (!rules.contains(currentRuleTag)) + { QvMessageBoxWarn(this, tr("Show rule details"), tr("A rule cannot be found: ") + currentRuleTag); LOG(MODULE_UI, "WARNING, trying to access a non-exist rule entry. return.") return; @@ -384,16 +425,15 @@ void RouteEditor::ShowCurrentRuleDetail() balancerSelectionCombo->clear(); // BUG added the wrong items, should be outbound list. - for (auto out : outbounds) { - balancerSelectionCombo->addItem((out)["tag"].toString()); - } + for (auto out : outbounds) { balancerSelectionCombo->addItem((out)["tag"].toString()); } // // Balancers combo and balancer list. enableBalancerCB->setChecked(CurrentRule.QV2RAY_RULE_USE_BALANCER); balancersWidget->setEnabled(CurrentRule.QV2RAY_RULE_USE_BALANCER); - if (!CurrentRule.balancerTag.isEmpty()) { + if (!CurrentRule.balancerTag.isEmpty()) + { balancerList->clear(); balancerList->addItems(balancers[CurrentRule.balancerTag]); } @@ -490,12 +530,15 @@ void RouteEditor::on_balancerAddBtn_clicked() LOADINGCHECK auto balancerTx = balancerSelectionCombo->currentText(); - if (!balancerTx.isEmpty()) { + if (!balancerTx.isEmpty()) + { this->balancers[CurrentRule.balancerTag].append(balancerSelectionCombo->currentText()); balancerList->addItem(balancerTx); balancerSelectionCombo->setEditText(""); statusLabel->setText(tr("OK")); - } else { + } + else + { statusLabel->setText(tr("Balancer is empty, not processing.")); } } @@ -503,9 +546,7 @@ void RouteEditor::on_balancerDelBtn_clicked() { LOADINGCHECK - if (balancerList->currentRow() < 0) { - return; - } + if (balancerList->currentRow() < 0) { return; } balancers[CurrentRule.balancerTag].removeAt(balancerList->currentRow()); balancerList->takeItem(balancerList->currentRow()); @@ -568,7 +609,8 @@ void RouteEditor::on_enableBalancerCB_stateChanged(int arg1) CurrentRule.QV2RAY_RULE_USE_BALANCER = useBalancer; balancersWidget->setEnabled(useBalancer); - if (CurrentRule.balancerTag.isEmpty()) { + if (CurrentRule.balancerTag.isEmpty()) + { LOG(MODULE_UI, "Creating a new balancer tag.") CurrentRule.balancerTag = GenerateRandomString(6); balancers[CurrentRule.balancerTag] = QStringList(); @@ -576,16 +618,18 @@ void RouteEditor::on_enableBalancerCB_stateChanged(int arg1) DEBUG(MODULE_UI, "Balancer: " + CurrentRule.balancerTag) - if (useBalancer) { + if (useBalancer) + { LOG(MODULE_UI, "A rule has been set to use balancer, disconnect it to any outbound.") auto ruleNode = ruleNodes[currentRuleTag]; - for (auto &&[_, conn] : nodeScene->connections()) { - if (conn.get()->getNode(PortType::Out) == ruleNode) { - nodeScene->deleteConnection(*conn); - } + for (auto &&[_, conn] : nodeScene->connections()) + { + if (conn.get()->getNode(PortType::Out) == ruleNode) { nodeScene->deleteConnection(*conn); } } - } else { + } + else + { QvMessageBoxWarn(this, tr("Route Editor"), tr("To make this rule ready to use, you need to connect it to an outbound node.")); } } @@ -597,8 +641,7 @@ void RouteEditor::on_addDefaultBtn_clicked() auto _Inconfig = GlobalConfig.inboundConfig; // auto _in_httpConf = GenerateHTTPIN(QList() << _Inconfig.httpAccount); - auto _in_socksConf = GenerateSocksIN((_Inconfig.socks_useAuth ? "password" : "noauth"), - QList() << _Inconfig.socksAccount, + auto _in_socksConf = GenerateSocksIN((_Inconfig.socks_useAuth ? "password" : "noauth"), QList() << _Inconfig.socksAccount, _Inconfig.socksUDP, _Inconfig.socksLocalIP); // auto _in_HTTP = GenerateInboundEntry(_Inconfig.listenip, _Inconfig.http_port, "http", _in_httpConf, "HTTP_gConf"); @@ -622,9 +665,7 @@ void RouteEditor::on_addInboundBtn_clicked() InboundEditor w(INBOUND(), this); auto _result = w.OpenEditor(); - if (w.result() == QDialog::Accepted) { - AddInbound(_result); - } + if (w.result() == QDialog::Accepted) { AddInbound(_result); } CHECKEMPTYRULES } @@ -635,19 +676,17 @@ void RouteEditor::on_addOutboundBtn_clicked() // True here for not keep the inbounds. auto configs = w.OpenImport(true); - for (auto i = 0; i < configs.count(); i++) { + for (auto i = 0; i < configs.count(); i++) + { auto conf = configs.values()[i]; auto name = configs.key(conf, ""); - if (name.isEmpty()) - continue; + if (name.isEmpty()) continue; // conf is rootObject, needs to unwrap it. auto confList = conf["outbounds"].toArray(); - for (int i = 0; i < confList.count(); i++) { - AddOutbound(OUTBOUND(confList[i].toObject())); - } + for (int i = 0; i < confList.count(); i++) { AddOutbound(OUTBOUND(confList[i].toObject())); } } CHECKEMPTYRULES @@ -661,7 +700,8 @@ void RouteEditor::on_ruleEnableCB_stateChanged(int arg1) } void RouteEditor::on_delBtn_clicked() { - if (nodeScene->selectedNodes().empty()) { + if (nodeScene->selectedNodes().empty()) + { QvMessageBoxWarn(this, tr("Remove Items"), tr("Please select a node from the graph to continue.")); return; } @@ -671,40 +711,46 @@ void RouteEditor::on_delBtn_clicked() auto isOutbound = outboundNodes.values().contains(firstNode); auto isRule = ruleNodes.values().contains(firstNode); - // Get the tag first, and call inbounds/outbounds/rules container variable remove() - // Remove the node last since some events may trigger. - // Then remove the node container. - if (isInbound) { + // Get the tag first, and call inbounds/outbounds/rules container variable + // remove() Remove the node last since some events may trigger. Then remove + // the node container. + if (isInbound) + { currentInboundOutboundTag = GetFirstNodeData(*firstNode, QvInboundNodeModel, InboundNodeData)->GetInbound(); nodeScene->removeNode(*inboundNodes[currentInboundOutboundTag]); inboundNodes.remove(currentInboundOutboundTag); // Remove corresponded inbound tags from the rules. - for (auto k : rules.keys()) { + for (auto k : rules.keys()) + { auto v = rules[k]; v.inboundTag.removeAll(currentInboundOutboundTag); rules[k] = v; } inbounds.remove(currentInboundOutboundTag); - } else if (isOutbound) { + } + else if (isOutbound) + { currentInboundOutboundTag = GetFirstNodeData(*firstNode, QvOutboundNodeModel, OutboundNodeData)->GetOutbound(); outbounds.remove(currentInboundOutboundTag); ResolveDefaultOutboundTag(currentInboundOutboundTag, ""); // Remove corresponded outbound tags from the rules. - for (auto k : rules.keys()) { + for (auto k : rules.keys()) + { auto v = rules[k]; - if (v.outboundTag == currentInboundOutboundTag) - v.outboundTag.clear(); + if (v.outboundTag == currentInboundOutboundTag) v.outboundTag.clear(); rules[k] = v; } nodeScene->removeNode(*outboundNodes[currentInboundOutboundTag]); outboundNodes.remove(currentInboundOutboundTag); - } else if (isRule) { + } + else if (isRule) + { ruleEnableCB->setEnabled(false); ruleTagLineEdit->setEnabled(false); ruleRenameBtn->setEnabled(false); @@ -719,27 +765,30 @@ void RouteEditor::on_delBtn_clicked() // Remove item from the rule order list widget. ruleListWidget->takeItem(ruleListWidget->row(ruleListWidget->findItems(RuleTag, Qt::MatchExactly).first())); CHECKEMPTYRULES - //currentRuleTag = rules.firstKey(); - //ShowCurrentRuleDetail(); - } else { + // currentRuleTag = rules.firstKey(); + // ShowCurrentRuleDetail(); + } + else + { LOG(MODULE_UI, "Unknown node selected.") QvMessageBoxWarn(this, tr("Error"), tr("Qv2ray entered an unknown state.")); } } void RouteEditor::on_editBtn_clicked() { - if (nodeScene->selectedNodes().empty()) { - QvMessageBoxWarn(this, tr("Edit Inbound/Outbound"), tr("Please select a node from the graph to continue.")); - } + if (nodeScene->selectedNodes().empty()) + { QvMessageBoxWarn(this, tr("Edit Inbound/Outbound"), tr("Please select a node from the graph to continue.")); } auto firstNode = nodeScene->selectedNodes().at(0); auto isInbound = inboundNodes.values().contains(firstNode); auto isOutbound = outboundNodes.values().contains(firstNode); - if (isInbound) { + if (isInbound) + { currentInboundOutboundTag = GetFirstNodeData(*firstNode, QvInboundNodeModel, InboundNodeData)->GetInbound(); - if (!inbounds.contains(currentInboundOutboundTag)) { + if (!inbounds.contains(currentInboundOutboundTag)) + { QvMessageBoxWarn(this, tr("Edit Inbound"), tr("No inbound tag found: ") + currentInboundOutboundTag); return; } @@ -749,14 +798,18 @@ void RouteEditor::on_editBtn_clicked() auto protocol = _in["protocol"].toString(); int _code; - if (protocol != "http" && protocol != "mtproto" && protocol != "socks" && protocol != "dokodemo-door") { - QvMessageBoxWarn(this, tr("Cannot Edit"), tr("Currently, this type of outbound is not supported by the editor.") + "\r\n" + - tr("We will launch Json Editor instead.")); + if (protocol != "http" && protocol != "mtproto" && protocol != "socks" && protocol != "dokodemo-door") + { + QvMessageBoxWarn(this, tr("Cannot Edit"), + tr("Currently, this type of outbound is not supported by the editor.") + "\r\n" + + tr("We will launch Json Editor instead.")); statusLabel->setText(tr("Opening JSON editor")); JsonEditor w(_in, this); _result = INBOUND(w.OpenEditor()); _code = w.result(); - } else { + } + else + { InboundEditor w(_in, this); statusLabel->setText(tr("Opening default inbound editor")); _result = w.OpenEditor(); @@ -765,22 +818,24 @@ void RouteEditor::on_editBtn_clicked() statusLabel->setText(tr("OK")); - if (_code == QDialog::Accepted) { + if (_code == QDialog::Accepted) + { bool isTagChanged = getTag(_in) != getTag(_result); - if (isTagChanged) { - RenameItemTag(RENAME_INBOUND, getTag(_in), getTag(_result)); - } + if (isTagChanged) { RenameItemTag(RENAME_INBOUND, getTag(_in), getTag(_result)); } DEBUG(MODULE_UI, "Removed old tag: " + getTag(_in)) inbounds.remove(getTag(_in)); DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result)) inbounds[getTag(_result)] = _result; } - } else if (isOutbound) { + } + else if (isOutbound) + { currentInboundOutboundTag = GetFirstNodeData(*firstNode, QvOutboundNodeModel, OutboundNodeData)->GetOutbound(); - if (!outbounds.contains(currentInboundOutboundTag)) { + if (!outbounds.contains(currentInboundOutboundTag)) + { QvMessageBoxWarn(this, tr("Edit Inbound"), tr("No inbound tag found: ") + currentInboundOutboundTag); return; } @@ -790,25 +845,30 @@ void RouteEditor::on_editBtn_clicked() auto protocol = _out["protocol"].toString().toLower(); int _code; - if (protocol != "vmess" && protocol != "shadowsocks" && protocol != "socks") { + if (protocol != "vmess" && protocol != "shadowsocks" && protocol != "socks") + { QvMessageBoxWarn(this, tr("Unsupported Outbound Type"), tr("This outbound entry is not supported by the GUI editor.") + NEWLINE + - tr("We will launch Json Editor instead.")); + tr("We will launch Json Editor instead.")); JsonEditor w(_out, this); statusLabel->setText(tr("Opening JSON editor")); _result = OUTBOUND(w.OpenEditor()); _code = w.result(); - } else { + } + else + { OutboundEditor w(_out, this); statusLabel->setText(tr("Opening default outbound editor.")); _result = w.OpenEditor(); _code = w.result(); } - if (_code == QDialog::Accepted) { + if (_code == QDialog::Accepted) + { bool isTagChanged = getTag(_out) != getTag(_result); - if (isTagChanged) { + if (isTagChanged) + { DEBUG(MODULE_UI, "Outbound tag is changed: " + QString(isTagChanged)) RenameItemTag(RENAME_OUTBOUND, getTag(_out), getTag(_result)); DEBUG(MODULE_UI, "Removed old tag: " + getTag(_out)) @@ -819,7 +879,9 @@ void RouteEditor::on_editBtn_clicked() outbounds[getTag(_result)] = _result; statusLabel->setText(tr("OK")); } - } else { + } + else + { LOG(MODULE_UI, "Cannot apply 'edit' operation to non-inbound and non-outbound") } } @@ -840,16 +902,23 @@ void RouteEditor::on_ruleRenameBtn_clicked() { auto newTag = ruleTagLineEdit->text(); - if (newTag.isEmpty()) { + if (newTag.isEmpty()) + { LOG(MODULE_UI, "Tag is empty, this is ILLEGAL!") QvMessageBoxWarn(this, tr("Renaming a tag"), tr("New tag is empty, please try another.")); - } else if (newTag == CurrentRule.QV2RAY_RULE_TAG) { + } + else if (newTag == CurrentRule.QV2RAY_RULE_TAG) + { LOG(MODULE_UI, "No tag changed, returning.") QvMessageBoxInfo(this, tr("Renaming a tag"), tr("New tag is the same as the original one.")); - } else if (rules.contains(newTag)) { + } + else if (rules.contains(newTag)) + { LOG(MODULE_UI, "Tag duplicate detected.") QvMessageBoxWarn(this, tr("Renaming a tag"), tr("Duplicate rule tag detected, please try another.")); - } else { + } + else + { RenameItemTag(RENAME_RULE, CurrentRule.QV2RAY_RULE_TAG, newTag); } } diff --git a/src/ui/editors/w_RoutesEditor.hpp b/src/ui/editors/w_RoutesEditor.hpp index 04c0fbbf..9aa52f4d 100644 --- a/src/ui/editors/w_RoutesEditor.hpp +++ b/src/ui/editors/w_RoutesEditor.hpp @@ -1,131 +1,134 @@ #pragma once -#include +#include "ConnectionStyle.hpp" +#include "FlowScene.hpp" +#include "Node.hpp" +#include "NodeData.hpp" +#include "common/QvHelpers.hpp" + #include #include #include #include -#include "common/QvHelpers.hpp" +#include -#include "Node.hpp" -#include "NodeData.hpp" -#include "ConnectionStyle.hpp" -#include "FlowScene.hpp" - -using QtNodes::Node; -using QtNodes::FlowScene; using QtNodes::ConnectionStyle; +using QtNodes::FlowScene; +using QtNodes::Node; -#include "ui_w_RoutesEditor.h" #include "ui/messaging/QvMessageBus.hpp" +#include "ui_w_RoutesEditor.h" -enum ROUTE_EDIT_MODE { +enum ROUTE_EDIT_MODE +{ RENAME_INBOUND, RENAME_OUTBOUND, RENAME_RULE, }; -class RouteEditor : public QDialog, private Ui::RouteEditor +class RouteEditor + : public QDialog + , private Ui::RouteEditor { - Q_OBJECT + Q_OBJECT - public: - explicit RouteEditor(QJsonObject connection, QWidget *parent = nullptr); - ~RouteEditor(); - CONFIGROOT OpenEditor(); - public slots: - QvMessageBusSlotDecl + public: + explicit RouteEditor(QJsonObject connection, QWidget *parent = nullptr); + ~RouteEditor(); + CONFIGROOT OpenEditor(); + public slots: + QvMessageBusSlotDecl; - private slots: - void on_buttonBox_accepted(); + private slots: + void on_buttonBox_accepted(); - void on_insertDirectBtn_clicked(); + void on_insertDirectBtn_clicked(); - void on_routeProtocolHTTPCB_stateChanged(int arg1); + void on_routeProtocolHTTPCB_stateChanged(int arg1); - void on_routeProtocolTLSCB_stateChanged(int arg1); + void on_routeProtocolTLSCB_stateChanged(int arg1); - void on_routeProtocolBTCB_stateChanged(int arg1); + void on_routeProtocolBTCB_stateChanged(int arg1); - void on_balancerAddBtn_clicked(); + void on_balancerAddBtn_clicked(); - void on_balancerDelBtn_clicked(); + void on_balancerDelBtn_clicked(); - void on_hostList_textChanged(); + void on_hostList_textChanged(); - void on_ipList_textChanged(); + void on_ipList_textChanged(); - void on_routePortTxt_textEdited(const QString &arg1); + void on_routePortTxt_textEdited(const QString &arg1); - void on_routeUserTxt_textEdited(const QString &arg1); + void on_routeUserTxt_textEdited(const QString &arg1); - void on_addRouteBtn_clicked(); + void on_addRouteBtn_clicked(); - void on_netBothRB_clicked(); + void on_netBothRB_clicked(); - void on_netUDPRB_clicked(); + void on_netUDPRB_clicked(); - void on_netTCPRB_clicked(); + void on_netTCPRB_clicked(); - void on_routeUserTxt_textChanged(); + void on_routeUserTxt_textChanged(); - void on_sourceIPList_textChanged(); + void on_sourceIPList_textChanged(); - void on_enableBalancerCB_stateChanged(int arg1); + void on_enableBalancerCB_stateChanged(int arg1); - void on_addDefaultBtn_clicked(); + void on_addDefaultBtn_clicked(); - void on_insertBlackBtn_clicked(); + void on_insertBlackBtn_clicked(); - void on_addInboundBtn_clicked(); + void on_addInboundBtn_clicked(); - void on_addOutboundBtn_clicked(); + void on_addOutboundBtn_clicked(); - void on_ruleEnableCB_stateChanged(int arg1); + void on_ruleEnableCB_stateChanged(int arg1); - void on_delBtn_clicked(); + void on_delBtn_clicked(); - void on_editBtn_clicked(); + void on_editBtn_clicked(); - void on_domainStrategyCombo_currentIndexChanged(const QString &arg1); + void on_domainStrategyCombo_currentIndexChanged(const QString &arg1); - void on_defaultOutboundCombo_currentIndexChanged(const QString &arg1); + void on_defaultOutboundCombo_currentIndexChanged(const QString &arg1); - void on_ruleRenameBtn_clicked(); + void on_ruleRenameBtn_clicked(); - public slots: - void onNodeClicked(QtNodes::Node &n); - void onConnectionCreated(QtNodes::Connection const &c); - void onConnectionDeleted(QtNodes::Connection const &c); + public slots: + void onNodeClicked(QtNodes::Node &n); + void onConnectionCreated(QtNodes::Connection const &c); + void onConnectionDeleted(QtNodes::Connection const &c); - private: - void RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, const QString newTag); - void ShowCurrentRuleDetail(); - // - QString currentRuleTag; - QString currentInboundOutboundTag; - QMap balancers; - QString domainStrategy; - QString defaultOutbound; - // - QMap inbounds; - QMap outbounds; - QMap rules; - // - CONFIGROOT root; - CONFIGROOT original; - // - // ---------------------------- Node Graph Impl -------------------------- - void SetupNodeWidget(); - QMap inboundNodes; - QMap outboundNodes; - QMap ruleNodes; - // - FlowScene *nodeScene; - // ---------------------------- Extra Source File Headers ---------------- - void AddInbound(INBOUND in); - void AddOutbound(OUTBOUND out); - void AddRule(RuleObject rule); - QString AddNewRule(); - void ResolveDefaultOutboundTag(QString original, QString newTag); + private: + void RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, const QString newTag); + void ShowCurrentRuleDetail(); + // + QString currentRuleTag; + QString currentInboundOutboundTag; + QMap balancers; + QString domainStrategy; + QString defaultOutbound; + // + QMap inbounds; + QMap outbounds; + QMap rules; + // + CONFIGROOT root; + CONFIGROOT original; + // + // ---------------------------- Node Graph Impl -------------------------- + void SetupNodeWidget(); + QMap inboundNodes; + QMap outboundNodes; + QMap ruleNodes; + // + FlowScene *nodeScene; + // ---------------------------- Extra Source File Headers ---------------- + void AddInbound(INBOUND in); + void AddOutbound(OUTBOUND out); + void AddRule(RuleObject rule); + QString AddNewRule(); + void ResolveDefaultOutboundTag(QString original, QString newTag); }; diff --git a/src/ui/editors/w_RoutesEditor_extra.cpp b/src/ui/editors/w_RoutesEditor_extra.cpp index 87e8baa6..cd44d994 100644 --- a/src/ui/editors/w_RoutesEditor_extra.cpp +++ b/src/ui/editors/w_RoutesEditor_extra.cpp @@ -1,18 +1,16 @@ // WARNING -// Since it's required for this file to know the content of the macros defined in another CPP file. -// We included an CPP file instead of the proper HPP file. +// Since it's required for this file to know the content of the macros defined +// in another CPP file. We included an CPP file instead of the proper HPP file. #include "w_RoutesEditor.cpp" -// Supplementary source file for Routes editor, basically providing routes-related operations. - +// Supplementary source file for Routes editor, basically providing +// routes-related operations. void RouteEditor::AddInbound(INBOUND in) { QString tag = getTag(in); - if (inbounds.contains(tag)) { - tag = tag + "_" + GenerateRandomString(5); - } + if (inbounds.contains(tag)) { tag = tag + "_" + GenerateRandomString(5); } in["tag"] = tag; auto _nodeData = make_unique(make_shared(tag)); @@ -29,9 +27,7 @@ void RouteEditor::AddOutbound(OUTBOUND out) { QString tag = getTag(out); - if (outbounds.contains(tag)) { - tag = tag + "_" + GenerateRandomString(5); - } + if (outbounds.contains(tag)) { tag = tag + "_" + GenerateRandomString(5); } out["tag"] = tag; auto _nodeData = make_unique(make_shared(tag)); @@ -64,9 +60,7 @@ QString RouteEditor::AddNewRule() void RouteEditor::AddRule(RuleObject rule) { // Prevent duplicate - if (ruleNodes.contains(rule.QV2RAY_RULE_TAG)) { - rule.QV2RAY_RULE_TAG += "-" + GenerateRandomString(5); - } + if (ruleNodes.contains(rule.QV2RAY_RULE_TAG)) { rule.QV2RAY_RULE_TAG += "-" + GenerateRandomString(5); } rules[rule.QV2RAY_RULE_TAG] = rule; auto pos = nodeGraphWidget->pos(); @@ -76,25 +70,34 @@ void RouteEditor::AddRule(RuleObject rule) auto &node = nodeScene->createNode(std::move(_nodeData)); nodeScene->setNodePosition(node, pos); - for (auto inTag : rule.inboundTag) { - if (!inboundNodes.contains(inTag)) { + for (auto inTag : rule.inboundTag) + { + if (!inboundNodes.contains(inTag)) + { LOG(MODULE_UI, "No inbound tag found for rule: " + rule.QV2RAY_RULE_TAG + ", inbound tag: " + inTag) QvMessageBoxWarn(this, tr("No Inbound"), tr("No inbound item found: ") + inTag); rule.inboundTag.removeAll(inTag); - } else { + } + else + { auto inboundNode = inboundNodes[inTag]; nodeScene->createConnection(node, 0, *inboundNode, 0); } } // If not using balancers (use outbound tag) - if (!rule.QV2RAY_RULE_USE_BALANCER) { - if (outboundNodes.contains(rule.outboundTag)) { + if (!rule.QV2RAY_RULE_USE_BALANCER) + { + if (outboundNodes.contains(rule.outboundTag)) + { DEBUG(MODULE_GRAPH, "Found outbound tag: " + rule.outboundTag + ", for rule: " + rule.QV2RAY_RULE_TAG) nodeScene->createConnection(*outboundNodes[rule.outboundTag], 0, node, 0); - } else { + } + else + { LOG(MODULE_GRAPH, "Outbound tag not found: " + rule.outboundTag + ", for: " + rule.QV2RAY_RULE_TAG) - //QvMessageBoxWarn(this, tr("No outbound tag"), tr("Please connect the rule with an outbound.")); + // QvMessageBoxWarn(this, tr("No outbound tag"), tr("Please connect + // the rule with an outbound.")); } } @@ -105,19 +108,20 @@ void RouteEditor::AddRule(RuleObject rule) // Do not use reference here, we need deep void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, QString newTag) { - switch (mode) { + switch (mode) + { case RENAME_RULE: - if (rules.contains(originalTag) && ruleNodes.contains(originalTag)) { - if (rules.contains(newTag) && rules.contains(newTag)) { + if (rules.contains(originalTag) && ruleNodes.contains(originalTag)) + { + if (rules.contains(newTag) && rules.contains(newTag)) + { QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a postfix.")); newTag += "_" + GenerateRandomString(5); } auto node = static_cast(ruleNodes[originalTag]->nodeDataModel()); - if (node == nullptr) { - LOG(MODULE_GRAPH, "EMPTY NODE WARN") - } + if (node == nullptr) { LOG(MODULE_GRAPH, "EMPTY NODE WARN") } node->setData(newTag); // @@ -125,27 +129,30 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, rules[newTag].QV2RAY_RULE_TAG = newTag; ruleNodes[newTag] = ruleNodes.take(originalTag); // - // No other operation needed, but need to rename the one in the ruleOrder list widget. + // No other operation needed, but need to rename the one in the + // ruleOrder list widget. auto items = ruleListWidget->findItems(originalTag, Qt::MatchExactly); - if (items.isEmpty()) { - LOG(MODULE_UI, "Cannot find a node: " + originalTag) - } else { + if (items.isEmpty()) { LOG(MODULE_UI, "Cannot find a node: " + originalTag) } + else + { items.first()->setText(newTag); } - if (currentRuleTag == originalTag) { - currentRuleTag = newTag; - } - } else { + if (currentRuleTag == originalTag) { currentRuleTag = newTag; } + } + else + { LOG(MODULE_UI, "There's nothing match " + originalTag + " in the containers.") } break; case RENAME_OUTBOUND: - if (outbounds.contains(originalTag) && outboundNodes.contains(originalTag)) { - if (outbounds.contains(newTag) && outboundNodes.contains(newTag)) { + if (outbounds.contains(originalTag) && outboundNodes.contains(originalTag)) + { + if (outbounds.contains(newTag) && outboundNodes.contains(newTag)) + { QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a postfix.")); newTag += "_" + GenerateRandomString(5); } @@ -154,34 +161,39 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, outboundNodes[newTag] = outboundNodes.take(originalTag); auto node = static_cast(outboundNodes[newTag]->nodeDataModel()); - if (node == nullptr) { - LOG(MODULE_GRAPH, "EMPTY NODE WARN") - } + if (node == nullptr) { LOG(MODULE_GRAPH, "EMPTY NODE WARN") } node->setData(newTag); // Change outbound tag in rules accordingly. - for (auto k : rules.keys()) { + for (auto k : rules.keys()) + { auto v = rules[k]; - if (v.outboundTag == originalTag) { + if (v.outboundTag == originalTag) + { v.outboundTag = newTag; - // Put this inside the if block since no need an extra operation if the condition is false. + // Put this inside the if block since no need an extra + // operation if the condition is false. rules[k] = v; } } // Resolve default outbound. ResolveDefaultOutboundTag(originalTag, newTag); - } else { + } + else + { LOG(MODULE_UI, "Failed to rename an outbound --> Item not found.") } break; case RENAME_INBOUND: - if (inbounds.contains(originalTag) && inboundNodes.contains(originalTag)) { - if (inbounds.contains(newTag) && inboundNodes.contains(newTag)) { + if (inbounds.contains(originalTag) && inboundNodes.contains(originalTag)) + { + if (inbounds.contains(newTag) && inboundNodes.contains(newTag)) + { QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a postfix.")); newTag += "_" + GenerateRandomString(5); } @@ -190,26 +202,29 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, inboundNodes[newTag] = inboundNodes.take(originalTag); auto node = static_cast(inboundNodes[newTag]->nodeDataModel()); - if (node == nullptr) { - LOG(MODULE_GRAPH, "EMPTY NODE WARN") - } + if (node == nullptr) { LOG(MODULE_GRAPH, "EMPTY NODE WARN") } node->setData(newTag); // Change inbound tag in rules accordingly. // k -> rule tag // v -> rule object - for (auto k : rules.keys()) { + for (auto k : rules.keys()) + { auto v = rules[k]; - if (v.inboundTag.contains(originalTag)) { + if (v.inboundTag.contains(originalTag)) + { v.inboundTag.append(newTag); v.inboundTag.removeAll(originalTag); - // Put this inside the if block since no need an extra operation if the condition is false. + // Put this inside the if block since no need an extra + // operation if the condition is false. rules[k] = v; } } - } else { + } + else + { LOG(MODULE_UI, "Failed to rename an outbound --> Item not found.") } @@ -219,26 +234,31 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, void RouteEditor::ResolveDefaultOutboundTag(QString original, QString newTag) { - LOG(MODULE_UI, "Resolving default outbound settings: default=" + defaultOutbound + " original=" + original + " new=" + newTag) + LOG(MODULE_UI, "Resolving default outbound settings: default=" + defaultOutbound + " original=" + original + " new=" + newTag) auto isDefaultChanged = original == defaultOutbound; defaultOutboundCombo->clear(); defaultOutboundCombo->addItems(outbounds.keys()); - if (!isDefaultChanged) { + if (!isDefaultChanged) + { LOG(MODULE_UI, "Default outbound is not changed: retaining: " + defaultOutbound) // Just simply restore the default one. defaultOutboundCombo->setCurrentText(defaultOutbound); - } else if (newTag.isEmpty()) { + } + else if (newTag.isEmpty()) + { LOG(MODULE_UI, "Default outbound is removed, using first key from the outbounds as the default one.") // Removed the default one, so set the first one as the default. - if (outbounds.isEmpty()) { - defaultOutbound.clear(); - } else { + if (outbounds.isEmpty()) { defaultOutbound.clear(); } + else + { defaultOutbound = getTag(outbounds.first()); defaultOutboundCombo->addItem(outbounds.firstKey()); } - } else { + } + else + { LOG(MODULE_UI, "Default outbound is renamed, ") defaultOutboundCombo->setCurrentText(newTag); defaultOutbound = newTag; diff --git a/src/ui/messaging/QvMessageBus.cpp b/src/ui/messaging/QvMessageBus.cpp index 122d4314..5b2514a4 100644 --- a/src/ui/messaging/QvMessageBus.cpp +++ b/src/ui/messaging/QvMessageBus.cpp @@ -1,8 +1,9 @@ -#include - #include "QvMessageBus.hpp" + #include "base/Qv2rayBase.hpp" +#include + namespace Qv2ray::ui::messaging { QvMessageBusObject::QvMessageBusObject() @@ -15,4 +16,4 @@ namespace Qv2ray::ui::messaging LOG(MODULE_MESSAGING, "Emitting signal: " + QString(metaEnum.valueToKey(msg))); emit QvSendMessage(msg); } -} +} // namespace Qv2ray::ui::messaging diff --git a/src/ui/messaging/QvMessageBus.hpp b/src/ui/messaging/QvMessageBus.hpp index ca36fd69..4ef11e91 100644 --- a/src/ui/messaging/QvMessageBus.hpp +++ b/src/ui/messaging/QvMessageBus.hpp @@ -6,28 +6,27 @@ #define QvMessageBusSlotSig const QvMBMessage &msg #define QvMessageBusSlotIdentifier on_QvMessageReceived -#define QvMessageBusSlotDecl void QvMessageBusSlotIdentifier(QvMessageBusSlotSig); +#define QvMessageBusSlotDecl void QvMessageBusSlotIdentifier(QvMessageBusSlotSig) #define QvMessageBusSlotImpl(CLASSNAME) void CLASSNAME::QvMessageBusSlotIdentifier(QvMessageBusSlotSig) -#define MBShowDefaultImpl \ - case SHOW_WINDOWS:\ - this->setWindowOpacity(1);\ - break; +#define MBShowDefaultImpl \ + case SHOW_WINDOWS: \ + this->setWindowOpacity(1); \ + break; -#define MBHideDefaultImpl \ - case HIDE_WINDOWS:\ - this->setWindowOpacity(0);\ - break; +#define MBHideDefaultImpl \ + case HIDE_WINDOWS: \ + this->setWindowOpacity(0); \ + break; -#define MBRetranslateDefaultImpl \ - case RETRANSLATE:\ - this->retranslateUi(this);\ - break; +#define MBRetranslateDefaultImpl \ + case RETRANSLATE: this->retranslateUi(this); break; namespace Qv2ray::ui::messaging { Q_NAMESPACE - enum QvMBMessage { + enum QvMBMessage + { /// Show all windows. SHOW_WINDOWS, /// Hide all windows. @@ -43,20 +42,20 @@ namespace Qv2ray::ui::messaging // class QvMessageBusObject : public QObject { - Q_OBJECT - public: - explicit QvMessageBusObject(); + Q_OBJECT + public: + explicit QvMessageBusObject(); - // - void EmitGlobalSignal(const QvMBMessage &msg); - signals: - void QvSendMessage(const QvMBMessage &msg); - //private slots: - // void on_QvMessageReceived(QvMessage msg); + // + void EmitGlobalSignal(const QvMBMessage &msg); + signals: + void QvSendMessage(const QvMBMessage &msg); + // private slots: + // void on_QvMessageReceived(QvMessage msg); }; // Danger, new is used here. Possible memory leak (hope not so much leak) inline QvMessageBusObject messageBus = QvMessageBusObject(); -} +} // namespace Qv2ray::ui::messaging using namespace Qv2ray::ui::messaging; diff --git a/src/ui/models/InboundNodeModel.cpp b/src/ui/models/InboundNodeModel.cpp index c83ba037..caa42543 100644 --- a/src/ui/models/InboundNodeModel.cpp +++ b/src/ui/models/InboundNodeModel.cpp @@ -1,6 +1,6 @@ #include "ui/models/InboundNodeModel.hpp" -QvInboundNodeModel::QvInboundNodeModel(std::shared_ptr data): NodeDataModel() +QvInboundNodeModel::QvInboundNodeModel(std::shared_ptr data) : NodeDataModel() { _in = data; _label = new QLabel(); diff --git a/src/ui/models/InboundNodeModel.hpp b/src/ui/models/InboundNodeModel.hpp index 472bd410..fac642d4 100644 --- a/src/ui/models/InboundNodeModel.hpp +++ b/src/ui/models/InboundNodeModel.hpp @@ -1,68 +1,72 @@ #pragma once -#include #include "ui/models/NodeModelsBase.hpp" +#include + class QvInboundNodeModel : public NodeDataModel { - Q_OBJECT - public: - explicit QvInboundNodeModel(std::shared_ptr data); - ~QvInboundNodeModel() - { - //if (_label) { - // delete _label; - //} - } + Q_OBJECT + public: + explicit QvInboundNodeModel(std::shared_ptr data); + ~QvInboundNodeModel() + { + // if (_label) { + // delete _label; + //} + } - QString caption() const override - { - return "Nothing"; - } + QString caption() const override + { + return "Nothing"; + } - bool captionVisible() const override - { - return false; - } + bool captionVisible() const override + { + return false; + } - unsigned int nPorts(PortType portType) const override - { - return portType == PortType::Out ? 1 : 0; - } + unsigned int nPorts(PortType portType) const override + { + return portType == PortType::Out ? 1 : 0; + } - QString name() const override - { - return "InboundNode"; - } + QString name() const override + { + return "InboundNode"; + } - NodeDataType dataType(PortType portType, PortIndex portIndex) const override - { - Q_UNUSED(portType); - Q_UNUSED(portIndex); - return inboundType; - } + NodeDataType dataType(PortType portType, PortIndex portIndex) const override + { + Q_UNUSED(portType); + Q_UNUSED(portIndex); + return inboundType; + } - std::shared_ptr outData(PortIndex) override - { - return _in; - } + std::shared_ptr outData(PortIndex) override + { + return _in; + } - void setInData(std::shared_ptr, int) override {} - void setData(const QString &data) - { - _in = make_shared(data); - _label->setText(data); - _label->adjustSize(); - } + void setInData(std::shared_ptr, int) override + { + } + void setData(const QString &data) + { + _in = make_shared(data); + _label->setText(data); + _label->adjustSize(); + } - QWidget *embeddedWidget() override - { - return _label; - } - private: - NodeValidationState modelValidationState = NodeValidationState::Warning; - QString modelValidationError = tr("Missing or incorrect inputs"); - // - std::shared_ptr _in; - QLabel *_label; + QWidget *embeddedWidget() override + { + return _label; + } + + private: + NodeValidationState modelValidationState = NodeValidationState::Warning; + QString modelValidationError = tr("Missing or incorrect inputs"); + // + std::shared_ptr _in; + QLabel *_label; }; diff --git a/src/ui/models/NodeModelsBase.hpp b/src/ui/models/NodeModelsBase.hpp index 36d3336b..69b5f204 100644 --- a/src/ui/models/NodeModelsBase.hpp +++ b/src/ui/models/NodeModelsBase.hpp @@ -1,101 +1,99 @@ #pragma once -#include - #include "NodeDataModel.hpp" #include "PortType.hpp" - #include "common/QvHelpers.hpp" -using QtNodes::PortType; -using QtNodes::PortIndex; +#include + using QtNodes::NodeData; -using QtNodes::NodeDataType; using QtNodes::NodeDataModel; -using QtNodes::NodeValidationState; - - using QtNodes::NodeDataType; +using QtNodes::NodeValidationState; +using QtNodes::PortIndex; +using QtNodes::PortType; + using QtNodes::NodeData; +using QtNodes::NodeDataType; const int GRAPH_NODE_LABEL_FONTSIZE_INCREMENT = 3; namespace Qv2ray::ui::nodemodels { - const NodeDataType outboundType = {"outbound", "Outbound Object"}; - const NodeDataType inboundType = {"inbound", "Inbound Object"}; + const NodeDataType outboundType = { "outbound", "Outbound Object" }; + const NodeDataType inboundType = { "inbound", "Inbound Object" }; /// The class can potentially incapsulate any user data /// need to be transferred within the Node Editor graph class InboundNodeData : public NodeData { - public: - InboundNodeData() - { - DEBUG(MODULE_GRAPH, "DANGER: Initialising a data model without value.") - } - InboundNodeData(QString in) : _inboundTag(in) { } + public: + InboundNodeData(){ DEBUG(MODULE_GRAPH, "DANGER: Initialising a data model without value.") } InboundNodeData(QString in) + : _inboundTag(in) + { + } - NodeDataType type() const override - { - return inboundType; - } + NodeDataType type() const override + { + return inboundType; + } - QString GetInbound() - { - return _inboundTag; - } - private: - QString _inboundTag; + QString GetInbound() + { + return _inboundTag; + } + + private: + QString _inboundTag; }; /// The class can potentially incapsulate any user data /// need to be transferred within the Node Editor graph class OutboundNodeData : public NodeData { - public: - OutboundNodeData() : _outboundTag() - { - DEBUG(MODULE_GRAPH, "DANGER: Initialising a data model without value.") - } - OutboundNodeData(QString out) : _outboundTag(out) { } + public: + OutboundNodeData() + : _outboundTag(){ DEBUG(MODULE_GRAPH, "DANGER: Initialising a data model without value.") } OutboundNodeData(QString out) + : _outboundTag(out) + { + } - NodeDataType type() const override - { - return outboundType; - } + NodeDataType type() const override + { + return outboundType; + } - QString GetOutbound() - { - return _outboundTag; - } - private: - QString _outboundTag; + QString GetOutbound() + { + return _outboundTag; + } + + private: + QString _outboundTag; }; /// The class can potentially incapsulate any user data /// need to be transferred within the Node Editor graph class RuleNodeData : public NodeData { - public: - RuleNodeData() : _ruleTag() - { - DEBUG(MODULE_GRAPH, "DANGER: Initialising a data model without value.") - } - RuleNodeData(QString out) : _ruleTag(out) { } + public: + RuleNodeData() + : _ruleTag(){ DEBUG(MODULE_GRAPH, "DANGER: Initialising a data model without value.") } RuleNodeData(QString out) : _ruleTag(out) + { + } - NodeDataType type() const override - { - return outboundType; - } + NodeDataType type() const override + { + return outboundType; + } - QString GetRuleTag() - { - return _ruleTag; - } - private: - QString _ruleTag; + QString GetRuleTag() + { + return _ruleTag; + } + + private: + QString _ruleTag; }; -} - +} // namespace Qv2ray::ui::nodemodels using namespace Qv2ray::ui::nodemodels; diff --git a/src/ui/models/OutboundNodeModel.cpp b/src/ui/models/OutboundNodeModel.cpp index a73d87a7..37f6ee80 100644 --- a/src/ui/models/OutboundNodeModel.cpp +++ b/src/ui/models/OutboundNodeModel.cpp @@ -1,6 +1,6 @@ #include "ui/models/OutboundNodeModel.hpp" -QvOutboundNodeModel::QvOutboundNodeModel(std::shared_ptr data): NodeDataModel() +QvOutboundNodeModel::QvOutboundNodeModel(std::shared_ptr data) : NodeDataModel() { _out = data; _label = new QLabel(); diff --git a/src/ui/models/OutboundNodeModel.hpp b/src/ui/models/OutboundNodeModel.hpp index 1a23a985..d1e9ce2a 100644 --- a/src/ui/models/OutboundNodeModel.hpp +++ b/src/ui/models/OutboundNodeModel.hpp @@ -1,74 +1,80 @@ #pragma once -#include #include "ui/models/NodeModelsBase.hpp" +#include + class QvOutboundNodeModel : public NodeDataModel { - Q_OBJECT - public: - explicit QvOutboundNodeModel(std::shared_ptr data); - ~QvOutboundNodeModel() - { - //if (_label) { - // delete _label; - //} - } + Q_OBJECT + public: + explicit QvOutboundNodeModel(std::shared_ptr data); + ~QvOutboundNodeModel() + { + // if (_label) { + // delete _label; + //} + } - QString caption() const override - { - return "Nothing"; - } + QString caption() const override + { + return "Nothing"; + } - bool captionVisible() const override - { - return false; - } + bool captionVisible() const override + { + return false; + } - unsigned int nPorts(PortType portType) const override - { - return portType == PortType::In ? 1 : 0; - } + unsigned int nPorts(PortType portType) const override + { + return portType == PortType::In ? 1 : 0; + } - QString name() const override - { - return "OutboundNode"; - } + QString name() const override + { + return "OutboundNode"; + } - NodeDataType dataType(PortType portType, PortIndex portIndex) const override - { - Q_UNUSED(portType); - Q_UNUSED(portIndex); - return outboundType; - } + NodeDataType dataType(PortType portType, PortIndex portIndex) const override + { + Q_UNUSED(portType); + Q_UNUSED(portIndex); + return outboundType; + } - std::shared_ptr outData(PortIndex) override - { - return _out; - } + std::shared_ptr outData(PortIndex) override + { + return _out; + } - void setInData(shared_ptr, int) override {} + void setInData(shared_ptr, int) override + { + } - void setInData(vector>, int) override {} - void setData(const QString &data) - { - _out = make_shared(data); - _label->setText(_out->GetOutbound()); - _label->adjustSize(); - } + void setInData(vector>, int) override + { + } + void setData(const QString &data) + { + _out = make_shared(data); + _label->setText(_out->GetOutbound()); + _label->adjustSize(); + } - QWidget *embeddedWidget() override - { - return _label; - } + QWidget *embeddedWidget() override + { + return _label; + } - ConnectionPolicy portInConnectionPolicy(PortIndex) const override - { - return ConnectionPolicy::Many; - } - private: - NodeValidationState modelValidationState = NodeValidationState::Warning; - QString modelValidationError = tr("Missing or incorrect inputs"); - // - std::shared_ptr _out; - QLabel *_label; + ConnectionPolicy portInConnectionPolicy(PortIndex) const override + { + return ConnectionPolicy::Many; + } + + private: + NodeValidationState modelValidationState = NodeValidationState::Warning; + QString modelValidationError = tr("Missing or incorrect inputs"); + // + std::shared_ptr _out; + QLabel *_label; }; diff --git a/src/ui/models/RuleNodeModel.cpp b/src/ui/models/RuleNodeModel.cpp index f62c02ab..8d668ca3 100644 --- a/src/ui/models/RuleNodeModel.cpp +++ b/src/ui/models/RuleNodeModel.cpp @@ -1,6 +1,6 @@ #include "ui/models/RuleNodeModel.hpp" -QvRuleNodeDataModel::QvRuleNodeDataModel(std::shared_ptr data): NodeDataModel() +QvRuleNodeDataModel::QvRuleNodeDataModel(std::shared_ptr data) : NodeDataModel() { _ruleTag = data; _label = new QLabel(); diff --git a/src/ui/models/RuleNodeModel.hpp b/src/ui/models/RuleNodeModel.hpp index bf75fa2b..4f27eb0b 100644 --- a/src/ui/models/RuleNodeModel.hpp +++ b/src/ui/models/RuleNodeModel.hpp @@ -1,98 +1,103 @@ #pragma once -#include #include "ui/models/NodeModelsBase.hpp" +#include + class QvRuleNodeDataModel : public NodeDataModel { - Q_OBJECT - public: - QvRuleNodeDataModel(std::shared_ptr data); - ~QvRuleNodeDataModel() + Q_OBJECT + public: + QvRuleNodeDataModel(std::shared_ptr data); + ~QvRuleNodeDataModel() + { + // if (_label) { + // delete _label; + //} + } + + QString caption() const override + { + return "Nothing"; + } + + bool captionVisible() const override + { + return false; + } + + unsigned int nPorts(PortType portType) const override + { + if (portType == PortType::In) { return 1; } + else if (portType == PortType::Out) { - //if (_label) { - // delete _label; - //} + return 1; + } + else + { + return 0; + } + } + + QString name() const override + { + return "RuleNode"; + } + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override + { + Q_UNUSED(portIndex) + + switch (portType) + { + case PortType::In: return inboundType; + + case PortType::Out: return outboundType; + + case PortType::None: break; } - QString caption() const override - { - return "Nothing"; - } + return NodeDataType(); + } - bool captionVisible() const override - { - return false; - } + std::shared_ptr outData(PortIndex port) override + { + Q_UNUSED(port) + return _ruleTag; + } - unsigned int nPorts(PortType portType) const override - { - if (portType == PortType::In) { - return 1; - } else if (portType == PortType::Out) { - return 1; - } else { - return 0; - } - } + void setInData(std::shared_ptr, int) override + { + } + void setInData(vector>, int) override + { + } + void setData(const QString &data) + { + _ruleTag = make_shared(data); + _label->setText(_ruleTag->GetRuleTag()); + _label->adjustSize(); + } - QString name() const override - { - return "RuleNode"; - } + QWidget *embeddedWidget() override + { + return _label; + } - NodeDataType dataType(PortType portType, PortIndex portIndex) const override - { - Q_UNUSED(portIndex) + ConnectionPolicy portInConnectionPolicy(PortIndex) const override + { + return ConnectionPolicy::Many; + } - switch (portType) { - case PortType::In: - return inboundType; + ConnectionPolicy portOutConnectionPolicy(PortIndex) const override + { + return ConnectionPolicy::One; + } - case PortType::Out: - return outboundType; - - case PortType::None: - break; - } - - return NodeDataType(); - } - - std::shared_ptr outData(PortIndex port) override - { - Q_UNUSED(port) - return _ruleTag; - } - - void setInData(std::shared_ptr, int) override {} - void setInData(vector>, int) override {} - void setData(const QString &data) - { - _ruleTag = make_shared(data); - _label->setText(_ruleTag->GetRuleTag()); - _label->adjustSize(); - } - - QWidget *embeddedWidget() override - { - return _label; - } - - ConnectionPolicy portInConnectionPolicy(PortIndex) const override - { - return ConnectionPolicy::Many; - } - - ConnectionPolicy portOutConnectionPolicy(PortIndex) const override - { - return ConnectionPolicy::One; - } - - private: - NodeValidationState modelValidationState = NodeValidationState::Warning; - QString modelValidationError = tr("Missing or incorrect inputs"); - // - shared_ptr _ruleTag; - QLabel *_label; + private: + NodeValidationState modelValidationState = NodeValidationState::Warning; + QString modelValidationError = tr("Missing or incorrect inputs"); + // + shared_ptr _ruleTag; + QLabel *_label; }; diff --git a/src/ui/w_ExportConfig.cpp b/src/ui/w_ExportConfig.cpp index 9c91f107..fa659aba 100644 --- a/src/ui/w_ExportConfig.cpp +++ b/src/ui/w_ExportConfig.cpp @@ -1,12 +1,11 @@ #include "w_ExportConfig.hpp" #include "common/QvHelpers.hpp" #include "core/connection/Serialization.hpp" + #include // Private initialiser -ConfigExporter::ConfigExporter(QWidget *parent) : - QDialog(parent), - qzxing(this) +ConfigExporter::ConfigExporter(QWidget *parent) : QDialog(parent), qzxing(this) { setupUi(this); QvMessageBusConnect(ConfigExporter); @@ -14,10 +13,9 @@ ConfigExporter::ConfigExporter(QWidget *parent) : QvMessageBusSlotImpl(ConfigExporter) { - switch (msg) { - MBShowDefaultImpl - MBHideDefaultImpl - MBRetranslateDefaultImpl + switch (msg) + { + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl } } @@ -25,7 +23,7 @@ ConfigExporter::~ConfigExporter() { } -//ConfigExporter::ConfigExporter(QWidget *parent) : ConfigExporter(parent) +// ConfigExporter::ConfigExporter(QWidget *parent) : ConfigExporter(parent) //{ // // WIP // // /auto &x = connection; @@ -49,17 +47,13 @@ void ConfigExporter::changeEvent(QEvent *e) { QDialog::changeEvent(e); - switch (e->type()) { - case QEvent::LanguageChange: - retranslateUi(this); - break; + switch (e->type()) + { + case QEvent::LanguageChange: retranslateUi(this); break; - case QEvent::Resize: - imageLabel->setPixmap(QPixmap::fromImage(image)); - break; + case QEvent::Resize: imageLabel->setPixmap(QPixmap::fromImage(image)); break; - default: - break; + default: break; } } diff --git a/src/ui/w_ExportConfig.hpp b/src/ui/w_ExportConfig.hpp index 4bbf95a9..ffce983a 100644 --- a/src/ui/w_ExportConfig.hpp +++ b/src/ui/w_ExportConfig.hpp @@ -1,32 +1,36 @@ #pragma once -#include "ui_w_ExportConfig.h" -#include "base/Qv2rayBase.hpp" #include "3rdparty/qzxing/src/QZXing.h" +#include "base/Qv2rayBase.hpp" #include "ui/messaging/QvMessageBus.hpp" +#include "ui_w_ExportConfig.h" -class ConfigExporter : public QDialog, private Ui::ExportConfigWindow +class ConfigExporter + : public QDialog + , private Ui::ExportConfigWindow { - Q_OBJECT + Q_OBJECT - public: - explicit ConfigExporter(QWidget *parent = nullptr); - ~ConfigExporter(); - void OpenExport(); - public slots: - QvMessageBusSlotDecl - protected: - void changeEvent(QEvent *e); - private slots: - void on_closeBtn_clicked(); + public: + explicit ConfigExporter(QWidget *parent = nullptr); + ~ConfigExporter(); + void OpenExport(); + public slots: + QvMessageBusSlotDecl; - void on_saveBtn_clicked(); + protected: + void changeEvent(QEvent *e); + private slots: + void on_closeBtn_clicked(); - void on_copyImageBtn_clicked(); + void on_saveBtn_clicked(); - void on_copyVMessBtn_clicked(); - private: - QZXing qzxing; - QImage image; - QString message; + void on_copyImageBtn_clicked(); + + void on_copyVMessBtn_clicked(); + + private: + QZXing qzxing; + QImage image; + QString message; }; diff --git a/src/ui/w_ImportConfig.cpp b/src/ui/w_ImportConfig.cpp index 622eb657..573ceb3f 100644 --- a/src/ui/w_ImportConfig.cpp +++ b/src/ui/w_ImportConfig.cpp @@ -1,26 +1,25 @@ #include +#include "w_ImportConfig.hpp" + +#include "3rdparty/qzxing/src/QZXing.h" +#include "core/CoreUtils.hpp" +#include "core/connection/ConnectionIO.hpp" +#include "core/connection/Serialization.hpp" +#include "core/kernel/KernelInteractions.hpp" +#include "ui/editors/w_JsonEditor.hpp" +#include "ui/editors/w_OutboundEditor.hpp" +#include "ui/editors/w_RoutesEditor.hpp" +#include "ui/w_SubscriptionManager.hpp" +#include "w_ScreenShot_Core.hpp" + #include #include #include #include #include #include -#include "3rdparty/qzxing/src/QZXing.h" -#include "core/CoreUtils.hpp" -#include "core/kernel/KernelInteractions.hpp" -#include "core/connection/ConnectionIO.hpp" -#include "core/connection/Serialization.hpp" - -#include "w_ScreenShot_Core.hpp" -#include "ui/editors/w_OutboundEditor.hpp" -#include "ui/editors/w_JsonEditor.hpp" -#include "w_ImportConfig.hpp" -#include "ui/w_SubscriptionManager.hpp" -#include "ui/editors/w_RoutesEditor.hpp" - -ImportConfigWindow::ImportConfigWindow(QWidget *parent) - : QDialog(parent) +ImportConfigWindow::ImportConfigWindow(QWidget *parent) : QDialog(parent) { setupUi(this); nameTxt->setText(QDateTime::currentDateTime().toString("MMdd_hhmm")); @@ -30,10 +29,9 @@ ImportConfigWindow::ImportConfigWindow(QWidget *parent) QvMessageBusSlotImpl(ImportConfigWindow) { - switch (msg) { - MBShowDefaultImpl - MBHideDefaultImpl - MBRetranslateDefaultImpl + switch (msg) + { + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl } } @@ -43,7 +41,8 @@ ImportConfigWindow::~ImportConfigWindow() QMap ImportConfigWindow::OpenImport(bool partialImport) { - // partial import means only import as an outbound, will set keepImported to false and disable the checkbox + // partial import means only import as an outbound, will set keepImported to + // false and disable the checkbox // keepImportedInboundCheckBox->setChecked(!outboundsOnly); keepImportedInboundCheckBox->setEnabled(!partialImport); routeEditBtn->setEnabled(!partialImport); @@ -61,9 +60,7 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() { bool hideQv2ray = hideQv2rayCB->isChecked(); - if (hideQv2ray) { - messageBus.EmitGlobalSignal(QvMBMessage::HIDE_WINDOWS); - } + if (hideQv2ray) { messageBus.EmitGlobalSignal(QvMBMessage::HIDE_WINDOWS); } QApplication::processEvents(); QThread::msleep(static_cast(doubleSpinBox->value() * 1000)); @@ -72,24 +69,29 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() auto _r = w.result(); // Explicitly delete w to call UNREGISTER_WINDOW - if (hideQv2ray) { + if (hideQv2ray) + { messageBus.EmitGlobalSignal(QvMBMessage::SHOW_WINDOWS); - //ShowAllGlobalWindow(); + // ShowAllGlobalWindow(); } - if (_r == QDialog::Accepted) { + if (_r == QDialog::Accepted) + { QZXing decoder; decoder.setDecoder(QZXing::DecoderFormat_QR_CODE | QZXing::DecoderFormat_EAN_13); auto str = decoder.decodeImage(pix); - //auto str = QZXing().decodeImage(pix); + // auto str = QZXing().decodeImage(pix); - if (str.trimmed().isEmpty()) { + if (str.trimmed().isEmpty()) + { LOG(MODULE_UI, "Cannot decode QR Code from an image, size: h=" + QSTRN(pix.width()) + ", v=" + QSTRN(pix.height())) QvMessageBoxWarn(this, tr("Capture QRCode"), tr("Cannot find a valid QRCode from this region.")); - } else { + } + else + { vmessConnectionStringTxt->appendPlainText(str.trimmed() + NEWLINE); - //QvMessageBoxWarn(this, tr("Capture QRCode"), tr("Successfully imported a QR code form the screen.")); - //this->show(); + // QvMessageBoxWarn(this, tr("Capture QRCode"), tr("Successfully + // imported a QR code form the screen.")); this->show(); } } } @@ -97,26 +99,30 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() void ImportConfigWindow::on_beginImportBtn_clicked() { QString aliasPrefix = nameTxt->text(); - //auto conf = GetGlobalConfig(); + // auto conf = GetGlobalConfig(); - switch (tabWidget->currentIndex()) { - case 0: { + switch (tabWidget->currentIndex()) + { + case 0: + { //// From File... - //bool ImportAsComplex = keepImportedInboundCheckBox->isChecked(); - //QString path = fileLineTxt->text(); + // bool ImportAsComplex = keepImportedInboundCheckBox->isChecked(); + // QString path = fileLineTxt->text(); // - //if (!V2rayKernelInstance::ValidateConfig(path)) { - // QvMessageBoxWarn(this, tr("Import config file"), tr("Failed to check the validity of the config file.")); - // return; + // if (!V2rayKernelInstance::ValidateConfig(path)) { + // QvMessageBoxWarn(this, tr("Import config file"), tr("Failed to + // check the validity of the config file.")); return; //} // - //aliasPrefix += "_" + QFileInfo(path).fileName(); - ////CONFIGROOT config = ConvertConfigFromFile(path, ImportAsComplex); - //connections[aliasPrefix] = config; - //break; + // aliasPrefix += "_" + QFileInfo(path).fileName(); + ////CONFIGROOT config = ConvertConfigFromFile(path, + /// ImportAsComplex); + // connections[aliasPrefix] = config; + // break; } - case 1: { + case 1: + { QStringList linkList = SplitLines(vmessConnectionStringTxt->toPlainText()); // // Clear UI and error lists @@ -126,24 +132,30 @@ void ImportConfigWindow::on_beginImportBtn_clicked() // LOG(MODULE_IMPORT, QSTRN(linkList.count()) + " string found in vmess box.") - while (!linkList.isEmpty()) { + while (!linkList.isEmpty()) + { aliasPrefix = nameTxt->text(); auto link = linkList.takeFirst(); QString errMessage; CONFIGROOT config = ConvertConfigFromString(link, &aliasPrefix, &errMessage); // If the config is empty or we have any err messages. - if (config.isEmpty() || !errMessage.isEmpty()) { + if (config.isEmpty() || !errMessage.isEmpty()) + { // To prevent duplicated values. linkErrors[link] = QSTRN(linkErrors.count() + 1) + ": " + errMessage; continue; - } else { + } + else + { connections[aliasPrefix] = config; } } - if (!linkErrors.isEmpty()) { - for (auto item : linkErrors) { + if (!linkErrors.isEmpty()) + { + for (auto item : linkErrors) + { vmessConnectionStringTxt->appendPlainText(linkErrors.key(item)); errorsList->addItem(item); } @@ -173,10 +185,13 @@ void ImportConfigWindow::on_selectImageBtn_clicked() decoder.setDecoder(QZXing::DecoderFormat_QR_CODE | QZXing::DecoderFormat_EAN_13); auto str = decoder.decodeImage(QImage::fromData(buf)); - if (str.isEmpty()) { + if (str.isEmpty()) + { QvMessageBoxWarn(this, tr("QRCode scanning failed"), tr("Cannot find any QRCode from the image.")); return; - } else { + } + else + { vmessConnectionStringTxt->appendPlainText(str.trimmed() + NEWLINE); } } @@ -184,9 +199,7 @@ void ImportConfigWindow::on_errorsList_currentItemChanged(QListWidgetItem *curre { Q_UNUSED(previous) - if (current == nullptr) { - return; - } + if (current == nullptr) { return; } auto currentErrorText = current->text(); auto vmessEntry = linkErrors.key(currentErrorText); @@ -194,9 +207,7 @@ void ImportConfigWindow::on_errorsList_currentItemChanged(QListWidgetItem *curre auto startPos = vmessConnectionStringTxt->toPlainText().indexOf(vmessEntry); auto endPos = startPos + vmessEntry.length(); - if (startPos < 0) { - return; - } + if (startPos < 0) { return; } // Select vmess string that is invalid. QTextCursor c = vmessConnectionStringTxt->textCursor(); @@ -208,36 +219,43 @@ void ImportConfigWindow::on_editFileBtn_clicked() { QFile file(fileLineTxt->text()); - if (!file.exists()) { - QvMessageBoxWarn(this, tr("Edit file as JSON"), tr("Provided file not found: ") + fileLineTxt->text()); + if (!file.exists()) + { + QvMessageBoxWarn(this, tr("Edit file as JSON"), tr("Provided file not found: ") + fileLineTxt->text()); return; } auto jsonString = StringFromFile(&file); auto jsonCheckingError = VerifyJsonString(jsonString); - if (!jsonCheckingError.isEmpty()) { + if (!jsonCheckingError.isEmpty()) + { LOG(MODULE_FILEIO, "Currupted JSON file detected") - if (QvMessageBoxAsk(this, tr("Edit file as JSON"), tr("The file you selected has json syntax error. Continue editing may make you lose data. Would you like to continue?") + NEWLINE + jsonCheckingError) != QMessageBox::Yes) { - return; - } else { + if (QvMessageBoxAsk( + this, tr("Edit file as JSON"), + tr("The file you selected has json syntax error. Continue editing may make you lose data. Would you like to continue?") + + NEWLINE + jsonCheckingError) != QMessageBox::Yes) + { return; } + else + { LOG(MODULE_FILEIO, "Continue editing curruped json file, data loss is expected.") } } - auto json = JsonFromString(jsonString); + auto json = JsonFromString(jsonString); JsonEditor editor(json, this); json = editor.OpenEditor(); - if (editor.result() == QDialog::Accepted) { + if (editor.result() == QDialog::Accepted) + { auto str = JsonToString(json); bool result = StringToFile(str, file); - if (!result) { - QvMessageBoxWarn(this, tr("Edit file as JSON"), tr("Failed to save file, please check if you have proper permissions")); - } - } else { + if (!result) { QvMessageBoxWarn(this, tr("Edit file as JSON"), tr("Failed to save file, please check if you have proper permissions")); } + } + else + { LOG(MODULE_FILEIO, "Canceled saving a file.") } } @@ -249,7 +267,8 @@ void ImportConfigWindow::on_connectionEditBtn_clicked() bool isChanged = w.result() == QDialog::Accepted; QString alias = w.GetFriendlyName(); - if (isChanged) { + if (isChanged) + { OUTBOUNDS outboundsList; outboundsList.push_back(outboundEntry); CONFIGROOT root; @@ -257,7 +276,9 @@ void ImportConfigWindow::on_connectionEditBtn_clicked() // connections[alias] = root; accept(); - } else { + } + else + { return; } } @@ -275,7 +296,8 @@ void ImportConfigWindow::on_subscriptionButton_clicked() auto importToComplex = !keepImportedInboundCheckBox->isEnabled(); connections.clear(); - if (importToComplex) { + if (importToComplex) + { auto _result = w.GetSelectedConfig(); connections[_result.first] = _result.second; } @@ -290,10 +312,13 @@ void ImportConfigWindow::on_routeEditBtn_clicked() bool isChanged = w.result() == QDialog::Accepted; QString alias = nameTxt->text(); - if (isChanged) { + if (isChanged) + { connections[alias] = result; accept(); - } else { + } + else + { return; } } diff --git a/src/ui/w_ImportConfig.hpp b/src/ui/w_ImportConfig.hpp index 718e8657..09bbbd0c 100644 --- a/src/ui/w_ImportConfig.hpp +++ b/src/ui/w_ImportConfig.hpp @@ -1,44 +1,47 @@ #pragma once -#include -#include -#include #include "base/Qv2rayBase.hpp" -#include "ui_w_ImportConfig.h" #include "ui/messaging/QvMessageBus.hpp" +#include "ui_w_ImportConfig.h" -class ImportConfigWindow : public QDialog, private Ui::ImportConfigWindow +#include +#include +#include + +class ImportConfigWindow + : public QDialog + , private Ui::ImportConfigWindow { - Q_OBJECT + Q_OBJECT - public: - explicit ImportConfigWindow(QWidget *parent = nullptr); - ~ImportConfigWindow(); - QMap OpenImport(bool outboundsOnly = false); - public slots: - QvMessageBusSlotDecl - private slots: + public: + explicit ImportConfigWindow(QWidget *parent = nullptr); + ~ImportConfigWindow(); + QMap OpenImport(bool outboundsOnly = false); + public slots: + QvMessageBusSlotDecl; + private slots: - void on_selectFileBtn_clicked(); + void on_selectFileBtn_clicked(); - void on_qrFromScreenBtn_clicked(); - void on_beginImportBtn_clicked(); - void on_selectImageBtn_clicked(); - void on_errorsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous); + void on_qrFromScreenBtn_clicked(); + void on_beginImportBtn_clicked(); + void on_selectImageBtn_clicked(); + void on_errorsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous); - void on_editFileBtn_clicked(); + void on_editFileBtn_clicked(); - void on_connectionEditBtn_clicked(); + void on_connectionEditBtn_clicked(); - void on_cancelImportBtn_clicked(); + void on_cancelImportBtn_clicked(); - void on_subscriptionButton_clicked(); + void on_subscriptionButton_clicked(); - void on_routeEditBtn_clicked(); + void on_routeEditBtn_clicked(); - void on_hideQv2rayCB_stateChanged(int arg1); + void on_hideQv2rayCB_stateChanged(int arg1); - private: - QMap connections; - QMap linkErrors; + private: + QMap connections; + QMap linkErrors; }; diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 9dda22e4..39743d16 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -1,76 +1,86 @@ #pragma once #include "w_MainWindow.hpp" + +#include "ui/editors/w_JsonEditor.hpp" +#include "ui/editors/w_OutboundEditor.hpp" +#include "ui/editors/w_RoutesEditor.hpp" +#include "w_ExportConfig.hpp" #include "w_ImportConfig.hpp" #include "w_PreferencesWindow.hpp" #include "w_SubscriptionManager.hpp" -#include "w_ExportConfig.hpp" -#include "ui/editors/w_OutboundEditor.hpp" -#include "ui/editors/w_RoutesEditor.hpp" -#include "ui/editors/w_JsonEditor.hpp" //#include +#include "components/pac/QvPACHandler.hpp" +#include "components/plugins/toolbar/QvToolbar.hpp" +#include "core/connection/ConnectionIO.hpp" +#include "ui/widgets/ConnectionInfoWidget.hpp" + #include #include +#include #include #include #include #include +#include #include #include -#include #include #include -#include -#include "components/plugins/toolbar/QvToolbar.hpp" -#include "components/pac/QvPACHandler.hpp" - -#include "core/connection/ConnectionIO.hpp" -#include "ui/widgets/ConnectionInfoWidget.hpp" - -// MainWindow.cpp --> Main MainWindow source file, handles mostly UI-related operations. +// MainWindow.cpp --> Main MainWindow source file, handles mostly UI-related +// operations. #define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING // -#define GetItemWidget(item) (qobject_cast(connectionListWidget->itemWidget(item, 0))) +#define GetItemWidget(item) (qobject_cast(connectionListWidget->itemWidget(item, 0))) /* -#define ItemConnectionIdentifier(__item__) (__item__->data(0, Qt::UserRole).value()) +#define ItemConnectionIdentifier(__item__) (__item__->data(0, +Qt::UserRole).value()) -#define CheckConfigType(_item_, TYPE) (connections.contains(ItemConnectionIdentifier(_item_)) && connections[ItemConnectionIdentifier(_item_)].configType == CONNECTION_ ## TYPE) +#define CheckConfigType(_item_, TYPE) +(connections.contains(ItemConnectionIdentifier(_item_)) && +connections[ItemConnectionIdentifier(_item_)].configType == CONNECTION_ ## TYPE) -#define SUBSCRIPTION_CONFIG_MODIFY_ASK(_item_) \ - if (!CheckConfigType(_item_, REGULAR)) { \ - if (QvMessageBoxAsk(this, QObject::tr("Editing a subscription config"), QObject::tr("You are trying to edit a config loaded from subscription.") + \ - NEWLINE + QObject::tr("All changes will be overwritten when the subscriptions are updated next time.") + \ - NEWLINE + QObject::tr("Are you still going to do so?")) != QMessageBox::Yes) { \ - return; \ - } \ - } \ +#define SUBSCRIPTION_CONFIG_MODIFY_ASK(_item_) \ + if (!CheckConfigType(_item_, REGULAR)) { \ + if (QvMessageBoxAsk(this, QObject::tr("Editing a subscription config"), +QObject::tr("You are trying to edit a config loaded from subscription.") + \ + NEWLINE + QObject::tr("All changes will be +overwritten when the subscriptions are updated next time.") + \ + NEWLINE + QObject::tr("Are you still going to do +so?")) != QMessageBox::Yes) { \ + return; \ + } \ + } \ -#define SUBSCRIPTION_CONFIG_MODIFY_DENY(_item_) \ - if (!CheckConfigType(_item_, REGULAR)) { \ - QvMessageBoxWarn(this, QObject::tr("Editing a subscription config"), QObject::tr("You should not modity this property of a config from a subscription")); \ - return; \ - } \ +#define SUBSCRIPTION_CONFIG_MODIFY_DENY(_item_) \ + if (!CheckConfigType(_item_, REGULAR)) { \ + QvMessageBoxWarn(this, QObject::tr("Editing a subscription config"), +QObject::tr("You should not modity this property of a config from a +subscription")); \ + return; \ + } \ -#define IsConnectableItem(item) (item != nullptr && item->childCount() == 0 && (CheckConfigType(item, REGULAR) || CheckConfigType(item, SUBSCRIPTION))) -#define IsSelectionConnectable (!connectionListWidget->selectedItems().empty() && IsConnectableItem(connectionListWidget->selectedItems().first())) +#define IsConnectableItem(item) (item != nullptr && item->childCount() == 0 && +(CheckConfigType(item, REGULAR) || CheckConfigType(item, SUBSCRIPTION))) #define +IsSelectionConnectable (!connectionListWidget->selectedItems().empty() && +IsConnectableItem(connectionListWidget->selectedItems().first())) */ MainWindow *MainWindow::mwInstance = nullptr; QvMessageBusSlotImpl(MainWindow) { - switch (msg) { - MBShowDefaultImpl - MBHideDefaultImpl - MBRetranslateDefaultImpl + switch (msg) + { + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl } } -MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTray(this), tcpingHelper(3, this) +MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), hTray(this), tcpingHelper(3, this) { setupUi(this); MainWindow::mwInstance = this; @@ -86,8 +96,8 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr this->setWindowIcon(QIcon(":/assets/icons/qv2ray.png")); hTray.setIcon(QIcon(GlobalConfig.uiConfig.useDarkTrayIcon ? ":/assets/icons/ui_dark/tray.png" : ":/assets/icons/ui_light/tray.png")); importConfigButton->setIcon(QICON_R("import.png")); - //pingTestBtn->setIcon(QICON_R("ping_gauge.png")); - //shareBtn->setIcon(QICON_R("share.png")); + // pingTestBtn->setIcon(QICON_R("ping_gauge.png")); + // shareBtn->setIcon(QICON_R("share.png")); updownImageBox->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); updownImageBox_2->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); // @@ -96,7 +106,7 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr this->show(); QvMessageBoxWarn(this, tr("V2ray vcore terminated."), tr("V2ray vcore terminated unexpectedly.") + NEWLINE + NEWLINE + - tr("To solve the problem, read the V2ray log in the log text browser.")); + tr("To solve the problem, read the V2ray log in the log text browser.")); }); connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &MainWindow::OnConnected); connect(ConnectionManager, &QvConnectionHandler::OnDisConnected, this, &MainWindow::OnDisConnected); @@ -141,9 +151,11 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr // connect(action_Tray_ShowHide, &QAction::triggered, this, &MainWindow::ToggleVisibility); connect(action_Tray_ShowPreferencesWindow, &QAction::triggered, this, &MainWindow::on_preferencesBtn_clicked); - //connect(action_Tray_Start, &QAction::triggered, this, &MainWindow::on_startButton_clicked); - //connect(action_Tray_Stop, &QAction::triggered, this, &MainWindow::on_stopButton_clicked); - //connect(action_Tray_Reconnect, &QAction::triggered, this, &MainWindow::on_reconnectButton_clicked); + // connect(action_Tray_Start, &QAction::triggered, this, + // &MainWindow::on_startButton_clicked); connect(action_Tray_Stop, + // &QAction::triggered, this, &MainWindow::on_stopButton_clicked); + // connect(action_Tray_Reconnect, &QAction::triggered, this, + // &MainWindow::on_reconnectButton_clicked); connect(action_Tray_Quit, &QAction::triggered, this, &MainWindow::on_actionExit_triggered); connect(action_Tray_SetSystemProxy, &QAction::triggered, this, &MainWindow::MWSetSystemProxy); connect(action_Tray_ClearSystemProxy, &QAction::triggered, this, &MainWindow::MWClearSystemProxy); @@ -166,9 +178,11 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr connect(action_RCM_ShareQR, &QAction::triggered, this, &MainWindow::on_action_RCM_ShareQR_triggered); // // Globally invokable signals. - //connect(this, &MainWindow::Connect, this, &MainWindow::on_startButton_clicked); - //connect(this, &MainWindow::DisConnect, this, &MainWindow::on_stopButton_clicked); - //connect(this, &MainWindow::ReConnect, this, &MainWindow::on_reconnectButton_clicked); + // connect(this, &MainWindow::Connect, this, + // &MainWindow::on_startButton_clicked); connect(this, + // &MainWindow::DisConnect, this, &MainWindow::on_stopButton_clicked); + // connect(this, &MainWindow::ReConnect, this, + // &MainWindow::on_reconnectButton_clicked); // hTray.setContextMenu(tray_RootMenu); hTray.show(); @@ -183,13 +197,15 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr LOG(MODULE_UI, "Loading data...") auto groups = ConnectionManager->AllGroups(); - for (auto group : groups) { + for (auto group : groups) + { auto groupItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetDisplayName(group)); connectionListWidget->addTopLevelItem(groupItem); connectionListWidget->setItemWidget(groupItem, 0, new ConnectionItemWidget(group, connectionListWidget)); auto connections = ConnectionManager->Connections(group); - for (auto connection : connections) { + for (auto connection : connections) + { auto connectionItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetDisplayName(connection)); groupItem->addChild(connectionItem); auto widget = new ConnectionItemWidget(connection, connectionListWidget); @@ -202,18 +218,16 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr // Find and start if there is an auto-connection auto needShowWindow = true; - if (!GlobalConfig.autoStartId.isEmpty()) { + if (!GlobalConfig.autoStartId.isEmpty()) + { auto id = ConnectionId(GlobalConfig.autoStartId); needShowWindow = ConnectionManager->StartConnection(id).has_value(); } - if (needShowWindow) { - this->show(); - } + if (needShowWindow) { this->show(); } //// If we are not connected to anything, show the MainWindow. - if (needShowWindow) { - } + if (needShowWindow) {} #ifndef DISABLE_AUTO_UPDATE requestHelper = new QvHttpRequestHelper(); @@ -221,7 +235,8 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr requestHelper->get("https://api.github.com/repos/Qv2ray/Qv2ray/releases/latest"); #endif - if (StartupOption.enableToolbarPlguin) { + if (StartupOption.enableToolbarPlguin) + { LOG(MODULE_UI, "Plugin daemon is enabled.") StartProcessingPlugins(); } @@ -231,33 +246,35 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr splitter->setSizes(QList() << 100 << 300); } - void MainWindow::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { + if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) + { // If pressed enter or return on connectionListWidget. // Try to connect to the selected connection. - //if (focusWidget() == connectionListWidget) { + // if (focusWidget() == connectionListWidget) { // if (!IsSelectionConnectable) return; // // auto selections = connectionListWidget->selectedItems(); // QVariant v; // auto vv = v.value(); - // ShowAndSetConnection(ItemConnectionIdentifier(selections.first()), true, true); + // ShowAndSetConnection(ItemConnectionIdentifier(selections.first()), + // true, true); //} } } void MainWindow::on_action_StartThis_triggered() { - //if (!IsSelectionConnectable) { - // QvMessageBoxWarn(this, tr("No connection selected!"), tr("Please select a config from the list.")); - // return; + // if (!IsSelectionConnectable) { + // QvMessageBoxWarn(this, tr("No connection selected!"), tr("Please + // select a config from the list.")); return; //} // - //CurrentSelectedItemPtr = connectionListWidget->selectedItems().first(); - //CurrentConnectionIdentifier = ItemConnectionIdentifier(CurrentSelectedItemPtr); - //on_reconnectButton_clicked(); + // CurrentSelectedItemPtr = connectionListWidget->selectedItems().first(); + // CurrentConnectionIdentifier = + // ItemConnectionIdentifier(CurrentSelectedItemPtr); + // on_reconnectButton_clicked(); } #ifndef DISABLE_AUTO_UPDATE @@ -269,28 +286,27 @@ void MainWindow::VersionUpdate(QByteArray &data) QVersionNumber newVersion = QVersionNumber::fromString(root["tag_name"].toString("v").remove(0, 1)); QVersionNumber currentVersion = QVersionNumber::fromString(QString(QV2RAY_VERSION_STRING).remove(0, 1)); QVersionNumber ignoredVersion = QVersionNumber::fromString(GlobalConfig.ignoredVersion); - LOG(MODULE_UPDATE, "Received update info, Latest: " + newVersion.toString() + " Current: " + currentVersion.toString() + " Ignored: " + ignoredVersion.toString()) + LOG(MODULE_UPDATE, "Received update info, Latest: " + newVersion.toString() + " Current: " + currentVersion.toString() + + " Ignored: " + ignoredVersion.toString()) // If the version is newer than us. // And new version is newer than the ignored version. - if (newVersion > currentVersion && newVersion > ignoredVersion) { + if (newVersion > currentVersion && newVersion > ignoredVersion) + { LOG(MODULE_UPDATE, "New version detected.") auto link = root["html_url"].toString(""); - auto result = QvMessageBoxAsk(this, tr("Update"), - tr("Found a new version: ") + root["tag_name"].toString("") + - "\r\n" + - root["name"].toString("") + - "\r\n------------\r\n" + - root["body"].toString("") + - "\r\n------------\r\n" + - tr("Download Link: ") + link, QMessageBox::Ignore); + auto result = + QvMessageBoxAsk(this, tr("Update"), + tr("Found a new version: ") + root["tag_name"].toString("") + "\r\n" + root["name"].toString("") + + "\r\n------------\r\n" + root["body"].toString("") + "\r\n------------\r\n" + tr("Download Link: ") + link, + QMessageBox::Ignore); - if (result == QMessageBox::Yes) { - QDesktopServices::openUrl(QUrl::fromUserInput(link)); - } else if (result == QMessageBox::Ignore) { + if (result == QMessageBox::Yes) { QDesktopServices::openUrl(QUrl::fromUserInput(link)); } + else if (result == QMessageBox::Ignore) + { // Set and save ingored version. GlobalConfig.ignoredVersion = newVersion.toString(); - //SaveGlobalConfig(GlobalConfig); + // SaveGlobalConfig(GlobalConfig); } } } @@ -309,12 +325,14 @@ void MainWindow::closeEvent(QCloseEvent *event) } void MainWindow::on_activatedTray(QSystemTrayIcon::ActivationReason reason) { - switch (reason) { + switch (reason) + { case QSystemTrayIcon::Trigger: // Toggle Show/Hide #ifndef __APPLE__ // Every single click will trigger the Show/Hide toggling. - // So, as what common macOS Apps do, we don't toggle visibility here. + // So, as what common macOS Apps do, we don't toggle visibility + // here. ToggleVisibility(); #endif break; @@ -325,13 +343,13 @@ void MainWindow::on_activatedTray(QSystemTrayIcon::ActivationReason reason) #endif break; - default: - break; + default: break; } } void MainWindow::ToggleVisibility() { - if (this->isHidden()) { + if (this->isHidden()) + { this->show(); #ifdef Q_OS_WIN setWindowState(Qt::WindowNoState); @@ -340,7 +358,9 @@ void MainWindow::ToggleVisibility() SetWindowPos(HWND(this->winId()), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); #endif tray_RootMenu->actions()[0]->setText(tr("Hide")); - } else { + } + else + { this->hide(); tray_RootMenu->actions()[0]->setText(tr("Show")); } @@ -348,9 +368,7 @@ void MainWindow::ToggleVisibility() void MainWindow::on_actionExit_triggered() { - if (StartupOption.enableToolbarPlguin) { - StopProcessingPlugins(); - } + if (StartupOption.enableToolbarPlguin) { StopProcessingPlugins(); } ExitQv2ray(); } @@ -366,13 +384,14 @@ void MainWindow::on_clearlogButton_clicked() void MainWindow::on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { Q_UNUSED(previous) - //CurrentItem = current; - //isRenamingInProgress = false; + // CurrentItem = current; + // isRenamingInProgress = false; // - //if (!IsConnectableItem(current)) return; + // if (!IsConnectableItem(current)) return; // //// no need to check !isRenamingInProgress since it's always true. - //ShowAndSetConnection(ItemConnectionIdentifier(current), !vinstance->KernelStarted, false); + // ShowAndSetConnection(ItemConnectionIdentifier(current), + // !vinstance->KernelStarted, false); ////on_connectionListWidget_itemClicked(current, 0); } void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint &pos) @@ -381,52 +400,55 @@ void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint auto _pos = QCursor::pos(); auto item = connectionListWidget->itemAt(connectionListWidget->mapFromGlobal(_pos)); - if (GetItemWidget(item)->IsConnection()) { - connectionListMenu->popup(_pos); - } + if (GetItemWidget(item)->IsConnection()) { connectionListMenu->popup(_pos); } } void MainWindow::on_action_RCM_RenameConnection_triggered() { - //auto item = connectionListWidget->currentItem(); - //SUBSCRIPTION_CONFIG_MODIFY_DENY(item) - //item->setFlags(item->flags() | Qt::ItemIsEditable); - //isRenamingInProgress = true; - //connectionListWidget->editItem(item); - //renameOriginalIdentifier = ItemConnectionIdentifier(item); + // auto item = connectionListWidget->currentItem(); + // SUBSCRIPTION_CONFIG_MODIFY_DENY(item) + // item->setFlags(item->flags() | Qt::ItemIsEditable); + // isRenamingInProgress = true; + // connectionListWidget->editItem(item); + // renameOriginalIdentifier = ItemConnectionIdentifier(item); } void MainWindow::on_connectionListWidget_itemChanged(QTreeWidgetItem *item, int) { - //DEBUG(UI, "A connection ListViewItem is changed. This should ONLY occur when renaming an connection.") + // DEBUG(UI, "A connection ListViewItem is changed. This should ONLY occur + // when renaming an connection.") // - //if (!isRenamingInProgress) { + // if (!isRenamingInProgress) { // return; //} // - //isRenamingInProgress = false; + // isRenamingInProgress = false; //// In this case it's after we entered the name. //// and tell user you should not rename a config from subscription. - //auto newIdentifier = renameOriginalIdentifier; - //newIdentifier.connectionName = item->text(0); - //LOG(CONNECTION, "RENAME: " + renameOriginalIdentifier.IdentifierString() + " -> " + newIdentifier.IdentifierString()) + // auto newIdentifier = renameOriginalIdentifier; + // newIdentifier.connectionName = item->text(0); + // LOG(CONNECTION, "RENAME: " + renameOriginalIdentifier.IdentifierString() + // + " -> " + newIdentifier.IdentifierString()) // //// If I really did some changes. - //if (renameOriginalIdentifier != newIdentifier) { + // if (renameOriginalIdentifier != newIdentifier) { // bool canContinueRename = true; // // if (newIdentifier.connectionName.trimmed().isEmpty()) { - // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name cannot be empty")); - // canContinueRename = false; + // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name + // cannot be empty")); canContinueRename = false; // } // // QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); // //if (GlobalConfig.configs.contains(newIdentifier.connectionName)) { - // // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name has been used already, Please choose another.")); + // // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name + // has been used already, Please choose another.")); // // canContinueRename = false; // //} // - // if (!IsValidFileName(newIdentifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION)) { - // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name you suggested is not valid, please try another.")); - // canContinueRename = false; + // if (!IsValidFileName(newIdentifier.connectionName + + // QV2RAY_CONFIG_FILE_EXTENSION)) { + // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name you + // suggested is not valid, please try another.")); canContinueRename + // = false; // } // // if (!canContinueRename) { @@ -448,8 +470,10 @@ void MainWindow::on_connectionListWidget_itemChanged(QTreeWidgetItem *item, int) // //GlobalConfig.configs.removeOne(renameOriginalIdentifier.connectionName); // //GlobalConfig.configs.push_back(newIdentifier.connectionName); // // - // //connections[newIdentifier] = connections.take(renameOriginalIdentifier); - // //RenameConnection(renameOriginalIdentifier.connectionName, newIdentifier.connectionName); + // //connections[newIdentifier] = + // connections.take(renameOriginalIdentifier); + // //RenameConnection(renameOriginalIdentifier.connectionName, + // newIdentifier.connectionName); // //LOG(UI, "Saving a global config") // //SaveGlobalConfig(GlobalConfig); // //// @@ -462,35 +486,38 @@ void MainWindow::on_connectionListWidget_itemChanged(QTreeWidgetItem *item, int) // // on_reconnectButton_clicked(); // // } // //} - // //OnConfigListChanged(CurrentConnectionIdentifier.connectionName == renameOriginalName); + // //OnConfigListChanged(CurrentConnectionIdentifier.connectionName == + // renameOriginalName); //} } void MainWindow::on_removeConfigButton_clicked() { QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - //QList connlist; + // QList connlist; // - //for (auto item : connectionListWidget->selectedItems()) { + // for (auto item : connectionListWidget->selectedItems()) { // if (IsConnectableItem(item)) { // connlist.append(ItemConnectionIdentifier(item)); // } //} // - //LOG(UI, "Selected " + QSTRN(connlist.count()) + " items") + // LOG(UI, "Selected " + QSTRN(connlist.count()) + " items") // - //if (connlist.isEmpty()) { + // if (connlist.isEmpty()) { // // Remove nothing means doing nothing. // return; //} // - //if (QvMessageBoxAsk(this, tr("Removing Connection(s)"), tr("Are you sure to remove selected connection(s)?")) != QMessageBox::Yes) { + // if (QvMessageBoxAsk(this, tr("Removing Connection(s)"), tr("Are you sure + // to remove selected connection(s)?")) != QMessageBox::Yes) { // return; //} // - //// A triple-state flag which indicates if the user wants to remove the configs loaded from a subscription. - //int subscriptionRemovalCheckStatus = -1; + //// A triple-state flag which indicates if the user wants to remove the + /// configs loaded from a subscription. + // int subscriptionRemovalCheckStatus = -1; // - //for (auto conn : connlist) { + // for (auto conn : connlist) { // if (conn == CurrentConnectionIdentifier) { // on_stopButton_clicked(); // CurrentConnectionIdentifier = ConnectionIdentifier(); @@ -499,8 +526,10 @@ void MainWindow::on_removeConfigButton_clicked() // auto connData = connections[conn]; // // // Remove auto start config. - // if (GlobalConfig.autoStartConfig.subscriptionName == connData.subscriptionName && - // GlobalConfig.autoStartConfig.connectionName == connData.connectionName) + // if (GlobalConfig.autoStartConfig.subscriptionName == + // connData.subscriptionName && + // GlobalConfig.autoStartConfig.connectionName == + // connData.connectionName) // // If all those settings match. // { // GlobalConfig.autoStartConfig.subscriptionName.clear(); @@ -510,44 +539,53 @@ void MainWindow::on_removeConfigButton_clicked() // if (connData.configType == CONNECTION_REGULAR) { // // Just remove the regular configs. // if (!connData.subscriptionName.isEmpty()) { - // LOG(UI, "Unexpected subscription name in a single regular config.") - // connData.subscriptionName.clear(); + // LOG(UI, "Unexpected subscription name in a single regular + // config.") connData.subscriptionName.clear(); // } // // GlobalConfig.configs.removeOne(conn.connectionName); // // if (!RemoveConnection(conn.connectionName)) { - // QvMessageBoxWarn(this, tr("Removing this Connection"), tr("Failed to delete connection file, please delete manually.")); + // QvMessageBoxWarn(this, tr("Removing this Connection"), + // tr("Failed to delete connection file, please delete + // manually.")); // } // } else if (connData.configType == CONNECTION_SUBSCRIPTION) { // if (subscriptionRemovalCheckStatus == -1) { - // subscriptionRemovalCheckStatus = (QvMessageBoxAsk(this, tr("Removing a subscription config"), tr("Do you want to remove the config loaded from a subscription?")) == QMessageBox::Yes) + // subscriptionRemovalCheckStatus = (QvMessageBoxAsk(this, + // tr("Removing a subscription config"), tr("Do you want to + // remove the config loaded from a subscription?")) == + // QMessageBox::Yes) // ? 1 // Yes i want // : 0; // No please keep // } // // if (subscriptionRemovalCheckStatus == 1) { - // if (!RemoveSubscriptionConnection(connData.subscriptionName, connData.connectionName)) { - // QvMessageBoxWarn(this, tr("Removing this Connection"), tr("Failed to delete connection file, please delete manually.")); + // if (!RemoveSubscriptionConnection(connData.subscriptionName, + // connData.connectionName)) { + // QvMessageBoxWarn(this, tr("Removing this Connection"), + // tr("Failed to delete connection file, please delete + // manually.")); // } // } // } else { - // LOG(SETTINGS, "Unknown config type -> Not regular nor subscription...") + // LOG(SETTINGS, "Unknown config type -> Not regular nor + // subscription...") // } //} // - //LOG(UI, "Saving GlobalConfig") - //SaveGlobalConfig(GlobalConfig); - //OnConfigListChanged(false); - //ShowAndSetConnection(CurrentConnectionIdentifier, false, false); + // LOG(UI, "Saving GlobalConfig") + // SaveGlobalConfig(GlobalConfig); + // OnConfigListChanged(false); + // ShowAndSetConnection(CurrentConnectionIdentifier, false, false); } void MainWindow::on_importConfigButton_clicked() { QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - //ImportConfigWindow w(this); - //auto configs = w.OpenImport(); - //if (!configs.isEmpty()) { + // ImportConfigWindow w(this); + // auto configs = w.OpenImport(); + // if (!configs.isEmpty()) { // for (auto conf : configs) { // auto name = configs.key(conf, ""); // @@ -569,26 +607,26 @@ void MainWindow::on_editConfigButton_clicked() void MainWindow::on_action_RCM_ConvToComplex_triggered() { //// Check if we have a connection selected... - //if (!IsSelectionConnectable) { - // QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a Config")); - // return; + // if (!IsSelectionConnectable) { + // QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a + // Config")); return; //} // - //auto selectedFirst = connectionListWidget->currentItem(); - //auto _identifier = ItemConnectionIdentifier(selectedFirst); - //SUBSCRIPTION_CONFIG_MODIFY_DENY(selectedFirst) + // auto selectedFirst = connectionListWidget->currentItem(); + // auto _identifier = ItemConnectionIdentifier(selectedFirst); + // SUBSCRIPTION_CONFIG_MODIFY_DENY(selectedFirst) //// - //auto outBoundRoot = connections[_identifier].config; - //CONFIGROOT root; - //bool isChanged = false; + // auto outBoundRoot = connections[_identifier].config; + // CONFIGROOT root; + // bool isChanged = false; //// - //LOG(UI, "INFO: Opening route editor.") - //RouteEditor routeWindow(outBoundRoot, this); - //root = routeWindow.OpenEditor(); - //isChanged = routeWindow.result() == QDialog::Accepted; - //QString alias = _identifier.connectionName; + // LOG(UI, "INFO: Opening route editor.") + // RouteEditor routeWindow(outBoundRoot, this); + // root = routeWindow.OpenEditor(); + // isChanged = routeWindow.result() == QDialog::Accepted; + // QString alias = _identifier.connectionName; // - //if (isChanged) { + // if (isChanged) { // connections[_identifier].config = root; // // true indicates the alias will NOT change // SaveConnectionConfig(root, &alias, true); @@ -603,7 +641,7 @@ void MainWindow::on_action_RCM_EditJson_triggered() void MainWindow::on_action_RCM_ShareQR_triggered() { - //on_shareBtn_clicked(); + // on_shareBtn_clicked(); } void MainWindow::on_subsButton_clicked() @@ -616,9 +654,7 @@ void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item Q_UNUSED(column) auto widget = GetItemWidget(item); - if (widget->IsConnection()) { - widget->BeginConnection(); - } + if (widget->IsConnection()) { widget->BeginConnection(); } } void MainWindow::OnDisConnected(const ConnectionId &id) @@ -628,14 +664,13 @@ void MainWindow::OnDisConnected(const ConnectionId &id) hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE); connetionStatusLabel->setText(tr("Disconnected")); - if (systemProxyEnabled) { - MWClearSystemProxy(false); - } + if (systemProxyEnabled) { MWClearSystemProxy(false); } - //QFile(QV2RAY_GENERATED_FILE_PATH).remove(); + // QFile(QV2RAY_GENERATED_FILE_PATH).remove(); - if (GlobalConfig.inboundConfig.pacConfig.enablePAC) { - //pacServer.StopServer(); + if (GlobalConfig.inboundConfig.pacConfig.enablePAC) + { + // pacServer.StopServer(); LOG(MODULE_UI, "Stopping PAC server") } } @@ -655,56 +690,64 @@ void MainWindow::OnConnected(const ConnectionId &id) bool httpEnabled = GlobalConfig.inboundConfig.useHTTP; bool socksEnabled = GlobalConfig.inboundConfig.useSocks; - if (usePAC) { + if (usePAC) + { bool canStartPAC = true; - QString pacProxyString; // Something like this --> SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT; http://proxy:8080 + QString pacProxyString; // Something like this --> SOCKS5 127.0.0.1:1080; SOCKS + // 127.0.0.1:1080; DIRECT; http://proxy:8080 auto pacIP = GlobalConfig.inboundConfig.pacConfig.localIP; - if (pacIP.isEmpty()) { + if (pacIP.isEmpty()) + { LOG(MODULE_PROXY, "PAC Local IP is empty, default to 127.0.0.1") pacIP = "127.0.0.1"; } - if (pacUseSocks) { - if (socksEnabled) { - pacProxyString = "SOCKS5 " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.socks_port); - } else { + if (pacUseSocks) + { + if (socksEnabled) { pacProxyString = "SOCKS5 " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.socks_port); } + else + { LOG(MODULE_UI, "PAC is using SOCKS, but it is not enabled") - QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use SOCKS, but it is not enabled")); + QvMessageBoxWarn(this, tr("Configuring PAC"), + tr("Could not start PAC server as it is configured to use SOCKS, but it is not enabled")); canStartPAC = false; } - } else { - if (httpEnabled) { - pacProxyString = "PROXY " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.http_port); - } else { + } + else + { + if (httpEnabled) { pacProxyString = "PROXY " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.http_port); } + else + { LOG(MODULE_UI, "PAC is using HTTP, but it is not enabled") - QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use HTTP, but it is not enabled")); + QvMessageBoxWarn(this, tr("Configuring PAC"), + tr("Could not start PAC server as it is configured to use HTTP, but it is not enabled")); canStartPAC = false; } } - if (canStartPAC) { - //pacServer.SetProxyString(pacProxyString); - //pacServer.StartListen(); - } else { + if (canStartPAC) + { + // pacServer.SetProxyString(pacProxyString); + // pacServer.StartListen(); + } + else + { LOG(MODULE_PROXY, "Not starting PAC due to previous error.") } } - if (GlobalConfig.inboundConfig.setSystemProxy) { - MWSetSystemProxy(); - } + if (GlobalConfig.inboundConfig.setSystemProxy) { MWSetSystemProxy(); } } - void MainWindow::onConnectionWidgetFocusRequested(const ConnectionItemWidget *_widget) { - if (_widget == nullptr) { - return; - } + if (_widget == nullptr) { return; } - for (auto _item_ : connectionListWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard | Qt::MatchRecursive)) { - if (GetItemWidget(_item_) == _widget) { + for (auto _item_ : connectionListWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard | Qt::MatchRecursive)) + { + if (GetItemWidget(_item_) == _widget) + { LOG(MODULE_UI, "Setting current item.") connectionListWidget->setCurrentItem(_item_); connectionListWidget->scrollToItem(_item_); @@ -717,28 +760,31 @@ void MainWindow::onConnectionWidgetFocusRequested(const ConnectionItemWidget *_w void MainWindow::on_connectionFilterTxt_textEdited(const QString &arg1) { // No recursive since we only need top level item - for (auto _top_item_ : connectionListWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard)) { - //auto topWidget = GetItemWidget(_top_item_); + for (auto _top_item_ : connectionListWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard)) + { + // auto topWidget = GetItemWidget(_top_item_); bool isTotallyHide = true; - for (auto i = 0; i < _top_item_->childCount(); i++) { + for (auto i = 0; i < _top_item_->childCount(); i++) + { auto _child_ = _top_item_->child(i); - if (GetItemWidget(_child_)->NameMatched(arg1)) { + if (GetItemWidget(_child_)->NameMatched(arg1)) + { LOG(MODULE_UI, "Setting current item.") // Show the child _child_->setHidden(false); isTotallyHide = false; - } else { + } + else + { _child_->setHidden(true); } } _top_item_->setHidden(isTotallyHide); - if (!isTotallyHide) { - connectionListWidget->expandItem(_top_item_); - } + if (!isTotallyHide) { connectionListWidget->expandItem(_top_item_); } } } @@ -748,11 +794,12 @@ void MainWindow::on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int infoWidget->ShowDetails(GetItemWidget(item)->Identifier()); } -void MainWindow::onConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, const quint64 totalDown) +void MainWindow::onConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, + const quint64 totalDown) { Q_UNUSED(id); - // This may not be, or may not precisely be, speed per second if low-level has "any" latency. - // (Hope not...) + // This may not be, or may not precisely be, speed per second if low-level + // has "any" latency. (Hope not...) speedChartWidget->AddPointData(upSpeed, downSpeed); // auto totalSpeedUp = FormatBytes(upSpeed) + "/s"; @@ -763,7 +810,8 @@ void MainWindow::onConnectionStatsArrived(const ConnectionId &id, const quint64 netspeedLabel->setText(totalSpeedUp + NEWLINE + totalSpeedDown); dataamountLabel->setText(totalDataUp + NEWLINE + totalDataDown); // - hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + ConnectionManager->GetDisplayName(id) + NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); + hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + ConnectionManager->GetDisplayName(id) + NEWLINE "Up: " + totalSpeedUp + + " Down: " + totalSpeedDown); } void MainWindow::onVCoreLogArrived(const ConnectionId &id, const QString &log) @@ -777,35 +825,40 @@ void MainWindow::onVCoreLogArrived(const ConnectionId &id, const QString &log) auto maxLines = GlobalConfig.uiConfig.maximumLogLines; QTextBlock block = masterLogBrowser->document()->begin(); - while (block.isValid()) { - if (masterLogBrowser->document()->blockCount() > maxLines) { + while (block.isValid()) + { + if (masterLogBrowser->document()->blockCount() > maxLines) + { QTextCursor cursor(block); block = block.next(); cursor.select(QTextCursor::BlockUnderCursor); cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); cursor.removeSelectedText(); - } else { + } + else + { break; } } - if (val >= max * 0.8 || val >= max - 20) - bar->setValue(max); + if (val >= max * 0.8 || val >= max - 20) bar->setValue(max); } - void MainWindow::OnEditRequested(const ConnectionId &id) { auto outBoundRoot = ConnectionManager->GetConnectionRoot(id); CONFIGROOT root; bool isChanged = false; - if (IsComplexConfig(outBoundRoot)) { + if (IsComplexConfig(outBoundRoot)) + { LOG(MODULE_UI, "INFO: Opening route editor.") RouteEditor routeWindow(outBoundRoot, this); root = routeWindow.OpenEditor(); isChanged = routeWindow.result() == QDialog::Accepted; - } else { + } + else + { LOG(MODULE_UI, "INFO: Opening single connection edit window.") auto out = OUTBOUND(outBoundRoot["outbounds"].toArray().first().toObject()); OutboundEditor w(out, this); @@ -816,18 +869,21 @@ void MainWindow::OnEditRequested(const ConnectionId &id) root.insert("outbounds", outboundsList); } - if (isChanged) { - //if (CheckConfigType(firstSelected, SUBSCRIPTION)) { + if (isChanged) + { + // if (CheckConfigType(firstSelected, SUBSCRIPTION)) { // auto name = connections[_identifier].connectionName; // // Assume name will not change. - // SaveSubscriptionConfig(root, connections[_identifier].subscriptionName, &name); + // SaveSubscriptionConfig(root, + // connections[_identifier].subscriptionName, &name); //} else { // connections[_identifier].config = root; // // true indicates the alias will NOT change // SaveConnectionConfig(root, &alias, true); //} ConnectionManager->UpdateConnection(id, root); - //OnConfigListChanged(alias == CurrentConnectionIdentifier.connectionName); + // OnConfigListChanged(alias == + // CurrentConnectionIdentifier.connectionName); } } void MainWindow::OnJsonEditRequested(const ConnectionId &id) @@ -835,7 +891,5 @@ void MainWindow::OnJsonEditRequested(const ConnectionId &id) JsonEditor w(ConnectionManager->GetConnectionRoot(id), this); auto root = CONFIGROOT(w.OpenEditor()); - if (w.result() == QDialog::Accepted) { - ConnectionManager->UpdateConnection(id, root); - } + if (w.result() == QDialog::Accepted) { ConnectionManager->UpdateConnection(id, root); } } diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index b43ae600..f7b4dc09 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -1,114 +1,116 @@ #pragma once +#include "common/HTTPRequestHelper.hpp" +#include "common/LogHighlighter.hpp" +#include "components/speedchart/speedwidget.hpp" +#include "core/handler/ConnectionHandler.hpp" +#include "ui/messaging/QvMessageBus.hpp" +#include "ui_w_MainWindow.h" + #include #include #include #include -#include "ui_w_MainWindow.h" - -#include "common/LogHighlighter.hpp" -#include "common/HTTPRequestHelper.hpp" -#include "components/speedchart/speedwidget.hpp" -#include "core/handler/ConnectionHandler.hpp" -#include "ui/messaging/QvMessageBus.hpp" - // ========================================================================================== -#include "ui/widgets/ConnectionItemWidget.hpp" #include "ui/widgets/ConnectionInfoWidget.hpp" +#include "ui/widgets/ConnectionItemWidget.hpp" -class MainWindow : public QMainWindow, Ui::MainWindow +class MainWindow + : public QMainWindow + , Ui::MainWindow { - Q_OBJECT - public: - explicit MainWindow(QWidget *parent = nullptr); - ~MainWindow() override; - signals: - void Connect() const; - void DisConnect() const; - void ReConnect() const; - public slots: - QvMessageBusSlotDecl - private slots: - void on_action_RCM_ShareQR_triggered(); - void on_activatedTray(QSystemTrayIcon::ActivationReason reason); - void on_actionExit_triggered(); - void on_preferencesBtn_clicked(); - void on_clearlogButton_clicked(); - void on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); - void on_connectionListWidget_customContextMenuRequested(const QPoint &pos); - void on_connectionListWidget_itemChanged(QTreeWidgetItem *item, int column); - void on_removeConfigButton_clicked(); - void on_importConfigButton_clicked(); - void on_editConfigButton_clicked(); - void on_subsButton_clicked(); - // - void ToggleVisibility(); + Q_OBJECT + public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow() override; + signals: + void Connect() const; + void DisConnect() const; + void ReConnect() const; + public slots: + QvMessageBusSlotDecl; + private slots: + void on_action_RCM_ShareQR_triggered(); + void on_activatedTray(QSystemTrayIcon::ActivationReason reason); + void on_actionExit_triggered(); + void on_preferencesBtn_clicked(); + void on_clearlogButton_clicked(); + void on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + void on_connectionListWidget_customContextMenuRequested(const QPoint &pos); + void on_connectionListWidget_itemChanged(QTreeWidgetItem *item, int column); + void on_removeConfigButton_clicked(); + void on_importConfigButton_clicked(); + void on_editConfigButton_clicked(); + void on_subsButton_clicked(); + // + void ToggleVisibility(); #ifndef DISABLE_AUTO_UPDATE - void VersionUpdate(QByteArray &data); + void VersionUpdate(QByteArray &data); #endif - // + // - public: - static MainWindow *mwInstance; + public: + static MainWindow *mwInstance; - protected: - void keyPressEvent(QKeyEvent *e) override; - void closeEvent(QCloseEvent *) override; + protected: + void keyPressEvent(QKeyEvent *e) override; + void closeEvent(QCloseEvent *) override; - private slots: - // - void OnConnected(const ConnectionId &id); - void OnDisConnected(const ConnectionId &id); - void OnEditRequested(const ConnectionId &id); - void OnJsonEditRequested(const ConnectionId &id); + private slots: + // + void OnConnected(const ConnectionId &id); + void OnDisConnected(const ConnectionId &id); + void OnEditRequested(const ConnectionId &id); + void OnJsonEditRequested(const ConnectionId &id); - void onConnectionWidgetFocusRequested(const ConnectionItemWidget *widget); - //void onConnectionConnected(const ConnectionId &id); - //void onConnectionDisConnected(const ConnectionId &id); - void onConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, const quint64 totalDown); - void onVCoreLogArrived(const ConnectionId &id, const QString &log); - // - void on_action_StartThis_triggered(); - void on_action_RCM_EditJson_triggered(); - void on_action_RCM_ConvToComplex_triggered(); - void on_action_RCM_RenameConnection_triggered(); - void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); - void on_connectionFilterTxt_textEdited(const QString &arg1); - void on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column); + void onConnectionWidgetFocusRequested(const ConnectionItemWidget *widget); + // void onConnectionConnected(const ConnectionId &id); + // void onConnectionDisConnected(const ConnectionId &id); + void onConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, + const quint64 totalDown); + void onVCoreLogArrived(const ConnectionId &id, const QString &log); + // + void on_action_StartThis_triggered(); + void on_action_RCM_EditJson_triggered(); + void on_action_RCM_ConvToComplex_triggered(); + void on_action_RCM_RenameConnection_triggered(); + void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); + void on_connectionFilterTxt_textEdited(const QString &arg1); + void on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column); - private: - QTreeWidgetItem *CurrentItem; - // Charts - SpeedWidget *speedChartWidget; - QMenu *connectionListMenu; + private: + QTreeWidgetItem *CurrentItem; + // Charts + SpeedWidget *speedChartWidget; + QMenu *connectionListMenu; #ifndef DISABLE_AUTO_UPDATE - QvHttpRequestHelper *requestHelper; + QvHttpRequestHelper *requestHelper; #endif - QSystemTrayIcon hTray; - //PACServer pacServer; - //QvTCPingModel tcpingHelper; - SyntaxHighlighter *vCoreLogHighlighter; - ConnectionInfoWidget *infoWidget; - // - // Actions in the system tray menu - // - QMenu *tray_RootMenu = new QMenu(this); - QAction *action_Tray_ShowHide; - QAction *action_Tray_ShowPreferencesWindow; - QAction *action_Tray_Quit; - // --> Connectivities - QAction *action_Tray_Start; - QAction *action_Tray_Reconnect ; - QAction *action_Tray_Stop; - // --> System proxy settings - QMenu *tray_SystemProxyMenu = new QMenu(this); - QAction *action_Tray_SetSystemProxy; - QAction *action_Tray_ClearSystemProxy; - // - // ----------------------------------- Extra Headers For w_MainWindow_extra.cpp Handling V2ray Connectivities. - bool systemProxyEnabled; - void MWSetSystemProxy(); - void MWClearSystemProxy(bool); - void CheckSubscriptionsUpdate(); + QSystemTrayIcon hTray; + // PACServer pacServer; + // QvTCPingModel tcpingHelper; + SyntaxHighlighter *vCoreLogHighlighter; + ConnectionInfoWidget *infoWidget; + // + // Actions in the system tray menu + // + QMenu *tray_RootMenu = new QMenu(this); + QAction *action_Tray_ShowHide; + QAction *action_Tray_ShowPreferencesWindow; + QAction *action_Tray_Quit; + // --> Connectivities + QAction *action_Tray_Start; + QAction *action_Tray_Reconnect; + QAction *action_Tray_Stop; + // --> System proxy settings + QMenu *tray_SystemProxyMenu = new QMenu(this); + QAction *action_Tray_SetSystemProxy; + QAction *action_Tray_ClearSystemProxy; + // + // ----------------------------------- Extra Headers For w_MainWindow_extra.cpp Handling V2ray Connectivities. + bool systemProxyEnabled; + void MWSetSystemProxy(); + void MWClearSystemProxy(bool); + void CheckSubscriptionsUpdate(); }; diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index 49bf3779..158c7f82 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -1,16 +1,19 @@ -// Supplementary file for MainWindow -- Basically the handler for connectivity management -// and components interactions. -// We NEED to include the cpp file to define the macros. -#include "w_MainWindow.cpp" +// Supplementary file for MainWindow -- Basically the handler for connectivity +// management and components interactions. We NEED to include the cpp file to +// define the macros. #include "components/proxy/QvProxyConfigurator.hpp" +#include "w_MainWindow.cpp" -//QTreeWidgetItem *MainWindow::FindItemByIdentifier(QvConnectionObject identifier) +// QTreeWidgetItem *MainWindow::FindItemByIdentifier(QvConnectionObject +// identifier) //{ // //// First filter out all items with our config name. -// //auto items = connectionListWidget->findItems(identifier.connectionName, Qt::MatchExactly | Qt::MatchRecursive); +// //auto items = connectionListWidget->findItems(identifier.connectionName, +// Qt::MatchExactly | Qt::MatchRecursive); // // // //for (auto item : items) { -// // // This connectable prevents the an item with (which is the parent node of a subscription, having the same +// // // This connectable prevents the an item with (which is the parent +// node of a subscription, having the same // // // -- name as our current connected name) // // if (!IsConnectableItem(item)) { // // LOG(UI, "Invalid Item found: " + item->text(0)) @@ -25,8 +28,8 @@ // // } // //} // // -// //LOG(UI, "Warning: Failed to find an item named: " + identifier.IdentifierString()) -// return nullptr; +// //LOG(UI, "Warning: Failed to find an item named: " + +// identifier.IdentifierString()) return nullptr; //} void MainWindow::MWClearSystemProxy(bool showMessage) @@ -35,9 +38,7 @@ void MainWindow::MWClearSystemProxy(bool showMessage) LOG(MODULE_UI, "Clearing System Proxy") systemProxyEnabled = false; - if (showMessage) { - hTray.showMessage("Qv2ray", tr("System proxy cleared."), windowIcon()); - } + if (showMessage) { hTray.showMessage("Qv2ray", tr("System proxy cleared."), windowIcon()); } } void MainWindow::MWSetSystemProxy() @@ -48,45 +49,58 @@ void MainWindow::MWSetSystemProxy() bool socksEnabled = GlobalConfig.inboundConfig.useSocks; // // Set system proxy if necessary - //bool isComplex = IsComplexConfig(connections[CurrentConnectionIdentifier].config); + // bool isComplex = + // IsComplexConfig(connections[CurrentConnectionIdentifier].config); bool isComplex = true; - if (!isComplex) { + if (!isComplex) + { // Is simple config and we will try to set system proxy. LOG(MODULE_UI, "Preparing to set system proxy") // QString proxyAddress; bool canSetSystemProxy = true; - if (usePAC) { - if ((httpEnabled && !pacUseSocks) || (socksEnabled && pacUseSocks)) { + if (usePAC) + { + if ((httpEnabled && !pacUseSocks) || (socksEnabled && pacUseSocks)) + { // If we use PAC and socks/http are properly configured for PAC LOG(MODULE_PROXY, "System proxy uses PAC") - proxyAddress = "http://" + GlobalConfig.inboundConfig.listenip + ":" + QSTRN(GlobalConfig.inboundConfig.pacConfig.port) + "/pac"; - } else { + proxyAddress = "http://" + GlobalConfig.inboundConfig.listenip + ":" + QSTRN(GlobalConfig.inboundConfig.pacConfig.port) + "/pac"; + } + else + { // Not properly configured LOG(MODULE_PROXY, "Failed to process pac due to following reasons:") LOG(MODULE_PROXY, " --> PAC is configured to use socks but socks is not enabled.") LOG(MODULE_PROXY, " --> PAC is configuted to use http but http is not enabled.") - QvMessageBoxWarn(this, tr("PAC Processing Failed"), tr("HTTP or SOCKS inbound is not properly configured for PAC") + - NEWLINE + tr("Qv2ray will continue, but will not set system proxy.")); + QvMessageBoxWarn(this, tr("PAC Processing Failed"), + tr("HTTP or SOCKS inbound is not properly configured for PAC") + NEWLINE + + tr("Qv2ray will continue, but will not set system proxy.")); canSetSystemProxy = false; } - } else { + } + else + { // Not using PAC - if (httpEnabled || socksEnabled) { + if (httpEnabled || socksEnabled) + { // Not use PAC, System proxy should use HTTP or SOCKS LOG(MODULE_PROXY, "Setting up system proxy.") // A 'proxy host' should be a host WITHOUT `http://` uri scheme proxyAddress = "localhost"; - } else { + } + else + { LOG(MODULE_PROXY, "Neither of HTTP nor SOCKS is enabled, cannot set system proxy.") QvMessageBoxWarn(this, tr("Cannot set system proxy"), tr("Both HTTP and SOCKS inbounds are not enabled")); canSetSystemProxy = false; } } - if (canSetSystemProxy) { + if (canSetSystemProxy) + { LOG(MODULE_UI, "Setting system proxy for simple config.") auto httpPort = GlobalConfig.inboundConfig.useHTTP ? GlobalConfig.inboundConfig.http_port : 0; auto socksPort = GlobalConfig.inboundConfig.useSocks ? GlobalConfig.inboundConfig.socks_port : 0; @@ -96,7 +110,9 @@ void MainWindow::MWSetSystemProxy() systemProxyEnabled = true; hTray.showMessage("Qv2ray", tr("System proxy settings applied."), windowIcon()); } - } else { + } + else + { hTray.showMessage("Qv2ray", tr("Cannot set proxy for complex config."), windowIcon()); } } @@ -105,28 +121,29 @@ void MainWindow::CheckSubscriptionsUpdate() { QStringList updateList; - for (auto index = 0; index < GlobalConfig.subscriptions.count(); index++) { + for (auto index = 0; index < GlobalConfig.subscriptions.count(); index++) + { auto subs = GlobalConfig.subscriptions.values()[index]; auto key = GlobalConfig.subscriptions.keys()[index]; // auto lastRenewDate = QDateTime::fromTime_t(subs.lastUpdated); auto renewTime = lastRenewDate.addSecs(subs.updateInterval * 86400); - LOG(MODULE_SUBSCRIPTION, "Subscription \"" + key + "\": " + NEWLINE + - " --> Last renewal time: " + lastRenewDate.toString() + NEWLINE + - " --> Renew interval: " + QSTRN(subs.updateInterval) + NEWLINE + - " --> Ideal renew time: " + renewTime.toString()) + LOG(MODULE_SUBSCRIPTION, "Subscription \"" + key + "\": " + NEWLINE + " --> Last renewal time: " + lastRenewDate.toString() + NEWLINE + + " --> Renew interval: " + QSTRN(subs.updateInterval) + NEWLINE + + " --> Ideal renew time: " + renewTime.toString()) - if (renewTime <= QDateTime::currentDateTime()) { + if (renewTime <= QDateTime::currentDateTime()) + { LOG(MODULE_SUBSCRIPTION, "Subscription: " + key + " needs to be updated.") updateList.append(key); } } - if (!updateList.isEmpty()) { + if (!updateList.isEmpty()) + { QvMessageBoxWarn(this, tr("Update Subscriptions"), - tr("There are subscriptions need to be updated, please go to subscriptions window to update them.") + NEWLINE + NEWLINE + - tr("These subscriptions are out-of-date: ") + NEWLINE + updateList.join(";")); + tr("There are subscriptions need to be updated, please go to subscriptions window to update them.") + NEWLINE + + NEWLINE + tr("These subscriptions are out-of-date: ") + NEWLINE + updateList.join(";")); on_subsButton_clicked(); } } - diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index bfb8a8ae..61f9a0e9 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -1,27 +1,28 @@ #include "w_PreferencesWindow.hpp" -#include -#include -#include -#include -#include - -#include "common/QvHelpers.hpp" #include "common/HTTPRequestHelper.hpp" +#include "common/QvHelpers.hpp" +#include "common/QvTranslator.hpp" +#include "components/autolaunch/QvAutoLaunch.hpp" +#include "components/plugins/toolbar/QvToolbar.hpp" #include "core/config/ConfigBackend.hpp" #include "core/connection/ConnectionIO.hpp" -#include "core/kernel/KernelInteractions.hpp" #include "core/handler/ConnectionHandler.hpp" -#include "components/plugins/toolbar/QvToolbar.hpp" -#include "components/autolaunch/QvAutoLaunch.hpp" -#include "common/QvTranslator.hpp" +#include "core/kernel/KernelInteractions.hpp" + +#include +#include +#include +#include +#include using Qv2ray::common::validation::IsValidIPAddress; -#define LOADINGCHECK if(!finishedLoading) return; -#define NEEDRESTART if(finishedLoading) IsConnectionPropertyChanged = true; +#define LOADINGCHECK \ + if (!finishedLoading) return; +#define NEEDRESTART \ + if (finishedLoading) IsConnectionPropertyChanged = true; -PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), - CurrentConfig() +PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), CurrentConfig() { setupUi(this); QvMessageBusConnect(PreferencesWindow); @@ -31,17 +32,14 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), // Set network Toolbar page state. networkToolbarPage->setEnabled(StartupOption.enableToolbarPlguin); - if (!StartupOption.enableToolbarPlguin) { - networkToolbarInfoLabel->setText(tr("Qv2ray Network Toolbar is disabled and still under test. Add --withToolbarPlugin to enable.")); - } + if (!StartupOption.enableToolbarPlguin) + { networkToolbarInfoLabel->setText(tr("Qv2ray Network Toolbar is disabled and still under test. Add --withToolbarPlugin to enable.")); } // We add locales languageComboBox->clear(); QDirIterator it(":/translations"); - while (it.hasNext()) { - languageComboBox->addItem(it.next().split("/").last().split(".").first()); - } + while (it.hasNext()) { languageComboBox->addItem(it.next().split("/").last().split(".").first()); } // Set auto start button state SetAutoStartButtonsState(GetLaunchAtLoginStatus()); @@ -120,26 +118,30 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), // DNSListTxt->clear(); - for (auto dnsStr : CurrentConfig.connectionConfig.dnsList) { + for (auto dnsStr : CurrentConfig.connectionConfig.dnsList) + { auto str = dnsStr.trimmed(); - if (!str.isEmpty()) { - DNSListTxt->appendPlainText(str); - } + if (!str.isEmpty()) { DNSListTxt->appendPlainText(str); } } // cancelIgnoreVersionBtn->setEnabled(CurrentConfig.ignoredVersion != ""); ignoredNextVersion->setText(CurrentConfig.ignoredVersion); - for (auto i = 0; i < CurrentConfig.toolBarConfig.Pages.size(); i++) { - nsBarPagesList->addItem(tr("Page") + QSTRN(i + 1) + ": " + QSTRN(CurrentConfig.toolBarConfig.Pages[i].Lines.size()) + " " + tr("Item(s)")); + for (auto i = 0; i < CurrentConfig.toolBarConfig.Pages.size(); i++) + { + nsBarPagesList->addItem(tr("Page") + QSTRN(i + 1) + ": " + QSTRN(CurrentConfig.toolBarConfig.Pages[i].Lines.size()) + " " + + tr("Item(s)")); } - if (CurrentConfig.toolBarConfig.Pages.size() > 0) { + if (CurrentConfig.toolBarConfig.Pages.size() > 0) + { nsBarPagesList->setCurrentRow(0); on_nsBarPagesList_currentRowChanged(0); - } else { + } + else + { networkToolbarSettingsFrame->setEnabled(false); nsBarLinesList->setEnabled(false); nsBarLineDelBTN->setEnabled(false); @@ -153,22 +155,17 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), auto autoStartConnId = ConnectionId(CurrentConfig.autoStartId); auto autoStartGroupId = ConnectionManager->GetConnectionGroupId(autoStartConnId); - for (auto group : ConnectionManager->AllGroups()) { - autoStartSubsCombo->addItem(ConnectionManager->GetDisplayName(group)); - } + for (auto group : ConnectionManager->AllGroups()) { autoStartSubsCombo->addItem(ConnectionManager->GetDisplayName(group)); } autoStartSubsCombo->setCurrentText(ConnectionManager->GetDisplayName(autoStartGroupId)); - for (auto conn : ConnectionManager->Connections(autoStartGroupId)) { - autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(conn)); - } + for (auto conn : ConnectionManager->Connections(autoStartGroupId)) { autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(conn)); } autoStartConnCombo->setCurrentText(ConnectionManager->GetDisplayName(autoStartConnId)); // FP Settings - if (CurrentConfig.connectionConfig.forwardProxyConfig.type.trimmed().isEmpty()) { - CurrentConfig.connectionConfig.forwardProxyConfig.type = "http"; - } + if (CurrentConfig.connectionConfig.forwardProxyConfig.type.trimmed().isEmpty()) + { CurrentConfig.connectionConfig.forwardProxyConfig.type = "http"; } fpGroupBox->setChecked(CurrentConfig.connectionConfig.forwardProxyConfig.enableForwardProxy); fpUsernameTx->setText(CurrentConfig.connectionConfig.forwardProxyConfig.username); @@ -182,18 +179,17 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), // maxLogLinesSB->setValue(CurrentConfig.uiConfig.maximumLogLines); // - pacListenAddrLabel->setText("http://" + (pacProxyTxt->text().isEmpty() ? "127.0.0.1" : pacProxyTxt->text()) + ":" + QSTRN(pacPortSB->value()) + "/pac"); + pacListenAddrLabel->setText("http://" + (pacProxyTxt->text().isEmpty() ? "127.0.0.1" : pacProxyTxt->text()) + ":" + + QSTRN(pacPortSB->value()) + "/pac"); // finishedLoading = true; } - QvMessageBusSlotImpl(PreferencesWindow) { - switch (msg) { - MBShowDefaultImpl - MBHideDefaultImpl - MBRetranslateDefaultImpl + switch (msg) + { + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl } } @@ -204,45 +200,57 @@ PreferencesWindow::~PreferencesWindow() void PreferencesWindow::on_buttonBox_accepted() { // Note: - // A signal-slot connection from buttonbox_accpted to QDialog::accepted() has been removed. - // To prevent closing this Dialog. + // A signal-slot connection from buttonbox_accpted to QDialog::accepted() + // has been removed. To prevent closing this Dialog. QSet ports; auto size = 0; - if (CurrentConfig.inboundConfig.useHTTP) { - size ++; + if (CurrentConfig.inboundConfig.useHTTP) + { + size++; ports << CurrentConfig.inboundConfig.http_port; } - if (CurrentConfig.inboundConfig.useSocks) { - size ++; + if (CurrentConfig.inboundConfig.useSocks) + { + size++; ports << CurrentConfig.inboundConfig.socks_port; } - if (CurrentConfig.inboundConfig.pacConfig.enablePAC) { - size ++; + if (CurrentConfig.inboundConfig.pacConfig.enablePAC) + { + size++; ports << CurrentConfig.inboundConfig.pacConfig.port; } - if (!StartupOption.noAPI) { - size ++; + if (!StartupOption.noAPI) + { + size++; ports << CurrentConfig.apiConfig.statsPort; } - if (ports.size() != size) { + if (ports.size() != size) + { // Duplicates detected. QvMessageBoxWarn(this, tr("Preferences"), tr("Duplicated port numbers detected, please check the port number settings.")); - } else if (CurrentConfig.inboundConfig.listenip.toLower() != "localhost" && !IsValidIPAddress(CurrentConfig.inboundConfig.listenip)) { - QvMessageBoxWarn(this, tr("Preferences"), tr("Invalid inbound listening address."));; - } else { - if (CurrentConfig.uiConfig.language != GlobalConfig.uiConfig.language) { + } + else if (CurrentConfig.inboundConfig.listenip.toLower() != "localhost" && !IsValidIPAddress(CurrentConfig.inboundConfig.listenip)) + { + QvMessageBoxWarn(this, tr("Preferences"), tr("Invalid inbound listening address.")); + ; + } + else + { + if (CurrentConfig.uiConfig.language != GlobalConfig.uiConfig.language) + { qApp->removeTranslator(Qv2rayTranslator.get()); Qv2rayTranslator = std::move(QvTranslator(CurrentConfig.uiConfig.language).pTranslator); // Install translator - if (!qApp->installTranslator(Qv2rayTranslator.get())) { - LOG(MODULE_UI, "Failed to translate UI to: " + CurrentConfig.uiConfig.language) - } else { + if (!qApp->installTranslator(Qv2rayTranslator.get())) + { LOG(MODULE_UI, "Failed to translate UI to: " + CurrentConfig.uiConfig.language) } + else + { messageBus.EmitGlobalSignal(QvMBMessage::RETRANSLATE); QApplication::processEvents(); } @@ -296,13 +304,14 @@ void PreferencesWindow::on_listenIPTxt_textEdited(const QString &arg1) NEEDRESTART CurrentConfig.inboundConfig.listenip = arg1; - if (IsValidIPAddress(arg1)) { - BLACK(listenIPTxt) - } else { + if (IsValidIPAddress(arg1)) { BLACK(listenIPTxt) } + else + { RED(listenIPTxt) } - //pacAccessPathTxt->setText("http://" + arg1 + ":" + QSTRN(pacPortSB->value()) + "/pac"); + // pacAccessPathTxt->setText("http://" + arg1 + ":" + + // QSTRN(pacPortSB->value()) + "/pac"); } void PreferencesWindow::on_httpAuthUsernameTxt_textEdited(const QString &arg1) @@ -346,7 +355,8 @@ void PreferencesWindow::on_selectVAssetBtn_clicked() NEEDRESTART QString dir = QFileDialog::getExistingDirectory(this, tr("Open V2ray assets folder"), QDir::currentPath()); - if (!dir.isEmpty()) { + if (!dir.isEmpty()) + { vCoreAssetsPathTxt->setText(dir); on_vCoreAssetsPathTxt_textEdited(dir); } @@ -356,7 +366,8 @@ void PreferencesWindow::on_selectVCoreBtn_clicked() { QString core = QFileDialog::getOpenFileName(this, tr("Open V2ray core file"), QDir::currentPath()); - if (!core.isEmpty()) { + if (!core.isEmpty()) + { vCorePathTxt->setText(core); on_vCorePathTxt_textEdited(core); } @@ -370,13 +381,17 @@ void PreferencesWindow::on_vCorePathTxt_textEdited(const QString &arg1) void PreferencesWindow::on_DNSListTxt_textChanged() { - if (finishedLoading) { - try { + if (finishedLoading) + { + try + { QStringList hosts = DNSListTxt->toPlainText().replace("\r", "").split("\n"); CurrentConfig.connectionConfig.dnsList.clear(); - foreach (auto host, hosts) { - if (host != "" && host != "\r") { + foreach (auto host, hosts) + { + if (host != "" && host != "\r") + { // Not empty, so we save. CurrentConfig.connectionConfig.dnsList.push_back(host); NEEDRESTART @@ -384,7 +399,9 @@ void PreferencesWindow::on_DNSListTxt_textChanged() } BLACK(DNSListTxt) - } catch (...) { + } + catch (...) + { RED(DNSListTxt) } } @@ -408,19 +425,25 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) // Setting up tProxy for linux // Steps: - // --> 1. Copy V2ray core files to the QV2RAY_TPROXY_VCORE_PATH and QV2RAY_TPROXY_VCTL_PATH dir. + // --> 1. Copy V2ray core files to the QV2RAY_TPROXY_VCORE_PATH and + // QV2RAY_TPROXY_VCTL_PATH dir. // --> 2. Change GlobalConfig.v2CorePath. - // --> 3. Call `pkexec setcap CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip` on the V2ray core. - if (arg1 == Qt::Checked) { + // --> 3. Call `pkexec setcap + // CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip` on the V2ray core. + if (arg1 == Qt::Checked) + { // We enable it! if (QvMessageBoxAsk(this, tr("Enable tProxy Support"), - tr("This will append capabilities to the V2ray executable.") + NEWLINE + NEWLINE + - tr("Qv2ray will copy your V2ray core to this path: ") + NEWLINE + QV2RAY_TPROXY_VCORE_PATH + NEWLINE + NEWLINE + - tr("If anything goes wrong after enabling this, please check issue #57 or the link below:") + NEWLINE + - " https://github.com/Qv2ray/Qv2ray/wiki/FAQ ") != QMessageBox::Yes) { + tr("This will append capabilities to the V2ray executable.") + NEWLINE + NEWLINE + + tr("Qv2ray will copy your V2ray core to this path: ") + NEWLINE + QV2RAY_TPROXY_VCORE_PATH + NEWLINE + NEWLINE + + tr("If anything goes wrong after enabling this, please check issue #57 or the link below:") + NEWLINE + + " https://github.com/Qv2ray/Qv2ray/wiki/FAQ ") != QMessageBox::Yes) + { tProxyCheckBox->setChecked(false); LOG(MODULE_UI, "Canceled enabling tProxy feature.") - } else { + } + else + { LOG(MODULE_VCORE, "ENABLING tProxy Support") LOG(MODULE_FILEIO, " --> Origin V2ray core file is at: " + CurrentConfig.v2CorePath) auto v2ctlPath = QFileInfo(CurrentConfig.v2CorePath).absolutePath() + "/v2ctl"; @@ -433,17 +456,22 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) // LOG(MODULE_FILEIO, " --> Copying files....") - if (QFileInfo(CurrentConfig.v2CorePath).absoluteFilePath() != QFileInfo(QV2RAY_TPROXY_VCORE_PATH).absoluteFilePath()) { - // Only trying to remove file when they are not in the default dir. - // (In other words...) Keep using the current files. + if (QFileInfo(CurrentConfig.v2CorePath).absoluteFilePath() != QFileInfo(QV2RAY_TPROXY_VCORE_PATH).absoluteFilePath()) + { + // Only trying to remove file when they are not in the default + // dir. (In other words...) Keep using the current files. + // // - if (QFile(QV2RAY_TPROXY_VCORE_PATH).exists()) { + if (QFile(QV2RAY_TPROXY_VCORE_PATH).exists()) + { LOG(MODULE_FILEIO, QString(QV2RAY_TPROXY_VCORE_PATH) + ": File already exists.") LOG(MODULE_FILEIO, QString(QV2RAY_TPROXY_VCORE_PATH) + ": Deleting file.") QFile(QV2RAY_TPROXY_VCORE_PATH).remove(); } - if (QFile(QV2RAY_TPROXY_VCTL_PATH).exists()) { + if (QFile(QV2RAY_TPROXY_VCTL_PATH).exists()) + { LOG(MODULE_FILEIO, QV2RAY_TPROXY_VCTL_PATH + ": File already exists.") LOG(MODULE_FILEIO, QV2RAY_TPROXY_VCTL_PATH + ": Deleting file.") QFile(QV2RAY_TPROXY_VCTL_PATH).remove(); @@ -456,18 +484,22 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) LOG(MODULE_FILEIO, " --> V2ray Ctl: " + vCtlresult) // - if (vCoreresult == "OK" && vCtlresult == "OK") { + if (vCoreresult == "OK" && vCtlresult == "OK") + { LOG(MODULE_VCORE, " --> Done copying files.") on_vCorePathTxt_textEdited(QV2RAY_TPROXY_VCORE_PATH); - } else { + } + else + { LOG(MODULE_VCORE, "FAILED to copy V2ray files. Aborting.") QvMessageBoxWarn(this, tr("Enable tProxy Support"), - tr("Qv2ray cannot copy one or both V2ray files from: ") + NEWLINE + NEWLINE + - CurrentConfig.v2CorePath + NEWLINE + v2ctlPath + NEWLINE + NEWLINE + - tr("to this path: ") + NEWLINE + newPath); + tr("Qv2ray cannot copy one or both V2ray files from: ") + NEWLINE + NEWLINE + CurrentConfig.v2CorePath + + NEWLINE + v2ctlPath + NEWLINE + NEWLINE + tr("to this path: ") + NEWLINE + newPath); return; } - } else { + } + else + { LOG(MODULE_VCORE, "Skipped removing files since the current V2ray core is in the default path.") LOG(MODULE_VCORE, " --> Actually because we don't know where else to obtain the files.") } @@ -475,7 +507,8 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) LOG(MODULE_UI, "Calling pkexec and setcap...") int ret = QProcess::execute("pkexec setcap CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip " + CurrentConfig.v2CorePath); - if (ret != 0) { + if (ret != 0) + { LOG(MODULE_UI, "WARN: setcap exits with code: " + QSTRN(ret)) QvMessageBoxWarn(this, tr("Preferences"), tr("Failed to setcap onto V2ray executable. You may need to run `setcap` manually.")); } @@ -483,10 +516,13 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) CurrentConfig.tProxySupport = true; NEEDRESTART } - } else { + } + else + { int ret = QProcess::execute("pkexec setcap -r " + CurrentConfig.v2CorePath); - if (ret != 0) { + if (ret != 0) + { LOG(MODULE_UI, "WARN: setcap exits with code: " + QSTRN(ret)) QvMessageBoxWarn(this, tr("Preferences"), tr("Failed to setcap onto V2ray executable. You may need to run `setcap` manually.")); } @@ -540,14 +576,15 @@ void PreferencesWindow::on_socksUDPIP_textEdited(const QString &arg1) NEEDRESTART CurrentConfig.inboundConfig.socksLocalIP = arg1; - if (IsValidIPAddress(arg1)) { - BLACK(socksUDPIP) - } else { + if (IsValidIPAddress(arg1)) { BLACK(socksUDPIP) } + else + { RED(socksUDPIP) } } -// ------------------- NET SPEED PLUGIN OPERATIONS ----------------------------------------------------------------- +// ------------------- NET SPEED PLUGIN OPERATIONS +// ----------------------------------------------------------------- #define CurrentBarPage CurrentConfig.toolBarConfig.Pages[this->CurrentBarPageId] #define CurrentBarLine CurrentBarPage.Lines[this->CurrentBarLineId] @@ -557,7 +594,7 @@ void PreferencesWindow::on_nsBarPageAddBTN_clicked() { QvBarPage page; CurrentConfig.toolBarConfig.Pages.push_back(page); - CurrentBarPageId = CurrentConfig.toolBarConfig.Pages.size() - 1 ; + CurrentBarPageId = CurrentConfig.toolBarConfig.Pages.size() - 1; // Add default line. QvBarLine line; CurrentBarPage.Lines.push_back(line); @@ -576,11 +613,13 @@ void PreferencesWindow::on_nsBarPageAddBTN_clicked() void PreferencesWindow::on_nsBarPageDelBTN_clicked() { - if (nsBarPagesList->currentRow() >= 0) { + if (nsBarPagesList->currentRow() >= 0) + { CurrentConfig.toolBarConfig.Pages.removeAt(nsBarPagesList->currentRow()); nsBarPagesList->takeItem(nsBarPagesList->currentRow()); - if (nsBarPagesList->count() <= 0) { + if (nsBarPagesList->count() <= 0) + { nsBarPageDelBTN->setEnabled(false); nsBarLineAddBTN->setEnabled(false); nsBarLineDelBTN->setEnabled(false); @@ -613,12 +652,14 @@ void PreferencesWindow::on_nsBarLineAddBTN_clicked() void PreferencesWindow::on_nsBarLineDelBTN_clicked() { - if (nsBarLinesList->currentRow() >= 0) { + if (nsBarLinesList->currentRow() >= 0) + { CurrentBarPage.Lines.removeAt(nsBarLinesList->currentRow()); nsBarLinesList->takeItem(nsBarLinesList->currentRow()); CurrentBarLineId = 0; - if (nsBarLinesList->count() <= 0) { + if (nsBarLinesList->count() <= 0) + { networkToolbarSettingsFrame->setEnabled(false); nsBarLineDelBTN->setEnabled(false); } @@ -639,15 +680,19 @@ void PreferencesWindow::on_nsBarPagesList_currentRowChanged(int currentRow) nsBarPageYOffset->setValue(CurrentBarPage.OffsetYpx); nsBarLinesList->clear(); - if (!CurrentBarPage.Lines.empty()) { - for (auto line : CurrentBarPage.Lines) { + if (!CurrentBarPage.Lines.empty()) + { + for (auto line : CurrentBarPage.Lines) + { auto description = GetBarLineDescription(line); nsBarLinesList->addItem(description); } nsBarLinesList->setCurrentRow(0); ShowLineParameters(CurrentBarLine); - } else { + } + else + { networkToolbarSettingsFrame->setEnabled(false); } } @@ -725,11 +770,9 @@ QString PreferencesWindow::GetBarLineDescription(QvBarLine barLine) QString result = "Empty"; result = NetSpeedPluginMessages[barLine.ContentType]; - if (barLine.ContentType == 0) { - result += " (" + barLine.Message + ")"; - } + if (barLine.ContentType == 0) { result += " (" + barLine.Message + ")"; } - result = result.append(barLine.Bold ? ", " + tr("Bold") : ""); + result = result.append(barLine.Bold ? ", " + tr("Bold") : ""); result = result.append(barLine.Italic ? ", " + tr("Italic") : ""); return result; } @@ -738,9 +781,7 @@ void PreferencesWindow::ShowLineParameters(QvBarLine &barLine) { finishedLoading = false; - if (!barLine.Family.isEmpty()) { - fontComboBox->setCurrentFont(QFont(barLine.Family)); - } + if (!barLine.Family.isEmpty()) { fontComboBox->setCurrentFont(QFont(barLine.Family)); } // Colors nsBarFontASB->setValue(barLine.ColorA); @@ -749,10 +790,9 @@ void PreferencesWindow::ShowLineParameters(QvBarLine &barLine) nsBarFontRSB->setValue(barLine.ColorR); // QColor color = QColor::fromRgb(barLine.ColorR, barLine.ColorG, barLine.ColorB, barLine.ColorA); - QString s(QStringLiteral("background: #") - + ((color.red() < 16) ? "0" : "") + QString::number(color.red(), 16) - + ((color.green() < 16) ? "0" : "") + QString::number(color.green(), 16) - + ((color.blue() < 16) ? "0" : "") + QString::number(color.blue(), 16) + ";"); + QString s(QStringLiteral("background: #") + ((color.red() < 16) ? "0" : "") + QString::number(color.red(), 16) + + ((color.green() < 16) ? "0" : "") + QString::number(color.green(), 16) + ((color.blue() < 16) ? "0" : "") + + QString::number(color.blue(), 16) + ";"); chooseColorBtn->setStyleSheet(s); nsBarFontSizeSB->setValue(barLine.Size); nsBarFontBoldCB->setChecked(barLine.Bold); @@ -769,7 +809,8 @@ void PreferencesWindow::on_chooseColorBtn_clicked() QColorDialog d(QColor::fromRgb(CurrentBarLine.ColorR, CurrentBarLine.ColorG, CurrentBarLine.ColorB, CurrentBarLine.ColorA), this); d.exec(); - if (d.result() == QDialog::DialogCode::Accepted) { + if (d.result() == QDialog::DialogCode::Accepted) + { d.selectedColor().getRgb(&CurrentBarLine.ColorR, &CurrentBarLine.ColorG, &CurrentBarLine.ColorB, &CurrentBarLine.ColorA); ShowLineParameters(CurrentBarLine); SET_LINE_LIST_TEXT @@ -792,9 +833,10 @@ void PreferencesWindow::on_nsBarContentCombo_currentIndexChanged(const QString & void PreferencesWindow::on_applyNSBarSettingsBtn_clicked() { - if (QvMessageBoxAsk(this, tr("Apply network toolbar settings"), tr("All other modified settings will be applied as well after this object.") + - NEWLINE + - tr("Do you want to continue?")) == QMessageBox::Yes) { + if (QvMessageBoxAsk(this, tr("Apply network toolbar settings"), + tr("All other modified settings will be applied as well after this object.") + NEWLINE + + tr("Do you want to continue?")) == QMessageBox::Yes) + { auto conf = GlobalConfig; conf.toolBarConfig = CurrentConfig.toolBarConfig; SaveGlobalConfig(conf); @@ -815,7 +857,8 @@ void PreferencesWindow::on_darkThemeCB_stateChanged(int arg1) #ifdef QV2RAY_USE_BUILTIN_DARKTHEME themeCombo->setEnabled(arg1 != Qt::Checked); - if (arg1 == Qt::Checked) { + if (arg1 == Qt::Checked) + { themeCombo->setCurrentIndex(QStyleFactory::keys().indexOf("Fusion")); CurrentConfig.uiConfig.theme = "Fusion"; } @@ -840,7 +883,8 @@ void PreferencesWindow::on_pacGoBtn_clicked() LOG(MODULE_PROXY, "Downloading GFWList file.") bool withProxy = getGFWListWithProxyCB->isChecked(); - switch (gfwListCB->currentIndex()) { + switch (gfwListCB->currentIndex()) + { case 0: gfwLocation = "https://gitlab.com/gfwlist/gfwlist/raw/master/gfwlist.txt"; fileContent = QString::fromUtf8(request.syncget(gfwLocation, withProxy)); @@ -874,7 +918,8 @@ void PreferencesWindow::on_pacGoBtn_clicked() case 6: auto file = QFileDialog::getOpenFileName(this, tr("Select GFWList in base64")); - if (file.isEmpty()) { + if (file.isEmpty()) + { QvMessageBoxWarn(this, tr("Download GFWList"), tr("Operation is cancelled.")); return; } @@ -888,9 +933,7 @@ void PreferencesWindow::on_pacGoBtn_clicked() pacGoBtn->setEnabled(true); gfwListCB->setEnabled(true); - if (!QDir(QV2RAY_RULES_DIR).exists()) { - QDir(QV2RAY_RULES_DIR).mkpath(QV2RAY_RULES_DIR); - } + if (!QDir(QV2RAY_RULES_DIR).exists()) { QDir(QV2RAY_RULES_DIR).mkpath(QV2RAY_RULES_DIR); } StringToFile(fileContent, QV2RAY_RULES_GFWLIST_PATH); } @@ -900,7 +943,8 @@ void PreferencesWindow::on_pacPortSB_valueChanged(int arg1) LOADINGCHECK NEEDRESTART CurrentConfig.inboundConfig.pacConfig.port = arg1; - pacListenAddrLabel->setText("http://" + (pacProxyTxt->text().isEmpty() ? "127.0.0.1" : pacProxyTxt->text()) + ":" + QSTRN(pacPortSB->value()) + "/pac"); + pacListenAddrLabel->setText("http://" + (pacProxyTxt->text().isEmpty() ? "127.0.0.1" : pacProxyTxt->text()) + ":" + + QSTRN(pacPortSB->value()) + "/pac"); } void PreferencesWindow::on_setSysProxyCB_stateChanged(int arg1) @@ -939,9 +983,7 @@ void PreferencesWindow::on_autoStartSubsCombo_currentIndexChanged(const QString auto list = ConnectionManager->Connections(groupId); autoStartConnCombo->clear(); - for (auto id : list) { - autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(id)); - } + for (auto id : list) { autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(id)); } } void PreferencesWindow::on_autoStartConnCombo_currentIndexChanged(const QString &arg1) @@ -955,9 +997,7 @@ void PreferencesWindow::on_startWithLoginCB_stateChanged(int arg1) bool isEnabled = arg1 == Qt::Checked; SetLaunchAtLoginStatus(isEnabled); - if (GetLaunchAtLoginStatus() != isEnabled) { - QvMessageBoxWarn(this, tr("Start with boot"), tr("Failed to set auto start option.")); - } + if (GetLaunchAtLoginStatus() != isEnabled) { QvMessageBoxWarn(this, tr("Start with boot"), tr("Failed to set auto start option.")); } SetAutoStartButtonsState(GetLaunchAtLoginStatus()); } @@ -978,9 +1018,9 @@ void PreferencesWindow::on_fpAddressTx_textEdited(const QString &arg1) LOADINGCHECK CurrentConfig.connectionConfig.forwardProxyConfig.serverAddress = arg1; - if (IsValidIPAddress(arg1)) { - BLACK(fpAddressTx) - } else { + if (IsValidIPAddress(arg1)) { BLACK(fpAddressTx) } + else + { RED(fpAddressTx) } } @@ -1021,13 +1061,14 @@ void PreferencesWindow::on_pacProxyTxt_textChanged(const QString &arg1) { Q_UNUSED(arg1) - if (IsValidIPAddress(arg1)) { - BLACK(pacProxyTxt) - } else { + if (IsValidIPAddress(arg1)) { BLACK(pacProxyTxt) } + else + { RED(pacProxyTxt) } - pacListenAddrLabel->setText("http://" + (pacProxyTxt->text().isEmpty() ? "127.0.0.1" : pacProxyTxt->text()) + ":" + QSTRN(pacPortSB->value()) + "/pac"); + pacListenAddrLabel->setText("http://" + (pacProxyTxt->text().isEmpty() ? "127.0.0.1" : pacProxyTxt->text()) + ":" + + QSTRN(pacPortSB->value()) + "/pac"); } void PreferencesWindow::on_checkVCoreSettings_clicked() @@ -1036,11 +1077,12 @@ void PreferencesWindow::on_checkVCoreSettings_clicked() auto vAssetsPath = vCoreAssetsPathTxt->text(); QString result; - if (!V2rayKernelInstance::ValidateKernel(vcorePath, vAssetsPath, &result)) { - QvMessageBoxWarn(this, tr("V2ray Core Settings"), result); - } else { - QvMessageBoxInfo(this, tr("V2ray Core Settings"), tr("V2ray path configuration check passed.") + NEWLINE + NEWLINE + - tr("Current version of V2ray is: ") + NEWLINE + result); + if (!V2rayKernelInstance::ValidateKernel(vcorePath, vAssetsPath, &result)) { QvMessageBoxWarn(this, tr("V2ray Core Settings"), result); } + else + { + QvMessageBoxInfo(this, tr("V2ray Core Settings"), + tr("V2ray path configuration check passed.") + NEWLINE + NEWLINE + tr("Current version of V2ray is: ") + NEWLINE + + result); } } diff --git a/src/ui/w_PreferencesWindow.hpp b/src/ui/w_PreferencesWindow.hpp index 5fba2a5c..06348abe 100644 --- a/src/ui/w_PreferencesWindow.hpp +++ b/src/ui/w_PreferencesWindow.hpp @@ -1,180 +1,183 @@ #pragma once -#include -#include #include "base/Qv2rayBase.hpp" #include "ui/messaging/QvMessageBus.hpp" -class PreferencesWindow : public QDialog, private Ui::PreferencesWindow +#include +#include + +class PreferencesWindow + : public QDialog + , private Ui::PreferencesWindow { - Q_OBJECT + Q_OBJECT - public: - explicit PreferencesWindow(QWidget *parent = nullptr); - ~PreferencesWindow(); - signals: - void s_reload_config(bool need_restart); + public: + explicit PreferencesWindow(QWidget *parent = nullptr); + ~PreferencesWindow(); + signals: + void s_reload_config(bool need_restart); - public slots: - QvMessageBusSlotDecl + public slots: + QvMessageBusSlotDecl; - private slots: - void on_buttonBox_accepted(); + private slots: + void on_buttonBox_accepted(); - void on_httpAuthCB_stateChanged(int arg1); + void on_httpAuthCB_stateChanged(int arg1); - void on_socksAuthCB_stateChanged(int arg1); + void on_socksAuthCB_stateChanged(int arg1); - void on_languageComboBox_currentTextChanged(const QString &arg1); + void on_languageComboBox_currentTextChanged(const QString &arg1); - void on_logLevelComboBox_currentIndexChanged(int index); + void on_logLevelComboBox_currentIndexChanged(int index); - void on_vCoreAssetsPathTxt_textEdited(const QString &arg1); + void on_vCoreAssetsPathTxt_textEdited(const QString &arg1); - void on_listenIPTxt_textEdited(const QString &arg1); + void on_listenIPTxt_textEdited(const QString &arg1); - void on_socksPortLE_valueChanged(int arg1); + void on_socksPortLE_valueChanged(int arg1); - void on_httpPortLE_valueChanged(int arg1); + void on_httpPortLE_valueChanged(int arg1); - void on_httpAuthUsernameTxt_textEdited(const QString &arg1); + void on_httpAuthUsernameTxt_textEdited(const QString &arg1); - void on_httpAuthPasswordTxt_textEdited(const QString &arg1); + void on_httpAuthPasswordTxt_textEdited(const QString &arg1); - void on_socksAuthUsernameTxt_textEdited(const QString &arg1); + void on_socksAuthUsernameTxt_textEdited(const QString &arg1); - void on_socksAuthPasswordTxt_textEdited(const QString &arg1); + void on_socksAuthPasswordTxt_textEdited(const QString &arg1); - void on_proxyDefaultCb_stateChanged(int arg1); + void on_proxyDefaultCb_stateChanged(int arg1); - void on_localDNSCb_stateChanged(int arg1); + void on_localDNSCb_stateChanged(int arg1); - void on_selectVAssetBtn_clicked(); + void on_selectVAssetBtn_clicked(); - void on_DNSListTxt_textChanged(); + void on_DNSListTxt_textChanged(); - void on_aboutQt_clicked(); + void on_aboutQt_clicked(); - void on_cancelIgnoreVersionBtn_clicked(); + void on_cancelIgnoreVersionBtn_clicked(); - void on_tProxyCheckBox_stateChanged(int arg1); + void on_tProxyCheckBox_stateChanged(int arg1); - void on_bypassCNCb_stateChanged(int arg1); + void on_bypassCNCb_stateChanged(int arg1); - void on_statsPortBox_valueChanged(int arg1); + void on_statsPortBox_valueChanged(int arg1); - void on_socksUDPCB_stateChanged(int arg1); + void on_socksUDPCB_stateChanged(int arg1); - void on_socksUDPIP_textEdited(const QString &arg1); + void on_socksUDPIP_textEdited(const QString &arg1); - void on_nsBarPageAddBTN_clicked(); + void on_nsBarPageAddBTN_clicked(); - void on_nsBarPageDelBTN_clicked(); + void on_nsBarPageDelBTN_clicked(); - void on_nsBarPageYOffset_valueChanged(int arg1); + void on_nsBarPageYOffset_valueChanged(int arg1); - void on_nsBarLineAddBTN_clicked(); + void on_nsBarLineAddBTN_clicked(); - void on_nsBarLineDelBTN_clicked(); + void on_nsBarLineDelBTN_clicked(); - void on_nsBarPagesList_currentRowChanged(int currentRow); + void on_nsBarPagesList_currentRowChanged(int currentRow); - void on_nsBarLinesList_currentRowChanged(int currentRow); + void on_nsBarLinesList_currentRowChanged(int currentRow); - void on_fontComboBox_currentFontChanged(const QFont &f); + void on_fontComboBox_currentFontChanged(const QFont &f); - void on_nsBarFontBoldCB_stateChanged(int arg1); + void on_nsBarFontBoldCB_stateChanged(int arg1); - void on_nsBarFontItalicCB_stateChanged(int arg1); + void on_nsBarFontItalicCB_stateChanged(int arg1); - void on_nsBarFontASB_valueChanged(int arg1); + void on_nsBarFontASB_valueChanged(int arg1); - void on_nsBarFontRSB_valueChanged(int arg1); + void on_nsBarFontRSB_valueChanged(int arg1); - void on_nsBarFontGSB_valueChanged(int arg1); + void on_nsBarFontGSB_valueChanged(int arg1); - void on_nsBarFontBSB_valueChanged(int arg1); + void on_nsBarFontBSB_valueChanged(int arg1); - void on_nsBarFontSizeSB_valueChanged(double arg1); + void on_nsBarFontSizeSB_valueChanged(double arg1); - void on_chooseColorBtn_clicked(); + void on_chooseColorBtn_clicked(); - void on_nsBarTagTxt_textEdited(const QString &arg1); + void on_nsBarTagTxt_textEdited(const QString &arg1); - void on_nsBarContentCombo_currentIndexChanged(const QString &arg1); + void on_nsBarContentCombo_currentIndexChanged(const QString &arg1); - void on_applyNSBarSettingsBtn_clicked(); + void on_applyNSBarSettingsBtn_clicked(); - void on_selectVCoreBtn_clicked(); + void on_selectVCoreBtn_clicked(); - void on_vCorePathTxt_textEdited(const QString &arg1); + void on_vCorePathTxt_textEdited(const QString &arg1); - void on_themeCombo_currentTextChanged(const QString &arg1); + void on_themeCombo_currentTextChanged(const QString &arg1); - void on_darkThemeCB_stateChanged(int arg1); + void on_darkThemeCB_stateChanged(int arg1); - void on_darkTrayCB_stateChanged(int arg1); + void on_darkTrayCB_stateChanged(int arg1); - void on_pacGoBtn_clicked(); + void on_pacGoBtn_clicked(); - void on_pacPortSB_valueChanged(int arg1); + void on_pacPortSB_valueChanged(int arg1); - void on_setSysProxyCB_stateChanged(int arg1); + void on_setSysProxyCB_stateChanged(int arg1); - void on_pacProxyCB_currentIndexChanged(int index); + void on_pacProxyCB_currentIndexChanged(int index); - void on_pushButton_clicked(); + void on_pushButton_clicked(); - void on_pacProxyTxt_textEdited(const QString &arg1); + void on_pacProxyTxt_textEdited(const QString &arg1); - void on_autoStartSubsCombo_currentIndexChanged(const QString &arg1); + void on_autoStartSubsCombo_currentIndexChanged(const QString &arg1); - void on_autoStartConnCombo_currentIndexChanged(const QString &arg1); + void on_autoStartConnCombo_currentIndexChanged(const QString &arg1); - void on_fpTypeCombo_currentIndexChanged(const QString &arg1); + void on_fpTypeCombo_currentIndexChanged(const QString &arg1); - void on_fpAddressTx_textEdited(const QString &arg1); + void on_fpAddressTx_textEdited(const QString &arg1); - void on_spPortSB_valueChanged(int arg1); + void on_spPortSB_valueChanged(int arg1); - void on_fpUseAuthCB_stateChanged(int arg1); + void on_fpUseAuthCB_stateChanged(int arg1); - void on_fpUsernameTx_textEdited(const QString &arg1); + void on_fpUsernameTx_textEdited(const QString &arg1); - void on_fpPasswordTx_textEdited(const QString &arg1); + void on_fpPasswordTx_textEdited(const QString &arg1); - void on_fpPortSB_valueChanged(int arg1); + void on_fpPortSB_valueChanged(int arg1); - void on_pacProxyTxt_textChanged(const QString &arg1); + void on_pacProxyTxt_textChanged(const QString &arg1); - void on_checkVCoreSettings_clicked(); + void on_checkVCoreSettings_clicked(); - void on_httpGroupBox_clicked(bool checked); + void on_httpGroupBox_clicked(bool checked); - void on_socksGroupBox_clicked(bool checked); + void on_socksGroupBox_clicked(bool checked); - void on_pacGroupBox_clicked(bool checked); + void on_pacGroupBox_clicked(bool checked); - void on_fpGroupBox_clicked(bool checked); + void on_fpGroupBox_clicked(bool checked); - void on_maxLogLinesSB_valueChanged(int arg1); + void on_maxLogLinesSB_valueChanged(int arg1); - void on_enableAPI_stateChanged(int arg1); + void on_enableAPI_stateChanged(int arg1); - void on_startWithLoginCB_stateChanged(int arg1); + void on_startWithLoginCB_stateChanged(int arg1); - void on_tProxyGroupBox_clicked(bool checked); + void on_tProxyGroupBox_clicked(bool checked); - private: - void SetAutoStartButtonsState(bool isAutoStart); - // Set ui parameters for a line; - void ShowLineParameters(QvBarLine &line); - QString GetBarLineDescription(QvBarLine line); - // - int CurrentBarLineId; - int CurrentBarPageId; - // - bool IsConnectionPropertyChanged = false; - bool finishedLoading = false; - Qv2rayConfig CurrentConfig; + private: + void SetAutoStartButtonsState(bool isAutoStart); + // Set ui parameters for a line; + void ShowLineParameters(QvBarLine &line); + QString GetBarLineDescription(QvBarLine line); + // + int CurrentBarLineId; + int CurrentBarPageId; + // + bool IsConnectionPropertyChanged = false; + bool finishedLoading = false; + Qv2rayConfig CurrentConfig; }; diff --git a/src/ui/w_ScreenShot_Core.cpp b/src/ui/w_ScreenShot_Core.cpp index 598562ca..1af073f0 100644 --- a/src/ui/w_ScreenShot_Core.cpp +++ b/src/ui/w_ScreenShot_Core.cpp @@ -1,15 +1,18 @@ #include "w_ScreenShot_Core.hpp" + #include "common/QvHelpers.hpp" + #include -#include #include +#include #define QV2RAY_SCREENSHOT_DIM_RATIO 0.6f ScreenShotWindow::ScreenShotWindow() : QDialog(), rubber(new QRubberBand(QRubberBand::Rectangle, this)) { setupUi(this); - // Fusion prevents the KDE Plasma Breeze's "Move window when dragging in the empty area" issue + // Fusion prevents the KDE Plasma Breeze's "Move window when dragging in the + // empty area" issue this->setStyle(QStyleFactory::create("Fusion")); // label->setAttribute(Qt::WA_TranslucentBackground); @@ -30,8 +33,9 @@ ScreenShotWindow::ScreenShotWindow() : QDialog(), rubber(new QRubberBand(QRubber QImage ScreenShotWindow::DoScreenShot() { LOG(MODULE_IMPORT, "We currently only support the current screen.") - // The msleep is the only solution which prevent capturing our windows again. - // It works on KDE, https://www.qtcentre.org/threads/55708-Get-Desktop-Screenshot-Without-Application-Window-Being-Shown?p=248993#post248993 + // The msleep is the only solution which prevent capturing our windows + // again. It works on KDE, + // https://www.qtcentre.org/threads/55708-Get-Desktop-Screenshot-Without-Application-Window-Being-Shown?p=248993#post248993 QThread::msleep(100); QApplication::processEvents(); // @@ -45,8 +49,10 @@ QImage ScreenShotWindow::DoScreenShot() int r, g, b; auto _xdesktopImg = desktopImage.toImage(); - for (int i = 0; i < w; i++) { - for (int j = 0; j < h; j++) { + for (int i = 0; i < w; i++) + { + for (int j = 0; j < h; j++) + { r = static_cast(qRed(_xdesktopImg.pixel(i, j)) * QV2RAY_SCREENSHOT_DIM_RATIO); g = static_cast(qGreen(_xdesktopImg.pixel(i, j)) * QV2RAY_SCREENSHOT_DIM_RATIO); b = static_cast(qBlue(_xdesktopImg.pixel(i, j)) * QV2RAY_SCREENSHOT_DIM_RATIO); @@ -72,16 +78,18 @@ void ScreenShotWindow::pSize() imgH = abs(end.y() - origin.y()); imgX = origin.x() < end.x() ? origin.x() : end.x(); imgY = origin.y() < end.y() ? origin.y() : end.y(); - DEBUG("Capture Mouse Position", QSTRN(imgW) + " " + QSTRN(imgH) + " " + QSTRN(imgX) + " " + QSTRN(imgY)) + DEBUG("Capture Mouse Position", QSTRN(imgW) + " " + QSTRN(imgH) + " " + QSTRN(imgX) + " " + QSTRN(imgY)) rubber->setGeometry(imgX, imgY, imgW, imgH); fg->setGeometry(rubber->geometry()); - auto copied = desktopImage.copy(fg->x() * devicePixelRatio(), fg->y() * devicePixelRatio(), fg->width() * devicePixelRatio(), fg->height() * devicePixelRatio()); + auto copied = desktopImage.copy(fg->x() * devicePixelRatio(), fg->y() * devicePixelRatio(), fg->width() * devicePixelRatio(), + fg->height() * devicePixelRatio()); fg->setPixmap(copied); } bool ScreenShotWindow::event(QEvent *e) { - if (e->type() == QEvent::Move) { + if (e->type() == QEvent::Move) + { // } @@ -90,9 +98,9 @@ bool ScreenShotWindow::event(QEvent *e) void ScreenShotWindow::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape) { - reject(); - } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { + if (e->key() == Qt::Key_Escape) { reject(); } + else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) + { on_startBtn_clicked(); } } @@ -103,13 +111,14 @@ void ScreenShotWindow::mousePressEvent(QMouseEvent *e) rubber->setGeometry(origin.x(), origin.y(), 0, 0); rubber->show(); rubber->raise(); - //label->hide(); - //startBtn->hide(); + // label->hide(); + // startBtn->hide(); } void ScreenShotWindow::mouseMoveEvent(QMouseEvent *e) { - if (e->buttons() & Qt::LeftButton) { + if (e->buttons() & Qt::LeftButton) + { end = e->pos(); pSize(); // @@ -120,15 +129,15 @@ void ScreenShotWindow::mouseMoveEvent(QMouseEvent *e) QRect labelRect(label->contentsRect()); QRect btnRect(startBtn->contentsRect()); - if (imgY > labelRect.height()) { - label->move(imgX, imgY - labelRect.height()); - } else { + if (imgY > labelRect.height()) { label->move(imgX, imgY - labelRect.height()); } + else + { label->move(imgX, imgY); } - if (height() - imgY - imgH > btnRect.height()) { - startBtn->move(imgX + imgW - btnRect.width(), imgY + imgH); - } else { + if (height() - imgY - imgH > btnRect.height()) { startBtn->move(imgX + imgW - btnRect.width(), imgY + imgH); } + else + { startBtn->move(imgX + imgW - btnRect.width(), imgY + imgH - btnRect.height()); } @@ -137,12 +146,9 @@ void ScreenShotWindow::mouseMoveEvent(QMouseEvent *e) } } - void ScreenShotWindow::mouseReleaseEvent(QMouseEvent *e) { - if (e->button() == Qt::RightButton) { - reject(); - } + if (e->button() == Qt::RightButton) { reject(); } } ScreenShotWindow::~ScreenShotWindow() diff --git a/src/ui/w_ScreenShot_Core.hpp b/src/ui/w_ScreenShot_Core.hpp index 747e7394..b74da91b 100644 --- a/src/ui/w_ScreenShot_Core.hpp +++ b/src/ui/w_ScreenShot_Core.hpp @@ -1,46 +1,48 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "ui_w_ScreenShot_Core.h" -class ScreenShotWindow : public QDialog, private Ui::ScreenShot +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class ScreenShotWindow + : public QDialog + , private Ui::ScreenShot { - Q_OBJECT + Q_OBJECT - public: - ScreenShotWindow(); - ~ScreenShotWindow(); - QImage DoScreenShot(); - // - void mouseMoveEvent(QMouseEvent *e) override; - void mousePressEvent(QMouseEvent *e) override; - void mouseReleaseEvent(QMouseEvent *e) override; - void keyPressEvent(QKeyEvent *e) override; + public: + ScreenShotWindow(); + ~ScreenShotWindow(); + QImage DoScreenShot(); + // + void mouseMoveEvent(QMouseEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; + void keyPressEvent(QKeyEvent *e) override; - protected: - bool event(QEvent *e) override; + protected: + bool event(QEvent *e) override; - private slots: - void on_startBtn_clicked(); + private slots: + void on_startBtn_clicked(); - private: - QRubberBand *rubber; - // Desktop Image - QPixmap desktopImage; - QImage windowBg; - QImage resultImage; - // - QPoint origin; - QPoint end; - int imgW, imgH, imgX, imgY; + private: + QRubberBand *rubber; + // Desktop Image + QPixmap desktopImage; + QImage windowBg; + QImage resultImage; + // + QPoint origin; + QPoint end; + int imgW, imgH, imgX, imgY; - void pSize(); + void pSize(); }; diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 84236a40..d07a4b10 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -1,33 +1,31 @@ #include "w_SubscriptionManager.hpp" + #include "common/QvHelpers.hpp" #include "core/config/ConfigBackend.hpp" #include "core/handler/ConnectionHandler.hpp" -SubscribeEditor::SubscribeEditor(QWidget *parent) : - QDialog(parent) +SubscribeEditor::SubscribeEditor(QWidget *parent) : QDialog(parent) { setupUi(this); QvMessageBusConnect(SubscribeEditor); addSubsButton->setIcon(QICON_R("add.png")); removeSubsButton->setIcon(QICON_R("delete.png")); - for (auto subs : ConnectionManager->Subscriptions()) { - subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList() << ConnectionManager->GetDisplayName(subs) << subs.toString())); - } + for (auto subs : ConnectionManager->Subscriptions()) + { subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList() << ConnectionManager->GetDisplayName(subs) << subs.toString())); } } QvMessageBusSlotImpl(SubscribeEditor) { - switch (msg) { - MBShowDefaultImpl - MBHideDefaultImpl - MBRetranslateDefaultImpl + switch (msg) + { + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl } } QPair SubscribeEditor::GetSelectedConfig() { - return QPair (); + return QPair(); } SubscribeEditor::~SubscribeEditor() @@ -46,22 +44,26 @@ void SubscribeEditor::on_addSubsButton_clicked() void SubscribeEditor::on_updateButton_clicked() { - //auto newName = subNameTxt->text().trimmed(); - //auto newAddress = subAddrTxt->text().trimmed(); - //auto newUpdateInterval = updateIntervalSB->value(); - //if (currentSubId != newName) { + ConnectionManager->UpdateSubscription(currentSubId, withProxyCB->isChecked()); + // auto newName = subNameTxt->text().trimmed(); + // auto newAddress = subAddrTxt->text().trimmed(); + // auto newUpdateInterval = updateIntervalSB->value(); + // if (currentSubId != newName) { // // Rename needed. - // LOG(MODULE_SUBSCRIPTION, "Renaming a subscription, from " + currentSubId + " to: " + newName) - // bool canGo = true; + // LOG(MODULE_SUBSCRIPTION, "Renaming a subscription, from " + + // currentSubId + " to: " + newName) bool canGo = true; // // if (newName.isEmpty() || !IsValidFileName(newName)) { - // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("The subscription name is invalid, please try another.")); - // canGo = false; + // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("The + // subscription name is invalid, please try another.")); canGo = + // false; // } // - // if (subscriptionList->findItems(newName, Qt::MatchExactly).count() > 0) { - // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("New name of this subscription has been used already, please suggest another one")); - // canGo = false; + // if (subscriptionList->findItems(newName, Qt::MatchExactly).count() > + // 0) { + // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("New name + // of this subscription has been used already, please suggest another + // one")); canGo = false; // } // // if (!canGo) { @@ -72,7 +74,8 @@ void SubscribeEditor::on_updateButton_clicked() // ////bool result = RenameSubscription(currentSubName, newName); // // // //if (!result) { - // // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("Failed to rename a subscription, this is an unknown error.")); + // // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("Failed + // to rename a subscription, this is an unknown error.")); // // return; // //} // subscriptions[newName] = subscriptions[currentSubId]; @@ -93,68 +96,45 @@ void SubscribeEditor::on_updateButton_clicked() // // Update thing still down // subAddrTxt->setText(newAddress); // updateIntervalSB->setValue(newUpdateInterval); - // QvMessageBoxInfo(this, tr("Renaming a subscription"), tr("Successfully renamed a subscription")); + // QvMessageBoxInfo(this, tr("Renaming a subscription"), tr("Successfully + // renamed a subscription")); //} // - //subscriptions[currentSubId].updateInterval = newUpdateInterval; + // subscriptions[currentSubId].updateInterval = newUpdateInterval; // - //if (subscriptions[currentSubId].address != newAddress) { - // LOG(MODULE_SUBSCRIPTION, "Setting new address, from " + subscriptions[currentSubId].address + " to: " + newAddress) + // if (subscriptions[currentSubId].address != newAddress) { + // LOG(MODULE_SUBSCRIPTION, "Setting new address, from " + + // subscriptions[currentSubId].address + " to: " + newAddress) // subscriptions[currentSubId].address = newAddress; //} // ////SaveConfig(); // - ////if (QvMessageBoxAsk(this, tr("Update Subscription"), tr("Would you like to reload this subscription from the Url?")) == QMessageBox::Yes) { - //// StartUpdateSubscription(currentSubId); + ////if (QvMessageBoxAsk(this, tr("Update Subscription"), tr("Would you like + /// to reload this subscription from the Url?")) == QMessageBox::Yes) { / + /// StartUpdateSubscription(currentSubId); ////} } void SubscribeEditor::StartUpdateSubscription(const QString &subscriptionName) { this->setEnabled(false); - // auto data = helper.syncget(subscriptions[subscriptionName].address, withProxyCB->isChecked()); - // auto content = DecodeSubscriptionString(data).trimmed(); - //if (!content.isEmpty()) { - // connectionsList->clear(); - // auto vmessList = SplitLines(content); - // QDir(QV2RAY_SUBSCRIPTION_DIR + subscriptionName).removeRecursively(); - // QDir().mkpath(QV2RAY_SUBSCRIPTION_DIR + subscriptionName); - // - // for (auto vmess : vmessList) { - // QString errMessage; - // QString _alias; - // auto config = ConvertConfigFromString(vmess.trimmed(), &_alias, &errMessage); - // - // if (!errMessage.isEmpty()) { - // LOG(MODULE_SUBSCRIPTION, "Processing a subscription with following error: " + errMessage) - // } else { - // //SaveSubscriptionConfig(config, subscriptionName, &_alias); - // connectionsList->addItem(_alias); - // } - // } - // - // subscriptions[subscriptionName].lastUpdated = system_clock::to_time_t(system_clock::now()); - // lastUpdatedLabel->setText(timeToString(subscriptions[subscriptionName].lastUpdated)); - // isUpdateInProgress = false; - //} else { - // LOG(MODULE_NETWORK, "We have received an empty string from the URL.") - // QvMessageBoxWarn(this, tr("Updating subscriptions"), tr("Failed to process the result from the upstream, please check your Url.")); - //} - // + // auto data = helper.syncget(subscriptions[subscriptionName].address, + // withProxyCB->isChecked()); auto content = + this->setEnabled(true); } void SubscribeEditor::on_removeSubsButton_clicked() { - //if (subscriptionList->currentRow() < 0) + // if (subscriptionList->currentRow() < 0) // return; // - //auto name = subscriptionList->currentItem()->text(); - //subscriptionList->takeItem(subscriptionList->currentRow()); - //subscriptions.remove(name); + // auto name = subscriptionList->currentItem()->text(); + // subscriptionList->takeItem(subscriptionList->currentRow()); + // subscriptions.remove(name); // - //if (!name.isEmpty()) { + // if (!name.isEmpty()) { // QDir(QV2RAY_SUBSCRIPTION_DIR + name).removeRecursively(); //} // @@ -163,22 +143,22 @@ void SubscribeEditor::on_removeSubsButton_clicked() //// GlobalConfig.autoStartConfig = QvConnectionObject(); //// SaveGlobalConfig(GlobalConfig); ////} - //groupBox_2->setEnabled(subscriptionList->count() > 0); - //SaveConfig(); + // groupBox_2->setEnabled(subscriptionList->count() > 0); + // SaveConfig(); } void SubscribeEditor::SaveConfig() { - //QMap newConf; + // QMap newConf; // - //for (auto _ : subscriptions.toStdMap()) { + // for (auto _ : subscriptions.toStdMap()) { // if (!_.second.address.isEmpty()) { // newConf[_.first] = _.second; // } //} // - //GlobalConfig.subscriptions = newConf; - //SaveGlobalConfig(GlobalConfig); + // GlobalConfig.subscriptions = newConf; + // SaveGlobalConfig(GlobalConfig); } void SubscribeEditor::on_buttonBox_accepted() @@ -195,9 +175,7 @@ void SubscribeEditor::on_subscriptionList_itemClicked(QTreeWidgetItem *item, int { Q_UNUSED(column) - if (item == nullptr) { - return; - } + if (item == nullptr) { return; } currentSubId = GroupId(item->text(1)); // @@ -209,7 +187,5 @@ void SubscribeEditor::on_subscriptionList_itemClicked(QTreeWidgetItem *item, int // connectionsList->clear(); - for (auto conn : ConnectionManager->Connections(currentSubId)) { - connectionsList->addItem(ConnectionManager->GetDisplayName(conn)); - } + for (auto conn : ConnectionManager->Connections(currentSubId)) { connectionsList->addItem(ConnectionManager->GetDisplayName(conn)); } } diff --git a/src/ui/w_SubscriptionManager.hpp b/src/ui/w_SubscriptionManager.hpp index b8e8a7db..b0e5350c 100644 --- a/src/ui/w_SubscriptionManager.hpp +++ b/src/ui/w_SubscriptionManager.hpp @@ -1,40 +1,43 @@ #pragma once -#include #include "base/Qv2rayBase.hpp" -#include "ui_w_SubscriptionManager.h" -#include "ui/messaging/QvMessageBus.hpp" #include "core/CoreSafeTypes.hpp" +#include "ui/messaging/QvMessageBus.hpp" +#include "ui_w_SubscriptionManager.h" -class SubscribeEditor : public QDialog, private Ui::w_SubscribeEditor +#include + +class SubscribeEditor + : public QDialog + , private Ui::w_SubscribeEditor { - Q_OBJECT + Q_OBJECT - public: - explicit SubscribeEditor(QWidget *parent = nullptr); - ~SubscribeEditor(); - QPair GetSelectedConfig(); + public: + explicit SubscribeEditor(QWidget *parent = nullptr); + ~SubscribeEditor(); + QPair GetSelectedConfig(); - public slots: - QvMessageBusSlotDecl + public slots: + QvMessageBusSlotDecl; - private slots: - void on_addSubsButton_clicked(); + private slots: + void on_addSubsButton_clicked(); - void on_updateButton_clicked(); + void on_updateButton_clicked(); - void on_removeSubsButton_clicked(); + void on_removeSubsButton_clicked(); - void on_buttonBox_accepted(); + void on_buttonBox_accepted(); - void on_subscriptionList_itemSelectionChanged(); + void on_subscriptionList_itemSelectionChanged(); - void on_subscriptionList_itemClicked(QTreeWidgetItem *item, int column); + void on_subscriptionList_itemClicked(QTreeWidgetItem *item, int column); - private: - void StartUpdateSubscription(const QString &subscriptionName); - void SaveConfig(); + private: + void StartUpdateSubscription(const QString &subscriptionName); + void SaveConfig(); - bool isUpdateInProgress = false; - GroupId currentSubId = NullGroupId; + bool isUpdateInProgress = false; + GroupId currentSubId = NullGroupId; }; diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 5e3143b7..bd96f337 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -1,9 +1,10 @@ #include "ConnectionInfoWidget.hpp" + +#include "3rdparty/qzxing/src/QZXing.h" #include "core/CoreUtils.hpp" #include "core/connection/Serialization.hpp" -#include "3rdparty/qzxing/src/QZXing.h" -ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent): QWidget(parent) +ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) { setupUi(this); duplicateBtn->setIcon(QICON_R("duplicate.png")); @@ -12,7 +13,8 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent): QWidget(parent) editJsonBtn->setIcon(QICON_R("json.png")); // shareLinkTxt->setAutoFillBackground(true); - shareLinkTxt->setStyleSheet("border-bottom: 1px solid gray; border-radius: 0px; padding: 2px; background-color: " + this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); + shareLinkTxt->setStyleSheet("border-bottom: 1px solid gray; border-radius: 0px; padding: 2px; background-color: " + + this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); shareLinkTxt->setCursor(QCursor(Qt::CursorShape::IBeamCursor)); shareLinkTxt->installEventFilter(this); // @@ -30,10 +32,12 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden duplicateBtn->setEnabled(isConnection); editBtn->setEnabled(isConnection); - if (isConnection) { + if (isConnection) + { groupLabel->setText(ConnectionManager->GetDisplayName(groupId, 175)); protocolLabel->setText(ConnectionManager->GetConnectionProtocolString(connectionId)); - auto [host, port] = ConnectionManager->GetConnectionInfo(connectionId); + auto [protocol, host, port] = ConnectionManager->GetConnectionData(connectionId); + Q_UNUSED(protocol) addressLabel->setText(host); portLabel->setNum(port); // @@ -48,7 +52,9 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden qrLabel->setPixmap(QPixmap::fromImage(img)); // connectBtn->setIcon(ConnectionManager->IsConnected(connectionId) ? QICON_R("stop.png") : QICON_R("connect.png")); - } else { + } + else + { connectBtn->setIcon(QICON_R("connect.png")); groupLabel->setText(tr("N/A")); protocolLabel->setText(tr("N/A")); @@ -66,9 +72,9 @@ ConnectionInfoWidget::~ConnectionInfoWidget() void ConnectionInfoWidget::on_connectBtn_clicked() { - if (ConnectionManager->IsConnected(connectionId)) { - ConnectionManager->StopConnection(); - } else { + if (ConnectionManager->IsConnected(connectionId)) { ConnectionManager->StopConnection(); } + else + { ConnectionManager->StartConnection(connectionId); } } @@ -90,11 +96,11 @@ void ConnectionInfoWidget::on_deleteBtn_clicked() bool ConnectionInfoWidget::eventFilter(QObject *object, QEvent *event) { - if (event->type() == QEvent::MouseButtonRelease) { - if (shareLinkTxt->underMouse()) { - if (!shareLinkTxt->hasSelectedText()) { - shareLinkTxt->selectAll(); - } + if (event->type() == QEvent::MouseButtonRelease) + { + if (shareLinkTxt->underMouse()) + { + if (!shareLinkTxt->hasSelectedText()) { shareLinkTxt->selectAll(); } } } @@ -103,51 +109,50 @@ bool ConnectionInfoWidget::eventFilter(QObject *object, QEvent *event) void ConnectionInfoWidget::OnConnected(const ConnectionId &id) { - if (connectionId == id) { - connectBtn->setIcon(QICON_R("stop.png")); - } + if (connectionId == id) { connectBtn->setIcon(QICON_R("stop.png")); } } void ConnectionInfoWidget::OnDisConnected(const ConnectionId &id) { - if (connectionId == id) { - connectBtn->setIcon(QICON_R("connect.png")); - } + if (connectionId == id) { connectBtn->setIcon(QICON_R("connect.png")); } } -//MWTryPingConnection(CurrentConnectionIdentifier); +// MWTryPingConnection(CurrentConnectionIdentifier); void ConnectionInfoWidget::on_duplicateBtn_clicked() { - //QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - //if (!IsSelectionConnectable) { + // QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); + // if (!IsSelectionConnectable) { // return; //} // - //auto selectedFirst = connectionListWidget->currentItem(); - //auto _identifier = ItemConnectionIdentifier(selectedFirst); - //SUBSCRIPTION_CONFIG_MODIFY_ASK(selectedFirst) - //CONFIGROOT conf; + // auto selectedFirst = connectionListWidget->currentItem(); + // auto _identifier = ItemConnectionIdentifier(selectedFirst); + // SUBSCRIPTION_CONFIG_MODIFY_ASK(selectedFirst) + // CONFIGROOT conf; //// Alias may change. - //QString alias = _identifier.connectionName; - //bool isComplex = IsComplexConfig(connections[_identifier].config); + // QString alias = _identifier.connectionName; + // bool isComplex = IsComplexConfig(connections[_identifier].config); // - //if (connections[_identifier].configType == CONNECTION_REGULAR) { - // conf = ConvertConfigFromFile(QV2RAY_CONFIG_DIR + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex); + // if (connections[_identifier].configType == CONNECTION_REGULAR) { + // conf = ConvertConfigFromFile(QV2RAY_CONFIG_DIR + + // _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex); //} else { - // conf = ConvertConfigFromFile(QV2RAY_SUBSCRIPTION_DIR + _identifier.subscriptionName + "/" + _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex); - // alias = _identifier.subscriptionName + "_" + _identifier.connectionName; + // conf = ConvertConfigFromFile(QV2RAY_SUBSCRIPTION_DIR + + // _identifier.subscriptionName + "/" + _identifier.connectionName + + // QV2RAY_CONFIG_FILE_EXTENSION, isComplex); alias = + // _identifier.subscriptionName + "_" + _identifier.connectionName; //} // - //SaveConnectionConfig(conf, &alias, false); - //GlobalConfig.configs.push_back(alias); - //SaveGlobalConfig(GlobalConfig); - //this->OnConfigListChanged(false);} + // SaveConnectionConfig(conf, &alias, false); + // GlobalConfig.configs.push_back(alias); + // SaveGlobalConfig(GlobalConfig); + // this->OnConfigListChanged(false);} } void ConnectionInfoWidget::on_latencyBtn_clicked() { - if (connectionId != NullConnectionId) { - ConnectionManager->StartLatencyTest(connectionId); - } else { + if (connectionId != NullConnectionId) { ConnectionManager->StartLatencyTest(connectionId); } + else + { ConnectionManager->StartLatencyTest(groupId); } } diff --git a/src/ui/widgets/ConnectionInfoWidget.hpp b/src/ui/widgets/ConnectionInfoWidget.hpp index 968b88e1..2d87e0e8 100644 --- a/src/ui/widgets/ConnectionInfoWidget.hpp +++ b/src/ui/widgets/ConnectionInfoWidget.hpp @@ -1,39 +1,41 @@ #pragma once -#include -#include "ui_ConnectionInfoWidget.h" #include "core/handler/ConnectionHandler.hpp" +#include "ui_ConnectionInfoWidget.h" -class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget +#include + +class ConnectionInfoWidget + : public QWidget + , private Ui::ConnectionInfoWidget { - Q_OBJECT + Q_OBJECT - public: - explicit ConnectionInfoWidget(QWidget *parent = nullptr); - void ShowDetails(const tuple &_identifier); - ~ConnectionInfoWidget(); + public: + explicit ConnectionInfoWidget(QWidget *parent = nullptr); + void ShowDetails(const tuple &_identifier); + ~ConnectionInfoWidget(); - signals: - void OnEditRequested(const ConnectionId &id); - void OnJsonEditRequested(const ConnectionId &id); + signals: + void OnEditRequested(const ConnectionId &id); + void OnJsonEditRequested(const ConnectionId &id); - private slots: - void on_connectBtn_clicked(); - void on_editBtn_clicked(); - void on_editJsonBtn_clicked(); - void on_deleteBtn_clicked(); + private slots: + void on_connectBtn_clicked(); + void on_editBtn_clicked(); + void on_editJsonBtn_clicked(); + void on_deleteBtn_clicked(); - protected: - bool eventFilter(QObject *object, QEvent *event) override; + protected: + bool eventFilter(QObject *object, QEvent *event) override; - private slots: - void OnConnected(const ConnectionId &id); - void OnDisConnected(const ConnectionId &id); - void on_duplicateBtn_clicked(); - void on_latencyBtn_clicked(); + private slots: + void OnConnected(const ConnectionId &id); + void OnDisConnected(const ConnectionId &id); + void on_duplicateBtn_clicked(); + void on_latencyBtn_clicked(); - private: - ConnectionId connectionId = NullConnectionId; - GroupId groupId = NullGroupId; + private: + ConnectionId connectionId = NullConnectionId; + GroupId groupId = NullGroupId; }; - diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index 6e52bffc..483b76fb 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -1,4 +1,5 @@ #include "ConnectionItemWidget.hpp" + #include "common/QvHelpers.hpp" ConnectionItemWidget::ConnectionItemWidget(QWidget *parent) : QWidget(parent), connectionId("null"), groupId("null") @@ -11,7 +12,7 @@ ConnectionItemWidget::ConnectionItemWidget(QWidget *parent) : QWidget(parent), c connect(ConnectionManager, &QvConnectionHandler::OnLatencyTestFinished, this, &ConnectionItemWidget::OnLatencyTestFinished); } -ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *parent): ConnectionItemWidget(parent) +ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *parent) : ConnectionItemWidget(parent) { connectionId = id; groupId = ConnectionManager->GetConnectionGroupId(id); @@ -21,9 +22,9 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare // TODO auto latency = ConnectionManager->GetConnectionLatency(id); - if (latency == 0) { - latencyLabel->setText(tr("Not Tested")); - } else { + if (latency == 0) { latencyLabel->setText(tr("Not Tested")); } + else + { latencyLabel->setText(QSTRN(latency) + " " + tr("ms")); } @@ -52,16 +53,17 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : void ConnectionItemWidget::BeginConnection() { - if (itemType == NODE_ITEM) { - ConnectionManager->StartConnection(connectionId); - } else { + if (itemType == NODE_ITEM) { ConnectionManager->StartConnection(connectionId); } + else + { LOG(MODULE_UI, "Trying to start a non-connection entry, this call is illegal.") } } void ConnectionItemWidget::OnConnected(const ConnectionId &id) { - if (id == connectionId) { + if (id == connectionId) + { connNameLabel->setText("• " + originalConnectionName); LOG(MODULE_UI, "OnConnected signal received for: " + id.toString()) emit RequestWidgetFocus(this); @@ -70,34 +72,33 @@ void ConnectionItemWidget::OnConnected(const ConnectionId &id) void ConnectionItemWidget::OnDisConnected(const ConnectionId &id) { - if (id == connectionId) { - connNameLabel->setText(originalConnectionName); - } + if (id == connectionId) { connNameLabel->setText(originalConnectionName); } } -void ConnectionItemWidget::OnConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, const quint64 totalDown) +void ConnectionItemWidget::OnConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, + const quint64 totalUp, const quint64 totalDown) { Q_UNUSED(upSpeed) Q_UNUSED(downSpeed) - if (id == connectionId) { - dataLabel->setText(FormatBytes(totalUp) + " / " + FormatBytes(totalDown)); - } + if (id == connectionId) { dataLabel->setText(FormatBytes(totalUp) + " / " + FormatBytes(totalDown)); } } void ConnectionItemWidget::OnLatencyTestStart(const ConnectionId &id) { - if (id == connectionId) { - latencyLabel->setText(tr("Testing...")); - } + if (id == connectionId) { latencyLabel->setText(tr("Testing...")); } } void ConnectionItemWidget::OnLatencyTestFinished(const ConnectionId &id, const uint average) { - if (id == connectionId) { - if (average == 0) { + if (id == connectionId) + { + if (average == 0) + { latencyLabel->setText(tr("Error")); RED(latencyLabel) - } else { + } + else + { latencyLabel->setText(QSTRN(average) + tr("ms")); BLACK(latencyLabel) } diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index 9aad5c8c..05b1b0d3 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -1,57 +1,63 @@ #pragma once -#include -#include "ui_ConnectionItemWidget.h" #include "core/handler/ConnectionHandler.hpp" +#include "ui_ConnectionItemWidget.h" -enum ITEM_TYPE { +#include + +enum ITEM_TYPE +{ GROUP_HEADER_ITEM, NODE_ITEM }; -class ConnectionItemWidget : public QWidget, private Ui::ConnectionWidget +class ConnectionItemWidget + : public QWidget + , private Ui::ConnectionWidget { - Q_OBJECT - public: - explicit ConnectionItemWidget(const ConnectionId &connecionId, QWidget *parent = nullptr); - explicit ConnectionItemWidget(const GroupId &groupId, QWidget *parent = nullptr); - // - void BeginConnection(); - ~ConnectionItemWidget(); - // - inline bool NameMatched(const QString &arg) - { - auto searchString = arg.toLower(); - auto headerMatched = ConnectionManager->GetDisplayName(groupId).toLower().contains(arg); + Q_OBJECT + public: + explicit ConnectionItemWidget(const ConnectionId &connecionId, QWidget *parent = nullptr); + explicit ConnectionItemWidget(const GroupId &groupId, QWidget *parent = nullptr); + // + void BeginConnection(); + ~ConnectionItemWidget(); + // + inline bool NameMatched(const QString &arg) + { + auto searchString = arg.toLower(); + auto headerMatched = ConnectionManager->GetDisplayName(groupId).toLower().contains(arg); - if (itemType != NODE_ITEM) { - return headerMatched; - } else { - return headerMatched || ConnectionManager->GetDisplayName(connectionId).toLower().contains(searchString); - } - } - inline const tuple Identifier() const + if (itemType != NODE_ITEM) { return headerMatched; } + else { - return make_tuple(groupId, connectionId); + return headerMatched || ConnectionManager->GetDisplayName(connectionId).toLower().contains(searchString); } - inline bool IsConnection() const - { - return itemType == NODE_ITEM; - } - signals: - void RequestWidgetFocus(const ConnectionItemWidget *me); - private slots: - void OnConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, const quint64 totalDown); - void OnConnected(const ConnectionId &id); - void OnDisConnected(const ConnectionId &id); - void OnLatencyTestStart(const ConnectionId &id); - void OnLatencyTestFinished(const ConnectionId &id, const uint average); - private: - QString originalConnectionName; - explicit ConnectionItemWidget(QWidget *parent = nullptr); - ITEM_TYPE itemType; - ConnectionId connectionId; - GroupId groupId; + } + inline const tuple Identifier() const + { + return make_tuple(groupId, connectionId); + } + inline bool IsConnection() const + { + return itemType == NODE_ITEM; + } + signals: + void RequestWidgetFocus(const ConnectionItemWidget *me); + private slots: + void OnConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, + const quint64 totalDown); + void OnConnected(const ConnectionId &id); + void OnDisConnected(const ConnectionId &id); + void OnLatencyTestStart(const ConnectionId &id); + void OnLatencyTestFinished(const ConnectionId &id, const uint average); - Q_DISABLE_COPY_MOVE(ConnectionItemWidget) + private: + QString originalConnectionName; + explicit ConnectionItemWidget(QWidget *parent = nullptr); + ITEM_TYPE itemType; + ConnectionId connectionId; + GroupId groupId; + + Q_DISABLE_COPY_MOVE(ConnectionItemWidget) }; diff --git a/src/ui/widgets/QvAutoCompleteTextEdit.cpp b/src/ui/widgets/QvAutoCompleteTextEdit.cpp index 3ab7e571..87d781e0 100644 --- a/src/ui/widgets/QvAutoCompleteTextEdit.cpp +++ b/src/ui/widgets/QvAutoCompleteTextEdit.cpp @@ -49,17 +49,17 @@ ****************************************************************************/ #include "textedit.h" + +#include +#include +#include #include #include -#include -#include -#include #include -#include #include +#include -TextEdit::TextEdit(QWidget *parent) - : QTextEdit(parent) +TextEdit::TextEdit(QWidget *parent) : QTextEdit(parent) { setPlainText(tr("This TextEdit provides autocompletions for words that have more than" " 3 characters. You can trigger autocompletion using ") + @@ -72,14 +72,11 @@ TextEdit::~TextEdit() void TextEdit::setCompleter(QCompleter *completer) { - if (c) - c->disconnect(this); + if (c) c->disconnect(this); c = completer; - if (!c) { - return; - } + if (!c) { return; } c->setWidget(this); c->setCompletionMode(QCompleter::PopupCompletion); @@ -94,8 +91,7 @@ QCompleter *TextEdit::completer() const void TextEdit::insertCompletion(const QString &completion) { - if (c->widget() != this) - return; + if (c->widget() != this) return; QTextCursor tc = textCursor(); int extra = completion.length() - c->completionPrefix().length(); @@ -121,43 +117,43 @@ void TextEdit::focusInEvent(QFocusEvent *e) void TextEdit::keyPressEvent(QKeyEvent *e) { - if (c && c->popup()->isVisible()) { + if (c && c->popup()->isVisible()) + { // The following keys are forwarded by the completer to the widget - switch (e->key()) { + switch (e->key()) + { case Qt::Key_Enter: case Qt::Key_Return: case Qt::Key_Escape: 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; } } const bool isShortcut = (e->modifiers().testFlag(Qt::ControlModifier) && e->key() == Qt::Key_Space); // CTRL+Space - if (!c || !isShortcut) // do not process the shortcut when we have a completer + if (!c || !isShortcut) // do not process the shortcut when we have a + // completer QTextEdit::keyPressEvent(e); - const bool ctrlOrShift = e->modifiers().testFlag(Qt::ControlModifier) || - e->modifiers().testFlag(Qt::ShiftModifier); + const bool ctrlOrShift = e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::ShiftModifier); - if (!c || (ctrlOrShift && e->text().isEmpty())) - return; + if (!c || (ctrlOrShift && e->text().isEmpty())) return; static QString eow("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="); // end of word const bool hasModifier = (e->modifiers() != Qt::NoModifier) && !ctrlOrShift; QString completionPrefix = textUnderCursor(); - if (!isShortcut && (hasModifier || e->text().isEmpty() || completionPrefix.length() < 2 || eow.contains(e->text().right(1)))) { + if (!isShortcut && (hasModifier || e->text().isEmpty() || completionPrefix.length() < 2 || eow.contains(e->text().right(1)))) + { c->popup()->hide(); return; } - if (completionPrefix != c->completionPrefix()) { + if (completionPrefix != c->completionPrefix()) + { c->setCompletionPrefix(completionPrefix); c->popup()->setCurrentIndex(c->completionModel()->index(0, 0)); } diff --git a/src/ui/widgets/QvAutoCompleteTextEdit.h b/src/ui/widgets/QvAutoCompleteTextEdit.h index 788cb74a..847168fd 100644 --- a/src/ui/widgets/QvAutoCompleteTextEdit.h +++ b/src/ui/widgets/QvAutoCompleteTextEdit.h @@ -62,27 +62,26 @@ class TextEdit : public QTextEdit { Q_OBJECT -public: + public: TextEdit(QWidget *parent = nullptr); ~TextEdit(); void setCompleter(QCompleter *c); QCompleter *completer() const; -protected: + protected: void keyPressEvent(QKeyEvent *e) override; void focusInEvent(QFocusEvent *e) override; -private slots: + private slots: void insertCompletion(const QString &completion); -private: + private: QString textUnderCursor() const; -private: + private: QCompleter *c = nullptr; }; //! [0] #endif // TEXTEDIT_H - diff --git a/src/ui/widgets/StreamSettingsWidget.cpp b/src/ui/widgets/StreamSettingsWidget.cpp index c1e74945..6e0c5d32 100644 --- a/src/ui/widgets/StreamSettingsWidget.cpp +++ b/src/ui/widgets/StreamSettingsWidget.cpp @@ -1,9 +1,9 @@ #include "StreamSettingsWidget.hpp" + #include "common/QvHelpers.hpp" #include "ui/editors/w_JsonEditor.hpp" -StreamSettingsWidget::StreamSettingsWidget(QWidget *parent) : - QWidget(parent) +StreamSettingsWidget::StreamSettingsWidget(QWidget *parent) : QWidget(parent) { setupUi(this); } @@ -34,9 +34,8 @@ void StreamSettingsWidget::SetStreamObject(StreamSettingsObject sso) wsPathTxt->setText(stream.wsSettings.path); QString wsHeaders; - for (auto item = stream.wsSettings.headers.begin(); item != stream.wsSettings.headers.end(); item++) { - wsHeaders += item.key() + "|" + item.value() + NEWLINE; - } + for (auto item = stream.wsSettings.headers.begin(); item != stream.wsSettings.headers.end(); item++) + { wsHeaders += item.key() + "|" + item.value() + NEWLINE; } wsHeadersTxt->setPlainText(wsHeaders); // mKCP @@ -60,7 +59,6 @@ void StreamSettingsWidget::SetStreamObject(StreamSettingsObject sso) soMarkSpinBox->setValue(stream.sockopt.mark); } - void StreamSettingsWidget::on_transportCombo_currentIndexChanged(int index) { v2rayStackView->setCurrentIndex(index); @@ -73,29 +71,33 @@ void StreamSettingsWidget::on_httpPathTxt_textEdited(const QString &arg1) void StreamSettingsWidget::on_httpHostTxt_textChanged() { - try { + try + { QStringList hosts = httpHostTxt->toPlainText().replace("\r", "").split("\n"); stream.httpSettings.host.clear(); - for (auto host : hosts) { - if (!host.trimmed().isEmpty()) { - stream.httpSettings.host.push_back(host.trimmed()); - } + for (auto host : hosts) + { + if (!host.trimmed().isEmpty()) { stream.httpSettings.host.push_back(host.trimmed()); } } BLACK(httpHostTxt) - } catch (...) { + } + catch (...) + { RED(httpHostTxt) } } void StreamSettingsWidget::on_wsHeadersTxt_textChanged() { - try { + try + { QStringList headers = SplitLines(wsHeadersTxt->toPlainText()); stream.wsSettings.headers.clear(); - for (auto header : headers) { + for (auto header : headers) + { if (header.isEmpty()) continue; auto index = header.indexOf("|"); @@ -108,12 +110,13 @@ void StreamSettingsWidget::on_wsHeadersTxt_textChanged() } BLACK(wsHeadersTxt) - } catch (...) { + } + catch (...) + { RED(wsHeadersTxt) } } - void StreamSettingsWidget::on_tcpRequestDefBtn_clicked() { tcpRequestTxt->clear(); @@ -130,7 +133,8 @@ void StreamSettingsWidget::on_tcpRequestDefBtn_clicked() void StreamSettingsWidget::on_tcpRespDefBtn_clicked() { tcpRespTxt->clear(); - tcpRespTxt->setPlainText("{\"version\":\"1.1\",\"status\":\"200\",\"reason\":\"OK\",\"headers\":{\"Content-Type\":[\"application/octet-stream\",\"video/mpeg\"],\"Transfer-Encoding\":[\"chunked\"],\"Connection\":[\"keep-alive\"],\"Pragma\":\"no-cache\"}}"); + tcpRespTxt->setPlainText( + "{\"version\":\"1.1\",\"status\":\"200\",\"reason\":\"OK\",\"headers\":{\"Content-Type\":[\"application/octet-stream\",\"video/mpeg\"],\"Transfer-Encoding\":[\"chunked\"],\"Connection\":[\"keep-alive\"],\"Pragma\":\"no-cache\"}}"); } void StreamSettingsWidget::on_tlsCB_stateChanged(int arg1) @@ -185,7 +189,7 @@ void StreamSettingsWidget::on_kcpMTU_valueChanged(int arg1) void StreamSettingsWidget::on_kcpTTI_valueChanged(int arg1) { - stream.kcpSettings.tti = arg1; + stream.kcpSettings.tti = arg1; } void StreamSettingsWidget::on_kcpUploadCapacSB_valueChanged(int arg1) diff --git a/src/ui/widgets/StreamSettingsWidget.hpp b/src/ui/widgets/StreamSettingsWidget.hpp index ddca1458..5fd4a688 100644 --- a/src/ui/widgets/StreamSettingsWidget.hpp +++ b/src/ui/widgets/StreamSettingsWidget.hpp @@ -4,77 +4,78 @@ #include "base/Qv2rayBase.hpp" #include "ui_StreamSettingsWidget.h" -class StreamSettingsWidget : public QWidget, private Ui::StreamSettingsWidget +class StreamSettingsWidget + : public QWidget + , private Ui::StreamSettingsWidget { - Q_OBJECT + Q_OBJECT - public: - explicit StreamSettingsWidget(QWidget *parent = nullptr); - void SetStreamObject(StreamSettingsObject sso); - StreamSettingsObject GetStreamSettings(); + public: + explicit StreamSettingsWidget(QWidget *parent = nullptr); + void SetStreamObject(StreamSettingsObject sso); + StreamSettingsObject GetStreamSettings(); - private slots: - void on_httpPathTxt_textEdited(const QString &arg1); + private slots: + void on_httpPathTxt_textEdited(const QString &arg1); - void on_httpHostTxt_textChanged(); + void on_httpHostTxt_textChanged(); - void on_wsHeadersTxt_textChanged(); + void on_wsHeadersTxt_textChanged(); - void on_tcpRequestDefBtn_clicked(); + void on_tcpRequestDefBtn_clicked(); - void on_tcpRespDefBtn_clicked(); + void on_tcpRespDefBtn_clicked(); - void on_tlsCB_stateChanged(int arg1); + void on_tlsCB_stateChanged(int arg1); - void on_soMarkSpinBox_valueChanged(int arg1); + void on_soMarkSpinBox_valueChanged(int arg1); - void on_tcpFastOpenCB_stateChanged(int arg1); + void on_tcpFastOpenCB_stateChanged(int arg1); - void on_tProxyCB_currentIndexChanged(const QString &arg1); + void on_tProxyCB_currentIndexChanged(const QString &arg1); - void on_quicSecurityCB_currentTextChanged(const QString &arg1); + void on_quicSecurityCB_currentTextChanged(const QString &arg1); - void on_quicKeyTxt_textEdited(const QString &arg1); + void on_quicKeyTxt_textEdited(const QString &arg1); - void on_quicHeaderTypeCB_currentIndexChanged(const QString &arg1); + void on_quicHeaderTypeCB_currentIndexChanged(const QString &arg1); - void on_tcpHeaderTypeCB_currentIndexChanged(const QString &arg1); + void on_tcpHeaderTypeCB_currentIndexChanged(const QString &arg1); - void on_wsPathTxt_textEdited(const QString &arg1); + void on_wsPathTxt_textEdited(const QString &arg1); - void on_kcpMTU_valueChanged(int arg1); + void on_kcpMTU_valueChanged(int arg1); - void on_kcpTTI_valueChanged(int arg1); + void on_kcpTTI_valueChanged(int arg1); - void on_kcpUploadCapacSB_valueChanged(int arg1); + void on_kcpUploadCapacSB_valueChanged(int arg1); - void on_kcpCongestionCB_stateChanged(int arg1); + void on_kcpCongestionCB_stateChanged(int arg1); - void on_kcpDownCapacitySB_valueChanged(int arg1); + void on_kcpDownCapacitySB_valueChanged(int arg1); - void on_kcpReadBufferSB_valueChanged(int arg1); + void on_kcpReadBufferSB_valueChanged(int arg1); - void on_kcpWriteBufferSB_valueChanged(int arg1); + void on_kcpWriteBufferSB_valueChanged(int arg1); - void on_kcpHeaderType_currentTextChanged(const QString &arg1); + void on_kcpHeaderType_currentTextChanged(const QString &arg1); - void on_dsPathTxt_textEdited(const QString &arg1); + void on_dsPathTxt_textEdited(const QString &arg1); - void on_tcpRequestEditBtn_clicked(); + void on_tcpRequestEditBtn_clicked(); - void on_tcpResponseEditBtn_clicked(); + void on_tcpResponseEditBtn_clicked(); - void on_transportCombo_currentIndexChanged(int index); + void on_transportCombo_currentIndexChanged(int index); - void on_transportCombo_currentIndexChanged(const QString &arg1); + void on_transportCombo_currentIndexChanged(const QString &arg1); - void on_serverNameTxt_textEdited(const QString &arg1); + void on_serverNameTxt_textEdited(const QString &arg1); - void on_allowInsecureCB_stateChanged(int arg1); + void on_allowInsecureCB_stateChanged(int arg1); - void on_alpnTxt_textChanged(); + void on_alpnTxt_textChanged(); - private: - StreamSettingsObject stream; + private: + StreamSettingsObject stream; }; - From fa6a8dae1f5d468d5011d46b6a2495055d3a2e39 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 29 Feb 2020 00:28:59 +0800 Subject: [PATCH 065/332] wip: add: added back subscription feature, group renaming, group deleting, subscription update --- _clang-format | 2 +- makespec/BUILDVERSION | 2 +- src/base/Qv2rayBase.hpp | 5 +- src/base/Qv2rayLog.cpp | 10 +- src/common/CommandArgs.cpp | 6 +- src/common/HTTPRequestHelper.cpp | 7 +- src/common/HTTPRequestHelper.hpp | 2 +- src/common/QJsonModel.cpp | 56 +++-- src/common/QvHelpers.cpp | 5 +- src/components/autolaunch/QvAutoLaunch.cpp | 8 +- src/components/icmping/win/ICMPPinger.cpp | 15 +- src/components/pac/QvGFWPACConverter.cpp | 31 ++- src/components/pac/QvPACHandler.cpp | 5 +- src/components/plugins/toolbar/QvToolbar.cpp | 5 +- .../plugins/toolbar/QvToolbar_linux.cpp | 3 +- .../plugins/toolbar/QvToolbar_win.cpp | 4 +- src/components/proxy/QvProxyConfigurator.cpp | 92 ++++++-- src/components/speedchart/speedplotview.cpp | 21 +- src/core/CoreSafeTypes.hpp | 2 +- src/core/config/ConfigBackend.cpp | 5 +- src/core/config/ConfigUpgrade.cpp | 19 +- src/core/connection/Generation.cpp | 39 +++- src/core/connection/SSDConverter.hpp | 15 +- src/core/connection/Serialization.cpp | 77 +++++-- src/core/handler/ConnectionHandler.cpp | 215 +++++++++++++++--- src/core/handler/ConnectionHandler.hpp | 12 +- src/core/kernel/APIBackend.cpp | 5 +- src/core/kernel/KernelInteractions.cpp | 10 +- src/core/tcping/QvTCPing.cpp | 30 ++- src/main.cpp | 18 +- src/ui/editors/w_InboundEditor.cpp | 43 +++- src/ui/editors/w_OutboundEditor.cpp | 12 +- src/ui/editors/w_RoutesEditor.cpp | 103 ++++++--- src/ui/editors/w_RoutesEditor_extra.cpp | 45 +++- src/ui/models/RuleNodeModel.hpp | 5 +- src/ui/w_ImportConfig.cpp | 24 +- src/ui/w_MainWindow.cpp | 161 +++++++------ src/ui/w_MainWindow.hpp | 2 + src/ui/w_MainWindow_extra.cpp | 5 +- src/ui/w_PreferencesWindow.cpp | 74 ++++-- src/ui/w_ScreenShot_Core.cpp | 20 +- src/ui/w_SubscriptionManager.cpp | 191 ++++++---------- src/ui/w_SubscriptionManager.hpp | 11 +- src/ui/w_SubscriptionManager.ui | 21 +- src/ui/widgets/ConnectionInfoWidget.cpp | 38 +++- src/ui/widgets/ConnectionItemWidget.cpp | 33 ++- src/ui/widgets/ConnectionItemWidget.hpp | 5 +- src/ui/widgets/QvAutoCompleteTextEdit.cpp | 17 +- src/ui/widgets/StreamSettingsWidget.cpp | 11 +- 49 files changed, 1088 insertions(+), 459 deletions(-) diff --git a/_clang-format b/_clang-format index 76d7dab8..38833c2c 100644 --- a/_clang-format +++ b/_clang-format @@ -8,7 +8,7 @@ AllowAllParametersOfDeclarationOnNextLine: 'false' AllowShortBlocksOnASingleLine: 'true' AllowShortCaseLabelsOnASingleLine: 'true' AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: Always +AllowShortIfStatementsOnASingleLine: 'false' AllowShortLambdasOnASingleLine: Inline AllowShortLoopsOnASingleLine: 'true' AlwaysBreakAfterDefinitionReturnType: None diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 1a9e10d9..6ed4d106 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4031 +4086 diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index 0cbfda18..d897ad6c 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -118,7 +118,10 @@ using namespace Qv2ray::base::objects::transfer; #define QV2RAY_USE_FPROXY_KEY "_QV2RAY_USE_GLOBAL_FORWARD_PROXY_" #define JSON_ROOT_TRY_REMOVE(obj) \ - if (root.contains(obj)) { root.remove(obj); } + if (root.contains(obj)) \ + { \ + root.remove(obj); \ + } namespace Qv2ray { diff --git a/src/base/Qv2rayLog.cpp b/src/base/Qv2rayLog.cpp index 560c7e57..2cbd4622 100644 --- a/src/base/Qv2rayLog.cpp +++ b/src/base/Qv2rayLog.cpp @@ -21,14 +21,20 @@ namespace Qv2ray::base { // Debug build version, we only print info for DEBUG logs and print // ALL info when debugLog presents, - if (type == QV2RAY_LOG_DEBUG || StartupOption.debugLog) { logString = logString.prepend(funcPrepend); } + if (type == QV2RAY_LOG_DEBUG || StartupOption.debugLog) + { + logString = logString.prepend(funcPrepend); + } } else { // We only process DEBUG log in Release mode if (type == QV2RAY_LOG_DEBUG) { - if (StartupOption.debugLog) { logString = logString.prepend(funcPrepend); } + if (StartupOption.debugLog) + { + logString = logString.prepend(funcPrepend); + } else { // Discard debug log in non-debug Qv2ray version with diff --git a/src/common/CommandArgs.cpp b/src/common/CommandArgs.cpp index b394c850..89fd9152 100644 --- a/src/common/CommandArgs.cpp +++ b/src/common/CommandArgs.cpp @@ -31,9 +31,11 @@ namespace Qv2ray::common return CommandLineError; } - if (parser.isSet(versionOption)) return CommandLineVersionRequested; + if (parser.isSet(versionOption)) + return CommandLineVersionRequested; - if (parser.isSet(helpOption)) return CommandLineHelpRequested; + if (parser.isSet(helpOption)) + return CommandLineHelpRequested; if (parser.isSet(noAPIOption)) { diff --git a/src/common/HTTPRequestHelper.cpp b/src/common/HTTPRequestHelper.cpp index eead1a0e..0fc9cc06 100644 --- a/src/common/HTTPRequestHelper.cpp +++ b/src/common/HTTPRequestHelper.cpp @@ -7,7 +7,7 @@ namespace Qv2ray::common { - QvHttpRequestHelper::QvHttpRequestHelper() : reply() + QvHttpRequestHelper::QvHttpRequestHelper(QObject *parent) : QObject(parent), reply() { } @@ -124,7 +124,10 @@ namespace Qv2ray::common void QvHttpRequestHelper::onRequestFinished_p() { - if (reply->attribute(QNetworkRequest::HTTP2WasUsedAttribute).toBool()) { DEBUG(MODULE_NETWORK, "HTTP/2 was used.") } + if (reply->attribute(QNetworkRequest::HTTP2WasUsedAttribute).toBool()) + { + DEBUG(MODULE_NETWORK, "HTTP/2 was used.") + } if (reply->error() != QNetworkReply::NoError) { diff --git a/src/common/HTTPRequestHelper.hpp b/src/common/HTTPRequestHelper.hpp index 00b1c611..18155b32 100644 --- a/src/common/HTTPRequestHelper.hpp +++ b/src/common/HTTPRequestHelper.hpp @@ -29,7 +29,7 @@ namespace Qv2ray::common { Q_OBJECT public: - explicit QvHttpRequestHelper(); + explicit QvHttpRequestHelper(QObject *parent = nullptr); ~QvHttpRequestHelper(); bool setUrl(const QString &url); void setHeader(const QByteArray &key, const QByteArray &value); diff --git a/src/common/QJsonModel.cpp b/src/common/QJsonModel.cpp index 7dafbe60..33bbcd75 100644 --- a/src/common/QJsonModel.cpp +++ b/src/common/QJsonModel.cpp @@ -60,7 +60,8 @@ int QJsonTreeItem::childCount() const int QJsonTreeItem::row() const { - if (mParent) return mParent->mChilds.indexOf(const_cast(this)); + if (mParent) + return mParent->mChilds.indexOf(const_cast(this)); return 0; } @@ -220,19 +221,25 @@ bool QJsonModel::loadJson(const QByteArray &json) QVariant QJsonModel::data(const QModelIndex &index, int role) const { - if (!index.isValid()) return QVariant(); + if (!index.isValid()) + return QVariant(); QJsonTreeItem *item = static_cast(index.internalPointer()); if (role == Qt::DisplayRole) { - if (index.column() == 0) return QString("%1").arg(item->key()); + if (index.column() == 0) + return QString("%1").arg(item->key()); - if (index.column() == 1) return QString("%1").arg(item->value()); + if (index.column() == 1) + return QString("%1").arg(item->value()); } else if (Qt::EditRole == role) { - if (index.column() == 1) { return QString("%1").arg(item->value()); } + if (index.column() == 1) + { + return QString("%1").arg(item->value()); + } } return QVariant(); @@ -258,38 +265,47 @@ bool QJsonModel::setData(const QModelIndex &index, const QVariant &value, int ro QVariant QJsonModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (role != Qt::DisplayRole) return QVariant(); + if (role != Qt::DisplayRole) + return QVariant(); - if (orientation == Qt::Horizontal) { return mHeaders.value(section); } + if (orientation == Qt::Horizontal) + { + return mHeaders.value(section); + } else return QVariant(); } QModelIndex QJsonModel::index(int row, int column, const QModelIndex &parent) const { - if (!hasIndex(row, column, parent)) return QModelIndex(); + if (!hasIndex(row, column, parent)) + return QModelIndex(); QJsonTreeItem *parentItem; - if (!parent.isValid()) parentItem = mRootItem; + if (!parent.isValid()) + parentItem = mRootItem; else parentItem = static_cast(parent.internalPointer()); QJsonTreeItem *childItem = parentItem->child(row); - if (childItem) return createIndex(row, column, childItem); + if (childItem) + return createIndex(row, column, childItem); else return QModelIndex(); } QModelIndex QJsonModel::parent(const QModelIndex &index) const { - if (!index.isValid()) return QModelIndex(); + if (!index.isValid()) + return QModelIndex(); QJsonTreeItem *childItem = static_cast(index.internalPointer()); QJsonTreeItem *parentItem = childItem->parent(); - if (parentItem == mRootItem) return QModelIndex(); + if (parentItem == mRootItem) + return QModelIndex(); return createIndex(parentItem->row(), 0, parentItem); } @@ -298,9 +314,11 @@ int QJsonModel::rowCount(const QModelIndex &parent) const { QJsonTreeItem *parentItem; - if (parent.column() > 0) return 0; + if (parent.column() > 0) + return 0; - if (!parent.isValid()) parentItem = mRootItem; + if (!parent.isValid()) + parentItem = mRootItem; else parentItem = static_cast(parent.internalPointer()); @@ -320,7 +338,10 @@ Qt::ItemFlags QJsonModel::flags(const QModelIndex &index) const auto isArray = QJsonValue::Array == item->type(); auto isObject = QJsonValue::Object == item->type(); - if ((col == 1) && !(isArray || isObject)) { return Qt::ItemIsEditable | QAbstractItemModel::flags(index); } + if ((col == 1) && !(isArray || isObject)) + { + return Qt::ItemIsEditable | QAbstractItemModel::flags(index); + } else { return QAbstractItemModel::flags(index); @@ -332,7 +353,10 @@ QJsonDocument QJsonModel::json() const auto v = genJson(mRootItem); QJsonDocument doc; - if (v.isObject()) { doc = QJsonDocument(v.toObject()); } + if (v.isObject()) + { + doc = QJsonDocument(v.toObject()); + } else { doc = QJsonDocument(v.toArray()); diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 33455bbd..e7766bf2 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -75,7 +75,10 @@ namespace Qv2ray::common QJsonDocument doc = QJsonDocument::fromJson(source.toUtf8(), &error); Q_UNUSED(doc) - if (error.error == QJsonParseError::NoError) { return ""; } + if (error.error == QJsonParseError::NoError) + { + return ""; + } else { LOG(MODULE_UI, "WARNING: Json parse returns: " + error.errorString()) diff --git a/src/components/autolaunch/QvAutoLaunch.cpp b/src/components/autolaunch/QvAutoLaunch.cpp index 475ce0c4..96a672fd 100644 --- a/src/components/autolaunch/QvAutoLaunch.cpp +++ b/src/components/autolaunch/QvAutoLaunch.cpp @@ -61,7 +61,10 @@ namespace Qv2ray::components::autolaunch { CFStringRef itemUrlString = CFURLGetString(itemUrlRef); - if (CFStringCompare(itemUrlString, appUrlRefString, 0) == kCFCompareEqualTo) { returnValue = true; } + if (CFStringCompare(itemUrlString, appUrlRefString, 0) == kCFCompareEqualTo) + { + returnValue = true; + } CFRelease(itemUrlRef); } @@ -113,7 +116,8 @@ namespace Qv2ray::components::autolaunch // Insert an item to the list. LSSharedFileListItemRef item = LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemLast, 0, 0, urlRef, 0, 0); - if (item) CFRelease(item); + if (item) + CFRelease(item); CFRelease(loginItems); } diff --git a/src/components/icmping/win/ICMPPinger.cpp b/src/components/icmping/win/ICMPPinger.cpp index ccff38bb..2a1de164 100644 --- a/src/components/icmping/win/ICMPPinger.cpp +++ b/src/components/icmping/win/ICMPPinger.cpp @@ -3,7 +3,10 @@ ICMPPinger::ICMPPinger(UINT64 timeout = DEFAULT_TIMEOUT) { // create icmp handle - if ((this->hIcmpFile = IcmpCreateFile()) == INVALID_HANDLE_VALUE) { throw "IcmpCreateFile failed"; } + if ((this->hIcmpFile = IcmpCreateFile()) == INVALID_HANDLE_VALUE) + { + throw "IcmpCreateFile failed"; + } // remember the timeout this->timeout = timeout; @@ -19,7 +22,10 @@ std::pair, std::optional> ICMPPinger::ping(co { // convert network address const auto addr = inet_addr(ipAddr.c_str()); - if (addr == INADDR_NONE) { return std::pair(std::nullopt, "invalid ip address: " + ipAddr); } + if (addr == INADDR_NONE) + { + return std::pair(std::nullopt, "invalid ip address: " + ipAddr); + } // request buffer const static char bufRequest[] = "echo test"; @@ -32,7 +38,10 @@ std::pair, std::optional> ICMPPinger::ping(co auto ret = IcmpSendEcho(this->hIcmpFile, addr, (LPVOID) bufRequest, sizeof(bufRequest), NULL, bufRecv.get(), responseSize, this->timeout); // ret == 0: failed - if (ret == 0) { return std::pair(std::nullopt, "IcmpSendEcho returned error"); } + if (ret == 0) + { + return std::pair(std::nullopt, "IcmpSendEcho returned error"); + } // read round-trip time PICMP_ECHO_REPLY pReply = (PICMP_ECHO_REPLY) bufRecv.get(); diff --git a/src/components/pac/QvGFWPACConverter.cpp b/src/components/pac/QvGFWPACConverter.cpp index 49fd1a02..3148d86f 100644 --- a/src/components/pac/QvGFWPACConverter.cpp +++ b/src/components/pac/QvGFWPACConverter.cpp @@ -21,21 +21,34 @@ namespace Qv2ray::components::pac bool passRule1 = originLine.find("|") != string::npos; // Proxy Lines bool passRule2 = originLine.find(".") != string::npos; // Link-Contained Lines - if (originLine[endPosition] == '\n') { endPosition -= 1; } + if (originLine[endPosition] == '\n') + { + endPosition -= 1; + } - if (originLine.find("http://") != string::npos) { startPosition += 8; } + if (originLine.find("http://") != string::npos) + { + startPosition += 8; + } else if (originLine.find("https://") != string::npos) { startPosition += 9; } // Skip unrelated lines - if (skipRule1 || skipRule2 || skipRule3 || skipRule4) { return ""; } + if (skipRule1 || skipRule2 || skipRule3 || skipRule4) + { + return ""; + } else if (passRule2) { - if (passRule1) { startPosition += originLine.find_last_of("|") + 1; } + if (passRule1) + { + startPosition += originLine.find_last_of("|") + 1; + } - if (originLine[startPosition] == '\n') startPosition += 1; + if (originLine[startPosition] == '\n') + startPosition += 1; for (size_t i = startPosition; i < endPosition; ++i) { returnBuffer += originLine[i]; } } @@ -58,7 +71,10 @@ namespace Qv2ray::components::pac { writeBuffer = getRawDomain(readBuffer); - if (writeBuffer != "") { domainListCache += writeBuffer + "\n"; } + if (writeBuffer != "") + { + domainListCache += writeBuffer + "\n"; + } readBuffer = ""; i += 1; @@ -90,7 +106,8 @@ namespace Qv2ray::components::pac } // Format - if (!isFirstLine) outputContent += ",\n"; + if (!isFirstLine) + outputContent += ",\n"; else isFirstLine = false; diff --git a/src/components/pac/QvPACHandler.cpp b/src/components/pac/QvPACHandler.cpp index 456159b1..3e172e95 100644 --- a/src/components/pac/QvPACHandler.cpp +++ b/src/components/pac/QvPACHandler.cpp @@ -14,7 +14,10 @@ namespace Qv2ray::components::pac } PACServer::~PACServer() { - if (isStarted) { pacServer.close(); } + if (isStarted) + { + pacServer.close(); + } } void PACServer::SetProxyString(const QString &proxyString) { diff --git a/src/components/plugins/toolbar/QvToolbar.cpp b/src/components/plugins/toolbar/QvToolbar.cpp index 7b8d7685..b04d8717 100644 --- a/src/components/plugins/toolbar/QvToolbar.cpp +++ b/src/components/plugins/toolbar/QvToolbar.cpp @@ -42,7 +42,10 @@ namespace Qv2ray::components::plugins auto req = pchRequest.trimmed(); QString reply = "{}"; - if (req == "START") { emit instance->Connect(); } + if (req == "START") + { + emit instance->Connect(); + } else if (req == "STOP") { emit instance->DisConnect(); diff --git a/src/components/plugins/toolbar/QvToolbar_linux.cpp b/src/components/plugins/toolbar/QvToolbar_linux.cpp index de82ec56..1fa19908 100644 --- a/src/components/plugins/toolbar/QvToolbar_linux.cpp +++ b/src/components/plugins/toolbar/QvToolbar_linux.cpp @@ -17,7 +17,8 @@ namespace Qv2ray::components::plugins::Toolbar { QLocalSocket *socket = server->nextPendingConnection(); - if (!socket->waitForConnected() || !socket->waitForReadyRead()) return; + if (!socket->waitForConnected() || !socket->waitForReadyRead()) + return; try { diff --git a/src/components/plugins/toolbar/QvToolbar_win.cpp b/src/components/plugins/toolbar/QvToolbar_win.cpp index f7553fb7..718c625e 100644 --- a/src/components/plugins/toolbar/QvToolbar_win.cpp +++ b/src/components/plugins/toolbar/QvToolbar_win.cpp @@ -92,7 +92,9 @@ namespace Qv2ray::components::plugins::Toolbar if (!fSuccess || cbBytesRead == 0) { if (GetLastError() == ERROR_BROKEN_PIPE) - { LOG(MODULE_PLUGIN, "InstanceThread: client disconnected, GLE=" + QSTRN(GetLastError())) } + { + LOG(MODULE_PLUGIN, "InstanceThread: client disconnected, GLE=" + QSTRN(GetLastError())) + } else { LOG(MODULE_PLUGIN, "InstanceThread ReadFile failed, GLE=" + QSTRN(GetLastError())) diff --git a/src/components/proxy/QvProxyConfigurator.cpp b/src/components/proxy/QvProxyConfigurator.cpp index 84b85c3a..de73f636 100644 --- a/src/components/proxy/QvProxyConfigurator.cpp +++ b/src/components/proxy/QvProxyConfigurator.cpp @@ -28,7 +28,10 @@ namespace Qv2ray::components::proxy for (auto i = 1; i < lines.count(); i++) { // * means disabled. - if (!lines[i].contains("*")) { result << (lines[i].contains(" ") ? "\"" + lines[i] + "\"" : lines[i]); } + if (!lines[i].contains("*")) + { + result << (lines[i].contains(" ") ? "\"" + lines[i] + "\"" : lines[i]); + } } LOG(MODULE_PROXY, "Found " + QSTRN(result.size()) + " network services: " + result.join(";")) @@ -60,35 +63,65 @@ namespace Qv2ray::components::proxy List.pOptions = Option; if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) - { LOG(MODULE_PROXY, "InternetQueryOption failed, GLE=" + QSTRN(GetLastError())) } + { + LOG(MODULE_PROXY, "InternetQueryOption failed, GLE=" + QSTRN(GetLastError())) + } LOG(MODULE_PROXY, "System default proxy info:") - if (Option[0].Value.pszValue != nullptr) { LOG(MODULE_PROXY, QString::fromWCharArray(Option[0].Value.pszValue)) } + if (Option[0].Value.pszValue != nullptr) + { + LOG(MODULE_PROXY, QString::fromWCharArray(Option[0].Value.pszValue)) + } if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL) == PROXY_TYPE_AUTO_PROXY_URL) - { LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_PROXY_URL") } + { + LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_PROXY_URL") + } - if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_DETECT) == PROXY_TYPE_AUTO_DETECT) { LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_DETECT") } + if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_DETECT) == PROXY_TYPE_AUTO_DETECT) + { + LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_DETECT") + } - if ((Option[2].Value.dwValue & PROXY_TYPE_DIRECT) == PROXY_TYPE_DIRECT) { LOG(MODULE_PROXY, "PROXY_TYPE_DIRECT") } + if ((Option[2].Value.dwValue & PROXY_TYPE_DIRECT) == PROXY_TYPE_DIRECT) + { + LOG(MODULE_PROXY, "PROXY_TYPE_DIRECT") + } - if ((Option[2].Value.dwValue & PROXY_TYPE_PROXY) == PROXY_TYPE_PROXY) { LOG(MODULE_PROXY, "PROXY_TYPE_PROXY") } + if ((Option[2].Value.dwValue & PROXY_TYPE_PROXY) == PROXY_TYPE_PROXY) + { + LOG(MODULE_PROXY, "PROXY_TYPE_PROXY") + } if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) - { LOG(MODULE_PROXY, "InternetQueryOption failed,GLE=" + QSTRN(GetLastError())) } + { + LOG(MODULE_PROXY, "InternetQueryOption failed,GLE=" + QSTRN(GetLastError())) + } - if (Option[4].Value.pszValue != nullptr) { LOG(MODULE_PROXY, QString::fromStdWString(Option[4].Value.pszValue)) } + if (Option[4].Value.pszValue != nullptr) + { + LOG(MODULE_PROXY, QString::fromStdWString(Option[4].Value.pszValue)) + } INTERNET_VERSION_INFO Version; nSize = sizeof(INTERNET_VERSION_INFO); InternetQueryOption(nullptr, INTERNET_OPTION_VERSION, &Version, &nSize); - if (Option[0].Value.pszValue != nullptr) { GlobalFree(Option[0].Value.pszValue); } + if (Option[0].Value.pszValue != nullptr) + { + GlobalFree(Option[0].Value.pszValue); + } - if (Option[3].Value.pszValue != nullptr) { GlobalFree(Option[3].Value.pszValue); } + if (Option[3].Value.pszValue != nullptr) + { + GlobalFree(Option[3].Value.pszValue); + } - if (Option[4].Value.pszValue != nullptr) { GlobalFree(Option[4].Value.pszValue); } + if (Option[4].Value.pszValue != nullptr) + { + GlobalFree(Option[4].Value.pszValue); + } return false; } @@ -130,7 +163,10 @@ namespace Qv2ray::components::proxy list.dwOptionCount = 3; list.pOptions = new INTERNET_PER_CONN_OPTION[3]; - if (nullptr == list.pOptions) { return false; } + if (nullptr == list.pOptions) + { + return false; + } // Set flags. list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; @@ -164,18 +200,30 @@ namespace Qv2ray::components::proxy return; } - if (usePAC) { LOG(MODULE_PROXY, "Qv2ray will set system proxy to use PAC file") } + if (usePAC) + { + LOG(MODULE_PROXY, "Qv2ray will set system proxy to use PAC file") + } else { - if (hasHTTP) { LOG(MODULE_PROXY, "Qv2ray will set system proxy to use HTTP") } + if (hasHTTP) + { + LOG(MODULE_PROXY, "Qv2ray will set system proxy to use HTTP") + } - if (hasSOCKS) { LOG(MODULE_PROXY, "Qv2ray will set system proxy to use SOCKS") } + if (hasSOCKS) + { + LOG(MODULE_PROXY, "Qv2ray will set system proxy to use SOCKS") + } } #ifdef Q_OS_WIN QString __a; - if (usePAC) { __a = address; } + if (usePAC) + { + __a = address; + } else { __a = (hasHTTP ? "http://" : "socks5://") + address + ":" + QSTRN(httpPort); @@ -187,7 +235,10 @@ namespace Qv2ray::components::proxy // __QueryProxyOptions(); - if (!__SetProxyOptions(proxyStrW, usePAC)) { LOG(MODULE_PROXY, "Failed to set proxy.") } + if (!__SetProxyOptions(proxyStrW, usePAC)) + { + LOG(MODULE_PROXY, "Failed to set proxy.") + } __QueryProxyOptions(); #elif defined(Q_OS_LINUX) @@ -195,7 +246,10 @@ namespace Qv2ray::components::proxy auto proxyMode = usePAC ? "auto" : "manual"; actions << QString("gsettings set org.gnome.system.proxy mode '%1'").arg(proxyMode); - if (usePAC) { actions << QString("gsettings set org.gnome.system.proxy autoconfig-url '%1'").arg(address); } + if (usePAC) + { + actions << QString("gsettings set org.gnome.system.proxy autoconfig-url '%1'").arg(address); + } else { if (hasHTTP) diff --git a/src/components/speedchart/speedplotview.cpp b/src/components/speedchart/speedplotview.cpp index 848d4b32..7174fd0e 100644 --- a/src/components/speedchart/speedplotview.cpp +++ b/src/components/speedchart/speedplotview.cpp @@ -73,7 +73,8 @@ QString unitString(const SizeUnit unit, const bool isSpeed) const auto &unitString = units[static_cast(unit)]; QString ret = QCoreApplication::translate("misc", unitString.source, unitString.comment); - if (isSpeed) ret += QCoreApplication::translate("misc", "/s", "per second"); + if (isSpeed) + ret += QCoreApplication::translate("misc", "/s", "per second"); return ret; } @@ -119,9 +120,11 @@ namespace SplittedValue getRoundedYScale(double value) { - if (value == 0.0) return { 0, SizeUnit::Byte }; + if (value == 0.0) + return { 0, SizeUnit::Byte }; - if (value <= 12.0) return { 12, SizeUnit::Byte }; + if (value <= 12.0) + return { 12, SizeUnit::Byte }; SizeUnit calculatedUnit = SizeUnit::Byte; @@ -151,7 +154,8 @@ namespace for (const auto &roundedValue : roundingTable) { - if (value <= roundedValue) return { roundedValue, calculatedUnit }; + if (value <= roundedValue) + return { roundedValue, calculatedUnit }; } return { 10.0, calculatedUnit }; @@ -210,7 +214,8 @@ quint64 SpeedPlotView::maxYValue() // 30 is half min for (int i = queue.size() - 1, j = 0; (i >= 0) && (j <= VIEWABLE); --i, ++j) { - if (queue[i].y[id] > maxYValue) maxYValue = queue[i].y[id]; + if (queue[i].y[id] > maxYValue) + maxYValue = queue[i].y[id]; } } @@ -237,7 +242,8 @@ void SpeedPlotView::paintEvent(QPaintEvent *) int yAxisWidth = 0; for (const QString &label : speedLabels) - if (fontMetrics.horizontalAdvance(label) > yAxisWidth) yAxisWidth = fontMetrics.horizontalAdvance(label); + if (fontMetrics.horizontalAdvance(label) > yAxisWidth) + yAxisWidth = fontMetrics.horizontalAdvance(label); int i = 0; @@ -298,7 +304,8 @@ void SpeedPlotView::paintEvent(QPaintEvent *) for (const auto &property : m_properties) { - if (fontMetrics.horizontalAdvance(property.name) > legendWidth) legendWidth = fontMetrics.horizontalAdvance(property.name); + if (fontMetrics.horizontalAdvance(property.name) > legendWidth) + legendWidth = fontMetrics.horizontalAdvance(property.name); legendHeight += 1.5 * fontMetrics.height(); } diff --git a/src/core/CoreSafeTypes.hpp b/src/core/CoreSafeTypes.hpp index 145624cd..5cfbb859 100644 --- a/src/core/CoreSafeTypes.hpp +++ b/src/core/CoreSafeTypes.hpp @@ -96,7 +96,7 @@ namespace Qv2ray::core struct GroupMetaObject : SubscriptionObject_Config { // Implicit base of two types, since group object is actually the group base object. - bool isSubscription; + bool isSubscription = false; QList connections; // Suger for down casting. GroupMetaObject() : connections() diff --git a/src/core/config/ConfigBackend.cpp b/src/core/config/ConfigBackend.cpp index 6ea686b5..9e675178 100644 --- a/src/core/config/ConfigBackend.cpp +++ b/src/core/config/ConfigBackend.cpp @@ -15,7 +15,10 @@ namespace Qv2ray::core::config { Qv2rayConfigPath = path; - if (!path.endsWith("/")) { Qv2rayConfigPath += "/"; } + if (!path.endsWith("/")) + { + Qv2rayConfigPath += "/"; + } } } // namespace Qv2ray::core::config diff --git a/src/core/config/ConfigUpgrade.cpp b/src/core/config/ConfigUpgrade.cpp index 54a02117..043cbe3c 100644 --- a/src/core/config/ConfigUpgrade.cpp +++ b/src/core/config/ConfigUpgrade.cpp @@ -123,7 +123,10 @@ namespace Qv2ray defaultGroup["displayName"] = QObject::tr("Default Group"); QString defaultGroupId = "000000000000"; - if (!QDir(QV2RAY_CONNECTIONS_DIR + defaultGroupId).exists()) { QDir().mkpath(QV2RAY_CONNECTIONS_DIR + defaultGroupId); } + if (!QDir(QV2RAY_CONNECTIONS_DIR + defaultGroupId).exists()) + { + QDir().mkpath(QV2RAY_CONNECTIONS_DIR + defaultGroupId); + } QString autoStartId; UPGRADELOG("Upgrading connections...") @@ -143,7 +146,10 @@ namespace Qv2ray // Check Autostart Id if (root["autoStartConfig"].toObject()["subscriptionName"].toString().isEmpty()) { - if (root["autoStartConfig"].toObject()["connectionName"].toString() == config.toString()) { autoStartId = newUuid; } + if (root["autoStartConfig"].toObject()["connectionName"].toString() == config.toString()) + { + autoStartId = newUuid; + } } if (configFile.exists()) @@ -187,7 +193,10 @@ namespace Qv2ray auto newDirPath = QV2RAY_SUBSCRIPTION_DIR + subsUuid; QDir newDir(newDirPath); - if (!newDir.exists()) { newDir.mkpath(newDirPath); } + if (!newDir.exists()) + { + newDir.mkpath(newDirPath); + } // With extensions auto fileList = GetFileList(baseDirPath); @@ -212,7 +221,9 @@ namespace Qv2ray if (root["autoStartConfig"].toObject()["subscriptionName"].toString() == key) { if (root["autoStartConfig"].toObject()["connectionName"].toString() == subsConnection["displayName"].toString()) - { autoStartId = subsConnectionId; } + { + autoStartId = subsConnectionId; + } } } diff --git a/src/core/connection/Generation.cpp b/src/core/connection/Generation.cpp index b4864c2c..acb003fd 100644 --- a/src/core/connection/Generation.cpp +++ b/src/core/connection/Generation.cpp @@ -117,12 +117,18 @@ namespace Qv2ray::core::connection foreach (auto account, _accounts) { - if (account.user.isEmpty() && account.pass.isEmpty()) { continue; } + if (account.user.isEmpty() && account.pass.isEmpty()) + { + continue; + } accounts.append(GetRootObject(account)); } - if (!accounts.isEmpty()) { JADD(accounts) } + if (!accounts.isEmpty()) + { + JADD(accounts) + } JADD(timeout, allowTransparent, userLevel) RROOT @@ -160,14 +166,23 @@ namespace Qv2ray::core::connection foreach (auto acc, _accounts) { - if (acc.user.isEmpty() && acc.pass.isEmpty()) { continue; } + if (acc.user.isEmpty() && acc.pass.isEmpty()) + { + continue; + } accounts.append(GetRootObject(acc)); } - if (!accounts.isEmpty()) { JADD(accounts) } + if (!accounts.isEmpty()) + { + JADD(accounts) + } - if (udp) { JADD(auth, udp, ip, userLevel) } + if (udp) + { + JADD(auth, udp, ip, userLevel) + } else { JADD(auth, userLevel) @@ -199,11 +214,14 @@ namespace Qv2ray::core::connection QJsonObject root; QJsonArray services; - if (withHandler) services << "HandlerService"; + if (withHandler) + services << "HandlerService"; - if (withLogger) services << "LoggerService"; + if (withLogger) + services << "LoggerService"; - if (withStats) services << "StatsService"; + if (withStats) + services << "StatsService"; JADD(services, tag) RROOT @@ -335,7 +353,10 @@ namespace Qv2ray::core::connection } // If this entry has been disabled. - if (_b.contains("QV2RAY_RULE_ENABLED") && _b["QV2RAY_RULE_ENABLED"].toBool() == true) { rules.append(_b); } + if (_b.contains("QV2RAY_RULE_ENABLED") && _b["QV2RAY_RULE_ENABLED"].toBool() == true) + { + rules.append(_b); + } else { LOG(MODULE_SETTINGS, "Discarded a rule as it's been set DISABLED") diff --git a/src/core/connection/SSDConverter.hpp b/src/core/connection/SSDConverter.hpp index 9175957e..b23854a3 100644 --- a/src/core/connection/SSDConverter.hpp +++ b/src/core/connection/SSDConverter.hpp @@ -174,7 +174,10 @@ std::pair= 0 && port <= 65535) { ssObject.port = currPort; @@ -190,7 +193,10 @@ std::pairtimerId() == saveTimerId) { CHSaveConfigData_p(); } + if (event->timerId() == saveTimerId) + { + CHSaveConfigData_p(); + } else if (event->timerId() == pingAllTimerId) { StartLatencyTest(); } else if (event->timerId() == pingConnectionTimerId) { - if (currentConnectionId != NullConnectionId) { StartLatencyTest(currentConnectionId); } + if (currentConnectionId != NullConnectionId) + { + StartLatencyTest(currentConnectionId); + } } } @@ -123,7 +140,10 @@ namespace Qv2ray::core::handlers for (auto group : groups.keys()) { - if (groups[group].isSubscription) { subsList.push_back(group); } + if (groups[group].isSubscription) + { + subsList.push_back(group); + } } return subsList; @@ -148,7 +168,10 @@ namespace Qv2ray::core::handlers { for (auto conn : connections.keys()) { - if (connections[conn].displayName == displayName) { return conn; } + if (connections[conn].displayName == displayName) + { + return conn; + } } return NullConnectionId; @@ -158,7 +181,10 @@ namespace Qv2ray::core::handlers { for (auto group : groups.keys()) { - if (groups[group].displayName == displayName) { return group; } + if (groups[group].displayName == displayName) + { + return group; + } } return NullGroupId; @@ -166,14 +192,20 @@ namespace Qv2ray::core::handlers const GroupId QvConnectionHandler::GetConnectionGroupId(const ConnectionId &id) const { - if (!connections.contains(id)) { LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); } + if (!connections.contains(id)) + { + LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); + } return connections[id].groupId; } double QvConnectionHandler::GetConnectionLatency(const ConnectionId &id) const { - if (!connections.contains(id)) { LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); } + if (!connections.contains(id)) + { + LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); + } return connections[id].latency; } @@ -193,6 +225,7 @@ namespace Qv2ray::core::handlers { connections.remove(id); groups[groupId].connections.removeAll(id); + emit OnConnectionRemoved(id); return {}; } else @@ -202,11 +235,76 @@ namespace Qv2ray::core::handlers return tr("File does not exist."); } + const optional QvConnectionHandler::MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId, bool emitSignal) + { + auto const oldgid = connections[id].groupId; + // + QString oldPath = (groups[oldgid].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR) + oldgid.toString() + "/" + + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; + // + auto newDir = (groups[newGroupId].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR) + newGroupId.toString() + "/"; + QString newPath = newDir + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; + // + if (!QDir(newDir).exists()) + { + QDir().mkpath(newDir); + } + // + if (!QFile(oldPath).rename(newPath)) + { + LOG(MODULE_FILEIO, "Cannot rename") + } + groups[oldgid].connections.removeAll(id); + groups[newGroupId].connections.append(id); + connections[id].groupId = newGroupId; + // + if (emitSignal) + { + emit OnConnectionGroupChanged(id, oldgid, newGroupId); + } + // + return {}; + } + + const optional QvConnectionHandler::DeleteGroup(const GroupId &id) + { + if (!groups.contains(id)) + { + return tr("Group does not exist"); + } + + // Copy construct + auto list = groups[id].connections; + for (auto conn : list) + { + MoveConnectionGroup(conn, DefaultGroupId, false); // + } + // + if (groups[id].isSubscription) + { + QDir(QV2RAY_SUBSCRIPTION_DIR + id.toString()).removeRecursively(); // + } + else + { + QDir(QV2RAY_CONNECTIONS_DIR + id.toString()).removeRecursively(); + } + emit OnGroupDeleted(id, groups[id].displayName); + // + groups.remove(id); + return {}; + } + const optional QvConnectionHandler::StartConnection(const ConnectionId &identifier) { - if (!connections.contains(identifier)) { return tr("No connection selected!") + NEWLINE + tr("Please select a config from the list."); } + if (!connections.contains(identifier)) + { + return tr("No connection selected!"); + } - if (currentConnectionId != NullConnectionId) { StopConnection(); } + if (currentConnectionId != NullConnectionId) + { + StopConnection(); + } CONFIGROOT root = GetConnectionRoot(connections[identifier].groupId, identifier); return CHStartConnection_p(identifier, root); @@ -230,7 +328,10 @@ namespace Qv2ray::core::handlers { QString result; - if (!connections.contains(id)) { result = tr("N/A"); } + if (!connections.contains(id)) + { + result = tr("N/A"); + } CONFIGROOT root = GetConnectionRoot(connections[id].groupId, id); QStringList protocols; @@ -243,7 +344,9 @@ namespace Qv2ray::core::handlers result.append(" / " + outbound["streamSettings"].toObject()["network"].toString()); if (outbound["streamSettings"].toObject().contains("tls")) - { result.append(outbound["streamSettings"].toObject()["tls"].toBool() ? " / tls" : ""); } + { + result.append(outbound["streamSettings"].toObject()["tls"].toBool() ? " / tls" : ""); + } } return result; @@ -251,19 +354,17 @@ namespace Qv2ray::core::handlers const tuple QvConnectionHandler::GetConnectionUsageAmount(const ConnectionId &id) const { - if (!connections.contains(id)) { return make_tuple(0, 0); } + if (!connections.contains(id)) + { + return make_tuple(0, 0); + } return make_tuple(connections[id].upLinkData, connections[id].downLinkData); } - // const GroupMetaObject QvConnectionHandler::GetGroup(const GroupId &id) - // const - //{ - // return groups[id]; - //} - QvConnectionHandler::~QvConnectionHandler() { + LOG(MODULE_CORE_HANDLER, "Triggering save settings from destructor") CHSaveConfigData_p(); if (vCoreInstance->KernelStarted) @@ -344,18 +445,61 @@ namespace Qv2ray::core::handlers return StringToFile(content, path); } + const GroupId QvConnectionHandler::CreateGroup(const QString displayName, bool isSubscription) + { + GroupId id(GenerateRandomString()); + groups[id].displayName = displayName; + groups[id].isSubscription = isSubscription; + groups[id].importDate = system_clock::to_time_t(system_clock::now()); + emit OnGroupCreated(id, displayName); + return id; + } + + const optional QvConnectionHandler::RenameGroup(const GroupId &id, const QString &newName) + { + if (!groups.contains(id)) + { + return tr("Group does not exist"); + } + groups[id].displayName = newName; + return {}; + } + const tuple QvConnectionHandler::GetSubscriptionData(const GroupId &id) { tuple result; - if (!groups[id].isSubscription) { return result; } + if (!groups[id].isSubscription) + { + return result; + } return make_tuple(groups[id].address, groups[id].lastUpdated, groups[id].updateInterval); } + bool QvConnectionHandler::SetSubscriptionData(const GroupId &id, const QString &address, float updateInterval) + { + if (!groups.contains(id)) + { + return false; + } + if (!address.isEmpty()) + { + groups[id].address = address; + } + if (updateInterval != -1) + { + groups[id].updateInterval = updateInterval; + } + return true; + } + bool QvConnectionHandler::UpdateSubscription(const GroupId &id, bool useSystemProxy) { - if (isHttpRequestInProgress) { return false; } + if (isHttpRequestInProgress) + { + return false; + } isHttpRequestInProgress = true; auto data = httpHelper->syncget(groups[id].address, useSystemProxy); isHttpRequestInProgress = false; @@ -364,7 +508,10 @@ namespace Qv2ray::core::handlers bool QvConnectionHandler::CHUpdateSubscription_p(const GroupId &id, const QByteArray &subscriptionData) { - if (!groups.contains(id)) { return false; } + if (!groups.contains(id)) + { + return false; + } bool isAutoConnectionContainedWithin = groups[id].connections.contains(ConnectionId(GlobalConfig.autoStartId)); Q_UNUSED(isAutoConnectionContainedWithin) // @@ -375,16 +522,21 @@ namespace Qv2ray::core::handlers { nameMap[GetDisplayName(conn)] = conn; auto [protocol, host, port] = GetConnectionData(conn); - if (port != 0) { typeMap[make_tuple(protocol, host, port)] = conn; } + if (port != 0) + { + typeMap[make_tuple(protocol, host, port)] = conn; + } } // /// List that is holding connection IDs to be updated. auto connectionsOrig = groups[id].connections; + QList connectionsNew; auto str = DecodeSubscriptionString(subscriptionData); - if (str.isEmpty()) return false; + if (str.isEmpty()) + return false; // auto subsList = SplitLines(str); - QDir(QV2RAY_SUBSCRIPTION_DIR + id.toString()).removeRecursively(); + // QDir(QV2RAY_SUBSCRIPTION_DIR + id.toString()).removeRecursively(); QDir().mkpath(QV2RAY_SUBSCRIPTION_DIR + id.toString()); bool hasErrorOccured = false; @@ -407,14 +559,16 @@ namespace Qv2ray::core::handlers if (nameMap.contains(_alias)) { // Just go and save the connection... - LOG(MODULE_CORE_HANDLER, "Guessed id from name: " + _alias + ", connectionId: " + nameMap[_alias].toString()) + LOG(MODULE_CORE_HANDLER, "Reused connection id from name: " + _alias) + connectionsNew << nameMap[_alias]; UpdateConnection(nameMap[_alias], config); // Remove Connection Id from the list. connectionsOrig.removeAll(nameMap[_alias]); } else if (canGetOutboundData && typeMap.contains(outboundData)) { - LOG(MODULE_CORE_HANDLER, "Guessed id from protocol/host/port pair for connectionId: " + typeMap[outboundData].toString()) + LOG(MODULE_CORE_HANDLER, "Reused connection id from protocol/host/port pair for connection: " + _alias) + connectionsNew << typeMap[outboundData]; UpdateConnection(typeMap[outboundData], config); // Update displayName connections[typeMap[outboundData]].displayName = _alias; @@ -424,11 +578,12 @@ namespace Qv2ray::core::handlers else { // New connection id is required since nothing matched found... + LOG(MODULE_CORE_HANDLER, "Generated new connection id for connection: " + _alias) ConnectionId newId(GenerateUuid()); + connectionsNew << newId; connections[newId].groupId = id; connections[newId].importDate = system_clock::to_time_t(system_clock::now()); connections[newId].displayName = _alias; - LOG(MODULE_CORE_HANDLER, "Generated new connectionId.") UpdateConnection(newId, config); } // End guessing connectionId @@ -441,6 +596,8 @@ namespace Qv2ray::core::handlers LOG(MODULE_CORE_HANDLER, "Removing: " + conn.toString()) DeleteConnection(conn); } + // Set new connection list + groups[id].connections = connectionsNew; return hasErrorOccured; } diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 030c03e8..477abde0 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -10,6 +10,8 @@ namespace Qv2ray::core::handlers { + const inline GroupId DefaultGroupId = GroupId("000000000000"); + // class QvConnectionHandler : public QObject { Q_OBJECT @@ -42,7 +44,7 @@ namespace Qv2ray::core::handlers bool UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); const optional RenameConnection(const ConnectionId &id, const QString &newName); const ConnectionId DuplicateConnection(const ConnectionId &id); - const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); + const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId, bool emitSignal = true); // const CONFIGROOT GetConnectionRoot(const ConnectionId &id) const; const CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id) const; @@ -58,12 +60,13 @@ namespace Qv2ray::core::handlers void StartLatencyTest(const ConnectionId &id); // // Group Operations + const GroupId CreateGroup(const QString displayName, bool isSubscription); const optional DeleteGroup(const GroupId &id); - const optional DuplicateGroup(const GroupId &id); - const GroupId &CreateGroup(const QString displayName, bool isSubscription); const optional RenameGroup(const GroupId &id, const QString &newName); + // const optional DuplicateGroup(const GroupId &id); // // Subscriptions + bool SetSubscriptionData(const GroupId &id, const QString &address = "", float updateInterval = -1); bool UpdateSubscription(const GroupId &id, bool useSystemProxy); bool UpdateSubscriptionASync(const GroupId &id, bool useSystemProxy); const tuple GetSubscriptionData(const GroupId &id); @@ -78,8 +81,9 @@ namespace Qv2ray::core::handlers // void OnConnectionCreated(const ConnectionId &id, const QString &displayName); void OnConnectionRenamed(const ConnectionId &id, const QString &originalName, const QString &newName); + void OnConnectionRemoved(const ConnectionId &id); void OnConnectionChanged(const ConnectionId &id); - void OnConnectionGroupChanged(const ConnectionId &id, const QString &originalGroup, const QString &newGroup); + void OnConnectionGroupChanged(const ConnectionId &id, const GroupId &originalGroup, const GroupId &newGroup); // void OnLatencyTestStarted(const ConnectionId &id); void OnLatencyTestFinished(const ConnectionId &id, const uint average); diff --git a/src/core/kernel/APIBackend.cpp b/src/core/kernel/APIBackend.cpp index 99d12cf6..bd7b403a 100644 --- a/src/core/kernel/APIBackend.cpp +++ b/src/core/kernel/APIBackend.cpp @@ -50,7 +50,10 @@ namespace Qv2ray::core::kernel thread->wait(); // Although thread shouldnot be null, we'll add this check to be safe. - if (thread) { delete thread; } + if (thread) + { + delete thread; + } } // API Core Operations diff --git a/src/core/kernel/KernelInteractions.cpp b/src/core/kernel/KernelInteractions.cpp index 3fd0ed72..8337ae0e 100644 --- a/src/core/kernel/KernelInteractions.cpp +++ b/src/core/kernel/KernelInteractions.cpp @@ -200,7 +200,10 @@ namespace Qv2ray::core::kernel apiEnabled = false; // - if (StartupOption.noAPI) { LOG(MODULE_VCORE, "API has been disabled by the command line argument \"-noAPI\"") } + if (StartupOption.noAPI) + { + LOG(MODULE_VCORE, "API has been disabled by the command line argument \"-noAPI\"") + } else if (!GlobalConfig.apiConfig.enableAPI) { LOG(MODULE_VCORE, "API has been disabled by the global config option") @@ -244,7 +247,10 @@ namespace Qv2ray::core::kernel V2rayKernelInstance::~V2rayKernelInstance() { - if (KernelStarted) { StopConnection(); } + if (KernelStarted) + { + StopConnection(); + } delete apiWorker; delete vProcess; diff --git a/src/core/tcping/QvTCPing.cpp b/src/core/tcping/QvTCPing.cpp index 60c885a9..86fe38ab 100644 --- a/src/core/tcping/QvTCPing.cpp +++ b/src/core/tcping/QvTCPing.cpp @@ -40,7 +40,10 @@ namespace Qv2ray::core::tcping auto result = watcher->result(); this->pingWorkingThreads.removeOne(watcher); - if (!result.errorMessage.isEmpty()) { LOG(MODULE_NETWORK, "Ping --> " + result.errorMessage) } + if (!result.errorMessage.isEmpty()) + { + LOG(MODULE_NETWORK, "Ping --> " + result.errorMessage) + } emit this->OnLatencyTestCompleted(result); }); @@ -51,7 +54,8 @@ namespace Qv2ray::core::tcping QvTCPingResultObject data; data.connectionId = id; - if (isExiting) return data; + if (isExiting) + return data; auto [protocol, host, port] = ConnectionManager->GetConnectionData(id); Q_UNUSED(protocol) @@ -74,7 +78,8 @@ namespace Qv2ray::core::tcping while (currentCount < count) { - if (isExiting) return QvTCPingResultObject(); + if (isExiting) + return QvTCPingResultObject(); system_clock::time_point start; system_clock::time_point end; @@ -90,7 +95,10 @@ namespace Qv2ray::core::tcping } else { - if (noAddress) { LOG(MODULE_NETWORK, ".") } + if (noAddress) + { + LOG(MODULE_NETWORK, ".") + } else { LOG(MODULE_NETWORK, "error connecting to host: " + QSTRN(-errcode) + " " + strerror(-errcode)) @@ -127,7 +135,8 @@ namespace Qv2ray::core::tcping int resolveHost(const string &host, int port, addrinfo **res) { - if (isExiting) return 0; + if (isExiting) + return 0; addrinfo hints; #ifdef _WIN32 @@ -145,7 +154,8 @@ namespace Qv2ray::core::tcping int testLatency(struct addrinfo *addr, std::chrono::system_clock::time_point *start, std::chrono::system_clock::time_point *end) { - if (isExiting) return 0; + if (isExiting) + return 0; #ifdef _WIN32 SOCKET fd; @@ -159,12 +169,16 @@ namespace Qv2ray::core::tcping /* try to connect for each of the entries: */ while (addr != nullptr) { - if (isExiting) return 0; + if (isExiting) + return 0; /* create socket */ fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); - if (!fd) { goto next_addr0; } + if (!fd) + { + goto next_addr0; + } #ifdef _WIN32 diff --git a/src/main.cpp b/src/main.cpp index 9d4c2a11..ae943cce 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,7 +34,8 @@ void signalHandler(int signum) bool verifyConfigAvaliability(QString path, bool checkExistingConfig) { // Does not exist. - if (!QDir(path).exists()) return false; + if (!QDir(path).exists()) + return false; // A temp file used to test file permissions in that folder. QFile testFile(path + ".qv2ray_file_write_test_file" + QSTRN(QTime::currentTime().msecsSinceStartOfDay())); @@ -68,7 +69,8 @@ bool verifyConfigAvaliability(QString path, bool checkExistingConfig) QFile configFile(path + "Qv2ray.conf"); // No such config file. - if (!configFile.exists()) return false; + if (!configFile.exists()) + return false; bool opened2 = configFile.open(QIODevice::ReadWrite); @@ -152,7 +154,8 @@ bool initialiseQv2ray() bool isValidConfigPath = verifyConfigAvaliability(path, true); // If we already found a valid config file. just simply load it... - if (hasExistingConfig) break; + if (hasExistingConfig) + break; if (isValidConfigPath) { @@ -362,7 +365,10 @@ int main(int argc, char *argv[]) } // Qv2ray Initialize, find possible config paths and verify them. - if (!initialiseQv2ray()) { return -1; } + if (!initialiseQv2ray()) + { + return -1; + } // Load the config for upgrade, but do not parse it to the struct. auto conf = JsonFromString(StringFromFile(QV2RAY_CONFIG_FILE)); @@ -402,7 +408,9 @@ int main(int argc, char *argv[]) Qv2rayTranslator = std::move(QvTranslator(confObject.uiConfig.language).pTranslator); if (qApp->installTranslator(Qv2rayTranslator.get())) - { LOG(MODULE_INIT, "Successfully installed a translator for " + confObject.uiConfig.language) } + { + LOG(MODULE_INIT, "Successfully installed a translator for " + confObject.uiConfig.language) + } else { // Do not translate these..... diff --git a/src/ui/editors/w_InboundEditor.cpp b/src/ui/editors/w_InboundEditor.cpp index 2d95cfb8..08d3ab91 100644 --- a/src/ui/editors/w_InboundEditor.cpp +++ b/src/ui/editors/w_InboundEditor.cpp @@ -5,7 +5,8 @@ static bool isLoading = false; #define CHECKLOADING \ - if (isLoading) return; + if (isLoading) \ + return; InboundEditor::InboundEditor(INBOUND root, QWidget *parent) : QDialog(parent), original(root) { @@ -16,7 +17,10 @@ InboundEditor::InboundEditor(INBOUND root, QWidget *parent) : QDialog(parent), o allocate = root["allocate"].toObject(); sniffing = root["sniffing"].toObject(); - if (inboundType == "http") { httpSettings = root["settings"].toObject(); } + if (inboundType == "http") + { + httpSettings = root["settings"].toObject(); + } else if (inboundType == "socks") { socksSettings = root["settings"].toObject(); @@ -67,19 +71,28 @@ INBOUND InboundEditor::GenerateNewRoot() INBOUND _newRoot = root; auto inboundType = root["protocol"].toString(); - if (inboundType.isNull() || inboundType.isEmpty()) { inboundType = "http"; } + if (inboundType.isNull() || inboundType.isEmpty()) + { + inboundType = "http"; + } if (inboundType == "http") { // Remove useless, misleading 'accounts' array. - if (httpAccountListBox->count() == 0) { httpSettings.remove("accounts"); } + if (httpAccountListBox->count() == 0) + { + httpSettings.remove("accounts"); + } _newRoot["settings"] = httpSettings; } else if (inboundType == "socks") { // See above - if (socksAccountListBox->count() == 0) { socksSettings.remove("accounts"); } + if (socksAccountListBox->count() == 0) + { + socksSettings.remove("accounts"); + } _newRoot["settings"] = socksSettings; } @@ -113,9 +126,11 @@ void InboundEditor::LoadUIData() for (auto item : sniffing["destOverride"].toArray()) { - if (item.toString().toLower() == "http") destOverrideList->item(0)->setCheckState(Qt::Checked); + if (item.toString().toLower() == "http") + destOverrideList->item(0)->setCheckState(Qt::Checked); - if (item.toString().toLower() == "tls") destOverrideList->item(1)->setCheckState(Qt::Checked); + if (item.toString().toLower() == "tls") + destOverrideList->item(1)->setCheckState(Qt::Checked); } inboundTagTxt->setText(root["tag"].toString()); @@ -349,7 +364,10 @@ void InboundEditor::on_destOverrideList_itemChanged(QListWidgetItem *item) { auto _item = destOverrideList->item(i); - if (_item->checkState() == Qt::Checked) { list.append(_item->text().toLower()); } + if (_item->checkState() == Qt::Checked) + { + list.append(_item->text().toLower()); + } } sniffing["destOverride"] = list; @@ -433,7 +451,8 @@ void InboundEditor::on_mtEMailTxt_textEdited(const QString &arg1) { CHECKLOADING - if (!mtSettings.contains("users")) mtSettings["users"] = QJsonArray(); + if (!mtSettings.contains("users")) + mtSettings["users"] = QJsonArray(); QJsonObject user = mtSettings["users"].toArray().empty() ? QJsonObject() : mtSettings["users"].toArray().first().toObject(); user["email"] = arg1; @@ -446,7 +465,8 @@ void InboundEditor::on_mtSecretTxt_textEdited(const QString &arg1) { CHECKLOADING - if (!mtSettings.contains("users")) mtSettings["users"] = QJsonArray(); + if (!mtSettings.contains("users")) + mtSettings["users"] = QJsonArray(); QJsonObject user = mtSettings["users"].toArray().empty() ? QJsonObject() : mtSettings["users"].toArray().first().toObject(); user["secret"] = arg1; @@ -459,7 +479,8 @@ void InboundEditor::on_mtUserLevelSB_valueChanged(int arg1) { CHECKLOADING - if (!mtSettings.contains("users")) mtSettings["users"] = QJsonArray(); + if (!mtSettings.contains("users")) + mtSettings["users"] = QJsonArray(); QJsonObject user = mtSettings["users"].toArray().empty() ? QJsonObject() : mtSettings["users"].toArray().first().toObject(); user["userLevel"] = arg1; diff --git a/src/ui/editors/w_OutboundEditor.cpp b/src/ui/editors/w_OutboundEditor.cpp index 14bacfa7..995ae79f 100644 --- a/src/ui/editors/w_OutboundEditor.cpp +++ b/src/ui/editors/w_OutboundEditor.cpp @@ -166,7 +166,8 @@ void OutboundEditor::ReloadGUI() ipLineEdit->setText(socks.address); portLineEdit->setText(QSTRN(socks.port)); - if (socks.users.empty()) socks.users.push_back(SocksServerObject::UserObject()); + if (socks.users.empty()) + socks.users.push_back(SocksServerObject::UserObject()); socks_PasswordTxt->setText(socks.users.front().pass); socks_UserNameTxt->setText(socks.users.front().user); @@ -201,14 +202,16 @@ void OutboundEditor::on_portLineEdit_textEdited(const QString &arg1) void OutboundEditor::on_idLineEdit_textEdited(const QString &arg1) { - if (vmess.users.empty()) vmess.users.push_back(VMessServerObject::UserObject()); + if (vmess.users.empty()) + vmess.users.push_back(VMessServerObject::UserObject()); vmess.users.front().id = arg1; } void OutboundEditor::on_securityCombo_currentIndexChanged(const QString &arg1) { - if (vmess.users.empty()) vmess.users.push_back(VMessServerObject::UserObject()); + if (vmess.users.empty()) + vmess.users.push_back(VMessServerObject::UserObject()); vmess.users.front().security = arg1; } @@ -230,7 +233,8 @@ void OutboundEditor::on_muxConcurrencyTxt_valueChanged(int arg1) void OutboundEditor::on_alterLineEdit_valueChanged(int arg1) { - if (vmess.users.empty()) vmess.users.push_back(VMessServerObject::UserObject()); + if (vmess.users.empty()) + vmess.users.push_back(VMessServerObject::UserObject()); vmess.users.front().alterId = arg1; } diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index bd24045a..15fb5445 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -26,7 +26,8 @@ using namespace Qv2ray::ui::nodemodels; static bool isLoading = false; #define CurrentRule this->rules[this->currentRuleTag] #define LOADINGCHECK \ - if (isLoading) return; + if (isLoading) \ + return; #define GetFirstNodeData(node, nodeModel, dataModel) \ (static_cast(static_cast((node).nodeDataModel())->outData(0).get())) @@ -129,7 +130,9 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QDialog(pare auto _balancerObject = _balancer.toObject(); if (!_balancerObject["tag"].toString().isEmpty()) - { balancers[_balancerObject["tag"].toString()] = _balancerObject["selector"].toVariant().toStringList(); } + { + balancers[_balancerObject["tag"].toString()] = _balancerObject["selector"].toVariant().toStringList(); + } } isLoading = false; @@ -147,7 +150,8 @@ void RouteEditor::onNodeClicked(Node &n) { LOADINGCHECK - if (isExiting) return; + if (isExiting) + return; auto isOut = outboundNodes.values().contains(&n); auto isIn = inboundNodes.values().contains(&n); @@ -200,7 +204,8 @@ void RouteEditor::onConnectionCreated(QtNodes::Connection const &c) { LOADINGCHECK - if (isExiting) return; + if (isExiting) + return; // Connection Established auto const sourceNode = c.getNode(PortType::Out); @@ -222,7 +227,9 @@ void RouteEditor::onConnectionCreated(QtNodes::Connection const &c) if (_connection->getNode(PortType::In) == targetNode && _connection->getNode(PortType::Out) == sourceNode && _connection->id() != c.id()) - { nodeScene->deleteConnection(*_connection); } + { + nodeScene->deleteConnection(*_connection); + } // Append all inbounds else if (_connection->getNode(PortType::In) == targetNode) { @@ -257,7 +264,8 @@ void RouteEditor::onConnectionDeleted(QtNodes::Connection const &c) { LOADINGCHECK - if (isExiting) return; + if (isExiting) + return; // Connection Deleted auto const source = c.getNode(PortType::Out); @@ -281,7 +289,10 @@ void RouteEditor::onConnectionDeleted(QtNodes::Connection const &c) currentRuleTag = GetFirstNodeData(*source, QvRuleNodeDataModel, RuleNodeData)->GetRuleTag(); auto _outboundTag = GetFirstNodeData(*target, QvOutboundNodeModel, OutboundNodeData)->GetOutbound(); - if (!CurrentRule.QV2RAY_RULE_USE_BALANCER && CurrentRule.outboundTag == _outboundTag) { CurrentRule.outboundTag.clear(); } + if (!CurrentRule.QV2RAY_RULE_USE_BALANCER && CurrentRule.outboundTag == _outboundTag) + { + CurrentRule.outboundTag.clear(); + } LOG(MODULE_GRAPH, "Removing an outbound: " + _outboundTag) } @@ -322,7 +333,10 @@ CONFIGROOT RouteEditor::OpenEditor() ruleJsonObject.remove("outboundTag"); // Find balancer list - if (!balancers.contains(_rule.balancerTag)) { LOG(MODULE_UI, "Cannot find a balancer for tag: " + _rule.balancerTag) } + if (!balancers.contains(_rule.balancerTag)) + { + LOG(MODULE_UI, "Cannot find a balancer for tag: " + _rule.balancerTag) + } else { auto _balancerList = balancers[_rule.balancerTag]; @@ -334,9 +348,15 @@ CONFIGROOT RouteEditor::OpenEditor() } // Remove some empty fields. - if (_rule.port.isEmpty()) { ruleJsonObject.remove("port"); } + if (_rule.port.isEmpty()) + { + ruleJsonObject.remove("port"); + } - if (_rule.network.isEmpty()) { ruleJsonObject.remove("network"); } + if (_rule.network.isEmpty()) + { + ruleJsonObject.remove("network"); + } rulesArray.append(ruleJsonObject); } @@ -352,14 +372,16 @@ CONFIGROOT RouteEditor::OpenEditor() // Convert our internal data format to QJsonArray for (auto x : inbounds) { - if (x.isEmpty()) continue; + if (x.isEmpty()) + continue; _inbounds.append(x.raw()); } for (auto x : outbounds) { - if (x.isEmpty()) continue; + if (x.isEmpty()) + continue; if (getTag(x) == defaultOutbound) { @@ -488,11 +510,14 @@ void RouteEditor::on_routeProtocolHTTPCB_stateChanged(int arg1) LOADINGCHECK QStringList protocols; - if (arg1 == Qt::Checked) protocols.push_back("http"); + if (arg1 == Qt::Checked) + protocols.push_back("http"); - if (routeProtocolTLSCB->isChecked()) protocols.push_back("tls"); + if (routeProtocolTLSCB->isChecked()) + protocols.push_back("tls"); - if (routeProtocolBTCB->isChecked()) protocols.push_back("bittorrent"); + if (routeProtocolBTCB->isChecked()) + protocols.push_back("bittorrent"); CurrentRule.protocol = protocols; statusLabel->setText(tr("Protocol list changed: ") + protocols.join(";")); @@ -502,11 +527,14 @@ void RouteEditor::on_routeProtocolTLSCB_stateChanged(int arg1) LOADINGCHECK QStringList protocols; - if (arg1 == Qt::Checked) protocols.push_back("tls"); + if (arg1 == Qt::Checked) + protocols.push_back("tls"); - if (routeProtocolHTTPCB->isChecked()) protocols.push_back("http"); + if (routeProtocolHTTPCB->isChecked()) + protocols.push_back("http"); - if (routeProtocolBTCB->isChecked()) protocols.push_back("bittorrent"); + if (routeProtocolBTCB->isChecked()) + protocols.push_back("bittorrent"); CurrentRule.protocol = protocols; statusLabel->setText(tr("Protocol list changed: ") + protocols.join(";")); @@ -516,11 +544,14 @@ void RouteEditor::on_routeProtocolBTCB_stateChanged(int arg1) LOADINGCHECK QStringList protocols; - if (arg1 == Qt::Checked) protocols.push_back("bittorrent"); + if (arg1 == Qt::Checked) + protocols.push_back("bittorrent"); - if (routeProtocolHTTPCB->isChecked()) protocols.push_back("http"); + if (routeProtocolHTTPCB->isChecked()) + protocols.push_back("http"); - if (routeProtocolTLSCB->isChecked()) protocols.push_back("tls"); + if (routeProtocolTLSCB->isChecked()) + protocols.push_back("tls"); CurrentRule.protocol = protocols; statusLabel->setText(tr("Protocol list changed: ") + protocols.join(";")); @@ -546,7 +577,10 @@ void RouteEditor::on_balancerDelBtn_clicked() { LOADINGCHECK - if (balancerList->currentRow() < 0) { return; } + if (balancerList->currentRow() < 0) + { + return; + } balancers[CurrentRule.balancerTag].removeAt(balancerList->currentRow()); balancerList->takeItem(balancerList->currentRow()); @@ -625,7 +659,10 @@ void RouteEditor::on_enableBalancerCB_stateChanged(int arg1) for (auto &&[_, conn] : nodeScene->connections()) { - if (conn.get()->getNode(PortType::Out) == ruleNode) { nodeScene->deleteConnection(*conn); } + if (conn.get()->getNode(PortType::Out) == ruleNode) + { + nodeScene->deleteConnection(*conn); + } } } else @@ -665,7 +702,10 @@ void RouteEditor::on_addInboundBtn_clicked() InboundEditor w(INBOUND(), this); auto _result = w.OpenEditor(); - if (w.result() == QDialog::Accepted) { AddInbound(_result); } + if (w.result() == QDialog::Accepted) + { + AddInbound(_result); + } CHECKEMPTYRULES } @@ -681,7 +721,8 @@ void RouteEditor::on_addOutboundBtn_clicked() auto conf = configs.values()[i]; auto name = configs.key(conf, ""); - if (name.isEmpty()) continue; + if (name.isEmpty()) + continue; // conf is rootObject, needs to unwrap it. auto confList = conf["outbounds"].toArray(); @@ -741,7 +782,8 @@ void RouteEditor::on_delBtn_clicked() { auto v = rules[k]; - if (v.outboundTag == currentInboundOutboundTag) v.outboundTag.clear(); + if (v.outboundTag == currentInboundOutboundTag) + v.outboundTag.clear(); rules[k] = v; } @@ -777,7 +819,9 @@ void RouteEditor::on_delBtn_clicked() void RouteEditor::on_editBtn_clicked() { if (nodeScene->selectedNodes().empty()) - { QvMessageBoxWarn(this, tr("Edit Inbound/Outbound"), tr("Please select a node from the graph to continue.")); } + { + QvMessageBoxWarn(this, tr("Edit Inbound/Outbound"), tr("Please select a node from the graph to continue.")); + } auto firstNode = nodeScene->selectedNodes().at(0); auto isInbound = inboundNodes.values().contains(firstNode); @@ -822,7 +866,10 @@ void RouteEditor::on_editBtn_clicked() { bool isTagChanged = getTag(_in) != getTag(_result); - if (isTagChanged) { RenameItemTag(RENAME_INBOUND, getTag(_in), getTag(_result)); } + if (isTagChanged) + { + RenameItemTag(RENAME_INBOUND, getTag(_in), getTag(_result)); + } DEBUG(MODULE_UI, "Removed old tag: " + getTag(_in)) inbounds.remove(getTag(_in)); diff --git a/src/ui/editors/w_RoutesEditor_extra.cpp b/src/ui/editors/w_RoutesEditor_extra.cpp index cd44d994..c4a1a2fa 100644 --- a/src/ui/editors/w_RoutesEditor_extra.cpp +++ b/src/ui/editors/w_RoutesEditor_extra.cpp @@ -10,7 +10,10 @@ void RouteEditor::AddInbound(INBOUND in) { QString tag = getTag(in); - if (inbounds.contains(tag)) { tag = tag + "_" + GenerateRandomString(5); } + if (inbounds.contains(tag)) + { + tag = tag + "_" + GenerateRandomString(5); + } in["tag"] = tag; auto _nodeData = make_unique(make_shared(tag)); @@ -27,7 +30,10 @@ void RouteEditor::AddOutbound(OUTBOUND out) { QString tag = getTag(out); - if (outbounds.contains(tag)) { tag = tag + "_" + GenerateRandomString(5); } + if (outbounds.contains(tag)) + { + tag = tag + "_" + GenerateRandomString(5); + } out["tag"] = tag; auto _nodeData = make_unique(make_shared(tag)); @@ -60,7 +66,10 @@ QString RouteEditor::AddNewRule() void RouteEditor::AddRule(RuleObject rule) { // Prevent duplicate - if (ruleNodes.contains(rule.QV2RAY_RULE_TAG)) { rule.QV2RAY_RULE_TAG += "-" + GenerateRandomString(5); } + if (ruleNodes.contains(rule.QV2RAY_RULE_TAG)) + { + rule.QV2RAY_RULE_TAG += "-" + GenerateRandomString(5); + } rules[rule.QV2RAY_RULE_TAG] = rule; auto pos = nodeGraphWidget->pos(); @@ -121,7 +130,10 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, auto node = static_cast(ruleNodes[originalTag]->nodeDataModel()); - if (node == nullptr) { LOG(MODULE_GRAPH, "EMPTY NODE WARN") } + if (node == nullptr) + { + LOG(MODULE_GRAPH, "EMPTY NODE WARN") + } node->setData(newTag); // @@ -133,13 +145,19 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, // ruleOrder list widget. auto items = ruleListWidget->findItems(originalTag, Qt::MatchExactly); - if (items.isEmpty()) { LOG(MODULE_UI, "Cannot find a node: " + originalTag) } + if (items.isEmpty()) + { + LOG(MODULE_UI, "Cannot find a node: " + originalTag) + } else { items.first()->setText(newTag); } - if (currentRuleTag == originalTag) { currentRuleTag = newTag; } + if (currentRuleTag == originalTag) + { + currentRuleTag = newTag; + } } else { @@ -161,7 +179,10 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, outboundNodes[newTag] = outboundNodes.take(originalTag); auto node = static_cast(outboundNodes[newTag]->nodeDataModel()); - if (node == nullptr) { LOG(MODULE_GRAPH, "EMPTY NODE WARN") } + if (node == nullptr) + { + LOG(MODULE_GRAPH, "EMPTY NODE WARN") + } node->setData(newTag); @@ -202,7 +223,10 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, inboundNodes[newTag] = inboundNodes.take(originalTag); auto node = static_cast(inboundNodes[newTag]->nodeDataModel()); - if (node == nullptr) { LOG(MODULE_GRAPH, "EMPTY NODE WARN") } + if (node == nullptr) + { + LOG(MODULE_GRAPH, "EMPTY NODE WARN") + } node->setData(newTag); @@ -250,7 +274,10 @@ void RouteEditor::ResolveDefaultOutboundTag(QString original, QString newTag) LOG(MODULE_UI, "Default outbound is removed, using first key from the outbounds as the default one.") // Removed the default one, so set the first one as the default. - if (outbounds.isEmpty()) { defaultOutbound.clear(); } + if (outbounds.isEmpty()) + { + defaultOutbound.clear(); + } else { defaultOutbound = getTag(outbounds.first()); diff --git a/src/ui/models/RuleNodeModel.hpp b/src/ui/models/RuleNodeModel.hpp index 4f27eb0b..7d889e0f 100644 --- a/src/ui/models/RuleNodeModel.hpp +++ b/src/ui/models/RuleNodeModel.hpp @@ -28,7 +28,10 @@ class QvRuleNodeDataModel : public NodeDataModel unsigned int nPorts(PortType portType) const override { - if (portType == PortType::In) { return 1; } + if (portType == PortType::In) + { + return 1; + } else if (portType == PortType::Out) { return 1; diff --git a/src/ui/w_ImportConfig.cpp b/src/ui/w_ImportConfig.cpp index 573ceb3f..29920030 100644 --- a/src/ui/w_ImportConfig.cpp +++ b/src/ui/w_ImportConfig.cpp @@ -60,7 +60,10 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() { bool hideQv2ray = hideQv2rayCB->isChecked(); - if (hideQv2ray) { messageBus.EmitGlobalSignal(QvMBMessage::HIDE_WINDOWS); } + if (hideQv2ray) + { + messageBus.EmitGlobalSignal(QvMBMessage::HIDE_WINDOWS); + } QApplication::processEvents(); QThread::msleep(static_cast(doubleSpinBox->value() * 1000)); @@ -199,7 +202,10 @@ void ImportConfigWindow::on_errorsList_currentItemChanged(QListWidgetItem *curre { Q_UNUSED(previous) - if (current == nullptr) { return; } + if (current == nullptr) + { + return; + } auto currentErrorText = current->text(); auto vmessEntry = linkErrors.key(currentErrorText); @@ -207,7 +213,10 @@ void ImportConfigWindow::on_errorsList_currentItemChanged(QListWidgetItem *curre auto startPos = vmessConnectionStringTxt->toPlainText().indexOf(vmessEntry); auto endPos = startPos + vmessEntry.length(); - if (startPos < 0) { return; } + if (startPos < 0) + { + return; + } // Select vmess string that is invalid. QTextCursor c = vmessConnectionStringTxt->textCursor(); @@ -236,7 +245,9 @@ void ImportConfigWindow::on_editFileBtn_clicked() this, tr("Edit file as JSON"), tr("The file you selected has json syntax error. Continue editing may make you lose data. Would you like to continue?") + NEWLINE + jsonCheckingError) != QMessageBox::Yes) - { return; } + { + return; + } else { LOG(MODULE_FILEIO, "Continue editing curruped json file, data loss is expected.") @@ -252,7 +263,10 @@ void ImportConfigWindow::on_editFileBtn_clicked() auto str = JsonToString(json); bool result = StringToFile(str, file); - if (!result) { QvMessageBoxWarn(this, tr("Edit file as JSON"), tr("Failed to save file, please check if you have proper permissions")); } + if (!result) + { + QvMessageBoxWarn(this, tr("Edit file as JSON"), tr("Failed to save file, please check if you have proper permissions")); + } } else { diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 39743d16..e81b60b8 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -32,44 +32,8 @@ // operations. #define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING -// #define GetItemWidget(item) (qobject_cast(connectionListWidget->itemWidget(item, 0))) -/* -#define ItemConnectionIdentifier(__item__) (__item__->data(0, -Qt::UserRole).value()) - -#define CheckConfigType(_item_, TYPE) -(connections.contains(ItemConnectionIdentifier(_item_)) && -connections[ItemConnectionIdentifier(_item_)].configType == CONNECTION_ ## TYPE) - -#define SUBSCRIPTION_CONFIG_MODIFY_ASK(_item_) \ - if (!CheckConfigType(_item_, REGULAR)) { \ - if (QvMessageBoxAsk(this, QObject::tr("Editing a subscription config"), -QObject::tr("You are trying to edit a config loaded from subscription.") + \ - NEWLINE + QObject::tr("All changes will be -overwritten when the subscriptions are updated next time.") + \ - NEWLINE + QObject::tr("Are you still going to do -so?")) != QMessageBox::Yes) { \ - return; \ - } \ - } \ - - -#define SUBSCRIPTION_CONFIG_MODIFY_DENY(_item_) \ - if (!CheckConfigType(_item_, REGULAR)) { \ - QvMessageBoxWarn(this, QObject::tr("Editing a subscription config"), -QObject::tr("You should not modity this property of a config from a -subscription")); \ - return; \ - } \ - -#define IsConnectableItem(item) (item != nullptr && item->childCount() == 0 && -(CheckConfigType(item, REGULAR) || CheckConfigType(item, SUBSCRIPTION))) #define -IsSelectionConnectable (!connectionListWidget->selectedItems().empty() && -IsConnectableItem(connectionListWidget->selectedItems().first())) -*/ - MainWindow *MainWindow::mwInstance = nullptr; QvMessageBusSlotImpl(MainWindow) @@ -112,6 +76,18 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h connect(ConnectionManager, &QvConnectionHandler::OnDisConnected, this, &MainWindow::OnDisConnected); connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &MainWindow::onConnectionStatsArrived); connect(ConnectionManager, &QvConnectionHandler::OnVCoreLogAvailable, this, &MainWindow::onVCoreLogArrived); + // + connect(ConnectionManager, &QvConnectionHandler::OnGroupCreated, this, &MainWindow::ReloadConnectionList); + connect(ConnectionManager, &QvConnectionHandler::OnGroupRenamed, this, &MainWindow::ReloadConnectionList); + connect(ConnectionManager, &QvConnectionHandler::OnGroupDeleted, this, &MainWindow::ReloadConnectionList); + + // TODO: A better UI algorithm + connect(ConnectionManager, &QvConnectionHandler::OnConnectionRemoved, this, &MainWindow::ReloadConnectionList); + connect(ConnectionManager, &QvConnectionHandler::OnConnectionChanged, this, &MainWindow::ReloadConnectionList); + connect(ConnectionManager, &QvConnectionHandler::OnConnectionCreated, this, &MainWindow::ReloadConnectionList); + connect(ConnectionManager, &QvConnectionHandler::OnConnectionRenamed, this, &MainWindow::ReloadConnectionList); + connect(ConnectionManager, &QvConnectionHandler::OnConnectionGroupChanged, this, &MainWindow::ReloadConnectionList); + // connect(infoWidget, &ConnectionInfoWidget::OnEditRequested, this, &MainWindow::OnEditRequested); connect(infoWidget, &ConnectionInfoWidget::OnJsonEditRequested, this, &MainWindow::OnJsonEditRequested); @@ -194,26 +170,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h connectionListMenu->addAction(action_RCM_EditJson); connectionListMenu->addAction(action_RCM_ConvToComplex); // - LOG(MODULE_UI, "Loading data...") - auto groups = ConnectionManager->AllGroups(); - - for (auto group : groups) - { - auto groupItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetDisplayName(group)); - connectionListWidget->addTopLevelItem(groupItem); - connectionListWidget->setItemWidget(groupItem, 0, new ConnectionItemWidget(group, connectionListWidget)); - auto connections = ConnectionManager->Connections(group); - - for (auto connection : connections) - { - auto connectionItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetDisplayName(connection)); - groupItem->addChild(connectionItem); - auto widget = new ConnectionItemWidget(connection, connectionListWidget); - connect(widget, &ConnectionItemWidget::RequestWidgetFocus, this, &MainWindow::onConnectionWidgetFocusRequested); - connectionListWidget->setItemWidget(connectionItem, 0, widget); - } - } - + ReloadConnectionList(); // // Find and start if there is an auto-connection auto needShowWindow = true; @@ -224,7 +181,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h needShowWindow = ConnectionManager->StartConnection(id).has_value(); } - if (needShowWindow) { this->show(); } + if (needShowWindow) + { + this->show(); + } //// If we are not connected to anything, show the MainWindow. if (needShowWindow) {} @@ -246,6 +206,35 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h splitter->setSizes(QList() << 100 << 300); } +void MainWindow::ReloadConnectionList() +{ + // Firstly, delete all items. + // for (auto _item_ : connectionListWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard | Qt::MatchRecursive)) + //{ + //} + connectionListWidget->clear(); + // + LOG(MODULE_UI, "Loading data...") + auto groups = ConnectionManager->AllGroups(); + + for (auto group : groups) + { + auto groupItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetDisplayName(group)); + connectionListWidget->addTopLevelItem(groupItem); + connectionListWidget->setItemWidget(groupItem, 0, new ConnectionItemWidget(group, connectionListWidget)); + auto connections = ConnectionManager->Connections(group); + + for (auto connection : connections) + { + auto connectionItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetDisplayName(connection)); + groupItem->addChild(connectionItem); + auto widget = new ConnectionItemWidget(connection, connectionListWidget); + connect(widget, &ConnectionItemWidget::RequestWidgetFocus, this, &MainWindow::onConnectionWidgetFocusRequested); + connectionListWidget->setItemWidget(connectionItem, 0, widget); + } + } +} + void MainWindow::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) @@ -301,7 +290,10 @@ void MainWindow::VersionUpdate(QByteArray &data) "\r\n------------\r\n" + root["body"].toString("") + "\r\n------------\r\n" + tr("Download Link: ") + link, QMessageBox::Ignore); - if (result == QMessageBox::Yes) { QDesktopServices::openUrl(QUrl::fromUserInput(link)); } + if (result == QMessageBox::Yes) + { + QDesktopServices::openUrl(QUrl::fromUserInput(link)); + } else if (result == QMessageBox::Ignore) { // Set and save ingored version. @@ -368,7 +360,10 @@ void MainWindow::ToggleVisibility() void MainWindow::on_actionExit_triggered() { - if (StartupOption.enableToolbarPlguin) { StopProcessingPlugins(); } + if (StartupOption.enableToolbarPlguin) + { + StopProcessingPlugins(); + } ExitQv2ray(); } @@ -400,7 +395,10 @@ void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint auto _pos = QCursor::pos(); auto item = connectionListWidget->itemAt(connectionListWidget->mapFromGlobal(_pos)); - if (GetItemWidget(item)->IsConnection()) { connectionListMenu->popup(_pos); } + if (GetItemWidget(item)->IsConnection()) + { + connectionListMenu->popup(_pos); + } } void MainWindow::on_action_RCM_RenameConnection_triggered() { @@ -654,7 +652,10 @@ void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item Q_UNUSED(column) auto widget = GetItemWidget(item); - if (widget->IsConnection()) { widget->BeginConnection(); } + if (widget->IsConnection()) + { + widget->BeginConnection(); + } } void MainWindow::OnDisConnected(const ConnectionId &id) @@ -664,7 +665,10 @@ void MainWindow::OnDisConnected(const ConnectionId &id) hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE); connetionStatusLabel->setText(tr("Disconnected")); - if (systemProxyEnabled) { MWClearSystemProxy(false); } + if (systemProxyEnabled) + { + MWClearSystemProxy(false); + } // QFile(QV2RAY_GENERATED_FILE_PATH).remove(); @@ -705,7 +709,10 @@ void MainWindow::OnConnected(const ConnectionId &id) if (pacUseSocks) { - if (socksEnabled) { pacProxyString = "SOCKS5 " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.socks_port); } + if (socksEnabled) + { + pacProxyString = "SOCKS5 " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.socks_port); + } else { LOG(MODULE_UI, "PAC is using SOCKS, but it is not enabled") @@ -716,7 +723,10 @@ void MainWindow::OnConnected(const ConnectionId &id) } else { - if (httpEnabled) { pacProxyString = "PROXY " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.http_port); } + if (httpEnabled) + { + pacProxyString = "PROXY " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.http_port); + } else { LOG(MODULE_UI, "PAC is using HTTP, but it is not enabled") @@ -737,12 +747,18 @@ void MainWindow::OnConnected(const ConnectionId &id) } } - if (GlobalConfig.inboundConfig.setSystemProxy) { MWSetSystemProxy(); } + if (GlobalConfig.inboundConfig.setSystemProxy) + { + MWSetSystemProxy(); + } } void MainWindow::onConnectionWidgetFocusRequested(const ConnectionItemWidget *_widget) { - if (_widget == nullptr) { return; } + if (_widget == nullptr) + { + return; + } for (auto _item_ : connectionListWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard | Qt::MatchRecursive)) { @@ -784,7 +800,10 @@ void MainWindow::on_connectionFilterTxt_textEdited(const QString &arg1) _top_item_->setHidden(isTotallyHide); - if (!isTotallyHide) { connectionListWidget->expandItem(_top_item_); } + if (!isTotallyHide) + { + connectionListWidget->expandItem(_top_item_); + } } } @@ -841,7 +860,8 @@ void MainWindow::onVCoreLogArrived(const ConnectionId &id, const QString &log) } } - if (val >= max * 0.8 || val >= max - 20) bar->setValue(max); + if (val >= max * 0.8 || val >= max - 20) + bar->setValue(max); } void MainWindow::OnEditRequested(const ConnectionId &id) @@ -891,5 +911,8 @@ void MainWindow::OnJsonEditRequested(const ConnectionId &id) JsonEditor w(ConnectionManager->GetConnectionRoot(id), this); auto root = CONFIGROOT(w.OpenEditor()); - if (w.result() == QDialog::Accepted) { ConnectionManager->UpdateConnection(id, root); } + if (w.result() == QDialog::Accepted) + { + ConnectionManager->UpdateConnection(id, root); + } } diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index f7b4dc09..2f45ed43 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -58,6 +58,8 @@ class MainWindow void closeEvent(QCloseEvent *) override; private slots: + // + void ReloadConnectionList(); // void OnConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id); diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index 158c7f82..6c9d4e31 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -38,7 +38,10 @@ void MainWindow::MWClearSystemProxy(bool showMessage) LOG(MODULE_UI, "Clearing System Proxy") systemProxyEnabled = false; - if (showMessage) { hTray.showMessage("Qv2ray", tr("System proxy cleared."), windowIcon()); } + if (showMessage) + { + hTray.showMessage("Qv2ray", tr("System proxy cleared."), windowIcon()); + } } void MainWindow::MWSetSystemProxy() diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index 61f9a0e9..d6a1e537 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -18,9 +18,11 @@ using Qv2ray::common::validation::IsValidIPAddress; #define LOADINGCHECK \ - if (!finishedLoading) return; + if (!finishedLoading) \ + return; #define NEEDRESTART \ - if (finishedLoading) IsConnectionPropertyChanged = true; + if (finishedLoading) \ + IsConnectionPropertyChanged = true; PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), CurrentConfig() { @@ -33,7 +35,9 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), Current networkToolbarPage->setEnabled(StartupOption.enableToolbarPlguin); if (!StartupOption.enableToolbarPlguin) - { networkToolbarInfoLabel->setText(tr("Qv2ray Network Toolbar is disabled and still under test. Add --withToolbarPlugin to enable.")); } + { + networkToolbarInfoLabel->setText(tr("Qv2ray Network Toolbar is disabled and still under test. Add --withToolbarPlugin to enable.")); + } // We add locales languageComboBox->clear(); @@ -122,7 +126,10 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), Current { auto str = dnsStr.trimmed(); - if (!str.isEmpty()) { DNSListTxt->appendPlainText(str); } + if (!str.isEmpty()) + { + DNSListTxt->appendPlainText(str); + } } // @@ -165,7 +172,9 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), Current // FP Settings if (CurrentConfig.connectionConfig.forwardProxyConfig.type.trimmed().isEmpty()) - { CurrentConfig.connectionConfig.forwardProxyConfig.type = "http"; } + { + CurrentConfig.connectionConfig.forwardProxyConfig.type = "http"; + } fpGroupBox->setChecked(CurrentConfig.connectionConfig.forwardProxyConfig.enableForwardProxy); fpUsernameTx->setText(CurrentConfig.connectionConfig.forwardProxyConfig.username); @@ -248,7 +257,9 @@ void PreferencesWindow::on_buttonBox_accepted() // Install translator if (!qApp->installTranslator(Qv2rayTranslator.get())) - { LOG(MODULE_UI, "Failed to translate UI to: " + CurrentConfig.uiConfig.language) } + { + LOG(MODULE_UI, "Failed to translate UI to: " + CurrentConfig.uiConfig.language) + } else { messageBus.EmitGlobalSignal(QvMBMessage::RETRANSLATE); @@ -304,7 +315,10 @@ void PreferencesWindow::on_listenIPTxt_textEdited(const QString &arg1) NEEDRESTART CurrentConfig.inboundConfig.listenip = arg1; - if (IsValidIPAddress(arg1)) { BLACK(listenIPTxt) } + if (IsValidIPAddress(arg1)) + { + BLACK(listenIPTxt) + } else { RED(listenIPTxt) @@ -576,7 +590,10 @@ void PreferencesWindow::on_socksUDPIP_textEdited(const QString &arg1) NEEDRESTART CurrentConfig.inboundConfig.socksLocalIP = arg1; - if (IsValidIPAddress(arg1)) { BLACK(socksUDPIP) } + if (IsValidIPAddress(arg1)) + { + BLACK(socksUDPIP) + } else { RED(socksUDPIP) @@ -670,7 +687,8 @@ void PreferencesWindow::on_nsBarLineDelBTN_clicked() void PreferencesWindow::on_nsBarPagesList_currentRowChanged(int currentRow) { - if (currentRow < 0) return; + if (currentRow < 0) + return; // Change page. // We reload the lines @@ -699,7 +717,8 @@ void PreferencesWindow::on_nsBarPagesList_currentRowChanged(int currentRow) void PreferencesWindow::on_nsBarLinesList_currentRowChanged(int currentRow) { - if (currentRow < 0) return; + if (currentRow < 0) + return; CurrentBarLineId = currentRow; ShowLineParameters(CurrentBarLine); @@ -770,7 +789,10 @@ QString PreferencesWindow::GetBarLineDescription(QvBarLine barLine) QString result = "Empty"; result = NetSpeedPluginMessages[barLine.ContentType]; - if (barLine.ContentType == 0) { result += " (" + barLine.Message + ")"; } + if (barLine.ContentType == 0) + { + result += " (" + barLine.Message + ")"; + } result = result.append(barLine.Bold ? ", " + tr("Bold") : ""); result = result.append(barLine.Italic ? ", " + tr("Italic") : ""); @@ -781,7 +803,10 @@ void PreferencesWindow::ShowLineParameters(QvBarLine &barLine) { finishedLoading = false; - if (!barLine.Family.isEmpty()) { fontComboBox->setCurrentFont(QFont(barLine.Family)); } + if (!barLine.Family.isEmpty()) + { + fontComboBox->setCurrentFont(QFont(barLine.Family)); + } // Colors nsBarFontASB->setValue(barLine.ColorA); @@ -933,7 +958,10 @@ void PreferencesWindow::on_pacGoBtn_clicked() pacGoBtn->setEnabled(true); gfwListCB->setEnabled(true); - if (!QDir(QV2RAY_RULES_DIR).exists()) { QDir(QV2RAY_RULES_DIR).mkpath(QV2RAY_RULES_DIR); } + if (!QDir(QV2RAY_RULES_DIR).exists()) + { + QDir(QV2RAY_RULES_DIR).mkpath(QV2RAY_RULES_DIR); + } StringToFile(fileContent, QV2RAY_RULES_GFWLIST_PATH); } @@ -997,7 +1025,10 @@ void PreferencesWindow::on_startWithLoginCB_stateChanged(int arg1) bool isEnabled = arg1 == Qt::Checked; SetLaunchAtLoginStatus(isEnabled); - if (GetLaunchAtLoginStatus() != isEnabled) { QvMessageBoxWarn(this, tr("Start with boot"), tr("Failed to set auto start option.")); } + if (GetLaunchAtLoginStatus() != isEnabled) + { + QvMessageBoxWarn(this, tr("Start with boot"), tr("Failed to set auto start option.")); + } SetAutoStartButtonsState(GetLaunchAtLoginStatus()); } @@ -1018,7 +1049,10 @@ void PreferencesWindow::on_fpAddressTx_textEdited(const QString &arg1) LOADINGCHECK CurrentConfig.connectionConfig.forwardProxyConfig.serverAddress = arg1; - if (IsValidIPAddress(arg1)) { BLACK(fpAddressTx) } + if (IsValidIPAddress(arg1)) + { + BLACK(fpAddressTx) + } else { RED(fpAddressTx) @@ -1061,7 +1095,10 @@ void PreferencesWindow::on_pacProxyTxt_textChanged(const QString &arg1) { Q_UNUSED(arg1) - if (IsValidIPAddress(arg1)) { BLACK(pacProxyTxt) } + if (IsValidIPAddress(arg1)) + { + BLACK(pacProxyTxt) + } else { RED(pacProxyTxt) @@ -1077,7 +1114,10 @@ void PreferencesWindow::on_checkVCoreSettings_clicked() auto vAssetsPath = vCoreAssetsPathTxt->text(); QString result; - if (!V2rayKernelInstance::ValidateKernel(vcorePath, vAssetsPath, &result)) { QvMessageBoxWarn(this, tr("V2ray Core Settings"), result); } + if (!V2rayKernelInstance::ValidateKernel(vcorePath, vAssetsPath, &result)) + { + QvMessageBoxWarn(this, tr("V2ray Core Settings"), result); + } else { QvMessageBoxInfo(this, tr("V2ray Core Settings"), diff --git a/src/ui/w_ScreenShot_Core.cpp b/src/ui/w_ScreenShot_Core.cpp index 1af073f0..4f1ecb41 100644 --- a/src/ui/w_ScreenShot_Core.cpp +++ b/src/ui/w_ScreenShot_Core.cpp @@ -98,7 +98,10 @@ bool ScreenShotWindow::event(QEvent *e) void ScreenShotWindow::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape) { reject(); } + if (e->key() == Qt::Key_Escape) + { + reject(); + } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { on_startBtn_clicked(); @@ -129,13 +132,19 @@ void ScreenShotWindow::mouseMoveEvent(QMouseEvent *e) QRect labelRect(label->contentsRect()); QRect btnRect(startBtn->contentsRect()); - if (imgY > labelRect.height()) { label->move(imgX, imgY - labelRect.height()); } + if (imgY > labelRect.height()) + { + label->move(imgX, imgY - labelRect.height()); + } else { label->move(imgX, imgY); } - if (height() - imgY - imgH > btnRect.height()) { startBtn->move(imgX + imgW - btnRect.width(), imgY + imgH); } + if (height() - imgY - imgH > btnRect.height()) + { + startBtn->move(imgX + imgW - btnRect.width(), imgY + imgH); + } else { startBtn->move(imgX + imgW - btnRect.width(), imgY + imgH - btnRect.height()); @@ -148,7 +157,10 @@ void ScreenShotWindow::mouseMoveEvent(QMouseEvent *e) void ScreenShotWindow::mouseReleaseEvent(QMouseEvent *e) { - if (e->button() == Qt::RightButton) { reject(); } + if (e->button() == Qt::RightButton) + { + reject(); + } } ScreenShotWindow::~ScreenShotWindow() diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index d07a4b10..9c0c36fe 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -12,7 +12,11 @@ SubscribeEditor::SubscribeEditor(QWidget *parent) : QDialog(parent) removeSubsButton->setIcon(QICON_R("delete.png")); for (auto subs : ConnectionManager->Subscriptions()) - { subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList() << ConnectionManager->GetDisplayName(subs) << subs.toString())); } + { + subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList() // + << ConnectionManager->GetDisplayName(subs) // + << subs.toString())); // + } } QvMessageBusSlotImpl(SubscribeEditor) @@ -34,136 +38,49 @@ SubscribeEditor::~SubscribeEditor() void SubscribeEditor::on_addSubsButton_clicked() { - // auto const key = QSTRN(QTime::currentTime().msecsSinceStartOfDay()); - // subscriptionList->addItem(key); - // subscriptions[key].address = "https://example.com/myfile"; - // QDir().mkpath(QV2RAY_SUBSCRIPTION_DIR + key); - // subscriptionList->setCurrentRow(subscriptions.count() - 1); - // SaveConfig(); + auto const key = QSTRN(QTime::currentTime().msecsSinceStartOfDay()); + auto id = ConnectionManager->CreateGroup(key, true); + // + subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList() // + << key // + << id.toString())); // } void SubscribeEditor::on_updateButton_clicked() { - ConnectionManager->UpdateSubscription(currentSubId, withProxyCB->isChecked()); - // auto newName = subNameTxt->text().trimmed(); - // auto newAddress = subAddrTxt->text().trimmed(); - // auto newUpdateInterval = updateIntervalSB->value(); - // if (currentSubId != newName) { - // // Rename needed. - // LOG(MODULE_SUBSCRIPTION, "Renaming a subscription, from " + - // currentSubId + " to: " + newName) bool canGo = true; - // - // if (newName.isEmpty() || !IsValidFileName(newName)) { - // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("The - // subscription name is invalid, please try another.")); canGo = - // false; - // } - // - // if (subscriptionList->findItems(newName, Qt::MatchExactly).count() > - // 0) { - // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("New name - // of this subscription has been used already, please suggest another - // one")); canGo = false; - // } - // - // if (!canGo) { - // subNameTxt->setText(currentSubId); - // return; - // } - // - // ////bool result = RenameSubscription(currentSubName, newName); - // // - // //if (!result) { - // // QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("Failed - // to rename a subscription, this is an unknown error.")); - // // return; - // //} - // subscriptions[newName] = subscriptions[currentSubId]; - // subscriptions.remove(currentSubId); - // subNameTxt->setText(newName); - // // - // QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - // // Update auto-start config if possible - // //auto ASsetting = GlobalConfig.autoStartConfig.subscriptionName; - // // - // //if (ASsetting == currentSubName) { - // // GlobalConfig.autoStartConfig.subscriptionName = newName; - // //} - // SaveGlobalConfig(GlobalConfig); - // // This will set the name to the new name. - // LoadSubscriptionList(subscriptions); - // // Keep subAddress && Interval changes - // // Update thing still down - // subAddrTxt->setText(newAddress); - // updateIntervalSB->setValue(newUpdateInterval); - // QvMessageBoxInfo(this, tr("Renaming a subscription"), tr("Successfully - // renamed a subscription")); - //} - // - // subscriptions[currentSubId].updateInterval = newUpdateInterval; - // - // if (subscriptions[currentSubId].address != newAddress) { - // LOG(MODULE_SUBSCRIPTION, "Setting new address, from " + - // subscriptions[currentSubId].address + " to: " + newAddress) - // subscriptions[currentSubId].address = newAddress; - //} - // - ////SaveConfig(); - // - ////if (QvMessageBoxAsk(this, tr("Update Subscription"), tr("Would you like - /// to reload this subscription from the Url?")) == QMessageBox::Yes) { / - /// StartUpdateSubscription(currentSubId); - ////} -} - -void SubscribeEditor::StartUpdateSubscription(const QString &subscriptionName) -{ - this->setEnabled(false); - // auto data = helper.syncget(subscriptions[subscriptionName].address, - // withProxyCB->isChecked()); auto content = - - this->setEnabled(true); + if (QvMessageBoxAsk(this, tr("Reload Subscription"), tr("Would you like to reload the subscription?")) == QMessageBox::Yes) + { + this->setEnabled(false); + ConnectionManager->UpdateSubscription(currentSubId, withProxyCB->isChecked()); // + this->setEnabled(true); + on_subscriptionList_itemClicked(subscriptionList->currentItem(), 0); + } } void SubscribeEditor::on_removeSubsButton_clicked() { - // if (subscriptionList->currentRow() < 0) - // return; - // - // auto name = subscriptionList->currentItem()->text(); - // subscriptionList->takeItem(subscriptionList->currentRow()); - // subscriptions.remove(name); - // - // if (!name.isEmpty()) { - // QDir(QV2RAY_SUBSCRIPTION_DIR + name).removeRecursively(); - //} - // - ////// If removed a whole subscription... - ////if (GlobalConfig.autoStartConfig.subscriptionName == name) { - //// GlobalConfig.autoStartConfig = QvConnectionObject(); - //// SaveGlobalConfig(GlobalConfig); - ////} - // groupBox_2->setEnabled(subscriptionList->count() > 0); - // SaveConfig(); -} - -void SubscribeEditor::SaveConfig() -{ - // QMap newConf; - // - // for (auto _ : subscriptions.toStdMap()) { - // if (!_.second.address.isEmpty()) { - // newConf[_.first] = _.second; - // } - //} - // - // GlobalConfig.subscriptions = newConf; - // SaveGlobalConfig(GlobalConfig); + if (QvMessageBoxAsk(this, tr("Deleting a subscription"), tr("All connections will be moved to default group, do you want to continue?")) == + QMessageBox::Yes) + { + ConnectionManager->DeleteGroup(currentSubId); // + auto item = subscriptionList->currentItem(); + subscriptionList->removeItemWidget(item, 0); + delete item; + if (subscriptionList->topLevelItemCount() > 0) + { + subscriptionList->setCurrentItem(subscriptionList->topLevelItem(0)); + on_subscriptionList_itemClicked(subscriptionList->topLevelItem(0), 0); + } + else + { + groupBox_2->setEnabled(false); + } + } } void SubscribeEditor::on_buttonBox_accepted() { - SaveConfig(); + // Nothing? } void SubscribeEditor::on_subscriptionList_itemSelectionChanged() @@ -175,8 +92,13 @@ void SubscribeEditor::on_subscriptionList_itemClicked(QTreeWidgetItem *item, int { Q_UNUSED(column) - if (item == nullptr) { return; } + if (item == nullptr) + { + return; + } + // + groupBox_2->setEnabled(true); currentSubId = GroupId(item->text(1)); // subNameTxt->setText(ConnectionManager->GetDisplayName(currentSubId)); @@ -187,5 +109,32 @@ void SubscribeEditor::on_subscriptionList_itemClicked(QTreeWidgetItem *item, int // connectionsList->clear(); - for (auto conn : ConnectionManager->Connections(currentSubId)) { connectionsList->addItem(ConnectionManager->GetDisplayName(conn)); } + for (auto conn : ConnectionManager->Connections(currentSubId)) + { + connectionsList->addItem(ConnectionManager->GetDisplayName(conn)); // + } +} + +void SubscribeEditor::on_subscriptionList_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) +{ + on_subscriptionList_itemClicked(current, 0); + Q_UNUSED(previous) +} + +void SubscribeEditor::on_subNameTxt_textEdited(const QString &arg1) +{ + subscriptionList->selectedItems().first()->setText(0, arg1); + ConnectionManager->RenameGroup(currentSubId, arg1.trimmed()); +} + +void SubscribeEditor::on_subAddrTxt_textEdited(const QString &arg1) +{ + auto newUpdateInterval = updateIntervalSB->value(); + ConnectionManager->SetSubscriptionData(currentSubId, arg1, newUpdateInterval); +} + +void SubscribeEditor::on_updateIntervalSB_valueChanged(double arg1) +{ + auto newAddress = subAddrTxt->text().trimmed(); + ConnectionManager->SetSubscriptionData(currentSubId, newAddress, arg1); } diff --git a/src/ui/w_SubscriptionManager.hpp b/src/ui/w_SubscriptionManager.hpp index b0e5350c..66d31783 100644 --- a/src/ui/w_SubscriptionManager.hpp +++ b/src/ui/w_SubscriptionManager.hpp @@ -34,10 +34,15 @@ class SubscribeEditor void on_subscriptionList_itemClicked(QTreeWidgetItem *item, int column); - private: - void StartUpdateSubscription(const QString &subscriptionName); - void SaveConfig(); + void on_subscriptionList_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + void on_subNameTxt_textEdited(const QString &arg1); + + void on_subAddrTxt_textEdited(const QString &arg1); + + void on_updateIntervalSB_valueChanged(double arg1); + + private: bool isUpdateInProgress = false; GroupId currentSubId = NullGroupId; }; diff --git a/src/ui/w_SubscriptionManager.ui b/src/ui/w_SubscriptionManager.ui index fa379cbb..478a244b 100644 --- a/src/ui/w_SubscriptionManager.ui +++ b/src/ui/w_SubscriptionManager.ui @@ -59,6 +59,11 @@ true + + + 1 + + @@ -88,7 +93,11 @@ Add Subscription - A + + + + + :/assets/icons/ui_light/add.png:/assets/icons/ui_light/add.png @@ -104,7 +113,11 @@ Remove Subscription - D + + + + + :/assets/icons/ui_light/delete.png:/assets/icons/ui_light/delete.png @@ -260,7 +273,9 @@ - + + + buttonBox diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index bd96f337..60627a2c 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -1,6 +1,7 @@ #include "ConnectionInfoWidget.hpp" #include "3rdparty/qzxing/src/QZXing.h" +#include "common/QvHelpers.hpp" #include "core/CoreUtils.hpp" #include "core/connection/Serialization.hpp" @@ -72,7 +73,10 @@ ConnectionInfoWidget::~ConnectionInfoWidget() void ConnectionInfoWidget::on_connectBtn_clicked() { - if (ConnectionManager->IsConnected(connectionId)) { ConnectionManager->StopConnection(); } + if (ConnectionManager->IsConnected(connectionId)) + { + ConnectionManager->StopConnection(); + } else { ConnectionManager->StartConnection(connectionId); @@ -91,7 +95,17 @@ void ConnectionInfoWidget::on_editJsonBtn_clicked() void ConnectionInfoWidget::on_deleteBtn_clicked() { - ConnectionManager->DeleteConnection(connectionId); + if (QvMessageBoxAsk(this, tr("Delete an item"), tr("Are you sure to delete the current item?")) == QMessageBox::Yes) + { + if (connectionId != NullConnectionId) + { + ConnectionManager->DeleteConnection(connectionId); + } + else + { + ConnectionManager->DeleteGroup(groupId); + } + } } bool ConnectionInfoWidget::eventFilter(QObject *object, QEvent *event) @@ -100,7 +114,10 @@ bool ConnectionInfoWidget::eventFilter(QObject *object, QEvent *event) { if (shareLinkTxt->underMouse()) { - if (!shareLinkTxt->hasSelectedText()) { shareLinkTxt->selectAll(); } + if (!shareLinkTxt->hasSelectedText()) + { + shareLinkTxt->selectAll(); + } } } @@ -109,12 +126,18 @@ bool ConnectionInfoWidget::eventFilter(QObject *object, QEvent *event) void ConnectionInfoWidget::OnConnected(const ConnectionId &id) { - if (connectionId == id) { connectBtn->setIcon(QICON_R("stop.png")); } + if (connectionId == id) + { + connectBtn->setIcon(QICON_R("stop.png")); + } } void ConnectionInfoWidget::OnDisConnected(const ConnectionId &id) { - if (connectionId == id) { connectBtn->setIcon(QICON_R("connect.png")); } + if (connectionId == id) + { + connectBtn->setIcon(QICON_R("connect.png")); + } } // MWTryPingConnection(CurrentConnectionIdentifier); void ConnectionInfoWidget::on_duplicateBtn_clicked() @@ -150,7 +173,10 @@ void ConnectionInfoWidget::on_duplicateBtn_clicked() void ConnectionInfoWidget::on_latencyBtn_clicked() { - if (connectionId != NullConnectionId) { ConnectionManager->StartLatencyTest(connectionId); } + if (connectionId != NullConnectionId) + { + ConnectionManager->StartLatencyTest(connectionId); + } else { ConnectionManager->StartLatencyTest(groupId); diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index 483b76fb..f4617108 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -18,11 +18,13 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare groupId = ConnectionManager->GetConnectionGroupId(id); originalConnectionName = ConnectionManager->GetDisplayName(id); itemType = NODE_ITEM; - connNameLabel->setText("" + originalConnectionName); - // TODO + connNameLabel->setText((ConnectionManager->IsConnected(id) ? "• " : "") + originalConnectionName); auto latency = ConnectionManager->GetConnectionLatency(id); - if (latency == 0) { latencyLabel->setText(tr("Not Tested")); } + if (latency == 0) + { + latencyLabel->setText(tr("Not Tested")); + } else { latencyLabel->setText(QSTRN(latency) + " " + tr("ms")); @@ -33,6 +35,11 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare dataLabel->setText(FormatBytes(uplink) + " / " + FormatBytes(downlink)); // indentSpacer->changeSize(10, indentSpacer->sizeHint().height()); + // + if (ConnectionManager->IsConnected(id)) + { + emit RequestWidgetFocus(this); + } } // ======================================= Initialisation for root nodes. @@ -53,7 +60,10 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : void ConnectionItemWidget::BeginConnection() { - if (itemType == NODE_ITEM) { ConnectionManager->StartConnection(connectionId); } + if (itemType == NODE_ITEM) + { + ConnectionManager->StartConnection(connectionId); + } else { LOG(MODULE_UI, "Trying to start a non-connection entry, this call is illegal.") @@ -72,7 +82,10 @@ void ConnectionItemWidget::OnConnected(const ConnectionId &id) void ConnectionItemWidget::OnDisConnected(const ConnectionId &id) { - if (id == connectionId) { connNameLabel->setText(originalConnectionName); } + if (id == connectionId) + { + connNameLabel->setText(originalConnectionName); + } } void ConnectionItemWidget::OnConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, @@ -81,12 +94,18 @@ void ConnectionItemWidget::OnConnectionStatsArrived(const ConnectionId &id, cons Q_UNUSED(upSpeed) Q_UNUSED(downSpeed) - if (id == connectionId) { dataLabel->setText(FormatBytes(totalUp) + " / " + FormatBytes(totalDown)); } + if (id == connectionId) + { + dataLabel->setText(FormatBytes(totalUp) + " / " + FormatBytes(totalDown)); + } } void ConnectionItemWidget::OnLatencyTestStart(const ConnectionId &id) { - if (id == connectionId) { latencyLabel->setText(tr("Testing...")); } + if (id == connectionId) + { + latencyLabel->setText(tr("Testing...")); + } } void ConnectionItemWidget::OnLatencyTestFinished(const ConnectionId &id, const uint average) { diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index 05b1b0d3..7fc1eda6 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -28,7 +28,10 @@ class ConnectionItemWidget auto searchString = arg.toLower(); auto headerMatched = ConnectionManager->GetDisplayName(groupId).toLower().contains(arg); - if (itemType != NODE_ITEM) { return headerMatched; } + if (itemType != NODE_ITEM) + { + return headerMatched; + } else { return headerMatched || ConnectionManager->GetDisplayName(connectionId).toLower().contains(searchString); diff --git a/src/ui/widgets/QvAutoCompleteTextEdit.cpp b/src/ui/widgets/QvAutoCompleteTextEdit.cpp index 87d781e0..a4b1d2bb 100644 --- a/src/ui/widgets/QvAutoCompleteTextEdit.cpp +++ b/src/ui/widgets/QvAutoCompleteTextEdit.cpp @@ -72,11 +72,15 @@ TextEdit::~TextEdit() void TextEdit::setCompleter(QCompleter *completer) { - if (c) c->disconnect(this); + if (c) + c->disconnect(this); c = completer; - if (!c) { return; } + if (!c) + { + return; + } c->setWidget(this); c->setCompletionMode(QCompleter::PopupCompletion); @@ -91,7 +95,8 @@ QCompleter *TextEdit::completer() const void TextEdit::insertCompletion(const QString &completion) { - if (c->widget() != this) return; + if (c->widget() != this) + return; QTextCursor tc = textCursor(); int extra = completion.length() - c->completionPrefix().length(); @@ -110,7 +115,8 @@ QString TextEdit::textUnderCursor() const void TextEdit::focusInEvent(QFocusEvent *e) { - if (c) c->setWidget(this); + if (c) + c->setWidget(this); QTextEdit::focusInEvent(e); } @@ -140,7 +146,8 @@ void TextEdit::keyPressEvent(QKeyEvent *e) const bool ctrlOrShift = e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::ShiftModifier); - if (!c || (ctrlOrShift && e->text().isEmpty())) return; + if (!c || (ctrlOrShift && e->text().isEmpty())) + return; static QString eow("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="); // end of word const bool hasModifier = (e->modifiers() != Qt::NoModifier) && !ctrlOrShift; diff --git a/src/ui/widgets/StreamSettingsWidget.cpp b/src/ui/widgets/StreamSettingsWidget.cpp index 6e0c5d32..ff47e83f 100644 --- a/src/ui/widgets/StreamSettingsWidget.cpp +++ b/src/ui/widgets/StreamSettingsWidget.cpp @@ -78,7 +78,10 @@ void StreamSettingsWidget::on_httpHostTxt_textChanged() for (auto host : hosts) { - if (!host.trimmed().isEmpty()) { stream.httpSettings.host.push_back(host.trimmed()); } + if (!host.trimmed().isEmpty()) + { + stream.httpSettings.host.push_back(host.trimmed()); + } } BLACK(httpHostTxt) @@ -98,11 +101,13 @@ void StreamSettingsWidget::on_wsHeadersTxt_textChanged() for (auto header : headers) { - if (header.isEmpty()) continue; + if (header.isEmpty()) + continue; auto index = header.indexOf("|"); - if (index < 0) throw "fast fail to set RED color"; + if (index < 0) + throw "fast fail to set RED color"; auto key = header.left(index); auto value = header.right(header.length() - index - 1); From 2d198f4292c2d3ba6109314fe33e77460e9bfda3 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 29 Feb 2020 20:25:17 +0800 Subject: [PATCH 066/332] add: added KDE proxy settings support --- makespec/BUILDVERSION | 2 +- src/components/proxy/QvProxyConfigurator.cpp | 50 ++++++++++++++++++-- src/ui/w_MainWindow_extra.cpp | 2 +- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 6ed4d106..7193414d 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4086 +4097 diff --git a/src/components/proxy/QvProxyConfigurator.cpp b/src/components/proxy/QvProxyConfigurator.cpp index de73f636..59f4a722 100644 --- a/src/components/proxy/QvProxyConfigurator.cpp +++ b/src/components/proxy/QvProxyConfigurator.cpp @@ -245,13 +245,31 @@ namespace Qv2ray::components::proxy QStringList actions; auto proxyMode = usePAC ? "auto" : "manual"; actions << QString("gsettings set org.gnome.system.proxy mode '%1'").arg(proxyMode); - + bool isKDE = qEnvironmentVariable("XDG_SESSION_DESKTOP") == "KDE"; + if (isKDE) + { + LOG(MODULE_PROXY, "KDE detected") + } + // if (usePAC) { actions << QString("gsettings set org.gnome.system.proxy autoconfig-url '%1'").arg(address); + if (isKDE) + { + actions << QString("kwriteconfig5 --file " + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + + "/kioslaverc --group \"Proxy Settings\" --key ProxyType 2"); + + actions << QString("kwriteconfig5 --file " + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + + "/kioslaverc --group \"Proxy Settings\" --key \"Proxy Config Script\" " + address); + } } else { + if (isKDE) + { + actions << QString("kwriteconfig5 --file " + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + + "/kioslaverc --group \"Proxy Settings\" --key ProxyType 1"); + } if (hasHTTP) { actions << QString("gsettings set org.gnome.system.proxy.http host '%1'").arg(address); @@ -259,13 +277,32 @@ namespace Qv2ray::components::proxy // actions << QString("gsettings set org.gnome.system.proxy.https host '%1'").arg(address); actions << QString("gsettings set org.gnome.system.proxy.https port %1").arg(httpPort); - ; + if (isKDE) + { + // FTP here should be scheme: ftp:// + for (auto protocol : { "http", "ftp", "https" }) + { + auto str = QString("kwriteconfig5 --file " + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + + "/kioslaverc --group \"Proxy Settings\" --key %1Proxy \"http://%2 %3\"") + .arg(protocol) + .arg(address) + .arg(QSTRN(httpPort)); + actions << str; + } + } } if (hasSOCKS) { actions << QString("gsettings set org.gnome.system.proxy.socks host '%1'").arg(address); actions << QString("gsettings set org.gnome.system.proxy.socks port %1").arg(socksPort); + if (isKDE) + { + actions << QString("kwriteconfig5 --file " + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + + "/kioslaverc --group \"Proxy Settings\" --key socksProxy \"socks://%1 %2\"") + .arg(address) + .arg(QSTRN(socksPort)); + } } } @@ -278,8 +315,8 @@ namespace Qv2ray::components::proxy if (!result) { - LOG(MODULE_PROXY, "Something wrong happens when setting system proxy -> Gnome ONLY.") - LOG(MODULE_PROXY, "If you are using KDE Plasma and receiving this message, just simply ignore this.") + LOG(MODULE_PROXY, "There was something wrong when setting proxies.") + LOG(MODULE_PROXY, "It may happen if you are using KDE with no gsettings support.") } Q_UNUSED(result); @@ -347,6 +384,11 @@ namespace Qv2ray::components::proxy InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0); InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0); #elif defined(Q_OS_LINUX) + if (qEnvironmentVariable("XDG_SESSION_DESKTOP") == "KDE") + { + QProcess::execute("kwriteconfig5 --file " + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + + "/kioslaverc --group \"Proxy Settings\" --key ProxyType 0"); + } QProcess::execute("gsettings set org.gnome.system.proxy mode 'none'"); #else diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index 6c9d4e31..a4514a67 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -54,7 +54,7 @@ void MainWindow::MWSetSystemProxy() // Set system proxy if necessary // bool isComplex = // IsComplexConfig(connections[CurrentConnectionIdentifier].config); - bool isComplex = true; + bool isComplex = false; if (!isComplex) { From 85d980e91b6c5c06ca8e4448575b709fd538e492 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 29 Feb 2020 23:11:03 +0800 Subject: [PATCH 067/332] add: added ConnectionCreate, ConnectionDelete, ConnectionChangeGroup, GroupCreate, GroupDelete UI slot implementations for MainWindow --- makespec/BUILDVERSION | 2 +- src/core/handler/ConnectionHandler.cpp | 66 +++++--- src/core/handler/ConnectionHandler.hpp | 31 ++-- src/core/handler/V2rayInstanceHandler.cpp | 4 +- src/ui/w_MainWindow.cpp | 184 ++++++++++++---------- src/ui/w_MainWindow.hpp | 36 +++-- src/ui/widgets/ConnectionInfoWidget.cpp | 3 +- src/ui/widgets/ConnectionInfoWidget.ui | 5 +- src/ui/widgets/ConnectionItemWidget.cpp | 11 +- src/ui/widgets/ConnectionItemWidget.hpp | 5 + 10 files changed, 200 insertions(+), 147 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 7193414d..5045e5c2 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4097 +4171 diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index ec0bac9d..b9e22857 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -20,16 +20,28 @@ namespace Qv2ray::core::handlers for (auto key : GlobalConfig.subscriptions.keys()) { + GroupId gkey(key); + if (gkey == NullGroupId) + { + LOG(MODULE_CORE_HANDLER, "Removed a null subscription id") + continue; + } auto val = GlobalConfig.subscriptions[key]; - groups[GroupId(key)] = val; + groups[gkey] = val; for (auto conn : val.connections) { connections[ConnectionId(conn)].groupId = GroupId(key); } } for (auto key : GlobalConfig.groups.keys()) { + GroupId gkey(key); + if (gkey == NullGroupId) + { + LOG(MODULE_CORE_HANDLER, "Removed a null group id") + continue; + } auto val = GlobalConfig.groups[key]; - groups[GroupId(key)] = val; + groups[gkey] = val; for (auto conn : val.connections) { connections[ConnectionId(conn)].groupId = GroupId(key); } } @@ -225,7 +237,7 @@ namespace Qv2ray::core::handlers { connections.remove(id); groups[groupId].connections.removeAll(id); - emit OnConnectionRemoved(id); + emit OnConnectionDeleted(id, groupId); return {}; } else @@ -235,7 +247,7 @@ namespace Qv2ray::core::handlers return tr("File does not exist."); } - const optional QvConnectionHandler::MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId, bool emitSignal) + const optional QvConnectionHandler::MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId) { auto const oldgid = connections[id].groupId; // @@ -258,39 +270,37 @@ namespace Qv2ray::core::handlers groups[newGroupId].connections.append(id); connections[id].groupId = newGroupId; // - if (emitSignal) - { - emit OnConnectionGroupChanged(id, oldgid, newGroupId); - } + emit OnConnectionGroupChanged(id, oldgid, newGroupId); // return {}; } const optional QvConnectionHandler::DeleteGroup(const GroupId &id) { - if (!groups.contains(id)) + if (!groups.contains(id) || id == NullGroupId) { return tr("Group does not exist"); } // Copy construct auto list = groups[id].connections; - for (auto conn : list) - { - MoveConnectionGroup(conn, DefaultGroupId, false); // - } + for (auto conn : list) { MoveConnectionGroup(conn, DefaultGroupId); } // if (groups[id].isSubscription) { - QDir(QV2RAY_SUBSCRIPTION_DIR + id.toString()).removeRecursively(); // + QDir(QV2RAY_SUBSCRIPTION_DIR + id.toString()).removeRecursively(); } else { QDir(QV2RAY_CONNECTIONS_DIR + id.toString()).removeRecursively(); } - emit OnGroupDeleted(id, groups[id].displayName); // groups.remove(id); + emit OnGroupDeleted(id, list); + if (id == DefaultGroupId) + { + groups[id].displayName = tr("Default Group"); + } return {}; } @@ -310,6 +320,16 @@ namespace Qv2ray::core::handlers return CHStartConnection_p(identifier, root); } + void QvConnectionHandler::RestartConnection() // const ConnectionId &id + { + auto conn = currentConnectionId; + if (conn != NullConnectionId) + { + StopConnection(); + StartConnection(conn); + } + } + void QvConnectionHandler::StopConnection() // const ConnectionId &id { // Currently just simply stop it. @@ -374,6 +394,7 @@ namespace Qv2ray::core::handlers } delete vCoreInstance; + delete httpHelper; } const CONFIGROOT QvConnectionHandler::GetConnectionRoot(const ConnectionId &id) const @@ -528,15 +549,15 @@ namespace Qv2ray::core::handlers } } // - /// List that is holding connection IDs to be updated. + // List that is holding connection IDs to be updated. + // Copy construct here. auto connectionsOrig = groups[id].connections; - QList connectionsNew; + groups[id].connections.clear(); auto str = DecodeSubscriptionString(subscriptionData); if (str.isEmpty()) return false; // auto subsList = SplitLines(str); - // QDir(QV2RAY_SUBSCRIPTION_DIR + id.toString()).removeRecursively(); QDir().mkpath(QV2RAY_SUBSCRIPTION_DIR + id.toString()); bool hasErrorOccured = false; @@ -560,7 +581,7 @@ namespace Qv2ray::core::handlers { // Just go and save the connection... LOG(MODULE_CORE_HANDLER, "Reused connection id from name: " + _alias) - connectionsNew << nameMap[_alias]; + groups[id].connections << nameMap[_alias]; UpdateConnection(nameMap[_alias], config); // Remove Connection Id from the list. connectionsOrig.removeAll(nameMap[_alias]); @@ -568,7 +589,7 @@ namespace Qv2ray::core::handlers else if (canGetOutboundData && typeMap.contains(outboundData)) { LOG(MODULE_CORE_HANDLER, "Reused connection id from protocol/host/port pair for connection: " + _alias) - connectionsNew << typeMap[outboundData]; + groups[id].connections << typeMap[outboundData]; UpdateConnection(typeMap[outboundData], config); // Update displayName connections[typeMap[outboundData]].displayName = _alias; @@ -580,11 +601,12 @@ namespace Qv2ray::core::handlers // New connection id is required since nothing matched found... LOG(MODULE_CORE_HANDLER, "Generated new connection id for connection: " + _alias) ConnectionId newId(GenerateUuid()); - connectionsNew << newId; + groups[id].connections << newId; connections[newId].groupId = id; connections[newId].importDate = system_clock::to_time_t(system_clock::now()); connections[newId].displayName = _alias; UpdateConnection(newId, config); + emit OnConnectionCreated(newId, _alias); } // End guessing connectionId } @@ -596,8 +618,6 @@ namespace Qv2ray::core::handlers LOG(MODULE_CORE_HANDLER, "Removing: " + conn.toString()) DeleteConnection(conn); } - // Set new connection list - groups[id].connections = connectionsNew; return hasErrorOccured; } diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 477abde0..e181ad62 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -32,26 +32,26 @@ namespace Qv2ray::core::handlers const ConnectionId GetConnectionIdByDisplayName(const QString &displayName) const; // // Connectivity Operationss - bool IsConnected(const ConnectionId &id) const; const optional StartConnection(const ConnectionId &identifier); void StopConnection(); // const ConnectionId &id + void RestartConnection(); + bool IsConnected(const ConnectionId &id) const; // // Connection Operations. - const GroupId GetConnectionGroupId(const ConnectionId &id) const; - double GetConnectionLatency(const ConnectionId &id) const; - const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); - const optional DeleteConnection(const ConnectionId &id); bool UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); + const optional DeleteConnection(const ConnectionId &id); const optional RenameConnection(const ConnectionId &id, const QString &newName); + const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); + const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); const ConnectionId DuplicateConnection(const ConnectionId &id); - const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId, bool emitSignal = true); - // - const CONFIGROOT GetConnectionRoot(const ConnectionId &id) const; - const CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id) const; // // Get Conncetion Property - const QString GetConnectionProtocolString(const ConnectionId &id) const; const tuple GetConnectionData(const ConnectionId &connectionId) const; + const GroupId GetConnectionGroupId(const ConnectionId &id) const; + const QString GetConnectionProtocolString(const ConnectionId &id) const; + const CONFIGROOT GetConnectionRoot(const ConnectionId &id) const; + const CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id) const; + double GetConnectionLatency(const ConnectionId &id) const; const tuple GetConnectionUsageAmount(const ConnectionId &id) const; // // Misc Connection Operations @@ -74,14 +74,13 @@ namespace Qv2ray::core::handlers signals: void OnCrashed(); void OnConnected(const ConnectionId &id); - void OnDisConnected(const ConnectionId &id); + void OnDisconnected(const ConnectionId &id); void OnVCoreLogAvailable(const ConnectionId &id, const QString &log); - void OnStatsAvailable(const ConnectionId &id, const quint64 uploadSpeed, const quint64 downloadSpeed, const quint64 totalUpload, - const quint64 totalDownload); + void OnStatsAvailable(const ConnectionId &id, const quint64 upS, const quint64 downS, const quint64 upD, const quint64 downD); // void OnConnectionCreated(const ConnectionId &id, const QString &displayName); void OnConnectionRenamed(const ConnectionId &id, const QString &originalName, const QString &newName); - void OnConnectionRemoved(const ConnectionId &id); + void OnConnectionDeleted(const ConnectionId &id, const GroupId &originalGroupId); void OnConnectionChanged(const ConnectionId &id); void OnConnectionGroupChanged(const ConnectionId &id, const GroupId &originalGroup, const GroupId &newGroup); // @@ -90,10 +89,8 @@ namespace Qv2ray::core::handlers // void OnGroupCreated(const GroupId &id, const QString &displayName); void OnGroupRenamed(const GroupId &id, const QString &oldName, const QString &newName); - void OnGroupDeleted(const GroupId &id, const QString &displayName); + void OnGroupDeleted(const GroupId &id, const QList &connections); // - // void OnSubscriptionCreated(const GroupId &id, const QString &displayName, const QString &address); - // void OnSubscriptionDeleted(const GroupId &id, const QString &oldName, const QString &newName); void OnSubscriptionUpdateFinished(const GroupId &id); private slots: diff --git a/src/core/handler/V2rayInstanceHandler.cpp b/src/core/handler/V2rayInstanceHandler.cpp index 500f15cf..b270b04d 100644 --- a/src/core/handler/V2rayInstanceHandler.cpp +++ b/src/core/handler/V2rayInstanceHandler.cpp @@ -25,7 +25,7 @@ void QvConnectionHandler::CHStopConnection_p() // Copy ConnectionId id = currentConnectionId; currentConnectionId = NullConnectionId; - emit OnDisConnected(id); + emit OnDisconnected(id); } else { @@ -44,6 +44,6 @@ void QvConnectionHandler::OnVCoreCrashed(const ConnectionId &id) { LOG(MODULE_CORE_HANDLER, "V2ray core crashed!") currentConnectionId = NullConnectionId; - emit OnDisConnected(id); + emit OnDisconnected(id); emit OnCrashed(); } diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index e81b60b8..51f9aab8 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -44,6 +44,29 @@ QvMessageBusSlotImpl(MainWindow) } } +void MainWindow::MWAddConnectionItem_p(const ConnectionId &connection, const GroupId &groupId) +{ + if (!groupNodes.contains(groupId)) + { + MWAddGroupItem_p(groupId); + } + auto groupItem = groupNodes[groupId]; + auto connectionItem = make_shared(QStringList() << "" << ConnectionManager->GetDisplayName(connection)); + connectionNodes[connection] = connectionItem; + groupItem->addChild(connectionItem.get()); + auto widget = new ConnectionItemWidget(connection, connectionListWidget); + connect(widget, &ConnectionItemWidget::RequestWidgetFocus, this, &MainWindow::OnConnectionWidgetFocusRequested); + connectionListWidget->setItemWidget(connectionItem.get(), 0, widget); +} + +void MainWindow::MWAddGroupItem_p(const GroupId &groupId) +{ + auto groupItem = make_shared(QStringList() << "" << ConnectionManager->GetDisplayName(groupId)); + groupNodes[groupId] = groupItem; + connectionListWidget->addTopLevelItem(groupItem.get()); + connectionListWidget->setItemWidget(groupItem.get(), 0, new ConnectionItemWidget(groupId, connectionListWidget)); +} + MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), hTray(this), tcpingHelper(3, this) { setupUi(this); @@ -72,21 +95,18 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h tr("V2ray vcore terminated unexpectedly.") + NEWLINE + NEWLINE + tr("To solve the problem, read the V2ray log in the log text browser.")); }); - connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &MainWindow::OnConnected); - connect(ConnectionManager, &QvConnectionHandler::OnDisConnected, this, &MainWindow::OnDisConnected); - connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &MainWindow::onConnectionStatsArrived); - connect(ConnectionManager, &QvConnectionHandler::OnVCoreLogAvailable, this, &MainWindow::onVCoreLogArrived); // - connect(ConnectionManager, &QvConnectionHandler::OnGroupCreated, this, &MainWindow::ReloadConnectionList); - connect(ConnectionManager, &QvConnectionHandler::OnGroupRenamed, this, &MainWindow::ReloadConnectionList); - connect(ConnectionManager, &QvConnectionHandler::OnGroupDeleted, this, &MainWindow::ReloadConnectionList); - - // TODO: A better UI algorithm - connect(ConnectionManager, &QvConnectionHandler::OnConnectionRemoved, this, &MainWindow::ReloadConnectionList); - connect(ConnectionManager, &QvConnectionHandler::OnConnectionChanged, this, &MainWindow::ReloadConnectionList); - connect(ConnectionManager, &QvConnectionHandler::OnConnectionCreated, this, &MainWindow::ReloadConnectionList); - connect(ConnectionManager, &QvConnectionHandler::OnConnectionRenamed, this, &MainWindow::ReloadConnectionList); - connect(ConnectionManager, &QvConnectionHandler::OnConnectionGroupChanged, this, &MainWindow::ReloadConnectionList); + connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &MainWindow::OnConnected); + connect(ConnectionManager, &QvConnectionHandler::OnDisconnected, this, &MainWindow::OnDisconnected); + connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &MainWindow::OnStatsAvailable); + connect(ConnectionManager, &QvConnectionHandler::OnVCoreLogAvailable, this, &MainWindow::OnVCoreLogAvailable); + // + connect(ConnectionManager, &QvConnectionHandler::OnConnectionDeleted, this, &MainWindow::OnConnectionDeleted); + connect(ConnectionManager, &QvConnectionHandler::OnConnectionCreated, this, &MainWindow::OnConnectionCreated); + connect(ConnectionManager, &QvConnectionHandler::OnConnectionGroupChanged, this, &MainWindow::OnConnectionGroupChanged); + // + connect(ConnectionManager, &QvConnectionHandler::OnGroupCreated, this, &MainWindow::OnGroupCreated); + connect(ConnectionManager, &QvConnectionHandler::OnGroupDeleted, this, &MainWindow::OnGroupDeleted); // connect(infoWidget, &ConnectionInfoWidget::OnEditRequested, this, &MainWindow::OnEditRequested); @@ -127,11 +147,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h // connect(action_Tray_ShowHide, &QAction::triggered, this, &MainWindow::ToggleVisibility); connect(action_Tray_ShowPreferencesWindow, &QAction::triggered, this, &MainWindow::on_preferencesBtn_clicked); - // connect(action_Tray_Start, &QAction::triggered, this, - // &MainWindow::on_startButton_clicked); connect(action_Tray_Stop, - // &QAction::triggered, this, &MainWindow::on_stopButton_clicked); - // connect(action_Tray_Reconnect, &QAction::triggered, this, - // &MainWindow::on_reconnectButton_clicked); + // + connect(action_Tray_Start, &QAction::triggered, [&] { ConnectionManager->StartConnection(lastConnectedId); }); + connect(action_Tray_Stop, &QAction::triggered, ConnectionManager, &QvConnectionHandler::StopConnection); + connect(action_Tray_Reconnect, &QAction::triggered, ConnectionManager, &QvConnectionHandler::RestartConnection); + // connect(action_Tray_Quit, &QAction::triggered, this, &MainWindow::on_actionExit_triggered); connect(action_Tray_SetSystemProxy, &QAction::triggered, this, &MainWindow::MWSetSystemProxy); connect(action_Tray_ClearSystemProxy, &QAction::triggered, this, &MainWindow::MWClearSystemProxy); @@ -154,11 +174,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h connect(action_RCM_ShareQR, &QAction::triggered, this, &MainWindow::on_action_RCM_ShareQR_triggered); // // Globally invokable signals. - // connect(this, &MainWindow::Connect, this, - // &MainWindow::on_startButton_clicked); connect(this, - // &MainWindow::DisConnect, this, &MainWindow::on_stopButton_clicked); - // connect(this, &MainWindow::ReConnect, this, - // &MainWindow::on_reconnectButton_clicked); + connect(this, &MainWindow::Connect, [&] { ConnectionManager->StartConnection(lastConnectedId); }); + connect(this, &MainWindow::DisConnect, ConnectionManager, &QvConnectionHandler::StopConnection); + connect(this, &MainWindow::ReConnect, ConnectionManager, &QvConnectionHandler::RestartConnection); // hTray.setContextMenu(tray_RootMenu); hTray.show(); @@ -170,7 +188,19 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h connectionListMenu->addAction(action_RCM_EditJson); connectionListMenu->addAction(action_RCM_ConvToComplex); // - ReloadConnectionList(); + LOG(MODULE_UI, "Loading data...") + auto groups = ConnectionManager->AllGroups(); + + for (auto group : groups) + { + MWAddGroupItem_p(group); + auto connections = ConnectionManager->Connections(group); + + for (auto connection : connections) + { + MWAddConnectionItem_p(connection, group); // + } + } // // Find and start if there is an auto-connection auto needShowWindow = true; @@ -182,12 +212,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h } if (needShowWindow) - { this->show(); - } - - //// If we are not connected to anything, show the MainWindow. - if (needShowWindow) {} #ifndef DISABLE_AUTO_UPDATE requestHelper = new QvHttpRequestHelper(); @@ -206,35 +231,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h splitter->setSizes(QList() << 100 << 300); } -void MainWindow::ReloadConnectionList() -{ - // Firstly, delete all items. - // for (auto _item_ : connectionListWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard | Qt::MatchRecursive)) - //{ - //} - connectionListWidget->clear(); - // - LOG(MODULE_UI, "Loading data...") - auto groups = ConnectionManager->AllGroups(); - - for (auto group : groups) - { - auto groupItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetDisplayName(group)); - connectionListWidget->addTopLevelItem(groupItem); - connectionListWidget->setItemWidget(groupItem, 0, new ConnectionItemWidget(group, connectionListWidget)); - auto connections = ConnectionManager->Connections(group); - - for (auto connection : connections) - { - auto connectionItem = new QTreeWidgetItem(QStringList() << "" << ConnectionManager->GetDisplayName(connection)); - groupItem->addChild(connectionItem); - auto widget = new ConnectionItemWidget(connection, connectionListWidget); - connect(widget, &ConnectionItemWidget::RequestWidgetFocus, this, &MainWindow::onConnectionWidgetFocusRequested); - connectionListWidget->setItemWidget(connectionItem, 0, widget); - } - } -} - void MainWindow::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) @@ -658,7 +654,7 @@ void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item } } -void MainWindow::OnDisConnected(const ConnectionId &id) +void MainWindow::OnDisconnected(const ConnectionId &id) { Q_UNUSED(id) this->hTray.showMessage("Qv2ray", tr("Disonnected"), this->windowIcon()); @@ -753,7 +749,7 @@ void MainWindow::OnConnected(const ConnectionId &id) } } -void MainWindow::onConnectionWidgetFocusRequested(const ConnectionItemWidget *_widget) +void MainWindow::OnConnectionWidgetFocusRequested(const ConnectionItemWidget *_widget) { if (_widget == nullptr) { @@ -790,6 +786,7 @@ void MainWindow::on_connectionFilterTxt_textEdited(const QString &arg1) LOG(MODULE_UI, "Setting current item.") // Show the child _child_->setHidden(false); + // If any one of the children matches, the parent should not be hidden. isTotallyHide = false; } else @@ -813,18 +810,17 @@ void MainWindow::on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int infoWidget->ShowDetails(GetItemWidget(item)->Identifier()); } -void MainWindow::onConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, - const quint64 totalDown) +void MainWindow::OnStatsAvailable(const ConnectionId &id, const quint64 upS, const quint64 downS, const quint64 upD, const quint64 downD) { Q_UNUSED(id); - // This may not be, or may not precisely be, speed per second if low-level + // This may not be, or may not precisely be, speed per second if the backend // has "any" latency. (Hope not...) - speedChartWidget->AddPointData(upSpeed, downSpeed); + speedChartWidget->AddPointData(upS, downS); // - auto totalSpeedUp = FormatBytes(upSpeed) + "/s"; - auto totalSpeedDown = FormatBytes(downSpeed) + "/s"; - auto totalDataUp = FormatBytes(totalUp); - auto totalDataDown = FormatBytes(totalDown); + auto totalSpeedUp = FormatBytes(upS) + "/s"; + auto totalSpeedDown = FormatBytes(downS) + "/s"; + auto totalDataUp = FormatBytes(upD); + auto totalDataDown = FormatBytes(downD); // netspeedLabel->setText(totalSpeedUp + NEWLINE + totalSpeedDown); dataamountLabel->setText(totalDataUp + NEWLINE + totalDataDown); @@ -833,7 +829,7 @@ void MainWindow::onConnectionStatsArrived(const ConnectionId &id, const quint64 " Down: " + totalSpeedDown); } -void MainWindow::onVCoreLogArrived(const ConnectionId &id, const QString &log) +void MainWindow::OnVCoreLogAvailable(const ConnectionId &id, const QString &log) { Q_UNUSED(id); auto bar = masterLogBrowser->verticalScrollBar(); @@ -853,11 +849,10 @@ void MainWindow::onVCoreLogArrived(const ConnectionId &id, const QString &log) cursor.select(QTextCursor::BlockUnderCursor); cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); cursor.removeSelectedText(); + continue; } - else - { - break; - } + + break; } if (val >= max * 0.8 || val >= max - 20) @@ -891,19 +886,7 @@ void MainWindow::OnEditRequested(const ConnectionId &id) if (isChanged) { - // if (CheckConfigType(firstSelected, SUBSCRIPTION)) { - // auto name = connections[_identifier].connectionName; - // // Assume name will not change. - // SaveSubscriptionConfig(root, - // connections[_identifier].subscriptionName, &name); - //} else { - // connections[_identifier].config = root; - // // true indicates the alias will NOT change - // SaveConnectionConfig(root, &alias, true); - //} ConnectionManager->UpdateConnection(id, root); - // OnConfigListChanged(alias == - // CurrentConnectionIdentifier.connectionName); } } void MainWindow::OnJsonEditRequested(const ConnectionId &id) @@ -916,3 +899,32 @@ void MainWindow::OnJsonEditRequested(const ConnectionId &id) ConnectionManager->UpdateConnection(id, root); } } + +void MainWindow::OnConnectionCreated(const ConnectionId &id, const QString &displayName) +{ + Q_UNUSED(displayName) + MWAddConnectionItem_p(id, ConnectionManager->GetConnectionGroupId(id)); +} +void MainWindow::OnConnectionDeleted(const ConnectionId &id, const GroupId &groupId) +{ + auto &child = connectionNodes[id]; + groupNodes[groupId]->removeChild(child.get()); + connectionNodes.remove(id); +} +void MainWindow::OnConnectionGroupChanged(const ConnectionId &id, const GroupId &originalGroup, const GroupId &newGroup) +{ + delete GetItemWidget(connectionNodes[id].get()); + groupNodes[originalGroup]->removeChild(connectionNodes[id].get()); + connectionNodes.remove(id); + MWAddConnectionItem_p(id, newGroup); +} +void MainWindow::OnGroupCreated(const GroupId &id, const QString &displayName) +{ + Q_UNUSED(displayName) + MWAddGroupItem_p(id); +} +void MainWindow::OnGroupDeleted(const GroupId &id, const QList &connections) +{ + for (auto conn : connections) { groupNodes[id]->removeChild(connectionNodes[conn].get()); } + groupNodes.remove(id); +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 2f45ed43..839bbb20 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -58,20 +58,23 @@ class MainWindow void closeEvent(QCloseEvent *) override; private slots: - // - void ReloadConnectionList(); - // - void OnConnected(const ConnectionId &id); - void OnDisConnected(const ConnectionId &id); void OnEditRequested(const ConnectionId &id); void OnJsonEditRequested(const ConnectionId &id); - - void onConnectionWidgetFocusRequested(const ConnectionItemWidget *widget); - // void onConnectionConnected(const ConnectionId &id); - // void onConnectionDisConnected(const ConnectionId &id); - void onConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, - const quint64 totalDown); - void onVCoreLogArrived(const ConnectionId &id, const QString &log); + // + void OnConnectionWidgetFocusRequested(const ConnectionItemWidget *widget); + // + void OnConnected(const ConnectionId &id); + void OnDisconnected(const ConnectionId &id); + // + void OnStatsAvailable(const ConnectionId &id, const quint64 upS, const quint64 downS, const quint64 upD, const quint64 downD); + void OnVCoreLogAvailable(const ConnectionId &id, const QString &log); + // + void OnConnectionCreated(const ConnectionId &id, const QString &displayName); + void OnConnectionDeleted(const ConnectionId &id, const GroupId &groupId); + void OnConnectionGroupChanged(const ConnectionId &id, const GroupId &originalGroup, const GroupId &newGroup); + // + void OnGroupCreated(const GroupId &id, const QString &displayName); + void OnGroupDeleted(const GroupId &id, const QList &connections); // void on_action_StartThis_triggered(); void on_action_RCM_EditJson_triggered(); @@ -82,6 +85,9 @@ class MainWindow void on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column); private: + QHash> groupNodes; + QHash> connectionNodes; + // QTreeWidgetItem *CurrentItem; // Charts SpeedWidget *speedChartWidget; @@ -110,9 +116,13 @@ class MainWindow QAction *action_Tray_SetSystemProxy; QAction *action_Tray_ClearSystemProxy; // - // ----------------------------------- Extra Headers For w_MainWindow_extra.cpp Handling V2ray Connectivities. + // Extra Headers For w_MainWindow_extra.cpp Handling V2ray Connectivities. bool systemProxyEnabled; + ConnectionId lastConnectedId; void MWSetSystemProxy(); void MWClearSystemProxy(bool); void CheckSubscriptionsUpdate(); + // + void MWAddConnectionItem_p(const ConnectionId &connection, const GroupId &groupId); + void MWAddGroupItem_p(const GroupId &groupId); }; diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 60627a2c..ac22eb84 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -20,7 +20,7 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) shareLinkTxt->installEventFilter(this); // connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &ConnectionInfoWidget::OnConnected); - connect(ConnectionManager, &QvConnectionHandler::OnDisConnected, this, &ConnectionInfoWidget::OnDisConnected); + connect(ConnectionManager, &QvConnectionHandler::OnDisconnected, this, &ConnectionInfoWidget::OnDisConnected); } void ConnectionInfoWidget::ShowDetails(const tuple &_identifier) @@ -50,6 +50,7 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden conf.border = true; conf.imageSize = QSize(400, 400); auto img = QZXing().encodeData(shareLink, conf); + qrLabel->setScaledContents(true); qrLabel->setPixmap(QPixmap::fromImage(img)); // connectBtn->setIcon(ConnectionManager->IsConnected(connectionId) ? QICON_R("stop.png") : QICON_R("connect.png")); diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index e5976bc5..80eef415 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -6,7 +6,7 @@ 0 0 - 378 + 403 215 @@ -197,6 +197,9 @@ + + 9 + 6 diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index f4617108..f335988c 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -6,7 +6,7 @@ ConnectionItemWidget::ConnectionItemWidget(QWidget *parent) : QWidget(parent), c { setupUi(this); connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &ConnectionItemWidget::OnConnected); - connect(ConnectionManager, &QvConnectionHandler::OnDisConnected, this, &ConnectionItemWidget::OnDisConnected); + connect(ConnectionManager, &QvConnectionHandler::OnDisconnected, this, &ConnectionItemWidget::OnDisConnected); connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &ConnectionItemWidget::OnConnectionStatsArrived); connect(ConnectionManager, &QvConnectionHandler::OnLatencyTestStarted, this, &ConnectionItemWidget::OnLatencyTestStart); connect(ConnectionManager, &QvConnectionHandler::OnLatencyTestFinished, this, &ConnectionItemWidget::OnLatencyTestFinished); @@ -48,14 +48,19 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : groupId = id; itemType = GROUP_HEADER_ITEM; originalConnectionName = ConnectionManager->GetDisplayName(id); - auto connectionCount = ConnectionManager->Connections(id).count(); connNameLabel->setText(originalConnectionName); - latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections"))); + RecalculateConnectionsCount(); // layout()->removeWidget(connTypeLabel); layout()->removeWidget(dataLabel); delete connTypeLabel; delete dataLabel; + // + connect(ConnectionManager, &QvConnectionHandler::OnConnectionCreated, this, &ConnectionItemWidget::RecalculateConnectionsCount); + connect(ConnectionManager, &QvConnectionHandler::OnConnectionDeleted, this, &ConnectionItemWidget::RecalculateConnectionsCount); + connect(ConnectionManager, &QvConnectionHandler::OnConnectionChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); + connect(ConnectionManager, &QvConnectionHandler::OnConnectionGroupChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); + connect(ConnectionManager, &QvConnectionHandler::OnSubscriptionUpdateFinished, this, &ConnectionItemWidget::RecalculateConnectionsCount); } void ConnectionItemWidget::BeginConnection() diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index 7fc1eda6..067fb111 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -54,6 +54,11 @@ class ConnectionItemWidget void OnDisConnected(const ConnectionId &id); void OnLatencyTestStart(const ConnectionId &id); void OnLatencyTestFinished(const ConnectionId &id, const uint average); + void RecalculateConnectionsCount() + { + auto connectionCount = ConnectionManager->Connections(groupId).count(); + latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections"))); + } private: QString originalConnectionName; From c7a6bca26fa2a8ac1384074b42426cd29d423482 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 29 Feb 2020 23:20:55 +0800 Subject: [PATCH 068/332] add: added ConnectionRename, GroupRename UI slot implementations --- makespec/BUILDVERSION | 2 +- src/core/handler/ConnectionHandler.cpp | 1 + src/ui/widgets/ConnectionInfoWidget.ui | 3 +++ src/ui/widgets/ConnectionItemWidget.cpp | 13 +++++++++++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 5045e5c2..7223c3c3 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4171 +4177 diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index b9e22857..c298a918 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -482,6 +482,7 @@ namespace Qv2ray::core::handlers { return tr("Group does not exist"); } + OnGroupRenamed(id, groups[id].displayName, newName); groups[id].displayName = newName; return {}; } diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index 80eef415..d2cfdc57 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -187,6 +187,9 @@ :/assets/icons/qv2ray.ico + + true + Qt::AlignCenter diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index f335988c..f54cc635 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -40,6 +40,12 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare { emit RequestWidgetFocus(this); } + connect(ConnectionManager, &QvConnectionHandler::OnConnectionRenamed, [&](const ConnectionId &id, const QString &, const QString &newName) { + if (id == connectionId) + { + connNameLabel->setText(newName); + } + }); } // ======================================= Initialisation for root nodes. @@ -61,6 +67,13 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : connect(ConnectionManager, &QvConnectionHandler::OnConnectionChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConnectionHandler::OnConnectionGroupChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConnectionHandler::OnSubscriptionUpdateFinished, this, &ConnectionItemWidget::RecalculateConnectionsCount); + // + connect(ConnectionManager, &QvConnectionHandler::OnGroupRenamed, [&](const GroupId &id, const QString &, const QString &newName) { + if (id == groupId) + { + connNameLabel->setText(newName); + } + }); } void ConnectionItemWidget::BeginConnection() From cf25d760c76b1e63d3d097eb49856d432285febd Mon Sep 17 00:00:00 2001 From: ymshenyu <39402395+ymshenyu@users.noreply.github.com> Date: Sun, 1 Mar 2020 00:09:25 +0800 Subject: [PATCH 069/332] Re-enable grpc support for mac (#386) by @ymshenyu * re-enable grpc support for mac * update -1 * update -2 * update -3 * update -4 * update build version * DONE --- .github/workflows/build-qv2ray.yml | 4 +++- makespec/04-unix-macOS.pri | 15 ++++++++++----- makespec/BUILDVERSION | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-qv2ray.yml b/.github/workflows/build-qv2ray.yml index 1566b544..35faa415 100644 --- a/.github/workflows/build-qv2ray.yml +++ b/.github/workflows/build-qv2ray.yml @@ -60,7 +60,9 @@ jobs: - name: macOS - Install Packages if: matrix.platform == 'macos-latest' - run: brew install protobuf + run: | + brew install protobuf + brew install grpc - name: Windows - Install Packages if: matrix.platform == 'windows-latest' diff --git a/makespec/04-unix-macOS.pri b/makespec/04-unix-macOS.pri index 5cdb9fe4..6c6f0032 100644 --- a/makespec/04-unix-macOS.pri +++ b/makespec/04-unix-macOS.pri @@ -3,9 +3,14 @@ message(" ") # For Linux and macOS message("Configuring for macOS specific environment") LIBS += -framework Carbon -framework Cocoa - -use_grpc: error("The use of gRPC backend is not supported on macOS platform.") - -message(" --> Linking libqvb static library and Security framework, for macOS platform.") -LIBS += -L$$PWD/../libs/ -lqvb-darwin +message(" --> Linking Security framework, for macOS platform.") LIBS += -framework Security + +use_grpc { + # For gRPC and protobuf in macOS + message(" --> Linking against gRPC library.") + LIBS += -L/usr/local/lib -lgrpc++ -lgrpc -lgpr -lupb +} else { + message(" --> Linking libqvb static library, for macOS platform.") + LIBS += -L$$PWD/../libs/ -lqvb-darwin +} diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 9bb70db0..30ee12d5 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -3862 +3867 From 7a183ece8d2b6772caa9461aa23f438ccc328209 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 1 Mar 2020 00:12:23 +0800 Subject: [PATCH 070/332] add: added CreateConnection, ImportConnection, RouteEditor-outbound-type-deduce, ImportFromSubscription --- makespec/BUILDVERSION | 2 +- src/common/QvHelpers.cpp | 5 + src/core/connection/ConnectionIO.cpp | 147 ++++--------------------- src/core/handler/ConnectionHandler.cpp | 57 +++++++--- src/core/handler/ConnectionHandler.hpp | 9 +- src/ui/editors/w_RoutesEditor.cpp | 1 - src/ui/w_ImportConfig.cpp | 32 +++--- src/ui/w_MainWindow.cpp | 41 ++++--- src/ui/w_SubscriptionManager.cpp | 9 +- src/ui/w_SubscriptionManager.hpp | 3 + 10 files changed, 124 insertions(+), 182 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 7223c3c3..26de2ed8 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4177 +4197 diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index e7766bf2..38cdc08d 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -40,6 +40,11 @@ namespace Qv2ray::common } bool StringToFile(const QString &text, QFile &targetFile) { + QFileInfo info(targetFile); + if (!info.dir().exists()) + { + info.dir().mkpath(info.dir().path()); + } bool override = targetFile.exists(); targetFile.open(QFile::WriteOnly); QTextStream stream(&targetFile); diff --git a/src/core/connection/ConnectionIO.cpp b/src/core/connection/ConnectionIO.cpp index 4c4b528a..b666b488 100644 --- a/src/core/connection/ConnectionIO.cpp +++ b/src/core/connection/ConnectionIO.cpp @@ -6,127 +6,28 @@ namespace Qv2ray::core::connection { namespace ConnectionIO { - //// - //// Save Connection to a place, with checking if there's existing file. - //// If so, append "_N" to the name. - // bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool - // canOverrideExisting) - //{ - // auto str = JsonToString(obj); - // auto fullPath = QV2RAY_CONFIG_DIR + *alias + - // QV2RAY_CONFIG_FILE_EXTENSION; - // - // // If there's already a file AND we CANNOT override existing file. - // if (QFile::exists(fullPath) && !canOverrideExisting) { - // // Alias is a pointer to a QString. - // DeducePossibleFileName(QV2RAY_CONFIG_DIR, alias, - // QV2RAY_CONFIG_FILE_EXTENSION); fullPath = QV2RAY_CONFIG_DIR + - // *alias + QV2RAY_CONFIG_FILE_EXTENSION; - // } - // - // LOG(MODULE_SETTINGS, "Saving a config named: " + *alias) - // QFile config(fullPath); - // return StringToFile(&str, &config); - //} - // - // bool SaveSubscriptionConfig(CONFIGROOT obj, const QString - // &subscription, QString *name) - //{ - // auto str = JsonToString(obj); - // auto fName = *name; - // - // if (!IsValidFileName(fName)) { - // fName = RemoveInvalidFileName(fName); - // } - // - // QFile config(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + fName - // + QV2RAY_CONFIG_FILE_EXTENSION); - // - // // If there's already a file. THIS IS EXTREMELY RARE - // if (config.exists()) { - // LOG(MODULE_FILEIO, "Trying to overrwrite an existing - // subscription config file. THIS IS RARE") - // } - // - // LOG(MODULE_SETTINGS, "Saving a subscription named: " + fName) - // bool result = StringToFile(&str, &config); - // - // if (!result) { - // LOG(MODULE_FILEIO, "Failed to save a connection config from - // subscription: " + subscription + ", name: " + fName) - // } - // - // *name = fName; - // return result; - //} - // - // bool RemoveConnection(const QString &alias) - //{ - // QFile config(QV2RAY_CONFIG_DIR + alias + - // QV2RAY_CONFIG_FILE_EXTENSION); - // - // if (!config.exists()) { - // LOG(MODULE_FILEIO, "Trying to remove a non-existing file?") - // return false; - // } else { - // return config.remove(); - // } - //} - // - // bool RemoveSubscriptionConnection(const QString &subsName, const - // QString &name) - //{ - // QFile config(QV2RAY_SUBSCRIPTION_DIR + subsName + "/" + name + - // QV2RAY_CONFIG_FILE_EXTENSION); - // - // if (!config.exists()) { - // LOG(MODULE_FILEIO, "Trying to remove a non-existing file?") - // return false; - // } else { - // return config.remove(); - // } - //} - // - // bool RenameConnection(const QString &originalName, const QString - // &newName) - //{ - // LOG(MODULE_CONNECTION, "[RENAME] --> ORIGINAL: " + originalName + - // ", NEW: " + newName) return QFile::rename(QV2RAY_CONFIG_DIR + - // originalName + QV2RAY_CONFIG_FILE_EXTENSION, QV2RAY_CONFIG_DIR + - // newName + QV2RAY_CONFIG_FILE_EXTENSION); - //} - // - // bool RenameSubscription(const QString &originalName, const QString - // &newName) - //{ - // LOG(MODULE_SUBSCRIPTION, "[RENAME] --> ORIGINAL: " + originalName - // + ", NEW: " + newName) return - // QDir().rename(QV2RAY_SUBSCRIPTION_DIR + originalName, - // QV2RAY_SUBSCRIPTION_DIR + newName); - //} - // - // CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool - // importComplex) - //{ - // QFile source(sourceFilePath); - // - // if (!source.exists()) { - // LOG(MODULE_FILEIO, "Trying to import from an non-existing - // file.") return CONFIGROOT(); - // } - // - // auto root = CONFIGROOT(JsonFromString(StringFromFile(&source))); - // - // if (!importComplex) { - // JSON_ROOT_TRY_REMOVE("inbounds") - // JSON_ROOT_TRY_REMOVE("routing") - // } - // - // JSON_ROOT_TRY_REMOVE("log") - // JSON_ROOT_TRY_REMOVE("api") - // JSON_ROOT_TRY_REMOVE("stats") - // JSON_ROOT_TRY_REMOVE("dns") - // return root; - //} - } + CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool importComplex) + { + QFile source(sourceFilePath); + + if (!source.exists()) + { + LOG(MODULE_FILEIO, "Trying to import from an non-existing file.") return CONFIGROOT(); + } + + auto root = CONFIGROOT(JsonFromString(StringFromFile(&source))); + + if (!importComplex) + { + JSON_ROOT_TRY_REMOVE("inbounds") + JSON_ROOT_TRY_REMOVE("routing") + } + + JSON_ROOT_TRY_REMOVE("log") + JSON_ROOT_TRY_REMOVE("api") + JSON_ROOT_TRY_REMOVE("stats") + JSON_ROOT_TRY_REMOVE("dns") + return root; + } + } // namespace ConnectionIO } // namespace Qv2ray::core::connection diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index c298a918..d8fde426 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -188,7 +188,18 @@ namespace Qv2ray::core::handlers return NullConnectionId; } + const ConnectionId QvConnectionHandler::GetConnectionIdByDisplayName(const QString &displayName, const GroupId &group) const + { + for (auto conn : groups[group].connections) + { + if (connections[conn].displayName == displayName) + { + return conn; + } + } + return NullConnectionId; + } const GroupId QvConnectionHandler::GetGroupIdByDisplayName(const QString &displayName) const { for (auto group : groups.keys()) @@ -221,30 +232,37 @@ namespace Qv2ray::core::handlers return connections[id].latency; } - + const optional QvConnectionHandler::RenameConnection(const ConnectionId &id, const QString &newName) + { + if (!connections.contains(id)) + { + return tr("Connection doesn't exist"); + } + OnConnectionRenamed(id, connections[id].displayName, newName); + connections[id].displayName = newName; + return {}; + } const optional QvConnectionHandler::DeleteConnection(const ConnectionId &id) { - // auto groupId = connections[id].groupId; QFile connectionFile((groups[groupId].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR) + groupId.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION); // + connections.remove(id); + groups[groupId].connections.removeAll(id); + emit OnConnectionDeleted(id, groupId); + // bool exists = connectionFile.exists(); if (exists) { bool removed = connectionFile.remove(); if (removed) { - connections.remove(id); - groups[groupId].connections.removeAll(id); - emit OnConnectionDeleted(id, groupId); return {}; } - else - return "Failed to remove file"; + return "Failed to remove file"; } - else - return tr("File does not exist."); + return tr("File does not exist."); } const optional QvConnectionHandler::MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId) @@ -601,13 +619,7 @@ namespace Qv2ray::core::handlers { // New connection id is required since nothing matched found... LOG(MODULE_CORE_HANDLER, "Generated new connection id for connection: " + _alias) - ConnectionId newId(GenerateUuid()); - groups[id].connections << newId; - connections[newId].groupId = id; - connections[newId].importDate = system_clock::to_time_t(system_clock::now()); - connections[newId].displayName = _alias; - UpdateConnection(newId, config); - emit OnConnectionCreated(newId, _alias); + CreateConnection(_alias, id, config); } // End guessing connectionId } @@ -623,4 +635,17 @@ namespace Qv2ray::core::handlers return hasErrorOccured; } + const ConnectionId QvConnectionHandler::CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root) + { + LOG(MODULE_CORE_HANDLER, "Creating new connection: " + displayName) + ConnectionId newId(GenerateUuid()); + groups[groupId].connections << newId; + connections[newId].groupId = groupId; + connections[newId].importDate = system_clock::to_time_t(system_clock::now()); + connections[newId].displayName = displayName; + UpdateConnection(newId, root); + emit OnConnectionCreated(newId, displayName); + return newId; + } + } // namespace Qv2ray::core::handlers diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index e181ad62..e55c6071 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -18,6 +18,8 @@ namespace Qv2ray::core::handlers public: explicit QvConnectionHandler(); ~QvConnectionHandler(); + + public: // const QList Connections() const; // @@ -30,6 +32,7 @@ namespace Qv2ray::core::handlers const QString GetDisplayName(const ConnectionId &id, int limit = -1) const; const GroupId GetGroupIdByDisplayName(const QString &displayName) const; const ConnectionId GetConnectionIdByDisplayName(const QString &displayName) const; + const ConnectionId GetConnectionIdByDisplayName(const QString &displayName, const GroupId &group) const; // // Connectivity Operationss const optional StartConnection(const ConnectionId &identifier); @@ -42,8 +45,8 @@ namespace Qv2ray::core::handlers const optional DeleteConnection(const ConnectionId &id); const optional RenameConnection(const ConnectionId &id, const QString &newName); const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); - const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); - const ConnectionId DuplicateConnection(const ConnectionId &id); + const ConnectionId CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); + // const ConnectionId DuplicateConnection(const ConnectionId &id); // // Get Conncetion Property const tuple GetConnectionData(const ConnectionId &connectionId) const; @@ -68,7 +71,7 @@ namespace Qv2ray::core::handlers // Subscriptions bool SetSubscriptionData(const GroupId &id, const QString &address = "", float updateInterval = -1); bool UpdateSubscription(const GroupId &id, bool useSystemProxy); - bool UpdateSubscriptionASync(const GroupId &id, bool useSystemProxy); + // bool UpdateSubscriptionASync(const GroupId &id, bool useSystemProxy); const tuple GetSubscriptionData(const GroupId &id); signals: diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index 15fb5445..00581303 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -177,7 +177,6 @@ void RouteEditor::onNodeClicked(Node &n) { alias = GetFirstNodeData(n, QvOutboundNodeModel, OutboundNodeData)->GetOutbound(); QJsonObject _root = outbounds[alias].raw(); - throw new runtime_error("Not implemented"); GetOutboundData(OUTBOUND(_root), &host, &port, &protocol); } else diff --git a/src/ui/w_ImportConfig.cpp b/src/ui/w_ImportConfig.cpp index 29920030..3c04d049 100644 --- a/src/ui/w_ImportConfig.cpp +++ b/src/ui/w_ImportConfig.cpp @@ -1,5 +1,4 @@ -#include -#include "w_ImportConfig.hpp" +#include "w_ImportConfig.hpp" #include "3rdparty/qzxing/src/QZXing.h" #include "core/CoreUtils.hpp" @@ -12,6 +11,7 @@ #include "ui/w_SubscriptionManager.hpp" #include "w_ScreenShot_Core.hpp" +#include #include #include #include @@ -108,20 +108,20 @@ void ImportConfigWindow::on_beginImportBtn_clicked() { case 0: { - //// From File... - // bool ImportAsComplex = keepImportedInboundCheckBox->isChecked(); - // QString path = fileLineTxt->text(); - // - // if (!V2rayKernelInstance::ValidateConfig(path)) { - // QvMessageBoxWarn(this, tr("Import config file"), tr("Failed to - // check the validity of the config file.")); return; - //} - // - // aliasPrefix += "_" + QFileInfo(path).fileName(); - ////CONFIGROOT config = ConvertConfigFromFile(path, - /// ImportAsComplex); - // connections[aliasPrefix] = config; - // break; + // From File... + bool ImportAsComplex = keepImportedInboundCheckBox->isChecked(); + QString path = fileLineTxt->text(); + + if (!V2rayKernelInstance::ValidateConfig(path)) + { + QvMessageBoxWarn(this, tr("Import config file"), tr("Failed to check the validity of the config file.")); + return; + } + + aliasPrefix += "_" + QFileInfo(path).fileName(); + CONFIGROOT config = ConvertConfigFromFile(path, ImportAsComplex); + connections[aliasPrefix] = config; + break; } case 1: diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 51f9aab8..69863337 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -576,23 +576,20 @@ void MainWindow::on_removeConfigButton_clicked() void MainWindow::on_importConfigButton_clicked() { - QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - // ImportConfigWindow w(this); - // auto configs = w.OpenImport(); - // if (!configs.isEmpty()) { - // for (auto conf : configs) { - // auto name = configs.key(conf, ""); - // - // if (name.isEmpty()) - // continue; - // - // SaveConnectionConfig(conf, &name, false); - // GlobalConfig.configs.push_back(name); - // } - // - // SaveGlobalConfig(GlobalConfig); - // OnConfigListChanged(false); - //} + + ImportConfigWindow w(this); + auto configs = w.OpenImport(); + if (!configs.isEmpty()) + { + for (auto conf : configs) + { + auto name = configs.key(conf, ""); + + if (name.isEmpty()) + continue; + ConnectionManager->CreateConnection(name, DefaultGroupId, conf); + } + } } void MainWindow::on_editConfigButton_clicked() { @@ -601,9 +598,10 @@ void MainWindow::on_editConfigButton_clicked() void MainWindow::on_action_RCM_ConvToComplex_triggered() { //// Check if we have a connection selected... - // if (!IsSelectionConnectable) { - // QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a - // Config")); return; + // if (!IsSelectionConnectable) + //{ + // QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a Config")); + // return; //} // // auto selectedFirst = connectionListWidget->currentItem(); @@ -620,7 +618,8 @@ void MainWindow::on_action_RCM_ConvToComplex_triggered() // isChanged = routeWindow.result() == QDialog::Accepted; // QString alias = _identifier.connectionName; // - // if (isChanged) { + // if (isChanged) + //{ // connections[_identifier].config = root; // // true indicates the alias will NOT change // SaveConnectionConfig(root, &alias, true); diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 9c0c36fe..a8c616c3 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -29,7 +29,8 @@ QvMessageBusSlotImpl(SubscribeEditor) QPair SubscribeEditor::GetSelectedConfig() { - return QPair(); + return QPair(ConnectionManager->GetDisplayName(currentConnectionId), + ConnectionManager->GetConnectionRoot(currentConnectionId)); } SubscribeEditor::~SubscribeEditor() @@ -138,3 +139,9 @@ void SubscribeEditor::on_updateIntervalSB_valueChanged(double arg1) auto newAddress = subAddrTxt->text().trimmed(); ConnectionManager->SetSubscriptionData(currentSubId, newAddress, arg1); } + +void SubscribeEditor::on_connectionsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous) +{ + Q_UNUSED(previous) + currentConnectionId = ConnectionManager->GetConnectionIdByDisplayName(current->text(), currentSubId); +} diff --git a/src/ui/w_SubscriptionManager.hpp b/src/ui/w_SubscriptionManager.hpp index 66d31783..c1003d0b 100644 --- a/src/ui/w_SubscriptionManager.hpp +++ b/src/ui/w_SubscriptionManager.hpp @@ -42,7 +42,10 @@ class SubscribeEditor void on_updateIntervalSB_valueChanged(double arg1); + void on_connectionsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous); + private: bool isUpdateInProgress = false; GroupId currentSubId = NullGroupId; + ConnectionId currentConnectionId = NullConnectionId; }; From 56f0886afd915bacdbc1579712ccdbd7deef8a37 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 1 Mar 2020 10:05:59 +0800 Subject: [PATCH 071/332] add: added support when importing with duplicated name, added ConnectionDuplicate --- makespec/BUILDVERSION | 2 +- src/core/connection/Serialization.cpp | 5 ++++ src/core/connection/Serialization.hpp | 1 + src/core/handler/ConnectionHandler.hpp | 1 - src/ui/w_ImportConfig.cpp | 16 +++++------ src/ui/w_ImportConfig.hpp | 4 +-- src/ui/w_SubscriptionManager.cpp | 5 ++-- src/ui/w_SubscriptionManager.hpp | 2 +- src/ui/widgets/ConnectionInfoWidget.cpp | 35 +++++-------------------- src/ui/widgets/ConnectionInfoWidget.ui | 2 +- src/ui/widgets/ConnectionItemWidget.cpp | 19 ++++---------- src/ui/widgets/ConnectionItemWidget.hpp | 25 ++++++++++++++++++ src/ui/widgets/ConnectionItemWidget.ui | 2 +- 13 files changed, 59 insertions(+), 60 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 225f7b3b..b9da2614 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4200 +4211 diff --git a/src/core/connection/Serialization.cpp b/src/core/connection/Serialization.cpp index 900bcc59..2e7bb53d 100644 --- a/src/core/connection/Serialization.cpp +++ b/src/core/connection/Serialization.cpp @@ -33,6 +33,11 @@ namespace Qv2ray::core::connection { auto server = ConnectionManager->GetConnectionRoot(id); auto alias = ConnectionManager->GetDisplayName(id); + return ConvertConfigToString(alias, server, isSip002); + } + + const QString ConvertConfigToString(const QString &alias, const CONFIGROOT &server, bool isSip002) + { OUTBOUND outbound = OUTBOUND(server["outbounds"].toArray().first().toObject()); auto type = outbound["protocol"].toString(); QString sharelink = ""; diff --git a/src/core/connection/Serialization.hpp b/src/core/connection/Serialization.hpp index 99a03c24..12c6705e 100644 --- a/src/core/connection/Serialization.hpp +++ b/src/core/connection/Serialization.hpp @@ -11,6 +11,7 @@ namespace Qv2ray::core::connection // General CONFIGROOT ConvertConfigFromString(const QString &link, QString *alias, QString *errMessage); const QString ConvertConfigToString(const ConnectionId &id, bool isSip002 = false); + const QString ConvertConfigToString(const QString &alias, const CONFIGROOT &server, bool isSip002); // VMess URI Protocol CONFIGROOT ConvertConfigFromVMessString(const QString &vmess, QString *alias, QString *errMessage); diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index e55c6071..5f52d930 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -46,7 +46,6 @@ namespace Qv2ray::core::handlers const optional RenameConnection(const ConnectionId &id, const QString &newName); const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); const ConnectionId CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); - // const ConnectionId DuplicateConnection(const ConnectionId &id); // // Get Conncetion Property const tuple GetConnectionData(const ConnectionId &connectionId) const; diff --git a/src/ui/w_ImportConfig.cpp b/src/ui/w_ImportConfig.cpp index 3c04d049..3154b180 100644 --- a/src/ui/w_ImportConfig.cpp +++ b/src/ui/w_ImportConfig.cpp @@ -39,7 +39,7 @@ ImportConfigWindow::~ImportConfigWindow() { } -QMap ImportConfigWindow::OpenImport(bool partialImport) +QMultiMap ImportConfigWindow::OpenImport(bool partialImport) { // partial import means only import as an outbound, will set keepImported to // false and disable the checkbox @@ -47,7 +47,7 @@ QMap ImportConfigWindow::OpenImport(bool partialImport) keepImportedInboundCheckBox->setEnabled(!partialImport); routeEditBtn->setEnabled(!partialImport); this->exec(); - return this->result() == QDialog::Accepted ? connections : QMap(); + return this->result() == QDialog::Accepted ? connections : QMultiMap(); } void ImportConfigWindow::on_selectFileBtn_clicked() @@ -120,7 +120,7 @@ void ImportConfigWindow::on_beginImportBtn_clicked() aliasPrefix += "_" + QFileInfo(path).fileName(); CONFIGROOT config = ConvertConfigFromFile(path, ImportAsComplex); - connections[aliasPrefix] = config; + connections.insert(aliasPrefix, config); break; } @@ -151,7 +151,7 @@ void ImportConfigWindow::on_beginImportBtn_clicked() } else { - connections[aliasPrefix] = config; + connections.insert(aliasPrefix, config); } } @@ -288,7 +288,7 @@ void ImportConfigWindow::on_connectionEditBtn_clicked() CONFIGROOT root; root.insert("outbounds", outboundsList); // - connections[alias] = root; + connections.insert(alias, root); accept(); } else @@ -312,8 +312,8 @@ void ImportConfigWindow::on_subscriptionButton_clicked() if (importToComplex) { - auto _result = w.GetSelectedConfig(); - connections[_result.first] = _result.second; + auto [alias, conf] = w.GetSelectedConfig(); + connections.insert(alias, conf); } accept(); @@ -328,7 +328,7 @@ void ImportConfigWindow::on_routeEditBtn_clicked() if (isChanged) { - connections[alias] = result; + connections.insert(alias, result); accept(); } else diff --git a/src/ui/w_ImportConfig.hpp b/src/ui/w_ImportConfig.hpp index 09bbbd0c..754d865b 100644 --- a/src/ui/w_ImportConfig.hpp +++ b/src/ui/w_ImportConfig.hpp @@ -17,7 +17,7 @@ class ImportConfigWindow public: explicit ImportConfigWindow(QWidget *parent = nullptr); ~ImportConfigWindow(); - QMap OpenImport(bool outboundsOnly = false); + QMultiMap OpenImport(bool outboundsOnly = false); public slots: QvMessageBusSlotDecl; private slots: @@ -42,6 +42,6 @@ class ImportConfigWindow void on_hideQv2rayCB_stateChanged(int arg1); private: - QMap connections; + QMultiMap connections; QMap linkErrors; }; diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index a8c616c3..983d621b 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -27,10 +27,9 @@ QvMessageBusSlotImpl(SubscribeEditor) } } -QPair SubscribeEditor::GetSelectedConfig() +tuple SubscribeEditor::GetSelectedConfig() { - return QPair(ConnectionManager->GetDisplayName(currentConnectionId), - ConnectionManager->GetConnectionRoot(currentConnectionId)); + return make_tuple(ConnectionManager->GetDisplayName(currentConnectionId), ConnectionManager->GetConnectionRoot(currentConnectionId)); } SubscribeEditor::~SubscribeEditor() diff --git a/src/ui/w_SubscriptionManager.hpp b/src/ui/w_SubscriptionManager.hpp index c1003d0b..986c5db2 100644 --- a/src/ui/w_SubscriptionManager.hpp +++ b/src/ui/w_SubscriptionManager.hpp @@ -16,7 +16,7 @@ class SubscribeEditor public: explicit SubscribeEditor(QWidget *parent = nullptr); ~SubscribeEditor(); - QPair GetSelectedConfig(); + tuple GetSelectedConfig(); public slots: QvMessageBusSlotDecl; diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index ac22eb84..a5d2cd71 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -140,36 +140,15 @@ void ConnectionInfoWidget::OnDisConnected(const ConnectionId &id) connectBtn->setIcon(QICON_R("connect.png")); } } -// MWTryPingConnection(CurrentConnectionIdentifier); + void ConnectionInfoWidget::on_duplicateBtn_clicked() { - // QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - // if (!IsSelectionConnectable) { - // return; - //} - // - // auto selectedFirst = connectionListWidget->currentItem(); - // auto _identifier = ItemConnectionIdentifier(selectedFirst); - // SUBSCRIPTION_CONFIG_MODIFY_ASK(selectedFirst) - // CONFIGROOT conf; - //// Alias may change. - // QString alias = _identifier.connectionName; - // bool isComplex = IsComplexConfig(connections[_identifier].config); - // - // if (connections[_identifier].configType == CONNECTION_REGULAR) { - // conf = ConvertConfigFromFile(QV2RAY_CONFIG_DIR + - // _identifier.connectionName + QV2RAY_CONFIG_FILE_EXTENSION, isComplex); - //} else { - // conf = ConvertConfigFromFile(QV2RAY_SUBSCRIPTION_DIR + - // _identifier.subscriptionName + "/" + _identifier.connectionName + - // QV2RAY_CONFIG_FILE_EXTENSION, isComplex); alias = - // _identifier.subscriptionName + "_" + _identifier.connectionName; - //} - // - // SaveConnectionConfig(conf, &alias, false); - // GlobalConfig.configs.push_back(alias); - // SaveGlobalConfig(GlobalConfig); - // this->OnConfigListChanged(false);} + if (connectionId != NullConnectionId) + { + ConnectionManager->CreateConnection(ConnectionManager->GetDisplayName(connectionId) + tr(" (Copy)"), + ConnectionManager->GetConnectionGroupId(connectionId), + ConnectionManager->GetConnectionRoot(connectionId)); + } } void ConnectionInfoWidget::on_latencyBtn_clicked() diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index d2cfdc57..e8c42fc7 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -111,7 +111,7 @@ - Delete Connection + Duplicate Connection diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index f54cc635..5eaaa4bd 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -18,7 +18,6 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare groupId = ConnectionManager->GetConnectionGroupId(id); originalConnectionName = ConnectionManager->GetDisplayName(id); itemType = NODE_ITEM; - connNameLabel->setText((ConnectionManager->IsConnected(id) ? "• " : "") + originalConnectionName); auto latency = ConnectionManager->GetConnectionLatency(id); if (latency == 0) @@ -40,12 +39,9 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare { emit RequestWidgetFocus(this); } - connect(ConnectionManager, &QvConnectionHandler::OnConnectionRenamed, [&](const ConnectionId &id, const QString &, const QString &newName) { - if (id == connectionId) - { - connNameLabel->setText(newName); - } - }); + OnConnectionItemRenamed(id, "", originalConnectionName); + this->setToolTip(originalConnectionName); + connect(ConnectionManager, &QvConnectionHandler::OnConnectionRenamed, this, &ConnectionItemWidget::OnConnectionItemRenamed); } // ======================================= Initialisation for root nodes. @@ -54,7 +50,6 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : groupId = id; itemType = GROUP_HEADER_ITEM; originalConnectionName = ConnectionManager->GetDisplayName(id); - connNameLabel->setText(originalConnectionName); RecalculateConnectionsCount(); // layout()->removeWidget(connTypeLabel); @@ -62,18 +57,14 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : delete connTypeLabel; delete dataLabel; // + OnGroupItemRenamed(id, "", originalConnectionName); connect(ConnectionManager, &QvConnectionHandler::OnConnectionCreated, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConnectionHandler::OnConnectionDeleted, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConnectionHandler::OnConnectionChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConnectionHandler::OnConnectionGroupChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConnectionHandler::OnSubscriptionUpdateFinished, this, &ConnectionItemWidget::RecalculateConnectionsCount); // - connect(ConnectionManager, &QvConnectionHandler::OnGroupRenamed, [&](const GroupId &id, const QString &, const QString &newName) { - if (id == groupId) - { - connNameLabel->setText(newName); - } - }); + connect(ConnectionManager, &QvConnectionHandler::OnGroupRenamed, this, &ConnectionItemWidget::OnGroupItemRenamed); } void ConnectionItemWidget::BeginConnection() diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index 067fb111..4120d176 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -59,6 +59,31 @@ class ConnectionItemWidget auto connectionCount = ConnectionManager->Connections(groupId).count(); latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections"))); } + void OnConnectionItemRenamed(const ConnectionId &id, const QString &, const QString &newName) + { + if (id == connectionId) + { + if (ConnectionManager->IsConnected(id)) + { + connNameLabel->setText("• " + originalConnectionName); + } + else + { + connNameLabel->setText(newName); + } + originalConnectionName = newName; + this->setToolTip(newName); + } + } + void OnGroupItemRenamed(const GroupId &id, const QString &, const QString &newName) + { + if (id == groupId) + { + originalConnectionName = newName; + connNameLabel->setText(newName); + this->setToolTip(newName); + } + } private: QString originalConnectionName; diff --git a/src/ui/widgets/ConnectionItemWidget.ui b/src/ui/widgets/ConnectionItemWidget.ui index 97d0d5c0..2acc24d4 100644 --- a/src/ui/widgets/ConnectionItemWidget.ui +++ b/src/ui/widgets/ConnectionItemWidget.ui @@ -41,7 +41,7 @@ - 12 + 11 From 46c13543a4e85cb2f42c6abbdf9ef642420e9ba4 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 1 Mar 2020 17:24:58 +0800 Subject: [PATCH 072/332] fix: changed inline code block settings --- _clang-format | 2 +- makespec/BUILDVERSION | 2 +- src/common/QvHelpers.cpp | 5 +++- src/components/pac/QvGFWPACConverter.cpp | 5 +++- src/components/speedchart/speedplotview.cpp | 5 +++- src/core/CoreSafeTypes.hpp | 10 +++++-- src/core/config/ConfigUpgrade.cpp | 5 +++- src/core/connection/Serialization.cpp | 5 +++- src/core/handler/ConnectionHandler.cpp | 29 ++++++++++++++++----- src/main.cpp | 5 +++- src/ui/editors/w_InboundEditor.cpp | 8 ++++-- src/ui/editors/w_RoutesEditor.cpp | 10 +++++-- src/ui/w_ExportConfig.cpp | 1 + src/ui/w_MainWindow.cpp | 5 +++- src/ui/w_PreferencesWindow.cpp | 20 +++++++++++--- src/ui/w_SubscriptionManager.cpp | 4 +-- src/ui/widgets/StreamSettingsWidget.cpp | 4 ++- 17 files changed, 96 insertions(+), 29 deletions(-) diff --git a/_clang-format b/_clang-format index 38833c2c..8586680d 100644 --- a/_clang-format +++ b/_clang-format @@ -5,7 +5,7 @@ AlignAfterOpenBracket: Align AllowAllArgumentsOnNextLine: 'false' AllowAllConstructorInitializersOnNextLine: 'false' AllowAllParametersOfDeclarationOnNextLine: 'false' -AllowShortBlocksOnASingleLine: 'true' +AllowShortBlocksOnASingleLine: 'false' AllowShortCaseLabelsOnASingleLine: 'true' AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: 'false' diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index b9da2614..a6c9dc98 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4211 +4215 diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 38cdc08d..dee61789 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -118,7 +118,10 @@ namespace Qv2ray::common { list list; - for (auto line : _string.split(QRegExp("[\r\n]"), QString::SkipEmptyParts)) { list.push_back(line.toStdString()); } + for (auto line : _string.split(QRegExp("[\r\n]"), QString::SkipEmptyParts)) + { + list.push_back(line.toStdString()); + } return list; } diff --git a/src/components/pac/QvGFWPACConverter.cpp b/src/components/pac/QvGFWPACConverter.cpp index 3148d86f..30e0e9e8 100644 --- a/src/components/pac/QvGFWPACConverter.cpp +++ b/src/components/pac/QvGFWPACConverter.cpp @@ -50,7 +50,10 @@ namespace Qv2ray::components::pac if (originLine[startPosition] == '\n') startPosition += 1; - for (size_t i = startPosition; i < endPosition; ++i) { returnBuffer += originLine[i]; } + for (size_t i = startPosition; i < endPosition; ++i) + { + returnBuffer += originLine[i]; + } } return returnBuffer; diff --git a/src/components/speedchart/speedplotview.cpp b/src/components/speedchart/speedplotview.cpp index 7174fd0e..6a393104 100644 --- a/src/components/speedchart/speedplotview.cpp +++ b/src/components/speedchart/speedplotview.cpp @@ -191,7 +191,10 @@ void SpeedPlotView::pushPoint(const SpeedPlotView::PointData &point) { m_datahalfMin.push_back(point); - while (m_datahalfMin.length() > VIEWABLE) { m_datahalfMin.removeFirst(); } + while (m_datahalfMin.length() > VIEWABLE) + { + m_datahalfMin.removeFirst(); + } } void SpeedPlotView::replot() diff --git a/src/core/CoreSafeTypes.hpp b/src/core/CoreSafeTypes.hpp index 5cfbb859..67360464 100644 --- a/src/core/CoreSafeTypes.hpp +++ b/src/core/CoreSafeTypes.hpp @@ -53,7 +53,10 @@ namespace Qv2ray::core { QList list; - for (auto str : strings) { list << IDType(str); } + for (auto str : strings) + { + list << IDType(str); + } return list; } @@ -63,7 +66,10 @@ namespace Qv2ray::core { QList list; - for (auto id : ids) { list << id.toString(); } + for (auto id : ids) + { + list << id.toString(); + } return list; } diff --git a/src/core/config/ConfigUpgrade.cpp b/src/core/config/ConfigUpgrade.cpp index 043cbe3c..28d09ed3 100644 --- a/src/core/config/ConfigUpgrade.cpp +++ b/src/core/config/ConfigUpgrade.cpp @@ -266,7 +266,10 @@ namespace Qv2ray { LOG(MODULE_SETTINGS, "Migrating config from version " + QSTRN(fromVersion) + " to " + QSTRN(toVersion)) - for (int i = fromVersion; i < toVersion; i++) { root = UpgradeConfig_Inc(i, root); } + for (int i = fromVersion; i < toVersion; i++) + { + root = UpgradeConfig_Inc(i, root); + } return root; } diff --git a/src/core/connection/Serialization.cpp b/src/core/connection/Serialization.cpp index 2e7bb53d..7875498f 100644 --- a/src/core/connection/Serialization.cpp +++ b/src/core/connection/Serialization.cpp @@ -420,7 +420,10 @@ namespace Qv2ray::core::connection else if (net == "http" || net == "h2") { // Fill hosts for HTTP - for (auto _host : host.split(',')) { streaming.httpSettings.host.push_back(_host.trimmed()); } + for (auto _host : host.split(',')) + { + streaming.httpSettings.host.push_back(_host.trimmed()); + } streaming.httpSettings.path = path; } diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index d8fde426..81004e85 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -29,7 +29,10 @@ namespace Qv2ray::core::handlers auto val = GlobalConfig.subscriptions[key]; groups[gkey] = val; - for (auto conn : val.connections) { connections[ConnectionId(conn)].groupId = GroupId(key); } + for (auto conn : val.connections) + { + connections[ConnectionId(conn)].groupId = GroupId(key); + } } for (auto key : GlobalConfig.groups.keys()) @@ -43,7 +46,10 @@ namespace Qv2ray::core::handlers auto val = GlobalConfig.groups[key]; groups[gkey] = val; - for (auto conn : val.connections) { connections[ConnectionId(conn)].groupId = GroupId(key); } + for (auto conn : val.connections) + { + connections[ConnectionId(conn)].groupId = GroupId(key); + } } // @@ -78,7 +84,9 @@ namespace Qv2ray::core::handlers newGlobalConfig.subscriptions.clear(); for (auto i = 0; i < connections.count(); i++) - { newGlobalConfig.connections[connections.keys()[i].toString()] = connections.values()[i]; } + { + newGlobalConfig.connections[connections.keys()[i].toString()] = connections.values()[i]; + } for (auto i = 0; i < groups.count(); i++) { @@ -122,12 +130,18 @@ namespace Qv2ray::core::handlers void QvConnectionHandler::StartLatencyTest() { - for (auto connection : connections.keys()) { StartLatencyTest(connection); } + for (auto connection : connections.keys()) + { + StartLatencyTest(connection); + } } void QvConnectionHandler::StartLatencyTest(const GroupId &id) { - for (auto connection : groups[id].connections) { StartLatencyTest(connection); } + for (auto connection : groups[id].connections) + { + StartLatencyTest(connection); + } } void QvConnectionHandler::StartLatencyTest(const ConnectionId &id) @@ -302,7 +316,10 @@ namespace Qv2ray::core::handlers // Copy construct auto list = groups[id].connections; - for (auto conn : list) { MoveConnectionGroup(conn, DefaultGroupId); } + for (auto conn : list) + { + MoveConnectionGroup(conn, DefaultGroupId); + } // if (groups[id].isSubscription) { diff --git a/src/main.cpp b/src/main.cpp index ae943cce..912c07ca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -361,7 +361,10 @@ int main(int argc, char *argv[]) } else { - for (auto lang : langs) { LOG(MODULE_INIT, "Found Translator: " + lang) } + for (auto lang : langs) + { + LOG(MODULE_INIT, "Found Translator: " + lang) + } } // Qv2ray Initialize, find possible config paths and verify them. diff --git a/src/ui/editors/w_InboundEditor.cpp b/src/ui/editors/w_InboundEditor.cpp index 08d3ab91..7a7957a1 100644 --- a/src/ui/editors/w_InboundEditor.cpp +++ b/src/ui/editors/w_InboundEditor.cpp @@ -144,7 +144,9 @@ void InboundEditor::LoadUIData() httpAccountListBox->clear(); for (auto user : httpSettings["accounts"].toArray()) - { httpAccountListBox->addItem(user.toObject()["user"].toString() + ":" + user.toObject()["pass"].toString()); } + { + httpAccountListBox->addItem(user.toObject()["user"].toString() + ":" + user.toObject()["pass"].toString()); + } // SOCKS socksAuthCombo->setCurrentText(socksSettings["auth"].toString()); @@ -153,7 +155,9 @@ void InboundEditor::LoadUIData() socksUserLevelSB->setValue(socksSettings["userLevel"].toInt()); for (auto user : socksSettings["accounts"].toArray()) - { socksAccountListBox->addItem(user.toObject()["user"].toString() + ":" + user.toObject()["pass"].toString()); } + { + socksAccountListBox->addItem(user.toObject()["user"].toString() + ":" + user.toObject()["pass"].toString()); + } // Dokodemo-Door dokoFollowRedirectCB->setChecked(dokoSettings["followRedirect"].toBool()); diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index 00581303..9a7141fc 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -446,7 +446,10 @@ void RouteEditor::ShowCurrentRuleDetail() balancerSelectionCombo->clear(); // BUG added the wrong items, should be outbound list. - for (auto out : outbounds) { balancerSelectionCombo->addItem((out)["tag"].toString()); } + for (auto out : outbounds) + { + balancerSelectionCombo->addItem((out)["tag"].toString()); + } // // Balancers combo and balancer list. @@ -726,7 +729,10 @@ void RouteEditor::on_addOutboundBtn_clicked() // conf is rootObject, needs to unwrap it. auto confList = conf["outbounds"].toArray(); - for (int i = 0; i < confList.count(); i++) { AddOutbound(OUTBOUND(confList[i].toObject())); } + for (int i = 0; i < confList.count(); i++) + { + AddOutbound(OUTBOUND(confList[i].toObject())); + } } CHECKEMPTYRULES diff --git a/src/ui/w_ExportConfig.cpp b/src/ui/w_ExportConfig.cpp index fa659aba..49704c06 100644 --- a/src/ui/w_ExportConfig.cpp +++ b/src/ui/w_ExportConfig.cpp @@ -1,4 +1,5 @@ #include "w_ExportConfig.hpp" + #include "common/QvHelpers.hpp" #include "core/connection/Serialization.hpp" diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 69863337..e19e9353 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -924,6 +924,9 @@ void MainWindow::OnGroupCreated(const GroupId &id, const QString &displayName) } void MainWindow::OnGroupDeleted(const GroupId &id, const QList &connections) { - for (auto conn : connections) { groupNodes[id]->removeChild(connectionNodes[conn].get()); } + for (auto conn : connections) + { + groupNodes[id]->removeChild(connectionNodes[conn].get()); + } groupNodes.remove(id); } diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index d6a1e537..eca5af3b 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -43,7 +43,10 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), Current languageComboBox->clear(); QDirIterator it(":/translations"); - while (it.hasNext()) { languageComboBox->addItem(it.next().split("/").last().split(".").first()); } + while (it.hasNext()) + { + languageComboBox->addItem(it.next().split("/").last().split(".").first()); + } // Set auto start button state SetAutoStartButtonsState(GetLaunchAtLoginStatus()); @@ -162,11 +165,17 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), Current auto autoStartConnId = ConnectionId(CurrentConfig.autoStartId); auto autoStartGroupId = ConnectionManager->GetConnectionGroupId(autoStartConnId); - for (auto group : ConnectionManager->AllGroups()) { autoStartSubsCombo->addItem(ConnectionManager->GetDisplayName(group)); } + for (auto group : ConnectionManager->AllGroups()) + { + autoStartSubsCombo->addItem(ConnectionManager->GetDisplayName(group)); + } autoStartSubsCombo->setCurrentText(ConnectionManager->GetDisplayName(autoStartGroupId)); - for (auto conn : ConnectionManager->Connections(autoStartGroupId)) { autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(conn)); } + for (auto conn : ConnectionManager->Connections(autoStartGroupId)) + { + autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(conn)); + } autoStartConnCombo->setCurrentText(ConnectionManager->GetDisplayName(autoStartConnId)); @@ -1011,7 +1020,10 @@ void PreferencesWindow::on_autoStartSubsCombo_currentIndexChanged(const QString auto list = ConnectionManager->Connections(groupId); autoStartConnCombo->clear(); - for (auto id : list) { autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(id)); } + for (auto id : list) + { + autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(id)); + } } void PreferencesWindow::on_autoStartConnCombo_currentIndexChanged(const QString &arg1) diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 983d621b..543365d3 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -13,9 +13,7 @@ SubscribeEditor::SubscribeEditor(QWidget *parent) : QDialog(parent) for (auto subs : ConnectionManager->Subscriptions()) { - subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList() // - << ConnectionManager->GetDisplayName(subs) // - << subs.toString())); // + subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList{ ConnectionManager->GetDisplayName(subs), subs.toString() })); // } } diff --git a/src/ui/widgets/StreamSettingsWidget.cpp b/src/ui/widgets/StreamSettingsWidget.cpp index ff47e83f..b342b30c 100644 --- a/src/ui/widgets/StreamSettingsWidget.cpp +++ b/src/ui/widgets/StreamSettingsWidget.cpp @@ -35,7 +35,9 @@ void StreamSettingsWidget::SetStreamObject(StreamSettingsObject sso) QString wsHeaders; for (auto item = stream.wsSettings.headers.begin(); item != stream.wsSettings.headers.end(); item++) - { wsHeaders += item.key() + "|" + item.value() + NEWLINE; } + { + wsHeaders += item.key() + "|" + item.value() + NEWLINE; + } wsHeadersTxt->setPlainText(wsHeaders); // mKCP From 1c7bb289a97b8a33a87f15b5e7246bd4069618f0 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 1 Mar 2020 17:30:41 +0800 Subject: [PATCH 073/332] fix: use c++11 initializer list of QStringList --- makespec/BUILDVERSION | 2 +- src/base/models/QvConfigModel.hpp | 4 +--- src/common/QvHelpers.cpp | 4 +--- src/components/proxy/QvProxyConfigurator.cpp | 2 +- src/core/connection/Generation.cpp | 13 +++++++++---- src/core/connection/Generation.hpp | 1 + src/core/kernel/KernelInteractions.cpp | 7 ++----- src/ui/w_MainWindow.cpp | 4 ++-- src/ui/w_SubscriptionManager.cpp | 6 ++---- 9 files changed, 20 insertions(+), 23 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index a6c9dc98..e1c3d7b5 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4215 +4216 diff --git a/src/base/models/QvConfigModel.hpp b/src/base/models/QvConfigModel.hpp index 521fc4f1..ae545130 100644 --- a/src/base/models/QvConfigModel.hpp +++ b/src/base/models/QvConfigModel.hpp @@ -118,9 +118,7 @@ namespace Qv2ray::base::config bool withLocalDNS; QList dnsList; Qv2rayForwardProxyConfig forwardProxyConfig; - Qv2rayConnectionConfig() - : bypassCN(true), enableProxy(true), withLocalDNS(false), dnsList(QStringList() << "8.8.4.4" - << "1.1.1.1") + Qv2rayConnectionConfig() : bypassCN(true), enableProxy(true), withLocalDNS(false), dnsList(QStringList{ "8.8.4.4", "1.1.1.1" }) { } XTOSTRUCT(O(bypassCN, enableProxy, withLocalDNS, dnsList, forwardProxyConfig)) diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index dee61789..a539ff9e 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -128,9 +128,7 @@ namespace Qv2ray::common QStringList GetFileList(QDir dir) { - return dir.entryList(QStringList() << "*" - << "*.*", - QDir::Hidden | QDir::Files); + return dir.entryList(QStringList{ "*", "*.*" }, QDir::Hidden | QDir::Files); } bool FileExistsIn(QDir dir, QString fileName) diff --git a/src/components/proxy/QvProxyConfigurator.cpp b/src/components/proxy/QvProxyConfigurator.cpp index 59f4a722..4cc274bc 100644 --- a/src/components/proxy/QvProxyConfigurator.cpp +++ b/src/components/proxy/QvProxyConfigurator.cpp @@ -15,7 +15,7 @@ namespace Qv2ray::components::proxy { QProcess p; p.setProgram("/usr/sbin/networksetup"); - p.setArguments(QStringList() << "-listallnetworkservices"); + p.setArguments(QStringList{ "-listallnetworkservices" }); p.start(); p.waitForStarted(); p.waitForFinished(); diff --git a/src/core/connection/Generation.cpp b/src/core/connection/Generation.cpp index acb003fd..f65ff1a2 100644 --- a/src/core/connection/Generation.cpp +++ b/src/core/connection/Generation.cpp @@ -21,15 +21,15 @@ namespace Qv2ray::core::connection { // This is added to disable all proxies, as a alternative // influence of #64 - rulesList.append(GenerateSingleRouteRule(QStringList() << "regexp:.*", true, OUTBOUND_TAG_DIRECT)); + rulesList.append(GenerateSingleRouteRule("regexp:.*", true, OUTBOUND_TAG_DIRECT)); } // Private IPs should always NOT TO PROXY! - rulesList.append(GenerateSingleRouteRule(QStringList() << "geoip:private", false, OUTBOUND_TAG_DIRECT)); + rulesList.append(GenerateSingleRouteRule("geoip:private", false, OUTBOUND_TAG_DIRECT)); // // Check if CN needs proxy, or direct. - rulesList.append(GenerateSingleRouteRule(QStringList() << "geoip:cn", false, proxyCN ? OUTBOUND_TAG_DIRECT : OUTBOUND_TAG_PROXY)); - rulesList.append(GenerateSingleRouteRule(QStringList() << "geosite:cn", true, proxyCN ? OUTBOUND_TAG_DIRECT : OUTBOUND_TAG_PROXY)); + rulesList.append(GenerateSingleRouteRule("geoip:cn", false, proxyCN ? OUTBOUND_TAG_DIRECT : OUTBOUND_TAG_PROXY)); + rulesList.append(GenerateSingleRouteRule("geosite:cn", true, proxyCN ? OUTBOUND_TAG_DIRECT : OUTBOUND_TAG_PROXY)); // // As a bug fix of #64, this default rule has been disabled. // rulesList.append(GenerateSingleRouteRule(QStringList({"regexp:.*"}), @@ -38,6 +38,11 @@ namespace Qv2ray::core::connection RROOT } + ROUTERULE GenerateSingleRouteRule(QString str, bool isDomain, QString outboundTag, QString type) + { + return GenerateSingleRouteRule(QStringList{ str }, isDomain, outboundTag, type); + } + ROUTERULE GenerateSingleRouteRule(QStringList list, bool isDomain, QString outboundTag, QString type) { ROUTERULE root; diff --git a/src/core/connection/Generation.hpp b/src/core/connection/Generation.hpp index 3fc7ebb8..c40b32d3 100644 --- a/src/core/connection/Generation.hpp +++ b/src/core/connection/Generation.hpp @@ -7,6 +7,7 @@ namespace Qv2ray::core::connection // Important config generation algorithms. const QStringList vLogLevels = { "none", "debug", "info", "warning", "error" }; ROUTING GenerateRoutes(bool enableProxy, bool cnProxy); + ROUTERULE GenerateSingleRouteRule(QString str, bool isDomain, QString outboundTag, QString type = "field"); ROUTERULE GenerateSingleRouteRule(QStringList list, bool isDomain, QString outboundTag, QString type = "field"); QJsonObject GenerateDNS(bool withLocalhost, QStringList dnsServers); QJsonObject GenerateAPIEntry(QString tag, bool withHandler = true, bool withLogger = true, bool withStats = true); diff --git a/src/core/kernel/KernelInteractions.cpp b/src/core/kernel/KernelInteractions.cpp index 8337ae0e..10cd59dc 100644 --- a/src/core/kernel/KernelInteractions.cpp +++ b/src/core/kernel/KernelInteractions.cpp @@ -109,10 +109,7 @@ namespace Qv2ray::core::kernel QProcess process; process.setProcessEnvironment(env); DEBUG(MODULE_VCORE, "Starting V2ray core with test options") - process.start(GlobalConfig.v2CorePath, - QStringList() << "-test" - << "-config" << path, - QIODevice::ReadWrite | QIODevice::Text); + process.start(GlobalConfig.v2CorePath, QStringList{ "-test", "-config", path }, QIODevice::ReadWrite | QIODevice::Text); process.waitForFinished(); if (process.exitCode() != 0) @@ -175,7 +172,7 @@ namespace Qv2ray::core::kernel QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert("V2RAY_LOCATION_ASSET", GlobalConfig.v2AssetsPath); vProcess->setProcessEnvironment(env); - vProcess->start(GlobalConfig.v2CorePath, QStringList() << "-config" << filePath, QIODevice::ReadWrite | QIODevice::Text); + vProcess->start(GlobalConfig.v2CorePath, QStringList{ "-config", filePath }, QIODevice::ReadWrite | QIODevice::Text); vProcess->waitForStarted(); DEBUG(MODULE_VCORE, "V2ray core started.") KernelStarted = true; diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index e19e9353..7514961a 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -51,7 +51,7 @@ void MainWindow::MWAddConnectionItem_p(const ConnectionId &connection, const Gro MWAddGroupItem_p(groupId); } auto groupItem = groupNodes[groupId]; - auto connectionItem = make_shared(QStringList() << "" << ConnectionManager->GetDisplayName(connection)); + auto connectionItem = make_shared(QStringList{ "", ConnectionManager->GetDisplayName(connection) }); connectionNodes[connection] = connectionItem; groupItem->addChild(connectionItem.get()); auto widget = new ConnectionItemWidget(connection, connectionListWidget); @@ -61,7 +61,7 @@ void MainWindow::MWAddConnectionItem_p(const ConnectionId &connection, const Gro void MainWindow::MWAddGroupItem_p(const GroupId &groupId) { - auto groupItem = make_shared(QStringList() << "" << ConnectionManager->GetDisplayName(groupId)); + auto groupItem = make_shared(QStringList{ "", ConnectionManager->GetDisplayName(groupId) }); groupNodes[groupId] = groupItem; connectionListWidget->addTopLevelItem(groupItem.get()); connectionListWidget->setItemWidget(groupItem.get(), 0, new ConnectionItemWidget(groupId, connectionListWidget)); diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 543365d3..7606a9ad 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -13,7 +13,7 @@ SubscribeEditor::SubscribeEditor(QWidget *parent) : QDialog(parent) for (auto subs : ConnectionManager->Subscriptions()) { - subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList{ ConnectionManager->GetDisplayName(subs), subs.toString() })); // + subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList{ ConnectionManager->GetDisplayName(subs), subs.toString() })); } } @@ -39,9 +39,7 @@ void SubscribeEditor::on_addSubsButton_clicked() auto const key = QSTRN(QTime::currentTime().msecsSinceStartOfDay()); auto id = ConnectionManager->CreateGroup(key, true); // - subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList() // - << key // - << id.toString())); // + subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList{ key, id.toString() })); } void SubscribeEditor::on_updateButton_clicked() From ab2f2c3e11c8f8e5783d51eb8f0964635644e496 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 1 Mar 2020 17:35:18 +0800 Subject: [PATCH 074/332] fix: use c++11 initializer list of std::tuple<> --- makespec/BUILDVERSION | 2 +- src/core/handler/ConnectionHandler.cpp | 12 ++++++------ src/ui/w_SubscriptionManager.cpp | 2 +- src/ui/widgets/ConnectionItemWidget.hpp | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index e1c3d7b5..dc2f5ce1 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4216 +4217 diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index 81004e85..be64c069 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -411,10 +411,10 @@ namespace Qv2ray::core::handlers { if (!connections.contains(id)) { - return make_tuple(0, 0); + return { 0, 0 }; } - return make_tuple(connections[id].upLinkData, connections[id].downLinkData); + return { connections[id].upLinkData, connections[id].downLinkData }; } QvConnectionHandler::~QvConnectionHandler() @@ -468,14 +468,14 @@ namespace Qv2ray::core::handlers if (GetOutboundData(outBoundRoot, &host, &port, &outboundType)) { *ok = true; - return make_tuple(outboundType, host, port); + return { outboundType, host, port }; } else { LOG(MODULE_CORE_HANDLER, "Unknown outbound type: " + outboundType + ", cannot deduce host and port.") } } - return make_tuple(tr("N/A"), tr("N/A"), 0); + return { tr("N/A"), tr("N/A"), 0 }; } void QvConnectionHandler::OnLatencyDataArrived(const QvTCPingResultObject &result) @@ -531,7 +531,7 @@ namespace Qv2ray::core::handlers return result; } - return make_tuple(groups[id].address, groups[id].lastUpdated, groups[id].updateInterval); + return { groups[id].address, groups[id].lastUpdated, groups[id].updateInterval }; } bool QvConnectionHandler::SetSubscriptionData(const GroupId &id, const QString &address, float updateInterval) @@ -581,7 +581,7 @@ namespace Qv2ray::core::handlers auto [protocol, host, port] = GetConnectionData(conn); if (port != 0) { - typeMap[make_tuple(protocol, host, port)] = conn; + typeMap[{ protocol, host, port }] = conn; } } // diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 7606a9ad..20cc75bc 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -27,7 +27,7 @@ QvMessageBusSlotImpl(SubscribeEditor) tuple SubscribeEditor::GetSelectedConfig() { - return make_tuple(ConnectionManager->GetDisplayName(currentConnectionId), ConnectionManager->GetConnectionRoot(currentConnectionId)); + return { ConnectionManager->GetDisplayName(currentConnectionId), ConnectionManager->GetConnectionRoot(currentConnectionId) }; } SubscribeEditor::~SubscribeEditor() diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index 4120d176..63f061f4 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -39,7 +39,7 @@ class ConnectionItemWidget } inline const tuple Identifier() const { - return make_tuple(groupId, connectionId); + return { groupId, connectionId }; } inline bool IsConnection() const { From c7ef92bbc2a63bac49708d60805008f202a98ec3 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 1 Mar 2020 18:02:08 +0800 Subject: [PATCH 075/332] fix: changed from f2f2f2 to e6e6e6 and ececec in light theme tray icon --- assets/icons/ui_dark/design/tray.svg | 20 ++++++++++---------- assets/icons/ui_dark/tray.png | Bin 1564 -> 1624 bytes makespec/BUILDVERSION | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/assets/icons/ui_dark/design/tray.svg b/assets/icons/ui_dark/design/tray.svg index bd679ad8..d71090af 100644 --- a/assets/icons/ui_dark/design/tray.svg +++ b/assets/icons/ui_dark/design/tray.svg @@ -17,8 +17,8 @@ version="1.1" id="svg8" inkscape:version="0.92.4 5da689c313, 2019-01-14" - sodipodi:docname="Qv2ray_System_Tray_Light.svg" - inkscape:export-filename="/home/axionl/Desktop/Qv2ray_Design/qv2ray.png" + sodipodi:docname="tray.svg" + inkscape:export-filename="" inkscape:export-xdpi="558.54999" inkscape:export-ydpi="558.54999"> ~H99LGP~Y~)8HPJ0|lk`^^|eqMe=TSdQ+Z}~N*(e;BpQpT8UH|IxljD=iQ z`X$VdhZ0Uhn`-%yR3|z=ckIa6%{Zn`Ij+0M_5S1ec)j26Ki+@5->)}M`>l2kh4ID< z@8M75$%l?)7(vGBGYZ8Px`tr~ce?eUYlZ~Ex(@hRv5<6MnU^l1x$Z+~ zV5g3X_8>(&47L?`Hq(4P417Hf{L=NZ3;!U!DsFPgCAPLFn){;IvHdxHq}#SAVeXwm z@JQ9kwF7!z1Y=b@6QZ`SBfLrmg6K*@IZ=}(33)}h>JY~@Zx7XTK11H&y$>=1n(D%U zw_0y72#GUFctM*vQK|j?SeeWgj1(lG(bMa4OYR$5+XJ)Niq`~-C0d}6boz>WjD zZNYUiaCru3FEYWCm?rD&vF;BalWnG&{j(TzumB=)NJpXtj%2oVe@tF32~?DO^VSMw zG8u*Z+!?5%T^o?&DI$cwL6 zl6IZ~)uOf=wscuF`kPg%h%}S;)D>c(VLl+;fBp(<>Uo8163aG>isD;_pqX%|p2^tZ zh6ls-jg5_u3wrr#R}dt@;+}M(3|@`8Q8|jproxURe2yv8d6V!L$lcHgu5nQ)$IW=R zs|qzI;59WhGgEmC3bid2CkX*}+b#t%Vc5G1wE*FBP%c+^2>Clw&dNz(*b)T9L%9M*D0EOswyo%FFBFM* zDUS=z+Di_EiVgIpHra@cVI0;O6e%DHJigTsmCoEJiq6*(W{jc((JLJ`^2UI?{%Y5F z;2?47WhCk>f--+fZrXpevzb)kZMog8g}UF6>=Ad)O#`+r^Fq=(bspw*@c zPO`T6LD(C^@R4H6$m_B5Rx1~};(-M{&Lfve$1r@T7E2<%#z_sQZDHTK$WPQ0A~xgB zUTQmUK-dSKBseC`jUUQrEA2Wt7m(c5j=r z(9%s)4V)^m*%jd6v~y362Jt_5^cqo0_&!huBVsv{V)ym4-oCy}O8A+RpDan4UG?sV z*<(Vsxz~B(Ru=|;<4YJ3@CeVHfNxt>ur ztvmRTYNe{9PQoJo0J;rkse-SFY?@Bvo75<)%9}$K zF?krKr79GENJ`fnDUVdbP^OGJuVU=FTz%?xHzBy=a2j)vD;3AalhKGAKXG`C1BR*X zw>G7&6-4Bmz*KHPnQrcL3w;41^2V%F^2H!R+Hcbaq>|VFQ`)hrzo3Dnb*1tz{Z-*P zFl-ypv2D$++LY@z1Ktv$0?$yaY>wQ^D#?x)DdgP9`Rbi!-g)28AD?+6ozI*kh7Clf6kujej| zTQCkg$%!oO<&1ZGoA^c8V@@#mPB_ys2W?BSDErT345_KsyM#MQ!no)2Ny6=x%l!Ns z6tQH6Ly@eWmNdz+f3Q06F74C#&Z*d=*#qG@zL!@%s0Dr4+DmuOhO@?5NN@PC+GS)?HKe2`ktyZYKS0x!?xLO{bKg*1(0W&#%xr4W5te|?lv zDB65Vj^1JHCsb&3U#&CJ&`b3SC#wncat-5HkUnQSt>BY$xTk8^IF&%o*p%_7Lg_w0 z}R2NmKDU-6I47VbOi+eT-Bf;7G$Ir)YV59m7ifVBT(9$QdCl2Ur4Cl@(-x z>_45?f*`7oYpmymlm${WnO5ueArtH3J3b!bH^k`7*(d}G=G)o}Q0P`)`_g@fwUwhP zh0VeC?;*SSC;H0$Sr5YumAzhJfK>Vu5Lc;CsH*a@b|kVP>z?bUKZZ|%sYYa%Yi!8D69GWO9 zzAc1`%tJlGH9I`RZQh#01Z%T<8bFF>TpLZ4jlC{Iw_nz~tr?du+GgR*ONrH9`U$w_ zeLIegY?r&%Ic!}~SC=WC_)?ZqkG;McS=yDH^qVXERU_oZk@*izTW4GXk=DhkDw9(v zkJY**@WyWY#t>#S5UEl{=&pLHJA)4r6E{yXRb zyVKLt-QcL)wT@ei#*;(7ki6z5T%>n-PW3f8q zjCVr(moj`qpEoon_fo>STr7N4j(#M}heLq!E=e;LK0&5`Qa zZJdihD|-YDACp4Z4WJj%QMaKYT+O94D9c8_M+u=HpO$TbqFCh{#G_kNEd5aOboqoq z^v@vT(8RuFEU%#C!5N#N9}d`Y49-xC-rQ*}UOi-nNf+nsampwuZ_mAEC%kBp4d!I= z=OjV!w}gJ$qzuOR-wWISFw#_&ga53zj@GZlGMy+1;{TY+hXLt)xe1wv<$`_4BwJ#c HCFRE7f(EPi diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index dc2f5ce1..14995ca5 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4217 +4221 From 4db9721784725a4fa804c73063fed11937a7719c Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 1 Mar 2020 22:21:37 +0800 Subject: [PATCH 076/332] add: added ConnectionItemLocate, ConnectionSelection, BoldGroupName --- assets/icons/ui_dark/design/locate.svg | 1 + assets/icons/ui_dark/locate.png | Bin 0 -> 3484 bytes assets/icons/ui_light/design/locate.svg | 1 + assets/icons/ui_light/locate.png | Bin 0 -> 3454 bytes makespec/BUILDVERSION | 2 +- resources.qrc | 2 + src/components/proxy/QvProxyConfigurator.cpp | 2 + src/core/handler/ConnectionHandler.cpp | 10 - src/core/handler/ConnectionHandler.hpp | 15 +- src/ui/w_MainWindow.cpp | 197 ++++++++----------- src/ui/w_MainWindow.hpp | 13 +- src/ui/w_MainWindow.ui | 31 ++- src/ui/w_MainWindow_extra.cpp | 56 +----- src/ui/widgets/ConnectionInfoWidget.cpp | 3 +- src/ui/widgets/ConnectionInfoWidget.ui | 7 +- src/ui/widgets/ConnectionItemWidget.cpp | 5 +- 16 files changed, 148 insertions(+), 197 deletions(-) create mode 100644 assets/icons/ui_dark/design/locate.svg create mode 100644 assets/icons/ui_dark/locate.png create mode 100644 assets/icons/ui_light/design/locate.svg create mode 100644 assets/icons/ui_light/locate.png diff --git a/assets/icons/ui_dark/design/locate.svg b/assets/icons/ui_dark/design/locate.svg new file mode 100644 index 00000000..db6eefaa --- /dev/null +++ b/assets/icons/ui_dark/design/locate.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/ui_dark/locate.png b/assets/icons/ui_dark/locate.png new file mode 100644 index 0000000000000000000000000000000000000000..3f577194bfeae40fbaf857f1449de7bda348e634 GIT binary patch literal 3484 zcmV;N4P)|&P) zd#oKr9mkJUER+gGARwSt1VuzB2nYyTMC1{J7$EV1wkiaaN5L3DL|OupYYNs??&M28d6=>Tp5@D~720~jHqIsjv@8h~X)v=qP)fa?ML0Kg#t zJ{US316rV7uWt#~*QZUAR8^W4$V(G5eVcR;05Ns?qHGtUR` zAb_{D3cQ61u^Pbd0UT+JnI1YH`i>}y_9mj+iYoAoYbAi|nR%zs`O@>)f`7OKg`Re; z0dV`EB6tA6?f~vrEUbu#{te)90FMB84geF;Dy1&swm6Qr3!QIW&x#c*-Us074h!LB zG)MEN5Ygdr9Pd)E*Ei16jG}0xD2jHDqUcLRbduHoPluJ^Tw}}zMdVe_0pJ7xE7~md zhX5Sw)Qf2w%wM9h^hdN(Du`_BuO$8z`bo`a*c>CEV9Xs<9ItFx&Y1jgH|iT z6~>r%7v-@l0k9*0Wi4jv6U;m>D!{d& zJr;p6W*UG89Qp9)&>p=2;EsN4_9cul(~0P>j!N*8&>mF*aEv3d!=e3!AW4#$87<-- zp*^ZFK0dw)5se8?{&+vnjT6ys_6;Dd0z4hsp9%o3lWI9L9~RnQXaJn$=o(K7?JpN` z9Pi^u+zp}ql?4EQ7xHOkk|bM&_SZ4eK!=FN#>dAu3GJ^eL{YRegjLN%bY*CN9l^{8 zIGX-%h4xoA09+(gfYn_&H(-}%4MzPf0$>IJ7V_+((Ei%Oj&4(*{wRt*9ok=6VdfKs zR$x_Eb(utTOW9_*n0Yoc&tv9=XwJ#6b20Nm`!};gcr?bW4V4 zV&(&i^uo-u0W1J8;+Sxet`PtWimnXI{6oRdvqk#o7-s&qP=o(fpoiH+w77#pmtI*H z7gZ7L3}Na6lqAWVB0S^*%`Mnz8F^|E`pmqLh#FdjKdBNln0a9lX#jAu;Ny}a^gAX= zlC7i+Wace=YTM?1NW0)ut|8xxRhaoup%PYo>gI-sz9wYay*_o5B$?ymsdu#oKAU4> z%z8vLo~9kg@ke~=<_5quLZ%((OS8?wzl)jYGxOZZPjREsn8nOF!1ZfdpK`-Mz;(T856 z(U?U>+(4KBs@Ln=YU;S2{!Rva9q7+5suh4d5d4{@ zjtWShZ-3Q;&XABP!`fO755t0oyOeeINYf#rTQqf4K>GeSXlmHmzQX!ohYwdPG+Rr@ zZYfKv01s(tsDbo&KFgFfP7VF^Px2zQ0&3qp?C0UM3h<7pn)M5@fJ5qzh^V2dlQz3bM5{D4R1h-bsRA^XYHGBD zjV`{9Cru4BqnmrxPyy-7nxE0SzhmGvtfkQ|(l|hKK#FD*)2SM7YTaKA;pu!{>;8@k zutZCvT>va8paP^tDSb`r{%Q!{uUYH*tN>FEwpe?`TK882!oo|f z`#V|y)lqjlKz=KktEl0%WmN;f6GCRFECqAS!w+lRzZ0Y}fY$ejD2hHTr1=qz`>O)r z_B6AaQ9Xss7}2_a2Y$S^dPH=Pkmeh;G}HiazR+Bqtf;YEXk}(=X|#%?MOv<<0pLtQ zqkIuW030cpy;)Hsb<~Z5mYh%VBFzLYQPj9c(DN*hDb5%Xqujr%tmjakC|3;iD8S`(mEIFA1R361-EfrzdYOkb>};phemYXzjI zU%C0eNzgb?OG6!LM~iYdAbyJ{qQzP|60SXmTJQfhu$HvJc25lrFBoIigM4DA<|!C}WE5;&v*6-E$}o_9oqTspdPmJu>e#L96uV zCH)^`%m&i-W@bK7Q>)cVV6PDXzeF?i%jYIv02bInA8F-Y+J#@K$l+m#sA`OPm!_6? z9DVe1ZLKydLGH^(;a4h^3V@dc%>~+8-m!&}dKj~h{eqQB=7v$N%gaVkB05>nd!?IB zOnV2mxlKzH`%09ZC`$cmnDbihYx7AIMH@jrSW0acwQyW9g8-c2Q`^3`YgB~gzP~dt z^VyPq*N4+*=3fYjTQM;)v8iu;H23x|K}NKXDc6MkjrTJPnRyGyBmZ-J>wCwZmL+Ar zm;O{DNs>9tJfDab*+J?sfZ?_OX6E@t$KnHUtx))N05gj8;tc>lmY%jGNp=YBFBEYc z?;_=k=1QvI7-Kd75DAI(8bYqjK%U7Aw$9NTXr2%*)%Nb0=>;W|SI-F7HK4j_Cox37KWjRdNJ<17IaMbXZo{rM*2 zA?V&opH_+EcuN2)g|6Vy(Efa4S4^dD_a>rh6h#|__E-qg(I`M~A1H<9;T2N4`|Auv zB6?KFjJTAMFmqx9KBcyNC~N#*pTu#zowV{5W!(Fg69D%KX^l#|(Ze?Y&gh3Gk%+$2 zckleIV2qhYM9)iILA_qzIJC#S*eL30A@mHoX`P=h;yB({dOC>c*P;F8#nJQ|BKkmR zf29DxZyj?3pAYS?Q!?TT|1`9}(on0_wubyo{N*G`W`_3IF1G1U-6iGg5RI-zI&aWk zSB3W1E&%Qo((*Qxc1!mhMD#~TCD=c-zgBUao@P+y-Myi4O%nqcF~+PP+G7^>OJ7=O zH$y}(bVC|~;#eMS0Q@|(zbqi1`e~SXuh9Ow0wVgGl!3QsXc2&sqm9<)J>!Q5Gal9+i&qy)=?kvhj-w{R8fsR(7 zupKo3o)x;IajgR~1_%(*4I#S%BD&Bq9{H+o{l3RW3}>MbUiG=m3UUxkgMeoj^&R%D zKzjZ1vbzYt49HQuxEJ>_lp0r44B#|vJqVFJ0IVUR&uHrn$iNu$9%)HA5v?Yok7;Q+ z4sS3-bh(z!fHsMuXm3ZsJY|fTmRG}$ITAsme>QZM6#&;bx`J~R?tiCa!sk$pGz`c= z#^CI&JW;;@eBDvGuG37%fE)nW-_aFxw1No0=F;L$0LunVf60LRv+SAe-j9fGlSch< z9PjHR4Fhs8Iy$-`+@an--s-*3j4mqO=Q5w^7?1-S_h0G?mbMae-!}cJXC2tM{oNV4 zyI%lsqhr*5b_>71-%*LaP(&IAtgg$~$z}rr0AR;9E5HMxJr7VO>j3CUm)CWL0|H^Yg4E^QQ?BDfdmZ43D2hG_ z;LSnP-^W0XPaF?6b@T}U?nrs<>z!lT2Drhx%gFwVK035&GXDe6s^j<@T-LS#0000< KMNUMnLSTaIrId~U literal 0 HcmV?d00001 diff --git a/assets/icons/ui_light/design/locate.svg b/assets/icons/ui_light/design/locate.svg new file mode 100644 index 00000000..0d378bdb --- /dev/null +++ b/assets/icons/ui_light/design/locate.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/ui_light/locate.png b/assets/icons/ui_light/locate.png new file mode 100644 index 0000000000000000000000000000000000000000..0ee991febc8dec18b4a64e37ca35ade2c67ca32c GIT binary patch literal 3454 zcmV-^4T18BP) zd8{2(9mlU!ESseWgso~tP()-aU_ro(Na?)SIp_PG%Ooynt3p88jS)nI5^y1aKv*n` zv|y0U2u5VbR{};5l|mpOC@r+16lhrrg$C&Jk2fXdb$(~=@;h_x_DSXs=)3d%p8d>O zE0r$B7_*%*##n1l1aLLUdjUKOU_QyEB!@{319%C*GbHB$7y@tw$sdxO8prV`LWiSI z9Yj$y&RTmg$p7739RreC3%ar_GAFnG)>nJ9o{~bN+nIxjR4Fbc_+zt6%)MZ zSxNGb0BTVbjSU?SJx7uxlL1^`VuHJ#znNhXuLrwtN)tp~s=k~j1- zf(Mc$*&V>`ii!0Cfd2q^kmP+NpCGxI&+i) zM%X!uqH#rIMWkmODzrvW&c$v3I7nu=^;PEq9__mayrR>)#>>`W6Tzz{I)eDQ<87h5s7~xxp!#4qanF3fV=9c zv8=WGg!bE3WNquJf{2?>(uVe0gthh%l8Xv5!U~cHh4$JOkUX=FQgc=(^`_%E-hkvq zb%g8C&|ZTA;KG6kdb5*z&{_YWsBds&XrDnKd3r&_EFk%r&^}wm7_$e-C5}wK%36C! zXrHBGtv#ZknpdMbS6_Lj}#< zq|iRS636l93ljgr&>npQ;17;CSVVHu&>p>zrs?_so^}NOvd|vOAWhRT0Pb+a!(T&t z^a9Bnd#&1+h@xmLfWJ91!B0bbR0Y7Hj=;_h?Joq`oQGH=8e{ed?NNm^O*aPcvQYAu z_43%bF=jUa?+9`8XlQ>bki1;V<<{DP(EdUL;1oyGcywrgEkSZ`N7a92Xn*Yj$$toO zw0vM-V9U_{nnvpA0C+h~(~U#>YZo}O0x5S@Gk}Xj`)dkg%mI$l|LxHJ+6@5b2ywNt zBgX~++}-c>*H1QsxLBwK&I#?WA&fD*IXZq{4DGL7A$gP#Z!0>g$s~DgyNz-Im`HLu zfYY-5e|gVo+22eI;c?QWN$Zk)QK$ue9Kut>WK~)2(k^4n0cCmtFcH9U*=izj4nm0V z`PpwLmg$+~j|4xDm+7NvNPb5Mz`x7#kR|-=MibqU8D^K25z;i>NGd=8b}hq0OOU)* zFn@d*`dJnKidN#U;r|r?r} zKy}Sh3}Afr|7MW9xg9bA$twlj@A=Yf8In)snVvRn+BQD)>P-As0nBLP-N%!BHB=@b z`AtFdcRuu5CP|X51jA4J(925g!vzU6vz7Kb)0kPH@vx6Rfz+P@@T|6$3M8irku=MP z9)R-;O1;{C0swH;1^~|2(pnP=D~a23RFLEed1kG(KhV|!P%TJ&^=cWwt_7K(s;x<3 zL^Vm0$=X^iBXs})9OywytonU+%(6@%=?-b@QQkZ=U0bVVC=384NisoG$5r~9>FhP3 zKclQ#z|j%>g{F=QdE@N>-teF^BqYFGZ7m6sa|I7KYwBd%%JOus)znde`TO6V*VM>n z^h#@k9X?#O&_perY)e_5#@$*PY9Qx49{|rNYaAcC^sh#$1vKY8vgzSGjfb@~)Bx~y zj@c(PH7JbImC^Q(#*rCSn*rv0c>s7$Q$vL^a;h}y7h(a2)EohLMN^0QqpK@4HB=Bv z!y_eV%+u6p(9gU)PnsG49`&uE0`r$OKc@A5N5^ZfmPVsE`TEsZ8T&GDT9kaJ2YfH$??uZA#xy;$-6QU;i*rO||^+=(LP8enOT#uBaf zt067CRD8eG1gQ498-emyNmWt9Yt5<#Mo#Wr%dFN?FvmFjT#ffPgQE|iG9MAg@u!3^ z->30@RY=|-m{mK~Q;6*OTJLWZ-?bjegM>J}N=rixl0O#`=om$f1%k#zEsc6{)JO}o zG_18J3mWZrf(U?`kT};UYDm5AQkI;L@{&6esQFcbk#mvrG^S{2sF5Ve1R=Mo^;o5; z*bvQtRQ+oXOHOkJnqS*|%=Hh2-={WRfJM^m>8flttELHzWlI*FW z;fr-3+}NqPN|*AA9Is7*tLmrXcm#m&3mOZxG`xY4o4WGM|4C6pTp8pm6BH!A>ZhnQ zsMeNi0Y^h}Um=p-i{p4REuA_xY^d$z#mK=CF0GkbTD4kjdqHDW$J|9oVMBvvqGUQ^ zQ;_KmwK6P=k*#M#E)C79zf!4GNd899xl>ceD^eQ{>EU6LM`>!+n+dXvFdx8q0FER150&M^Q`1 zb!HIBlYDAt-|ZS1VS(>?29l>r`W=6qKFMDRIs3K2!NE;@>tlpDEI93B)blEUIhv!F z5>XUw?&$fS?pxnGQ521nBHvegDv^EO&A`aXAu~BLjxcxie`o(z>REgwFB1}fX&lEJ zl92+M=LKn&i{!$tY47S_aBy%F2p4IQye+gpZ_sgv5IXHrgcfj2nYZ^z zpc+uVOJJDfPNDtzrl1gX?x0V-7-O~|xm<{Z`$PNl%sLRZdy`x=Wy+KdLmMmw%2%Td zvx_g3%4Q*R!`*XtD3ZKih>Rs|c@k!eWCuRw)_iE!^M8F(tJSupu=17dxc99^NZuwS z{tIop(Ze?+PwIs#k>q!K?wh|J(li|d;7O?|h@xm*XpgOuB*|9DIYKXcI%l1qFRZou zI7-KFL;GtLsp`*axsQkT*A@Wyz2mFkE1~^0OTiw(pN00=qtyQI8aqS4V%xNk6vuuDSwYZL&t3gLNAYqxaQ0pQP$_Hw__{^|w7?P=N5zPo!v z;~FLgFn`jdN$ZC8Sj6Dq;3mvJ+HIKRQ=Jfoph(N3v*(wg{S^WE*3V%8dxiGb5s>`5 zBNOZr+Mk5AcA%U3F~P9b?&yff_B$)T^8VWXg@W&eo%kga6xWt)Ywd}l{f&m?EQjB& z8P+b1G)>1)xQUeHN@L7+p*^mqU^KJ$X8N=Muor+;Lc~50+FzwosYFpUmhujyu9(jV z3V?GR9l~Qn`y+XQqv~g9e;rS?T3ydk!d4_n^2t!%k|f#FQA1r9%2(H6jM?8&3)~aJ zQ?}VPoh52_R z4FkBTEFV1wfCC++uCyIB03H_-f0@<=8GQsuUKz3}AbGY!|7*VWd!Fp2fK|qrFKO%b zDIiVLk2sc;uQbMdR!fWW#*C&jmii(WeDCa`wNJ zaPum4oVg#z@n(*@4i}F!X5wlAAid+lP%YyE%S4 z-O-u!ekWlcB}h(nB;=D(6pbDI8vqjlydnJVd1K5+LxiPIlN21rxYqD3fCn5^f5&W0 z?URwMAd>bK43nI?`fmZ8;`qDHKeNAANs?qw3QM<0z6fA^k|YxVye-re|EzS{ZC!mn z2+5y2nu6;{-Xi?_TbeV9eFBl4L?#{2Dn7n$HtQ3BIF5H{B=G^<5!!PfWn8t+Ajcjr(gB=FqF?HUee#x(Ib$&F{ku*&oym*+~h1H g`(H0zTD2zs2N_$T=*Ctyt^fc407*qoM6N<$g52?%&;S4c literal 0 HcmV?d00001 diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 14995ca5..47497e8e 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4221 +4267 diff --git a/resources.qrc b/resources.qrc index bb66fcd6..84a3e4e6 100644 --- a/resources.qrc +++ b/resources.qrc @@ -28,5 +28,7 @@ assets/icons/ui_light/connect.png assets/icons/ui_dark/stop.png assets/icons/ui_light/stop.png + assets/icons/ui_dark/locate.png + assets/icons/ui_light/locate.png diff --git a/src/components/proxy/QvProxyConfigurator.cpp b/src/components/proxy/QvProxyConfigurator.cpp index 4cc274bc..16ad2139 100644 --- a/src/components/proxy/QvProxyConfigurator.cpp +++ b/src/components/proxy/QvProxyConfigurator.cpp @@ -191,6 +191,7 @@ namespace Qv2ray::components::proxy void SetSystemProxy(const QString &address, int httpPort, int socksPort, bool usePAC) { + LOG(MODULE_PROXY, "Setting up System Proxy") bool hasHTTP = (httpPort != 0); bool hasSOCKS = (socksPort != 0); @@ -354,6 +355,7 @@ namespace Qv2ray::components::proxy void ClearSystemProxy() { + LOG(MODULE_PROXY, "Clearing System Proxy") #ifdef Q_OS_WIN LOG(MODULE_PROXY, "Cleaning system proxy settings.") INTERNET_PER_CONN_OPTION_LIST list; diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index be64c069..a3ea4bdb 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -150,16 +150,6 @@ namespace Qv2ray::core::handlers tcpingHelper->TestLatency(id); } - const QList QvConnectionHandler::Connections() const - { - return connections.keys(); - } - - const QList QvConnectionHandler::AllGroups() const - { - return groups.keys(); - } - const QList QvConnectionHandler::Subscriptions() const { QList subsList; diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 5f52d930..4adf5984 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -21,9 +21,20 @@ namespace Qv2ray::core::handlers public: // - const QList Connections() const; + inline const ConnectionId CurrentConnection() const + { + return currentConnectionId; + } + inline const QList Connections() const + { + return connections.keys(); + } + inline const QList AllGroups() const + { + return groups.keys(); + } + // // - const QList AllGroups() const; const QList Subscriptions() const; const QList Connections(const GroupId &groupId) const; // diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 7514961a..2840c182 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -2,18 +2,18 @@ #include "w_MainWindow.hpp" +#include "components/pac/QvPACHandler.hpp" +#include "components/plugins/toolbar/QvToolbar.hpp" +#include "components/proxy/QvProxyConfigurator.hpp" +#include "core/connection/ConnectionIO.hpp" #include "ui/editors/w_JsonEditor.hpp" #include "ui/editors/w_OutboundEditor.hpp" #include "ui/editors/w_RoutesEditor.hpp" +#include "ui/widgets/ConnectionInfoWidget.hpp" #include "w_ExportConfig.hpp" #include "w_ImportConfig.hpp" #include "w_PreferencesWindow.hpp" #include "w_SubscriptionManager.hpp" -//#include -#include "components/pac/QvPACHandler.hpp" -#include "components/plugins/toolbar/QvToolbar.hpp" -#include "core/connection/ConnectionIO.hpp" -#include "ui/widgets/ConnectionInfoWidget.hpp" #include #include @@ -32,6 +32,10 @@ // operations. #define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING +#define CheckCurrentWidget \ + auto widget = GetItemWidget(connectionListWidget->currentItem()); \ + if (widget == nullptr) \ + return; #define GetItemWidget(item) (qobject_cast(connectionListWidget->itemWidget(item, 0))) MainWindow *MainWindow::mwInstance = nullptr; @@ -154,25 +158,17 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h // connect(action_Tray_Quit, &QAction::triggered, this, &MainWindow::on_actionExit_triggered); connect(action_Tray_SetSystemProxy, &QAction::triggered, this, &MainWindow::MWSetSystemProxy); - connect(action_Tray_ClearSystemProxy, &QAction::triggered, this, &MainWindow::MWClearSystemProxy); + connect(action_Tray_ClearSystemProxy, &QAction::triggered, [&] { ClearSystemProxy(); }); connect(&hTray, &QSystemTrayIcon::activated, this, &MainWindow::on_activatedTray); // // Actions for right click the connection list // - QAction *action_RCM_RenameConnection = new QAction(tr("Rename"), this); QAction *action_RCM_StartThis = new QAction(tr("Connect to this"), this); QAction *action_RCM_ConvToComplex = new QAction(QICON_R("edit.png"), tr("Edit as Complex Config"), this); - QAction *action_RCM_EditJson = new QAction(QICON_R("json.png"), tr("Edit as Json"), this); - QAction *action_RCM_ShareQR = new QAction(QICON_R("share.png"), tr("Share as QRCode/VMess URL"), this); // - connect(action_RCM_RenameConnection, &QAction::triggered, this, &MainWindow::on_action_RCM_RenameConnection_triggered); connect(action_RCM_StartThis, &QAction::triggered, this, &MainWindow::on_action_StartThis_triggered); - connect(action_RCM_EditJson, &QAction::triggered, this, &MainWindow::on_action_RCM_EditJson_triggered); connect(action_RCM_ConvToComplex, &QAction::triggered, this, &MainWindow::on_action_RCM_ConvToComplex_triggered); // - // Share options - connect(action_RCM_ShareQR, &QAction::triggered, this, &MainWindow::on_action_RCM_ShareQR_triggered); - // // Globally invokable signals. connect(this, &MainWindow::Connect, [&] { ConnectionManager->StartConnection(lastConnectedId); }); connect(this, &MainWindow::DisConnect, ConnectionManager, &QvConnectionHandler::StopConnection); @@ -183,9 +179,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h // connectionListMenu = new QMenu(this); connectionListMenu->addAction(action_RCM_StartThis); - connectionListMenu->addAction(action_RCM_ShareQR); - connectionListMenu->addAction(action_RCM_RenameConnection); - connectionListMenu->addAction(action_RCM_EditJson); connectionListMenu->addAction(action_RCM_ConvToComplex); // LOG(MODULE_UI, "Loading data...") @@ -235,31 +228,42 @@ void MainWindow::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { - // If pressed enter or return on connectionListWidget. - // Try to connect to the selected connection. - // if (focusWidget() == connectionListWidget) { - // if (!IsSelectionConnectable) return; - // - // auto selections = connectionListWidget->selectedItems(); - // QVariant v; - // auto vv = v.value(); - // ShowAndSetConnection(ItemConnectionIdentifier(selections.first()), - // true, true); - //} + if (focusWidget() == connectionListWidget) + { + CheckCurrentWidget; + // If pressed enter or return on connectionListWidget. Try to connect to the selected connection. + if (widget->IsConnection()) + { + widget->BeginConnection(); + } + else + { + connectionListWidget->expandItem(connectionListWidget->currentItem()); + } + } + } +} + +void MainWindow::keyReleaseEvent(QKeyEvent *e) +{ + // Workaround of QtWidget not grabbing KeyDown and KeyUp in keyPressEvent + if (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down) + { + if (focusWidget() == connectionListWidget) + { + CheckCurrentWidget; + on_connectionListWidget_itemClicked(connectionListWidget->currentItem(), 0); + } } } void MainWindow::on_action_StartThis_triggered() { - // if (!IsSelectionConnectable) { - // QvMessageBoxWarn(this, tr("No connection selected!"), tr("Please - // select a config from the list.")); return; - //} - // - // CurrentSelectedItemPtr = connectionListWidget->selectedItems().first(); - // CurrentConnectionIdentifier = - // ItemConnectionIdentifier(CurrentSelectedItemPtr); - // on_reconnectButton_clicked(); + CheckCurrentWidget; + if (widget->IsConnection()) + { + widget->BeginConnection(); + } } #ifndef DISABLE_AUTO_UPDATE @@ -372,19 +376,6 @@ void MainWindow::on_clearlogButton_clicked() { masterLogBrowser->clear(); } -void MainWindow::on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) -{ - Q_UNUSED(previous) - // CurrentItem = current; - // isRenamingInProgress = false; - // - // if (!IsConnectableItem(current)) return; - // - //// no need to check !isRenamingInProgress since it's always true. - // ShowAndSetConnection(ItemConnectionIdentifier(current), - // !vinstance->KernelStarted, false); - ////on_connectionListWidget_itemClicked(current, 0); -} void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint &pos) { Q_UNUSED(pos) @@ -396,15 +387,7 @@ void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint connectionListMenu->popup(_pos); } } -void MainWindow::on_action_RCM_RenameConnection_triggered() -{ - // auto item = connectionListWidget->currentItem(); - // SUBSCRIPTION_CONFIG_MODIFY_DENY(item) - // item->setFlags(item->flags() | Qt::ItemIsEditable); - // isRenamingInProgress = true; - // connectionListWidget->editItem(item); - // renameOriginalIdentifier = ItemConnectionIdentifier(item); -} + void MainWindow::on_connectionListWidget_itemChanged(QTreeWidgetItem *item, int) { // DEBUG(UI, "A connection ListViewItem is changed. This should ONLY occur @@ -576,7 +559,6 @@ void MainWindow::on_removeConfigButton_clicked() void MainWindow::on_importConfigButton_clicked() { - ImportConfigWindow w(this); auto configs = w.OpenImport(); if (!configs.isEmpty()) @@ -591,50 +573,25 @@ void MainWindow::on_importConfigButton_clicked() } } } -void MainWindow::on_editConfigButton_clicked() -{ -} void MainWindow::on_action_RCM_ConvToComplex_triggered() { - //// Check if we have a connection selected... - // if (!IsSelectionConnectable) - //{ - // QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a Config")); - // return; - //} - // - // auto selectedFirst = connectionListWidget->currentItem(); - // auto _identifier = ItemConnectionIdentifier(selectedFirst); - // SUBSCRIPTION_CONFIG_MODIFY_DENY(selectedFirst) - //// - // auto outBoundRoot = connections[_identifier].config; - // CONFIGROOT root; - // bool isChanged = false; - //// - // LOG(UI, "INFO: Opening route editor.") - // RouteEditor routeWindow(outBoundRoot, this); - // root = routeWindow.OpenEditor(); - // isChanged = routeWindow.result() == QDialog::Accepted; - // QString alias = _identifier.connectionName; - // - // if (isChanged) - //{ - // connections[_identifier].config = root; - // // true indicates the alias will NOT change - // SaveConnectionConfig(root, &alias, true); - // OnConfigListChanged(_identifier == CurrentConnectionIdentifier); - // ShowAndSetConnection(CurrentConnectionIdentifier, false, false); - //} -} - -void MainWindow::on_action_RCM_EditJson_triggered() -{ -} - -void MainWindow::on_action_RCM_ShareQR_triggered() -{ - // on_shareBtn_clicked(); + CheckCurrentWidget; + if (widget->IsConnection()) + { + auto id = get<1>(widget->Identifier()); + CONFIGROOT root = ConnectionManager->GetConnectionRoot(id); + bool isChanged = false; + // + LOG(MODULE_UI, "INFO: Opening route editor.") + RouteEditor routeWindow(root, this); + root = routeWindow.OpenEditor(); + isChanged = routeWindow.result() == QDialog::Accepted; + if (isChanged) + { + ConnectionManager->UpdateConnection(id, root); + } + } } void MainWindow::on_subsButton_clicked() @@ -646,7 +603,8 @@ void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item { Q_UNUSED(column) auto widget = GetItemWidget(item); - + if (widget == nullptr) + return; if (widget->IsConnection()) { widget->BeginConnection(); @@ -656,20 +614,19 @@ void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item void MainWindow::OnDisconnected(const ConnectionId &id) { Q_UNUSED(id) - this->hTray.showMessage("Qv2ray", tr("Disonnected"), this->windowIcon()); + lastConnectedId = id; + locateBtn->setEnabled(false); + this->hTray.showMessage("Qv2ray", tr("Disconnected from: ") + ConnectionManager->GetDisplayName(id), this->windowIcon()); hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE); - connetionStatusLabel->setText(tr("Disconnected")); - - if (systemProxyEnabled) + connetionStatusLabel->setText(tr("Not Connected")); + if (GlobalConfig.inboundConfig.setSystemProxy) { - MWClearSystemProxy(false); + ClearSystemProxy(); } - // QFile(QV2RAY_GENERATED_FILE_PATH).remove(); - if (GlobalConfig.inboundConfig.pacConfig.enablePAC) { - // pacServer.StopServer(); + pacServer.StopServer(); LOG(MODULE_UI, "Stopping PAC server") } } @@ -677,6 +634,8 @@ void MainWindow::OnDisconnected(const ConnectionId &id) void MainWindow::OnConnected(const ConnectionId &id) { Q_UNUSED(id) + lastConnectedId = id; + locateBtn->setEnabled(true); on_clearlogButton_clicked(); auto name = ConnectionManager->GetDisplayName(id); this->hTray.showMessage("Qv2ray", tr("Connected: ") + name, this->windowIcon()); @@ -733,8 +692,8 @@ void MainWindow::OnConnected(const ConnectionId &id) if (canStartPAC) { - // pacServer.SetProxyString(pacProxyString); - // pacServer.StartListen(); + pacServer.SetProxyString(pacProxyString); + pacServer.StartListen(); } else { @@ -806,7 +765,10 @@ void MainWindow::on_connectionFilterTxt_textEdited(const QString &arg1) void MainWindow::on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column) { Q_UNUSED(column) - infoWidget->ShowDetails(GetItemWidget(item)->Identifier()); + auto widget = GetItemWidget(item); + if (widget == nullptr) + return; + infoWidget->ShowDetails(widget->Identifier()); } void MainWindow::OnStatsAvailable(const ConnectionId &id, const quint64 upS, const quint64 downS, const quint64 upD, const quint64 downD) @@ -930,3 +892,12 @@ void MainWindow::OnGroupDeleted(const GroupId &id, const QList &co } groupNodes.remove(id); } + +void MainWindow::on_locateBtn_clicked() +{ + auto id = ConnectionManager->CurrentConnection(); + if (id != NullConnectionId) + { + connectionListWidget->setCurrentItem(connectionNodes[id].get()); + } +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 839bbb20..f10d9cce 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -2,6 +2,7 @@ #include "common/HTTPRequestHelper.hpp" #include "common/LogHighlighter.hpp" +#include "components/pac/QvPACHandler.hpp" #include "components/speedchart/speedwidget.hpp" #include "core/handler/ConnectionHandler.hpp" #include "ui/messaging/QvMessageBus.hpp" @@ -31,17 +32,14 @@ class MainWindow public slots: QvMessageBusSlotDecl; private slots: - void on_action_RCM_ShareQR_triggered(); void on_activatedTray(QSystemTrayIcon::ActivationReason reason); void on_actionExit_triggered(); void on_preferencesBtn_clicked(); void on_clearlogButton_clicked(); - void on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); void on_connectionListWidget_customContextMenuRequested(const QPoint &pos); void on_connectionListWidget_itemChanged(QTreeWidgetItem *item, int column); void on_removeConfigButton_clicked(); void on_importConfigButton_clicked(); - void on_editConfigButton_clicked(); void on_subsButton_clicked(); // void ToggleVisibility(); @@ -55,6 +53,7 @@ class MainWindow protected: void keyPressEvent(QKeyEvent *e) override; + void keyReleaseEvent(QKeyEvent *e) override; void closeEvent(QCloseEvent *) override; private slots: @@ -77,12 +76,12 @@ class MainWindow void OnGroupDeleted(const GroupId &id, const QList &connections); // void on_action_StartThis_triggered(); - void on_action_RCM_EditJson_triggered(); void on_action_RCM_ConvToComplex_triggered(); - void on_action_RCM_RenameConnection_triggered(); + // void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); void on_connectionFilterTxt_textEdited(const QString &arg1); void on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column); + void on_locateBtn_clicked(); private: QHash> groupNodes; @@ -96,7 +95,7 @@ class MainWindow QvHttpRequestHelper *requestHelper; #endif QSystemTrayIcon hTray; - // PACServer pacServer; + PACServer pacServer; // QvTCPingModel tcpingHelper; SyntaxHighlighter *vCoreLogHighlighter; ConnectionInfoWidget *infoWidget; @@ -117,10 +116,8 @@ class MainWindow QAction *action_Tray_ClearSystemProxy; // // Extra Headers For w_MainWindow_extra.cpp Handling V2ray Connectivities. - bool systemProxyEnabled; ConnectionId lastConnectedId; void MWSetSystemProxy(); - void MWClearSystemProxy(bool); void CheckSubscriptionsUpdate(); // void MWAddConnectionItem_p(const ConnectionId &connection, const GroupId &groupId); diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index c5dad60b..f4481879 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -85,8 +85,8 @@ 0 - - + + Search @@ -96,7 +96,24 @@ - + + + + false + + + Locate Current Connection + + + + + + + :/assets/icons/ui_light/locate.png:/assets/icons/ui_light/locate.png + + + + Qt::CustomContextMenu @@ -135,7 +152,7 @@ - + @@ -354,7 +371,7 @@ - Connection Status + Not Connected @@ -705,6 +722,8 @@ connectionListWidget importConfigButton - + + + diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index a4514a67..a6ae76d2 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -1,48 +1,6 @@ -// Supplementary file for MainWindow -- Basically the handler for connectivity -// management and components interactions. We NEED to include the cpp file to -// define the macros. +#include "common/QvHelpers.hpp" #include "components/proxy/QvProxyConfigurator.hpp" -#include "w_MainWindow.cpp" - -// QTreeWidgetItem *MainWindow::FindItemByIdentifier(QvConnectionObject -// identifier) -//{ -// //// First filter out all items with our config name. -// //auto items = connectionListWidget->findItems(identifier.connectionName, -// Qt::MatchExactly | Qt::MatchRecursive); -// // -// //for (auto item : items) { -// // // This connectable prevents the an item with (which is the parent -// node of a subscription, having the same -// // // -- name as our current connected name) -// // if (!IsConnectableItem(item)) { -// // LOG(UI, "Invalid Item found: " + item->text(0)) -// // continue; -// // } -// // -// // auto thisIdentifier = ItemConnectionIdentifier(item); -// // DEBUG(UI, "Item Identifier: " + thisIdentifier.IdentifierString()) -// // -// // if (identifier == thisIdentifier) { -// // return item; -// // } -// //} -// // -// //LOG(UI, "Warning: Failed to find an item named: " + -// identifier.IdentifierString()) return nullptr; -//} - -void MainWindow::MWClearSystemProxy(bool showMessage) -{ - ClearSystemProxy(); - LOG(MODULE_UI, "Clearing System Proxy") - systemProxyEnabled = false; - - if (showMessage) - { - hTray.showMessage("Qv2ray", tr("System proxy cleared."), windowIcon()); - } -} +#include "w_MainWindow.hpp" void MainWindow::MWSetSystemProxy() { @@ -51,10 +9,7 @@ void MainWindow::MWSetSystemProxy() bool httpEnabled = GlobalConfig.inboundConfig.useHTTP; bool socksEnabled = GlobalConfig.inboundConfig.useSocks; // - // Set system proxy if necessary - // bool isComplex = - // IsComplexConfig(connections[CurrentConnectionIdentifier].config); - bool isComplex = false; + bool isComplex = IsComplexConfig(ConnectionManager->GetConnectionRoot(ConnectionManager->CurrentConnection())); if (!isComplex) { @@ -108,15 +63,12 @@ void MainWindow::MWSetSystemProxy() auto httpPort = GlobalConfig.inboundConfig.useHTTP ? GlobalConfig.inboundConfig.http_port : 0; auto socksPort = GlobalConfig.inboundConfig.useSocks ? GlobalConfig.inboundConfig.socks_port : 0; // - // If usePAC is set SetSystemProxy(proxyAddress, httpPort, socksPort, usePAC); - systemProxyEnabled = true; - hTray.showMessage("Qv2ray", tr("System proxy settings applied."), windowIcon()); } } else { - hTray.showMessage("Qv2ray", tr("Cannot set proxy for complex config."), windowIcon()); + hTray.showMessage("Qv2ray", tr("Didn't set proxy for complex config."), windowIcon()); } } diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index a5d2cd71..9372b2cc 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -25,8 +25,7 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) void ConnectionInfoWidget::ShowDetails(const tuple &_identifier) { - groupId = get<0>(_identifier); - connectionId = get<1>(_identifier); + auto [groupId, connectionId] = _identifier; bool isConnection = connectionId != NullConnectionId; editJsonBtn->setEnabled(isConnection); connectBtn->setEnabled(isConnection); diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index e8c42fc7..8c256b52 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -57,6 +57,9 @@ + + Latency Test + @@ -83,7 +86,7 @@ - Edit Connection Config as JSON + Edit Connection as JSON @@ -125,7 +128,7 @@ - Connect To This Connection + Connect/Disconnect diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index 5eaaa4bd..afaf031b 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -40,7 +40,6 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare emit RequestWidgetFocus(this); } OnConnectionItemRenamed(id, "", originalConnectionName); - this->setToolTip(originalConnectionName); connect(ConnectionManager, &QvConnectionHandler::OnConnectionRenamed, this, &ConnectionItemWidget::OnConnectionItemRenamed); } @@ -57,6 +56,10 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : delete connTypeLabel; delete dataLabel; // + auto font = connNameLabel->font(); + font.setBold(true); + connNameLabel->setFont(font); + // OnGroupItemRenamed(id, "", originalConnectionName); connect(ConnectionManager, &QvConnectionHandler::OnConnectionCreated, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConnectionHandler::OnConnectionDeleted, this, &ConnectionItemWidget::RecalculateConnectionsCount); From 44e9a550d275d03fd7b2c1dab8d738521617ce0e Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 1 Mar 2020 22:57:14 +0800 Subject: [PATCH 077/332] add: added more ui functionalities --- makespec/BUILDVERSION | 2 +- src/core/handler/ConnectionHandler.hpp | 4 + src/ui/w_MainWindow.cpp | 12 +- src/ui/w_MainWindow.ui | 10 +- src/ui/widgets/ConnectionInfoWidget.cpp | 20 +- src/ui/widgets/ConnectionInfoWidget.ui | 497 ++++++++++++++---------- 6 files changed, 332 insertions(+), 213 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 47497e8e..87ca4f07 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4267 +4284 diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index 4adf5984..b2aad268 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -79,6 +79,10 @@ namespace Qv2ray::core::handlers // const optional DuplicateGroup(const GroupId &id); // // Subscriptions + bool IsSubscription(const GroupId &id) const + { + return groups[id].isSubscription; + } bool SetSubscriptionData(const GroupId &id, const QString &address = "", float updateInterval = -1); bool UpdateSubscription(const GroupId &id, bool useSystemProxy); // bool UpdateSubscriptionASync(const GroupId &id, bool useSystemProxy); diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 2840c182..9c1a9ed6 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "w_MainWindow.hpp" #include "components/pac/QvPACHandler.hpp" @@ -203,6 +201,16 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h auto id = ConnectionId(GlobalConfig.autoStartId); needShowWindow = ConnectionManager->StartConnection(id).has_value(); } + else + { + if (connectionListWidget->topLevelItemCount() > 0 && connectionListWidget->topLevelItem(0)->childCount() > 0) + { + // Select the first connection. + auto item = connectionListWidget->topLevelItem(0)->child(0); + on_connectionListWidget_itemClicked(item, 0); + connectionListWidget->setCurrentItem(item); + } + } if (needShowWindow) this->show(); diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index f4481879..f2a3cf76 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -225,7 +225,7 @@ 0 0 480 - 743 + 768 @@ -240,7 +240,13 @@ 0 - 205 + 230 + + + + + 16777215 + 230 diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 9372b2cc..aa4e3400 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -27,11 +27,13 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden { auto [groupId, connectionId] = _identifier; bool isConnection = connectionId != NullConnectionId; + // + editBtn->setEnabled(isConnection); editJsonBtn->setEnabled(isConnection); connectBtn->setEnabled(isConnection); duplicateBtn->setEnabled(isConnection); - editBtn->setEnabled(isConnection); + stackedWidget->setCurrentIndex(isConnection ? 0 : 1); if (isConnection) { groupLabel->setText(ConnectionManager->GetDisplayName(groupId, 175)); @@ -57,13 +59,15 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden else { connectBtn->setIcon(QICON_R("connect.png")); - groupLabel->setText(tr("N/A")); - protocolLabel->setText(tr("N/A")); - addressLabel->setText(tr("N/A")); - portLabel->setText(tr("N/A")); - // - shareLinkTxt->clear(); - qrLabel->clear(); + groupNameLabel->setText(ConnectionManager->GetDisplayName(groupId)); + QStringList shareLinks; + for (auto connection : ConnectionManager->Connections(groupId)) + { + shareLinks << ConvertConfigToString(connection, false); + } + groupShareTxt->setPlainText(shareLinks.join(NEWLINE)); + groupSubsLinkLabel->setText(ConnectionManager->IsSubscription(groupId) ? get<0>(ConnectionManager->GetSubscriptionData(groupId)) : + tr("Not a subscription")); } } diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index 8c256b52..bc813740 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -6,8 +6,8 @@ 0 0 - 403 - 215 + 412 + 230 @@ -16,17 +16,20 @@ 0 + + + 412 + 230 + + true Form - - - 0 - - + + @@ -143,205 +146,299 @@ - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 150 - 150 - - - - - 150 - 150 - - - - QR Code - - - - - - :/assets/icons/qv2ray.ico - - - true - - - Qt::AlignCenter - - - - - - - - - - 9 - - - 6 - - - - - Group - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - IBeamCursor - - - type - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Protocol - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - IBeamCursor - - - proto - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Address - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - IBeamCursor - - - addr - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Port - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - IBeamCursor - - - port - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Link - - - - - - - IBeamCursor - - - true - - - - - - + Qt::Horizontal + + + + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 9 + + + 6 + + + + + Group + + + + + + + IBeamCursor + + + type + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Protocol + + + + + + + IBeamCursor + + + proto + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Address + + + + + + + IBeamCursor + + + addr + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Port + + + + + + + IBeamCursor + + + port + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Link + + + + + + + IBeamCursor + + + true + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 150 + 150 + + + + + 150 + 150 + + + + QR Code + + + + + + :/assets/icons/qv2ray.ico + + + true + + + Qt::AlignCenter + + + Qt::NoTextInteraction + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Group Name + + + + + + + + + + + + + + Subscription Link + + + + + + + + + + + + + + Share Link + + + + + + + + 0 + 0 + + + + + 1 + 1 + + + + Qt::ScrollBarAlwaysOn + + + QAbstractScrollArea::AdjustToContents + + + QPlainTextEdit::NoWrap + + + true + + + + + + + From 7fb8cd3d94f36c3d336decd9e73b4e987ef9b3d1 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 2 Mar 2020 00:03:07 +0800 Subject: [PATCH 078/332] add: added more ui functionalities - 2 --- makespec/BUILDVERSION | 2 +- src/core/kernel/APIBackend.cpp | 13 +- src/ui/w_MainWindow.cpp | 101 +++-------- src/ui/w_MainWindow.hpp | 2 +- src/ui/w_MainWindow.ui | 226 ------------------------ src/ui/w_PreferencesWindow.cpp | 7 +- src/ui/w_SubscriptionManager.cpp | 4 + src/ui/widgets/ConnectionInfoWidget.cpp | 7 +- src/ui/widgets/ConnectionInfoWidget.ui | 12 ++ src/ui/widgets/ConnectionItemWidget.cpp | 40 ++++- src/ui/widgets/ConnectionItemWidget.hpp | 11 +- src/ui/widgets/ConnectionItemWidget.ui | 173 ++++++++++++------ 12 files changed, 221 insertions(+), 377 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 87ca4f07..7174ebd1 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4284 +4326 diff --git a/src/core/kernel/APIBackend.cpp b/src/core/kernel/APIBackend.cpp index bd7b403a..3f7b0823 100644 --- a/src/core/kernel/APIBackend.cpp +++ b/src/core/kernel/APIBackend.cpp @@ -13,6 +13,15 @@ namespace Qv2ray::core::kernel { // To all contributors: // + // You may feel it difficult to understand this part of API backend. + // It's been expected that you will take hours to fully understand the tricks and hacks lying deeply in this class. + // + // The API Worker runs as a daemon together with Qv2ray, on a single thread. + // They use a flag, running, to indicate if the API worker should go and fetch the statistics from V2ray Core. + // + // The flag, running, will be set to true, immediately after the V2ray core reported that it's been started. + // and will be set to false right before we stopping V2ray Core. + // // --- CONSTRUCTOR --- APIWorker::APIWorker() @@ -20,9 +29,9 @@ namespace Qv2ray::core::kernel thread = new QThread(); this->moveToThread(thread); DEBUG(MODULE_VCORE, "API Worker initialised.") - connect(this, SIGNAL(error(QString)), this, SLOT(errorString(QString))); + // connect(this, SIGNAL(error(QString)), this, SLOT(errorString(QString))); connect(thread, SIGNAL(started()), this, SLOT(process())); - connect(thread, &QThread::finished, []() { LOG(MODULE_VCORE, "API thread stopped") }); + connect(thread, &QThread::finished, [] { LOG(MODULE_VCORE, "API thread stopped") }); started = true; thread->start(); DEBUG(MODULE_VCORE, "API Worker started.") diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 9c1a9ed6..b633eb71 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -162,10 +162,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h // Actions for right click the connection list // QAction *action_RCM_StartThis = new QAction(tr("Connect to this"), this); + QAction *action_RCM_RenameThis = new QAction(tr("Rename"), this); QAction *action_RCM_ConvToComplex = new QAction(QICON_R("edit.png"), tr("Edit as Complex Config"), this); // connect(action_RCM_StartThis, &QAction::triggered, this, &MainWindow::on_action_StartThis_triggered); connect(action_RCM_ConvToComplex, &QAction::triggered, this, &MainWindow::on_action_RCM_ConvToComplex_triggered); + connect(action_RCM_RenameThis, &QAction::triggered, this, &MainWindow::on_action_RCM_RenameThis_triggered); // // Globally invokable signals. connect(this, &MainWindow::Connect, [&] { ConnectionManager->StartConnection(lastConnectedId); }); @@ -177,6 +179,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h // connectionListMenu = new QMenu(this); connectionListMenu->addAction(action_RCM_StartThis); + connectionListMenu->addAction(action_RCM_RenameThis); connectionListMenu->addAction(action_RCM_ConvToComplex); // LOG(MODULE_UI, "Loading data...") @@ -189,7 +192,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h for (auto connection : connections) { - MWAddConnectionItem_p(connection, group); // + MWAddConnectionItem_p(connection, group); } } // @@ -368,6 +371,7 @@ void MainWindow::ToggleVisibility() void MainWindow::on_actionExit_triggered() { + ConnectionManager->StopConnection(); if (StartupOption.enableToolbarPlguin) { StopProcessingPlugins(); @@ -396,85 +400,6 @@ void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint } } -void MainWindow::on_connectionListWidget_itemChanged(QTreeWidgetItem *item, int) -{ - // DEBUG(UI, "A connection ListViewItem is changed. This should ONLY occur - // when renaming an connection.") - // - // if (!isRenamingInProgress) { - // return; - //} - // - // isRenamingInProgress = false; - //// In this case it's after we entered the name. - //// and tell user you should not rename a config from subscription. - // auto newIdentifier = renameOriginalIdentifier; - // newIdentifier.connectionName = item->text(0); - // LOG(CONNECTION, "RENAME: " + renameOriginalIdentifier.IdentifierString() - // + " -> " + newIdentifier.IdentifierString()) - // - //// If I really did some changes. - // if (renameOriginalIdentifier != newIdentifier) { - // bool canContinueRename = true; - // - // if (newIdentifier.connectionName.trimmed().isEmpty()) { - // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name - // cannot be empty")); canContinueRename = false; - // } - // - // QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - // //if (GlobalConfig.configs.contains(newIdentifier.connectionName)) { - // // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name - // has been used already, Please choose another.")); - // // canContinueRename = false; - // //} - // - // if (!IsValidFileName(newIdentifier.connectionName + - // QV2RAY_CONFIG_FILE_EXTENSION)) { - // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name you - // suggested is not valid, please try another.")); canContinueRename - // = false; - // } - // - // if (!canContinueRename) { - // // Set the item text back - // assert(item != nullptr); // Let's say the item should not be null - // item->setText(0, renameOriginalIdentifier.connectionName); - // return; - // } - // - // // Change auto start config. - // // |--------------=== In case it's not in a subscription --| - // if (GlobalConfig.autoStartConfig == renameOriginalIdentifier) { - // GlobalConfig.autoStartConfig = newIdentifier; - // } - // - // QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - // //// Replace the items in the current loaded config list and settings. - // //// Note: This original name should only be a reguular. - // //GlobalConfig.configs.removeOne(renameOriginalIdentifier.connectionName); - // //GlobalConfig.configs.push_back(newIdentifier.connectionName); - // // - // //connections[newIdentifier] = - // connections.take(renameOriginalIdentifier); - // //RenameConnection(renameOriginalIdentifier.connectionName, - // newIdentifier.connectionName); - // //LOG(UI, "Saving a global config") - // //SaveGlobalConfig(GlobalConfig); - // //// - // //item->setData(0, Qt::UserRole, QVariant::fromValue(newIdentifier)); - // // - // //if (CurrentConnectionIdentifier == renameOriginalIdentifier) { - // // CurrentConnectionIdentifier = newIdentifier; - // // - // // if (vinstance->KernelStarted) { - // // on_reconnectButton_clicked(); - // // } - // //} - // //OnConfigListChanged(CurrentConnectionIdentifier.connectionName == - // renameOriginalName); - //} -} void MainWindow::on_removeConfigButton_clicked() { QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); @@ -622,6 +547,10 @@ void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item void MainWindow::OnDisconnected(const ConnectionId &id) { Q_UNUSED(id) + action_Tray_Start->setEnabled(true); + action_Tray_Stop->setEnabled(false); + action_Tray_Reconnect->setEnabled(false); + tray_SystemProxyMenu->setEnabled(false); lastConnectedId = id; locateBtn->setEnabled(false); this->hTray.showMessage("Qv2ray", tr("Disconnected from: ") + ConnectionManager->GetDisplayName(id), this->windowIcon()); @@ -642,6 +571,10 @@ void MainWindow::OnDisconnected(const ConnectionId &id) void MainWindow::OnConnected(const ConnectionId &id) { Q_UNUSED(id) + action_Tray_Start->setEnabled(false); + action_Tray_Stop->setEnabled(true); + action_Tray_Reconnect->setEnabled(true); + tray_SystemProxyMenu->setEnabled(true); lastConnectedId = id; locateBtn->setEnabled(true); on_clearlogButton_clicked(); @@ -907,5 +840,13 @@ void MainWindow::on_locateBtn_clicked() if (id != NullConnectionId) { connectionListWidget->setCurrentItem(connectionNodes[id].get()); + connectionListWidget->scrollToItem(connectionNodes[id].get()); + on_connectionListWidget_itemClicked(connectionNodes[id].get(), 0); } } + +void MainWindow::on_action_RCM_RenameThis_triggered() +{ + CheckCurrentWidget; + widget->BeginRename(); +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index f10d9cce..90e46ed6 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -37,7 +37,6 @@ class MainWindow void on_preferencesBtn_clicked(); void on_clearlogButton_clicked(); void on_connectionListWidget_customContextMenuRequested(const QPoint &pos); - void on_connectionListWidget_itemChanged(QTreeWidgetItem *item, int column); void on_removeConfigButton_clicked(); void on_importConfigButton_clicked(); void on_subsButton_clicked(); @@ -77,6 +76,7 @@ class MainWindow // void on_action_StartThis_triggered(); void on_action_RCM_ConvToComplex_triggered(); + void on_action_RCM_RenameThis_triggered(); // void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); void on_connectionFilterTxt_textEdited(const QString &arg1); diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index f2a3cf76..c369cdaf 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -494,232 +494,6 @@ - - - - 0 - 0 - 900 - 26 - - - - - File - - - - Import Connection - - - - - - - - - - - - - - - - - - Subscriptions - - - - Update Subscriptions - - - - - - - - - - - - Tools - - - - - - - - Help - - - - - - - - - - - - - - - - #ManuallyCreateConnection - - - - - #ImportConnection - - - - - #Exit - - - - - #Preferences - - - - - #Start - - - - - #Stop - - - - - #Restart - - - - - Import from vmess:// - - - - - Import from QRCode File - - - - - Import from ScreenShot - - - - - Open Configuration Folder - - - - - Exit - - - - - From File - - - - - From Connection Link - - - - - From QRCode File - - - - - Take ScreenShot - - - - - Open Connection Editor - - - - - Manually Create Connection - - - - - Manually Create Complex Connection - - - - - Copy Connection Link - - - - - Copy QRCode - - - - - Save QRCode to File - - - - - Open Subscription Manager - - - - - Update All Subscriptions - - - - - Update All Subscriptions with System Proxy - - - - - Options - - - - - About Qt - - - - - About Qv2ray - - - - - Help - - - - - Save Qv2ray Log - - - - - Json Editor - - diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index eca5af3b..4cc72f03 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -1,4 +1,5 @@ #include "w_PreferencesWindow.hpp" + #include "common/HTTPRequestHelper.hpp" #include "common/QvHelpers.hpp" #include "common/QvTranslator.hpp" @@ -1029,7 +1030,11 @@ void PreferencesWindow::on_autoStartSubsCombo_currentIndexChanged(const QString void PreferencesWindow::on_autoStartConnCombo_currentIndexChanged(const QString &arg1) { LOADINGCHECK - CurrentConfig.autoStartId = ConnectionManager->GetConnectionIdByDisplayName(arg1).toString(); + // Fully qualify the connection item. + // Will not work when duplicated names are in the same group. + CurrentConfig.autoStartId = + ConnectionManager->GetConnectionIdByDisplayName(arg1, ConnectionManager->GetGroupIdByDisplayName(autoStartSubsCombo->currentText())) + .toString(); } void PreferencesWindow::on_startWithLoginCB_stateChanged(int arg1) diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 20cc75bc..a1277a09 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -15,6 +15,10 @@ SubscribeEditor::SubscribeEditor(QWidget *parent) : QDialog(parent) { subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList{ ConnectionManager->GetDisplayName(subs), subs.toString() })); } + if (subscriptionList->topLevelItemCount() > 0) + { + subscriptionList->setCurrentItem(subscriptionList->topLevelItem(0)); + } } QvMessageBusSlotImpl(SubscribeEditor) diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index aa4e3400..61245060 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -14,8 +14,6 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) editJsonBtn->setIcon(QICON_R("json.png")); // shareLinkTxt->setAutoFillBackground(true); - shareLinkTxt->setStyleSheet("border-bottom: 1px solid gray; border-radius: 0px; padding: 2px; background-color: " + - this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); shareLinkTxt->setCursor(QCursor(Qt::CursorShape::IBeamCursor)); shareLinkTxt->installEventFilter(this); // @@ -25,7 +23,10 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) void ConnectionInfoWidget::ShowDetails(const tuple &_identifier) { - auto [groupId, connectionId] = _identifier; + shareLinkTxt->setStyleSheet("border-bottom: 1px solid gray; border-radius: 0px; padding: 2px; background-color: " + + this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); + this->groupId = get<0>(_identifier); + this->connectionId = get<1>(_identifier); bool isConnection = connectionId != NullConnectionId; // editBtn->setEnabled(isConnection); diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index bc813740..6b5083f9 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -381,9 +381,15 @@ + + IBeamCursor + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + @@ -395,9 +401,15 @@ + + IBeamCursor + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index afaf031b..71b30510 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -2,6 +2,8 @@ #include "common/QvHelpers.hpp" +#include + ConnectionItemWidget::ConnectionItemWidget(QWidget *parent) : QWidget(parent), connectionId("null"), groupId("null") { setupUi(this); @@ -16,7 +18,7 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare { connectionId = id; groupId = ConnectionManager->GetConnectionGroupId(id); - originalConnectionName = ConnectionManager->GetDisplayName(id); + originalItemName = ConnectionManager->GetDisplayName(id); itemType = NODE_ITEM; auto latency = ConnectionManager->GetConnectionLatency(id); @@ -39,7 +41,7 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare { emit RequestWidgetFocus(this); } - OnConnectionItemRenamed(id, "", originalConnectionName); + OnConnectionItemRenamed(id, "", originalItemName); connect(ConnectionManager, &QvConnectionHandler::OnConnectionRenamed, this, &ConnectionItemWidget::OnConnectionItemRenamed); } @@ -48,7 +50,7 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : { groupId = id; itemType = GROUP_HEADER_ITEM; - originalConnectionName = ConnectionManager->GetDisplayName(id); + originalItemName = ConnectionManager->GetDisplayName(id); RecalculateConnectionsCount(); // layout()->removeWidget(connTypeLabel); @@ -60,7 +62,7 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : font.setBold(true); connNameLabel->setFont(font); // - OnGroupItemRenamed(id, "", originalConnectionName); + OnGroupItemRenamed(id, "", originalItemName); connect(ConnectionManager, &QvConnectionHandler::OnConnectionCreated, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConnectionHandler::OnConnectionDeleted, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConnectionHandler::OnConnectionChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); @@ -86,7 +88,7 @@ void ConnectionItemWidget::OnConnected(const ConnectionId &id) { if (id == connectionId) { - connNameLabel->setText("• " + originalConnectionName); + connNameLabel->setText("• " + originalItemName); LOG(MODULE_UI, "OnConnected signal received for: " + id.toString()) emit RequestWidgetFocus(this); } @@ -96,7 +98,7 @@ void ConnectionItemWidget::OnDisConnected(const ConnectionId &id) { if (id == connectionId) { - connNameLabel->setText(originalConnectionName); + connNameLabel->setText(originalItemName); } } @@ -126,17 +128,37 @@ void ConnectionItemWidget::OnLatencyTestFinished(const ConnectionId &id, const u if (average == 0) { latencyLabel->setText(tr("Error")); - RED(latencyLabel) } else { latencyLabel->setText(QSTRN(average) + tr("ms")); - BLACK(latencyLabel) } } } +void ConnectionItemWidget::BeginRename() +{ + stackedWidget->setCurrentIndex(1); + renameTxt->setStyle(QStyleFactory::create("Fusion")); + renameTxt->setStyleSheet("background-color: " + this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); + renameTxt->setText(originalItemName); +} + ConnectionItemWidget::~ConnectionItemWidget() { - // +} + +void ConnectionItemWidget::on_doRenameBtn_clicked() +{ + if (renameTxt->text().isEmpty()) + return; + if (connectionId == NullConnectionId) + { + ConnectionManager->RenameGroup(groupId, renameTxt->text()); + } + else + { + ConnectionManager->RenameConnection(connectionId, renameTxt->text()); + } + stackedWidget->setCurrentIndex(0); } diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index 63f061f4..5267e82e 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -23,6 +23,7 @@ class ConnectionItemWidget void BeginConnection(); ~ConnectionItemWidget(); // + void BeginRename(); inline bool NameMatched(const QString &arg) { auto searchString = arg.toLower(); @@ -65,13 +66,13 @@ class ConnectionItemWidget { if (ConnectionManager->IsConnected(id)) { - connNameLabel->setText("• " + originalConnectionName); + connNameLabel->setText("• " + newName); } else { connNameLabel->setText(newName); } - originalConnectionName = newName; + originalItemName = newName; this->setToolTip(newName); } } @@ -79,14 +80,16 @@ class ConnectionItemWidget { if (id == groupId) { - originalConnectionName = newName; + originalItemName = newName; connNameLabel->setText(newName); this->setToolTip(newName); } } + void on_doRenameBtn_clicked(); + private: - QString originalConnectionName; + QString originalItemName; explicit ConnectionItemWidget(QWidget *parent = nullptr); ITEM_TYPE itemType; ConnectionId connectionId; diff --git a/src/ui/widgets/ConnectionItemWidget.ui b/src/ui/widgets/ConnectionItemWidget.ui index 2acc24d4..51f3a80d 100644 --- a/src/ui/widgets/ConnectionItemWidget.ui +++ b/src/ui/widgets/ConnectionItemWidget.ui @@ -6,14 +6,26 @@ 0 0 - 277 - 66 + 203 + 58 Form + + 0 + + + 0 + + + 0 + + + 0 + @@ -31,63 +43,124 @@ - - - 5 + + + 0 - - + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 6 + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + + + 11 + + + + Connection Name + + + + + + + 500ms + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Type: vmess + tls + ws + + + + + + + + 8 + + + + 0KB / 0KB + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + - - - - 11 - - - - Connection Name - - + - + - 500ms - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + OK - - - - - - - Type: vmess + tls + ws - - - - - - - - 8 - - - - 0KB / 0KB - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - + + From 93b7f9f4a8805b39fae25a0fb2385d131b89059e Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 2 Mar 2020 00:15:19 +0800 Subject: [PATCH 079/332] add: added more ui functionalities - 3 --- makespec/BUILDVERSION | 2 +- src/ui/widgets/ConnectionItemWidget.cpp | 10 +++++----- src/ui/widgets/ConnectionItemWidget.ui | 12 +++++++++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 7174ebd1..208a59c4 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4326 +4334 diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index 71b30510..c4ac3d4a 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -48,16 +48,16 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare // ======================================= Initialisation for root nodes. ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : ConnectionItemWidget(parent) { - groupId = id; - itemType = GROUP_HEADER_ITEM; - originalItemName = ConnectionManager->GetDisplayName(id); - RecalculateConnectionsCount(); - // layout()->removeWidget(connTypeLabel); layout()->removeWidget(dataLabel); delete connTypeLabel; delete dataLabel; // + groupId = id; + itemType = GROUP_HEADER_ITEM; + originalItemName = ConnectionManager->GetDisplayName(id); + RecalculateConnectionsCount(); + // auto font = connNameLabel->font(); font.setBold(true); connNameLabel->setFont(font); diff --git a/src/ui/widgets/ConnectionItemWidget.ui b/src/ui/widgets/ConnectionItemWidget.ui index 51f3a80d..ea22eb3e 100644 --- a/src/ui/widgets/ConnectionItemWidget.ui +++ b/src/ui/widgets/ConnectionItemWidget.ui @@ -7,7 +7,7 @@ 0 0 203 - 58 + 60 @@ -49,6 +49,9 @@ + + QLayout::SetNoConstraint + 0 @@ -61,6 +64,9 @@ 0 + + 0 + @@ -70,13 +76,13 @@ 6 - 6 + 7 6 - 6 + 7 From d4be3a987ef3bfa0efba338045671d289dc4ca9e Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 2 Mar 2020 07:25:08 +0800 Subject: [PATCH 080/332] fix: fixed #387 --- src/core/kernel/APIBackend.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/core/kernel/APIBackend.cpp b/src/core/kernel/APIBackend.cpp index 3f7b0823..19c67f57 100644 --- a/src/core/kernel/APIBackend.cpp +++ b/src/core/kernel/APIBackend.cpp @@ -57,12 +57,7 @@ namespace Qv2ray::core::kernel // Set started signal to false and wait for API thread to stop. started = false; thread->wait(); - - // Although thread shouldnot be null, we'll add this check to be safe. - if (thread) - { - delete thread; - } + delete thread; } // API Core Operations From 36e8586f0f3d880a335bb3593303bcca72536616 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 2 Mar 2020 20:59:40 +0800 Subject: [PATCH 081/332] fix: fixed autostart settings --- makespec/BUILDVERSION | 2 +- src/ui/w_PreferencesWindow.cpp | 38 +++++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 208a59c4..f60afa77 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4334 +4340 diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index 4cc72f03..6b0beff5 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -1016,25 +1016,39 @@ void PreferencesWindow::on_pacProxyTxt_textEdited(const QString &arg1) void PreferencesWindow::on_autoStartSubsCombo_currentIndexChanged(const QString &arg1) { - LOADINGCHECK - auto groupId = ConnectionManager->GetGroupIdByDisplayName(arg1); - auto list = ConnectionManager->Connections(groupId); - autoStartConnCombo->clear(); - - for (auto id : list) + LOADINGCHECK if (arg1.isEmpty()) { - autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(id)); + CurrentConfig.autoStartId.clear(); + autoStartConnCombo->clear(); + } + else + { + auto groupId = ConnectionManager->GetGroupIdByDisplayName(arg1); + auto list = ConnectionManager->Connections(groupId); + autoStartConnCombo->clear(); + + for (auto id : list) + { + autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(id)); + } } } void PreferencesWindow::on_autoStartConnCombo_currentIndexChanged(const QString &arg1) { LOADINGCHECK - // Fully qualify the connection item. - // Will not work when duplicated names are in the same group. - CurrentConfig.autoStartId = - ConnectionManager->GetConnectionIdByDisplayName(arg1, ConnectionManager->GetGroupIdByDisplayName(autoStartSubsCombo->currentText())) - .toString(); + if (arg1.isEmpty()) + { + CurrentConfig.autoStartId.clear(); + } + else + { + // Fully qualify the connection item. + // Will not work when duplicated names are in the same group. + CurrentConfig.autoStartId = + ConnectionManager->GetConnectionIdByDisplayName(arg1, ConnectionManager->GetGroupIdByDisplayName(autoStartSubsCombo->currentText())) + .toString(); + } } void PreferencesWindow::on_startWithLoginCB_stateChanged(int arg1) From 11275e1c9ebb4e6683e998c3419efb3aa1265d97 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 2 Mar 2020 21:11:14 +0800 Subject: [PATCH 082/332] add: added multiple connection deletion support --- makespec/BUILDVERSION | 2 +- src/ui/w_MainWindow.cpp | 123 ++++++++++++---------------------------- src/ui/w_MainWindow.hpp | 2 +- 3 files changed, 39 insertions(+), 88 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index f60afa77..9a910c68 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4340 +4349 diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index b633eb71..eb9ca4f1 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -163,11 +163,13 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h // QAction *action_RCM_StartThis = new QAction(tr("Connect to this"), this); QAction *action_RCM_RenameThis = new QAction(tr("Rename"), this); + QAction *action_RCM_DeleteThese = new QAction(tr("Delete Connection"), this); QAction *action_RCM_ConvToComplex = new QAction(QICON_R("edit.png"), tr("Edit as Complex Config"), this); // connect(action_RCM_StartThis, &QAction::triggered, this, &MainWindow::on_action_StartThis_triggered); connect(action_RCM_ConvToComplex, &QAction::triggered, this, &MainWindow::on_action_RCM_ConvToComplex_triggered); connect(action_RCM_RenameThis, &QAction::triggered, this, &MainWindow::on_action_RCM_RenameThis_triggered); + connect(action_RCM_DeleteThese, &QAction::triggered, this, &MainWindow::on_action_RCM_DeleteThese_triggered); // // Globally invokable signals. connect(this, &MainWindow::Connect, [&] { ConnectionManager->StartConnection(lastConnectedId); }); @@ -180,6 +182,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h connectionListMenu = new QMenu(this); connectionListMenu->addAction(action_RCM_StartThis); connectionListMenu->addAction(action_RCM_RenameThis); + connectionListMenu->addAction(action_RCM_DeleteThese); connectionListMenu->addAction(action_RCM_ConvToComplex); // LOG(MODULE_UI, "Loading data...") @@ -400,94 +403,42 @@ void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint } } -void MainWindow::on_removeConfigButton_clicked() +void MainWindow::on_action_RCM_DeleteThese_triggered() { QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - // QList connlist; - // - // for (auto item : connectionListWidget->selectedItems()) { - // if (IsConnectableItem(item)) { - // connlist.append(ItemConnectionIdentifier(item)); - // } - //} - // - // LOG(UI, "Selected " + QSTRN(connlist.count()) + " items") - // - // if (connlist.isEmpty()) { - // // Remove nothing means doing nothing. - // return; - //} - // - // if (QvMessageBoxAsk(this, tr("Removing Connection(s)"), tr("Are you sure - // to remove selected connection(s)?")) != QMessageBox::Yes) { - // return; - //} - // - //// A triple-state flag which indicates if the user wants to remove the - /// configs loaded from a subscription. - // int subscriptionRemovalCheckStatus = -1; - // - // for (auto conn : connlist) { - // if (conn == CurrentConnectionIdentifier) { - // on_stopButton_clicked(); - // CurrentConnectionIdentifier = ConnectionIdentifier(); - // } - // - // auto connData = connections[conn]; - // - // // Remove auto start config. - // if (GlobalConfig.autoStartConfig.subscriptionName == - // connData.subscriptionName && - // GlobalConfig.autoStartConfig.connectionName == - // connData.connectionName) - // // If all those settings match. - // { - // GlobalConfig.autoStartConfig.subscriptionName.clear(); - // GlobalConfig.autoStartConfig.connectionName.clear(); - // } - // - // if (connData.configType == CONNECTION_REGULAR) { - // // Just remove the regular configs. - // if (!connData.subscriptionName.isEmpty()) { - // LOG(UI, "Unexpected subscription name in a single regular - // config.") connData.subscriptionName.clear(); - // } - // - // GlobalConfig.configs.removeOne(conn.connectionName); - // - // if (!RemoveConnection(conn.connectionName)) { - // QvMessageBoxWarn(this, tr("Removing this Connection"), - // tr("Failed to delete connection file, please delete - // manually.")); - // } - // } else if (connData.configType == CONNECTION_SUBSCRIPTION) { - // if (subscriptionRemovalCheckStatus == -1) { - // subscriptionRemovalCheckStatus = (QvMessageBoxAsk(this, - // tr("Removing a subscription config"), tr("Do you want to - // remove the config loaded from a subscription?")) == - // QMessageBox::Yes) - // ? 1 // Yes i want - // : 0; // No please keep - // } - // - // if (subscriptionRemovalCheckStatus == 1) { - // if (!RemoveSubscriptionConnection(connData.subscriptionName, - // connData.connectionName)) { - // QvMessageBoxWarn(this, tr("Removing this Connection"), - // tr("Failed to delete connection file, please delete - // manually.")); - // } - // } - // } else { - // LOG(SETTINGS, "Unknown config type -> Not regular nor - // subscription...") - // } - //} - // - // LOG(UI, "Saving GlobalConfig") - // SaveGlobalConfig(GlobalConfig); - // OnConfigListChanged(false); - // ShowAndSetConnection(CurrentConnectionIdentifier, false, false); + QList connlist; + + for (auto item : connectionListWidget->selectedItems()) + { + auto widget = GetItemWidget(item); + if (widget->IsConnection()) + { + connlist.append(get<1>(widget->Identifier())); + } + } + + LOG(MODULE_UI, "Selected " + QSTRN(connlist.count()) + " items") + + if (connlist.isEmpty()) + { + // Remove nothing means doing nothing. + return; + } + + if (QvMessageBoxAsk(this, tr("Removing Connection(s)"), tr("Are you sure to remove selected connection(s)?")) != QMessageBox::Yes) + { + return; + } + + for (auto conn : connlist) + { + if (ConnectionManager->IsConnected(conn)) + ConnectionManager->StopConnection(); + if (GlobalConfig.autoStartId == conn.toString()) + GlobalConfig.autoStartId.clear(); + + ConnectionManager->DeleteConnection(conn); + } } void MainWindow::on_importConfigButton_clicked() diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 90e46ed6..d08f0422 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -37,7 +37,6 @@ class MainWindow void on_preferencesBtn_clicked(); void on_clearlogButton_clicked(); void on_connectionListWidget_customContextMenuRequested(const QPoint &pos); - void on_removeConfigButton_clicked(); void on_importConfigButton_clicked(); void on_subsButton_clicked(); // @@ -77,6 +76,7 @@ class MainWindow void on_action_StartThis_triggered(); void on_action_RCM_ConvToComplex_triggered(); void on_action_RCM_RenameThis_triggered(); + void on_action_RCM_DeleteThese_triggered(); // void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); void on_connectionFilterTxt_textEdited(const QString &arg1); From 3df2cea74b5078a90ce08f57117e66402948e66d Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 3 Mar 2020 00:34:12 +0800 Subject: [PATCH 083/332] add: added multiple duplicate and sorting support --- assets/icons/ui_dark/design/sort.svg | 1 + assets/icons/ui_dark/sort.png | Bin 0 -> 304 bytes assets/icons/ui_light/design/sort.svg | 1 + assets/icons/ui_light/sort.png | Bin 0 -> 303 bytes makespec/BUILDVERSION | 2 +- resources.qrc | 2 + src/core/handler/ConnectionHandler.cpp | 14 ++- src/core/handler/ConnectionHandler.hpp | 3 +- src/ui/w_MainWindow.cpp | 108 +++++++++++++++++++++--- src/ui/w_MainWindow.hpp | 20 +++++ src/ui/w_MainWindow.ui | 105 +++++++++++++---------- src/ui/widgets/ConnectionInfoWidget.cpp | 23 ++--- src/ui/widgets/ConnectionInfoWidget.hpp | 8 +- src/ui/widgets/ConnectionInfoWidget.ui | 103 ++++++++++------------ 14 files changed, 253 insertions(+), 137 deletions(-) create mode 100644 assets/icons/ui_dark/design/sort.svg create mode 100644 assets/icons/ui_dark/sort.png create mode 100644 assets/icons/ui_light/design/sort.svg create mode 100644 assets/icons/ui_light/sort.png diff --git a/assets/icons/ui_dark/design/sort.svg b/assets/icons/ui_dark/design/sort.svg new file mode 100644 index 00000000..689c8367 --- /dev/null +++ b/assets/icons/ui_dark/design/sort.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/ui_dark/sort.png b/assets/icons/ui_dark/sort.png new file mode 100644 index 0000000000000000000000000000000000000000..046e1c7eb16f326fa013742c39b0e3e7077a2cef GIT binary patch literal 304 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRS-#uL%Ln`LHy>&5{*-(Vpv3y#| zyb$H7iQ$D22j(zFH2nCn@;WzA9WwY)^?c6ul9liC8Q3mN-!SLbKehyhTF%qh1q%Kx z^{%alYTtKx@Aq`e(*HYux%_$%Y9D}SHAV!pES_xY>rD}ukz zU(Fw|{GENc`~ttb_3P{$5E`oAzb|_Aj}c<%1J37j_8Wcu{ru-d<8uthBoA0HOQbVA q=1G{t*kjyK$YyX3+3jHVyswP=`ko|jVJ~3^@jYGrT-G@yGywp(m3Zp_ literal 0 HcmV?d00001 diff --git a/assets/icons/ui_light/design/sort.svg b/assets/icons/ui_light/design/sort.svg new file mode 100644 index 00000000..f189441b --- /dev/null +++ b/assets/icons/ui_light/design/sort.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/ui_light/sort.png b/assets/icons/ui_light/sort.png new file mode 100644 index 0000000000000000000000000000000000000000..89e6121b2ca43205ed1633ac2d540ada2c7c470b GIT binary patch literal 303 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRS-#lF$Ln`LHy>-yn#ZkcdAn%HL zo(YyIY=LX$ZCN)-=D?2HIoG*?>X5;Yit_L3v9EqhH!yxt)mgr8Kcj?0{GlT30(aJz ztbET8(S9JkYTol~%hLZlf4Te2-St1Fw!sR-VJLm|ulOtDt1Ew>zhb_!^7r|x>??x5 z&tJ_Su>75UxcmaYyY=hr91t3I|Bmy!YY%nOp2K(lPFZ>1{(S$OLNassets/icons/ui_light/stop.png assets/icons/ui_dark/locate.png assets/icons/ui_light/locate.png + assets/icons/ui_dark/sort.png + assets/icons/ui_light/sort.png diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index a3ea4bdb..d23e0ae8 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -227,14 +227,24 @@ namespace Qv2ray::core::handlers return connections[id].groupId; } - double QvConnectionHandler::GetConnectionLatency(const ConnectionId &id) const + uint64_t QvConnectionHandler::GetConnectionTotalData(const ConnectionId &id) const { if (!connections.contains(id)) { LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); } - return connections[id].latency; + return connections[id].upLinkData + connections[id].downLinkData; + } + + int64_t QvConnectionHandler::GetConnectionLatency(const ConnectionId &id) const + { + if (!connections.contains(id)) + { + LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); + } + + return max(connections[id].latency, 0L); } const optional QvConnectionHandler::RenameConnection(const ConnectionId &id, const QString &newName) { diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConnectionHandler.hpp index b2aad268..b431fe86 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConnectionHandler.hpp @@ -64,7 +64,8 @@ namespace Qv2ray::core::handlers const QString GetConnectionProtocolString(const ConnectionId &id) const; const CONFIGROOT GetConnectionRoot(const ConnectionId &id) const; const CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id) const; - double GetConnectionLatency(const ConnectionId &id) const; + int64_t GetConnectionLatency(const ConnectionId &id) const; + uint64_t GetConnectionTotalData(const ConnectionId &id) const; const tuple GetConnectionUsageAmount(const ConnectionId &id) const; // // Misc Connection Operations diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index eb9ca4f1..dfa85f96 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -26,15 +26,14 @@ #include #include -// MainWindow.cpp --> Main MainWindow source file, handles mostly UI-related -// operations. - #define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING #define CheckCurrentWidget \ auto widget = GetItemWidget(connectionListWidget->currentItem()); \ if (widget == nullptr) \ return; + #define GetItemWidget(item) (qobject_cast(connectionListWidget->itemWidget(item, 0))) +#define NumericString(i) (QString("%1").arg(i, 15, 10, QLatin1Char('0'))) MainWindow *MainWindow::mwInstance = nullptr; @@ -53,7 +52,14 @@ void MainWindow::MWAddConnectionItem_p(const ConnectionId &connection, const Gro MWAddGroupItem_p(groupId); } auto groupItem = groupNodes[groupId]; - auto connectionItem = make_shared(QStringList{ "", ConnectionManager->GetDisplayName(connection) }); + auto connectionItem = make_shared(QStringList{ + "", // + ConnectionManager->GetDisplayName(connection), // + NumericString(ConnectionManager->GetConnectionLatency(connection)), // + "IMPORTTIME_NOT_SUPPORTED", // + "LAST_CONNECTED_NOT_SUPPORTED", // + NumericString(ConnectionManager->GetConnectionTotalData(connection)) // + }); connectionNodes[connection] = connectionItem; groupItem->addChild(connectionItem.get()); auto widget = new ConnectionItemWidget(connection, connectionListWidget); @@ -69,6 +75,16 @@ void MainWindow::MWAddGroupItem_p(const GroupId &groupId) connectionListWidget->setItemWidget(groupItem.get(), 0, new ConnectionItemWidget(groupId, connectionListWidget)); } +void MainWindow::SortConnectionList(MW_ITEM_COL byCol, bool asending) +{ + + connectionListWidget->sortByColumn(MW_ITEM_COL_DISPLAYNAME, Qt::AscendingOrder); + for (auto i = 0; i < connectionListWidget->topLevelItemCount(); i++) + { + connectionListWidget->topLevelItem(i)->sortChildren(byCol, asending ? Qt::AscendingOrder : Qt::DescendingOrder); + } +} + MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), hTray(this), tcpingHelper(3, this) { setupUi(this); @@ -82,11 +98,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h // For charts speedChartWidget = new SpeedWidget(this); speedChart->addWidget(speedChartWidget); + // this->setWindowIcon(QIcon(":/assets/icons/qv2ray.png")); hTray.setIcon(QIcon(GlobalConfig.uiConfig.useDarkTrayIcon ? ":/assets/icons/ui_dark/tray.png" : ":/assets/icons/ui_light/tray.png")); + // importConfigButton->setIcon(QICON_R("import.png")); - // pingTestBtn->setIcon(QICON_R("ping_gauge.png")); - // shareBtn->setIcon(QICON_R("share.png")); updownImageBox->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); updownImageBox_2->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); // @@ -109,7 +125,13 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h // connect(ConnectionManager, &QvConnectionHandler::OnGroupCreated, this, &MainWindow::OnGroupCreated); connect(ConnectionManager, &QvConnectionHandler::OnGroupDeleted, this, &MainWindow::OnGroupDeleted); - + // + connect(ConnectionManager, &QvConnectionHandler::OnConnectionRenamed, [&](const ConnectionId &id, const QString &, const QString &newName) { + connectionNodes[id]->setText(MW_ITEM_COL_DISPLAYNAME, newName); // + }); + connect(ConnectionManager, &QvConnectionHandler::OnLatencyTestFinished, [&](const ConnectionId &id, const uint avg) { + connectionNodes[id]->setText(MW_ITEM_COL_LATENCY, NumericString(avg)); // + }); // connect(infoWidget, &ConnectionInfoWidget::OnEditRequested, this, &MainWindow::OnEditRequested); connect(infoWidget, &ConnectionInfoWidget::OnJsonEditRequested, this, &MainWindow::OnJsonEditRequested); @@ -164,12 +186,14 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h QAction *action_RCM_StartThis = new QAction(tr("Connect to this"), this); QAction *action_RCM_RenameThis = new QAction(tr("Rename"), this); QAction *action_RCM_DeleteThese = new QAction(tr("Delete Connection"), this); + QAction *action_RCM_DuplicateThese = new QAction(QICON_R("duplicate.png"), tr("Duplicate to the Same Group"), this); QAction *action_RCM_ConvToComplex = new QAction(QICON_R("edit.png"), tr("Edit as Complex Config"), this); // connect(action_RCM_StartThis, &QAction::triggered, this, &MainWindow::on_action_StartThis_triggered); connect(action_RCM_ConvToComplex, &QAction::triggered, this, &MainWindow::on_action_RCM_ConvToComplex_triggered); connect(action_RCM_RenameThis, &QAction::triggered, this, &MainWindow::on_action_RCM_RenameThis_triggered); connect(action_RCM_DeleteThese, &QAction::triggered, this, &MainWindow::on_action_RCM_DeleteThese_triggered); + connect(action_RCM_DuplicateThese, &QAction::triggered, this, &MainWindow::on_action_RCM_DuplicateThese_triggered); // // Globally invokable signals. connect(this, &MainWindow::Connect, [&] { ConnectionManager->StartConnection(lastConnectedId); }); @@ -182,11 +206,35 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h connectionListMenu = new QMenu(this); connectionListMenu->addAction(action_RCM_StartThis); connectionListMenu->addAction(action_RCM_RenameThis); + connectionListMenu->addAction(action_RCM_DuplicateThese); connectionListMenu->addAction(action_RCM_DeleteThese); connectionListMenu->addAction(action_RCM_ConvToComplex); // - LOG(MODULE_UI, "Loading data...") - auto groups = ConnectionManager->AllGroups(); + sortMenu = new QMenu(this); + sortAction_SortByName_Asc = new QAction(tr("By connection name, A-Z")); + sortAction_SortByName_Dsc = new QAction(tr("By connection name, Z-A")); + sortAction_SortByData_Asc = new QAction(tr("By data, Less to more")); + sortAction_SortByData_Dsc = new QAction(tr("By data, More to less")); + sortAction_SortByLatency_Asc = new QAction(tr("By latency, Short to long")); + sortAction_SortByLatency_Dsc = new QAction(tr("By latency, Long to short")); + // + connect(sortAction_SortByName_Asc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DISPLAYNAME, true); }); + connect(sortAction_SortByName_Dsc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DISPLAYNAME, false); }); + connect(sortAction_SortByData_Asc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DATAUSAGE, true); }); + connect(sortAction_SortByData_Dsc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DATAUSAGE, false); }); + connect(sortAction_SortByLatency_Asc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_LATENCY, true); }); + connect(sortAction_SortByLatency_Dsc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_LATENCY, false); }); + // + sortMenu->addAction(sortAction_SortByName_Asc); + sortMenu->addAction(sortAction_SortByName_Dsc); + sortMenu->addAction(sortAction_SortByData_Asc); + sortMenu->addAction(sortAction_SortByData_Dsc); + sortMenu->addAction(sortAction_SortByLatency_Asc); + sortMenu->addAction(sortAction_SortByLatency_Dsc); + // + sortBtn->setMenu(sortMenu); + // + LOG(MODULE_UI, "Loading data...") auto groups = ConnectionManager->AllGroups(); for (auto group : groups) { @@ -405,7 +453,6 @@ void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint void MainWindow::on_action_RCM_DeleteThese_triggered() { - QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); QList connlist; for (auto item : connectionListWidget->selectedItems()) @@ -678,8 +725,11 @@ void MainWindow::OnStatsAvailable(const ConnectionId &id, const quint64 upS, con netspeedLabel->setText(totalSpeedUp + NEWLINE + totalSpeedDown); dataamountLabel->setText(totalDataUp + NEWLINE + totalDataDown); // - hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + ConnectionManager->GetDisplayName(id) + NEWLINE "Up: " + totalSpeedUp + - " Down: " + totalSpeedDown); + hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + // + ConnectionManager->GetDisplayName(id) + NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); + // + // Set data accordingly + connectionNodes[id]->setText(MW_ITEM_COL_DATAUSAGE, NumericString(ConnectionManager->GetConnectionTotalData(id))); } void MainWindow::OnVCoreLogAvailable(const ConnectionId &id, const QString &log) @@ -801,3 +851,37 @@ void MainWindow::on_action_RCM_RenameThis_triggered() CheckCurrentWidget; widget->BeginRename(); } + +void MainWindow::on_action_RCM_DuplicateThese_triggered() +{ + QList connlist; + + for (auto item : connectionListWidget->selectedItems()) + { + auto widget = GetItemWidget(item); + if (widget->IsConnection()) + { + connlist.append(get<1>(widget->Identifier())); + } + } + + LOG(MODULE_UI, "Selected " + QSTRN(connlist.count()) + " items") + + if (connlist.isEmpty()) + { + return; + } + + if (connlist.count() > 1 && + QvMessageBoxAsk(this, tr("Duplicating Connection(s)"), tr("Are you sure to duplicate these connection(s)?")) != QMessageBox::Yes) + { + return; + } + + for (auto conn : connlist) + { + ConnectionManager->CreateConnection(ConnectionManager->GetDisplayName(conn) + tr(" (Copy)"), // + ConnectionManager->GetConnectionGroupId(conn), // + ConnectionManager->GetConnectionRoot(conn)); + } +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index d08f0422..185f29b2 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -17,6 +17,15 @@ #include "ui/widgets/ConnectionInfoWidget.hpp" #include "ui/widgets/ConnectionItemWidget.hpp" +enum MW_ITEM_COL +{ + MW_ITEM_COL_DISPLAYNAME = 1, + MW_ITEM_COL_LATENCY = 2, + MW_ITEM_COL_IMPORTTIME = 3, + MW_ITEM_COL_LASTCONNETED = 4, + MW_ITEM_COL_DATAUSAGE = 5 +}; + class MainWindow : public QMainWindow , Ui::MainWindow @@ -77,11 +86,14 @@ class MainWindow void on_action_RCM_ConvToComplex_triggered(); void on_action_RCM_RenameThis_triggered(); void on_action_RCM_DeleteThese_triggered(); + void on_action_RCM_DuplicateThese_triggered(); // void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); void on_connectionFilterTxt_textEdited(const QString &arg1); void on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column); void on_locateBtn_clicked(); + // + void SortConnectionList(MW_ITEM_COL byCol, bool asending); private: QHash> groupNodes; @@ -115,6 +127,14 @@ class MainWindow QAction *action_Tray_SetSystemProxy; QAction *action_Tray_ClearSystemProxy; // + QMenu *sortMenu; + QAction *sortAction_SortByName_Asc; + QAction *sortAction_SortByName_Dsc; + QAction *sortAction_SortByLatency_Asc; + QAction *sortAction_SortByLatency_Dsc; + QAction *sortAction_SortByData_Asc; + QAction *sortAction_SortByData_Dsc; + // // Extra Headers For w_MainWindow_extra.cpp Handling V2ray Connectivities. ConnectionId lastConnectedId; void MWSetSystemProxy(); diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index c369cdaf..2596a71a 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -86,16 +86,6 @@ - - - - Search - - - true - - - @@ -113,43 +103,14 @@ - - - - Qt::CustomContextMenu + + + + Search - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::ExtendedSelection - - - QAbstractItemView::ScrollPerPixel - - - 0 - - + true - - true - - - true - - - true - - - true - - - - 1 - - @@ -204,6 +165,62 @@ + + + + + + + + :/assets/icons/ui_light/sort.png:/assets/icons/ui_light/sort.png + + + QToolButton::InstantPopup + + + + + + + Qt::CustomContextMenu + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::ScrollPerPixel + + + 0 + + + true + + + true + + + true + + + true + + + true + + + false + + + + 1 + + + + diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 61245060..07ea8cdd 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -8,7 +8,6 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) { setupUi(this); - duplicateBtn->setIcon(QICON_R("duplicate.png")); deleteBtn->setIcon(QICON_R("delete.png")); editBtn->setIcon(QICON_R("edit.png")); editJsonBtn->setIcon(QICON_R("json.png")); @@ -32,20 +31,24 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden editBtn->setEnabled(isConnection); editJsonBtn->setEnabled(isConnection); connectBtn->setEnabled(isConnection); - duplicateBtn->setEnabled(isConnection); stackedWidget->setCurrentIndex(isConnection ? 0 : 1); if (isConnection) { + bool isComplexConfig = IsComplexConfig(ConnectionManager->GetConnectionRoot(connectionId)); + qrLabel->setVisible(!isComplexConfig); + // + auto shareLink = ConvertConfigToString(connectionId); + // + shareLinkTxt->setText(isComplexConfig ? tr("(Complex Connection Config)") : shareLink); + protocolLabel->setText(isComplexConfig ? tr("N/A") : ConnectionManager->GetConnectionProtocolString(connectionId)); + // groupLabel->setText(ConnectionManager->GetDisplayName(groupId, 175)); - protocolLabel->setText(ConnectionManager->GetConnectionProtocolString(connectionId)); auto [protocol, host, port] = ConnectionManager->GetConnectionData(connectionId); Q_UNUSED(protocol) addressLabel->setText(host); portLabel->setNum(port); // - auto shareLink = ConvertConfigToString(connectionId); - shareLinkTxt->setText(shareLink); shareLinkTxt->setCursorPosition(0); // QZXingEncoderConfig conf; @@ -145,16 +148,6 @@ void ConnectionInfoWidget::OnDisConnected(const ConnectionId &id) } } -void ConnectionInfoWidget::on_duplicateBtn_clicked() -{ - if (connectionId != NullConnectionId) - { - ConnectionManager->CreateConnection(ConnectionManager->GetDisplayName(connectionId) + tr(" (Copy)"), - ConnectionManager->GetConnectionGroupId(connectionId), - ConnectionManager->GetConnectionRoot(connectionId)); - } -} - void ConnectionInfoWidget::on_latencyBtn_clicked() { if (connectionId != NullConnectionId) diff --git a/src/ui/widgets/ConnectionInfoWidget.hpp b/src/ui/widgets/ConnectionInfoWidget.hpp index 2d87e0e8..43cf1958 100644 --- a/src/ui/widgets/ConnectionInfoWidget.hpp +++ b/src/ui/widgets/ConnectionInfoWidget.hpp @@ -20,19 +20,17 @@ class ConnectionInfoWidget void OnEditRequested(const ConnectionId &id); void OnJsonEditRequested(const ConnectionId &id); + protected: + bool eventFilter(QObject *object, QEvent *event) override; + private slots: void on_connectBtn_clicked(); void on_editBtn_clicked(); void on_editJsonBtn_clicked(); void on_deleteBtn_clicked(); - protected: - bool eventFilter(QObject *object, QEvent *event) override; - - private slots: void OnConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id); - void on_duplicateBtn_clicked(); void on_latencyBtn_clicked(); private: diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index 6b5083f9..ec1cdb52 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -58,6 +58,48 @@ + + + + Connect/Disconnect + + + + + + + :/assets/icons/ui_light/connect.png:/assets/icons/ui_light/connect.png + + + + + + + Edit Connection + + + + + + + :/assets/icons/ui_light/edit.png:/assets/icons/ui_light/edit.png + + + + + + + Edit Connection as JSON + + + + + + + :/assets/icons/ui_light/json.png:/assets/icons/ui_light/json.png + + + @@ -86,62 +128,6 @@ - - - - Edit Connection as JSON - - - - - - - :/assets/icons/ui_light/json.png:/assets/icons/ui_light/json.png - - - - - - - Edit Connection - - - - - - - :/assets/icons/ui_light/edit.png:/assets/icons/ui_light/edit.png - - - - - - - Duplicate Connection - - - - - - - :/assets/icons/ui_light/duplicate.png:/assets/icons/ui_light/duplicate.png - - - - - - - Connect/Disconnect - - - - - - - :/assets/icons/ui_light/connect.png:/assets/icons/ui_light/connect.png - - - @@ -264,7 +250,7 @@ - + Link @@ -323,6 +309,9 @@ QR Code + + QFrame::Box + From 41b84207cc131e31fb663db4c1a4325d4cbe0634 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 3 Mar 2020 00:39:04 +0800 Subject: [PATCH 084/332] fix: use better explainations in the sort menu --- makespec/BUILDVERSION | 2 +- src/ui/w_MainWindow.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index e6a49d5d..75df1256 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4385 +4386 diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index dfa85f96..c91757ef 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -213,10 +213,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h sortMenu = new QMenu(this); sortAction_SortByName_Asc = new QAction(tr("By connection name, A-Z")); sortAction_SortByName_Dsc = new QAction(tr("By connection name, Z-A")); - sortAction_SortByData_Asc = new QAction(tr("By data, Less to more")); - sortAction_SortByData_Dsc = new QAction(tr("By data, More to less")); - sortAction_SortByLatency_Asc = new QAction(tr("By latency, Short to long")); - sortAction_SortByLatency_Dsc = new QAction(tr("By latency, Long to short")); + sortAction_SortByData_Asc = new QAction(tr("By data, Ascending")); + sortAction_SortByData_Dsc = new QAction(tr("By data, Descending")); + sortAction_SortByLatency_Asc = new QAction(tr("By latency, Ascending")); + sortAction_SortByLatency_Dsc = new QAction(tr("By latency, Descending")); // connect(sortAction_SortByName_Asc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DISPLAYNAME, true); }); connect(sortAction_SortByName_Dsc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DISPLAYNAME, false); }); From ac5cb7c67e5235e70b6cdd0dafc3f63aff006922 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Mon, 2 Mar 2020 20:15:48 +0800 Subject: [PATCH 085/332] [fix] lastUpdated after updating subscription --- src/core/handler/ConnectionHandler.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index d23e0ae8..88ec3d63 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -648,7 +648,10 @@ namespace Qv2ray::core::handlers LOG(MODULE_CORE_HANDLER, "Removing: " + conn.toString()) DeleteConnection(conn); } - + + // Update the time + groups[id].lastUpdated = system_clock::to_time_t(system_clock::now()); + return hasErrorOccured; } From 75736e7c44d0fbea5511a46b7112710871bb8a25 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 3 Mar 2020 13:18:01 +0800 Subject: [PATCH 086/332] fix: fixed cross-platform build --- makespec/BUILDVERSION | 2 +- src/core/handler/ConnectionHandler.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 75df1256..38e1efbb 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4386 +4387 diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index 88ec3d63..3f60be91 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -244,7 +244,7 @@ namespace Qv2ray::core::handlers LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); } - return max(connections[id].latency, 0L); + return max(connections[id].latency, (int64_t) 0); } const optional QvConnectionHandler::RenameConnection(const ConnectionId &id, const QString &newName) { From 9d05be94b6153dce7c676f3afd937c5d695a2636 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 3 Mar 2020 21:51:37 +0800 Subject: [PATCH 087/332] fix: fixed a segfault on right click menu --- makespec/BUILDVERSION | 2 +- src/ui/w_MainWindow.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 38e1efbb..9e10b4b6 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4387 +4390 diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index c91757ef..2b639a7e 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -444,10 +444,12 @@ void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint Q_UNUSED(pos) auto _pos = QCursor::pos(); auto item = connectionListWidget->itemAt(connectionListWidget->mapFromGlobal(_pos)); - - if (GetItemWidget(item)->IsConnection()) + if (item != nullptr) { - connectionListMenu->popup(_pos); + if (GetItemWidget(item)->IsConnection()) + { + connectionListMenu->popup(_pos); + } } } From 86193ee0b7ca0226e7a19a8d4c0117ee7db8f2a8 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 3 Mar 2020 22:39:20 +0800 Subject: [PATCH 088/332] add: added MainWindow items folding --- makespec/BUILDVERSION | 2 +- src/core/handler/ConnectionHandler.cpp | 8 +- src/ui/w_MainWindow.ui | 158 +++++++++++++++---------- 3 files changed, 100 insertions(+), 68 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 9e10b4b6..31bd1cc7 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4390 +4395 diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index 3f60be91..dc8bd703 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -389,6 +389,10 @@ namespace Qv2ray::core::handlers } CONFIGROOT root = GetConnectionRoot(connections[id].groupId, id); + if (IsComplexConfig(root)) + { + return tr("Complex config"); + } QStringList protocols; QStringList streamProtocols; auto outbound = root["outbounds"].toArray().first().toObject(); @@ -648,10 +652,10 @@ namespace Qv2ray::core::handlers LOG(MODULE_CORE_HANDLER, "Removing: " + conn.toString()) DeleteConnection(conn); } - + // Update the time groups[id].lastUpdated = system_clock::to_time_t(system_clock::now()); - + return hasErrorOccured; } diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 2596a71a..f52ba91b 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -242,7 +242,7 @@ 0 0 480 - 768 + 551 @@ -285,18 +285,6 @@ - - - - - 13 - - - - Speed Graph - - - @@ -305,39 +293,104 @@ - - - - 0 - 200 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - + 13 - - Log + + 1 + + + + 0 + -9 + 450 + 218 + + + + Speed Graph + + + + + + + 0 + 200 + + + + + 10 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 0 + -45 + 450 + 254 + + + + Log + + + + + + + 0 + 200 + + + + + 9 + + + + QTextEdit::NoWrap + + + + + + + + 10 + + + + Clear Log + + + + + @@ -347,31 +400,6 @@ - - - - - 0 - 200 - - - - - 9 - - - - QTextEdit::NoWrap - - - - - - - Clear Log - - - From bdd9db005f6fedc88829978e349244ebd890521d Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 4 Mar 2020 11:13:46 +0800 Subject: [PATCH 089/332] Revert "add: added MainWindow items folding" This reverts commit 86193ee0b7ca0226e7a19a8d4c0117ee7db8f2a8. --- makespec/BUILDVERSION | 2 +- src/core/handler/ConnectionHandler.cpp | 8 +- src/ui/w_MainWindow.ui | 158 ++++++++++--------------- 3 files changed, 68 insertions(+), 100 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 31bd1cc7..9e10b4b6 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4395 +4390 diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConnectionHandler.cpp index dc8bd703..3f60be91 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConnectionHandler.cpp @@ -389,10 +389,6 @@ namespace Qv2ray::core::handlers } CONFIGROOT root = GetConnectionRoot(connections[id].groupId, id); - if (IsComplexConfig(root)) - { - return tr("Complex config"); - } QStringList protocols; QStringList streamProtocols; auto outbound = root["outbounds"].toArray().first().toObject(); @@ -652,10 +648,10 @@ namespace Qv2ray::core::handlers LOG(MODULE_CORE_HANDLER, "Removing: " + conn.toString()) DeleteConnection(conn); } - + // Update the time groups[id].lastUpdated = system_clock::to_time_t(system_clock::now()); - + return hasErrorOccured; } diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index f52ba91b..2596a71a 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -242,7 +242,7 @@ 0 0 480 - 551 + 768 @@ -285,6 +285,18 @@ + + + + + 13 + + + + Speed Graph + + + @@ -293,104 +305,39 @@ - + + + + 0 + 200 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 13 - - 1 + + Log - - - - 0 - -9 - 450 - 218 - - - - Speed Graph - - - - - - - 0 - 200 - - - - - 10 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - - 0 - -45 - 450 - 254 - - - - Log - - - - - - - 0 - 200 - - - - - 9 - - - - QTextEdit::NoWrap - - - - - - - - 10 - - - - Clear Log - - - - - @@ -400,6 +347,31 @@ + + + + + 0 + 200 + + + + + 9 + + + + QTextEdit::NoWrap + + + + + + + Clear Log + + + From 8a8afdea6164d9571e86b9f89e246c642160b8c6 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 4 Mar 2020 22:08:08 +0800 Subject: [PATCH 090/332] change: some refactors --- Qv2ray.pro | 6 +- makespec/BUILDVERSION | 2 +- src/core/CoreUtils.cpp | 81 +++++- src/core/CoreUtils.hpp | 22 +- src/core/connection/Serialization.cpp | 2 +- ...onnectionHandler.cpp => ConfigHandler.cpp} | 234 ++++++------------ ...onnectionHandler.hpp => ConfigHandler.hpp} | 59 +++-- src/core/handler/V2rayInstanceHandler.cpp | 10 +- .../SettingsBackend.cpp} | 2 +- .../SettingsBackend.hpp} | 0 .../SettingsUpgrade.cpp} | 0 src/core/tcping/QvTCPing.cpp | 4 +- src/main.cpp | 16 +- src/ui/editors/w_RoutesEditor.cpp | 2 +- src/ui/w_MainWindow.cpp | 46 ++-- src/ui/w_MainWindow.hpp | 2 +- src/ui/w_MainWindow_extra.cpp | 2 +- src/ui/w_PreferencesWindow.cpp | 4 +- src/ui/w_SubscriptionManager.cpp | 6 +- src/ui/widgets/ConnectionInfoWidget.cpp | 18 +- src/ui/widgets/ConnectionInfoWidget.hpp | 2 +- src/ui/widgets/ConnectionItemWidget.cpp | 30 +-- src/ui/widgets/ConnectionItemWidget.hpp | 2 +- 23 files changed, 292 insertions(+), 260 deletions(-) rename src/core/handler/{ConnectionHandler.cpp => ConfigHandler.cpp} (69%) rename src/core/handler/{ConnectionHandler.hpp => ConfigHandler.hpp} (76%) rename src/core/{config/ConfigBackend.cpp => settings/SettingsBackend.cpp} (94%) rename src/core/{config/ConfigBackend.hpp => settings/SettingsBackend.hpp} (100%) rename src/core/{config/ConfigUpgrade.cpp => settings/SettingsUpgrade.cpp} (100%) diff --git a/Qv2ray.pro b/Qv2ray.pro index 435562ca..922700f2 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -78,8 +78,8 @@ Qv2rayAddSource(components, proxy, QvProxyConfigurator, cpp, hpp) Qv2rayAddSource(components, speedchart, speedwidget, cpp, hpp) Qv2rayAddSource(components, speedchart, speedplotview, cpp, hpp) Qv2rayAddSource(components, geosite, QvGeositeReader, cpp, hpp) -Qv2rayAddSource(core, config, ConfigBackend, cpp, hpp) -Qv2rayAddSource(core, config, ConfigUpgrade, cpp) +Qv2rayAddSource(core, settings, SettingsBackend, cpp, hpp) +Qv2rayAddSource(core, settings, SettingsUpgrade, cpp) Qv2rayAddSource(core, connection, ConnectionIO, cpp, hpp) Qv2rayAddSource(core, connection, Generation, cpp, hpp) Qv2rayAddSource(core, connection, Serialization, cpp, hpp) @@ -87,7 +87,7 @@ Qv2rayAddSource(core, kernel, KernelInteractions, cpp, hpp) Qv2rayAddSource(core, kernel, APIBackend, cpp, hpp) Qv2rayAddSource(core, tcping, QvTCPing, cpp, hpp) # Connection Handlers -Qv2rayAddSource(core, handler, ConnectionHandler, cpp, hpp) +Qv2rayAddSource(core, handler, ConfigHandler, cpp, hpp) Qv2rayAddSource(core, handler, V2rayInstanceHandler, cpp) # Qv2rayAddSource(core, _, CoreUtils, cpp, hpp) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 9e10b4b6..686f859d 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4390 +4411 diff --git a/src/core/CoreUtils.cpp b/src/core/CoreUtils.cpp index 72c0c98f..6e6f731b 100644 --- a/src/core/CoreUtils.cpp +++ b/src/core/CoreUtils.cpp @@ -1,8 +1,14 @@ #include "CoreUtils.hpp" + #include "common/QvHelpers.hpp" +#include "core/handler/ConfigHandler.hpp" namespace Qv2ray::core { + bool IsComplexConfig(const ConnectionId &id) + { + return IsComplexConfig(ConnectionManager->GetConnectionRoot(id)); + } bool IsComplexConfig(const CONFIGROOT &root) { bool cRouting = root.contains("routing"); @@ -17,7 +23,7 @@ namespace Qv2ray::core return cRules || cInboundCount || cOutboundCount; } - bool GetOutboundData(const OUTBOUND &out, QString *host, int *port, QString *protocol) + bool GetOutboundInfo(const OUTBOUND &out, QString *host, int *port, QString *protocol) { // Set initial values. *host = QObject::tr("N/A"); @@ -53,4 +59,77 @@ namespace Qv2ray::core return false; } } + + const tuple GetConnectionInfo(const ConnectionId &id, bool *status) + { + // TODO, what if is complex? + if (status != nullptr) + *status = false; + auto root = ConnectionManager->GetConnectionRoot(id); + return GetConnectionInfo(root, status); + } + + const tuple GetConnectionInfo(const CONFIGROOT &out, bool *status) + { + if (status != nullptr) + *status = false; + for (auto item : out["outbounds"].toArray()) + { + OUTBOUND outBoundRoot = OUTBOUND(item.toObject()); + QString host; + int port; + QString outboundType = ""; + + if (GetOutboundInfo(outBoundRoot, &host, &port, &outboundType)) + { + if (status != nullptr) + *status = true; + return { outboundType, host, port }; + } + else + { + LOG(MODULE_CORE_HANDLER, "Unknown outbound type: " + outboundType + ", cannot deduce host and port.") + } + } + return { QObject::tr("N/A"), QObject::tr("N/A"), 0 }; + } + + const tuple GetConnectionUsageAmount(const ConnectionId &id) + { + auto connection = ConnectionManager->GetConnectionMetaObject(id); + return { connection.upLinkData, connection.downLinkData }; + } + + uint64_t GetConnectionTotalData(const ConnectionId &id) + { + auto connection = ConnectionManager->GetConnectionMetaObject(id); + return connection.upLinkData + connection.downLinkData; + } + + int64_t GetConnectionLatency(const ConnectionId &id) + { + auto connection = ConnectionManager->GetConnectionMetaObject(id); + return max(connection.latency, (int64_t) 0); + } + + const QString GetConnectionProtocolString(const ConnectionId &id) + { + CONFIGROOT root = ConnectionManager->GetConnectionRoot(id); + QString result; + QStringList protocols; + QStringList streamProtocols; + auto outbound = root["outbounds"].toArray().first().toObject(); + result.append(outbound["protocol"].toString()); + + if (outbound.contains("streamSettings")) + { + result.append(" / " + outbound["streamSettings"].toObject()["network"].toString()); + if (outbound["streamSettings"].toObject().contains("tls")) + { + result.append(outbound["streamSettings"].toObject()["tls"].toBool() ? " / tls" : ""); + } + } + + return result; + } } // namespace Qv2ray::core diff --git a/src/core/CoreUtils.hpp b/src/core/CoreUtils.hpp index 4a93d64d..f3f9689e 100644 --- a/src/core/CoreUtils.hpp +++ b/src/core/CoreUtils.hpp @@ -1,10 +1,13 @@ #pragma once +#include "base/models/CoreObjectModels.hpp" +#include "base/models/QvSafeType.hpp" +#include "core/CoreSafeTypes.hpp" + #include -#include -#include namespace Qv2ray::core { + const inline GroupId DefaultGroupId = GroupId("000000000000"); using namespace Qv2ray::base; using namespace Qv2ray::base::safetype; using namespace Qv2ray::base::objects; @@ -23,9 +26,20 @@ namespace Qv2ray::core { return in.QV2RAY_RULE_TAG; } - - bool GetOutboundData(const OUTBOUND &out, QString *host, int *port, QString *protocol); + // + int64_t GetConnectionLatency(const ConnectionId &id); + uint64_t GetConnectionTotalData(const ConnectionId &id); + const tuple GetConnectionUsageAmount(const ConnectionId &id); + // + const tuple GetConnectionInfo(const ConnectionId &id, bool *status = nullptr); + const tuple GetConnectionInfo(const CONFIGROOT &out, bool *status = nullptr); + // + bool GetOutboundInfo(const OUTBOUND &out, QString *host, int *port, QString *protocol); bool IsComplexConfig(const CONFIGROOT &root); + bool IsComplexConfig(const ConnectionId &id); + // + const QString GetConnectionProtocolString(const ConnectionId &id); + } // namespace Qv2ray::core using namespace Qv2ray::core; diff --git a/src/core/connection/Serialization.cpp b/src/core/connection/Serialization.cpp index 7875498f..4cbcbf9c 100644 --- a/src/core/connection/Serialization.cpp +++ b/src/core/connection/Serialization.cpp @@ -3,7 +3,7 @@ #include "Generation.hpp" #include "common/QvHelpers.hpp" #include "core/CoreUtils.hpp" -#include "core/handler/ConnectionHandler.hpp" +#include "core/handler/ConfigHandler.hpp" namespace Qv2ray::core::connection { diff --git a/src/core/handler/ConnectionHandler.cpp b/src/core/handler/ConfigHandler.cpp similarity index 69% rename from src/core/handler/ConnectionHandler.cpp rename to src/core/handler/ConfigHandler.cpp index 3f60be91..73e0a11f 100644 --- a/src/core/handler/ConnectionHandler.cpp +++ b/src/core/handler/ConfigHandler.cpp @@ -1,13 +1,13 @@ -#include "ConnectionHandler.hpp" +#include "ConfigHandler.hpp" #include "common/QvHelpers.hpp" -#include "core/config/ConfigBackend.hpp" #include "core/connection/Serialization.hpp" +#include "core/settings/SettingsBackend.hpp" namespace Qv2ray::core::handlers { - QvConnectionHandler::QvConnectionHandler() + QvConfigHandler::QvConfigHandler() { DEBUG(MODULE_CORE_HANDLER, "ConnectionHandler Constructor.") @@ -59,15 +59,15 @@ namespace Qv2ray::core::handlers // vCoreInstance = new V2rayKernelInstance(); - connect(vCoreInstance, &V2rayKernelInstance::OnProcessErrored, this, &QvConnectionHandler::OnVCoreCrashed); - connect(vCoreInstance, &V2rayKernelInstance::OnNewStatsDataArrived, this, &QvConnectionHandler::OnStatsDataArrived); + connect(vCoreInstance, &V2rayKernelInstance::OnProcessErrored, this, &QvConfigHandler::OnVCoreCrashed); + connect(vCoreInstance, &V2rayKernelInstance::OnNewStatsDataArrived, this, &QvConfigHandler::OnStatsDataArrived); // Directly connected to a signal. - connect(vCoreInstance, &V2rayKernelInstance::OnProcessOutputReadyRead, this, &QvConnectionHandler::OnVCoreLogAvailable); + connect(vCoreInstance, &V2rayKernelInstance::OnProcessOutputReadyRead, this, &QvConfigHandler::OnVCoreLogAvailable); // // tcpingHelper = new QvTCPingHelper(5, this); httpHelper = new QvHttpRequestHelper(this); - connect(tcpingHelper, &QvTCPingHelper::OnLatencyTestCompleted, this, &QvConnectionHandler::OnLatencyDataArrived); + connect(tcpingHelper, &QvTCPingHelper::OnLatencyTestCompleted, this, &QvConfigHandler::OnLatencyDataArrived); // saveTimerId = startTimer(10 * 1000); // Do not ping all... @@ -75,7 +75,7 @@ namespace Qv2ray::core::handlers pingConnectionTimerId = startTimer(60 * 1000); } - void QvConnectionHandler::CHSaveConfigData_p() + void QvConfigHandler::CHSaveConfigData_p() { // Copy auto newGlobalConfig = GlobalConfig; @@ -109,7 +109,7 @@ namespace Qv2ray::core::handlers SaveGlobalConfig(newGlobalConfig); } - void QvConnectionHandler::timerEvent(QTimerEvent *event) + void QvConfigHandler::timerEvent(QTimerEvent *event) { if (event->timerId() == saveTimerId) { @@ -128,7 +128,7 @@ namespace Qv2ray::core::handlers } } - void QvConnectionHandler::StartLatencyTest() + void QvConfigHandler::StartLatencyTest() { for (auto connection : connections.keys()) { @@ -136,7 +136,7 @@ namespace Qv2ray::core::handlers } } - void QvConnectionHandler::StartLatencyTest(const GroupId &id) + void QvConfigHandler::StartLatencyTest(const GroupId &id) { for (auto connection : groups[id].connections) { @@ -144,13 +144,13 @@ namespace Qv2ray::core::handlers } } - void QvConnectionHandler::StartLatencyTest(const ConnectionId &id) + void QvConfigHandler::StartLatencyTest(const ConnectionId &id) { emit OnLatencyTestStarted(id); tcpingHelper->TestLatency(id); } - const QList QvConnectionHandler::Subscriptions() const + const QList QvConfigHandler::Subscriptions() const { QList subsList; @@ -165,35 +165,36 @@ namespace Qv2ray::core::handlers return subsList; } - const QList QvConnectionHandler::Connections(const GroupId &groupId) const - { - return groups[groupId].connections; - } - - const QString QvConnectionHandler::GetDisplayName(const ConnectionId &id, int limit) const + const QString QvConfigHandler::GetDisplayName(const ConnectionId &id, int limit) const { + CheckConnectionExistance(id); return TruncateString(connections[id].displayName, limit); } - const QString QvConnectionHandler::GetDisplayName(const GroupId &id, int limit) const + const QString QvConfigHandler::GetDisplayName(const GroupId &id, int limit) const { + CheckGroupExistance(id); return TruncateString(groups[id].displayName, limit); } - const ConnectionId QvConnectionHandler::GetConnectionIdByDisplayName(const QString &displayName) const - { - for (auto conn : connections.keys()) - { - if (connections[conn].displayName == displayName) - { - return conn; - } - } - - return NullConnectionId; - } - const ConnectionId QvConnectionHandler::GetConnectionIdByDisplayName(const QString &displayName, const GroupId &group) const + // Obsolated, Please use: + // ConnectionId QvConnectionHandler::GetConnectionIdByDisplayName(const QString &displayName, const GroupId &group) const + // + // const ConnectionId QvConnectionHandler::GetConnectionIdByDisplayName(const QString &displayName) const + //{ + // for (auto conn : connections.keys()) + // { + // if (connections[conn].displayName == displayName) + // { + // return conn; + // } + // } + // + // return NullConnectionId; + //} + const ConnectionId QvConfigHandler::GetConnectionIdByDisplayName(const QString &displayName, const GroupId &group) const { + CheckGroupExistanceEx(group, NullConnectionId); for (auto conn : groups[group].connections) { if (connections[conn].displayName == displayName) @@ -204,7 +205,7 @@ namespace Qv2ray::core::handlers return NullConnectionId; } - const GroupId QvConnectionHandler::GetGroupIdByDisplayName(const QString &displayName) const + const GroupId QvConfigHandler::GetGroupIdByDisplayName(const QString &displayName) const { for (auto group : groups.keys()) { @@ -217,8 +218,9 @@ namespace Qv2ray::core::handlers return NullGroupId; } - const GroupId QvConnectionHandler::GetConnectionGroupId(const ConnectionId &id) const + const GroupId QvConfigHandler::GetConnectionGroupId(const ConnectionId &id) const { + CheckConnectionExistanceEx(id, NullGroupId); if (!connections.contains(id)) { LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); @@ -227,27 +229,9 @@ namespace Qv2ray::core::handlers return connections[id].groupId; } - uint64_t QvConnectionHandler::GetConnectionTotalData(const ConnectionId &id) const - { - if (!connections.contains(id)) - { - LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); - } - - return connections[id].upLinkData + connections[id].downLinkData; - } - - int64_t QvConnectionHandler::GetConnectionLatency(const ConnectionId &id) const - { - if (!connections.contains(id)) - { - LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); - } - - return max(connections[id].latency, (int64_t) 0); - } - const optional QvConnectionHandler::RenameConnection(const ConnectionId &id, const QString &newName) + const optional QvConfigHandler::RenameConnection(const ConnectionId &id, const QString &newName) { + CheckConnectionExistance(id); if (!connections.contains(id)) { return tr("Connection doesn't exist"); @@ -256,8 +240,9 @@ namespace Qv2ray::core::handlers connections[id].displayName = newName; return {}; } - const optional QvConnectionHandler::DeleteConnection(const ConnectionId &id) + const optional QvConfigHandler::DeleteConnection(const ConnectionId &id) { + CheckConnectionExistance(id); auto groupId = connections[id].groupId; QFile connectionFile((groups[groupId].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR) + groupId.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION); @@ -279,8 +264,9 @@ namespace Qv2ray::core::handlers return tr("File does not exist."); } - const optional QvConnectionHandler::MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId) + const optional QvConfigHandler::MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId) { + CheckConnectionExistance(id); auto const oldgid = connections[id].groupId; // QString oldPath = (groups[oldgid].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR) + oldgid.toString() + "/" + @@ -307,8 +293,9 @@ namespace Qv2ray::core::handlers return {}; } - const optional QvConnectionHandler::DeleteGroup(const GroupId &id) + const optional QvConfigHandler::DeleteGroup(const GroupId &id) { + CheckGroupExistance(id); if (!groups.contains(id) || id == NullGroupId) { return tr("Group does not exist"); @@ -339,23 +326,20 @@ namespace Qv2ray::core::handlers return {}; } - const optional QvConnectionHandler::StartConnection(const ConnectionId &identifier) + const optional QvConfigHandler::StartConnection(const ConnectionId &id) { - if (!connections.contains(identifier)) - { - return tr("No connection selected!"); - } + CheckConnectionExistance(id); if (currentConnectionId != NullConnectionId) { StopConnection(); } - CONFIGROOT root = GetConnectionRoot(connections[identifier].groupId, identifier); - return CHStartConnection_p(identifier, root); + CONFIGROOT root = GetConnectionRoot(connections[id].groupId, id); + return CHStartConnection_p(id, root); } - void QvConnectionHandler::RestartConnection() // const ConnectionId &id + void QvConfigHandler::RestartConnection() // const ConnectionId &id { auto conn = currentConnectionId; if (conn != NullConnectionId) @@ -365,7 +349,7 @@ namespace Qv2ray::core::handlers } } - void QvConnectionHandler::StopConnection() // const ConnectionId &id + void QvConfigHandler::StopConnection() // const ConnectionId &id { // Currently just simply stop it. //_UNUSED(id) @@ -374,50 +358,13 @@ namespace Qv2ray::core::handlers CHStopConnection_p(); } - bool QvConnectionHandler::IsConnected(const ConnectionId &id) const + bool QvConfigHandler::IsConnected(const ConnectionId &id) const { + CheckConnectionExistanceEx(id, false); return currentConnectionId == id; } - const QString QvConnectionHandler::GetConnectionProtocolString(const ConnectionId &id) const - { - QString result; - - if (!connections.contains(id)) - { - result = tr("N/A"); - } - - CONFIGROOT root = GetConnectionRoot(connections[id].groupId, id); - QStringList protocols; - QStringList streamProtocols; - auto outbound = root["outbounds"].toArray().first().toObject(); - result.append(outbound["protocol"].toString()); - - if (outbound.contains("streamSettings")) - { - result.append(" / " + outbound["streamSettings"].toObject()["network"].toString()); - - if (outbound["streamSettings"].toObject().contains("tls")) - { - result.append(outbound["streamSettings"].toObject()["tls"].toBool() ? " / tls" : ""); - } - } - - return result; - } - - const tuple QvConnectionHandler::GetConnectionUsageAmount(const ConnectionId &id) const - { - if (!connections.contains(id)) - { - return { 0, 0 }; - } - - return { connections[id].upLinkData, connections[id].downLinkData }; - } - - QvConnectionHandler::~QvConnectionHandler() + QvConfigHandler::~QvConfigHandler() { LOG(MODULE_CORE_HANDLER, "Triggering save settings from destructor") CHSaveConfigData_p(); @@ -432,53 +379,22 @@ namespace Qv2ray::core::handlers delete httpHelper; } - const CONFIGROOT QvConnectionHandler::GetConnectionRoot(const ConnectionId &id) const + const CONFIGROOT QvConfigHandler::GetConnectionRoot(const ConnectionId &id) const { + CheckConnectionExistanceEx(id, CONFIGROOT()); return connections.contains(id) ? GetConnectionRoot(connections[id].groupId, id) : CONFIGROOT(); } - const CONFIGROOT QvConnectionHandler::GetConnectionRoot(const GroupId &group, const ConnectionId &id) const + const CONFIGROOT QvConfigHandler::GetConnectionRoot(const GroupId &group, const ConnectionId &id) const { + CheckGroupExistanceEx(group, CONFIGROOT()); + CheckConnectionExistanceEx(id, CONFIGROOT()); auto path = group.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; path.prepend(groups[group].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR); return CONFIGROOT(JsonFromString(StringFromFile(path))); } - const tuple QvConnectionHandler::GetConnectionData(const ConnectionId &id) const - { - // TODO, what if is complex? - auto root = GetConnectionRoot(id); - - bool isSucceed = false; - auto result = CHGetOutboundData_p(root, &isSucceed); - return result; - } - - const tuple QvConnectionHandler::CHGetOutboundData_p(const CONFIGROOT &root, bool *ok) const - { - *ok = false; - - for (auto item : root["outbounds"].toArray()) - { - OUTBOUND outBoundRoot = OUTBOUND(item.toObject()); - QString host; - int port; - QString outboundType = ""; - - if (GetOutboundData(outBoundRoot, &host, &port, &outboundType)) - { - *ok = true; - return { outboundType, host, port }; - } - else - { - LOG(MODULE_CORE_HANDLER, "Unknown outbound type: " + outboundType + ", cannot deduce host and port.") - } - } - return { tr("N/A"), tr("N/A"), 0 }; - } - - void QvConnectionHandler::OnLatencyDataArrived(const QvTCPingResultObject &result) + void QvConfigHandler::OnLatencyDataArrived(const QvTCPingResultObject &result) { if (connections.contains(result.connectionId)) { @@ -491,8 +407,9 @@ namespace Qv2ray::core::handlers } } - bool QvConnectionHandler::UpdateConnection(const ConnectionId &id, const CONFIGROOT &root) + bool QvConfigHandler::UpdateConnection(const ConnectionId &id, const CONFIGROOT &root) { + CheckConnectionExistanceEx(id, false); auto groupId = connections[id].groupId; auto path = (groups[groupId].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR) + groupId.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; @@ -501,7 +418,7 @@ namespace Qv2ray::core::handlers return StringToFile(content, path); } - const GroupId QvConnectionHandler::CreateGroup(const QString displayName, bool isSubscription) + const GroupId QvConfigHandler::CreateGroup(const QString displayName, bool isSubscription) { GroupId id(GenerateRandomString()); groups[id].displayName = displayName; @@ -511,8 +428,9 @@ namespace Qv2ray::core::handlers return id; } - const optional QvConnectionHandler::RenameGroup(const GroupId &id, const QString &newName) + const optional QvConfigHandler::RenameGroup(const GroupId &id, const QString &newName) { + CheckGroupExistance(id); if (!groups.contains(id)) { return tr("Group does not exist"); @@ -522,8 +440,9 @@ namespace Qv2ray::core::handlers return {}; } - const tuple QvConnectionHandler::GetSubscriptionData(const GroupId &id) + const tuple QvConfigHandler::GetSubscriptionData(const GroupId &id) const { + CheckGroupExistance(id); tuple result; if (!groups[id].isSubscription) @@ -534,8 +453,9 @@ namespace Qv2ray::core::handlers return { groups[id].address, groups[id].lastUpdated, groups[id].updateInterval }; } - bool QvConnectionHandler::SetSubscriptionData(const GroupId &id, const QString &address, float updateInterval) + bool QvConfigHandler::SetSubscriptionData(const GroupId &id, const QString &address, float updateInterval) { + CheckGroupExistanceEx(id, false); if (!groups.contains(id)) { return false; @@ -551,8 +471,9 @@ namespace Qv2ray::core::handlers return true; } - bool QvConnectionHandler::UpdateSubscription(const GroupId &id, bool useSystemProxy) + bool QvConfigHandler::UpdateSubscription(const GroupId &id, bool useSystemProxy) { + CheckGroupExistanceEx(id, false); if (isHttpRequestInProgress) { return false; @@ -563,8 +484,9 @@ namespace Qv2ray::core::handlers return CHUpdateSubscription_p(id, data); } - bool QvConnectionHandler::CHUpdateSubscription_p(const GroupId &id, const QByteArray &subscriptionData) + bool QvConfigHandler::CHUpdateSubscription_p(const GroupId &id, const QByteArray &subscriptionData) { + CheckGroupExistanceEx(id, false); if (!groups.contains(id)) { return false; @@ -578,7 +500,7 @@ namespace Qv2ray::core::handlers for (auto conn : groups[id].connections) { nameMap[GetDisplayName(conn)] = conn; - auto [protocol, host, port] = GetConnectionData(conn); + auto [protocol, host, port] = GetConnectionInfo(conn); if (port != 0) { typeMap[{ protocol, host, port }] = conn; @@ -610,7 +532,7 @@ namespace Qv2ray::core::handlers continue; } bool canGetOutboundData = false; - auto outboundData = CHGetOutboundData_p(config, &canGetOutboundData); + auto outboundData = GetConnectionInfo(config, &canGetOutboundData); // // Begin guessing new ConnectionId if (nameMap.contains(_alias)) @@ -648,14 +570,14 @@ namespace Qv2ray::core::handlers LOG(MODULE_CORE_HANDLER, "Removing: " + conn.toString()) DeleteConnection(conn); } - + // Update the time groups[id].lastUpdated = system_clock::to_time_t(system_clock::now()); - + return hasErrorOccured; } - const ConnectionId QvConnectionHandler::CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root) + const ConnectionId QvConfigHandler::CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root) { LOG(MODULE_CORE_HANDLER, "Creating new connection: " + displayName) ConnectionId newId(GenerateUuid()); diff --git a/src/core/handler/ConnectionHandler.hpp b/src/core/handler/ConfigHandler.hpp similarity index 76% rename from src/core/handler/ConnectionHandler.hpp rename to src/core/handler/ConfigHandler.hpp index b431fe86..19be3276 100644 --- a/src/core/handler/ConnectionHandler.hpp +++ b/src/core/handler/ConfigHandler.hpp @@ -8,18 +8,29 @@ #include "core/kernel/KernelInteractions.hpp" #include "core/tcping/QvTCPing.hpp" +#define CheckIdExistance(type, id, val) \ + if (!type.contains(id)) \ + { \ + return val; \ + } + +#define CheckGroupExistanceEx(id, val) CheckIdExistance(groups, id, val) +#define CheckGroupExistance(id) CheckGroupExistanceEx(id, {}) + +#define CheckConnectionExistanceEx(id, val) CheckIdExistance(connections, id, val) +#define CheckConnectionExistance(id) CheckConnectionExistanceEx(id, {}) + namespace Qv2ray::core::handlers { - const inline GroupId DefaultGroupId = GroupId("000000000000"); // - class QvConnectionHandler : public QObject + class QvConfigHandler : public QObject { Q_OBJECT public: - explicit QvConnectionHandler(); - ~QvConnectionHandler(); + explicit QvConfigHandler(); + ~QvConfigHandler(); - public: + public slots: // inline const ConnectionId CurrentConnection() const { @@ -29,20 +40,39 @@ namespace Qv2ray::core::handlers { return connections.keys(); } + inline const QList Connections(const GroupId &groupId) const + { + CheckGroupExistance(groupId); + return groups[groupId].connections; + } inline const QList AllGroups() const { return groups.keys(); } + inline const ConnectionMetaObject GetConnectionMetaObject(const ConnectionId &id) const + { + CheckConnectionExistance(id); + return connections[id]; + } + inline const GroupMetaObject GetGroupMetaObject(const GroupId &id) const + { + CheckGroupExistance(id); + return groups[id]; + } + inline bool IsSubscription(const GroupId &id) const + { + CheckGroupExistance(id); + return groups[id].isSubscription; + } // // const QList Subscriptions() const; - const QList Connections(const GroupId &groupId) const; // // Generic Get Options const QString GetDisplayName(const GroupId &id, int limit = -1) const; const QString GetDisplayName(const ConnectionId &id, int limit = -1) const; const GroupId GetGroupIdByDisplayName(const QString &displayName) const; - const ConnectionId GetConnectionIdByDisplayName(const QString &displayName) const; + // const ConnectionId GetConnectionIdByDisplayName(const QString &displayName) const; const ConnectionId GetConnectionIdByDisplayName(const QString &displayName, const GroupId &group) const; // // Connectivity Operationss @@ -59,14 +89,9 @@ namespace Qv2ray::core::handlers const ConnectionId CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); // // Get Conncetion Property - const tuple GetConnectionData(const ConnectionId &connectionId) const; const GroupId GetConnectionGroupId(const ConnectionId &id) const; - const QString GetConnectionProtocolString(const ConnectionId &id) const; const CONFIGROOT GetConnectionRoot(const ConnectionId &id) const; const CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id) const; - int64_t GetConnectionLatency(const ConnectionId &id) const; - uint64_t GetConnectionTotalData(const ConnectionId &id) const; - const tuple GetConnectionUsageAmount(const ConnectionId &id) const; // // Misc Connection Operations void StartLatencyTest(); @@ -80,14 +105,10 @@ namespace Qv2ray::core::handlers // const optional DuplicateGroup(const GroupId &id); // // Subscriptions - bool IsSubscription(const GroupId &id) const - { - return groups[id].isSubscription; - } bool SetSubscriptionData(const GroupId &id, const QString &address = "", float updateInterval = -1); bool UpdateSubscription(const GroupId &id, bool useSystemProxy); // bool UpdateSubscriptionASync(const GroupId &id, bool useSystemProxy); - const tuple GetSubscriptionData(const GroupId &id); + const tuple GetSubscriptionData(const GroupId &id) const; signals: void OnCrashed(); @@ -125,8 +146,6 @@ namespace Qv2ray::core::handlers optional CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); void CHStopConnection_p(); bool CHUpdateSubscription_p(const GroupId &id, const QByteArray &subscriptionData); - // bool CHSaveConnectionConfig_p(CONFIGROOT obj, const ConnectionId &id, bool override); - const tuple CHGetOutboundData_p(const CONFIGROOT &obj, bool *succeed) const; private: int saveTimerId; @@ -149,7 +168,7 @@ namespace Qv2ray::core::handlers #endif }; - inline ::Qv2ray::core::handlers::QvConnectionHandler *ConnectionManager = nullptr; + inline ::Qv2ray::core::handlers::QvConfigHandler *ConnectionManager = nullptr; } // namespace Qv2ray::core::handlers using namespace Qv2ray::core::handlers; diff --git a/src/core/handler/V2rayInstanceHandler.cpp b/src/core/handler/V2rayInstanceHandler.cpp index b270b04d..e0c43045 100644 --- a/src/core/handler/V2rayInstanceHandler.cpp +++ b/src/core/handler/V2rayInstanceHandler.cpp @@ -1,7 +1,7 @@ -#include "ConnectionHandler.hpp" +#include "ConfigHandler.hpp" #include "core/connection/Generation.hpp" -optional QvConnectionHandler::CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root) +optional QvConfigHandler::CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root) { connections[id].lastConnected = system_clock::to_time_t(system_clock::now()); // @@ -17,7 +17,7 @@ optional QvConnectionHandler::CHStartConnection_p(const ConnectionId &i return result; } -void QvConnectionHandler::CHStopConnection_p() +void QvConfigHandler::CHStopConnection_p() { if (vCoreInstance->KernelStarted) { @@ -33,14 +33,14 @@ void QvConnectionHandler::CHStopConnection_p() } } -void QvConnectionHandler::OnStatsDataArrived(const ConnectionId &id, const quint64 uploadSpeed, const quint64 downloadSpeed) +void QvConfigHandler::OnStatsDataArrived(const ConnectionId &id, const quint64 uploadSpeed, const quint64 downloadSpeed) { connections[id].upLinkData += uploadSpeed; connections[id].downLinkData += downloadSpeed; emit OnStatsAvailable(id, uploadSpeed, downloadSpeed, connections[id].upLinkData, connections[id].downLinkData); } -void QvConnectionHandler::OnVCoreCrashed(const ConnectionId &id) +void QvConfigHandler::OnVCoreCrashed(const ConnectionId &id) { LOG(MODULE_CORE_HANDLER, "V2ray core crashed!") currentConnectionId = NullConnectionId; diff --git a/src/core/config/ConfigBackend.cpp b/src/core/settings/SettingsBackend.cpp similarity index 94% rename from src/core/config/ConfigBackend.cpp rename to src/core/settings/SettingsBackend.cpp index 9e675178..be7f98fd 100644 --- a/src/core/config/ConfigBackend.cpp +++ b/src/core/settings/SettingsBackend.cpp @@ -1,4 +1,4 @@ -#include "ConfigBackend.hpp" +#include "SettingsBackend.hpp" #include "common/QvHelpers.hpp" diff --git a/src/core/config/ConfigBackend.hpp b/src/core/settings/SettingsBackend.hpp similarity index 100% rename from src/core/config/ConfigBackend.hpp rename to src/core/settings/SettingsBackend.hpp diff --git a/src/core/config/ConfigUpgrade.cpp b/src/core/settings/SettingsUpgrade.cpp similarity index 100% rename from src/core/config/ConfigUpgrade.cpp rename to src/core/settings/SettingsUpgrade.cpp diff --git a/src/core/tcping/QvTCPing.cpp b/src/core/tcping/QvTCPing.cpp index 86fe38ab..6da38249 100644 --- a/src/core/tcping/QvTCPing.cpp +++ b/src/core/tcping/QvTCPing.cpp @@ -9,7 +9,7 @@ #endif #include "QtConcurrent/QtConcurrent" #include "QvTCPing.hpp" -#include "core/handler/ConnectionHandler.hpp" +#include "core/handler/ConfigHandler.hpp" namespace Qv2ray::core::tcping { @@ -57,7 +57,7 @@ namespace Qv2ray::core::tcping if (isExiting) return data; - auto [protocol, host, port] = ConnectionManager->GetConnectionData(id); + auto [protocol, host, port] = GetConnectionInfo(id); Q_UNUSED(protocol) double successCount = 0, errorCount = 0; addrinfo *resolved; diff --git a/src/main.cpp b/src/main.cpp index 912c07ca..1d069582 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,12 +1,12 @@ -#include -#include "common/CommandArgs.hpp" +#include "common/CommandArgs.hpp" #include "common/QvHelpers.hpp" #include "common/QvTranslator.hpp" -#include "core/config/ConfigBackend.hpp" -#include "core/handler/ConnectionHandler.hpp" +#include "core/handler/ConfigHandler.hpp" +#include "core/settings/SettingsBackend.hpp" #include "ui/w_MainWindow.hpp" #include +#include #include #include #include @@ -23,11 +23,7 @@ void signalHandler(int signum) { - cout << "Interrupt signal (" << signum << ") received." << endl; - // if (MainWindow::mwInstance && MainWindow::mwInstance->vinstance) { - // cout << "Trying to stop connection..." << endl; - // MainWindow::mwInstance->vinstance->StopConnection(); - //} + cout << "Qv2ray: Interrupt signal (" << signum << ") received." << endl; qApp->exit(-99); } @@ -504,7 +500,7 @@ int main(int argc, char *argv[]) #endif //_qApp.setAttribute(Qt::AA_DontUseNativeMenuBar); // Initialise Connection Handler - ConnectionManager = new QvConnectionHandler(); + ConnectionManager = new QvConfigHandler(); // Show MainWindow MainWindow w; QObject::connect(&_qApp, &SingleApplication::instanceStarted, [&]() { diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index 9a7141fc..8e91f3a7 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -177,7 +177,7 @@ void RouteEditor::onNodeClicked(Node &n) { alias = GetFirstNodeData(n, QvOutboundNodeModel, OutboundNodeData)->GetOutbound(); QJsonObject _root = outbounds[alias].raw(); - GetOutboundData(OUTBOUND(_root), &host, &port, &protocol); + GetOutboundInfo(OUTBOUND(_root), &host, &port, &protocol); } else { diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 2b639a7e..1e0144b9 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -53,12 +53,12 @@ void MainWindow::MWAddConnectionItem_p(const ConnectionId &connection, const Gro } auto groupItem = groupNodes[groupId]; auto connectionItem = make_shared(QStringList{ - "", // - ConnectionManager->GetDisplayName(connection), // - NumericString(ConnectionManager->GetConnectionLatency(connection)), // - "IMPORTTIME_NOT_SUPPORTED", // - "LAST_CONNECTED_NOT_SUPPORTED", // - NumericString(ConnectionManager->GetConnectionTotalData(connection)) // + "", // + ConnectionManager->GetDisplayName(connection), // + NumericString(GetConnectionLatency(connection)), // + "IMPORTTIME_NOT_SUPPORTED", // + "LAST_CONNECTED_NOT_SUPPORTED", // + NumericString(GetConnectionTotalData(connection)) // }); connectionNodes[connection] = connectionItem; groupItem->addChild(connectionItem.get()); @@ -107,29 +107,29 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h updownImageBox_2->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); // // - connect(ConnectionManager, &QvConnectionHandler::OnCrashed, [&] { + connect(ConnectionManager, &QvConfigHandler::OnCrashed, [&] { this->show(); QvMessageBoxWarn(this, tr("V2ray vcore terminated."), tr("V2ray vcore terminated unexpectedly.") + NEWLINE + NEWLINE + tr("To solve the problem, read the V2ray log in the log text browser.")); }); // - connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &MainWindow::OnConnected); - connect(ConnectionManager, &QvConnectionHandler::OnDisconnected, this, &MainWindow::OnDisconnected); - connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &MainWindow::OnStatsAvailable); - connect(ConnectionManager, &QvConnectionHandler::OnVCoreLogAvailable, this, &MainWindow::OnVCoreLogAvailable); + connect(ConnectionManager, &QvConfigHandler::OnConnected, this, &MainWindow::OnConnected); + connect(ConnectionManager, &QvConfigHandler::OnDisconnected, this, &MainWindow::OnDisconnected); + connect(ConnectionManager, &QvConfigHandler::OnStatsAvailable, this, &MainWindow::OnStatsAvailable); + connect(ConnectionManager, &QvConfigHandler::OnVCoreLogAvailable, this, &MainWindow::OnVCoreLogAvailable); // - connect(ConnectionManager, &QvConnectionHandler::OnConnectionDeleted, this, &MainWindow::OnConnectionDeleted); - connect(ConnectionManager, &QvConnectionHandler::OnConnectionCreated, this, &MainWindow::OnConnectionCreated); - connect(ConnectionManager, &QvConnectionHandler::OnConnectionGroupChanged, this, &MainWindow::OnConnectionGroupChanged); + connect(ConnectionManager, &QvConfigHandler::OnConnectionDeleted, this, &MainWindow::OnConnectionDeleted); + connect(ConnectionManager, &QvConfigHandler::OnConnectionCreated, this, &MainWindow::OnConnectionCreated); + connect(ConnectionManager, &QvConfigHandler::OnConnectionGroupChanged, this, &MainWindow::OnConnectionGroupChanged); // - connect(ConnectionManager, &QvConnectionHandler::OnGroupCreated, this, &MainWindow::OnGroupCreated); - connect(ConnectionManager, &QvConnectionHandler::OnGroupDeleted, this, &MainWindow::OnGroupDeleted); + connect(ConnectionManager, &QvConfigHandler::OnGroupCreated, this, &MainWindow::OnGroupCreated); + connect(ConnectionManager, &QvConfigHandler::OnGroupDeleted, this, &MainWindow::OnGroupDeleted); // - connect(ConnectionManager, &QvConnectionHandler::OnConnectionRenamed, [&](const ConnectionId &id, const QString &, const QString &newName) { + connect(ConnectionManager, &QvConfigHandler::OnConnectionRenamed, [&](const ConnectionId &id, const QString &, const QString &newName) { connectionNodes[id]->setText(MW_ITEM_COL_DISPLAYNAME, newName); // }); - connect(ConnectionManager, &QvConnectionHandler::OnLatencyTestFinished, [&](const ConnectionId &id, const uint avg) { + connect(ConnectionManager, &QvConfigHandler::OnLatencyTestFinished, [&](const ConnectionId &id, const uint avg) { connectionNodes[id]->setText(MW_ITEM_COL_LATENCY, NumericString(avg)); // }); // @@ -173,8 +173,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h connect(action_Tray_ShowPreferencesWindow, &QAction::triggered, this, &MainWindow::on_preferencesBtn_clicked); // connect(action_Tray_Start, &QAction::triggered, [&] { ConnectionManager->StartConnection(lastConnectedId); }); - connect(action_Tray_Stop, &QAction::triggered, ConnectionManager, &QvConnectionHandler::StopConnection); - connect(action_Tray_Reconnect, &QAction::triggered, ConnectionManager, &QvConnectionHandler::RestartConnection); + connect(action_Tray_Stop, &QAction::triggered, ConnectionManager, &QvConfigHandler::StopConnection); + connect(action_Tray_Reconnect, &QAction::triggered, ConnectionManager, &QvConfigHandler::RestartConnection); // connect(action_Tray_Quit, &QAction::triggered, this, &MainWindow::on_actionExit_triggered); connect(action_Tray_SetSystemProxy, &QAction::triggered, this, &MainWindow::MWSetSystemProxy); @@ -197,8 +197,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h // // Globally invokable signals. connect(this, &MainWindow::Connect, [&] { ConnectionManager->StartConnection(lastConnectedId); }); - connect(this, &MainWindow::DisConnect, ConnectionManager, &QvConnectionHandler::StopConnection); - connect(this, &MainWindow::ReConnect, ConnectionManager, &QvConnectionHandler::RestartConnection); + connect(this, &MainWindow::DisConnect, ConnectionManager, &QvConfigHandler::StopConnection); + connect(this, &MainWindow::ReConnect, ConnectionManager, &QvConfigHandler::RestartConnection); // hTray.setContextMenu(tray_RootMenu); hTray.show(); @@ -731,7 +731,7 @@ void MainWindow::OnStatsAvailable(const ConnectionId &id, const quint64 upS, con ConnectionManager->GetDisplayName(id) + NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); // // Set data accordingly - connectionNodes[id]->setText(MW_ITEM_COL_DATAUSAGE, NumericString(ConnectionManager->GetConnectionTotalData(id))); + connectionNodes[id]->setText(MW_ITEM_COL_DATAUSAGE, NumericString(GetConnectionTotalData(id))); } void MainWindow::OnVCoreLogAvailable(const ConnectionId &id, const QString &log) diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 185f29b2..77398ec2 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -4,7 +4,7 @@ #include "common/LogHighlighter.hpp" #include "components/pac/QvPACHandler.hpp" #include "components/speedchart/speedwidget.hpp" -#include "core/handler/ConnectionHandler.hpp" +#include "core/handler/ConfigHandler.hpp" #include "ui/messaging/QvMessageBus.hpp" #include "ui_w_MainWindow.h" diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index a6ae76d2..903745e7 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -9,7 +9,7 @@ void MainWindow::MWSetSystemProxy() bool httpEnabled = GlobalConfig.inboundConfig.useHTTP; bool socksEnabled = GlobalConfig.inboundConfig.useSocks; // - bool isComplex = IsComplexConfig(ConnectionManager->GetConnectionRoot(ConnectionManager->CurrentConnection())); + bool isComplex = IsComplexConfig(ConnectionManager->CurrentConnection()); if (!isComplex) { diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index 6b0beff5..170f4aad 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -5,10 +5,10 @@ #include "common/QvTranslator.hpp" #include "components/autolaunch/QvAutoLaunch.hpp" #include "components/plugins/toolbar/QvToolbar.hpp" -#include "core/config/ConfigBackend.hpp" #include "core/connection/ConnectionIO.hpp" -#include "core/handler/ConnectionHandler.hpp" +#include "core/handler/ConfigHandler.hpp" #include "core/kernel/KernelInteractions.hpp" +#include "core/settings/SettingsBackend.hpp" #include #include diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index a1277a09..3e25a74c 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -1,8 +1,8 @@ #include "w_SubscriptionManager.hpp" #include "common/QvHelpers.hpp" -#include "core/config/ConfigBackend.hpp" -#include "core/handler/ConnectionHandler.hpp" +#include "core/handler/ConfigHandler.hpp" +#include "core/settings/SettingsBackend.hpp" SubscribeEditor::SubscribeEditor(QWidget *parent) : QDialog(parent) { @@ -102,7 +102,7 @@ void SubscribeEditor::on_subscriptionList_itemClicked(QTreeWidgetItem *item, int currentSubId = GroupId(item->text(1)); // subNameTxt->setText(ConnectionManager->GetDisplayName(currentSubId)); - auto [addr, lastUpdated, updateInterval] = ConnectionManager->GetSubscriptionData(currentSubId); + auto const [addr, lastUpdated, updateInterval] = ConnectionManager->GetSubscriptionData(currentSubId); subAddrTxt->setText(addr); lastUpdatedLabel->setText(timeToString(lastUpdated)); updateIntervalSB->setValue(updateInterval); diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 07ea8cdd..da875789 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -5,6 +5,9 @@ #include "core/CoreUtils.hpp" #include "core/connection/Serialization.hpp" +#define INDEX_CONNECTION 0 +#define INDEX_GROUP 1 + ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) { setupUi(this); @@ -16,8 +19,8 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) shareLinkTxt->setCursor(QCursor(Qt::CursorShape::IBeamCursor)); shareLinkTxt->installEventFilter(this); // - connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &ConnectionInfoWidget::OnConnected); - connect(ConnectionManager, &QvConnectionHandler::OnDisconnected, this, &ConnectionInfoWidget::OnDisConnected); + connect(ConnectionManager, &QvConfigHandler::OnConnected, this, &ConnectionInfoWidget::OnConnected); + connect(ConnectionManager, &QvConfigHandler::OnDisconnected, this, &ConnectionInfoWidget::OnDisConnected); } void ConnectionInfoWidget::ShowDetails(const tuple &_identifier) @@ -31,20 +34,19 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden editBtn->setEnabled(isConnection); editJsonBtn->setEnabled(isConnection); connectBtn->setEnabled(isConnection); - - stackedWidget->setCurrentIndex(isConnection ? 0 : 1); + stackedWidget->setCurrentIndex(isConnection ? INDEX_CONNECTION : INDEX_GROUP); if (isConnection) { - bool isComplexConfig = IsComplexConfig(ConnectionManager->GetConnectionRoot(connectionId)); + bool isComplexConfig = IsComplexConfig(connectionId); qrLabel->setVisible(!isComplexConfig); // auto shareLink = ConvertConfigToString(connectionId); // - shareLinkTxt->setText(isComplexConfig ? tr("(Complex Connection Config)") : shareLink); - protocolLabel->setText(isComplexConfig ? tr("N/A") : ConnectionManager->GetConnectionProtocolString(connectionId)); + shareLinkTxt->setText(shareLink); + protocolLabel->setText(GetConnectionProtocolString(connectionId)); // groupLabel->setText(ConnectionManager->GetDisplayName(groupId, 175)); - auto [protocol, host, port] = ConnectionManager->GetConnectionData(connectionId); + auto [protocol, host, port] = GetConnectionInfo(connectionId); Q_UNUSED(protocol) addressLabel->setText(host); portLabel->setNum(port); diff --git a/src/ui/widgets/ConnectionInfoWidget.hpp b/src/ui/widgets/ConnectionInfoWidget.hpp index 43cf1958..226b960e 100644 --- a/src/ui/widgets/ConnectionInfoWidget.hpp +++ b/src/ui/widgets/ConnectionInfoWidget.hpp @@ -1,6 +1,6 @@ #pragma once -#include "core/handler/ConnectionHandler.hpp" +#include "core/handler/ConfigHandler.hpp" #include "ui_ConnectionInfoWidget.h" #include diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index c4ac3d4a..d23e994c 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -7,11 +7,11 @@ ConnectionItemWidget::ConnectionItemWidget(QWidget *parent) : QWidget(parent), connectionId("null"), groupId("null") { setupUi(this); - connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &ConnectionItemWidget::OnConnected); - connect(ConnectionManager, &QvConnectionHandler::OnDisconnected, this, &ConnectionItemWidget::OnDisConnected); - connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &ConnectionItemWidget::OnConnectionStatsArrived); - connect(ConnectionManager, &QvConnectionHandler::OnLatencyTestStarted, this, &ConnectionItemWidget::OnLatencyTestStart); - connect(ConnectionManager, &QvConnectionHandler::OnLatencyTestFinished, this, &ConnectionItemWidget::OnLatencyTestFinished); + connect(ConnectionManager, &QvConfigHandler::OnConnected, this, &ConnectionItemWidget::OnConnected); + connect(ConnectionManager, &QvConfigHandler::OnDisconnected, this, &ConnectionItemWidget::OnDisConnected); + connect(ConnectionManager, &QvConfigHandler::OnStatsAvailable, this, &ConnectionItemWidget::OnConnectionStatsArrived); + connect(ConnectionManager, &QvConfigHandler::OnLatencyTestStarted, this, &ConnectionItemWidget::OnLatencyTestStart); + connect(ConnectionManager, &QvConfigHandler::OnLatencyTestFinished, this, &ConnectionItemWidget::OnLatencyTestFinished); } ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *parent) : ConnectionItemWidget(parent) @@ -20,7 +20,7 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare groupId = ConnectionManager->GetConnectionGroupId(id); originalItemName = ConnectionManager->GetDisplayName(id); itemType = NODE_ITEM; - auto latency = ConnectionManager->GetConnectionLatency(id); + auto latency = GetConnectionLatency(id); if (latency == 0) { @@ -31,8 +31,8 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare latencyLabel->setText(QSTRN(latency) + " " + tr("ms")); } - connTypeLabel->setText(tr("Type: ") + ConnectionManager->GetConnectionProtocolString(id)); - auto [uplink, downlink] = ConnectionManager->GetConnectionUsageAmount(connectionId); + connTypeLabel->setText(tr("Type: ") + GetConnectionProtocolString(id)); + auto [uplink, downlink] = GetConnectionUsageAmount(connectionId); dataLabel->setText(FormatBytes(uplink) + " / " + FormatBytes(downlink)); // indentSpacer->changeSize(10, indentSpacer->sizeHint().height()); @@ -42,7 +42,7 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare emit RequestWidgetFocus(this); } OnConnectionItemRenamed(id, "", originalItemName); - connect(ConnectionManager, &QvConnectionHandler::OnConnectionRenamed, this, &ConnectionItemWidget::OnConnectionItemRenamed); + connect(ConnectionManager, &QvConfigHandler::OnConnectionRenamed, this, &ConnectionItemWidget::OnConnectionItemRenamed); } // ======================================= Initialisation for root nodes. @@ -63,13 +63,13 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : connNameLabel->setFont(font); // OnGroupItemRenamed(id, "", originalItemName); - connect(ConnectionManager, &QvConnectionHandler::OnConnectionCreated, this, &ConnectionItemWidget::RecalculateConnectionsCount); - connect(ConnectionManager, &QvConnectionHandler::OnConnectionDeleted, this, &ConnectionItemWidget::RecalculateConnectionsCount); - connect(ConnectionManager, &QvConnectionHandler::OnConnectionChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); - connect(ConnectionManager, &QvConnectionHandler::OnConnectionGroupChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); - connect(ConnectionManager, &QvConnectionHandler::OnSubscriptionUpdateFinished, this, &ConnectionItemWidget::RecalculateConnectionsCount); + connect(ConnectionManager, &QvConfigHandler::OnConnectionCreated, this, &ConnectionItemWidget::RecalculateConnectionsCount); + connect(ConnectionManager, &QvConfigHandler::OnConnectionDeleted, this, &ConnectionItemWidget::RecalculateConnectionsCount); + connect(ConnectionManager, &QvConfigHandler::OnConnectionChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); + connect(ConnectionManager, &QvConfigHandler::OnConnectionGroupChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); + connect(ConnectionManager, &QvConfigHandler::OnSubscriptionUpdateFinished, this, &ConnectionItemWidget::RecalculateConnectionsCount); // - connect(ConnectionManager, &QvConnectionHandler::OnGroupRenamed, this, &ConnectionItemWidget::OnGroupItemRenamed); + connect(ConnectionManager, &QvConfigHandler::OnGroupRenamed, this, &ConnectionItemWidget::OnGroupItemRenamed); } void ConnectionItemWidget::BeginConnection() diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index 5267e82e..d7a9d349 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -1,6 +1,6 @@ #pragma once -#include "core/handler/ConnectionHandler.hpp" +#include "core/handler/ConfigHandler.hpp" #include "ui_ConnectionItemWidget.h" #include From 0d8f0839f2a03a942189bcd18c7afd0636d7f046 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 4 Mar 2020 23:07:18 +0800 Subject: [PATCH 091/332] change: some more refactors --- makespec/BUILDVERSION | 2 +- src/components/plugins/toolbar/QvToolbar.cpp | 6 +- src/core/CoreUtils.cpp | 16 ++++ src/core/CoreUtils.hpp | 6 ++ src/core/connection/Serialization.cpp | 39 ++++++---- src/core/connection/Serialization.hpp | 6 +- src/core/handler/ConfigHandler.cpp | 23 ------ src/core/handler/ConfigHandler.hpp | 6 +- src/main.cpp | 4 +- src/ui/w_MainWindow.cpp | 79 ++++++++------------ src/ui/w_MainWindow.hpp | 32 +++----- src/ui/w_PreferencesWindow.cpp | 12 +-- src/ui/w_SubscriptionManager.cpp | 8 +- src/ui/widgets/ConnectionInfoWidget.cpp | 11 ++- src/ui/widgets/ConnectionItemWidget.cpp | 6 +- src/ui/widgets/ConnectionItemWidget.hpp | 4 +- 16 files changed, 123 insertions(+), 137 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 686f859d..8ea64211 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4411 +4427 diff --git a/src/components/plugins/toolbar/QvToolbar.cpp b/src/components/plugins/toolbar/QvToolbar.cpp index b04d8717..12857f75 100644 --- a/src/components/plugins/toolbar/QvToolbar.cpp +++ b/src/components/plugins/toolbar/QvToolbar.cpp @@ -44,15 +44,15 @@ namespace Qv2ray::components::plugins if (req == "START") { - emit instance->Connect(); + emit instance->StartConnection(); } else if (req == "STOP") { - emit instance->DisConnect(); + emit instance->StopConnection(); } else if (req == "RESTART") { - emit instance->ReConnect(); + emit instance->RestartConnection(); } auto BarConfig = GlobalConfig.toolBarConfig; diff --git a/src/core/CoreUtils.cpp b/src/core/CoreUtils.cpp index 6e6f731b..6fa976b2 100644 --- a/src/core/CoreUtils.cpp +++ b/src/core/CoreUtils.cpp @@ -132,4 +132,20 @@ namespace Qv2ray::core return result; } + + const QString GetDisplayName(const ConnectionId &id, int limit) + { + return TruncateString(ConnectionManager->GetConnectionMetaObject(id).displayName, limit); + } + + const QString GetDisplayName(const GroupId &id, int limit) + { + return TruncateString(ConnectionManager->GetGroupMetaObject(id).displayName, limit); + } + + const GroupId GetConnectionGroupId(const ConnectionId &id) + { + return ConnectionManager->GetConnectionMetaObject(id).groupId; + } + } // namespace Qv2ray::core diff --git a/src/core/CoreUtils.hpp b/src/core/CoreUtils.hpp index f3f9689e..a01c9798 100644 --- a/src/core/CoreUtils.hpp +++ b/src/core/CoreUtils.hpp @@ -39,7 +39,13 @@ namespace Qv2ray::core bool IsComplexConfig(const ConnectionId &id); // const QString GetConnectionProtocolString(const ConnectionId &id); + // + const QString GetDisplayName(const ConnectionId &id, int limit = -1); + const QString GetDisplayName(const GroupId &id, int limit = -1); + // + const GroupId GetConnectionGroupId(const ConnectionId &id); + // } // namespace Qv2ray::core using namespace Qv2ray::core; diff --git a/src/core/connection/Serialization.cpp b/src/core/connection/Serialization.cpp index 4cbcbf9c..a4f8a25e 100644 --- a/src/core/connection/Serialization.cpp +++ b/src/core/connection/Serialization.cpp @@ -9,6 +9,7 @@ namespace Qv2ray::core::connection { namespace Serialization { + const QString ConvertConfigToString(const QString &alias, const CONFIGROOT &server, bool isSip002); CONFIGROOT ConvertConfigFromString(const QString &link, QString *alias, QString *errMessage) { CONFIGROOT config; @@ -31,8 +32,13 @@ namespace Qv2ray::core::connection const QString ConvertConfigToString(const ConnectionId &id, bool isSip002) { + auto alias = GetDisplayName(id); + if (IsComplexConfig(id)) + { + DEBUG(MODULE_CONNECTION, "Ignored an complex config: " + alias) + return QV2RAY_SERIALIZATION_COMPLEX_CONFIG_PLACEHOLDER; + } auto server = ConnectionManager->GetConnectionRoot(id); - auto alias = ConnectionManager->GetDisplayName(id); return ConvertConfigToString(alias, server, isSip002); } @@ -65,16 +71,16 @@ namespace Qv2ray::core::connection // From // https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2) - QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &serverConfig, const QString &alias) + const QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &server, const QString &alias) { QJsonObject vmessUriRoot; // Constant vmessUriRoot["v"] = 2; vmessUriRoot["ps"] = alias; - vmessUriRoot["add"] = serverConfig.address; - vmessUriRoot["port"] = serverConfig.port; - vmessUriRoot["id"] = serverConfig.users.front().id; - vmessUriRoot["aid"] = serverConfig.users.front().alterId; + vmessUriRoot["add"] = server.address; + vmessUriRoot["port"] = server.port; + vmessUriRoot["id"] = server.users.front().id; + vmessUriRoot["aid"] = server.users.front().alterId; vmessUriRoot["net"] = transfer.network; vmessUriRoot["tls"] = transfer.security; @@ -216,14 +222,14 @@ namespace Qv2ray::core::connection CONFIGROOT root; OUTBOUNDS outbounds; outbounds.append( - GenerateOutboundEntry("shadowsocks", GenerateShadowSocksOUT(QList() << server), QJsonObject())); + GenerateOutboundEntry("shadowsocks", GenerateShadowSocksOUT(QList{ server }), QJsonObject())); JADD(outbounds) *alias = alias->isEmpty() ? d_name : *alias + "_" + d_name; LOG(MODULE_CONNECTION, "Deduced alias: " + *alias) return root; } - QString ConvertConfigToSSString(const ShadowSocksServerObject &server, const QString &alias, bool isSip002) + const QString ConvertConfigToSSString(const ShadowSocksServerObject &server, const QString &alias, bool isSip002) { auto myAlias = QUrl::toPercentEncoding(alias); @@ -333,13 +339,17 @@ namespace Qv2ray::core::connection // used as default. // [[val.size() <= 1]] is used when only the default value // exists. + /// // - It can be empty, if so, if the key is not in - // the JSON, or the value is empty, it'll report an error. + // the JSON, or the value is empty, it'll report an error. + // // - Else if it contains one thing. if the key is not in - // the JSON, or the value is empty, it'll use that one. + // the JSON, or the value is empty, it'll use that one. + // // - Else if it contains many things, when the key IS in - // the JSON but not in those THINGS, it'll use the first - // one in the THINGS + // the JSON but not in those THINGS, it'll use the first + // one in the THINGS + // // - Else, it'll use the value found from the JSON object. // #define empty_arg @@ -464,11 +474,10 @@ namespace Qv2ray::core::connection auto outbound = GenerateOutboundEntry("vmess", vConf, GetRootObject(streaming), QJsonObject(), "0.0.0.0", OUTBOUND_TAG_PROXY); // root["outbounds"] = QJsonArray() << outbound; - // If previous alias is empty, just the PS is needed, else, append a - // "_" + // If previous alias is empty, just the PS is needed, else, append a "_" *alias = alias->trimmed().isEmpty() ? ps : *alias + "_" + ps; -#undef default return root; +#undef default } } // namespace Serialization } // namespace Qv2ray::core::connection diff --git a/src/core/connection/Serialization.hpp b/src/core/connection/Serialization.hpp index 12c6705e..0e50dacf 100644 --- a/src/core/connection/Serialization.hpp +++ b/src/core/connection/Serialization.hpp @@ -5,21 +5,21 @@ namespace Qv2ray::core::connection { namespace Serialization { + const auto QV2RAY_SERIALIZATION_COMPLEX_CONFIG_PLACEHOLDER = QObject::tr("(Complex Connection Config)"); // int VerifyVMessProtocolString(QString vmess); QString DecodeSubscriptionString(QByteArray arr); // General CONFIGROOT ConvertConfigFromString(const QString &link, QString *alias, QString *errMessage); const QString ConvertConfigToString(const ConnectionId &id, bool isSip002 = false); - const QString ConvertConfigToString(const QString &alias, const CONFIGROOT &server, bool isSip002); // VMess URI Protocol CONFIGROOT ConvertConfigFromVMessString(const QString &vmess, QString *alias, QString *errMessage); - QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &serverConfig, const QString &alias); + const QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &server, const QString &alias); // SS URI Protocol CONFIGROOT ConvertConfigFromSSString(const QString &ss, QString *alias, QString *errMessage); - QString ConvertConfigToSSString(const ShadowSocksServerObject &server, const QString &alias, bool isSip002); + const QString ConvertConfigToSSString(const ShadowSocksServerObject &server, const QString &alias, bool isSip002); } // namespace Serialization } // namespace Qv2ray::core::connection diff --git a/src/core/handler/ConfigHandler.cpp b/src/core/handler/ConfigHandler.cpp index 73e0a11f..e388159f 100644 --- a/src/core/handler/ConfigHandler.cpp +++ b/src/core/handler/ConfigHandler.cpp @@ -165,18 +165,6 @@ namespace Qv2ray::core::handlers return subsList; } - const QString QvConfigHandler::GetDisplayName(const ConnectionId &id, int limit) const - { - CheckConnectionExistance(id); - return TruncateString(connections[id].displayName, limit); - } - - const QString QvConfigHandler::GetDisplayName(const GroupId &id, int limit) const - { - CheckGroupExistance(id); - return TruncateString(groups[id].displayName, limit); - } - // Obsolated, Please use: // ConnectionId QvConnectionHandler::GetConnectionIdByDisplayName(const QString &displayName, const GroupId &group) const // @@ -218,17 +206,6 @@ namespace Qv2ray::core::handlers return NullGroupId; } - const GroupId QvConfigHandler::GetConnectionGroupId(const ConnectionId &id) const - { - CheckConnectionExistanceEx(id, NullGroupId); - if (!connections.contains(id)) - { - LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString()); - } - - return connections[id].groupId; - } - const optional QvConfigHandler::RenameConnection(const ConnectionId &id, const QString &newName) { CheckConnectionExistance(id); diff --git a/src/core/handler/ConfigHandler.hpp b/src/core/handler/ConfigHandler.hpp index 19be3276..27a30f90 100644 --- a/src/core/handler/ConfigHandler.hpp +++ b/src/core/handler/ConfigHandler.hpp @@ -68,11 +68,8 @@ namespace Qv2ray::core::handlers // const QList Subscriptions() const; // - // Generic Get Options - const QString GetDisplayName(const GroupId &id, int limit = -1) const; - const QString GetDisplayName(const ConnectionId &id, int limit = -1) const; + // Get Options const GroupId GetGroupIdByDisplayName(const QString &displayName) const; - // const ConnectionId GetConnectionIdByDisplayName(const QString &displayName) const; const ConnectionId GetConnectionIdByDisplayName(const QString &displayName, const GroupId &group) const; // // Connectivity Operationss @@ -89,7 +86,6 @@ namespace Qv2ray::core::handlers const ConnectionId CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); // // Get Conncetion Property - const GroupId GetConnectionGroupId(const ConnectionId &id) const; const CONFIGROOT GetConnectionRoot(const ConnectionId &id) const; const CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id) const; // diff --git a/src/main.cpp b/src/main.cpp index 1d069582..37ef9622 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -514,8 +514,8 @@ int main(int argc, char *argv[]) QGuiApplication::setFallbackSessionManagementEnabled(false); QObject::connect(&_qApp, &QGuiApplication::commitDataRequest, []() { LOG(MODULE_INIT, "Quit triggered by session manager.") }); #ifndef Q_OS_WIN - signal(SIGUSR1, [](int) { emit MainWindow::mwInstance->Connect(); }); - signal(SIGUSR2, [](int) { emit MainWindow::mwInstance->DisConnect(); }); + signal(SIGUSR1, [](int) { emit MainWindow::mwInstance->StartConnection(); }); + signal(SIGUSR2, [](int) { emit MainWindow::mwInstance->StopConnection(); }); #endif auto rcode = _qApp.exec(); delete ConnectionManager; diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 1e0144b9..1df106c9 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -54,7 +54,7 @@ void MainWindow::MWAddConnectionItem_p(const ConnectionId &connection, const Gro auto groupItem = groupNodes[groupId]; auto connectionItem = make_shared(QStringList{ "", // - ConnectionManager->GetDisplayName(connection), // + GetDisplayName(connection), // NumericString(GetConnectionLatency(connection)), // "IMPORTTIME_NOT_SUPPORTED", // "LAST_CONNECTED_NOT_SUPPORTED", // @@ -69,7 +69,7 @@ void MainWindow::MWAddConnectionItem_p(const ConnectionId &connection, const Gro void MainWindow::MWAddGroupItem_p(const GroupId &groupId) { - auto groupItem = make_shared(QStringList{ "", ConnectionManager->GetDisplayName(groupId) }); + auto groupItem = make_shared(QStringList{ "", GetDisplayName(groupId) }); groupNodes[groupId] = groupItem; connectionListWidget->addTopLevelItem(groupItem.get()); connectionListWidget->setItemWidget(groupItem.get(), 0, new ConnectionItemWidget(groupId, connectionListWidget)); @@ -77,7 +77,6 @@ void MainWindow::MWAddGroupItem_p(const GroupId &groupId) void MainWindow::SortConnectionList(MW_ITEM_COL byCol, bool asending) { - connectionListWidget->sortByColumn(MW_ITEM_COL_DISPLAYNAME, Qt::AscendingOrder); for (auto i = 0; i < connectionListWidget->topLevelItemCount(); i++) { @@ -85,7 +84,7 @@ void MainWindow::SortConnectionList(MW_ITEM_COL byCol, bool asending) } } -MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), hTray(this), tcpingHelper(3, this) +MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setupUi(this); MainWindow::mwInstance = this; @@ -138,25 +137,16 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h // // Setup System tray icons and menus hTray.setToolTip(TRAY_TOOLTIP_PREFIX); + // // Basic actions - action_Tray_ShowHide = new QAction(this->windowIcon(), tr("Hide"), this); - action_Tray_ShowPreferencesWindow = new QAction(tr("Preferences"), this); - action_Tray_Quit = new QAction(tr("Quit"), this); - action_Tray_Start = new QAction(tr("Connect"), this); - action_Tray_Reconnect = new QAction(tr("Reconnect"), this); - action_Tray_Stop = new QAction(tr("Disconnect"), this); - // - action_Tray_SetSystemProxy = new QAction(tr("Enable System Proxy"), this); - action_Tray_ClearSystemProxy = new QAction(tr("Disable System Proxy"), this); - // action_Tray_Start->setEnabled(true); action_Tray_Stop->setEnabled(false); - action_Tray_Reconnect->setEnabled(false); + action_Tray_Restart->setEnabled(false); // - tray_SystemProxyMenu->addAction(action_Tray_SetSystemProxy); - tray_SystemProxyMenu->addAction(action_Tray_ClearSystemProxy); tray_SystemProxyMenu->setTitle(tr("System Proxy")); tray_SystemProxyMenu->setEnabled(false); + tray_SystemProxyMenu->addAction(action_Tray_SetSystemProxy); + tray_SystemProxyMenu->addAction(action_Tray_ClearSystemProxy); // tray_RootMenu->addAction(action_Tray_ShowHide); tray_RootMenu->addSeparator(); @@ -165,7 +155,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h tray_RootMenu->addSeparator(); tray_RootMenu->addAction(action_Tray_Start); tray_RootMenu->addAction(action_Tray_Stop); - tray_RootMenu->addAction(action_Tray_Reconnect); + tray_RootMenu->addAction(action_Tray_Restart); tray_RootMenu->addSeparator(); tray_RootMenu->addAction(action_Tray_Quit); // @@ -174,7 +164,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h // connect(action_Tray_Start, &QAction::triggered, [&] { ConnectionManager->StartConnection(lastConnectedId); }); connect(action_Tray_Stop, &QAction::triggered, ConnectionManager, &QvConfigHandler::StopConnection); - connect(action_Tray_Reconnect, &QAction::triggered, ConnectionManager, &QvConfigHandler::RestartConnection); + connect(action_Tray_Restart, &QAction::triggered, ConnectionManager, &QvConfigHandler::RestartConnection); // connect(action_Tray_Quit, &QAction::triggered, this, &MainWindow::on_actionExit_triggered); connect(action_Tray_SetSystemProxy, &QAction::triggered, this, &MainWindow::MWSetSystemProxy); @@ -196,9 +186,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h connect(action_RCM_DuplicateThese, &QAction::triggered, this, &MainWindow::on_action_RCM_DuplicateThese_triggered); // // Globally invokable signals. - connect(this, &MainWindow::Connect, [&] { ConnectionManager->StartConnection(lastConnectedId); }); - connect(this, &MainWindow::DisConnect, ConnectionManager, &QvConfigHandler::StopConnection); - connect(this, &MainWindow::ReConnect, ConnectionManager, &QvConfigHandler::RestartConnection); + connect(this, &MainWindow::StartConnection, ConnectionManager, &QvConfigHandler::RestartConnection); + connect(this, &MainWindow::StopConnection, ConnectionManager, &QvConfigHandler::StopConnection); + connect(this, &MainWindow::RestartConnection, ConnectionManager, &QvConfigHandler::RestartConnection); // hTray.setContextMenu(tray_RootMenu); hTray.show(); @@ -210,13 +200,13 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h connectionListMenu->addAction(action_RCM_DeleteThese); connectionListMenu->addAction(action_RCM_ConvToComplex); // - sortMenu = new QMenu(this); - sortAction_SortByName_Asc = new QAction(tr("By connection name, A-Z")); - sortAction_SortByName_Dsc = new QAction(tr("By connection name, Z-A")); - sortAction_SortByData_Asc = new QAction(tr("By data, Ascending")); - sortAction_SortByData_Dsc = new QAction(tr("By data, Descending")); - sortAction_SortByLatency_Asc = new QAction(tr("By latency, Ascending")); - sortAction_SortByLatency_Dsc = new QAction(tr("By latency, Descending")); + QMenu *sortMenu = new QMenu(tr("Sort connection list."), this); + QAction *sortAction_SortByName_Asc = new QAction(tr("By connection name, A-Z")); + QAction *sortAction_SortByName_Dsc = new QAction(tr("By connection name, Z-A")); + QAction *sortAction_SortByLatency_Asc = new QAction(tr("By data, Ascending")); + QAction *sortAction_SortByLatency_Dsc = new QAction(tr("By data, Descending")); + QAction *sortAction_SortByData_Asc = new QAction(tr("By latency, Ascending")); + QAction *sortAction_SortByData_Dsc = new QAction(tr("By latency, Descending")); // connect(sortAction_SortByName_Asc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DISPLAYNAME, true); }); connect(sortAction_SortByName_Dsc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DISPLAYNAME, false); }); @@ -411,12 +401,12 @@ void MainWindow::ToggleVisibility() QThread::msleep(20); SetWindowPos(HWND(this->winId()), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); #endif - tray_RootMenu->actions()[0]->setText(tr("Hide")); + action_Tray_ShowHide->setText(tr("Hide")); } else { this->hide(); - tray_RootMenu->actions()[0]->setText(tr("Show")); + action_Tray_ShowHide->setText(tr("Show")); } } @@ -549,11 +539,11 @@ void MainWindow::OnDisconnected(const ConnectionId &id) Q_UNUSED(id) action_Tray_Start->setEnabled(true); action_Tray_Stop->setEnabled(false); - action_Tray_Reconnect->setEnabled(false); + action_Tray_Restart->setEnabled(false); tray_SystemProxyMenu->setEnabled(false); lastConnectedId = id; locateBtn->setEnabled(false); - this->hTray.showMessage("Qv2ray", tr("Disconnected from: ") + ConnectionManager->GetDisplayName(id), this->windowIcon()); + this->hTray.showMessage("Qv2ray", tr("Disconnected from: ") + GetDisplayName(id), this->windowIcon()); hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE); connetionStatusLabel->setText(tr("Not Connected")); if (GlobalConfig.inboundConfig.setSystemProxy) @@ -573,12 +563,12 @@ void MainWindow::OnConnected(const ConnectionId &id) Q_UNUSED(id) action_Tray_Start->setEnabled(false); action_Tray_Stop->setEnabled(true); - action_Tray_Reconnect->setEnabled(true); + action_Tray_Restart->setEnabled(true); tray_SystemProxyMenu->setEnabled(true); lastConnectedId = id; locateBtn->setEnabled(true); on_clearlogButton_clicked(); - auto name = ConnectionManager->GetDisplayName(id); + auto name = GetDisplayName(id); this->hTray.showMessage("Qv2ray", tr("Connected: ") + name, this->windowIcon()); hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + name); connetionStatusLabel->setText(tr("Connected: ") + name); @@ -727,8 +717,8 @@ void MainWindow::OnStatsAvailable(const ConnectionId &id, const quint64 upS, con netspeedLabel->setText(totalSpeedUp + NEWLINE + totalSpeedDown); dataamountLabel->setText(totalDataUp + NEWLINE + totalDataDown); // - hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + // - ConnectionManager->GetDisplayName(id) + NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); + hTray.setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + GetDisplayName(id) + // + NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); // // Set data accordingly connectionNodes[id]->setText(MW_ITEM_COL_DATAUSAGE, NumericString(GetConnectionTotalData(id))); @@ -808,7 +798,7 @@ void MainWindow::OnJsonEditRequested(const ConnectionId &id) void MainWindow::OnConnectionCreated(const ConnectionId &id, const QString &displayName) { Q_UNUSED(displayName) - MWAddConnectionItem_p(id, ConnectionManager->GetConnectionGroupId(id)); + MWAddConnectionItem_p(id, GetConnectionGroupId(id)); } void MainWindow::OnConnectionDeleted(const ConnectionId &id, const GroupId &groupId) { @@ -869,21 +859,16 @@ void MainWindow::on_action_RCM_DuplicateThese_triggered() LOG(MODULE_UI, "Selected " + QSTRN(connlist.count()) + " items") - if (connlist.isEmpty()) - { - return; - } - - if (connlist.count() > 1 && - QvMessageBoxAsk(this, tr("Duplicating Connection(s)"), tr("Are you sure to duplicate these connection(s)?")) != QMessageBox::Yes) + if (connlist.count() > 1 && QvMessageBoxAsk(this, tr("Duplicating Connection(s)"), // + tr("Are you sure to duplicate these connection(s)?")) != QMessageBox::Yes) { return; } for (auto conn : connlist) { - ConnectionManager->CreateConnection(ConnectionManager->GetDisplayName(conn) + tr(" (Copy)"), // - ConnectionManager->GetConnectionGroupId(conn), // + ConnectionManager->CreateConnection(GetDisplayName(conn) + tr(" (Copy)"), // + GetConnectionGroupId(conn), // ConnectionManager->GetConnectionRoot(conn)); } } diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 77398ec2..6ff3ec0c 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -35,9 +35,9 @@ class MainWindow explicit MainWindow(QWidget *parent = nullptr); ~MainWindow() override; signals: - void Connect() const; - void DisConnect() const; - void ReConnect() const; + void StartConnection() const; + void StopConnection() const; + void RestartConnection() const; public slots: QvMessageBusSlotDecl; private slots: @@ -113,29 +113,19 @@ class MainWindow ConnectionInfoWidget *infoWidget; // // Actions in the system tray menu - // QMenu *tray_RootMenu = new QMenu(this); - QAction *action_Tray_ShowHide; - QAction *action_Tray_ShowPreferencesWindow; - QAction *action_Tray_Quit; + QAction *action_Tray_ShowHide = new QAction(this->windowIcon(), tr("Hide"), this); + QAction *action_Tray_ShowPreferencesWindow = new QAction(tr("Preferences"), this); + QAction *action_Tray_Quit = new QAction(tr("Quit"), this); // --> Connectivities - QAction *action_Tray_Start; - QAction *action_Tray_Reconnect; - QAction *action_Tray_Stop; + QAction *action_Tray_Start = new QAction(tr("Connect"), this); + QAction *action_Tray_Restart = new QAction(tr("Reconnect"), this); + QAction *action_Tray_Stop = new QAction(tr("Disconnect"), this); // --> System proxy settings QMenu *tray_SystemProxyMenu = new QMenu(this); - QAction *action_Tray_SetSystemProxy; - QAction *action_Tray_ClearSystemProxy; + QAction *action_Tray_SetSystemProxy = new QAction(tr("Enable System Proxy"), this); + QAction *action_Tray_ClearSystemProxy = new QAction(tr("Disable System Proxy"), this); // - QMenu *sortMenu; - QAction *sortAction_SortByName_Asc; - QAction *sortAction_SortByName_Dsc; - QAction *sortAction_SortByLatency_Asc; - QAction *sortAction_SortByLatency_Dsc; - QAction *sortAction_SortByData_Asc; - QAction *sortAction_SortByData_Dsc; - // - // Extra Headers For w_MainWindow_extra.cpp Handling V2ray Connectivities. ConnectionId lastConnectedId; void MWSetSystemProxy(); void CheckSubscriptionsUpdate(); diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index 170f4aad..bbe55dea 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -164,21 +164,21 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), Current // // Empty for global config. auto autoStartConnId = ConnectionId(CurrentConfig.autoStartId); - auto autoStartGroupId = ConnectionManager->GetConnectionGroupId(autoStartConnId); + auto autoStartGroupId = GetConnectionGroupId(autoStartConnId); for (auto group : ConnectionManager->AllGroups()) { - autoStartSubsCombo->addItem(ConnectionManager->GetDisplayName(group)); + autoStartSubsCombo->addItem(GetDisplayName(group)); } - autoStartSubsCombo->setCurrentText(ConnectionManager->GetDisplayName(autoStartGroupId)); + autoStartSubsCombo->setCurrentText(GetDisplayName(autoStartGroupId)); for (auto conn : ConnectionManager->Connections(autoStartGroupId)) { - autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(conn)); + autoStartConnCombo->addItem(GetDisplayName(conn)); } - autoStartConnCombo->setCurrentText(ConnectionManager->GetDisplayName(autoStartConnId)); + autoStartConnCombo->setCurrentText(GetDisplayName(autoStartConnId)); // FP Settings if (CurrentConfig.connectionConfig.forwardProxyConfig.type.trimmed().isEmpty()) @@ -1029,7 +1029,7 @@ void PreferencesWindow::on_autoStartSubsCombo_currentIndexChanged(const QString for (auto id : list) { - autoStartConnCombo->addItem(ConnectionManager->GetDisplayName(id)); + autoStartConnCombo->addItem(GetDisplayName(id)); } } } diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 3e25a74c..e1cbe321 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -13,7 +13,7 @@ SubscribeEditor::SubscribeEditor(QWidget *parent) : QDialog(parent) for (auto subs : ConnectionManager->Subscriptions()) { - subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList{ ConnectionManager->GetDisplayName(subs), subs.toString() })); + subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList{ GetDisplayName(subs), subs.toString() })); } if (subscriptionList->topLevelItemCount() > 0) { @@ -31,7 +31,7 @@ QvMessageBusSlotImpl(SubscribeEditor) tuple SubscribeEditor::GetSelectedConfig() { - return { ConnectionManager->GetDisplayName(currentConnectionId), ConnectionManager->GetConnectionRoot(currentConnectionId) }; + return { GetDisplayName(currentConnectionId), ConnectionManager->GetConnectionRoot(currentConnectionId) }; } SubscribeEditor::~SubscribeEditor() @@ -101,7 +101,7 @@ void SubscribeEditor::on_subscriptionList_itemClicked(QTreeWidgetItem *item, int groupBox_2->setEnabled(true); currentSubId = GroupId(item->text(1)); // - subNameTxt->setText(ConnectionManager->GetDisplayName(currentSubId)); + subNameTxt->setText(GetDisplayName(currentSubId)); auto const [addr, lastUpdated, updateInterval] = ConnectionManager->GetSubscriptionData(currentSubId); subAddrTxt->setText(addr); lastUpdatedLabel->setText(timeToString(lastUpdated)); @@ -111,7 +111,7 @@ void SubscribeEditor::on_subscriptionList_itemClicked(QTreeWidgetItem *item, int for (auto conn : ConnectionManager->Connections(currentSubId)) { - connectionsList->addItem(ConnectionManager->GetDisplayName(conn)); // + connectionsList->addItem(GetDisplayName(conn)); // } } diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index da875789..a2810b32 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -45,7 +45,7 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden shareLinkTxt->setText(shareLink); protocolLabel->setText(GetConnectionProtocolString(connectionId)); // - groupLabel->setText(ConnectionManager->GetDisplayName(groupId, 175)); + groupLabel->setText(GetDisplayName(groupId, 175)); auto [protocol, host, port] = GetConnectionInfo(connectionId); Q_UNUSED(protocol) addressLabel->setText(host); @@ -65,12 +65,19 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden else { connectBtn->setIcon(QICON_R("connect.png")); - groupNameLabel->setText(ConnectionManager->GetDisplayName(groupId)); + groupNameLabel->setText(GetDisplayName(groupId)); QStringList shareLinks; for (auto connection : ConnectionManager->Connections(groupId)) { shareLinks << ConvertConfigToString(connection, false); } + // + auto complexCount = shareLinks.removeAll(QV2RAY_SERIALIZATION_COMPLEX_CONFIG_PLACEHOLDER); + if (complexCount > 0) + { + shareLinks << tr("(Ignored %1 complex config(s))").arg(complexCount); + } + // groupShareTxt->setPlainText(shareLinks.join(NEWLINE)); groupSubsLinkLabel->setText(ConnectionManager->IsSubscription(groupId) ? get<0>(ConnectionManager->GetSubscriptionData(groupId)) : tr("Not a subscription")); diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index d23e994c..4372dddc 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -17,8 +17,8 @@ ConnectionItemWidget::ConnectionItemWidget(QWidget *parent) : QWidget(parent), c ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *parent) : ConnectionItemWidget(parent) { connectionId = id; - groupId = ConnectionManager->GetConnectionGroupId(id); - originalItemName = ConnectionManager->GetDisplayName(id); + groupId = GetConnectionGroupId(id); + originalItemName = GetDisplayName(id); itemType = NODE_ITEM; auto latency = GetConnectionLatency(id); @@ -55,7 +55,7 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : // groupId = id; itemType = GROUP_HEADER_ITEM; - originalItemName = ConnectionManager->GetDisplayName(id); + originalItemName = GetDisplayName(id); RecalculateConnectionsCount(); // auto font = connNameLabel->font(); diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index d7a9d349..24a216a2 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -27,7 +27,7 @@ class ConnectionItemWidget inline bool NameMatched(const QString &arg) { auto searchString = arg.toLower(); - auto headerMatched = ConnectionManager->GetDisplayName(groupId).toLower().contains(arg); + auto headerMatched = GetDisplayName(groupId).toLower().contains(arg); if (itemType != NODE_ITEM) { @@ -35,7 +35,7 @@ class ConnectionItemWidget } else { - return headerMatched || ConnectionManager->GetDisplayName(connectionId).toLower().contains(searchString); + return headerMatched || GetDisplayName(connectionId).toLower().contains(searchString); } } inline const tuple Identifier() const From 8ce165a116d7758c63b0f092a7e2bffe0c1fab10 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 4 Mar 2020 23:27:01 +0800 Subject: [PATCH 092/332] change: some even more refactors, separated vmess, ss and prepare for ssd (and ssr?) --- Qv2ray.pro | 2 + makespec/BUILDVERSION | 2 +- src/core/connection/Serialization.cpp | 405 +------------------- src/core/connection/Serialization.hpp | 28 +- src/core/connection/Serialization_ss.cpp | 130 +++++++ src/core/connection/Serialization_vmess.cpp | 292 ++++++++++++++ src/ui/w_MainWindow.cpp | 50 ++- src/ui/w_MainWindow.hpp | 6 +- 8 files changed, 488 insertions(+), 427 deletions(-) create mode 100644 src/core/connection/Serialization_ss.cpp create mode 100644 src/core/connection/Serialization_vmess.cpp diff --git a/Qv2ray.pro b/Qv2ray.pro index 922700f2..0f582072 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -83,6 +83,8 @@ Qv2rayAddSource(core, settings, SettingsUpgrade, cpp) Qv2rayAddSource(core, connection, ConnectionIO, cpp, hpp) Qv2rayAddSource(core, connection, Generation, cpp, hpp) Qv2rayAddSource(core, connection, Serialization, cpp, hpp) +Qv2rayAddSource(core, connection, Serialization_vmess, cpp) +Qv2rayAddSource(core, connection, Serialization_ss, cpp) Qv2rayAddSource(core, kernel, KernelInteractions, cpp, hpp) Qv2rayAddSource(core, kernel, APIBackend, cpp, hpp) Qv2rayAddSource(core, tcping, QvTCPing, cpp, hpp) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 8ea64211..032405f2 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4427 +4439 diff --git a/src/core/connection/Serialization.cpp b/src/core/connection/Serialization.cpp index a4f8a25e..6c6bd17b 100644 --- a/src/core/connection/Serialization.cpp +++ b/src/core/connection/Serialization.cpp @@ -53,13 +53,13 @@ namespace Qv2ray::core::connection auto vmessServer = StructFromJsonString(JsonToString(outbound["settings"].toObject()["vnext"].toArray().first().toObject())); auto transport = StructFromJsonString(JsonToString(outbound["streamSettings"].toObject())); - sharelink = ConvertConfigToVMessString(transport, vmessServer, alias); + sharelink = vmess::ConvertConfigToVMessString(transport, vmessServer, alias); } else if (type == "shadowsocks") { auto ssServer = StructFromJsonString( JsonToString(outbound["settings"].toObject()["servers"].toArray().first().toObject())); - sharelink = ConvertConfigToSSString(ssServer, alias, isSip002); + sharelink = ss::ConvertConfigToSSString(ssServer, alias, isSip002); } else { @@ -69,56 +69,6 @@ namespace Qv2ray::core::connection return sharelink; } - // From - // https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2) - const QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &server, const QString &alias) - { - QJsonObject vmessUriRoot; - // Constant - vmessUriRoot["v"] = 2; - vmessUriRoot["ps"] = alias; - vmessUriRoot["add"] = server.address; - vmessUriRoot["port"] = server.port; - vmessUriRoot["id"] = server.users.front().id; - vmessUriRoot["aid"] = server.users.front().alterId; - vmessUriRoot["net"] = transfer.network; - vmessUriRoot["tls"] = transfer.security; - - if (transfer.network == "tcp") - { - vmessUriRoot["type"] = transfer.tcpSettings.header.type; - } - else if (transfer.network == "kcp") - { - vmessUriRoot["type"] = transfer.kcpSettings.header.type; - } - else if (transfer.network == "quic") - { - vmessUriRoot["type"] = transfer.quicSettings.header.type; - vmessUriRoot["host"] = transfer.quicSettings.security; - vmessUriRoot["path"] = transfer.quicSettings.key; - } - else if (transfer.network == "ws") - { - auto x = transfer.wsSettings.headers; - auto host = x.contains("host"); - auto CapHost = x.contains("Host"); - auto realHost = host ? x["host"] : (CapHost ? x["Host"] : ""); - // - vmessUriRoot["host"] = realHost; - vmessUriRoot["path"] = transfer.wsSettings.path; - } - else if (transfer.network == "h2" || transfer.network == "http") - { - vmessUriRoot["host"] = transfer.httpSettings.host.join(","); - vmessUriRoot["path"] = transfer.httpSettings.path; - } - - // - auto vmessPart = Base64Encode(JsonToString(vmessUriRoot, QJsonDocument::JsonFormat::Compact)); - return "vmess://" + vmessPart; - } - QString DecodeSubscriptionString(QByteArray arr) { // String may start with: vmess:// and ss:// @@ -128,356 +78,5 @@ namespace Qv2ray::core::connection auto result = QString::fromUtf8(arr).trimmed(); return result.startsWith("vmess://") ? result : Base64Decode(result); } - - CONFIGROOT ConvertConfigFromSSString(const QString &ssUri, QString *alias, QString *errMessage) - { - ShadowSocksServerObject server; - QString d_name; - - // auto ssUri = _ssUri.toStdString(); - if (ssUri.length() < 5) - { - LOG(MODULE_CONNECTION, "ss:// string too short") - *errMessage = QObject::tr("SS URI is too short"); - } - - auto uri = ssUri.mid(5); - auto hashPos = uri.lastIndexOf("#"); - DEBUG(MODULE_CONNECTION, "Hash sign position: " + QSTRN(hashPos)) - - if (hashPos >= 0) - { - // Get the name/remark - d_name = uri.mid(uri.lastIndexOf("#") + 1); - uri.truncate(hashPos); - } - - // No plugins for Qv2ray so disable those lnes.i - // size_t pluginPos = uri.find_first_of('/'); - // - // if (pluginPos != std::string::npos) { - // // TODO: support plugins. For now, just ignore them - // uri.erase(pluginPos); - //} - auto atPos = uri.indexOf('@'); - DEBUG(MODULE_CONNECTION, "At sign position: " + QSTRN(atPos)) - - if (atPos < 0) - { - // Old URI scheme - QString decoded = QByteArray::fromBase64(uri.toUtf8(), QByteArray::Base64Option::OmitTrailingEquals); - auto colonPos = decoded.indexOf(':'); - DEBUG(MODULE_CONNECTION, "Colon position: " + QSTRN(colonPos)) - - if (colonPos < 0) - { - *errMessage = QObject::tr("Can't find the colon separator between method and password"); - } - - server.method = decoded.left(colonPos); - decoded.remove(0, colonPos + 1); - atPos = decoded.lastIndexOf('@'); - DEBUG(MODULE_CONNECTION, "At sign position: " + QSTRN(atPos)) - - if (atPos < 0) - { - *errMessage = QObject::tr("Can't find the at separator between password and hostname"); - } - - server.password = decoded.mid(0, atPos); - decoded.remove(0, atPos + 1); - colonPos = decoded.lastIndexOf(':'); - DEBUG(MODULE_CONNECTION, "Colon position: " + QSTRN(colonPos)) - - if (colonPos < 0) - { - *errMessage = QObject::tr("Can't find the colon separator between hostname and port"); - } - - server.address = decoded.mid(0, colonPos); - server.port = decoded.mid(colonPos + 1).toInt(); - } - else - { - // SIP002 URI scheme - auto x = QUrl::fromUserInput(uri); - server.address = x.host(); - server.port = x.port(); - QString userInfo = Base64Decode(x.userName()); - auto userInfoSp = userInfo.indexOf(':'); - // - DEBUG(MODULE_CONNECTION, "Userinfo splitter position: " + QSTRN(userInfoSp)) - - if (userInfoSp < 0) - { - *errMessage = QObject::tr("Can't find the colon separator between method and password"); - } - - QString method = userInfo.mid(0, userInfoSp); - server.method = method; - server.password = userInfo.mid(userInfoSp + 1); - } - - d_name = QUrl::fromPercentEncoding(d_name.toUtf8()); - CONFIGROOT root; - OUTBOUNDS outbounds; - outbounds.append( - GenerateOutboundEntry("shadowsocks", GenerateShadowSocksOUT(QList{ server }), QJsonObject())); - JADD(outbounds) - *alias = alias->isEmpty() ? d_name : *alias + "_" + d_name; - LOG(MODULE_CONNECTION, "Deduced alias: " + *alias) - return root; - } - - const QString ConvertConfigToSSString(const ShadowSocksServerObject &server, const QString &alias, bool isSip002) - { - auto myAlias = QUrl::toPercentEncoding(alias); - - if (isSip002) - { - LOG(MODULE_CONNECTION, "Converting an ss-server config to Sip002 ss:// format") - QString plainUserInfo = server.method + ":" + server.password; - QString userinfo(plainUserInfo.toUtf8().toBase64(QByteArray::Base64Option::Base64UrlEncoding).data()); - return "ss://" + userinfo + "@" + server.address + ":" + QSTRN(server.port) + "#" + myAlias; - } - else - { - LOG(MODULE_CONNECTION, "Converting an ss-server config to old ss:// string format") - QString ssUri = server.method + ":" + server.password + "@" + server.address + ":" + QSTRN(server.port); - return "ss://" + ssUri.toUtf8().toBase64(QByteArray::Base64Option::OmitTrailingEquals) + "#" + myAlias; - } - } - - // - // This generates global config containing only one outbound.... - CONFIGROOT ConvertConfigFromVMessString(const QString &vmessStr, QString *alias, QString *errMessage) - { -#define default CONFIGROOT() - LOG(MODULE_SETTINGS, "Trying to convert from a vmess string.") - QString vmess = vmessStr; - - if (vmess.trimmed() != vmess) - { - LOG(MODULE_SETTINGS, "VMess string has some prefix/postfix spaces, trimming.") - vmess = vmessStr.trimmed(); - } - - // Reset errMessage - *errMessage = ""; - - if (!vmess.toLower().startsWith("vmess://")) - { - *errMessage = QObject::tr("VMess string should start with 'vmess://'"); - return default; - } - - try - { - QStringRef vmessJsonB64(&vmess, 8, vmess.length() - 8); - auto b64Str = vmessJsonB64.toString(); - - if (b64Str.isEmpty()) - { - *errMessage = QObject::tr("VMess string should be a valid base64 string"); - return default; - } - - auto vmessString = Base64Decode(b64Str); - auto jsonErr = VerifyJsonString(vmessString); - - if (!jsonErr.isEmpty()) - { - *errMessage = jsonErr; - return default; - } - - auto vmessConf = JsonFromString(vmessString); - - if (vmessConf.isEmpty()) - { - *errMessage = QObject::tr("JSON should not be empty"); - return default; - } - - bool flag = true; - // C is a quick hack... -#define C(k) vmessConf.contains(k) - // id, aid, port and add are mandatory fields of a vmess:// - // link. - flag = flag && C("id") && C("aid") && C("port") && C("add"); - // Stream Settings - auto net = C("net") ? vmessConf["net"].toString() : "tcp"; - - if (net == "http" || net == "ws") - flag = flag && C("host") && C("path"); - else if (net == "domainsocket") - flag = flag && C("path"); - else if (net == "quic") - flag = flag && C("host") && C("type") && C("path"); - -#undef C - // return flag ? 0 : 1; - } - catch (exception *e) - { - *errMessage = e->what(); - LOG(MODULE_IMPORT, "Failed to decode vmess string: " + *errMessage) - delete e; - return default; - } - - // -------------------------------------------------------------------------------------- - CONFIGROOT root; - auto b64String = QStringRef(&vmess, 8, vmess.length() - 8).toString(); - auto vmessConf = JsonFromString(Base64Decode(b64String)); - // - QString ps, add, id, net, type, host, path, tls; - int port, aid; - // - // key = key in JSON and the variable name. - // values = Candidate variable list, if not match, the first one is - // used as default. - // [[val.size() <= 1]] is used when only the default value - // exists. - /// - // - It can be empty, if so, if the key is not in - // the JSON, or the value is empty, it'll report an error. - // - // - Else if it contains one thing. if the key is not in - // the JSON, or the value is empty, it'll use that one. - // - // - Else if it contains many things, when the key IS in - // the JSON but not in those THINGS, it'll use the first - // one in the THINGS - // - // - Else, it'll use the value found from the JSON object. - // -#define empty_arg -#define __vmess_checker__func(key, values) \ - { \ - auto val = QStringList() values; \ - if (vmessConf.contains(#key) && !vmessConf[#key].toVariant().toString().trimmed().isEmpty() && \ - (val.size() <= 1 || val.contains(vmessConf[#key].toVariant().toString()))) \ - { \ - key = vmessConf[#key].toVariant().toString(); \ - } \ - else if (!val.isEmpty()) \ - { \ - key = val.first(); \ - DEBUG(MODULE_IMPORT, "Using key \"" #key "\" from the first candidate list: " + key) \ - } \ - else \ - { \ - *errMessage = QObject::tr(#key " does not exist."); \ - LOG(MODULE_IMPORT, "Cannot process \"" #key "\" since it's not included in the json object.") \ - LOG(MODULE_IMPORT, " --> values: " + val.join(";")) \ - LOG(MODULE_IMPORT, " --> PS: " + ps) \ - } \ - } - // Strict check of VMess protocol, to check if the specified value - // is in the correct range. - // - // Get Alias (AKA ps) from address and port. - { - __vmess_checker__func(ps, << vmessConf["add"].toVariant().toString() + ":" + vmessConf["port"].toVariant().toString()) // - __vmess_checker__func(add, empty_arg) // - __vmess_checker__func(id, empty_arg) // - __vmess_checker__func(net, << "tcp" // - << "http" // - << "h2" // - << "ws" // - << "kcp" // - << "domainsocket" // - << "quic") // - __vmess_checker__func(type, << "none" // - << "http" // - << "srtp" // - << "utp" // - << "wechat-video") // - __vmess_checker__func(path, << "") // - __vmess_checker__func(host, << "") // - __vmess_checker__func(tls, << "") // - - } // - port = vmessConf["port"].toVariant().toInt(); - aid = vmessConf["aid"].toVariant().toInt(); - // Apply the settings. - // - // User - VMessServerObject::UserObject user; - user.id = id; - user.alterId = aid; - // - // Server - VMessServerObject serv; - serv.port = port; - serv.address = add; - serv.users.push_back(user); - // - // VMess root config - OUTBOUNDSETTING vConf; - QJsonArray vnextArray; - vnextArray.append(JsonFromString(StructToJsonString(serv))); - vConf["vnext"] = vnextArray; - // - // Stream Settings - StreamSettingsObject streaming; - - if (net == "tcp") - { - streaming.tcpSettings.header.type = type; - } - else if (net == "http" || net == "h2") - { - // Fill hosts for HTTP - for (auto _host : host.split(',')) - { - streaming.httpSettings.host.push_back(_host.trimmed()); - } - - streaming.httpSettings.path = path; - } - else if (net == "ws") - { - streaming.wsSettings.headers["Host"] = host; - streaming.wsSettings.path = path; - } - else if (net == "kcp") - { - streaming.kcpSettings.header.type = type; - } - else if (net == "domainsocket") - { - streaming.dsSettings.path = path; - } - else if (net == "quic") - { - streaming.quicSettings.security = host; - streaming.quicSettings.header.type = type; - streaming.quicSettings.key = path; - } - - // FIXME: makeshift patch for #290. - // to be rewritten after refactoring. - if (tls == "tls" && host != "" && (net == "tcp" || net == "ws")) - { - streaming.tlsSettings.serverName = host; - streaming.tlsSettings.allowInsecure = false; - } - - streaming.security = tls; - // - // Network type - streaming.network = net; - // - // WARN Mux is missing here. - auto outbound = GenerateOutboundEntry("vmess", vConf, GetRootObject(streaming), QJsonObject(), "0.0.0.0", OUTBOUND_TAG_PROXY); - // - root["outbounds"] = QJsonArray() << outbound; - // If previous alias is empty, just the PS is needed, else, append a "_" - *alias = alias->trimmed().isEmpty() ? ps : *alias + "_" + ps; - return root; -#undef default - } } // namespace Serialization } // namespace Qv2ray::core::connection diff --git a/src/core/connection/Serialization.hpp b/src/core/connection/Serialization.hpp index 0e50dacf..1d8b2d8a 100644 --- a/src/core/connection/Serialization.hpp +++ b/src/core/connection/Serialization.hpp @@ -5,24 +5,32 @@ namespace Qv2ray::core::connection { namespace Serialization { - const auto QV2RAY_SERIALIZATION_COMPLEX_CONFIG_PLACEHOLDER = QObject::tr("(Complex Connection Config)"); - // int VerifyVMessProtocolString(QString vmess); - QString DecodeSubscriptionString(QByteArray arr); - // General + const auto QV2RAY_SERIALIZATION_COMPLEX_CONFIG_PLACEHOLDER = QObject::tr("(Complex Connection Config)"); + QString DecodeSubscriptionString(QByteArray arr); CONFIGROOT ConvertConfigFromString(const QString &link, QString *alias, QString *errMessage); const QString ConvertConfigToString(const ConnectionId &id, bool isSip002 = false); - + // // VMess URI Protocol - CONFIGROOT ConvertConfigFromVMessString(const QString &vmess, QString *alias, QString *errMessage); - const QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &server, const QString &alias); - + namespace vmess + { + CONFIGROOT ConvertConfigFromVMessString(const QString &vmess, QString *alias, QString *errMessage); + const QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &server, + const QString &alias); + } // namespace vmess + // // SS URI Protocol - CONFIGROOT ConvertConfigFromSSString(const QString &ss, QString *alias, QString *errMessage); - const QString ConvertConfigToSSString(const ShadowSocksServerObject &server, const QString &alias, bool isSip002); + namespace ss + { + CONFIGROOT ConvertConfigFromSSString(const QString &ss, QString *alias, QString *errMessage); + const QString ConvertConfigToSSString(const ShadowSocksServerObject &server, const QString &alias, bool isSip002); + } // namespace ss + // } // namespace Serialization } // namespace Qv2ray::core::connection using namespace Qv2ray::core; using namespace Qv2ray::core::connection; using namespace Qv2ray::core::connection::Serialization; +using namespace Qv2ray::core::connection::Serialization::ss; +using namespace Qv2ray::core::connection::Serialization::vmess; diff --git a/src/core/connection/Serialization_ss.cpp b/src/core/connection/Serialization_ss.cpp new file mode 100644 index 00000000..4f7c5e39 --- /dev/null +++ b/src/core/connection/Serialization_ss.cpp @@ -0,0 +1,130 @@ +#include "Generation.hpp" +#include "Serialization.hpp" +#include "common/QvHelpers.hpp" +#include "core/CoreUtils.hpp" +#include "core/handler/ConfigHandler.hpp" + +namespace Qv2ray::core::connection +{ + namespace Serialization::ss + { + CONFIGROOT ConvertConfigFromSSString(const QString &ssUri, QString *alias, QString *errMessage) + { + ShadowSocksServerObject server; + QString d_name; + + // auto ssUri = _ssUri.toStdString(); + if (ssUri.length() < 5) + { + LOG(MODULE_CONNECTION, "ss:// string too short") + *errMessage = QObject::tr("SS URI is too short"); + } + + auto uri = ssUri.mid(5); + auto hashPos = uri.lastIndexOf("#"); + DEBUG(MODULE_CONNECTION, "Hash sign position: " + QSTRN(hashPos)) + + if (hashPos >= 0) + { + // Get the name/remark + d_name = uri.mid(uri.lastIndexOf("#") + 1); + uri.truncate(hashPos); + } + + // No plugins for Qv2ray so disable those lnes.i + // size_t pluginPos = uri.find_first_of('/'); + // + // if (pluginPos != std::string::npos) { + // // TODO: support plugins. For now, just ignore them + // uri.erase(pluginPos); + //} + auto atPos = uri.indexOf('@'); + DEBUG(MODULE_CONNECTION, "At sign position: " + QSTRN(atPos)) + + if (atPos < 0) + { + // Old URI scheme + QString decoded = QByteArray::fromBase64(uri.toUtf8(), QByteArray::Base64Option::OmitTrailingEquals); + auto colonPos = decoded.indexOf(':'); + DEBUG(MODULE_CONNECTION, "Colon position: " + QSTRN(colonPos)) + + if (colonPos < 0) + { + *errMessage = QObject::tr("Can't find the colon separator between method and password"); + } + + server.method = decoded.left(colonPos); + decoded.remove(0, colonPos + 1); + atPos = decoded.lastIndexOf('@'); + DEBUG(MODULE_CONNECTION, "At sign position: " + QSTRN(atPos)) + + if (atPos < 0) + { + *errMessage = QObject::tr("Can't find the at separator between password and hostname"); + } + + server.password = decoded.mid(0, atPos); + decoded.remove(0, atPos + 1); + colonPos = decoded.lastIndexOf(':'); + DEBUG(MODULE_CONNECTION, "Colon position: " + QSTRN(colonPos)) + + if (colonPos < 0) + { + *errMessage = QObject::tr("Can't find the colon separator between hostname and port"); + } + + server.address = decoded.mid(0, colonPos); + server.port = decoded.mid(colonPos + 1).toInt(); + } + else + { + // SIP002 URI scheme + auto x = QUrl::fromUserInput(uri); + server.address = x.host(); + server.port = x.port(); + QString userInfo = Base64Decode(x.userName()); + auto userInfoSp = userInfo.indexOf(':'); + // + DEBUG(MODULE_CONNECTION, "Userinfo splitter position: " + QSTRN(userInfoSp)) + + if (userInfoSp < 0) + { + *errMessage = QObject::tr("Can't find the colon separator between method and password"); + } + + QString method = userInfo.mid(0, userInfoSp); + server.method = method; + server.password = userInfo.mid(userInfoSp + 1); + } + + d_name = QUrl::fromPercentEncoding(d_name.toUtf8()); + CONFIGROOT root; + OUTBOUNDS outbounds; + outbounds.append( + GenerateOutboundEntry("shadowsocks", GenerateShadowSocksOUT(QList{ server }), QJsonObject())); + JADD(outbounds) + *alias = alias->isEmpty() ? d_name : *alias + "_" + d_name; + LOG(MODULE_CONNECTION, "Deduced alias: " + *alias) + return root; + } + + const QString ConvertConfigToSSString(const ShadowSocksServerObject &server, const QString &alias, bool isSip002) + { + auto myAlias = QUrl::toPercentEncoding(alias); + + if (isSip002) + { + LOG(MODULE_CONNECTION, "Converting an ss-server config to Sip002 ss:// format") + QString plainUserInfo = server.method + ":" + server.password; + QString userinfo(plainUserInfo.toUtf8().toBase64(QByteArray::Base64Option::Base64UrlEncoding).data()); + return "ss://" + userinfo + "@" + server.address + ":" + QSTRN(server.port) + "#" + myAlias; + } + else + { + LOG(MODULE_CONNECTION, "Converting an ss-server config to old ss:// string format") + QString ssUri = server.method + ":" + server.password + "@" + server.address + ":" + QSTRN(server.port); + return "ss://" + ssUri.toUtf8().toBase64(QByteArray::Base64Option::OmitTrailingEquals) + "#" + myAlias; + } + } + } // namespace Serialization::ss +} // namespace Qv2ray::core::connection diff --git a/src/core/connection/Serialization_vmess.cpp b/src/core/connection/Serialization_vmess.cpp new file mode 100644 index 00000000..572e1452 --- /dev/null +++ b/src/core/connection/Serialization_vmess.cpp @@ -0,0 +1,292 @@ +#include "Generation.hpp" +#include "Serialization.hpp" +#include "common/QvHelpers.hpp" +#include "core/CoreUtils.hpp" +#include "core/handler/ConfigHandler.hpp" + +namespace Qv2ray::core::connection +{ + namespace Serialization::vmess + { + + // From + // https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2) + const QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &server, const QString &alias) + { + QJsonObject vmessUriRoot; + // Constant + vmessUriRoot["v"] = 2; + vmessUriRoot["ps"] = alias; + vmessUriRoot["add"] = server.address; + vmessUriRoot["port"] = server.port; + vmessUriRoot["id"] = server.users.front().id; + vmessUriRoot["aid"] = server.users.front().alterId; + vmessUriRoot["net"] = transfer.network; + vmessUriRoot["tls"] = transfer.security; + + if (transfer.network == "tcp") + { + vmessUriRoot["type"] = transfer.tcpSettings.header.type; + } + else if (transfer.network == "kcp") + { + vmessUriRoot["type"] = transfer.kcpSettings.header.type; + } + else if (transfer.network == "quic") + { + vmessUriRoot["type"] = transfer.quicSettings.header.type; + vmessUriRoot["host"] = transfer.quicSettings.security; + vmessUriRoot["path"] = transfer.quicSettings.key; + } + else if (transfer.network == "ws") + { + auto x = transfer.wsSettings.headers; + auto host = x.contains("host"); + auto CapHost = x.contains("Host"); + auto realHost = host ? x["host"] : (CapHost ? x["Host"] : ""); + // + vmessUriRoot["host"] = realHost; + vmessUriRoot["path"] = transfer.wsSettings.path; + } + else if (transfer.network == "h2" || transfer.network == "http") + { + vmessUriRoot["host"] = transfer.httpSettings.host.join(","); + vmessUriRoot["path"] = transfer.httpSettings.path; + } + + // + auto vmessPart = Base64Encode(JsonToString(vmessUriRoot, QJsonDocument::JsonFormat::Compact)); + return "vmess://" + vmessPart; + } + // This generates global config containing only one outbound.... + CONFIGROOT ConvertConfigFromVMessString(const QString &vmessStr, QString *alias, QString *errMessage) + { +#define default CONFIGROOT() + LOG(MODULE_SETTINGS, "Trying to convert from a vmess string.") + QString vmess = vmessStr; + + if (vmess.trimmed() != vmess) + { + LOG(MODULE_SETTINGS, "VMess string has some prefix/postfix spaces, trimming.") + vmess = vmessStr.trimmed(); + } + + // Reset errMessage + *errMessage = ""; + + if (!vmess.toLower().startsWith("vmess://")) + { + *errMessage = QObject::tr("VMess string should start with 'vmess://'"); + return default; + } + + try + { + QStringRef vmessJsonB64(&vmess, 8, vmess.length() - 8); + auto b64Str = vmessJsonB64.toString(); + + if (b64Str.isEmpty()) + { + *errMessage = QObject::tr("VMess string should be a valid base64 string"); + return default; + } + + auto vmessString = Base64Decode(b64Str); + auto jsonErr = VerifyJsonString(vmessString); + + if (!jsonErr.isEmpty()) + { + *errMessage = jsonErr; + return default; + } + + auto vmessConf = JsonFromString(vmessString); + + if (vmessConf.isEmpty()) + { + *errMessage = QObject::tr("JSON should not be empty"); + return default; + } + + bool flag = true; + // C is a quick hack... +#define C(k) vmessConf.contains(k) + // id, aid, port and add are mandatory fields of a vmess:// + // link. + flag = flag && C("id") && C("aid") && C("port") && C("add"); + // Stream Settings + auto net = C("net") ? vmessConf["net"].toString() : "tcp"; + + if (net == "http" || net == "ws") + flag = flag && C("host") && C("path"); + else if (net == "domainsocket") + flag = flag && C("path"); + else if (net == "quic") + flag = flag && C("host") && C("type") && C("path"); + +#undef C + // return flag ? 0 : 1; + } + catch (exception *e) + { + *errMessage = e->what(); + LOG(MODULE_IMPORT, "Failed to decode vmess string: " + *errMessage) + delete e; + return default; + } + + // -------------------------------------------------------------------------------------- + CONFIGROOT root; + auto b64String = QStringRef(&vmess, 8, vmess.length() - 8).toString(); + auto vmessConf = JsonFromString(Base64Decode(b64String)); + // + QString ps, add, id, net, type, host, path, tls; + int port, aid; + // + // key = key in JSON and the variable name. + // values = Candidate variable list, if not match, the first one is + // used as default. + // [[val.size() <= 1]] is used when only the default value + // exists. + /// + // - It can be empty, if so, if the key is not in + // the JSON, or the value is empty, it'll report an error. + // + // - Else if it contains one thing. if the key is not in + // the JSON, or the value is empty, it'll use that one. + // + // - Else if it contains many things, when the key IS in + // the JSON but not in those THINGS, it'll use the first + // one in the THINGS + // + // - Else, it'll use the value found from the JSON object. + // +#define empty_arg +#define __vmess_checker__func(key, values) \ + { \ + auto val = QStringList() values; \ + if (vmessConf.contains(#key) && !vmessConf[#key].toVariant().toString().trimmed().isEmpty() && \ + (val.size() <= 1 || val.contains(vmessConf[#key].toVariant().toString()))) \ + { \ + key = vmessConf[#key].toVariant().toString(); \ + } \ + else if (!val.isEmpty()) \ + { \ + key = val.first(); \ + DEBUG(MODULE_IMPORT, "Using key \"" #key "\" from the first candidate list: " + key) \ + } \ + else \ + { \ + *errMessage = QObject::tr(#key " does not exist."); \ + LOG(MODULE_IMPORT, "Cannot process \"" #key "\" since it's not included in the json object.") \ + LOG(MODULE_IMPORT, " --> values: " + val.join(";")) \ + LOG(MODULE_IMPORT, " --> PS: " + ps) \ + } \ + } + // Strict check of VMess protocol, to check if the specified value + // is in the correct range. + // + // Get Alias (AKA ps) from address and port. + { + __vmess_checker__func(ps, << vmessConf["add"].toVariant().toString() + ":" + vmessConf["port"].toVariant().toString()) // + __vmess_checker__func(add, empty_arg) // + __vmess_checker__func(id, empty_arg) // + __vmess_checker__func(net, << "tcp" // + << "http" // + << "h2" // + << "ws" // + << "kcp" // + << "domainsocket" // + << "quic") // + __vmess_checker__func(type, << "none" // + << "http" // + << "srtp" // + << "utp" // + << "wechat-video") // + __vmess_checker__func(path, << "") // + __vmess_checker__func(host, << "") // + __vmess_checker__func(tls, << "") // + + } // + port = vmessConf["port"].toVariant().toInt(); + aid = vmessConf["aid"].toVariant().toInt(); + // Apply the settings. + // + // User + VMessServerObject::UserObject user; + user.id = id; + user.alterId = aid; + // + // Server + VMessServerObject serv; + serv.port = port; + serv.address = add; + serv.users.push_back(user); + // + // VMess root config + OUTBOUNDSETTING vConf; + QJsonArray vnextArray; + vnextArray.append(JsonFromString(StructToJsonString(serv))); + vConf["vnext"] = vnextArray; + // + // Stream Settings + StreamSettingsObject streaming; + + if (net == "tcp") + { + streaming.tcpSettings.header.type = type; + } + else if (net == "http" || net == "h2") + { + // Fill hosts for HTTP + for (auto _host : host.split(',')) + { + streaming.httpSettings.host.push_back(_host.trimmed()); + } + + streaming.httpSettings.path = path; + } + else if (net == "ws") + { + streaming.wsSettings.headers["Host"] = host; + streaming.wsSettings.path = path; + } + else if (net == "kcp") + { + streaming.kcpSettings.header.type = type; + } + else if (net == "domainsocket") + { + streaming.dsSettings.path = path; + } + else if (net == "quic") + { + streaming.quicSettings.security = host; + streaming.quicSettings.header.type = type; + streaming.quicSettings.key = path; + } + + // FIXME: makeshift patch for #290. + // to be rewritten after refactoring. + if (tls == "tls" && host != "" && (net == "tcp" || net == "ws")) + { + streaming.tlsSettings.serverName = host; + streaming.tlsSettings.allowInsecure = false; + } + + streaming.security = tls; + // + // Network type + streaming.network = net; + // + // WARN Mux is missing here. + auto outbound = GenerateOutboundEntry("vmess", vConf, GetRootObject(streaming), QJsonObject(), "0.0.0.0", OUTBOUND_TAG_PROXY); + // + root["outbounds"] = QJsonArray() << outbound; + // If previous alias is empty, just the PS is needed, else, append a "_" + *alias = alias->trimmed().isEmpty() ? ps : *alias + "_" + ps; + return root; +#undef default + } + } // namespace Serialization::vmess +} // namespace Qv2ray::core::connection diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 1df106c9..75603529 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -133,7 +133,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) }); // connect(infoWidget, &ConnectionInfoWidget::OnEditRequested, this, &MainWindow::OnEditRequested); - connect(infoWidget, &ConnectionInfoWidget::OnJsonEditRequested, this, &MainWindow::OnJsonEditRequested); + connect(infoWidget, &ConnectionInfoWidget::OnJsonEditRequested, this, &MainWindow::OnEditJsonRequested); // // Setup System tray icons and menus hTray.setToolTip(TRAY_TOOLTIP_PREFIX); @@ -168,22 +168,30 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) // connect(action_Tray_Quit, &QAction::triggered, this, &MainWindow::on_actionExit_triggered); connect(action_Tray_SetSystemProxy, &QAction::triggered, this, &MainWindow::MWSetSystemProxy); - connect(action_Tray_ClearSystemProxy, &QAction::triggered, [&] { ClearSystemProxy(); }); + connect(action_Tray_ClearSystemProxy, &QAction::triggered, &ClearSystemProxy); connect(&hTray, &QSystemTrayIcon::activated, this, &MainWindow::on_activatedTray); // // Actions for right click the connection list // - QAction *action_RCM_StartThis = new QAction(tr("Connect to this"), this); + QAction *action_RCM_StartThis = new QAction(QICON_R("connect.png"), tr("Connect to this"), this); + // + QAction *action_RCM_EditThis = new QAction(QICON_R("edit.png"), tr("Edit"), this); + QAction *action_RCM_EditAsJson = new QAction(QICON_R("json.png"), tr("Edit as JSON"), this); + QAction *action_RCM_EditAsComplex = new QAction(QICON_R("edit.png"), tr("Edit as Complex Config"), this); + // QAction *action_RCM_RenameThis = new QAction(tr("Rename"), this); - QAction *action_RCM_DeleteThese = new QAction(tr("Delete Connection"), this); QAction *action_RCM_DuplicateThese = new QAction(QICON_R("duplicate.png"), tr("Duplicate to the Same Group"), this); - QAction *action_RCM_ConvToComplex = new QAction(QICON_R("edit.png"), tr("Edit as Complex Config"), this); + QAction *action_RCM_DeleteThese = new QAction(QICON_R("delete.png"), tr("Delete Connection"), this); // connect(action_RCM_StartThis, &QAction::triggered, this, &MainWindow::on_action_StartThis_triggered); - connect(action_RCM_ConvToComplex, &QAction::triggered, this, &MainWindow::on_action_RCM_ConvToComplex_triggered); + // + connect(action_RCM_EditThis, &QAction::triggered, this, &MainWindow::on_action_RCM_EditThis_triggered); + connect(action_RCM_EditAsJson, &QAction::triggered, this, &MainWindow::on_action_RCM_EditAsJson_triggered); + connect(action_RCM_EditAsComplex, &QAction::triggered, this, &MainWindow::on_action_RCM_EditAsComplex_triggered); + // connect(action_RCM_RenameThis, &QAction::triggered, this, &MainWindow::on_action_RCM_RenameThis_triggered); - connect(action_RCM_DeleteThese, &QAction::triggered, this, &MainWindow::on_action_RCM_DeleteThese_triggered); connect(action_RCM_DuplicateThese, &QAction::triggered, this, &MainWindow::on_action_RCM_DuplicateThese_triggered); + connect(action_RCM_DeleteThese, &QAction::triggered, this, &MainWindow::on_action_RCM_DeleteThese_triggered); // // Globally invokable signals. connect(this, &MainWindow::StartConnection, ConnectionManager, &QvConfigHandler::RestartConnection); @@ -195,10 +203,15 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) // connectionListMenu = new QMenu(this); connectionListMenu->addAction(action_RCM_StartThis); + connectionListMenu->addSeparator(); + connectionListMenu->addAction(action_RCM_EditThis); + connectionListMenu->addAction(action_RCM_EditAsJson); + connectionListMenu->addAction(action_RCM_EditAsComplex); + connectionListMenu->addSeparator(); connectionListMenu->addAction(action_RCM_RenameThis); connectionListMenu->addAction(action_RCM_DuplicateThese); + connectionListMenu->addSeparator(); connectionListMenu->addAction(action_RCM_DeleteThese); - connectionListMenu->addAction(action_RCM_ConvToComplex); // QMenu *sortMenu = new QMenu(tr("Sort connection list."), this); QAction *sortAction_SortByName_Asc = new QAction(tr("By connection name, A-Z")); @@ -217,14 +230,17 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) // sortMenu->addAction(sortAction_SortByName_Asc); sortMenu->addAction(sortAction_SortByName_Dsc); + tray_RootMenu->addSeparator(); sortMenu->addAction(sortAction_SortByData_Asc); sortMenu->addAction(sortAction_SortByData_Dsc); + tray_RootMenu->addSeparator(); sortMenu->addAction(sortAction_SortByLatency_Asc); sortMenu->addAction(sortAction_SortByLatency_Dsc); // sortBtn->setMenu(sortMenu); // - LOG(MODULE_UI, "Loading data...") auto groups = ConnectionManager->AllGroups(); + LOG(MODULE_UI, "Loading data...") // + auto groups = ConnectionManager->AllGroups(); for (auto group : groups) { @@ -497,7 +513,7 @@ void MainWindow::on_importConfigButton_clicked() } } -void MainWindow::on_action_RCM_ConvToComplex_triggered() +void MainWindow::on_action_RCM_EditAsComplex_triggered() { CheckCurrentWidget; if (widget->IsConnection()) @@ -784,7 +800,7 @@ void MainWindow::OnEditRequested(const ConnectionId &id) ConnectionManager->UpdateConnection(id, root); } } -void MainWindow::OnJsonEditRequested(const ConnectionId &id) +void MainWindow::OnEditJsonRequested(const ConnectionId &id) { JsonEditor w(ConnectionManager->GetConnectionRoot(id), this); auto root = CONFIGROOT(w.OpenEditor()); @@ -872,3 +888,15 @@ void MainWindow::on_action_RCM_DuplicateThese_triggered() ConnectionManager->GetConnectionRoot(conn)); } } + +void MainWindow::on_action_RCM_EditThis_triggered() +{ + CheckCurrentWidget; + OnEditRequested(get<1>(widget->Identifier())); +} + +void MainWindow::on_action_RCM_EditAsJson_triggered() +{ + CheckCurrentWidget; + OnEditJsonRequested(get<1>(widget->Identifier())); +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 6ff3ec0c..1c8862cf 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -65,7 +65,7 @@ class MainWindow private slots: void OnEditRequested(const ConnectionId &id); - void OnJsonEditRequested(const ConnectionId &id); + void OnEditJsonRequested(const ConnectionId &id); // void OnConnectionWidgetFocusRequested(const ConnectionItemWidget *widget); // @@ -83,7 +83,9 @@ class MainWindow void OnGroupDeleted(const GroupId &id, const QList &connections); // void on_action_StartThis_triggered(); - void on_action_RCM_ConvToComplex_triggered(); + void on_action_RCM_EditThis_triggered(); + void on_action_RCM_EditAsJson_triggered(); + void on_action_RCM_EditAsComplex_triggered(); void on_action_RCM_RenameThis_triggered(); void on_action_RCM_DeleteThese_triggered(); void on_action_RCM_DuplicateThese_triggered(); From 5c84d8d583fd5ca8f4a4ab5bd08ec944e8da3d3e Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 00:09:23 +0800 Subject: [PATCH 093/332] add: added basic SSD decoder, by @DuckSoft --- src/core/connection/SSDConverter.hpp | 240 ---------------------- src/core/connection/Serialization.hpp | 28 ++- src/core/connection/Serialization_ssd.cpp | 235 +++++++++++++++++++++ 3 files changed, 262 insertions(+), 241 deletions(-) delete mode 100644 src/core/connection/SSDConverter.hpp create mode 100644 src/core/connection/Serialization_ssd.cpp diff --git a/src/core/connection/SSDConverter.hpp b/src/core/connection/SSDConverter.hpp deleted file mode 100644 index b23854a3..00000000 --- a/src/core/connection/SSDConverter.hpp +++ /dev/null @@ -1,240 +0,0 @@ -#pragma once - -#include "base/Qv2rayBase.hpp" -#include "common/QvHelpers.hpp" - -namespace Qv2ray::core::handlers -{ - /** - * A Naive SSD Decoder for Qv2ray - * - * @author DuckSoft - * @copyright Licensed under GPLv3. - */ - namespace ssd - { - /** - * pattern for the nodes in ssd links. - * - * %1: airport name - * %2: node name - * %3: rate - */ - inline auto DEFAULT_NAME_PATTERN = QString::tr("%1 - %2 (rate %3)"); - - /** - * @brief decodeSSD - * @param uri the uri of ssd link. - * @param pattern the pattern for node names. - * @return tuple of: - * - tuple of: - * - airport name (for the sake of grouping) - * - shadowsocks configuration list - * - log list - * in case of error, no objects will be returned. - */ - std::pair>>>, QStringList> decodeSSD( - const QString &uri, const QString &pattern = DEFAULT_NAME_PATTERN); - } // namespace ssd -} // namespace Qv2ray::core::handlers - -#define MUST_EXIST(fieldName) \ - if (obj[(fieldName)].isUndefined()) \ - { \ - logList << QObject::tr("invalid ssd link: json: field %1 must exist").arg(fieldName); \ - return std::make_pair(std::nullopt, logList); \ - } -#define MUST_PORT(fieldName) \ - MUST_EXIST(fieldName); \ - if (int value = obj[(fieldName)].toInt(-1); value < 0 || value > 65535) \ - { \ - logList << QObject::tr("invalid ssd link: json: field %1 must be valid port number"); \ - return std::make_pair(std::nullopt, logList); \ - } -#define MUST_STRING(fieldName) \ - MUST_EXIST(fieldName); \ - if (!obj[(fieldName)].isString()) \ - { \ - logList << QObject::tr("invalid ssd link: json: field %1 must be of type 'string'").arg(fieldName); \ - return std::make_pair(std::nullopt, logList); \ - } -#define MUST_ARRAY(fieldName) \ - MUST_EXIST(fieldName); \ - if (!obj[(fieldName)].isArray()) \ - { \ - logList << QObject::tr("invalid ssd link: json: field %1 must be an array").arg(fieldName); \ - return std::make_pair(std::nullopt, logList); \ - } - -#define SERVER_SHOULD_BE_OBJECT(server) \ - if (!server.isObject()) \ - { \ - logList << QObject::tr("skipping invalid ssd server: server must be an object"); \ - continue; \ - } -#define SHOULD_EXIST(fieldName) \ - if (serverObject[(fieldName)].isUndefined()) \ - { \ - logList << QObject::tr("skipping invalid ssd server: missing required field %1").arg(fieldName); \ - continue; \ - } -#define SHOULD_STRING(fieldName) \ - SHOULD_EXIST(fieldName); \ - if (!serverObject[(fieldName)].isString()) \ - { \ - logList << QObject::tr("skipping invalid ssd server: field %1 should be of type 'string'").arg(fieldName); \ - continue; \ - } - -std::pair>>>, QStringList> Qv2ray::core::handlers::ssd:: - decodeSSD(const QString &uri, const QString &pattern) -{ - // The list for the parsing log. - QStringList logList; - - // ssd links should begin with "ssd://" - if (!uri.startsWith("ssd://")) - { - logList << QObject::tr("invalid ssd link: should begin with ssd://"); - return std::make_pair(std::nullopt, logList); - } - - // decode base64 - const auto ssdURIBody = QStringRef(&uri, 5, uri.length() - 6); - const auto decodedJSON = QByteArray::fromBase64(ssdURIBody.toUtf8()); - - if (decodedJSON.length() == 0) - { - logList << QObject::tr("invalid ssd link: base64 parse failed"); - return std::make_pair(std::nullopt, logList); - } - - // parse json - QJsonParseError err; - QJsonDocument document = QJsonDocument::fromJson(decodedJSON, &err); - - if (document.isNull()) - { - logList << QObject::tr("invalid ssd link: json parse failed: ") % err.errorString(); - return std::make_pair(std::nullopt, logList); - } - - // json should be an object - if (!document.isObject()) - { - logList << QObject::tr("invalid ssd link: found non-object json, aborting"); - return std::make_pair(std::nullopt, logList); - } - - // casting to object - QJsonObject obj = document.object(); - // - // obj.airport - MUST_STRING("airport"); - const QString airport = obj["airport"].toString(); - // obj.port - MUST_PORT("port"); - const int port = obj["port"].toInt(); - // obj.encryption - MUST_STRING("encryption"); - const QString encryption = obj["encryption"].toString(); - - // check: rc4-md5 is not supported by v2ray-core - // TODO: more checks, including all algorithms - if (encryption == "rc4-md5") - { - logList << QObject::tr("invalid ssd link: rc4-md5 encryption is not supported by v2ray-core"); - return std::make_pair(std::nullopt, logList); - } - - // obj.password - MUST_STRING("password"); - const QString password = obj["password"].toString(); - // obj.servers - MUST_ARRAY("servers"); - // - QList> serverList; - // - - // iterate through the servers - for (QJsonValueRef server : obj["servers"].toArray()) - { - SERVER_SHOULD_BE_OBJECT(server); - QJsonObject serverObject = server.toObject(); - ShadowSocksServerObject ssObject; - // encryption - ssObject.method = encryption; - // password - ssObject.password = password; - // address :-> "server" - SHOULD_STRING("server"); - const QString serverAddress = serverObject["server"].toString(); - ssObject.address = serverAddress; - - // port selection: - // normal: use global settings - // overriding: use current config - if (serverObject["port"].isUndefined()) - { - ssObject.port = port; - } - else if (auto currPort = serverObject["port"].toInt(-1); port >= 0 && port <= 65535) - { - ssObject.port = currPort; - } - else - { - logList << QObject::tr("warning: invalid port encountered. using fallback value."); - ssObject.port = port; - } - - // name decision: - // untitled: using server:port as name - // entitled: using given name - QString nodeName; - - if (serverObject["remarks"].isUndefined()) - { - nodeName = QString("%1:%2").arg(ssObject.address).arg(ssObject.port); - } - else if (serverObject["remarks"].isString()) - { - nodeName = serverObject["remarks"].toString(); - } - else - { - logList << QObject::tr("warning: invalid name encountered. using fallback value."); - nodeName = QString("%1:%2").arg(ssObject.address).arg(ssObject.port); - } - - // ratio decision: - // unspecified: ratio = 1 - // specified: use given value - double ratio = 1.0; - - if (auto currRatio = serverObject["ratio"].toDouble(-1.0); currRatio != -1.0) - { - ratio = currRatio; - } - else if (!serverObject["ratio"].isUndefined()) - { - logList << QObject::tr("warning: invalid ratio encountered. using fallback value."); - } - - // format the total name of the node. - const QString totalName = pattern.arg(airport, nodeName).arg(ratio); - // appending to the total list - serverList.append(make_pair(totalName, ssObject)); - } - - // returns the current result - return std::make_pair(std::make_pair(airport, serverList), logList); -} - -#undef MUST_EXIST -#undef MUST_PORT -#undef MUST_ARRAY -#undef MUST_STRING -#undef SERVER_SHOULD_BE_OBJECT -#undef SHOULD_EXIST -#undef SHOULD_STRING diff --git a/src/core/connection/Serialization.hpp b/src/core/connection/Serialization.hpp index 1d8b2d8a..d9fa6620 100644 --- a/src/core/connection/Serialization.hpp +++ b/src/core/connection/Serialization.hpp @@ -5,8 +5,15 @@ namespace Qv2ray::core::connection { namespace Serialization { + /** + * pattern for the nodes in ssd links. + * %1: airport name + * %2: node name + * %3: rate + */ + inline auto QV2RAY_SSD_DEFAULT_NAME_PATTERN = QObject::tr("%1 - %2 (rate %3)"); + // // General - const auto QV2RAY_SERIALIZATION_COMPLEX_CONFIG_PLACEHOLDER = QObject::tr("(Complex Connection Config)"); QString DecodeSubscriptionString(QByteArray arr); CONFIGROOT ConvertConfigFromString(const QString &link, QString *alias, QString *errMessage); const QString ConvertConfigToString(const ConnectionId &id, bool isSip002 = false); @@ -26,6 +33,24 @@ namespace Qv2ray::core::connection const QString ConvertConfigToSSString(const ShadowSocksServerObject &server, const QString &alias, bool isSip002); } // namespace ss // + // SSD URI Protocol + namespace ssd + { + /** + * @brief decodeSSD + * @param uri the uri of ssd link. + * @param pattern the pattern for node names. + * @return tuple of: + * - tuple of: + * - airport name (for the sake of grouping) + * - shadowsocks configuration list + * - log list + * in case of error, no objects will be returned. + */ + std::pair>>>, QStringList> // + ConvertConfigFromSSDString(const QString &uri, const QString &pattern = QV2RAY_SSD_DEFAULT_NAME_PATTERN); + } // namespace ssd + // } // namespace Serialization } // namespace Qv2ray::core::connection @@ -33,4 +58,5 @@ using namespace Qv2ray::core; using namespace Qv2ray::core::connection; using namespace Qv2ray::core::connection::Serialization; using namespace Qv2ray::core::connection::Serialization::ss; +using namespace Qv2ray::core::connection::Serialization::ssd; using namespace Qv2ray::core::connection::Serialization::vmess; diff --git a/src/core/connection/Serialization_ssd.cpp b/src/core/connection/Serialization_ssd.cpp new file mode 100644 index 00000000..ebd75049 --- /dev/null +++ b/src/core/connection/Serialization_ssd.cpp @@ -0,0 +1,235 @@ +/** + * A Naive SSD Decoder for Qv2ray + * + * @author DuckSoft + * @copyright Licensed under GPLv3. + */ + +#pragma once + +#include "base/Qv2rayBase.hpp" +#include "common/QvHelpers.hpp" +#include "core/connection/Serialization.hpp" + +namespace Qv2ray::core::connection::Serialization +{ + + namespace ssd + { + // +#define default \ + { \ + {}, logList \ + } + // These below are super strict checking schemes, but necessary. +#define MUST_EXIST(fieldName) \ + if (!obj.contains((fieldName)) || obj[(fieldName)].isUndefined() || obj[(fieldName)].isNull()) \ + { \ + logList << QObject::tr("invalid ssd link: json: field %1 must exist").arg(fieldName); \ + return std::make_pair(std::nullopt, logList); \ + } +#define MUST_PORT(fieldName) \ + MUST_EXIST(fieldName); \ + if (int value = obj[(fieldName)].toInt(-1); value < 0 || value > 65535) \ + { \ + logList << QObject::tr("invalid ssd link: json: field %1 must be valid port number"); \ + return std::make_pair(std::nullopt, logList); \ + } +#define MUST_STRING(fieldName) \ + MUST_EXIST(fieldName); \ + if (!obj[(fieldName)].isString()) \ + { \ + logList << QObject::tr("invalid ssd link: json: field %1 must be of type 'string'").arg(fieldName); \ + return std::make_pair(std::nullopt, logList); \ + } +#define MUST_ARRAY(fieldName) \ + MUST_EXIST(fieldName); \ + if (!obj[(fieldName)].isArray()) \ + { \ + logList << QObject::tr("invalid ssd link: json: field %1 must be an array").arg(fieldName); \ + return std::make_pair(std::nullopt, logList); \ + } + +#define SERVER_SHOULD_BE_OBJECT(server) \ + if (!server.isObject()) \ + { \ + logList << QObject::tr("skipping invalid ssd server: server must be an object"); \ + continue; \ + } +#define SHOULD_EXIST(fieldName) \ + if (serverObject[(fieldName)].isUndefined()) \ + { \ + logList << QObject::tr("skipping invalid ssd server: missing required field %1").arg(fieldName); \ + continue; \ + } +#define SHOULD_STRING(fieldName) \ + SHOULD_EXIST(fieldName); \ + if (!serverObject[(fieldName)].isString()) \ + { \ + logList << QObject::tr("skipping invalid ssd server: field %1 should be of type 'string'").arg(fieldName); \ + continue; \ + } + + // std::pair>>>, QStringList> + // AKA + // + // pair>>>, QStringList> + // That is.... + // + // A pair of an error string list, together with some optionally existed pair, which contains a QString for airport name and a List of + // pairs that contains a QString for connection name and finally, our ShadowSocksServerObject + // + std::pair>>>, QStringList> // + ConvertConfigFromSSDString(const QString &uri, const QString &pattern) + { + // The list for the parsing log. + QStringList logList; + + // ssd links should begin with "ssd://" + if (!uri.startsWith("ssd://")) + { + logList << QObject::tr("Invalid ssd link: should begin with ssd://"); + return default; + } + + // decode base64 + const auto ssdURIBody = QStringRef(&uri, 5, uri.length() - 6); + const auto decodedJSON = QByteArray::fromBase64(ssdURIBody.toUtf8()); + + if (decodedJSON.length() == 0) + { + logList << QObject::tr("Invalid ssd link: base64 parse failed"); + return default; + } + + // parse json + QJsonParseError err; + QJsonDocument document = QJsonDocument::fromJson(decodedJSON, &err); + + if (document.isNull()) + { + logList << QObject::tr("Invalid ssd link: json parse failed: ") % err.errorString(); + return default; + } + + // json should be an object + if (!document.isObject()) + { + logList << QObject::tr("Invalid ssd link: found non-object json, aborting"); + return default; + } + + // casting to object + QJsonObject obj = document.object(); + // + // obj.airport + MUST_STRING("airport"); + const QString airport = obj["airport"].toString(); + // obj.port + MUST_PORT("port"); + const int port = obj["port"].toInt(); + // obj.encryption + MUST_STRING("encryption"); + const QString encryption = obj["encryption"].toString(); + + // check: rc4-md5 is not supported by v2ray-core + // TODO: more checks, including all algorithms + if (encryption.toLower() == "rc4-md5") + { + logList << QObject::tr("Invalid ssd link: rc4-md5 encryption is not supported by v2ray-core"); + return default; + } + + // obj.password + MUST_STRING("password"); + const QString password = obj["password"].toString(); + // obj.servers + MUST_ARRAY("servers"); + // + QList> serverList; + // + + // iterate through the servers + for (QJsonValueRef server : obj["servers"].toArray()) + { + SERVER_SHOULD_BE_OBJECT(server); + QJsonObject serverObject = server.toObject(); + ShadowSocksServerObject ssObject; + // encryption + ssObject.method = encryption; + // password + ssObject.password = password; + // address :-> "server" + SHOULD_STRING("server"); + const QString serverAddress = serverObject["server"].toString(); + ssObject.address = serverAddress; + + // port selection: + // normal: use global settings + // overriding: use current config + if (serverObject["port"].isUndefined()) + { + ssObject.port = port; + } + else if (auto currPort = serverObject["port"].toInt(-1); port >= 0 && port <= 65535) + { + ssObject.port = currPort; + } + else + { + logList << QObject::tr("Invalid port encountered. using fallback value."); + ssObject.port = port; + } + + // name decision: + // untitled: using server:port as name + // entitled: using given name + QString nodeName; + + if (serverObject["remarks"].isUndefined()) + { + nodeName = QString("%1:%2").arg(ssObject.address).arg(ssObject.port); + } + else if (serverObject["remarks"].isString()) + { + nodeName = serverObject["remarks"].toString(); + } + else + { + logList << QObject::tr("Invalid name encountered. using fallback value."); + nodeName = QString("%1:%2").arg(ssObject.address).arg(ssObject.port); + } + + // ratio decision: + // unspecified: ratio = 1 + // specified: use given value + double ratio = 1.0; + + if (auto currRatio = serverObject["ratio"].toDouble(-1.0); currRatio != -1.0) + { + ratio = currRatio; + } + else if (!serverObject["ratio"].isUndefined()) + { + logList << QObject::tr("Invalid ratio encountered. using fallback value."); + } + + // format the total name of the node. + const QString totalName = pattern.arg(airport, nodeName).arg(ratio); + // appending to the total list + serverList.append(make_pair(totalName, ssObject)); + } + + // returns the current result + return std::make_pair(std::make_pair(airport, serverList), logList); + } +#undef default +#undef MUST_EXIST +#undef MUST_PORT +#undef MUST_ARRAY +#undef MUST_STRING +#undef SERVER_SHOULD_BE_OBJECT +#undef SHOULD_EXIST +#undef SHOULD_STRING + } // namespace ssd +} // namespace Qv2ray::core::connection::Serialization From 93208f698cdf653c226db0469d1a9763ba1ead9d Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 00:10:40 +0800 Subject: [PATCH 094/332] add: added missing files --- Qv2ray.pro | 3 +++ makespec/BUILDVERSION | 2 +- src/base/Qv2rayBase.hpp | 2 +- src/core/CoreSafeTypes.hpp | 11 ++++++----- src/core/CoreUtils.cpp | 19 +++++++++++++++---- src/core/settings/SettingsUpgrade.cpp | 2 +- src/main.cpp | 2 +- 7 files changed, 28 insertions(+), 13 deletions(-) diff --git a/Qv2ray.pro b/Qv2ray.pro index 0f582072..1886eea5 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -82,9 +82,12 @@ Qv2rayAddSource(core, settings, SettingsBackend, cpp, hpp) Qv2rayAddSource(core, settings, SettingsUpgrade, cpp) Qv2rayAddSource(core, connection, ConnectionIO, cpp, hpp) Qv2rayAddSource(core, connection, Generation, cpp, hpp) +# Some serializations Qv2rayAddSource(core, connection, Serialization, cpp, hpp) Qv2rayAddSource(core, connection, Serialization_vmess, cpp) Qv2rayAddSource(core, connection, Serialization_ss, cpp) +Qv2rayAddSource(core, connection, Serialization_ssd, cpp) +# Qv2rayAddSource(core, kernel, KernelInteractions, cpp, hpp) Qv2rayAddSource(core, kernel, APIBackend, cpp, hpp) Qv2rayAddSource(core, tcping, QvTCPing, cpp, hpp) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 032405f2..113c7be3 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4439 +4449 diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index d897ad6c..515202c1 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -126,7 +126,7 @@ using namespace Qv2ray::base::objects::transfer; namespace Qv2ray { // Extra header for QvConfigUpgrade.cpp - QJsonObject UpgradeConfig(int fromVersion, int toVersion, QJsonObject root); + QJsonObject UpgradeSettingsVersion(int fromVersion, int toVersion, QJsonObject root); inline void ExitQv2ray() { diff --git a/src/core/CoreSafeTypes.hpp b/src/core/CoreSafeTypes.hpp index 67360464..283caa91 100644 --- a/src/core/CoreSafeTypes.hpp +++ b/src/core/CoreSafeTypes.hpp @@ -8,8 +8,9 @@ namespace Qv2ray::core { + static const inline auto QV2RAY_SERIALIZATION_COMPLEX_CONFIG_PLACEHOLDER = QObject::tr("(Complex config)"); template - class IDType + class IDType final { public: explicit IDType() : m_id("null") @@ -45,8 +46,8 @@ namespace Qv2ray::core typedef IDType<__QvGroup> GroupId; typedef IDType<__QvConnection> ConnectionId; - inline const static ConnectionId NullConnectionId = ConnectionId("null"); - inline const static GroupId NullGroupId = GroupId("null"); + inline const static auto NullConnectionId = ConnectionId("null"); + inline const static auto NullGroupId = GroupId("null"); template QList StringsToIdList(const QList &strings) @@ -80,7 +81,7 @@ namespace Qv2ray::core } // /// Metadata object representing a connection. - struct ConnectionMetaObject : ConnectionObject_Config + struct ConnectionMetaObject final : ConnectionObject_Config { GroupId groupId = NullGroupId; ConnectionMetaObject() : ConnectionObject_Config() @@ -99,7 +100,7 @@ namespace Qv2ray::core }; /// Metadata object representing a group. - struct GroupMetaObject : SubscriptionObject_Config + struct GroupMetaObject final : SubscriptionObject_Config { // Implicit base of two types, since group object is actually the group base object. bool isSubscription = false; diff --git a/src/core/CoreUtils.cpp b/src/core/CoreUtils.cpp index 6fa976b2..d60bc8cb 100644 --- a/src/core/CoreUtils.cpp +++ b/src/core/CoreUtils.cpp @@ -73,6 +73,8 @@ namespace Qv2ray::core { if (status != nullptr) *status = false; + // + // for (auto item : out["outbounds"].toArray()) { OUTBOUND outBoundRoot = OUTBOUND(item.toObject()); @@ -84,6 +86,11 @@ namespace Qv2ray::core { if (status != nullptr) *status = true; + if (IsComplexConfig(out)) + { + outboundType += " " + QObject::tr("(Guessed)"); + host += " " + QObject::tr("(Guessed)"); + } return { outboundType, host, port }; } else @@ -102,8 +109,8 @@ namespace Qv2ray::core uint64_t GetConnectionTotalData(const ConnectionId &id) { - auto connection = ConnectionManager->GetConnectionMetaObject(id); - return connection.upLinkData + connection.downLinkData; + auto result = GetConnectionUsageAmount(id); + return get<0>(result) + get<1>(result); } int64_t GetConnectionLatency(const ConnectionId &id) @@ -114,14 +121,18 @@ namespace Qv2ray::core const QString GetConnectionProtocolString(const ConnectionId &id) { + // Don't bother with the complex connection configs. + if (IsComplexConfig(id)) + { + return QV2RAY_SERIALIZATION_COMPLEX_CONFIG_PLACEHOLDER; + } CONFIGROOT root = ConnectionManager->GetConnectionRoot(id); QString result; - QStringList protocols; QStringList streamProtocols; auto outbound = root["outbounds"].toArray().first().toObject(); result.append(outbound["protocol"].toString()); - if (outbound.contains("streamSettings")) + if (outbound.contains("streamSettings") && outbound["streamSettings"].toObject().contains("network")) { result.append(" / " + outbound["streamSettings"].toObject()["network"].toString()); if (outbound["streamSettings"].toObject().contains("tls")) diff --git a/src/core/settings/SettingsUpgrade.cpp b/src/core/settings/SettingsUpgrade.cpp index 28d09ed3..17ca7961 100644 --- a/src/core/settings/SettingsUpgrade.cpp +++ b/src/core/settings/SettingsUpgrade.cpp @@ -262,7 +262,7 @@ namespace Qv2ray } // Exported function - QJsonObject UpgradeConfig(int fromVersion, int toVersion, QJsonObject root) + QJsonObject UpgradeSettingsVersion(int fromVersion, int toVersion, QJsonObject root) { LOG(MODULE_SETTINGS, "Migrating config from version " + QSTRN(fromVersion) + " to " + QSTRN(toVersion)) diff --git a/src/main.cpp b/src/main.cpp index 37ef9622..e8d3334f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -388,7 +388,7 @@ int main(int argc, char *argv[]) if (confVersion < QV2RAY_CONFIG_VERSION) { // That is, config file needs to be upgraded. - conf = Qv2ray::UpgradeConfig(confVersion, QV2RAY_CONFIG_VERSION, conf); + conf = Qv2ray::UpgradeSettingsVersion(confVersion, QV2RAY_CONFIG_VERSION, conf); } // Load config object from upgraded config QJsonObject From 7d138423647e7701f92131b3b163ddf44c8c575a Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 00:52:34 +0800 Subject: [PATCH 095/332] trigger ci --- makespec/BUILDVERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 113c7be3..788789d0 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4449 +4450 From b27477521788d0a2aadb4f676e328924c0817168 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 01:17:55 +0800 Subject: [PATCH 096/332] Fixed Qt CI and CD script (#390) * Update build-qv2ray.yml * Update build-qv2ray.yml * Update build-qv2ray.yml * Update build-qv2ray.yml * Update build-qv2ray.yml --- .github/workflows/build-qv2ray.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-qv2ray.yml b/.github/workflows/build-qv2ray.yml index 8cf2f057..262224f3 100644 --- a/.github/workflows/build-qv2ray.yml +++ b/.github/workflows/build-qv2ray.yml @@ -12,6 +12,13 @@ jobs: qt_version: [5.13.2, 5.14.1] platform: [ubuntu-16.04, macos-latest, windows-latest] arch: [x86, x64] + include: + - platform: windows-latest + arch: x86 + qtarch: win32_msvc2017 + - platform: windows-latest + arch: x64 + qtarch: win64_msvc2017_64 exclude: - platform: ubuntu-16.04 arch: x86 @@ -43,11 +50,19 @@ jobs: # 14.1 is for vs2017, 14.2 is vs2019, following the upstream vcpkg build from Qv2ray-deps repo toolset: 14.2 arch: ${{ matrix.arch }} + - name: Cache Qt + id: cache-qt + uses: actions/cache@v1 + with: + path: ../Qt + key: QtCache-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.qt_version }} - name: Installing Qt - ${{ matrix.arch }} - uses: Qv2ray/install-qt-action@master + uses: jurplel/install-qt-action@v2.5.0 with: version: ${{ matrix.qt_version }} - arch: ${{ matrix.arch }} + arch: ${{ matrix.qtarch }} + mirror: 'http://mirrors.ocf.berkeley.edu/qt/' + cached: ${{ steps.cache-qt.outputs.cache-hit }} # -------------------------------------------------------- - name: Linux - Install Packages if: matrix.platform == 'ubuntu-16.04' From 94120c434ada26ece05166020359ee1fae55851e Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 07:15:53 +0800 Subject: [PATCH 097/332] Update BUILDVERSION --- makespec/BUILDVERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 788789d0..9fe1dca4 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4450 +4451 From e4bd5b6b0aaf3360810666295dae779ff5b90254 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 09:16:36 +0800 Subject: [PATCH 098/332] translation: updated translations sources --- translations/en_US.ts | 1384 ++++++++++++++++++++++------------------- 1 file changed, 733 insertions(+), 651 deletions(-) diff --git a/translations/en_US.ts b/translations/en_US.ts index fbedad61..dc2c39fe 100644 --- a/translations/en_US.ts +++ b/translations/en_US.ts @@ -4,27 +4,222 @@ ConfigExporter - + Save Image - - + + Share Connection - + Image has been copied to the clipboard. - + VMess string has been copied to the clipboard. + + ConnectionInfoWidget + + + Form + + + + + Configuration Details + + + + + Connect/Disconnect + + + + + Edit Connection + + + + + Edit Connection as JSON + + + + + Latency Test + + + + + Delete Connection + + + + + Group + + + + + type + + + + + Protocol + + + + + proto + + + + + Address + + + + + addr + + + + + Port + + + + + port + + + + + Link + + + + + QR Code + + + + + Group Name + + + + + Subscription Link + + + + + Share Link + + + + + (Ignored %1 complex config(s)) + + + + + Not a subscription + + + + + Delete an item + + + + + Are you sure to delete the current item? + + + + + ConnectionItemWidget + + + Not Tested + + + + + + ms + + + + + Type: + + + + + Testing... + + + + + Error + + + + + connection + + + + + connections + + + + + ConnectionWidget + + + Form + + + + + Connection Name + + + + + 500ms + + + + + Type: vmess + tls + ws + + + + + 0KB / 0KB + + + + + OK + + + ExportConfigWindow @@ -135,16 +330,6 @@ Select - - - Inbound - - - - - Keep imported inbound settings - - Edit Config @@ -241,67 +426,72 @@ - + Select file to import - + Capture QRCode - + Cannot find a valid QRCode from this region. - + Import config file - + Failed to check the validity of the config file. - + Select an image to import - + QRCode scanning failed - + Cannot find any QRCode from the image. - - - + + + Edit file as JSON - + Provided file not found: - + The file you selected has json syntax error. Continue editing may make you lose data. Would you like to continue? - + Failed to save file, please check if you have proper permissions + + + Import as Complex Config (Manually edit route rules and inbounds) + + InboundEditor @@ -531,41 +721,41 @@ - + Inbound type not supported - + The inbound type is not supported by Qv2ray (yet). Please use JsonEditor to change the settings - + Inbound: - - + + Removing a user - - + + You haven't selected a user yet. - - + + Add a user - - + + This user exists already. @@ -598,28 +788,28 @@ - - + + Json Contains Syntax Errors - + Original Json may contain syntax errors. Json tree is disabled. - + You must correct these errors before continue. - + Syntax Errors - + Please fix the JSON errors before continue @@ -632,20 +822,17 @@ - - + Connect - - + Disconnect - - + Reconnect @@ -659,81 +846,11 @@ Subscriptions - - - Stopped - - - - - Host List - - Import connection - - - Duplicate connection - - - - - Delete a connection - - - - - Edit connection - - - - - Config Details - - - - - Config Type - - - - - Protocol - - - - - Address - - - - - Port Number - - - - - Latency - - - - - Operations - - - - - Edit connection as JSON - - - - - Log (click to switch log source) - - Add @@ -741,40 +858,15 @@ - + Preferences - - Duplicate - - - - - Delete - - - - + Edit - - - Edit JSON - - - - - Ping Test - - - - - Share - - Speed Graph @@ -803,399 +895,252 @@ - - #ManuallyCreateConnection - - - - - #ImportConnection - - - - - #Exit - - - - - #Preferences - - - - - #Start - - - - - #Stop - - - - - #Restart - - - - - + + Hide - + Quit - + Rename - + Connect to this - + + Edit as JSON + + + + Edit as Complex Config - - Edit as Json - - - - - Share as QRCode/VMess URL - - - - - Subscription: - - - - - - + + Show - - Autostarting a config - + + Duplicate to the Same Group + - - Could not find a specified config named: - + + Delete Connection + - - - No connection selected! - + + Sort connection list. + - - - Please select a config from the list. - + + By connection name, A-Z + - + + By connection name, Z-A + + + + + By data, Ascending + + + + + By data, Descending + + + + + By latency, Ascending + + + + + By latency, Descending + + + + Update - + Found a new version: - + Download Link: - - - - + + + + Connected: - - + + Configuring PAC - + Could not start PAC server as it is configured to use SOCKS, but it is not enabled - + Could not start PAC server as it is configured to use HTTP, but it is not enabled - + + Duplicating Connection(s) + + + + + Are you sure to duplicate these connection(s)? + + + + + (Copy) + + + + PAC Processing Failed - - Please reset the settings in Preference Window - - - - - System proxy cleared. - - - - + HTTP or SOCKS inbound is not properly configured for PAC - + Qv2ray will continue, but will not set system proxy. - + Cannot set system proxy - + Both HTTP and SOCKS inbounds are not enabled - - System proxy settings applied. + + Didn't set proxy for complex config. - - Cannot set proxy for complex config. - - - - + Update Subscriptions - + There are subscriptions need to be updated, please go to subscriptions window to update them. - + These subscriptions are out-of-date: - - Disconnected - - - - - Complex - - - - - Simple - - - - - No data - - - - - ms - - - - - There're no support of sharing configs other than vmess and shadowsocks - - - - - - - - - - N/A - - - - - - - Rename a Connection - - - - + V2ray vcore terminated. - + V2ray vcore terminated unexpectedly. - + To solve the problem, read the V2ray log in the log text browser. - + Enable System Proxy - + Disable System Proxy - + System Proxy - - Ping - - - - - Ping All - - - - - - Subscription - - - - - Already connected to: - - - - + Disconnected from: - - The name cannot be empty - - - - - The name has been used already, Please choose another. - - - - - The name you suggested is not valid, please try another. - - - - + Removing Connection(s) - + Are you sure to remove selected connection(s)? - - - Removing this Connection - - - - - - Failed to delete connection file, please delete manually. - - - - - Removing a subscription config + + Locate Current Connection - - Do you want to remove the config loaded from a subscription? + + Search - - - - No Config Selected - - - - - - - Please Select a Config - - - - - You are about to run latency test on all servers, do you want to continue? + + Log - - Testing... + + + Not Connected - - - - Latency Test - - - - - Failed to test latency for this connection. - - - - - Share Connection - - OutboundEditor @@ -1329,11 +1274,11 @@ PreferencesWindow - - - - - + + + + + Preferences @@ -1739,13 +1684,13 @@ - + Bold - + Italic @@ -1855,156 +1800,156 @@ - + Use Darkmode Theme - + Page - + Item(s) - - + + Enable tProxy Support - + to this path: - + Qv2ray Network Toolbar is disabled and still under test. Add --withToolbarPlugin to enable. - + Duplicated port numbers detected, please check the port number settings. - + Invalid inbound listening address. - + Open V2ray assets folder - + Open V2ray core file - + This will append capabilities to the V2ray executable. - + Qv2ray will copy your V2ray core to this path: - + If anything goes wrong after enabling this, please check issue #57 or the link below: - + Qv2ray cannot copy one or both V2ray files from: - - + + Failed to setcap onto V2ray executable. You may need to run `setcap` manually. - + tProxy is not supported on macOS and Windows - + Apply network toolbar settings - + All other modified settings will be applied as well after this object. - + Do you want to continue? - + Dark Mode - + Please restart Qv2ray to fully apply this feature. - + Select GFWList in base64 - - + + Download GFWList - + Operation is cancelled. - + Successfully downloaded GFWList. - + Start with boot - + Failed to set auto start option. - - + + V2ray Core Settings - + V2ray path configuration check passed. - + Current version of V2ray is: @@ -2027,376 +1972,551 @@ p, li { white-space: pre-wrap; } <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + + Transparent Proxy Settings + + + + + All settings below will only be applied onto simple connection. + + + + + Add Docodemo-door inbound + + + + + Address + + + + + TCP + + + + + UDP + + + + + Follow Redirect + + + + + Override Connection SockOpt Settings + + + + + TCP Fast Open + + + + + Mark + + + + + Match Contains + + + + + TProxy Mode + + + + + Settings will be added to the StreamSettings for matched connections. + + QObject - + Unsupported share link format. - + SS URI is too short - - + + Can't find the colon separator between method and password - + Can't find the at separator between password and hostname - + Can't find the colon separator between hostname and port - + VMess string should start with 'vmess://' - + VMess string should be a valid base64 string - + JSON should not be empty - + Warning - + Qv2ray cannot load the config file from here: - + Cannot Start Qv2ray - + Cannot find a place to store config files. - + Qv2ray has searched these paths below: - - - + + + Qv2ray will now exit. - + Failed to initialise Qv2ray - + Failed to determine the location of config file. - + Please report if you think it's a bug. - + You cannot run Qv2ray as root, please use --I-just-wanna-run-with-root if you REALLY want to do so. - + --> USE IT AT YOUR OWN RISK! - + Cannot load languages - + Qv2ray will continue running, but you cannot change the UI language. - + Qv2ray Cannot Continue - + You are running a lower version of Qv2ray compared to the current config file. - + Please check if there's an issue explaining about it. - + Or submit a new issue if you think this is an error. - + Dependency Missing - + This could be caused by a missing of `openssl` package in your system. - + If you are using an AppImage from Github Action, please report a bug. - + Cannot find openssl libs - + Technical Details - - Connected - - - - - Disconnected - - - - + Custom Text - + Current Time - + Current Date - + Current Qv2ray Version - + Current Connection Name - + Current Connection Status - + Total Upload Speed - + Total Download Speed - + Upload Speed for Specific Tag - + Download Speed for Specific Tag - + Total Uploaded Data - + Total Downloaded Data - + Uploaded Data for Specific Tag - + Downloaded Data for Specific Tag - - - Editing a subscription config - - - - - You are trying to edit a config loaded from subscription. - - - - - All changes will be overwritten when the subscriptions are updated next time. - - - - - Are you still going to do so? - - - - - You should not modity this property of a config from a subscription - - - - + - + N/A - + + + (Guessed) + + + + Qv2ray - A cross-platform Qt frontend for V2ray. - + Disable gRPC API subsystems. - + Explicitly run Qv2ray as root. - + Enable Debug Output - + Enable Qv2ray network toolbar plugin + + + Default Group + + + + + Configuration Upgrade Failed + + + + + Unsupported config version number: + + + + + Please upgrade firstly up to Qv2ray v2.0/v2.1 and try again. + + + + + invalid ssd link: json: field %1 must exist + + + + + invalid ssd link: json: field %1 must be valid port number + + + + + invalid ssd link: json: field %1 must be of type 'string' + + + + + invalid ssd link: json: field %1 must be an array + + + + + skipping invalid ssd server: server must be an object + + + + + skipping invalid ssd server: missing required field %1 + + + + + skipping invalid ssd server: field %1 should be of type 'string' + + + + + Invalid ssd link: should begin with ssd:// + + + + + Invalid ssd link: base64 parse failed + + + + + Invalid ssd link: json parse failed: + + + + + Invalid ssd link: found non-object json, aborting + + + + + Invalid ssd link: rc4-md5 encryption is not supported by v2ray-core + + + + + Invalid port encountered. using fallback value. + + + + + Invalid name encountered. using fallback value. + + + + + Invalid ratio encountered. using fallback value. + + + + + %1 - %2 (rate %3) + + + + + (Complex config) + + Qv2ray::components::pac::PACServer - + PAC Handler - + Failed to listen PAC request on this port, please verify the permissions + + Qv2ray::core::handlers::QvConfigHandler + + + + Default Group + + + + + Connection doesn't exist + + + + + File does not exist. + + + + + + Group does not exist + + + Qv2ray::core::kernel::V2rayKernelInstance - + V2ray core executable not found. - + V2ray core file cannot be opened, please ensure there's a file instead of a folder. - + V2ray assets path is not valid. - + No geoip.dat in assets path. - + No geosite.dat in assets path. - + V2ray core failed with an exit code: - + V2ray core returns empty string. - + Configuration Error - + Cannot start V2ray - + V2ray core settings is incorrect. - + The error is: + + + Invalid V2ray Instance Status. + + + + + V2ray kernel failed to start. + + QvInboundNodeModel - + Missing or incorrect inputs @@ -2404,7 +2524,7 @@ p, li { white-space: pre-wrap; } QvOutboundNodeModel - + Missing or incorrect inputs @@ -2412,7 +2532,7 @@ p, li { white-space: pre-wrap; } QvRuleNodeDataModel - + Missing or incorrect inputs @@ -2421,7 +2541,7 @@ p, li { white-space: pre-wrap; } RouteEditor - + Route Editor @@ -2661,182 +2781,182 @@ p, li { white-space: pre-wrap; } - - - + + + OK - + Cannot Edit - + This outbound entry is not supported by the GUI editor. - - + + We will launch Json Editor instead. - + Show rule details - + A rule cannot be found: - - - + + + Protocol list changed: - + Balancer is empty, not processing. - + Default rule - + rule - + No Inbound - + No inbound item found: - - - + + + The new tag has been used, we appended a postfix. - + To make this rule ready to use, you need to connect it to an outbound node. - + Remove Items - - + + Please select a node from the graph to continue. - + Error - + Qv2ray entered an unknown state. - + Edit Inbound/Outbound - - + + Edit Inbound - - + + No inbound tag found: - - + + Opening JSON editor - + Unsupported Outbound Type - + Opening default outbound editor. - - - + + + Renaming a tag - + New tag is empty, please try another. - + New tag is the same as the original one. - + Duplicate rule tag detected, please try another. - + Added DIRECT outbound - + Currently, this type of outbound is not supported by the editor. - + Opening default inbound editor - + Removed a balancer entry. - - - + + + Rename tags @@ -2892,12 +3012,12 @@ p, li { white-space: pre-wrap; } SpeedPlotView - + Total Upload - + Total Download @@ -3068,94 +3188,66 @@ p, li { white-space: pre-wrap; } SubscribeEditor - - - - - Renaming a subscription - - - - - The subscription name is invalid, please try another. + + Reload Subscription - - New name of this subscription has been used already, please suggest another one + + Would you like to reload the subscription? - - Failed to rename a subscription, this is an unknown error. - - - - - Successfully renamed a subscription - - - - - Update Subscription - - - - - Would you like to reload this subscription from the Url? + + Deleting a subscription - - Updating subscriptions - - - - - Failed to process the result from the upstream, please check your Url. + + All connections will be moved to default group, do you want to continue? misc - + B bytes - + KiB kibibytes (1024 bytes) - + MiB mebibytes (1024 kibibytes) - + GiB gibibytes (1024 mibibytes) - + TiB tebibytes (1024 gibibytes) - + PiB pebibytes (1024 tebibytes) - + EiB exbibytes (1024 pebibytes) @@ -3179,11 +3271,6 @@ p, li { white-space: pre-wrap; } Subscription List - - - A - - Add Subscription @@ -3194,11 +3281,6 @@ p, li { white-space: pre-wrap; } Remove Subscription - - - D - - Subscription Details From d95880e23415fce7b59a05d581930abbea947324 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 09:38:24 +0800 Subject: [PATCH 099/332] Update aur.yml --- .github/workflows/aur.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/aur.yml b/.github/workflows/aur.yml index 3737fa66..7982ad4e 100644 --- a/.github/workflows/aur.yml +++ b/.github/workflows/aur.yml @@ -1,7 +1,13 @@ -name: AUR Test Build +name: Build Qv2ray AUR on: push: - paths-ignore: [README.md] + paths-ignore: + - '.github' + branches: + - master + - dev + tags: + - 'v**' schedule: - cron: "0 19 * * *" From e15e67493302f2298a917dacbff17b4f8fab4fda Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 09:53:10 +0800 Subject: [PATCH 100/332] fix: updated release file names, fixed: #363 --- .github/workflows/build-qv2ray.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-qv2ray.yml b/.github/workflows/build-qv2ray.yml index 262224f3..825bd790 100644 --- a/.github/workflows/build-qv2ray.yml +++ b/.github/workflows/build-qv2ray.yml @@ -144,11 +144,11 @@ jobs: path: build/AppDir/Qv2ray.AppImage - name: Linux - ${{ matrix.qt_version }} - Upload binaries to release uses: svenstaro/upload-release-action@v1-release - if: github.event_name == 'release' && matrix.platform == 'ubuntu-16.04' + if: github.event_name == 'release' && matrix.platform == 'ubuntu-16.04' && matrix.qt_version == '5.14.1' with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: build/AppDir/Qv2ray.AppImage - asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.linux-${{ matrix.arch }}.qt${{ matrix.qt_version }}.AppImage + asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.linux-${{ matrix.arch }}.AppImage tag: ${{ github.ref }} overwrite: true # == @@ -168,11 +168,11 @@ jobs: path: build/Qv2ray.app.tar.gz - name: macOS - ${{ matrix.qt_version }} - Upload binaries to release uses: svenstaro/upload-release-action@v1-release - if: github.event_name == 'release' && matrix.platform == 'macos-latest' + if: github.event_name == 'release' && matrix.platform == 'macos-latest' && matrix.qt_version == '5.14.1' with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: build/Qv2ray.app.tar.gz - asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.macOS-${{ matrix.arch }}.qt${{ matrix.qt_version }}.tar.gz + asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.macOS-${{ matrix.arch }}.tar.gz tag: ${{ github.ref }} overwrite: true # == @@ -202,10 +202,10 @@ jobs: path: release.7z - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Upload binaries to release uses: svenstaro/upload-release-action@v1-release - if: github.event_name == 'release' && matrix.platform == 'windows-latest' + if: github.event_name == 'release' && matrix.platform == 'windows-latest' && matrix.qt_version == '5.14.1' with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: release.7z - asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.Windows-${{ matrix.arch }}.qt${{ matrix.qt_version }}.7z + asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.Windows-${{ matrix.arch }}.7z tag: ${{ github.ref }} overwrite: true From 938f529cf869fb5edb3d7028cd5cb55a5c9a8a7e Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 13:44:20 +0800 Subject: [PATCH 101/332] fix: now read file As-Is, and save file as UTF-8, #382 --- makespec/BUILDVERSION | 2 +- src/common/QvHelpers.cpp | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 9fe1dca4..0056142d 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4451 +4452 diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index a539ff9e..12c6b468 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -29,7 +29,8 @@ namespace Qv2ray::common QString StringFromFile(QFile *source) { source->open(QFile::ReadOnly); - QString str = QString::fromUtf8(source->readAll()); + QTextStream stream(source); + QString str = stream.readAll(); source->close(); return str; } @@ -47,9 +48,7 @@ namespace Qv2ray::common } bool override = targetFile.exists(); targetFile.open(QFile::WriteOnly); - QTextStream stream(&targetFile); - stream << text << endl; - stream.flush(); + targetFile.write(text.toUtf8()); targetFile.close(); return override; } From e8f93d62a8c517f5c0685d6ff083d084e2289329 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 14:43:37 +0800 Subject: [PATCH 102/332] add: added cross-platform vCore and vAssets path support, fixed #382 --- Qv2ray.pro | 2 +- makespec/01-sourcesparser.pri | 2 +- makespec/BUILDVERSION | 2 +- src/base/GlobalInstances.hpp | 2 +- src/base/Qv2rayBase.hpp | 2 +- ...QvConfigModel.hpp => QvSettingsObject.hpp} | 56 ++++++++++++++++--- src/core/connection/Serialization_ssd.cpp | 2 - src/core/kernel/KernelInteractions.cpp | 13 +++-- src/core/settings/SettingsUpgrade.cpp | 30 +++++++++- src/main.cpp | 4 +- src/ui/w_PreferencesWindow.cpp | 26 +++++---- 11 files changed, 104 insertions(+), 37 deletions(-) rename src/base/models/{QvConfigModel.hpp => QvSettingsObject.hpp} (72%) diff --git a/Qv2ray.pro b/Qv2ray.pro index 1886eea5..fea08816 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -57,7 +57,7 @@ Qv2rayAddSource(base, _, Qv2rayBase, hpp) Qv2rayAddSource(base, _, Qv2rayFeatures, hpp) Qv2rayAddSource(base, _, Qv2rayLog, cpp, hpp) Qv2rayAddSource(base, models, CoreObjectModels, hpp) -Qv2rayAddSource(base, models, QvConfigModel, hpp) +Qv2rayAddSource(base, models, QvSettingsObject, hpp) Qv2rayAddSource(base, models, QvConfigIdentifier, hpp) Qv2rayAddSource(base, models, QvSafeType, hpp) Qv2rayAddSource(base, models, QvRuntimeConfig, hpp) diff --git a/makespec/01-sourcesparser.pri b/makespec/01-sourcesparser.pri index 4a88992e..d66b800f 100644 --- a/makespec/01-sourcesparser.pri +++ b/makespec/01-sourcesparser.pri @@ -31,7 +31,7 @@ defineTest(Qv2rayAddSource) { filename = $$take_first(ARGS) extlist = $$ARGS FILEPATH = "$$PWD/src/$${module}" - qmake_debug: message(Qv2rayAddSource: Adding \"$${filename}\" of module \"$${module}\", component \"$${component}\" to the project) + qmake_debug: message("Qv2rayAddSource: Adding \"$${filename}\" of module \"$${module}\", component \"$${component}\" to the project") equals(component, "_") { qmake_debug: message("Qv2rayAddSource: Component is empty, ignore") FILEPATH += "/$${filename}" diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 0056142d..c1bdd6d8 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4452 +4475 diff --git a/src/base/GlobalInstances.hpp b/src/base/GlobalInstances.hpp index 114a9ccf..3b719f74 100644 --- a/src/base/GlobalInstances.hpp +++ b/src/base/GlobalInstances.hpp @@ -1,6 +1,6 @@ #pragma once -#include "base/models/QvConfigModel.hpp" +#include "base/models/QvSettingsObject.hpp" #include "base/models/QvRuntimeConfig.hpp" #include "base/models/QvStartupConfig.hpp" diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index 515202c1..84c4ece4 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -21,7 +21,7 @@ // Code Models #include "base/models/CoreObjectModels.hpp" #include "base/models/QvConfigIdentifier.hpp" -#include "base/models/QvConfigModel.hpp" +#include "base/models/QvSettingsObject.hpp" #include "base/models/QvRuntimeConfig.hpp" #include "base/models/QvSafeType.hpp" #include "base/models/QvStartupConfig.hpp" diff --git a/src/base/models/QvConfigModel.hpp b/src/base/models/QvSettingsObject.hpp similarity index 72% rename from src/base/models/QvConfigModel.hpp rename to src/base/models/QvSettingsObject.hpp index ae545130..20c011d9 100644 --- a/src/base/models/QvConfigModel.hpp +++ b/src/base/models/QvSettingsObject.hpp @@ -5,7 +5,7 @@ #include -const int QV2RAY_CONFIG_VERSION = 9; +const int QV2RAY_CONFIG_VERSION = 10; namespace Qv2ray::base::config { @@ -134,18 +134,57 @@ namespace Qv2ray::base::config XTOSTRUCT(O(enableAPI, statsPort)) }; + struct Qv2rayKernelConfig + { + QString v2CorePath_linux; + QString v2AssetsPath_linux; + QString v2CorePath_macx; + QString v2AssetsPath_macx; + QString v2CorePath_win; + QString v2AssetsPath_win; // + Qv2rayKernelConfig() + : v2CorePath_linux(), v2AssetsPath_linux(), // + v2CorePath_macx(), v2AssetsPath_macx(), // + v2CorePath_win(), v2AssetsPath_win() // + { + } + // +#ifdef Q_OS_LINUX + #define _VARNAME_VCOREPATH_ v2CorePath_linux + #define _VARNAME_VASSETSPATH_ v2AssetsPath_linux +#elif defined(Q_OS_MACOS) + #define _VARNAME_VCOREPATH_ v2CorePath_macx + #define _VARNAME_VASSETSPATH_ v2AssetsPath_macx +#elif defined(Q_OS_WIN) + #define _VARNAME_VCOREPATH_ v2CorePath_win + #define _VARNAME_VASSETSPATH_ v2AssetsPath_win +#endif + + inline const QString KernelPath(const QString &path = "") + { + return path.isEmpty() ? _VARNAME_VCOREPATH_ : _VARNAME_VCOREPATH_ = path; + } + inline const QString AssetsPath(const QString &path = "") + { + return path.isEmpty() ? _VARNAME_VASSETSPATH_ : _VARNAME_VASSETSPATH_ = path; + } + +#undef _VARNAME_VCOREPATH_ +#undef _VARNAME_VASSETSPATH_ + + XTOSTRUCT(O(v2CorePath_linux, v2AssetsPath_linux, v2CorePath_macx, v2CorePath_macx, v2CorePath_win, v2AssetsPath_win)) + }; + struct Qv2rayConfig { int config_version; bool tProxySupport; int logLevel; // - QString v2CorePath; - QString v2AssetsPath; QString ignoredVersion; QString autoStartId; // - // Key = groupId, connectionId, subscriptionId + // Key = groupId, connectionId QMap groups; QMap subscriptions; /// Connections are used privately. @@ -153,17 +192,18 @@ namespace Qv2ray::base::config // Qv2rayUIConfig uiConfig; Qv2rayAPIConfig apiConfig; + Qv2rayKernelConfig kernelConfig; Qv2rayToolBarConfig toolBarConfig; Qv2rayInboundsConfig inboundConfig; Qv2rayConnectionConfig connectionConfig; Qv2rayConfig() - : config_version(QV2RAY_CONFIG_VERSION), tProxySupport(false), logLevel(), v2CorePath(), v2AssetsPath(), ignoredVersion(), groups(), - subscriptions(), connections(), uiConfig(), apiConfig(), toolBarConfig(), inboundConfig(), connectionConfig() + : config_version(QV2RAY_CONFIG_VERSION), tProxySupport(false), logLevel(), ignoredVersion(), autoStartId("null"), groups(), + subscriptions(), connections(), uiConfig(), apiConfig(), kernelConfig(), toolBarConfig(), inboundConfig(), connectionConfig() { } - XTOSTRUCT(O(config_version, ignoredVersion, tProxySupport, logLevel, uiConfig, v2CorePath, v2AssetsPath, groups, connections, - subscriptions, autoStartId, inboundConfig, connectionConfig, toolBarConfig, apiConfig)) + XTOSTRUCT(O(config_version, ignoredVersion, tProxySupport, logLevel, uiConfig, kernelConfig, groups, connections, subscriptions, + autoStartId, inboundConfig, connectionConfig, toolBarConfig, apiConfig)) }; } // namespace Qv2ray::base::config diff --git a/src/core/connection/Serialization_ssd.cpp b/src/core/connection/Serialization_ssd.cpp index ebd75049..ceb55d85 100644 --- a/src/core/connection/Serialization_ssd.cpp +++ b/src/core/connection/Serialization_ssd.cpp @@ -5,8 +5,6 @@ * @copyright Licensed under GPLv3. */ -#pragma once - #include "base/Qv2rayBase.hpp" #include "common/QvHelpers.hpp" #include "core/connection/Serialization.hpp" diff --git a/src/core/kernel/KernelInteractions.cpp b/src/core/kernel/KernelInteractions.cpp index 10cd59dc..3bb1ccf4 100644 --- a/src/core/kernel/KernelInteractions.cpp +++ b/src/core/kernel/KernelInteractions.cpp @@ -98,18 +98,19 @@ namespace Qv2ray::core::kernel bool V2rayKernelInstance::ValidateConfig(const QString &path) { QString v2rayCheckResult; - - if (ValidateKernel(GlobalConfig.v2CorePath, GlobalConfig.v2AssetsPath, &v2rayCheckResult)) + auto kernelPath = GlobalConfig.kernelConfig.KernelPath(); + auto assetsPath = GlobalConfig.kernelConfig.AssetsPath(); + if (ValidateKernel(kernelPath, assetsPath, &v2rayCheckResult)) { DEBUG(MODULE_VCORE, "V2ray version: " + v2rayCheckResult) // Append assets location env. QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - env.insert("V2RAY_LOCATION_ASSET", GlobalConfig.v2AssetsPath); + env.insert("V2RAY_LOCATION_ASSET", assetsPath); // QProcess process; process.setProcessEnvironment(env); DEBUG(MODULE_VCORE, "Starting V2ray core with test options") - process.start(GlobalConfig.v2CorePath, QStringList{ "-test", "-config", path }, QIODevice::ReadWrite | QIODevice::Text); + process.start(kernelPath, QStringList{ "-test", "-config", path }, QIODevice::ReadWrite | QIODevice::Text); process.waitForFinished(); if (process.exitCode() != 0) @@ -170,9 +171,9 @@ namespace Qv2ray::core::kernel if (ValidateConfig(filePath)) { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - env.insert("V2RAY_LOCATION_ASSET", GlobalConfig.v2AssetsPath); + env.insert("V2RAY_LOCATION_ASSET", GlobalConfig.kernelConfig.AssetsPath()); vProcess->setProcessEnvironment(env); - vProcess->start(GlobalConfig.v2CorePath, QStringList{ "-config", filePath }, QIODevice::ReadWrite | QIODevice::Text); + vProcess->start(GlobalConfig.kernelConfig.KernelPath(), QStringList{ "-config", filePath }, QIODevice::ReadWrite | QIODevice::Text); vProcess->waitForStarted(); DEBUG(MODULE_VCORE, "V2ray core started.") KernelStarted = true; diff --git a/src/core/settings/SettingsUpgrade.cpp b/src/core/settings/SettingsUpgrade.cpp index 17ca7961..e649307f 100644 --- a/src/core/settings/SettingsUpgrade.cpp +++ b/src/core/settings/SettingsUpgrade.cpp @@ -15,8 +15,9 @@ namespace Qv2ray { switch (fromVersion) { - // -------------------------------------------------------------------------------------- - // Below is for Qv2ray version 2 + // Cases 1, 2, and 3 are not supported anymore. + // -------------------------------------------------------------------------------------- + // Below is for Qv2ray version 2 case 4: { // We changed the "proxyCN" to "bypassCN" as it's easier to @@ -243,6 +244,31 @@ namespace Qv2ray break; } + // Added cross-platform vCore and vAssets path support; + case 9: + { + QJsonObject kernelConfig; +#ifdef Q_OS_LINUX + #define _VARNAME_VCOREPATH_ kernelConfig["v2CorePath_linux"] + #define _VARNAME_VASSETSPATH_ kernelConfig["v2AssetsPath_linux"] + UPGRADELOG("Update kernel and assets paths for linux") +#elif defined(Q_OS_MACOS) + #define _VARNAME_VCOREPATH_ kernelConfig["v2CorePath_macx"] + #define _VARNAME_VASSETSPATH_ kernelConfig["v2AssetsPath_macx"] + UPGRADELOG("Update kernel and assets paths for macOS") +#elif defined(Q_OS_WIN) + #define _VARNAME_VCOREPATH_ kernelConfig["v2CorePath_win"] + #define _VARNAME_VASSETSPATH_ kernelConfig["v2AssetsPath_win"] + UPGRADELOG("Update kernel and assets paths for Windows") +#endif + _VARNAME_VCOREPATH_ = root["v2CorePath"].toString(); + _VARNAME_VASSETSPATH_ = root["v2AssetsPath"].toString(); + // + root["kernelConfig"] = kernelConfig; +#undef _VARNAME_VCOREPATH_ +#undef _VARNAME_VASSETSPATH_ + break; + } default: { // Due to technical issue, we cannot maintain all of those diff --git a/src/main.cpp b/src/main.cpp index e8d3334f..614e566b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -209,8 +209,8 @@ bool initialiseQv2ray() } Qv2rayConfig conf; - conf.v2AssetsPath = QString(QV2RAY_DEFAULT_VASSETS_PATH); - conf.v2CorePath = QString(QV2RAY_DEFAULT_VCORE_PATH); + conf.kernelConfig.KernelPath(QString(QV2RAY_DEFAULT_VASSETS_PATH)); + conf.kernelConfig.AssetsPath(QString(QV2RAY_DEFAULT_VCORE_PATH)); conf.logLevel = 3; // // Save initial config. diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index bbe55dea..8151db47 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -113,8 +113,8 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), Current socksUDPIP->setText(CurrentConfig.inboundConfig.socksLocalIP); // // - vCorePathTxt->setText(CurrentConfig.v2CorePath); - vCoreAssetsPathTxt->setText(CurrentConfig.v2AssetsPath); + vCorePathTxt->setText(CurrentConfig.kernelConfig.KernelPath()); + vCoreAssetsPathTxt->setText(CurrentConfig.kernelConfig.AssetsPath()); enableAPI->setChecked(CurrentConfig.apiConfig.enableAPI); statsPortBox->setValue(CurrentConfig.apiConfig.statsPort); // @@ -317,7 +317,7 @@ void PreferencesWindow::on_logLevelComboBox_currentIndexChanged(int index) void PreferencesWindow::on_vCoreAssetsPathTxt_textEdited(const QString &arg1) { NEEDRESTART - CurrentConfig.v2AssetsPath = arg1; + CurrentConfig.kernelConfig.AssetsPath(arg1); } void PreferencesWindow::on_listenIPTxt_textEdited(const QString &arg1) @@ -400,7 +400,7 @@ void PreferencesWindow::on_selectVCoreBtn_clicked() void PreferencesWindow::on_vCorePathTxt_textEdited(const QString &arg1) { NEEDRESTART - CurrentConfig.v2CorePath = arg1; + CurrentConfig.kernelConfig.KernelPath(arg1); } void PreferencesWindow::on_DNSListTxt_textChanged() @@ -454,6 +454,7 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) // --> 2. Change GlobalConfig.v2CorePath. // --> 3. Call `pkexec setcap // CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip` on the V2ray core. + auto const kernelPath = CurrentConfig.kernelConfig.KernelPath(); if (arg1 == Qt::Checked) { // We enable it! @@ -468,9 +469,10 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) } else { + LOG(MODULE_VCORE, "ENABLING tProxy Support") - LOG(MODULE_FILEIO, " --> Origin V2ray core file is at: " + CurrentConfig.v2CorePath) - auto v2ctlPath = QFileInfo(CurrentConfig.v2CorePath).absolutePath() + "/v2ctl"; + LOG(MODULE_FILEIO, " --> Origin V2ray core file is at: " + kernelPath) + auto v2ctlPath = QFileInfo(kernelPath).absolutePath() + "/v2ctl"; auto newPath = QFileInfo(QV2RAY_TPROXY_VCORE_PATH).absolutePath(); QString mkPathResult = QDir().mkpath(newPath) ? "OK" : "FAILED"; LOG(MODULE_FILEIO, " --> mkPath result: " + mkPathResult) @@ -480,7 +482,7 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) // LOG(MODULE_FILEIO, " --> Copying files....") - if (QFileInfo(CurrentConfig.v2CorePath).absoluteFilePath() != QFileInfo(QV2RAY_TPROXY_VCORE_PATH).absoluteFilePath()) + if (QFileInfo(kernelPath).absoluteFilePath() != QFileInfo(QV2RAY_TPROXY_VCORE_PATH).absoluteFilePath()) { // Only trying to remove file when they are not in the default // dir. (In other words...) Keep using the current files. @@ -501,7 +503,7 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) QFile(QV2RAY_TPROXY_VCTL_PATH).remove(); } - QString vCoreresult = QFile(CurrentConfig.v2CorePath).copy(QV2RAY_TPROXY_VCORE_PATH) ? "OK" : "FAILED"; + QString vCoreresult = QFile(kernelPath).copy(QV2RAY_TPROXY_VCORE_PATH) ? "OK" : "FAILED"; LOG(MODULE_FILEIO, " --> V2ray Core: " + vCoreresult) // QString vCtlresult = QFile(v2ctlPath).copy(QV2RAY_TPROXY_VCTL_PATH) ? "OK" : "FAILED"; @@ -517,8 +519,8 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) { LOG(MODULE_VCORE, "FAILED to copy V2ray files. Aborting.") QvMessageBoxWarn(this, tr("Enable tProxy Support"), - tr("Qv2ray cannot copy one or both V2ray files from: ") + NEWLINE + NEWLINE + CurrentConfig.v2CorePath + - NEWLINE + v2ctlPath + NEWLINE + NEWLINE + tr("to this path: ") + NEWLINE + newPath); + tr("Qv2ray cannot copy one or both V2ray files from: ") + NEWLINE + NEWLINE + kernelPath + NEWLINE + + v2ctlPath + NEWLINE + NEWLINE + tr("to this path: ") + NEWLINE + newPath); return; } } @@ -529,7 +531,7 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) } LOG(MODULE_UI, "Calling pkexec and setcap...") - int ret = QProcess::execute("pkexec setcap CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip " + CurrentConfig.v2CorePath); + int ret = QProcess::execute("pkexec setcap CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip " + kernelPath); if (ret != 0) { @@ -543,7 +545,7 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1) } else { - int ret = QProcess::execute("pkexec setcap -r " + CurrentConfig.v2CorePath); + int ret = QProcess::execute("pkexec setcap -r " + kernelPath); if (ret != 0) { From 56c7264a146b6623a376fb740d73e3807d70503f Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 15:15:22 +0800 Subject: [PATCH 103/332] fix: fixed some plugin content item supprt, added connection latency --- makespec/BUILDVERSION | 2 +- src/components/plugins/toolbar/QvToolbar.cpp | 147 +++++++++---------- src/components/plugins/toolbar/QvToolbar.hpp | 37 ++--- 3 files changed, 94 insertions(+), 92 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index c1bdd6d8..ddbeab24 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4475 +4476 diff --git a/src/components/plugins/toolbar/QvToolbar.cpp b/src/components/plugins/toolbar/QvToolbar.cpp index 12857f75..6c6cde88 100644 --- a/src/components/plugins/toolbar/QvToolbar.cpp +++ b/src/components/plugins/toolbar/QvToolbar.cpp @@ -1,8 +1,9 @@ -#include -#include "components/plugins/toolbar/QvToolbar.hpp" +#include "components/plugins/toolbar/QvToolbar.hpp" #include "common/QvHelpers.hpp" -#include "ui/w_MainWindow.hpp" +#include "core/handler/ConfigHandler.hpp" + +#include namespace Qv2ray::components::plugins { @@ -31,28 +32,20 @@ namespace Qv2ray::components::plugins } QString GetAnswerToRequest(const QString &pchRequest) { - auto instance = MainWindow::mwInstance; - // if (instance == nullptr || instance->vinstance == nullptr) { - // LOG(PLUGIN, "MainWindow != nullptr Assertion failed!") - // return "{}"; - //} - // - // auto vinstance = instance->vinstance; - // auto req = pchRequest.trimmed(); QString reply = "{}"; if (req == "START") { - emit instance->StartConnection(); + emit ConnectionManager->RestartConnection(); } else if (req == "STOP") { - emit instance->StopConnection(); + emit ConnectionManager->StopConnection(); } else if (req == "RESTART") { - emit instance->RestartConnection(); + emit ConnectionManager->RestartConnection(); } auto BarConfig = GlobalConfig.toolBarConfig; @@ -93,86 +86,92 @@ namespace Qv2ray::components::plugins break; } - // case 104: { - // // Current Connection Name - // CL.Message = - // instance->GetCurrentConnectedConfigName(); - // break; - //} - // - // case 105: { - // // Current Connection Status - // CL.Message = - // instance->vinstance->KernelStarted - // ? QObject::tr("Connected") - // : QObject::tr("Disconnected"); - // break; - //} - // - // case 201: { + case 104: + { + // Current Connection Name + CL.Message = GetDisplayName(ConnectionManager->CurrentConnection()); + break; + } + + case 105: + { + // Current Connection Status + CL.Message = ConnectionManager->CurrentConnection() == NullConnectionId ? QObject::tr("Not connected") : + QObject::tr("Connected"); + break; + } + + // case 201: + //{ // // Total upload speed; - // CL.Message = - // FormatBytes(vinstance->getAllSpeedUp()) + - // "/s"; break; + // CL.Message = FormatBytes(get<0>(GetConnectionUsageAmount())) + "/s"; + // break; //} // - // case 202: { + // case 202: + //{ // // Total download speed; - // CL.Message = - // FormatBytes(vinstance->getAllSpeedDown()) + - // "/s"; break; + // CL.Message = FormatBytes(vinstance->getAllSpeedDown()) + "/s"; + // break; //} // - // case 203: { + // case 203: + //{ // // Upload speed for tag - // CL.Message = - // FormatBytes(vinstance->getTagSpeedUp(CL.Message)) - // + "/s"; break; + // CL.Message = FormatBytes(vinstance->getTagSpeedUp(CL.Message)) + "/s"; + // break; //} // - // case 204: { + // case 204: + //{ // // Download speed for tag - // CL.Message = - // FormatBytes(vinstance->getTagSpeedDown(CL.Message)) - // + "/s"; break; - //} - // - // case 301: { - // // Total Upload - // CL.Message = - // FormatBytes(vinstance->getAllDataUp()); break; - //} - // - // case 302: { - // // Total download - // CL.Message = - // FormatBytes(vinstance->getAllDataDown()); - // break; - //} - // - // case 303: { - // // Upload for tag - // CL.Message = - // FormatBytes(vinstance->getTagDataUp(CL.Message)); - // break; - //} - // - // case 304: { - // // Download for tag - // CL.Message = - // FormatBytes(vinstance->getTagDataDown(CL.Message)); + // CL.Message = FormatBytes(vinstance->getTagSpeedDown(CL.Message)) + "/s"; // break; //} + case 301: + { + // Total Upload + CL.Message = FormatBytes(get<0>(GetConnectionUsageAmount(ConnectionManager->CurrentConnection()))); + break; + } + + case 302: + { + // Total download + CL.Message = FormatBytes(get<1>(GetConnectionUsageAmount(ConnectionManager->CurrentConnection()))); + break; + } + + // case 303: + //{ + // // Upload for tag + // CL.Message = FormatBytes(vinstance->getTagDataUp(CL.Message)); + // break; + //} + // + // case 304: + //{ + // // Download for tag + // CL.Message = FormatBytes(vinstance->getTagDataDown(CL.Message)); + // break; + //} + + case 305: + { + // Connection latency + CL.Message = QSTRN(GetConnectionLatency(ConnectionManager->CurrentConnection())) + " ms"; + break; + } default: { - CL.Message = "Not Supported?"; + CL.Message = "Not Implemented"; break; } } } } - +#undef CL reply = StructToJsonString(BarConfig); return reply; } diff --git a/src/components/plugins/toolbar/QvToolbar.hpp b/src/components/plugins/toolbar/QvToolbar.hpp index 6dd2b563..dac1dafa 100644 --- a/src/components/plugins/toolbar/QvToolbar.hpp +++ b/src/components/plugins/toolbar/QvToolbar.hpp @@ -9,23 +9,26 @@ namespace Qv2ray::components::plugins namespace Toolbar { /// NO NOT CHANGE THE ORDER - static const QMap NetSpeedPluginMessages{ { 0, QObject::tr("Custom Text") }, - // Current Status - { 101, QObject::tr("Current Time") }, - { 102, QObject::tr("Current Date") }, - { 103, QObject::tr("Current Qv2ray Version") }, - { 104, QObject::tr("Current Connection Name") }, - { 105, QObject::tr("Current Connection Status") }, - // Speeds - { 201, QObject::tr("Total Upload Speed") }, - { 202, QObject::tr("Total Download Speed") }, - { 203, QObject::tr("Upload Speed for Specific Tag") }, - { 204, QObject::tr("Download Speed for Specific Tag") }, - // Datas - { 301, QObject::tr("Total Uploaded Data") }, - { 302, QObject::tr("Total Downloaded Data") }, - { 303, QObject::tr("Uploaded Data for Specific Tag") }, - { 304, QObject::tr("Downloaded Data for Specific Tag") } }; + static const QMap NetSpeedPluginMessages{ + { 0, QObject::tr("Custom Text") }, + // Current Status + { 101, QObject::tr("Current Time") }, + { 102, QObject::tr("Current Date") }, + { 103, QObject::tr("Current Qv2ray Version") }, + { 104, QObject::tr("Current Connection Name") }, + { 105, QObject::tr("Current Connection Status") }, + // Speeds + { 201, QObject::tr("Total Upload Speed") }, + { 202, QObject::tr("Total Download Speed") }, + //{ 203, QObject::tr("Upload Speed for Specific Tag") }, + //{ 204, QObject::tr("Download Speed for Specific Tag") }, + // Datas + { 301, QObject::tr("Total Uploaded Data") }, + { 302, QObject::tr("Total Downloaded Data") }, + //{ 303, QObject::tr("Uploaded Data for Specific Tag") }, + //{ 304, QObject::tr("Downloaded Data for Specific Tag") } + { 305, QObject::tr("Current Connection Latency") } // + }; void StartProcessingPlugins(); void StopProcessingPlugins(); #ifdef Q_OS_WIN From bf1bcec1025071a6bfd16d223a13662bb4085c93 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 15:27:07 +0800 Subject: [PATCH 104/332] fix: lowered the autosave frequency --- src/core/handler/ConfigHandler.cpp | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/src/core/handler/ConfigHandler.cpp b/src/core/handler/ConfigHandler.cpp index e388159f..1dd9e608 100644 --- a/src/core/handler/ConfigHandler.cpp +++ b/src/core/handler/ConfigHandler.cpp @@ -69,7 +69,8 @@ namespace Qv2ray::core::handlers httpHelper = new QvHttpRequestHelper(this); connect(tcpingHelper, &QvTCPingHelper::OnLatencyTestCompleted, this, &QvConfigHandler::OnLatencyDataArrived); // - saveTimerId = startTimer(10 * 1000); + // Save per 2 minutes. + saveTimerId = startTimer(2 * 60 * 1000); // Do not ping all... // pingAllTimerId = startTimer(5 * 60 * 1000); pingConnectionTimerId = startTimer(60 * 1000); @@ -77,8 +78,8 @@ namespace Qv2ray::core::handlers void QvConfigHandler::CHSaveConfigData_p() { - // Copy - auto newGlobalConfig = GlobalConfig; + // Do not copy construct. + auto &newGlobalConfig = GlobalConfig; newGlobalConfig.connections.clear(); newGlobalConfig.groups.clear(); newGlobalConfig.subscriptions.clear(); @@ -165,21 +166,6 @@ namespace Qv2ray::core::handlers return subsList; } - // Obsolated, Please use: - // ConnectionId QvConnectionHandler::GetConnectionIdByDisplayName(const QString &displayName, const GroupId &group) const - // - // const ConnectionId QvConnectionHandler::GetConnectionIdByDisplayName(const QString &displayName) const - //{ - // for (auto conn : connections.keys()) - // { - // if (connections[conn].displayName == displayName) - // { - // return conn; - // } - // } - // - // return NullConnectionId; - //} const ConnectionId QvConfigHandler::GetConnectionIdByDisplayName(const QString &displayName, const GroupId &group) const { CheckGroupExistanceEx(group, NullConnectionId); @@ -318,8 +304,7 @@ namespace Qv2ray::core::handlers void QvConfigHandler::RestartConnection() // const ConnectionId &id { - auto conn = currentConnectionId; - if (conn != NullConnectionId) + if (currentConnectionId != NullConnectionId) { StopConnection(); StartConnection(conn); @@ -333,6 +318,7 @@ namespace Qv2ray::core::handlers // if (currentConnectionId == id) { //} CHStopConnection_p(); + CHSaveConfigData_p(); } bool QvConfigHandler::IsConnected(const ConnectionId &id) const From 663a1853244bf93a695244e02e4095dfa81f2509 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 16:11:23 +0800 Subject: [PATCH 105/332] fix: fixed some UI experiences and fixed build --- makespec/BUILDVERSION | 2 +- src/core/handler/ConfigHandler.cpp | 3 +- src/ui/w_MainWindow.cpp | 16 ++- src/ui/w_MainWindow.hpp | 2 + src/ui/widgets/ConnectionItemWidget.cpp | 49 ++++++++ src/ui/widgets/ConnectionItemWidget.hpp | 36 +----- src/ui/widgets/ConnectionItemWidget.ui | 157 ++++++++++-------------- 7 files changed, 136 insertions(+), 129 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index ddbeab24..eec95d2f 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4476 +4496 diff --git a/src/core/handler/ConfigHandler.cpp b/src/core/handler/ConfigHandler.cpp index 1dd9e608..5557b40f 100644 --- a/src/core/handler/ConfigHandler.cpp +++ b/src/core/handler/ConfigHandler.cpp @@ -304,7 +304,8 @@ namespace Qv2ray::core::handlers void QvConfigHandler::RestartConnection() // const ConnectionId &id { - if (currentConnectionId != NullConnectionId) + auto conn = currentConnectionId; + if (conn != NullConnectionId) { StopConnection(); StartConnection(conn); diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 75603529..67ab8e34 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -294,11 +294,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) void MainWindow::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) + if (focusWidget() == connectionListWidget) { - if (focusWidget() == connectionListWidget) + CheckCurrentWidget; + if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { - CheckCurrentWidget; // If pressed enter or return on connectionListWidget. Try to connect to the selected connection. if (widget->IsConnection()) { @@ -309,6 +309,7 @@ void MainWindow::keyPressEvent(QKeyEvent *e) connectionListWidget->expandItem(connectionListWidget->currentItem()); } } + widget->keyPressEvent(e); } } @@ -900,3 +901,12 @@ void MainWindow::on_action_RCM_EditAsJson_triggered() CheckCurrentWidget; OnEditJsonRequested(get<1>(widget->Identifier())); } + +void MainWindow::on_connectionListWidget_itemSelectionChanged() +{ + if (connectionListWidget->selectedItems().count() > 0) + { + connectionListWidget->setCurrentItem(connectionListWidget->selectedItems().first()); + connectionListWidget->setFocus(); + } +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 1c8862cf..c3b40986 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -97,6 +97,8 @@ class MainWindow // void SortConnectionList(MW_ITEM_COL byCol, bool asending); + void on_connectionListWidget_itemSelectionChanged(); + private: QHash> groupNodes; QHash> connectionNodes; diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index 4372dddc..53041593 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -43,6 +43,9 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare } OnConnectionItemRenamed(id, "", originalItemName); connect(ConnectionManager, &QvConfigHandler::OnConnectionRenamed, this, &ConnectionItemWidget::OnConnectionItemRenamed); + // + // Rename events + connect(renameTxt, &QLineEdit::returnPressed, this, &ConnectionItemWidget::on_doRenameBtn_clicked); } // ======================================= Initialisation for root nodes. @@ -53,6 +56,9 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : delete connTypeLabel; delete dataLabel; // + delete doRenameBtn; + delete renameTxt; + // groupId = id; itemType = GROUP_HEADER_ITEM; originalItemName = GetDisplayName(id); @@ -72,6 +78,23 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : connect(ConnectionManager, &QvConfigHandler::OnGroupRenamed, this, &ConnectionItemWidget::OnGroupItemRenamed); } +void ConnectionItemWidget::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Escape) + { + QLineEdit *focus = qobject_cast(focusWidget()); + if (focus != nullptr) + { + stackedWidget->setCurrentIndex(0); + } + } + else if (e->key() == Qt::Key_F2) + { + BeginRename(); + } + QWidget::keyPressEvent(e); +} + void ConnectionItemWidget::BeginConnection() { if (itemType == NODE_ITEM) @@ -142,6 +165,7 @@ void ConnectionItemWidget::BeginRename() renameTxt->setStyle(QStyleFactory::create("Fusion")); renameTxt->setStyleSheet("background-color: " + this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); renameTxt->setText(originalItemName); + renameTxt->setFocus(); } ConnectionItemWidget::~ConnectionItemWidget() @@ -162,3 +186,28 @@ void ConnectionItemWidget::on_doRenameBtn_clicked() } stackedWidget->setCurrentIndex(0); } +void ConnectionItemWidget::OnConnectionItemRenamed(const ConnectionId &id, const QString &, const QString &newName) +{ + if (id == connectionId) + { + if (ConnectionManager->IsConnected(id)) + { + connNameLabel->setText("• " + newName); + } + else + { + connNameLabel->setText(newName); + } + originalItemName = newName; + this->setToolTip(newName); + } +} +void ConnectionItemWidget::OnGroupItemRenamed(const GroupId &id, const QString &, const QString &newName) +{ + if (id == groupId) + { + originalItemName = newName; + connNameLabel->setText(newName); + this->setToolTip(newName); + } +} diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index 24a216a2..462089ac 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -46,51 +46,27 @@ class ConnectionItemWidget { return itemType == NODE_ITEM; } + void keyPressEvent(QKeyEvent *e) override; signals: void RequestWidgetFocus(const ConnectionItemWidget *me); private slots: - void OnConnectionStatsArrived(const ConnectionId &id, const quint64 upSpeed, const quint64 downSpeed, const quint64 totalUp, - const quint64 totalDown); + void OnConnectionStatsArrived(const ConnectionId &id, const quint64 upS, const quint64 downS, const quint64 upD, const quint64 downD); void OnConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id); void OnLatencyTestStart(const ConnectionId &id); void OnLatencyTestFinished(const ConnectionId &id, const uint average); - void RecalculateConnectionsCount() + inline void RecalculateConnectionsCount() { auto connectionCount = ConnectionManager->Connections(groupId).count(); latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections"))); } - void OnConnectionItemRenamed(const ConnectionId &id, const QString &, const QString &newName) - { - if (id == connectionId) - { - if (ConnectionManager->IsConnected(id)) - { - connNameLabel->setText("• " + newName); - } - else - { - connNameLabel->setText(newName); - } - originalItemName = newName; - this->setToolTip(newName); - } - } - void OnGroupItemRenamed(const GroupId &id, const QString &, const QString &newName) - { - if (id == groupId) - { - originalItemName = newName; - connNameLabel->setText(newName); - this->setToolTip(newName); - } - } - + void OnConnectionItemRenamed(const ConnectionId &id, const QString &, const QString &newName); + void OnGroupItemRenamed(const GroupId &id, const QString &, const QString &newName); void on_doRenameBtn_clicked(); private: - QString originalItemName; explicit ConnectionItemWidget(QWidget *parent = nullptr); + QString originalItemName; ITEM_TYPE itemType; ConnectionId connectionId; GroupId groupId; diff --git a/src/ui/widgets/ConnectionItemWidget.ui b/src/ui/widgets/ConnectionItemWidget.ui index ea22eb3e..93164286 100644 --- a/src/ui/widgets/ConnectionItemWidget.ui +++ b/src/ui/widgets/ConnectionItemWidget.ui @@ -6,14 +6,26 @@ 0 0 - 203 - 60 + 237 + 61 + + + 0 + 0 + + + + + 1 + 1 + + Form - + 0 @@ -48,109 +60,66 @@ 0 - - - QLayout::SetNoConstraint - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 6 - - - 6 - - - 7 - - - 6 - - - 7 - + + + - - - - - - 11 - - - - Connection Name - - - - - - - 500ms - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - + + + + 11 + + + + Connection Name + + - - - - - Type: vmess + tls + ws - - - - - - - - 8 - - - - 0KB / 0KB - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - + + + 500ms + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Type: vmess + tls + ws + + + + + + + + 8 + + + + 0KB / 0KB + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + - - - 0 - + 0 - - 0 - 0 From 2075b4757131f24bf97ea3ce57131a7a93fed051 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 16:43:52 +0800 Subject: [PATCH 106/332] fix: fixed subscription update caused renaming issue and auto restart issue --- makespec/BUILDVERSION | 2 +- src/core/CoreUtils.cpp | 12 ++++++------ src/core/handler/ConfigHandler.cpp | 15 ++++++++------- src/core/handler/ConfigHandler.hpp | 2 +- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index eec95d2f..8af91005 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4496 +4501 diff --git a/src/core/CoreUtils.cpp b/src/core/CoreUtils.cpp index d60bc8cb..d7e6c815 100644 --- a/src/core/CoreUtils.cpp +++ b/src/core/CoreUtils.cpp @@ -62,7 +62,6 @@ namespace Qv2ray::core const tuple GetConnectionInfo(const ConnectionId &id, bool *status) { - // TODO, what if is complex? if (status != nullptr) *status = false; auto root = ConnectionManager->GetConnectionRoot(id); @@ -86,11 +85,12 @@ namespace Qv2ray::core { if (status != nullptr) *status = true; - if (IsComplexConfig(out)) - { - outboundType += " " + QObject::tr("(Guessed)"); - host += " " + QObject::tr("(Guessed)"); - } + // These lines will mess up the detection of protocols in subscription update. + // if (IsComplexConfig(out)) + //{ + // outboundType += " " + QObject::tr("(Guessed)"); + // host += " " + QObject::tr("(Guessed)"); + //} return { outboundType, host, port }; } else diff --git a/src/core/handler/ConfigHandler.cpp b/src/core/handler/ConfigHandler.cpp index 5557b40f..5f923306 100644 --- a/src/core/handler/ConfigHandler.cpp +++ b/src/core/handler/ConfigHandler.cpp @@ -195,10 +195,6 @@ namespace Qv2ray::core::handlers const optional QvConfigHandler::RenameConnection(const ConnectionId &id, const QString &newName) { CheckConnectionExistance(id); - if (!connections.contains(id)) - { - return tr("Connection doesn't exist"); - } OnConnectionRenamed(id, connections[id].displayName, newName); connections[id].displayName = newName; return {}; @@ -371,7 +367,7 @@ namespace Qv2ray::core::handlers } } - bool QvConfigHandler::UpdateConnection(const ConnectionId &id, const CONFIGROOT &root) + bool QvConfigHandler::UpdateConnection(const ConnectionId &id, const CONFIGROOT &root, bool skipRestart) { CheckConnectionExistanceEx(id, false); auto groupId = connections[id].groupId; @@ -379,6 +375,10 @@ namespace Qv2ray::core::handlers id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; auto content = JsonToString(root); emit OnConnectionChanged(id); + if (!skipRestart && id == currentConnectionId) + { + emit RestartConnection(); + } return StringToFile(content, path); } @@ -496,6 +496,7 @@ namespace Qv2ray::core::handlers continue; } bool canGetOutboundData = false; + // Should not have complex connection we assume. auto outboundData = GetConnectionInfo(config, &canGetOutboundData); // // Begin guessing new ConnectionId @@ -512,9 +513,9 @@ namespace Qv2ray::core::handlers { LOG(MODULE_CORE_HANDLER, "Reused connection id from protocol/host/port pair for connection: " + _alias) groups[id].connections << typeMap[outboundData]; + // Update Connection Properties UpdateConnection(typeMap[outboundData], config); - // Update displayName - connections[typeMap[outboundData]].displayName = _alias; + RenameConnection(typeMap[outboundData], _alias); // Remove Connection Id from the list. connectionsOrig.removeAll(typeMap[outboundData]); } diff --git a/src/core/handler/ConfigHandler.hpp b/src/core/handler/ConfigHandler.hpp index 27a30f90..6f8cc677 100644 --- a/src/core/handler/ConfigHandler.hpp +++ b/src/core/handler/ConfigHandler.hpp @@ -79,7 +79,7 @@ namespace Qv2ray::core::handlers bool IsConnected(const ConnectionId &id) const; // // Connection Operations. - bool UpdateConnection(const ConnectionId &id, const CONFIGROOT &root); + bool UpdateConnection(const ConnectionId &id, const CONFIGROOT &root, bool skipRestart = false); const optional DeleteConnection(const ConnectionId &id); const optional RenameConnection(const ConnectionId &id, const QString &newName); const optional MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); From 7689a3e21541d85ccbd3a9622bfbe9d68850539f Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 17:21:21 +0800 Subject: [PATCH 107/332] add: auto update connection details when one is updated --- makespec/BUILDVERSION | 2 +- src/core/handler/ConfigHandler.cpp | 5 +-- src/core/handler/ConfigHandler.hpp | 2 +- src/ui/widgets/ConnectionInfoWidget.cpp | 10 +++++- src/ui/widgets/ConnectionItemWidget.cpp | 43 ++++++++----------------- 5 files changed, 28 insertions(+), 34 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 8af91005..f4a335bf 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4501 +4507 diff --git a/src/core/handler/ConfigHandler.cpp b/src/core/handler/ConfigHandler.cpp index 5f923306..49a2faff 100644 --- a/src/core/handler/ConfigHandler.cpp +++ b/src/core/handler/ConfigHandler.cpp @@ -374,12 +374,13 @@ namespace Qv2ray::core::handlers auto path = (groups[groupId].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR) + groupId.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; auto content = JsonToString(root); - emit OnConnectionChanged(id); + bool result = StringToFile(content, path); + emit OnConnectionModified(id); if (!skipRestart && id == currentConnectionId) { emit RestartConnection(); } - return StringToFile(content, path); + return result; } const GroupId QvConfigHandler::CreateGroup(const QString displayName, bool isSubscription) diff --git a/src/core/handler/ConfigHandler.hpp b/src/core/handler/ConfigHandler.hpp index 6f8cc677..3ed0ac71 100644 --- a/src/core/handler/ConfigHandler.hpp +++ b/src/core/handler/ConfigHandler.hpp @@ -116,7 +116,7 @@ namespace Qv2ray::core::handlers void OnConnectionCreated(const ConnectionId &id, const QString &displayName); void OnConnectionRenamed(const ConnectionId &id, const QString &originalName, const QString &newName); void OnConnectionDeleted(const ConnectionId &id, const GroupId &originalGroupId); - void OnConnectionChanged(const ConnectionId &id); + void OnConnectionModified(const ConnectionId &id); void OnConnectionGroupChanged(const ConnectionId &id, const GroupId &originalGroup, const GroupId &newGroup); // void OnLatencyTestStarted(const ConnectionId &id); diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index a2810b32..d1bf7cbc 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -21,8 +21,16 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) // connect(ConnectionManager, &QvConfigHandler::OnConnected, this, &ConnectionInfoWidget::OnConnected); connect(ConnectionManager, &QvConfigHandler::OnDisconnected, this, &ConnectionInfoWidget::OnDisConnected); + // + connect(ConnectionManager, &QvConfigHandler::OnConnectionModified, [&](const ConnectionId &id) { + if (id == connectionId) + ShowDetails({ GetConnectionGroupId(id), id }); + }); + connect(ConnectionManager, &QvConfigHandler::OnConnectionGroupChanged, [&](const ConnectionId &id) { + if (id == connectionId) + ShowDetails({ GetConnectionGroupId(id), id }); + }); } - void ConnectionInfoWidget::ShowDetails(const tuple &_identifier) { shareLinkTxt->setStyleSheet("border-bottom: 1px solid gray; border-radius: 0px; padding: 2px; background-color: " + diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index 53041593..8663944b 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -20,23 +20,16 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare groupId = GetConnectionGroupId(id); originalItemName = GetDisplayName(id); itemType = NODE_ITEM; + // + indentSpacer->changeSize(10, indentSpacer->sizeHint().height()); + // auto latency = GetConnectionLatency(id); - - if (latency == 0) - { - latencyLabel->setText(tr("Not Tested")); - } - else - { - latencyLabel->setText(QSTRN(latency) + " " + tr("ms")); - } - + latencyLabel->setText(latency == 0 ? tr("Not Tested") : (QSTRN(latency) + " " + tr("ms"))); + // connTypeLabel->setText(tr("Type: ") + GetConnectionProtocolString(id)); auto [uplink, downlink] = GetConnectionUsageAmount(connectionId); dataLabel->setText(FormatBytes(uplink) + " / " + FormatBytes(downlink)); // - indentSpacer->changeSize(10, indentSpacer->sizeHint().height()); - // if (ConnectionManager->IsConnected(id)) { emit RequestWidgetFocus(this); @@ -46,6 +39,10 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare // // Rename events connect(renameTxt, &QLineEdit::returnPressed, this, &ConnectionItemWidget::on_doRenameBtn_clicked); + connect(ConnectionManager, &QvConfigHandler::OnConnectionModified, [&](const ConnectionId &id) { + if (id == connectionId) + connTypeLabel->setText(tr("Type: ") + GetConnectionProtocolString(id)); // + }); } // ======================================= Initialisation for root nodes. @@ -71,7 +68,7 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : OnGroupItemRenamed(id, "", originalItemName); connect(ConnectionManager, &QvConfigHandler::OnConnectionCreated, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConfigHandler::OnConnectionDeleted, this, &ConnectionItemWidget::RecalculateConnectionsCount); - connect(ConnectionManager, &QvConfigHandler::OnConnectionChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); + connect(ConnectionManager, &QvConfigHandler::OnConnectionModified, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConfigHandler::OnConnectionGroupChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConfigHandler::OnSubscriptionUpdateFinished, this, &ConnectionItemWidget::RecalculateConnectionsCount); // @@ -148,14 +145,7 @@ void ConnectionItemWidget::OnLatencyTestFinished(const ConnectionId &id, const u { if (id == connectionId) { - if (average == 0) - { - latencyLabel->setText(tr("Error")); - } - else - { - latencyLabel->setText(QSTRN(average) + tr("ms")); - } + latencyLabel->setText(average == 0 ? tr("Error") : QSTRN(average) + tr("ms")); } } @@ -186,22 +176,17 @@ void ConnectionItemWidget::on_doRenameBtn_clicked() } stackedWidget->setCurrentIndex(0); } + void ConnectionItemWidget::OnConnectionItemRenamed(const ConnectionId &id, const QString &, const QString &newName) { if (id == connectionId) { - if (ConnectionManager->IsConnected(id)) - { - connNameLabel->setText("• " + newName); - } - else - { - connNameLabel->setText(newName); - } + connNameLabel->setText((ConnectionManager->IsConnected(id) ? "• " : "") + newName); originalItemName = newName; this->setToolTip(newName); } } + void ConnectionItemWidget::OnGroupItemRenamed(const GroupId &id, const QString &, const QString &newName) { if (id == groupId) From 557f027f74f33488b261173c9c360be0dc3213ad Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 21:47:46 +0800 Subject: [PATCH 108/332] add: added QRCode blur and toggle as default --- makespec/BUILDVERSION | 2 +- src/common/QvHelpers.cpp | 40 ++++++++++++- src/common/QvHelpers.hpp | 7 ++- src/ui/w_MainWindow.cpp | 76 ++++++++++++------------- src/ui/w_MainWindow.hpp | 6 +- src/ui/w_MainWindow.ui | 42 +++++++------- src/ui/widgets/ConnectionInfoWidget.cpp | 28 +++++---- src/ui/widgets/ConnectionInfoWidget.hpp | 4 ++ src/ui/widgets/ConnectionInfoWidget.ui | 15 +---- 9 files changed, 132 insertions(+), 88 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index f4a335bf..88cb9b42 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4507 +4540 diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 12c6b468..3db8a77a 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -1,5 +1,9 @@ #include "common/QvHelpers.hpp" +#include +#include +#include +#include #include namespace Qv2ray::common @@ -150,14 +154,15 @@ namespace Qv2ray::common return QMessageBox::question(parent, title, text, QMessageBox::Yes | QMessageBox::No | extraButtons); } - QString FormatBytes(long long bytes) + QString FormatBytes(const int64_t b) { + auto _bytes = b; char str[64]; const char *sizes[5] = { "B", "KB", "MB", "GB", "TB" }; int i; - double dblByte = bytes; + double dblByte = _bytes; - for (i = 0; i < 5 && bytes >= 1024; i++, bytes /= 1024) dblByte = bytes / 1024.0; + for (i = 0; i < 5 && _bytes >= 1024; i++, _bytes /= 1024) dblByte = _bytes / 1024.0; sprintf(str, "%.2f", dblByte); return QString(str) + " " + QString(sizes[i]); @@ -203,4 +208,33 @@ namespace Qv2ray::common i++; } } + + QPixmap BlurImage(const QPixmap &pixmap, const double rad) + { + QGraphicsView view; + QGraphicsScene scene; + QGraphicsBlurEffect pBlur; + // + view.setScene(&scene); + scene.setSceneRect(pixmap.rect()); + pBlur.setBlurRadius(rad); + QGraphicsPixmapItem *p = view.scene()->addPixmap(pixmap); + p->setGraphicsEffect(&pBlur); + return view.grab(); + } + + QPixmap LightenImage(const QPixmap &pixmap, const qreal factor) + { + QGraphicsView view; + QGraphicsScene scene; + QGraphicsColorizeEffect pColor; + pColor.setColor(QColor(Qt::white)); + pColor.setStrength(factor); + // + view.setScene(&scene); + scene.setSceneRect(pixmap.rect()); + QGraphicsPixmapItem *p = view.scene()->addPixmap(pixmap); + p->setGraphicsEffect(&pColor); + return view.grab(); + } } // namespace Qv2ray::common diff --git a/src/common/QvHelpers.hpp b/src/common/QvHelpers.hpp index cca199d8..3cefd584 100644 --- a/src/common/QvHelpers.hpp +++ b/src/common/QvHelpers.hpp @@ -35,9 +35,11 @@ namespace Qv2ray::common QString JsonToString(QJsonArray array, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented); QString VerifyJsonString(const QString &source); // - QString FormatBytes(long long bytes); + QString FormatBytes(const int64_t bytes); void DeducePossibleFileName(const QString &baseDir, QString *fileName, const QString &extension); - + // + QPixmap BlurImage(const QPixmap &pixmap, const double rad = 50); + QPixmap LightenImage(const QPixmap &pixmap, const qreal factor); // This function cannot be marked as inline. QString RemoveInvalidFileName(const QString &fileName); bool IsValidFileName(const QString &fileName); @@ -100,6 +102,7 @@ namespace Qv2ray::common { auto _tm = std::localtime(&t); char MY_TIME[128]; + setlocale(1, "3"); // using strftime to display time strftime(MY_TIME, sizeof(MY_TIME), "%x - %I:%M%p", _tm); return QString(MY_TIME); diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 67ab8e34..eaca08e0 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -33,7 +33,7 @@ return; #define GetItemWidget(item) (qobject_cast(connectionListWidget->itemWidget(item, 0))) -#define NumericString(i) (QString("%1").arg(i, 15, 10, QLatin1Char('0'))) +#define NumericString(i) (QString("%1").arg(i, 30, 10, QLatin1Char('0'))) MainWindow *MainWindow::mwInstance = nullptr; @@ -77,7 +77,7 @@ void MainWindow::MWAddGroupItem_p(const GroupId &groupId) void MainWindow::SortConnectionList(MW_ITEM_COL byCol, bool asending) { - connectionListWidget->sortByColumn(MW_ITEM_COL_DISPLAYNAME, Qt::AscendingOrder); + connectionListWidget->sortByColumn(MW_ITEM_COL_NAME, Qt::AscendingOrder); for (auto i = 0; i < connectionListWidget->topLevelItemCount(); i++) { connectionListWidget->topLevelItem(i)->sortChildren(byCol, asending ? Qt::AscendingOrder : Qt::DescendingOrder); @@ -126,10 +126,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) connect(ConnectionManager, &QvConfigHandler::OnGroupDeleted, this, &MainWindow::OnGroupDeleted); // connect(ConnectionManager, &QvConfigHandler::OnConnectionRenamed, [&](const ConnectionId &id, const QString &, const QString &newName) { - connectionNodes[id]->setText(MW_ITEM_COL_DISPLAYNAME, newName); // + connectionNodes[id]->setText(MW_ITEM_COL_NAME, newName); // }); connect(ConnectionManager, &QvConfigHandler::OnLatencyTestFinished, [&](const ConnectionId &id, const uint avg) { - connectionNodes[id]->setText(MW_ITEM_COL_LATENCY, NumericString(avg)); // + connectionNodes[id]->setText(MW_ITEM_COL_PING, NumericString(avg)); // }); // connect(infoWidget, &ConnectionInfoWidget::OnEditRequested, this, &MainWindow::OnEditRequested); @@ -173,25 +173,25 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) // // Actions for right click the connection list // - QAction *action_RCM_StartThis = new QAction(QICON_R("connect.png"), tr("Connect to this"), this); + QAction *action_RCM_Start = new QAction(QICON_R("connect.png"), tr("Connect to this"), this); // - QAction *action_RCM_EditThis = new QAction(QICON_R("edit.png"), tr("Edit"), this); - QAction *action_RCM_EditAsJson = new QAction(QICON_R("json.png"), tr("Edit as JSON"), this); - QAction *action_RCM_EditAsComplex = new QAction(QICON_R("edit.png"), tr("Edit as Complex Config"), this); + QAction *action_RCM_Edit = new QAction(QICON_R("edit.png"), tr("Edit"), this); + QAction *action_RCM_EditJson = new QAction(QICON_R("json.png"), tr("Edit as JSON"), this); + QAction *action_RCM_EditComplex = new QAction(QICON_R("edit.png"), tr("Edit as Complex Config"), this); // - QAction *action_RCM_RenameThis = new QAction(tr("Rename"), this); - QAction *action_RCM_DuplicateThese = new QAction(QICON_R("duplicate.png"), tr("Duplicate to the Same Group"), this); - QAction *action_RCM_DeleteThese = new QAction(QICON_R("delete.png"), tr("Delete Connection"), this); + QAction *action_RCM_Rename = new QAction(tr("Rename"), this); + QAction *action_RCM_Duplicate = new QAction(QICON_R("duplicate.png"), tr("Duplicate to the Same Group"), this); + QAction *action_RCM_Delete = new QAction(QICON_R("delete.png"), tr("Delete Connection"), this); // - connect(action_RCM_StartThis, &QAction::triggered, this, &MainWindow::on_action_StartThis_triggered); + connect(action_RCM_Start, &QAction::triggered, this, &MainWindow::on_action_StartThis_triggered); // - connect(action_RCM_EditThis, &QAction::triggered, this, &MainWindow::on_action_RCM_EditThis_triggered); - connect(action_RCM_EditAsJson, &QAction::triggered, this, &MainWindow::on_action_RCM_EditAsJson_triggered); - connect(action_RCM_EditAsComplex, &QAction::triggered, this, &MainWindow::on_action_RCM_EditAsComplex_triggered); + connect(action_RCM_Edit, &QAction::triggered, this, &MainWindow::on_action_RCM_EditThis_triggered); + connect(action_RCM_EditJson, &QAction::triggered, this, &MainWindow::on_action_RCM_EditAsJson_triggered); + connect(action_RCM_EditComplex, &QAction::triggered, this, &MainWindow::on_action_RCM_EditAsComplex_triggered); // - connect(action_RCM_RenameThis, &QAction::triggered, this, &MainWindow::on_action_RCM_RenameThis_triggered); - connect(action_RCM_DuplicateThese, &QAction::triggered, this, &MainWindow::on_action_RCM_DuplicateThese_triggered); - connect(action_RCM_DeleteThese, &QAction::triggered, this, &MainWindow::on_action_RCM_DeleteThese_triggered); + connect(action_RCM_Rename, &QAction::triggered, this, &MainWindow::on_action_RCM_RenameThis_triggered); + connect(action_RCM_Duplicate, &QAction::triggered, this, &MainWindow::on_action_RCM_DuplicateThese_triggered); + connect(action_RCM_Delete, &QAction::triggered, this, &MainWindow::on_action_RCM_DeleteThese_triggered); // // Globally invokable signals. connect(this, &MainWindow::StartConnection, ConnectionManager, &QvConfigHandler::RestartConnection); @@ -202,31 +202,31 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) hTray.show(); // connectionListMenu = new QMenu(this); - connectionListMenu->addAction(action_RCM_StartThis); + connectionListMenu->addAction(action_RCM_Start); connectionListMenu->addSeparator(); - connectionListMenu->addAction(action_RCM_EditThis); - connectionListMenu->addAction(action_RCM_EditAsJson); - connectionListMenu->addAction(action_RCM_EditAsComplex); + connectionListMenu->addAction(action_RCM_Edit); + connectionListMenu->addAction(action_RCM_EditJson); + connectionListMenu->addAction(action_RCM_EditComplex); connectionListMenu->addSeparator(); - connectionListMenu->addAction(action_RCM_RenameThis); - connectionListMenu->addAction(action_RCM_DuplicateThese); + connectionListMenu->addAction(action_RCM_Rename); + connectionListMenu->addAction(action_RCM_Duplicate); connectionListMenu->addSeparator(); - connectionListMenu->addAction(action_RCM_DeleteThese); + connectionListMenu->addAction(action_RCM_Delete); // QMenu *sortMenu = new QMenu(tr("Sort connection list."), this); QAction *sortAction_SortByName_Asc = new QAction(tr("By connection name, A-Z")); QAction *sortAction_SortByName_Dsc = new QAction(tr("By connection name, Z-A")); - QAction *sortAction_SortByLatency_Asc = new QAction(tr("By data, Ascending")); - QAction *sortAction_SortByLatency_Dsc = new QAction(tr("By data, Descending")); - QAction *sortAction_SortByData_Asc = new QAction(tr("By latency, Ascending")); - QAction *sortAction_SortByData_Dsc = new QAction(tr("By latency, Descending")); + QAction *sortAction_SortByPing_Asc = new QAction(tr("By latency, Ascending")); + QAction *sortAction_SortByPing_Dsc = new QAction(tr("By latency, Descending")); + QAction *sortAction_SortByData_Asc = new QAction(tr("By data, Ascending")); + QAction *sortAction_SortByData_Dsc = new QAction(tr("By data, Descending")); // - connect(sortAction_SortByName_Asc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DISPLAYNAME, true); }); - connect(sortAction_SortByName_Dsc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DISPLAYNAME, false); }); - connect(sortAction_SortByData_Asc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DATAUSAGE, true); }); - connect(sortAction_SortByData_Dsc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DATAUSAGE, false); }); - connect(sortAction_SortByLatency_Asc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_LATENCY, true); }); - connect(sortAction_SortByLatency_Dsc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_LATENCY, false); }); + connect(sortAction_SortByName_Asc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_NAME, true); }); + connect(sortAction_SortByName_Dsc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_NAME, false); }); + connect(sortAction_SortByData_Asc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DATA, true); }); + connect(sortAction_SortByData_Dsc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_DATA, false); }); + connect(sortAction_SortByPing_Asc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_PING, true); }); + connect(sortAction_SortByPing_Dsc, &QAction::triggered, [&] { SortConnectionList(MW_ITEM_COL_PING, false); }); // sortMenu->addAction(sortAction_SortByName_Asc); sortMenu->addAction(sortAction_SortByName_Dsc); @@ -234,8 +234,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) sortMenu->addAction(sortAction_SortByData_Asc); sortMenu->addAction(sortAction_SortByData_Dsc); tray_RootMenu->addSeparator(); - sortMenu->addAction(sortAction_SortByLatency_Asc); - sortMenu->addAction(sortAction_SortByLatency_Dsc); + sortMenu->addAction(sortAction_SortByPing_Asc); + sortMenu->addAction(sortAction_SortByPing_Dsc); // sortBtn->setMenu(sortMenu); // @@ -738,7 +738,7 @@ void MainWindow::OnStatsAvailable(const ConnectionId &id, const quint64 upS, con NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); // // Set data accordingly - connectionNodes[id]->setText(MW_ITEM_COL_DATAUSAGE, NumericString(GetConnectionTotalData(id))); + connectionNodes[id]->setText(MW_ITEM_COL_DATA, NumericString(GetConnectionTotalData(id))); } void MainWindow::OnVCoreLogAvailable(const ConnectionId &id, const QString &log) diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index c3b40986..3179d2f0 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -19,11 +19,11 @@ enum MW_ITEM_COL { - MW_ITEM_COL_DISPLAYNAME = 1, - MW_ITEM_COL_LATENCY = 2, + MW_ITEM_COL_NAME = 1, + MW_ITEM_COL_PING = 2, MW_ITEM_COL_IMPORTTIME = 3, MW_ITEM_COL_LASTCONNETED = 4, - MW_ITEM_COL_DATAUSAGE = 5 + MW_ITEM_COL_DATA = 5 }; class MainWindow diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 2596a71a..51d11eee 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -240,9 +240,9 @@ 0 - 0 + -19 480 - 768 + 743 @@ -329,16 +329,27 @@ - - - - 13 - - - - Log - - + + + + + + 13 + + + + Log + + + + + + + Clear Log + + + + @@ -365,13 +376,6 @@ - - - - Clear Log - - - diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index d1bf7cbc..d7fb47d6 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -18,6 +18,7 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) shareLinkTxt->setAutoFillBackground(true); shareLinkTxt->setCursor(QCursor(Qt::CursorShape::IBeamCursor)); shareLinkTxt->installEventFilter(this); + qrLabel->installEventFilter(this); // connect(ConnectionManager, &QvConfigHandler::OnConnected, this, &ConnectionInfoWidget::OnConnected); connect(ConnectionManager, &QvConfigHandler::OnDisconnected, this, &ConnectionInfoWidget::OnDisConnected); @@ -64,9 +65,16 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden QZXingEncoderConfig conf; conf.border = true; conf.imageSize = QSize(400, 400); - auto img = QZXing().encodeData(shareLink, conf); + conf.errorCorrectionLevel = QZXing::EncodeErrorCorrectionLevel_M; + QZXing qzx; + auto img = qzx.encodeData(shareLink, conf); + // + qrPixmap = QPixmap::fromImage(img); + qrPixmapBlured = BlurImage(LightenImage(QPixmap::fromImage(img), 0.75), 20); + // + isRealPixmapShown = false; + qrLabel->setPixmap(qrPixmapBlured); qrLabel->setScaledContents(true); - qrLabel->setPixmap(QPixmap::fromImage(img)); // connectBtn->setIcon(ConnectionManager->IsConnected(connectionId) ? QICON_R("stop.png") : QICON_R("connect.png")); } @@ -135,15 +143,15 @@ void ConnectionInfoWidget::on_deleteBtn_clicked() bool ConnectionInfoWidget::eventFilter(QObject *object, QEvent *event) { - if (event->type() == QEvent::MouseButtonRelease) + if (shareLinkTxt->underMouse() && event->type() == QEvent::MouseButtonRelease) { - if (shareLinkTxt->underMouse()) - { - if (!shareLinkTxt->hasSelectedText()) - { - shareLinkTxt->selectAll(); - } - } + if (!shareLinkTxt->hasSelectedText()) + shareLinkTxt->selectAll(); + } + else if (qrLabel->underMouse() && event->type() == QEvent::MouseButtonRelease) + { + qrLabel->setPixmap(isRealPixmapShown ? qrPixmapBlured : qrPixmap); + isRealPixmapShown = !isRealPixmapShown; } return QWidget::eventFilter(object, event); diff --git a/src/ui/widgets/ConnectionInfoWidget.hpp b/src/ui/widgets/ConnectionInfoWidget.hpp index 226b960e..1ae2c21a 100644 --- a/src/ui/widgets/ConnectionInfoWidget.hpp +++ b/src/ui/widgets/ConnectionInfoWidget.hpp @@ -36,4 +36,8 @@ class ConnectionInfoWidget private: ConnectionId connectionId = NullConnectionId; GroupId groupId = NullGroupId; + // + bool isRealPixmapShown; + QPixmap qrPixmap; + QPixmap qrPixmapBlured; }; diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index ec1cdb52..17fa3be5 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -29,6 +29,9 @@ Form + + 0 + @@ -146,9 +149,6 @@ - - 0 - 0 @@ -160,12 +160,6 @@ - - 9 - - - 6 - @@ -349,9 +343,6 @@ - - 0 - 0 From a2a95dfb5b8eb8c7efeb448462911da3e1427bae Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 5 Mar 2020 22:32:42 +0800 Subject: [PATCH 109/332] add: added toggle visibility of chart and log box in MainWindow --- makespec/BUILDVERSION | 2 +- src/ui/w_MainWindow.cpp | 15 +++ src/ui/w_MainWindow.hpp | 6 + src/ui/w_MainWindow.ui | 164 +++++++++++++++++-------- src/ui/widgets/ConnectionInfoWidget.ui | 2 +- 5 files changed, 134 insertions(+), 55 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 88cb9b42..cbd82cad 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4540 +4560 diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index eaca08e0..ba49218b 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -910,3 +910,18 @@ void MainWindow::on_connectionListWidget_itemSelectionChanged() connectionListWidget->setFocus(); } } + +void MainWindow::on_chartVisibilityBtn_clicked() +{ + speedChartHolderWidget->setVisible(!speedChartWidget->isVisible()); +} + +void MainWindow::on_logVisibilityBtn_clicked() +{ + masterLogBrowser->setVisible(!masterLogBrowser->isVisible()); +} + +void MainWindow::on_clearChartBtn_clicked() +{ + speedChartWidget->Clear(); +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 3179d2f0..936d7a18 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -99,6 +99,12 @@ class MainWindow void on_connectionListWidget_itemSelectionChanged(); + void on_chartVisibilityBtn_clicked(); + + void on_logVisibilityBtn_clicked(); + + void on_clearChartBtn_clicked(); + private: QHash> groupNodes; QHash> connectionNodes; diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 51d11eee..650007f2 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -19,6 +19,9 @@ Qv2ray + + Click to toggle show/hide + @@ -137,7 +140,7 @@ - Import connection + Import Connection Add @@ -167,6 +170,9 @@ + + Sort + @@ -240,9 +246,9 @@ 0 - -19 + -194 480 - 743 + 752 @@ -279,33 +285,53 @@ 0 - - 0 - - - - - 13 - - - - Speed Graph - - + + + + + + 13 + + + + Qt::NoFocus + + + Click to toggle show/hide + + + Text-align:left; + + + Speed Graph + + + true + + + + + + + Clear chart data + + + + + + + :/assets/icons/ui_light/delete.png:/assets/icons/ui_light/delete.png + + + + - - - Qt::Horizontal - - - - - + 0 @@ -313,9 +339,6 @@ - - 0 - 0 @@ -329,52 +352,84 @@ - + - + 13 + + Qt::NoFocus + + + Text-align:left; + - Log + Log + + + true - + + + Clear log + - Clear Log + + + + + :/assets/icons/ui_light/delete.png:/assets/icons/ui_light/delete.png - - - Qt::Horizontal + + + 6 - + + + + + 0 + 200 + + + + + 9 + + + + QTextEdit::NoWrap + + + + - - + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + - 0 - 200 + 20 + 0 - - - 9 - - - - QTextEdit::NoWrap - - + @@ -384,10 +439,7 @@ - 4 - - - 6 + 2 @@ -451,6 +503,9 @@ 8 + + Upload/Download speed + 0.00 B/s 0.00 B/s @@ -505,6 +560,9 @@ 8 + + Upload/Download Data + 0.00 B 0.00 B diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index 17fa3be5..8284fef2 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -30,7 +30,7 @@ - 0 + 6 From 108810e5fb2359d7e84892379926aaf1fd447d20 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 6 Mar 2020 09:45:12 +0800 Subject: [PATCH 110/332] add: navigate to current connection after sort --- makespec/BUILDVERSION | 2 +- src/ui/w_MainWindow.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index cbd82cad..ce7544c5 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4560 +4561 diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index ba49218b..0ab9f1b5 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -82,6 +82,7 @@ void MainWindow::SortConnectionList(MW_ITEM_COL byCol, bool asending) { connectionListWidget->topLevelItem(i)->sortChildren(byCol, asending ? Qt::AscendingOrder : Qt::DescendingOrder); } + on_locateBtn_clicked(); } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) From b7ab20f4c76806b8e5ac09049aa949863fcd03b5 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 6 Mar 2020 15:19:32 +0800 Subject: [PATCH 111/332] cmake: introducing cmake --- .github/workflows/build-qv2ray-cmake.yml | 213 +++++++++++++++++++++++ .gitignore | 2 +- CMakeLists.txt | 1 + 3 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build-qv2ray-cmake.yml create mode 100644 CMakeLists.txt diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml new file mode 100644 index 00000000..c7f28fbb --- /dev/null +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -0,0 +1,213 @@ +name: Qv2ray build matrix - cmake + +on: + push: + release: + types: [prereleased] + +jobs: + build: + strategy: + matrix: + qt_version: [5.13.2, 5.14.1] + platform: [ubuntu-16.04, macos-latest, windows-latest] + arch: [x86, x64] + include: + - platform: windows-latest + arch: x86 + qtarch: win32_msvc2017 + - platform: windows-latest + arch: x64 + qtarch: win64_msvc2017_64 + exclude: + - platform: ubuntu-16.04 + arch: x86 + - platform: macos-latest + arch: x86 + fail-fast: false + + runs-on: ${{ matrix.platform }} + + steps: + - name: Get the version + id: get_version + shell: bash + run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3) + - name: Checking out sources + uses: actions/checkout@master + - name: Install Python 3.7 version + uses: actions/setup-python@v1 + with: + python-version: '3.7' + architecture: ${{ matrix.arch }} + - name: Restoring submodules + run: git submodule update --init +# -------------------------------------------------------- + - name: Install MSVC compiler + if: matrix.platform == 'windows-latest' + uses: ilammy/msvc-dev-cmd@v1 + with: + # 14.1 is for vs2017, 14.2 is vs2019, following the upstream vcpkg build from Qv2ray-deps repo + toolset: 14.2 + arch: ${{ matrix.arch }} + - name: Cache Qt + id: cache-qt + uses: actions/cache@v1 + with: + path: ../Qt + key: QtCache-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.qt_version }} + - name: Installing Qt - ${{ matrix.arch }} + uses: jurplel/install-qt-action@v2.5.0 + with: + version: ${{ matrix.qt_version }} + arch: ${{ matrix.qtarch }} + mirror: 'http://mirrors.ocf.berkeley.edu/qt/' + cached: ${{ steps.cache-qt.outputs.cache-hit }} +# -------------------------------------------------------- + - name: Linux - Install Packages + if: matrix.platform == 'ubuntu-16.04' + run: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/test + sudo add-apt-repository ppa:webispy/grpc + sudo add-apt-repository ppa:carsten-uppenbrink-net/openssl + sudo apt update + sudo apt install -y gcc-7 libgl-dev openssl libx11-dev libxkbcommon-x11-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler + + - name: macOS - Install Packages + if: matrix.platform == 'macos-latest' + run: | + brew install protobuf + brew install grpc + + - name: Windows - Install Packages + if: matrix.platform == 'windows-latest' + run: choco install jom -y +# -------------------------------------------------------- + - name: Cross-platform - Download libraries + shell: bash + run: | + curl -o ./libs/libqvb-linux64.a -L https://github.com/Qv2ray/QvRPCBridge/releases/download/v1.1/libqvb-linux64.a + curl -o ./libs/libqvb-darwin.a -L https://github.com/Qv2ray/QvRPCBridge/releases/download/v1.1/libqvb-darwin.a + curl -o ./libs/Qv2ray-deps-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-${{ matrix.arch }}-windows.7z + - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Extract Windows Dependencies + if: matrix.platform == 'windows-latest' + uses: DuckSoft/extract-7z-action@v1.0 + with: + pathSource: ./libs/Qv2ray-deps-${{ matrix.arch }}-windows.7z + pathTarget: ./libs +# -------------------------------------------------------- Generate MakeFile + - name: Cross-platform - ${{ matrix.qt_version }} - Generate Dependencies and Makefile + shell: bash + run: | + mkdir build + cd build + export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" + export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" + cmake .. + +#qmake .. CONFIG+="debug_and_release no_increase_build_number" PREFIX=/usr +# -------------------------------------------------------- Build + - name: Unix - ${{ matrix.qt_version }} - Build Qv2ray + if: matrix.platform != 'windows-latest' + run: | + cd build + make -j2 release $([ "${{ matrix.platform }}" == "ubuntu-16.04" ] && echo "CC=gcc-7 CXX=g++-7" LINK="g++-7" || echo "") + - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Build Qv2ray + if: matrix.platform == 'windows-latest' + run: | + cd build + jom +# -------------------------------------------------------- Deployments + - name: Linux - ${{ matrix.qt_version }} - Generating AppImage + if: matrix.platform == 'ubuntu-16.04' + run: | + cd build + wget https://github.com/probonopd/linuxdeployqt/releases/download/6/linuxdeployqt-6-x86_64.AppImage + chmod +x ./linuxdeployqt-6-x86_64.AppImage + ./linuxdeployqt-6-x86_64.AppImage --appimage-extract + make install INSTALL_ROOT=AppDir + cd AppDir + wget -c https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/AppRun-patched-x86_64 -O AppRun + chmod a+x AppRun + mkdir -p ./usr/{lib,optional}/ + wget -c https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/exec-x86_64.so -O ./usr/optional/exec.so + mkdir -p ./usr/optional/libstdc++/ + cp -fv /usr/lib/x86_64-linux-gnu/libstdc++.so.6 ./usr/optional/libstdc++/ + mkdir -p ./usr/optional/libgcc_s/ + cp -fv /lib/x86_64-linux-gnu/libgcc_s.so.1 ./usr/optional/libgcc_s/ + cp -fv /usr/lib/x86_64-linux-gnu/{libssl.so.1.1,libcrypto.so.1.1} ./usr/lib/ + ../squashfs-root/AppRun usr/share/applications/qv2ray.desktop -appimage -no-strip -always-overwrite + mv ./Qv2ray*.AppImage ./Qv2ray.AppImage + - name: Linux - ${{ matrix.qt_version }} - Uploading artifact + if: matrix.platform == 'ubuntu-16.04' + uses: actions/upload-artifact@master + with: + name: Qv2ray-${{ github.sha }}.linux-${{ matrix.arch }}.qt${{ matrix.qt_version }}.AppImage + path: build/AppDir/Qv2ray.AppImage + - name: Linux - ${{ matrix.qt_version }} - Upload binaries to release + uses: svenstaro/upload-release-action@v1-release + if: github.event_name == 'release' && matrix.platform == 'ubuntu-16.04' && matrix.qt_version == '5.14.1' + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: build/AppDir/Qv2ray.AppImage + asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.linux-${{ matrix.arch }}.AppImage + tag: ${{ github.ref }} + overwrite: true +# == + - name: macOS - ${{ matrix.qt_version }} - Making release tarball + if: matrix.platform == 'macos-latest' + run: | + cd build + cd qv2ray.app + macdeployqt ./ + cd .. + tar czf Qv2ray.app.tar.gz qv2ray.app + - name: macOS - ${{ matrix.qt_version }} - Uploading Artifact + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@master + with: + name: Qv2ray-${{ github.sha }}.macOS-${{ matrix.arch }}.qt${{ matrix.qt_version }}.zip + path: build/Qv2ray.app.tar.gz + - name: macOS - ${{ matrix.qt_version }} - Upload binaries to release + uses: svenstaro/upload-release-action@v1-release + if: github.event_name == 'release' && matrix.platform == 'macos-latest' && matrix.qt_version == '5.14.1' + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: build/Qv2ray.app.tar.gz + asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.macOS-${{ matrix.arch }}.tar.gz + tag: ${{ github.ref }} + overwrite: true +# == + - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Copying DLLs to build output folders + if: matrix.platform == 'windows-latest' + run: .\.github\workflows\copy_DLLs.bat + - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Running windeployqt + if: matrix.platform == 'windows-latest' + shell: cmd + run: | + cd build + cd release + del *.cpp *.h *.o *.qrc *.qm *.hpp *.obj + set VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\ + windeployqt ./qv2ray.exe --compiler-runtime --verbose 2 + - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Create 7z Release + if: matrix.platform == 'windows-latest' + uses: DuckSoft/create-7z-action@v1.0 + with: + pathSource: ./build/release/ + pathTarget: ./release.7z + - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Uploading artifact + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@master + with: + name: Qv2ray-${{ github.sha }}.Windows-${{ matrix.arch }}.qt${{ matrix.qt_version }}.7z + path: release.7z + - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Upload binaries to release + uses: svenstaro/upload-release-action@v1-release + if: github.event_name == 'release' && matrix.platform == 'windows-latest' && matrix.qt_version == '5.14.1' + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: release.7z + asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.Windows-${{ matrix.arch }}.7z + tag: ${{ github.ref }} + overwrite: true diff --git a/.gitignore b/.gitignore index dc2ea0df..1e23df71 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,4 @@ libs/x64-windows/ libs/x86-windows/ libs/libqvb-* -build/ +build**/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..8f5390ad --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1 @@ +project(Qv2ray) From 11ae589dd9370c315a10439a332d60120a3f2c20 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 16:22:33 +0800 Subject: [PATCH 112/332] update CMakeLists.txt --- CMakeLists.txt | 18 ++++++++++++++++++ cmake/ssl.cmake | 1 + 2 files changed, 19 insertions(+) create mode 100644 cmake/ssl.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f5390ad..72a6cf6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1 +1,19 @@ +cmake_minimum_required(VERSION 3.5.1) + +file(READ "makespec/VERSION" QV2RAY_VERSION) +file(READ "makespec/BUILDVERSION" QV2RAY_BUILD_VERSION) +set(PROJECT_VERSION "${QV2RAY_VERSION}.${QV2RAY_BUILD_VERSION}") project(Qv2ray) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(CMAKE_VERSION VERSION_LESS "3.7.0") + set(CMAKE_INCLUDE_CURRENT_DIR ON) +endif() + +find_package(Qt5 COMPONENTS Core Gui Widgets Network REQUIRED) \ No newline at end of file diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake new file mode 100644 index 00000000..81abd3d8 --- /dev/null +++ b/cmake/ssl.cmake @@ -0,0 +1 @@ +find_package(OpenSSL REQUIRED) \ No newline at end of file From 4780ec0bb6ac3f299bca04f9bd1a7758ae093a92 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 17:18:47 +0800 Subject: [PATCH 113/332] add cpp sources --- CMakeLists.txt | 65 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 72a6cf6d..5385e3a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required(VERSION 3.5.1) -file(READ "makespec/VERSION" QV2RAY_VERSION) -file(READ "makespec/BUILDVERSION" QV2RAY_BUILD_VERSION) -set(PROJECT_VERSION "${QV2RAY_VERSION}.${QV2RAY_BUILD_VERSION}") +file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/VERSION" QV2RAY_VERSION) +file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" QV2RAY_BUILD_VERSION) +set(PACKAGE_VERSION "${QV2RAY_VERSION}.${QV2RAY_BUILD_VERSION}") project(Qv2ray) set(CMAKE_CXX_STANDARD 17) @@ -16,4 +16,63 @@ if(CMAKE_VERSION VERSION_LESS "3.7.0") set(CMAKE_INCLUDE_CURRENT_DIR ON) endif() +set(QV2RAY_SOURCES + src/base/Qv2rayLog.cpp + src/common/CommandArgs.cpp + src/common/HTTPRequestHelper.cpp + src/common/LogHighlighter.cpp + src/common/QJsonModel.cpp + src/common/QvHelpers.cpp + src/components/autolaunch/QvAutoLaunch.cpp + src/components/geosite/QvGeositeReader.cpp + src/components/icmping/win/ICMPPinger.cpp + src/components/pac/QvGFWPACConverter.cpp + src/components/pac/QvPACHandler.cpp + src/components/plugins/toolbar/QvToolbar.cpp + src/components/plugins/toolbar/QvToolbar_linux.cpp + src/components/plugins/toolbar/QvToolbar_win.cpp + src/components/proxy/QvProxyConfigurator.cpp + src/components/speedchart/speedplotview.cpp + src/components/speedchart/speedwidget.cpp + src/core/connection/ConnectionIO.cpp + src/core/connection/Generation.cpp + src/core/connection/Serialization.cpp + src/core/connection/Serialization_ss.cpp + src/core/connection/Serialization_ssd.cpp + src/core/connection/Serialization_vmess.cpp + src/core/CoreUtils.cpp + src/core/handler/ConfigHandler.cpp + src/core/handler/V2rayInstanceHandler.cpp + src/core/kernel/APIBackend.cpp + src/core/kernel/KernelInteractions.cpp + src/core/settings/SettingsBackend.cpp + src/core/settings/SettingsUpgrade.cpp + src/core/tcping/QvTCPing.cpp + src/main.cpp + src/ui/editors/w_InboundEditor.cpp + src/ui/editors/w_JsonEditor.cpp + src/ui/editors/w_OutboundEditor.cpp + src/ui/editors/w_RoutesEditor.cpp + src/ui/editors/w_RoutesEditor_extra.cpp + src/ui/messaging/QvMessageBus.cpp + src/ui/models/InboundNodeModel.cpp + src/ui/models/OutboundNodeModel.cpp + src/ui/models/RuleNodeModel.cpp + src/ui/widgets/ConnectionInfoWidget.cpp + src/ui/widgets/ConnectionItemWidget.cpp + src/ui/widgets/QvAutoCompleteTextEdit.cpp + src/ui/widgets/StreamSettingsWidget.cpp + src/ui/w_ExportConfig.cpp + src/ui/w_ImportConfig.cpp + src/ui/w_MainWindow.cpp + src/ui/w_MainWindow_extra.cpp + src/ui/w_PreferencesWindow.cpp + src/ui/w_ScreenShot_Core.cpp + src/ui/w_SubscriptionManager.cpp +) + +add_executable(qv2ray + ${QV2RAY_SOURCES} +) + find_package(Qt5 COMPONENTS Core Gui Widgets Network REQUIRED) \ No newline at end of file From 480ee1bb25f144c0c55f13a55f2b66810c0702d7 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 6 Mar 2020 17:26:54 +0800 Subject: [PATCH 114/332] cmake: fixed moc slots issue where MACROS are not being expanded --- makespec/BUILDVERSION | 2 +- src/ui/editors/w_InboundEditor.hpp | 3 ++- src/ui/editors/w_JsonEditor.hpp | 3 ++- src/ui/editors/w_OutboundEditor.hpp | 3 ++- src/ui/editors/w_RoutesEditor.hpp | 3 ++- src/ui/w_ExportConfig.hpp | 3 ++- src/ui/w_ImportConfig.hpp | 3 ++- src/ui/w_MainWindow.hpp | 3 ++- src/ui/w_PreferencesWindow.hpp | 2 +- src/ui/w_SubscriptionManager.hpp | 2 +- 10 files changed, 17 insertions(+), 10 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index ce7544c5..90d39491 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4561 +4562 diff --git a/src/ui/editors/w_InboundEditor.hpp b/src/ui/editors/w_InboundEditor.hpp index be23aed7..9e6a8333 100644 --- a/src/ui/editors/w_InboundEditor.hpp +++ b/src/ui/editors/w_InboundEditor.hpp @@ -18,7 +18,8 @@ class InboundEditor explicit InboundEditor(INBOUND root, QWidget *parent = nullptr); ~InboundEditor(); INBOUND OpenEditor(); - public slots: + + private: QvMessageBusSlotDecl; private slots: diff --git a/src/ui/editors/w_JsonEditor.hpp b/src/ui/editors/w_JsonEditor.hpp index afdf0b5f..01a155fc 100644 --- a/src/ui/editors/w_JsonEditor.hpp +++ b/src/ui/editors/w_JsonEditor.hpp @@ -18,7 +18,8 @@ class JsonEditor explicit JsonEditor(QJsonObject rootObject, QWidget *parent = nullptr); ~JsonEditor(); QJsonObject OpenEditor(); - public slots: + + private: QvMessageBusSlotDecl; private slots: diff --git a/src/ui/editors/w_OutboundEditor.hpp b/src/ui/editors/w_OutboundEditor.hpp index 153076e0..34a81964 100644 --- a/src/ui/editors/w_OutboundEditor.hpp +++ b/src/ui/editors/w_OutboundEditor.hpp @@ -18,7 +18,8 @@ class OutboundEditor ~OutboundEditor(); OUTBOUND OpenEditor(); QString GetFriendlyName(); - public slots: + + private: QvMessageBusSlotDecl; signals: void s_reload_config(bool need_restart); diff --git a/src/ui/editors/w_RoutesEditor.hpp b/src/ui/editors/w_RoutesEditor.hpp index 9aa52f4d..5fe867c1 100644 --- a/src/ui/editors/w_RoutesEditor.hpp +++ b/src/ui/editors/w_RoutesEditor.hpp @@ -36,7 +36,8 @@ class RouteEditor explicit RouteEditor(QJsonObject connection, QWidget *parent = nullptr); ~RouteEditor(); CONFIGROOT OpenEditor(); - public slots: + + private: QvMessageBusSlotDecl; private slots: diff --git a/src/ui/w_ExportConfig.hpp b/src/ui/w_ExportConfig.hpp index ffce983a..44546167 100644 --- a/src/ui/w_ExportConfig.hpp +++ b/src/ui/w_ExportConfig.hpp @@ -15,7 +15,8 @@ class ConfigExporter explicit ConfigExporter(QWidget *parent = nullptr); ~ConfigExporter(); void OpenExport(); - public slots: + + private: QvMessageBusSlotDecl; protected: diff --git a/src/ui/w_ImportConfig.hpp b/src/ui/w_ImportConfig.hpp index 754d865b..ef1210d9 100644 --- a/src/ui/w_ImportConfig.hpp +++ b/src/ui/w_ImportConfig.hpp @@ -18,7 +18,8 @@ class ImportConfigWindow explicit ImportConfigWindow(QWidget *parent = nullptr); ~ImportConfigWindow(); QMultiMap OpenImport(bool outboundsOnly = false); - public slots: + + private: QvMessageBusSlotDecl; private slots: diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 936d7a18..0c20cab1 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -38,7 +38,8 @@ class MainWindow void StartConnection() const; void StopConnection() const; void RestartConnection() const; - public slots: + + private: QvMessageBusSlotDecl; private slots: void on_activatedTray(QSystemTrayIcon::ActivationReason reason); diff --git a/src/ui/w_PreferencesWindow.hpp b/src/ui/w_PreferencesWindow.hpp index 06348abe..e45f102c 100644 --- a/src/ui/w_PreferencesWindow.hpp +++ b/src/ui/w_PreferencesWindow.hpp @@ -18,7 +18,7 @@ class PreferencesWindow signals: void s_reload_config(bool need_restart); - public slots: + private: QvMessageBusSlotDecl; private slots: diff --git a/src/ui/w_SubscriptionManager.hpp b/src/ui/w_SubscriptionManager.hpp index 986c5db2..b4e60bd8 100644 --- a/src/ui/w_SubscriptionManager.hpp +++ b/src/ui/w_SubscriptionManager.hpp @@ -18,7 +18,7 @@ class SubscribeEditor ~SubscribeEditor(); tuple GetSelectedConfig(); - public slots: + private: QvMessageBusSlotDecl; private slots: From 3f48e052c1ad6a4aae197b205770a07384223770 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 17:38:02 +0800 Subject: [PATCH 115/332] linking qt libraries --- CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5385e3a2..0e2069d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,8 @@ project(Qv2ray) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +find_package(Qt5 COMPONENTS Core Gui Widgets Network REQUIRED) + set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) @@ -75,4 +77,9 @@ add_executable(qv2ray ${QV2RAY_SOURCES} ) -find_package(Qt5 COMPONENTS Core Gui Widgets Network REQUIRED) \ No newline at end of file +target_link_libraries(qv2ray + Qt5::Core + Qt5::Gui + Qt5::Widgets + Qt5::Network +) \ No newline at end of file From 476bf37eb87f232dae24dbda6a3697042a979bc5 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 17:50:30 +0800 Subject: [PATCH 116/332] add target_include_directories --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e2069d5..82bae417 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,4 +82,8 @@ target_link_libraries(qv2ray Qt5::Gui Qt5::Widgets Qt5::Network +) + +target_include_directories(qv2ray PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} ) \ No newline at end of file From b2b4cf7899178ce635430dc0ca6834e70fb0f0e7 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 17:52:15 +0800 Subject: [PATCH 117/332] update github actions --- .github/workflows/build-qv2ray-cmake.yml | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index c7f28fbb..ae6a4bff 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -78,10 +78,6 @@ jobs: run: | brew install protobuf brew install grpc - - - name: Windows - Install Packages - if: matrix.platform == 'windows-latest' - run: choco install jom -y # -------------------------------------------------------- - name: Cross-platform - Download libraries shell: bash @@ -107,16 +103,10 @@ jobs: #qmake .. CONFIG+="debug_and_release no_increase_build_number" PREFIX=/usr # -------------------------------------------------------- Build - - name: Unix - ${{ matrix.qt_version }} - Build Qv2ray - if: matrix.platform != 'windows-latest' + - name: Build Qv2ray run: | cd build - make -j2 release $([ "${{ matrix.platform }}" == "ubuntu-16.04" ] && echo "CC=gcc-7 CXX=g++-7" LINK="g++-7" || echo "") - - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Build Qv2ray - if: matrix.platform == 'windows-latest' - run: | - cd build - jom + cmake --build . # -------------------------------------------------------- Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage if: matrix.platform == 'ubuntu-16.04' From 9517fedb7e2eece72470e44effcd1da0c234d21d Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 17:56:11 +0800 Subject: [PATCH 118/332] update CMakeLists.txt --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82bae417..a7f8544f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,4 +86,5 @@ target_link_libraries(qv2ray target_include_directories(qv2ray PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/src ) \ No newline at end of file From 285efe22a793e292024750d7f8a6b89f6604bd5e Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 18:16:24 +0800 Subject: [PATCH 119/332] add qhttpserver --- CMakeLists.txt | 4 ++++ cmake/qhttpserver.cmake | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 cmake/qhttpserver.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index a7f8544f..feee8682 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,8 @@ if(CMAKE_VERSION VERSION_LESS "3.7.0") set(CMAKE_INCLUDE_CURRENT_DIR ON) endif() +include(cmake/qhttpserver.cmake) + set(QV2RAY_SOURCES src/base/Qv2rayLog.cpp src/common/CommandArgs.cpp @@ -75,6 +77,7 @@ set(QV2RAY_SOURCES add_executable(qv2ray ${QV2RAY_SOURCES} + ${QHTTPSERVER_SOURCES} ) target_link_libraries(qv2ray @@ -87,4 +90,5 @@ target_link_libraries(qv2ray target_include_directories(qv2ray PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src + ${QHTTPSERVER_DIR} ) \ No newline at end of file diff --git a/cmake/qhttpserver.cmake b/cmake/qhttpserver.cmake new file mode 100644 index 00000000..fbf246b3 --- /dev/null +++ b/cmake/qhttpserver.cmake @@ -0,0 +1,8 @@ +set(QHTTPSERVER_DIR "${CMAKE_SOURCE_DIR}/3rdparty/qhttpserver/src") + +set(QHTTPSERVER_SOURCES + ${QHTTPSERVER_DIR}/qhttpconnection.cpp + ${QHTTPSERVER_DIR}/qhttprequest.cpp + ${QHTTPSERVER_DIR}/qhttpresponse.cpp + ${QHTTPSERVER_DIR}/qhttpserver.cpp +) \ No newline at end of file From b32d8e77f272b5dfd351385e1581295348b446e2 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 18:33:40 +0800 Subject: [PATCH 120/332] update actions --- .github/workflows/build-qv2ray-cmake.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index ae6a4bff..bd27425a 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -67,11 +67,10 @@ jobs: - name: Linux - Install Packages if: matrix.platform == 'ubuntu-16.04' run: | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo add-apt-repository ppa:webispy/grpc sudo add-apt-repository ppa:carsten-uppenbrink-net/openssl sudo apt update - sudo apt install -y gcc-7 libgl-dev openssl libx11-dev libxkbcommon-x11-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler + sudo apt install -y libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler - name: macOS - Install Packages if: matrix.platform == 'macos-latest' @@ -91,6 +90,12 @@ jobs: with: pathSource: ./libs/Qv2ray-deps-${{ matrix.arch }}-windows.7z pathTarget: ./libs +# -------------------------------------------------------- Set gcc version for xenial + - name: Linux - Set gcc version + shell: bash + run: | + export CC=gcc-9 + export CXX=g++-9 # -------------------------------------------------------- Generate MakeFile - name: Cross-platform - ${{ matrix.qt_version }} - Generate Dependencies and Makefile shell: bash From ba629f53c81a6c581fd71aec6e3012b980b5be8f Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 18:37:30 +0800 Subject: [PATCH 121/332] Revert "update actions" This reverts commit b32d8e77f272b5dfd351385e1581295348b446e2. --- .github/workflows/build-qv2ray-cmake.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index bd27425a..ae6a4bff 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -67,10 +67,11 @@ jobs: - name: Linux - Install Packages if: matrix.platform == 'ubuntu-16.04' run: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo add-apt-repository ppa:webispy/grpc sudo add-apt-repository ppa:carsten-uppenbrink-net/openssl sudo apt update - sudo apt install -y libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler + sudo apt install -y gcc-7 libgl-dev openssl libx11-dev libxkbcommon-x11-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler - name: macOS - Install Packages if: matrix.platform == 'macos-latest' @@ -90,12 +91,6 @@ jobs: with: pathSource: ./libs/Qv2ray-deps-${{ matrix.arch }}-windows.7z pathTarget: ./libs -# -------------------------------------------------------- Set gcc version for xenial - - name: Linux - Set gcc version - shell: bash - run: | - export CC=gcc-9 - export CXX=g++-9 # -------------------------------------------------------- Generate MakeFile - name: Cross-platform - ${{ matrix.qt_version }} - Generate Dependencies and Makefile shell: bash From e0dcbcfcad894fbed3176d087dba41fa6d445b1d Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 18:48:36 +0800 Subject: [PATCH 122/332] build-qv2ray-cmake.yml --- .github/workflows/build-qv2ray-cmake.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index ae6a4bff..ec4a4a42 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -67,11 +67,10 @@ jobs: - name: Linux - Install Packages if: matrix.platform == 'ubuntu-16.04' run: | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo add-apt-repository ppa:webispy/grpc sudo add-apt-repository ppa:carsten-uppenbrink-net/openssl sudo apt update - sudo apt install -y gcc-7 libgl-dev openssl libx11-dev libxkbcommon-x11-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler + sudo apt install -y libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler - name: macOS - Install Packages if: matrix.platform == 'macos-latest' @@ -94,13 +93,26 @@ jobs: # -------------------------------------------------------- Generate MakeFile - name: Cross-platform - ${{ matrix.qt_version }} - Generate Dependencies and Makefile shell: bash + if: matrix.platform != 'ubuntu-16.04' + run: | + mkdir build + cd build + export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" + export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" + cmake .. + + - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Makefile + if: matrix.platform == 'ubuntu-16.04' + shell: bash + env: + CC: /usr/bin/gcc-9 + CXX: /usr/bin/g++-9 run: | mkdir build cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" cmake .. - #qmake .. CONFIG+="debug_and_release no_increase_build_number" PREFIX=/usr # -------------------------------------------------------- Build - name: Build Qv2ray From 791e1ae902dbf671837ded03c725f2487e466227 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 21:45:20 +0800 Subject: [PATCH 123/332] add translation resources --- CMakeLists.txt | 32 +++++++++++++++++++++++++++++++- cmake/translations.cmake | 3 +++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 cmake/translations.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index feee8682..cc98000d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ if(CMAKE_VERSION VERSION_LESS "3.7.0") endif() include(cmake/qhttpserver.cmake) +include(cmake/translations.cmake) set(QV2RAY_SOURCES src/base/Qv2rayLog.cpp @@ -75,9 +76,12 @@ set(QV2RAY_SOURCES src/ui/w_SubscriptionManager.cpp ) +set(QRC_RESOURCES ${CMAKE_SOURCE_DIR}/resources.qrc) + add_executable(qv2ray ${QV2RAY_SOURCES} ${QHTTPSERVER_SOURCES} + ${QRC_RESOURCES} ) target_link_libraries(qv2ray @@ -91,4 +95,30 @@ target_include_directories(qv2ray PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src ${QHTTPSERVER_DIR} -) \ No newline at end of file +) + +install(TARGETS qv2ray + RUNTIME + DESTINATION bin +) + +if(UNIX AND NOT APPLE) + install(FILES assets/qv2ray.metainfo.xml + DESTINATION share/metainfo + ) + + install(FILES assets/qv2ray.desktop + DESTINATION share/applications + ) + + install(FILES assets/icons/qv2ray.png + DESTINATION share/icons/hicolor/256x256/apps/ + ) +endif() + +if(UNIX AND NOT WIN32) + + install(FILES ${QM_FILES} + DESTINATION share + ) +endif() \ No newline at end of file diff --git a/cmake/translations.cmake b/cmake/translations.cmake new file mode 100644 index 00000000..1423effc --- /dev/null +++ b/cmake/translations.cmake @@ -0,0 +1,3 @@ +find_package(Qt5 COMPONENTS LinguistTools) +set(TRANSLATIONS_DIR ${CMAKE_SOURCE_DIR}/translations) +qt5_create_translation(QM_FILES ${TRANSLATIONS_DIR} en_US.ts ja_JP.ts ru_RU.ts zh_CN.ts) \ No newline at end of file From 30179110fe022e616c492d874173baaf4a0d5dca Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 22:00:02 +0800 Subject: [PATCH 124/332] add qnodeeditor.cmake --- CMakeLists.txt | 4 +++- cmake/qnodeeditor.cmake | 31 +++++++++++++++++++++++++++++++ cmake/ssl.cmake | 1 - 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 cmake/qnodeeditor.cmake delete mode 100644 cmake/ssl.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index cc98000d..34d4d125 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ endif() include(cmake/qhttpserver.cmake) include(cmake/translations.cmake) +include(cmake/qnodeeditor.cmake) set(QV2RAY_SOURCES src/base/Qv2rayLog.cpp @@ -81,6 +82,7 @@ set(QRC_RESOURCES ${CMAKE_SOURCE_DIR}/resources.qrc) add_executable(qv2ray ${QV2RAY_SOURCES} ${QHTTPSERVER_SOURCES} + ${QNODEEDITOR_SOURCES} ${QRC_RESOURCES} ) @@ -95,6 +97,7 @@ target_include_directories(qv2ray PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src ${QHTTPSERVER_DIR} + ${QNODEEDITOR_INCLUDE_PATH} ) install(TARGETS qv2ray @@ -117,7 +120,6 @@ if(UNIX AND NOT APPLE) endif() if(UNIX AND NOT WIN32) - install(FILES ${QM_FILES} DESTINATION share ) diff --git a/cmake/qnodeeditor.cmake b/cmake/qnodeeditor.cmake new file mode 100644 index 00000000..cd3ec53d --- /dev/null +++ b/cmake/qnodeeditor.cmake @@ -0,0 +1,31 @@ +set(QNODEEDITOR_DIR ${CMAKE_SOURCE_DIR}3rdparty/QNodeEditor) +add_definitions(-DNODE_EDITOR_SHARED -DNODE_EDITOR_EXPORTS) +set(QNODEEDITOR_SOURCES + ${QNODEEDITOR_DIR}/src/Connection.cpp + ${QNODEEDITOR_DIR}/src/ConnectionBlurEffect.cpp + ${QNODEEDITOR_DIR}/src/ConnectionGeometry.cpp + ${QNODEEDITOR_DIR}/src/ConnectionGraphicsObject.cpp + ${QNODEEDITOR_DIR}/src/ConnectionPainter.cpp + ${QNODEEDITOR_DIR}/src/ConnectionState.cpp + ${QNODEEDITOR_DIR}/src/ConnectionStyle.cpp + ${QNODEEDITOR_DIR}/src/DataModelRegistry.cpp + ${QNODEEDITOR_DIR}/src/FlowScene.cpp + ${QNODEEDITOR_DIR}/src/FlowView.cpp + ${QNODEEDITOR_DIR}/src/FlowViewStyle.cpp + ${QNODEEDITOR_DIR}/src/Node.cpp + ${QNODEEDITOR_DIR}/src/NodeConnectionInteraction.cpp + ${QNODEEDITOR_DIR}/src/NodeDataModel.cpp + ${QNODEEDITOR_DIR}/src/NodeGeometry.cpp + ${QNODEEDITOR_DIR}/src/NodeGraphicsObject.cpp + ${QNODEEDITOR_DIR}/src/NodePainter.cpp + ${QNODEEDITOR_DIR}/src/NodeState.cpp + ${QNODEEDITOR_DIR}/src/NodeStyle.cpp + ${QNODEEDITOR_DIR}/src/Properties.cpp + ${QNODEEDITOR_DIR}/src/StyleCollection.cpp +) +set(QNODEEDITOR_INCLUDE_PATH + ${QNODEEDITOR_DIR}/src/ + ${QNODEEDITOR_DIR}/include/ + ${QNODEEDITOR_DIR}/include/nodes/ + ${QNODEEDITOR_DIR}/include/nodes/internal +) \ No newline at end of file diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake deleted file mode 100644 index 81abd3d8..00000000 --- a/cmake/ssl.cmake +++ /dev/null @@ -1 +0,0 @@ -find_package(OpenSSL REQUIRED) \ No newline at end of file From 8b257038e384fff1a6398d1f44ab983608eec3b5 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 22:03:50 +0800 Subject: [PATCH 125/332] fix typo --- CMakeLists.txt | 1 + cmake/qnodeeditor.cmake | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 34d4d125..0e61574c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,6 +83,7 @@ add_executable(qv2ray ${QV2RAY_SOURCES} ${QHTTPSERVER_SOURCES} ${QNODEEDITOR_SOURCES} + ${QNODEEDITOR_QRC_RESOURCES} ${QRC_RESOURCES} ) diff --git a/cmake/qnodeeditor.cmake b/cmake/qnodeeditor.cmake index cd3ec53d..bc70d99d 100644 --- a/cmake/qnodeeditor.cmake +++ b/cmake/qnodeeditor.cmake @@ -1,4 +1,4 @@ -set(QNODEEDITOR_DIR ${CMAKE_SOURCE_DIR}3rdparty/QNodeEditor) +set(QNODEEDITOR_DIR ${CMAKE_SOURCE_DIR}/3rdparty/QNodeEditor) add_definitions(-DNODE_EDITOR_SHARED -DNODE_EDITOR_EXPORTS) set(QNODEEDITOR_SOURCES ${QNODEEDITOR_DIR}/src/Connection.cpp @@ -28,4 +28,5 @@ set(QNODEEDITOR_INCLUDE_PATH ${QNODEEDITOR_DIR}/include/ ${QNODEEDITOR_DIR}/include/nodes/ ${QNODEEDITOR_DIR}/include/nodes/internal -) \ No newline at end of file +) +set(QNODEEDITOR_QRC_RESOURCES ${QNODEEDITOR_DIR})resources/QNodeEditor_resources.qrc) \ No newline at end of file From eeacc418808213fc83ea356adf1811e54cb812b6 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 22:05:52 +0800 Subject: [PATCH 126/332] fix typo --- cmake/qnodeeditor.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/qnodeeditor.cmake b/cmake/qnodeeditor.cmake index bc70d99d..3eaad787 100644 --- a/cmake/qnodeeditor.cmake +++ b/cmake/qnodeeditor.cmake @@ -29,4 +29,4 @@ set(QNODEEDITOR_INCLUDE_PATH ${QNODEEDITOR_DIR}/include/nodes/ ${QNODEEDITOR_DIR}/include/nodes/internal ) -set(QNODEEDITOR_QRC_RESOURCES ${QNODEEDITOR_DIR})resources/QNodeEditor_resources.qrc) \ No newline at end of file +set(QNODEEDITOR_QRC_RESOURCES ${QNODEEDITOR_DIR}/resources/QNodeEditor_resources.qrc) \ No newline at end of file From b930bc86a38806a67b60603b9dd702717d7d32a7 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 6 Mar 2020 22:15:18 +0800 Subject: [PATCH 127/332] cmake: added new http submodule --- .gitignore | 1 + .gitmodules | 3 +++ 3rdparty/cpp-httplib | 1 + 3rdparty/qhttpserver | 1 - CMakeLists.txt | 6 +++-- cmake/qhttpserver.cmake | 8 ------- src/components/pac/QvPACHandler.cpp | 36 ++++++++++++++--------------- src/components/pac/QvPACHandler.hpp | 14 +++++++---- 8 files changed, 35 insertions(+), 35 deletions(-) create mode 160000 3rdparty/cpp-httplib delete mode 160000 3rdparty/qhttpserver delete mode 100644 cmake/qhttpserver.cmake diff --git a/.gitignore b/.gitignore index 1e23df71..cc60618a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Some files .DS_Store *.pro.user +*.user *.qm ./.vscode diff --git a/.gitmodules b/.gitmodules index 6af22ff2..34515e2f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "libs/libqvb"] path = libs/libqvb url = https://github.com/Qv2ray/QvRPCBridge +[submodule "3rdparty/cpp-httplib"] + path = 3rdparty/cpp-httplib + url = https://github.com/yhirose/cpp-httplib diff --git a/3rdparty/cpp-httplib b/3rdparty/cpp-httplib new file mode 160000 index 00000000..bf7700d1 --- /dev/null +++ b/3rdparty/cpp-httplib @@ -0,0 +1 @@ +Subproject commit bf7700d1924e12a27faa5d346a5b8a9f8e163b61 diff --git a/3rdparty/qhttpserver b/3rdparty/qhttpserver deleted file mode 160000 index 02a6e717..00000000 --- a/3rdparty/qhttpserver +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 02a6e7174b5be76e2c0e74a109817e39a141b9fd diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e61574c..52b2edb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,9 +18,9 @@ if(CMAKE_VERSION VERSION_LESS "3.7.0") set(CMAKE_INCLUDE_CURRENT_DIR ON) endif() -include(cmake/qhttpserver.cmake) include(cmake/translations.cmake) include(cmake/qnodeeditor.cmake) +add_subdirectory(3rdparty/cpp-httplib) set(QV2RAY_SOURCES src/base/Qv2rayLog.cpp @@ -124,4 +124,6 @@ if(UNIX AND NOT WIN32) install(FILES ${QM_FILES} DESTINATION share ) -endif() \ No newline at end of file +endif() + +message(${QM_FILES}) diff --git a/cmake/qhttpserver.cmake b/cmake/qhttpserver.cmake deleted file mode 100644 index fbf246b3..00000000 --- a/cmake/qhttpserver.cmake +++ /dev/null @@ -1,8 +0,0 @@ -set(QHTTPSERVER_DIR "${CMAKE_SOURCE_DIR}/3rdparty/qhttpserver/src") - -set(QHTTPSERVER_SOURCES - ${QHTTPSERVER_DIR}/qhttpconnection.cpp - ${QHTTPSERVER_DIR}/qhttprequest.cpp - ${QHTTPSERVER_DIR}/qhttpresponse.cpp - ${QHTTPSERVER_DIR}/qhttpserver.cpp -) \ No newline at end of file diff --git a/src/components/pac/QvPACHandler.cpp b/src/components/pac/QvPACHandler.cpp index 3e172e95..a6fb90b7 100644 --- a/src/components/pac/QvPACHandler.cpp +++ b/src/components/pac/QvPACHandler.cpp @@ -1,22 +1,21 @@ #include "QvPACHandler.hpp" +#include "3rdparty/cpp-httplib/httplib.h" #include "common/QvHelpers.hpp" #include "core/CoreUtils.hpp" -#include "qhttprequest.h" -#include "qhttpresponse.h" namespace Qv2ray::components::pac { - PACServer::PACServer() : QObject(), pacServer(this) + PACServer::PACServer() : QObject() { - connect(&pacServer, &QHttpServer::newRequest, this, &PACServer::onNewRequest); + pacServer = new httplib::Server(); } PACServer::~PACServer() { if (isStarted) { - pacServer.close(); + delete pacServer; } } void PACServer::SetProxyString(const QString &proxyString) @@ -36,8 +35,7 @@ namespace Qv2ray::components::pac QString gfwContent = StringFromFile(QV2RAY_RULES_GFWLIST_PATH); pacContent = ConvertGFWToPAC(gfwContent, proxyString); // - auto result = pacServer.listen(QHostAddress(address), static_cast(port)); - + auto result = pacServer->listen(address.toStdString().c_str(), static_cast(port)); if (result) { isStarted = true; @@ -54,38 +52,38 @@ namespace Qv2ray::components::pac { if (isStarted) { - pacServer.close(); + pacServer->stop(); DEBUG(MODULE_PROXY, "PAC Handler stopped.") isStarted = false; } } - void PACServer::onNewRequest(QHttpRequest *req, QHttpResponse *rsp) + void PACServer::onNewRequest(const httplib::Request &req, httplib::Response &rsp) { - rsp->setHeader("Server", "Qv2ray/" QV2RAY_VERSION_STRING " PAC_Handler"); - if (req->method() == QHttpRequest::HTTP_GET) + rsp.set_header("Server", ("Qv2ray/" QV2RAY_VERSION_STRING " PAC_Handler").toss); + + if (req.method == "GET") { // - if (req->path() == "/pac") + if (req.path == "/pac") { DEBUG(MODULE_PROXY, "Serving PAC file request.") // - rsp->setHeader("Content-Type", "application/javascript; charset=utf-8"); - rsp->writeHead(QHttpResponse::StatusCode::STATUS_OK); - rsp->end(pacContent.toUtf8()); + rsp.status = 200; + rsp.set_content(pacContent.toStdString(), "application/javascript; charset=utf-8"); DEBUG(MODULE_PROXY, "Serving a pac file...") } else { - rsp->writeHead(QHttpResponse::StatusCode::STATUS_NOT_FOUND); - rsp->end("NOT FOUND"); + rsp.status = 404; + rsp.set_content("NOT FOUND", "text/plain; charset=utf-8"); } } else { - rsp->writeHead(QHttpResponse::StatusCode::STATUS_METHOD_NOT_ALLOWED); - rsp->end("PAC ONLY SUPPORT GET"); + rsp.status = 405; + rsp.set_content("PAC ONLY SUPPORT GET", "text/plain; charset=utf-8"); } } } // namespace Qv2ray::components::pac diff --git a/src/components/pac/QvPACHandler.hpp b/src/components/pac/QvPACHandler.hpp index e739ae30..ea92cd51 100644 --- a/src/components/pac/QvPACHandler.hpp +++ b/src/components/pac/QvPACHandler.hpp @@ -1,9 +1,15 @@ #pragma once -#include "qhttpserver.h" #include #include +namespace httplib +{ + class Server; + class Request; + class Response; +} // namespace httplib + namespace Qv2ray::components::pac { QString ConvertGFWToPAC(const QString &rawContent, const QString &customProxyString); @@ -19,12 +25,10 @@ namespace Qv2ray::components::pac QString gfwFilePath; - public slots: - void onNewRequest(QHttpRequest *request, QHttpResponse *response); - private: + void onNewRequest(const httplib::Request &req, httplib::Response &rsp); bool isStarted; - QHttpServer pacServer; + httplib::Server *pacServer; QString pacContent; QString proxyString; }; From e887b15e38b5cd53fad10eb5d76e3b8026b212b2 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 6 Mar 2020 22:19:51 +0800 Subject: [PATCH 128/332] cmake: do not use icmping on *nix --- src/components/icmping/win/ICMPPinger.cpp | 4 ++++ src/components/icmping/win/ICMPPinger.hpp | 15 +++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/components/icmping/win/ICMPPinger.cpp b/src/components/icmping/win/ICMPPinger.cpp index 2a1de164..287c0cf8 100644 --- a/src/components/icmping/win/ICMPPinger.cpp +++ b/src/components/icmping/win/ICMPPinger.cpp @@ -1,5 +1,7 @@ #include "ICMPPinger.hpp" +#ifdef Q_OS_WIN + ICMPPinger::ICMPPinger(UINT64 timeout = DEFAULT_TIMEOUT) { // create icmp handle @@ -47,3 +49,5 @@ std::pair, std::optional> ICMPPinger::ping(co PICMP_ECHO_REPLY pReply = (PICMP_ECHO_REPLY) bufRecv.get(); return std::pair(pReply->RoundTripTime, std::nullopt); } + +#endif diff --git a/src/components/icmping/win/ICMPPinger.hpp b/src/components/icmping/win/ICMPPinger.hpp index f0bfa39e..b657767e 100644 --- a/src/components/icmping/win/ICMPPinger.hpp +++ b/src/components/icmping/win/ICMPPinger.hpp @@ -1,17 +1,19 @@ #pragma once +#include +#ifdef Q_OS_WIN /** * ICMPPinger - An Implementation of ICMPPing on Windows Platform * Required Windows Version: 2000 / XP / 7 / Vista+ * License: WTFPL */ -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include class ICMPPinger { @@ -29,3 +31,4 @@ class ICMPPinger HANDLE hIcmpFile; UINT64 timeout = DEFAULT_TIMEOUT; }; +#endif From 86ad4a93c8cd603beaf12265e8e63dde441878ae Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 6 Mar 2020 22:39:15 +0800 Subject: [PATCH 129/332] cmake: removed an unused QHTTPSERVER_SOURCES --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 52b2edb1..064fe389 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,6 @@ set(QRC_RESOURCES ${CMAKE_SOURCE_DIR}/resources.qrc) add_executable(qv2ray ${QV2RAY_SOURCES} - ${QHTTPSERVER_SOURCES} ${QNODEEDITOR_SOURCES} ${QNODEEDITOR_QRC_RESOURCES} ${QRC_RESOURCES} From 09151ae55ad77ea64881ca6ae2222ab098f12b2f Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Fri, 6 Mar 2020 22:56:08 +0800 Subject: [PATCH 130/332] adding QV2RAY_VERSION_STRING maybe buggy --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 52b2edb1..cd578386 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,9 @@ cmake_minimum_required(VERSION 3.5.1) file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/VERSION" QV2RAY_VERSION) file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" QV2RAY_BUILD_VERSION) set(PACKAGE_VERSION "${QV2RAY_VERSION}.${QV2RAY_BUILD_VERSION}") + project(Qv2ray) +add_definitions(-DQV2RAY_VERSION_STRING="\\\"v${PACKAGE_VERSION}\\\"") set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) From 851d82a8e6672ca363ef7dcb158400a706b2e893 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 6 Mar 2020 23:00:49 +0800 Subject: [PATCH 131/332] cmake: completed cpp-httplib migration --- src/components/pac/QvPACHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/pac/QvPACHandler.cpp b/src/components/pac/QvPACHandler.cpp index a6fb90b7..8e5c19ad 100644 --- a/src/components/pac/QvPACHandler.cpp +++ b/src/components/pac/QvPACHandler.cpp @@ -61,7 +61,7 @@ namespace Qv2ray::components::pac void PACServer::onNewRequest(const httplib::Request &req, httplib::Response &rsp) { - rsp.set_header("Server", ("Qv2ray/" QV2RAY_VERSION_STRING " PAC_Handler").toss); + rsp.set_header("Server", "Qv2ray/" QV2RAY_VERSION_STRING " PAC_Handler"); if (req.method == "GET") { From d02fe35a7fb258ca5f767c1e34fb86badd99a89e Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 6 Mar 2020 23:20:02 +0800 Subject: [PATCH 132/332] cmake: fixed x2struct with Qt type support --- CMakeLists.txt | 1 + src/base/Qv2rayBase.hpp | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 79f599f0..d53c6f84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ set(PACKAGE_VERSION "${QV2RAY_VERSION}.${QV2RAY_BUILD_VERSION}") project(Qv2ray) add_definitions(-DQV2RAY_VERSION_STRING="\\\"v${PACKAGE_VERSION}\\\"") +add_definitions(-DXTOSTRUCT_QT) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index 84c4ece4..85ad1908 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -1,9 +1,5 @@ #pragma once // -#ifndef XTOSTRUCT_QT - #define XTOSTRUCT_QT -#endif -// #include #include #include @@ -21,9 +17,9 @@ // Code Models #include "base/models/CoreObjectModels.hpp" #include "base/models/QvConfigIdentifier.hpp" -#include "base/models/QvSettingsObject.hpp" #include "base/models/QvRuntimeConfig.hpp" #include "base/models/QvSafeType.hpp" +#include "base/models/QvSettingsObject.hpp" #include "base/models/QvStartupConfig.hpp" using namespace std; From 892ec76d63b242dd294d46596669336eb66d1bac Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 6 Mar 2020 23:27:04 +0800 Subject: [PATCH 133/332] cmake: moved singleapplication.h to a local search scope --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 614e566b..a24d1c8d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,5 @@ -#include "common/CommandArgs.hpp" +#include "3rdparty/SingleApplication/singleapplication.h" +#include "common/CommandArgs.hpp" #include "common/QvHelpers.hpp" #include "common/QvTranslator.hpp" #include "core/handler/ConfigHandler.hpp" @@ -14,7 +15,6 @@ #include #include #include -#include #ifdef Q_OS_UNIX // For unix root user check From 7b79dc59d1bb86054cc91853d30510056a42148e Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Fri, 6 Mar 2020 23:31:06 +0800 Subject: [PATCH 134/332] add singleapplication.cmake --- CMakeLists.txt | 9 +++++---- cmake/singleapplication.cmake | 5 +++++ 2 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 cmake/singleapplication.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index d53c6f84..abff3832 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ endif() include(cmake/translations.cmake) include(cmake/qnodeeditor.cmake) +include(cmake/singleapplication.cmake) add_subdirectory(3rdparty/cpp-httplib) set(QV2RAY_SOURCES @@ -86,6 +87,7 @@ add_executable(qv2ray ${QV2RAY_SOURCES} ${QNODEEDITOR_SOURCES} ${QNODEEDITOR_QRC_RESOURCES} + ${SINGLEAPPLICATION_SOURCES} ${QRC_RESOURCES} ) @@ -101,6 +103,7 @@ target_include_directories(qv2ray PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${QHTTPSERVER_DIR} ${QNODEEDITOR_INCLUDE_PATH} + ${SINGLEAPPLICATION_DIR} ) install(TARGETS qv2ray @@ -124,8 +127,6 @@ endif() if(UNIX AND NOT WIN32) install(FILES ${QM_FILES} - DESTINATION share + DESTINATION share/qv2ray/translations ) -endif() - -message(${QM_FILES}) +endif() \ No newline at end of file diff --git a/cmake/singleapplication.cmake b/cmake/singleapplication.cmake new file mode 100644 index 00000000..08e3cbab --- /dev/null +++ b/cmake/singleapplication.cmake @@ -0,0 +1,5 @@ +set(SINGLEAPPLICATION_DIR ${CMAKE_SOURCE_DIR}/3rdparty/SingleApplication) +set(SINGLEAPPLICATION_SOURCES + ${SINGLEAPPLICATION_DIR}/singleapplication.cpp + ${SINGLEAPPLICATION_DIR}/singleapplication_p.cpp +) \ No newline at end of file From fb70641f04f7b612968fed5d1daddc816c946551 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Fri, 6 Mar 2020 23:33:18 +0800 Subject: [PATCH 135/332] cmake: added singleapplication base class name define --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index abff3832..39cc58d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ endif() include(cmake/translations.cmake) include(cmake/qnodeeditor.cmake) include(cmake/singleapplication.cmake) +add_definitions(-DQAPPLICATION_CLASS=QApplication) add_subdirectory(3rdparty/cpp-httplib) set(QV2RAY_SOURCES @@ -129,4 +130,4 @@ if(UNIX AND NOT WIN32) install(FILES ${QM_FILES} DESTINATION share/qv2ray/translations ) -endif() \ No newline at end of file +endif() From 4455ebc7743b0d7fe15fd4a52c31c3c09353a2bb Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 00:11:30 +0800 Subject: [PATCH 136/332] cmake: added _QV2RAY_BUILD_INFO_ and _QV2RAY_BUILD_EXTRA_INFO_ support --- CMakeLists.txt | 17 +++++++++++++++++ src/ui/widgets/QvAutoCompleteTextEdit.cpp | 20 ++++++++++---------- src/ui/widgets/QvAutoCompleteTextEdit.h | 6 +++--- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 39cc58d4..c0e4b3bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,23 @@ include(cmake/singleapplication.cmake) add_definitions(-DQAPPLICATION_CLASS=QApplication) add_subdirectory(3rdparty/cpp-httplib) +if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) + set(_QV2RAY_BUILD_INFO_STR_ "$ENV{_QV2RAY_BUILD_INFO_}") +else() + set(_QV2RAY_BUILD_INFO_STR_ "Qv2ray from manual build") +endif() + +if(DEFINED ENV{_QV2RAY_BUILD_EXTRA_INFO_}) + set(_QV2RAY_BUILD_EXTRA_INFO_STR_ "$ENV{_QV2RAY_BUILD_EXTRA_INFO_}") +else() + set(_QV2RAY_BUILD_EXTRA_INFO_STR_ "Qv2ray v${PACKAGE_VERSION}") +endif() + +add_definitions(-D_QV2RAY_BUILD_INFO_STR_="\\\"${_QV2RAY_BUILD_INFO_STR_}\\\"") +add_definitions(-D_QV2RAY_BUILD_EXTRA_INFO_STR_="\\\"${_QV2RAY_BUILD_EXTRA_INFO_STR_}\\\"") +message("Qv2ray build info: ${_QV2RAY_BUILD_INFO_STR_}") +message("Qv2ray build info ex: ${_QV2RAY_BUILD_EXTRA_INFO_STR_}") + set(QV2RAY_SOURCES src/base/Qv2rayLog.cpp src/common/CommandArgs.cpp diff --git a/src/ui/widgets/QvAutoCompleteTextEdit.cpp b/src/ui/widgets/QvAutoCompleteTextEdit.cpp index a4b1d2bb..c0c47b1a 100644 --- a/src/ui/widgets/QvAutoCompleteTextEdit.cpp +++ b/src/ui/widgets/QvAutoCompleteTextEdit.cpp @@ -48,7 +48,7 @@ ** ****************************************************************************/ -#include "textedit.h" +#include "QvAutoCompleteTextEdit.h" #include #include @@ -59,18 +59,18 @@ #include #include -TextEdit::TextEdit(QWidget *parent) : QTextEdit(parent) +AutoCompleteTextEdit::AutoCompleteTextEdit(QWidget *parent) : QTextEdit(parent) { setPlainText(tr("This TextEdit provides autocompletions for words that have more than" " 3 characters. You can trigger autocompletion using ") + QKeySequence("Ctrl+E").toString(QKeySequence::NativeText)); } -TextEdit::~TextEdit() +AutoCompleteTextEdit::~AutoCompleteTextEdit() { } -void TextEdit::setCompleter(QCompleter *completer) +void AutoCompleteTextEdit::setCompleter(QCompleter *completer) { if (c) c->disconnect(this); @@ -85,15 +85,15 @@ void TextEdit::setCompleter(QCompleter *completer) c->setWidget(this); c->setCompletionMode(QCompleter::PopupCompletion); c->setCaseSensitivity(Qt::CaseInsensitive); - QObject::connect(c, QOverload::of(&QCompleter::activated), this, &TextEdit::insertCompletion); + QObject::connect(c, QOverload::of(&QCompleter::activated), this, &AutoCompleteTextEdit::insertCompletion); } -QCompleter *TextEdit::completer() const +QCompleter *AutoCompleteTextEdit::completer() const { return c; } -void TextEdit::insertCompletion(const QString &completion) +void AutoCompleteTextEdit::insertCompletion(const QString &completion) { if (c->widget() != this) return; @@ -106,14 +106,14 @@ void TextEdit::insertCompletion(const QString &completion) setTextCursor(tc); } -QString TextEdit::textUnderCursor() const +QString AutoCompleteTextEdit::textUnderCursor() const { QTextCursor tc = textCursor(); tc.select(QTextCursor::WordUnderCursor); return tc.selectedText(); } -void TextEdit::focusInEvent(QFocusEvent *e) +void AutoCompleteTextEdit::focusInEvent(QFocusEvent *e) { if (c) c->setWidget(this); @@ -121,7 +121,7 @@ void TextEdit::focusInEvent(QFocusEvent *e) QTextEdit::focusInEvent(e); } -void TextEdit::keyPressEvent(QKeyEvent *e) +void AutoCompleteTextEdit::keyPressEvent(QKeyEvent *e) { if (c && c->popup()->isVisible()) { diff --git a/src/ui/widgets/QvAutoCompleteTextEdit.h b/src/ui/widgets/QvAutoCompleteTextEdit.h index 847168fd..a9627b72 100644 --- a/src/ui/widgets/QvAutoCompleteTextEdit.h +++ b/src/ui/widgets/QvAutoCompleteTextEdit.h @@ -58,13 +58,13 @@ class QCompleter; QT_END_NAMESPACE //! [0] -class TextEdit : public QTextEdit +class AutoCompleteTextEdit : public QTextEdit { Q_OBJECT public: - TextEdit(QWidget *parent = nullptr); - ~TextEdit(); + AutoCompleteTextEdit(QWidget *parent = nullptr); + ~AutoCompleteTextEdit(); void setCompleter(QCompleter *c); QCompleter *completer() const; From 751193790fbcc846d5f230aca8722e9d374f40e2 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 08:43:22 +0800 Subject: [PATCH 137/332] remove system-observe from plugs --- snap/snapcraft.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 2f682cb7..05ae4e6b 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -40,7 +40,6 @@ apps: - gsettings - network-control - network-manager - - system-observe common-id: com.github.Qv2ray desktop: "usr/share/applications/qv2ray.desktop" From 8de9a38a810740a763415f19a860b900f2c42090 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 09:17:38 +0800 Subject: [PATCH 138/332] add qzxing.cmake --- CMakeLists.txt | 3 ++ cmake/qzxing.cmake | 86 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 cmake/qzxing.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index c0e4b3bf..a48030ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ endif() include(cmake/translations.cmake) include(cmake/qnodeeditor.cmake) include(cmake/singleapplication.cmake) +include(cmake/qzxing.cmake) add_definitions(-DQAPPLICATION_CLASS=QApplication) add_subdirectory(3rdparty/cpp-httplib) @@ -106,6 +107,7 @@ add_executable(qv2ray ${QNODEEDITOR_SOURCES} ${QNODEEDITOR_QRC_RESOURCES} ${SINGLEAPPLICATION_SOURCES} + ${QZXING_SOURCES} ${QRC_RESOURCES} ) @@ -121,6 +123,7 @@ target_include_directories(qv2ray PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${QHTTPSERVER_DIR} ${QNODEEDITOR_INCLUDE_PATH} + ${QZXING_INCLUDE_PATH} ${SINGLEAPPLICATION_DIR} ) diff --git a/cmake/qzxing.cmake b/cmake/qzxing.cmake new file mode 100644 index 00000000..b9a13002 --- /dev/null +++ b/cmake/qzxing.cmake @@ -0,0 +1,86 @@ +add_definitions(-DQZXING_LIBRARY -DZXING_ICONV_CONST -DDISABLE_LIBRARY_FEATURES -DENABLE_DECODER_QR_CODE -DENABLE_ENCODER_QR_CODE -DENABLE_ENCODER_GENERIC) +set(QZXING_DIR ${CMAKE_SOURCE_DIR}/3rdparty/qzxing/src) +set(QZXING_SOURCES + ${QZXING_DIR}/CameraImageWrapper.cpp + ${QZXING_DIR}/QZXing.cpp + ${QZXING_DIR}/ImageHandler.cpp + ${QZXING_DIR}/zxing/zxing/ResultIO.cpp + ${QZXING_DIR}/zxing/zxing/InvertedLuminanceSource.cpp + ${QZXING_DIR}/zxing/zxing/ChecksumException.cpp + ${QZXING_DIR}/zxing/zxing/ResultPointCallback.cpp + ${QZXING_DIR}/zxing/zxing/ResultPoint.cpp + ${QZXING_DIR}/zxing/zxing/Result.cpp + ${QZXING_DIR}/zxing/zxing/ResultMetadata.cpp + ${QZXING_DIR}/zxing/zxing/Reader.cpp + ${QZXING_DIR}/zxing/zxing/MultiFormatReader.cpp + ${QZXING_DIR}/zxing/zxing/LuminanceSource.cpp + ${QZXING_DIR}/zxing/zxing/FormatException.cpp + ${QZXING_DIR}/zxing/zxing/Exception.cpp + ${QZXING_DIR}/zxing/zxing/DecodeHints.cpp + ${QZXING_DIR}/zxing/zxing/BinaryBitmap.cpp + ${QZXING_DIR}/zxing/zxing/Binarizer.cpp + ${QZXING_DIR}/zxing/zxing/BarcodeFormat.cpp + ${QZXING_DIR}/zxing/zxing/ReaderException.cpp + ${QZXING_DIR}/zxing/zxing/IllegalStateException.cpp + ${QZXING_DIR}/zxing/zxing/NotFoundException.cpp + ${QZXING_DIR}/zxing/zxing/WriterException.cpp + ${QZXING_DIR}/zxing/zxing/common/Counted.cpp + ${QZXING_DIR}/zxing/zxing/common/StringUtils.cpp + ${QZXING_DIR}/zxing/zxing/common/Str.cpp + ${QZXING_DIR}/zxing/zxing/common/PerspectiveTransform.cpp + ${QZXING_DIR}/zxing/zxing/common/IllegalArgumentException.cpp + ${QZXING_DIR}/zxing/zxing/common/HybridBinarizer.cpp + ${QZXING_DIR}/zxing/zxing/common/GridSampler.cpp + ${QZXING_DIR}/zxing/zxing/common/GreyscaleRotatedLuminanceSource.cpp + ${QZXING_DIR}/zxing/zxing/common/GreyscaleLuminanceSource.cpp + ${QZXING_DIR}/zxing/zxing/common/GlobalHistogramBinarizer.cpp + ${QZXING_DIR}/zxing/zxing/common/DetectorResult.cpp + ${QZXING_DIR}/zxing/zxing/common/DecoderResult.cpp + ${QZXING_DIR}/zxing/zxing/common/CharacterSetECI.cpp + ${QZXING_DIR}/zxing/zxing/common/BitSource.cpp + ${QZXING_DIR}/zxing/zxing/common/BitMatrix.cpp + ${QZXING_DIR}/zxing/zxing/common/BitArray.cpp + ${QZXING_DIR}/zxing/zxing/common/BitArrayIO.cpp + ${QZXING_DIR}/zxing/zxing/common/detector/WhiteRectangleDetector.cpp + ${QZXING_DIR}/zxing/zxing/common/detector/MonochromeRectangleDetector.cpp + ${QZXING_DIR}/zxing/zxing/common/reedsolomon/ReedSolomonException.cpp + ${QZXING_DIR}/zxing/zxing/common/reedsolomon/ReedSolomonDecoder.cpp + ${QZXING_DIR}/zxing/zxing/common/reedsolomon/GenericGFPoly.cpp + ${QZXING_DIR}/zxing/zxing/common/reedsolomon/GenericGF.cpp + ${QZXING_DIR}/zxing/zxing/multi/MultipleBarcodeReader.cpp + ${QZXING_DIR}/zxing/zxing/multi/GenericMultipleBarcodeReader.cpp + ${QZXING_DIR}/zxing/zxing/multi/ByQuadrantReader.cpp + ${QZXING_DIR}/zxing/bigint/BigUnsignedInABase.cc + ${QZXING_DIR}/zxing/bigint/BigUnsigned.cc + ${QZXING_DIR}/zxing/bigint/BigIntegerUtils.cc + ${QZXING_DIR}/zxing/bigint/BigIntegerAlgorithms.cc + ${QZXING_DIR}/zxing/bigint/BigInteger.cc + ${QZXING_DIR}/zxing/zxing/qrcode/decoder/QRBitMatrixParser.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/decoder/QRDataBlock.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/decoder/QRDataMask.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/decoder/QRDecodedBitStreamParser.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/decoder/QRDecoder.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/detector/QRAlignmentPattern.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/detector/QRAlignmentPatternFinder.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/detector/QRDetector.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/detector/QRFinderPattern.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/detector/QRFinderPatternFinder.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/detector/QRFinderPatternInfo.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/QRCodeReader.cpp + ${QZXING_DIR}/zxing/zxing/multi/qrcode/QRCodeMultiReader.cpp + ${QZXING_DIR}/zxing/zxing/multi/qrcode/detector/MultiFinderPatternFinder.cpp + ${QZXING_DIR}/zxing/zxing/multi/qrcode/detector/MultiDetector.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/encoder/ByteMatrix.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/encoder/QREncoder.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/encoder/MaskUtil.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/encoder/MatrixUtil.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/encoder/QRCode.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/QRVersion.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/QRFormatInformation.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/QRErrorCorrectionLevel.cpp + ${QZXING_DIR}/zxing/zxing/qrcode/decoder/QRMode.cpp + ${QZXING_DIR}/zxing/zxing/EncodeHint.cpp + ${QZXING_DIR}/zxing/zxing/UnsupportedEncodingException.cpp + ${QZXING_DIR}/zxing/zxing/common/reedsolomon/ReedSolomonEncoder.cpp +) +set(QZXING_INCLUDE_PATH ${QZXING_DIR}) \ No newline at end of file From 1c9362ad7d5f057e853a4ca2877f803e37b30868 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 09:27:11 +0800 Subject: [PATCH 139/332] add protobuf.cmake --- CMakeLists.txt | 6 +++++- cmake/protobuf.cmake | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 cmake/protobuf.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index a48030ac..10d14065 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,7 +108,10 @@ add_executable(qv2ray ${QNODEEDITOR_QRC_RESOURCES} ${SINGLEAPPLICATION_SOURCES} ${QZXING_SOURCES} + ${PROTO_SRCS} + ${PROTO_HDRS} ${QRC_RESOURCES} + protobuf::libprotobuf ) target_link_libraries(qv2ray @@ -119,12 +122,13 @@ target_link_libraries(qv2ray ) target_include_directories(qv2ray PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_BINARY_DIR} ${QHTTPSERVER_DIR} ${QNODEEDITOR_INCLUDE_PATH} ${QZXING_INCLUDE_PATH} ${SINGLEAPPLICATION_DIR} + ${Protobuf_INCLUDE_DIRS} ) install(TARGETS qv2ray diff --git a/cmake/protobuf.cmake b/cmake/protobuf.cmake new file mode 100644 index 00000000..7c655b5a --- /dev/null +++ b/cmake/protobuf.cmake @@ -0,0 +1,2 @@ +find_package(Protobuf REQUIRED) +protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${CMAKE_SOURCE_DIR}/tools/v2ray_geosite.proto) \ No newline at end of file From e129d811ce5fd7be5589b2adf9a2fb506c753565 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 09:29:49 +0800 Subject: [PATCH 140/332] link against libprotobuf correctly --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 10d14065..6c224c78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,7 +111,6 @@ add_executable(qv2ray ${PROTO_SRCS} ${PROTO_HDRS} ${QRC_RESOURCES} - protobuf::libprotobuf ) target_link_libraries(qv2ray @@ -119,6 +118,7 @@ target_link_libraries(qv2ray Qt5::Gui Qt5::Widgets Qt5::Network + protobuf::libprotobuf ) target_include_directories(qv2ray PRIVATE From 184db5513611151faeb9c95725fa6acee69bc28f Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 09:32:45 +0800 Subject: [PATCH 141/332] update CMakeLists.txt --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c224c78..2eb8b763 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ include(cmake/translations.cmake) include(cmake/qnodeeditor.cmake) include(cmake/singleapplication.cmake) include(cmake/qzxing.cmake) +include(cmake/protobuf.cmake) add_definitions(-DQAPPLICATION_CLASS=QApplication) add_subdirectory(3rdparty/cpp-httplib) From 5da4e3db5fbf00682ccf328426ddc14095d19f81 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 09:34:39 +0800 Subject: [PATCH 142/332] update CMakeLists.txt --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2eb8b763..099b04e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,6 +123,7 @@ target_link_libraries(qv2ray ) target_include_directories(qv2ray PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_BINARY_DIR} ${QHTTPSERVER_DIR} From 5a0f7258e3e8db92bc1aeb05582b4f2ff9fd7ef0 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 09:39:23 +0800 Subject: [PATCH 143/332] set CMP0071 policy --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 099b04e9..82bee68f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,8 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) +cmake_policy(SET CMP0071 NEW) + if(CMAKE_VERSION VERSION_LESS "3.7.0") set(CMAKE_INCLUDE_CURRENT_DIR ON) endif() From eca7be07edd2b19f4aaaddbf19b90f1f230c1ad9 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 09:43:29 +0800 Subject: [PATCH 144/332] use ninja to build qv2ray --- .github/workflows/build-qv2ray-cmake.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index ec4a4a42..6afa9c5c 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -99,7 +99,7 @@ jobs: cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - cmake .. + cmake .. -GNinja - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Makefile if: matrix.platform == 'ubuntu-16.04' @@ -112,7 +112,7 @@ jobs: cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - cmake .. + cmake .. -GNinja #qmake .. CONFIG+="debug_and_release no_increase_build_number" PREFIX=/usr # -------------------------------------------------------- Build - name: Build Qv2ray From 7e1ffa927ddb400b029e0c24d2bfc57c8d026be5 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 09:46:05 +0800 Subject: [PATCH 145/332] Revert "use ninja to build qv2ray" This reverts commit eca7be07edd2b19f4aaaddbf19b90f1f230c1ad9. --- .github/workflows/build-qv2ray-cmake.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 6afa9c5c..ec4a4a42 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -99,7 +99,7 @@ jobs: cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - cmake .. -GNinja + cmake .. - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Makefile if: matrix.platform == 'ubuntu-16.04' @@ -112,7 +112,7 @@ jobs: cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - cmake .. -GNinja + cmake .. #qmake .. CONFIG+="debug_and_release no_increase_build_number" PREFIX=/usr # -------------------------------------------------------- Build - name: Build Qv2ray From 3e33fc7d13da280c2a8c91f89868f15ad6fb22a4 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 09:50:44 +0800 Subject: [PATCH 146/332] update QvGeositeReader.cpp --- src/components/geosite/QvGeositeReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/geosite/QvGeositeReader.cpp b/src/components/geosite/QvGeositeReader.cpp index 6a6f2f2e..228f723c 100644 --- a/src/components/geosite/QvGeositeReader.cpp +++ b/src/components/geosite/QvGeositeReader.cpp @@ -1,6 +1,6 @@ #include "QvGeositeReader.hpp" -#include "libs/gen/v2ray_geosite.pb.h" +#include namespace Qv2ray::components::geosite { From 2313b2b8f8694e15e3823a3508c51b85752ded61 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 09:58:29 +0800 Subject: [PATCH 147/332] update qzxing.cmake --- cmake/qzxing.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmake/qzxing.cmake b/cmake/qzxing.cmake index b9a13002..921622cf 100644 --- a/cmake/qzxing.cmake +++ b/cmake/qzxing.cmake @@ -83,4 +83,7 @@ set(QZXING_SOURCES ${QZXING_DIR}/zxing/zxing/UnsupportedEncodingException.cpp ${QZXING_DIR}/zxing/zxing/common/reedsolomon/ReedSolomonEncoder.cpp ) -set(QZXING_INCLUDE_PATH ${QZXING_DIR}) \ No newline at end of file +set(QZXING_INCLUDE_PATH + ${QZXING_DIR} + ${QZXING_DIR}/zxing +) \ No newline at end of file From 4bda118110e7ac261278239066debc03355cd5f3 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 11:22:15 +0800 Subject: [PATCH 148/332] update translations.cmake --- cmake/translations.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/translations.cmake b/cmake/translations.cmake index 1423effc..01eaab41 100644 --- a/cmake/translations.cmake +++ b/cmake/translations.cmake @@ -1,3 +1,3 @@ find_package(Qt5 COMPONENTS LinguistTools) set(TRANSLATIONS_DIR ${CMAKE_SOURCE_DIR}/translations) -qt5_create_translation(QM_FILES ${TRANSLATIONS_DIR} en_US.ts ja_JP.ts ru_RU.ts zh_CN.ts) \ No newline at end of file +qt5_create_translation(QM_FILES ${TRANSLATIONS_DIR}/en_US.ts ${TRANSLATIONS_DIR}/ja_JP.ts ${TRANSLATIONS_DIR}/ru_RU.ts ${TRANSLATIONS_DIR}/zh_CN.ts) \ No newline at end of file From 4b1d7142c7e32de172fabccca4aedeba36d8f81d Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 11:40:00 +0800 Subject: [PATCH 149/332] CMakeLists.txt --- CMakeLists.txt | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82bee68f..c413f00d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,13 +116,27 @@ add_executable(qv2ray ${QRC_RESOURCES} ) -target_link_libraries(qv2ray - Qt5::Core - Qt5::Gui - Qt5::Widgets - Qt5::Network - protobuf::libprotobuf -) +if(UNIX AND WIN32 AND NOT APPLE) + target_link_libraries(qv2ray + Qt5::Core + Qt5::Gui + Qt5::Widgets + Qt5::Network + protobuf::libprotobuf + ) +elseif(APPLE) + target_link_libraries(qv2ray + Qt5::Core + Qt5::Gui + Qt5::Widgets + Qt5::Network + protobuf::libprotobuf + -framework Carbon + -framework Cocoa + -framework Security + ) +endif() + target_include_directories(qv2ray PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} From 26bfa4564e5c59b069275352b2b11c7a07934c27 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 11:51:12 +0800 Subject: [PATCH 150/332] fix typo --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c413f00d..23eac1b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,7 +116,7 @@ add_executable(qv2ray ${QRC_RESOURCES} ) -if(UNIX AND WIN32 AND NOT APPLE) +if(UNIX OR WIN32 AND NOT APPLE) target_link_libraries(qv2ray Qt5::Core Qt5::Gui @@ -131,9 +131,9 @@ elseif(APPLE) Qt5::Widgets Qt5::Network protobuf::libprotobuf - -framework Carbon - -framework Cocoa - -framework Security + "-framework Carbon" + "-framework Cocoa" + "-framework Security" ) endif() From ce23e5250a37d453760ff1725dce1073495ab152 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 13:36:53 +0800 Subject: [PATCH 151/332] update --- CMakeLists.txt | 43 +++++++++++++++++------------------ cmake/cpp-httplib.cmake | 1 + cmake/protobuf.cmake | 5 +++- cmake/singleapplication.cmake | 1 + 4 files changed, 27 insertions(+), 23 deletions(-) create mode 100644 cmake/cpp-httplib.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 23eac1b4..48e126c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,8 +28,7 @@ include(cmake/qnodeeditor.cmake) include(cmake/singleapplication.cmake) include(cmake/qzxing.cmake) include(cmake/protobuf.cmake) -add_definitions(-DQAPPLICATION_CLASS=QApplication) -add_subdirectory(3rdparty/cpp-httplib) +include(cmake/cpp-httplib.cmake) if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) set(_QV2RAY_BUILD_INFO_STR_ "$ENV{_QV2RAY_BUILD_INFO_}") @@ -105,6 +104,21 @@ set(QV2RAY_SOURCES set(QRC_RESOURCES ${CMAKE_SOURCE_DIR}/resources.qrc) +set(QT_LIBRARY + Qt5::Core + Qt5::Gui + Qt5::Widgets + Qt5::Network +) + +if(APPLE) + set(MACOSX_FRAMEWORK + "-framework Carbon" + "-framework Cocoa" + "-framework Security" + ) +endif() + add_executable(qv2ray ${QV2RAY_SOURCES} ${QNODEEDITOR_SOURCES} @@ -116,26 +130,11 @@ add_executable(qv2ray ${QRC_RESOURCES} ) -if(UNIX OR WIN32 AND NOT APPLE) - target_link_libraries(qv2ray - Qt5::Core - Qt5::Gui - Qt5::Widgets - Qt5::Network - protobuf::libprotobuf - ) -elseif(APPLE) - target_link_libraries(qv2ray - Qt5::Core - Qt5::Gui - Qt5::Widgets - Qt5::Network - protobuf::libprotobuf - "-framework Carbon" - "-framework Cocoa" - "-framework Security" - ) -endif() +target_link_libraries(qv2ray + ${QT_LIBRARY} + ${MACOSX_FRAMEWORK} + ${QV2RAY_PROTOBUF_LIBRARY} +) target_include_directories(qv2ray PRIVATE diff --git a/cmake/cpp-httplib.cmake b/cmake/cpp-httplib.cmake new file mode 100644 index 00000000..063e89b8 --- /dev/null +++ b/cmake/cpp-httplib.cmake @@ -0,0 +1 @@ +add_subdirectory(3rdparty/cpp-httplib) \ No newline at end of file diff --git a/cmake/protobuf.cmake b/cmake/protobuf.cmake index 7c655b5a..39573bbd 100644 --- a/cmake/protobuf.cmake +++ b/cmake/protobuf.cmake @@ -1,2 +1,5 @@ find_package(Protobuf REQUIRED) -protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${CMAKE_SOURCE_DIR}/tools/v2ray_geosite.proto) \ No newline at end of file +protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${CMAKE_SOURCE_DIR}/tools/v2ray_geosite.proto) +set(QV2RAY_PROTOBUF_LIBRARY + protobuf::libprotobuf +) \ No newline at end of file diff --git a/cmake/singleapplication.cmake b/cmake/singleapplication.cmake index 08e3cbab..1f91b21b 100644 --- a/cmake/singleapplication.cmake +++ b/cmake/singleapplication.cmake @@ -1,3 +1,4 @@ +add_definitions(-DQAPPLICATION_CLASS=QApplication) set(SINGLEAPPLICATION_DIR ${CMAKE_SOURCE_DIR}/3rdparty/SingleApplication) set(SINGLEAPPLICATION_SOURCES ${SINGLEAPPLICATION_DIR}/singleapplication.cpp From 7a359153c7b28dd154f8b0f92f5d0d782d69f7b7 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 14:53:37 +0800 Subject: [PATCH 152/332] cmake: prevent including the cpp file --- src/ui/editors/w_RoutesEditor.cpp | 9 --------- src/ui/editors/w_RoutesEditor.hpp | 7 ++++--- src/ui/editors/w_RoutesEditor_extra.cpp | 10 +++++----- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index 8e91f3a7..2dd42e38 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -1,9 +1,3 @@ -// WARNING -// Since it's required for *extra.cpp to know the content of those macros -// defined below. We include this CPP file instead of the proper HPP file. -// Adding #pragma once to prevent duplicate function instances -#pragma once - #include "w_RoutesEditor.hpp" #include "FlowView.hpp" @@ -38,9 +32,6 @@ static bool isLoading = false; AddNewRule(); \ } -#define GRAPH_GLOBAL_OFFSET_X -80 -#define GRAPH_GLOBAL_OFFSET_Y -10 - #define LOAD_FLAG_BEGIN isLoading = true; #define LOAD_FLAG_END isLoading = false; diff --git a/src/ui/editors/w_RoutesEditor.hpp b/src/ui/editors/w_RoutesEditor.hpp index 5fe867c1..e3a2a22f 100644 --- a/src/ui/editors/w_RoutesEditor.hpp +++ b/src/ui/editors/w_RoutesEditor.hpp @@ -5,6 +5,8 @@ #include "Node.hpp" #include "NodeData.hpp" #include "common/QvHelpers.hpp" +#include "ui/messaging/QvMessageBus.hpp" +#include "ui_w_RoutesEditor.h" #include #include @@ -16,9 +18,8 @@ using QtNodes::ConnectionStyle; using QtNodes::FlowScene; using QtNodes::Node; -#include "ui/messaging/QvMessageBus.hpp" -#include "ui_w_RoutesEditor.h" - +#define GRAPH_GLOBAL_OFFSET_X -80 +#define GRAPH_GLOBAL_OFFSET_Y -10 enum ROUTE_EDIT_MODE { RENAME_INBOUND, diff --git a/src/ui/editors/w_RoutesEditor_extra.cpp b/src/ui/editors/w_RoutesEditor_extra.cpp index c4a1a2fa..1e9ac972 100644 --- a/src/ui/editors/w_RoutesEditor_extra.cpp +++ b/src/ui/editors/w_RoutesEditor_extra.cpp @@ -1,8 +1,8 @@ -// WARNING -// Since it's required for this file to know the content of the macros defined -// in another CPP file. We included an CPP file instead of the proper HPP file. -#include "w_RoutesEditor.cpp" - +#include "core/CoreUtils.hpp" +#include "ui/models/InboundNodeModel.hpp" +#include "ui/models/OutboundNodeModel.hpp" +#include "ui/models/RuleNodeModel.hpp" +#include "w_RoutesEditor.hpp" // Supplementary source file for Routes editor, basically providing // routes-related operations. From 021e7e0a3a3454179a0ad4ee289520ee0988a06d Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 15:18:06 +0800 Subject: [PATCH 153/332] cmake: fixed node editor AUTOMOC generation failure --- cmake/qnodeeditor.cmake | 11 ++++++++++- src/base/Qv2rayFeatures.hpp | 4 ++-- src/components/geosite/QvGeositeReader.cpp | 2 +- src/core/kernel/APIBackend.cpp | 4 ++-- src/core/kernel/APIBackend.hpp | 8 ++++---- src/ui/editors/w_RoutesEditor.cpp | 1 + src/ui/editors/w_RoutesEditor.hpp | 1 - src/ui/editors/w_RoutesEditor_extra.cpp | 1 + 8 files changed, 21 insertions(+), 11 deletions(-) diff --git a/cmake/qnodeeditor.cmake b/cmake/qnodeeditor.cmake index 3eaad787..7324db56 100644 --- a/cmake/qnodeeditor.cmake +++ b/cmake/qnodeeditor.cmake @@ -29,4 +29,13 @@ set(QNODEEDITOR_INCLUDE_PATH ${QNODEEDITOR_DIR}/include/nodes/ ${QNODEEDITOR_DIR}/include/nodes/internal ) -set(QNODEEDITOR_QRC_RESOURCES ${QNODEEDITOR_DIR}/resources/QNodeEditor_resources.qrc) \ No newline at end of file + +file(GLOB_RECURSE HEADERS_TO_MOC ${QNODEEDITOR_DIR}/include/nodes/internal/*.hpp) + +qt5_wrap_cpp(QNODEEDITOR_SOURCES + ${HEADERS_TO_MOC} + TARGET qv2ray + OPTIONS --no-notes # Don't display a note for the headers which don't produce a moc_*.cpp +) + +set(QNODEEDITOR_QRC_RESOURCES ${QNODEEDITOR_DIR}/resources/QNodeEditor_resources.qrc) diff --git a/src/base/Qv2rayFeatures.hpp b/src/base/Qv2rayFeatures.hpp index 9de9ecf7..2425dc43 100644 --- a/src/base/Qv2rayFeatures.hpp +++ b/src/base/Qv2rayFeatures.hpp @@ -2,8 +2,8 @@ // Qv2ray build features. // // Always use libgRPC++ on windows platform. -#ifndef WITH_LIB_GRPCPP +#ifdef BACKEND_LIBQVB #ifdef _WIN32 - #define WITH_LIB_GRPCPP + #error "libQvb is not supported on Windows Platform" #endif #endif diff --git a/src/components/geosite/QvGeositeReader.cpp b/src/components/geosite/QvGeositeReader.cpp index 228f723c..98756943 100644 --- a/src/components/geosite/QvGeositeReader.cpp +++ b/src/components/geosite/QvGeositeReader.cpp @@ -1,6 +1,6 @@ #include "QvGeositeReader.hpp" -#include +#include "v2ray_geosite.pb.h" namespace Qv2ray::components::geosite { diff --git a/src/core/kernel/APIBackend.cpp b/src/core/kernel/APIBackend.cpp index 19c67f57..bea48b1b 100644 --- a/src/core/kernel/APIBackend.cpp +++ b/src/core/kernel/APIBackend.cpp @@ -1,6 +1,6 @@ #include "APIBackend.hpp" -#ifdef WITH_LIB_GRPCPP +#ifndef BACKEND_LIBQVB using namespace v2ray::core::app::stats::command; using grpc::Channel; using grpc::ClientContext; @@ -74,7 +74,7 @@ namespace Qv2ray::core::kernel if (!dialed) { auto channelAddress = "127.0.0.1:" + QString::number(GlobalConfig.apiConfig.statsPort); -#ifdef WITH_LIB_GRPCPP +#ifndef BACKEND_LIBQVB Channel = grpc::CreateChannel(channelAddress.toStdString(), grpc::InsecureChannelCredentials()); StatsService service; Stub = service.NewStub(Channel); diff --git a/src/core/kernel/APIBackend.hpp b/src/core/kernel/APIBackend.hpp index 03e35c9d..eb8239f3 100644 --- a/src/core/kernel/APIBackend.hpp +++ b/src/core/kernel/APIBackend.hpp @@ -1,8 +1,8 @@ #pragma once #include "base/Qv2rayBase.hpp" -#ifdef WITH_LIB_GRPCPP - #include "libs/gen/v2ray_api.grpc.pb.h" - #include "libs/gen/v2ray_api.pb.h" +#ifndef BACKEND_LIBQVB + #include "v2ray_api.pb.h" + #include "v2ray_geosite.pb.h" #include #endif @@ -37,7 +37,7 @@ namespace Qv2ray::core::kernel bool started = false; bool running = false; uint apiFailedCounter = 0; -#ifdef WITH_LIB_GRPCPP +#ifndef BACKEND_LIBQVB std::shared_ptr<::grpc::Channel> Channel; std::unique_ptr<::v2ray::core::app::stats::command::StatsService::Stub> Stub; #endif diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index 2dd42e38..073e9471 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -1,5 +1,6 @@ #include "w_RoutesEditor.hpp" +#include "FlowScene.hpp" #include "FlowView.hpp" #include "FlowViewStyle.hpp" #include "NodeStyle.hpp" diff --git a/src/ui/editors/w_RoutesEditor.hpp b/src/ui/editors/w_RoutesEditor.hpp index e3a2a22f..03826885 100644 --- a/src/ui/editors/w_RoutesEditor.hpp +++ b/src/ui/editors/w_RoutesEditor.hpp @@ -1,7 +1,6 @@ #pragma once #include "ConnectionStyle.hpp" -#include "FlowScene.hpp" #include "Node.hpp" #include "NodeData.hpp" #include "common/QvHelpers.hpp" diff --git a/src/ui/editors/w_RoutesEditor_extra.cpp b/src/ui/editors/w_RoutesEditor_extra.cpp index 1e9ac972..cdbb3b22 100644 --- a/src/ui/editors/w_RoutesEditor_extra.cpp +++ b/src/ui/editors/w_RoutesEditor_extra.cpp @@ -1,3 +1,4 @@ +#include "FlowScene.hpp" #include "core/CoreUtils.hpp" #include "ui/models/InboundNodeModel.hpp" #include "ui/models/OutboundNodeModel.hpp" From 3faf40e2be96014b86ba10f15f4565ce96e82760 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 15:39:02 +0800 Subject: [PATCH 154/332] add backend.cmake --- CMakeLists.txt | 4 ++++ cmake/backend.cmake | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 cmake/backend.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 48e126c0..a4909ca9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ include(cmake/singleapplication.cmake) include(cmake/qzxing.cmake) include(cmake/protobuf.cmake) include(cmake/cpp-httplib.cmake) +include(cmake/backend.cmake) if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) set(_QV2RAY_BUILD_INFO_STR_ "$ENV{_QV2RAY_BUILD_INFO_}") @@ -127,6 +128,8 @@ add_executable(qv2ray ${QZXING_SOURCES} ${PROTO_SRCS} ${PROTO_HDRS} + ${API_GRPC_SRCS} + ${API_GRPC_HDRS} ${QRC_RESOURCES} ) @@ -134,6 +137,7 @@ target_link_libraries(qv2ray ${QT_LIBRARY} ${MACOSX_FRAMEWORK} ${QV2RAY_PROTOBUF_LIBRARY} + ${QV2RAY_BACKEND_LIBRARIES} ) diff --git a/cmake/backend.cmake b/cmake/backend.cmake new file mode 100644 index 00000000..84885381 --- /dev/null +++ b/cmake/backend.cmake @@ -0,0 +1,38 @@ +if(DEFINED USE_GRPC) + add_definitions(-DWITH_LIB_GRPCPP) + find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin) + + find_library(GRPC_LIBRARY NAMES grpc) + find_library(GRPCPP_LIBRARY NAMES grpc++) + + if(UNIX AND NOT APPLE) + set(QV2RAY_BACKEND_LIBRARIES ${GRPCPP_LIBRARY} ${GRPC_LIBRARY}) + elseif(APPLE) + find_library(UPB_LIBRARY NAMES upb) + set(QV2RAY_BACKEND_LIBRARIES ${GRPCPP_LIBRARY} ${GRPC_LIBRARY} ${UPB_LIBRARY}) + elseif(WIN32) + find_library(ABSL_BASE NAMES absl_base) + find_library(ABSL_STR NAMES absl_strings) + find_library(ABSL_THROW_DELEGATE NAMES absl_throw_delegate) + set(QV2RAY_BACKEND_LIBRARIES ${GRPCPP_LIBRARY} ${GRPC_LIBRARY} ${ABSL_BASE} ${ABSL_STR} ${ABSL_THROW_DELEGATE}) + endif() + + set(API_PROTO "${CMAKE_SOURCE_DIR}/tools/v2ray_api.proto") + set(API_GRPC_SRCS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.pb.cc") + set(API_GRPC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.pb.h") + add_custom_command( + OUTPUT "${API_GRPC_SRCS}" "${API_GRPC_HDRS}" + COMMAND ${Protobuf_PROTOC_EXECUTABLE} + ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" + --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" + --plugin=protoc-gen-grpc="${GRPC_CPP_PLUGIN}" + "${API_PROTO}" + DEPENDS "${API_PROTO}") + ) +else() + if(UNIX AND NOT APPLE) + set(QV2RAY_BACKEND_LIBRARIES ${CMAKE_SOURCE_DIR}/libs/libqvb-linux64.a) + elseif(APPLE) + set(QV2RAY_BACKEND_LIBRARIES ${CMAKE_SOURCE_DIR}/libs/libqvb-darwin.a) + endif() +endif() From d27d83ff0ba56a831e8bd8a9d21eda7954e1c0c8 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 15:40:48 +0800 Subject: [PATCH 155/332] update actions --- .github/workflows/build-qv2ray-cmake.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index ec4a4a42..2b3b1701 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -99,7 +99,7 @@ jobs: cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - cmake .. + cmake .. -DUSE_GRPC - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Makefile if: matrix.platform == 'ubuntu-16.04' @@ -112,13 +112,14 @@ jobs: cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - cmake .. + cmake .. -DUSE_GRPC #qmake .. CONFIG+="debug_and_release no_increase_build_number" PREFIX=/usr # -------------------------------------------------------- Build - name: Build Qv2ray + shell: bash run: | cd build - cmake --build . + cmake --build . --parallel $(nproc) # -------------------------------------------------------- Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage if: matrix.platform == 'ubuntu-16.04' From ca8c04e963e103da7d9d633aaddeb0aeb2b9fb0f Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 15:45:57 +0800 Subject: [PATCH 156/332] update --- .github/workflows/build-qv2ray-cmake.yml | 4 ++-- cmake/backend.cmake | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 2b3b1701..6bfcb0dd 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -99,7 +99,7 @@ jobs: cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - cmake .. -DUSE_GRPC + cmake .. -DUSE_GRPC=ON - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Makefile if: matrix.platform == 'ubuntu-16.04' @@ -112,7 +112,7 @@ jobs: cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - cmake .. -DUSE_GRPC + cmake .. -DUSE_GRPC=ON #qmake .. CONFIG+="debug_and_release no_increase_build_number" PREFIX=/usr # -------------------------------------------------------- Build - name: Build Qv2ray diff --git a/cmake/backend.cmake b/cmake/backend.cmake index 84885381..239eb5a0 100644 --- a/cmake/backend.cmake +++ b/cmake/backend.cmake @@ -1,5 +1,4 @@ -if(DEFINED USE_GRPC) - add_definitions(-DWITH_LIB_GRPCPP) +if(USE_GRPC) find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin) find_library(GRPC_LIBRARY NAMES grpc) From c0f173e19bc6f231bb229369a828ff7fcfb59c44 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 15:48:17 +0800 Subject: [PATCH 157/332] fix typo --- cmake/backend.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/backend.cmake b/cmake/backend.cmake index 239eb5a0..0b585f00 100644 --- a/cmake/backend.cmake +++ b/cmake/backend.cmake @@ -26,7 +26,7 @@ if(USE_GRPC) --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" --plugin=protoc-gen-grpc="${GRPC_CPP_PLUGIN}" "${API_PROTO}" - DEPENDS "${API_PROTO}") + DEPENDS "${API_PROTO}" ) else() if(UNIX AND NOT APPLE) From 21f02c578af762eba73edc773d32184cff8a8e26 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 15:56:09 +0800 Subject: [PATCH 158/332] add proto_path --- cmake/backend.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/backend.cmake b/cmake/backend.cmake index 0b585f00..5b1ef792 100644 --- a/cmake/backend.cmake +++ b/cmake/backend.cmake @@ -17,6 +17,7 @@ if(USE_GRPC) endif() set(API_PROTO "${CMAKE_SOURCE_DIR}/tools/v2ray_api.proto") + set(API_PROTO_PATH "${CMAKE_SOURCE_DIR}/tools") set(API_GRPC_SRCS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.pb.cc") set(API_GRPC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.pb.h") add_custom_command( @@ -24,6 +25,7 @@ if(USE_GRPC) COMMAND ${Protobuf_PROTOC_EXECUTABLE} ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" + -I "${API_PROTO_PATH}" --plugin=protoc-gen-grpc="${GRPC_CPP_PLUGIN}" "${API_PROTO}" DEPENDS "${API_PROTO}" From 34d092557d5bebdd681601e2fb38bf4855b10837 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 15:57:36 +0800 Subject: [PATCH 159/332] update action --- .github/workflows/build-qv2ray-cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 6bfcb0dd..8a05edc2 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -70,7 +70,7 @@ jobs: sudo add-apt-repository ppa:webispy/grpc sudo add-apt-repository ppa:carsten-uppenbrink-net/openssl sudo apt update - sudo apt install -y libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler + sudo apt install -y libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler libgrpc++-dev - name: macOS - Install Packages if: matrix.platform == 'macos-latest' From 78e428223cd444fdbe23eee8d5f2298c14dba045 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 15:59:52 +0800 Subject: [PATCH 160/332] update action --- .github/workflows/build-qv2ray-cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 8a05edc2..0a547401 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -70,7 +70,7 @@ jobs: sudo add-apt-repository ppa:webispy/grpc sudo add-apt-repository ppa:carsten-uppenbrink-net/openssl sudo apt update - sudo apt install -y libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler libgrpc++-dev + sudo apt install -y libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler libgrpc++-dev protobuf-compiler-grpc - name: macOS - Install Packages if: matrix.platform == 'macos-latest' From dc8e2a1beaee2da3e2adb4956b26bb88c484baa1 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 16:07:54 +0800 Subject: [PATCH 161/332] using grpc by default --- .github/workflows/build-qv2ray-cmake.yml | 4 ++-- cmake/backend.cmake | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 0a547401..3f144821 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -99,7 +99,7 @@ jobs: cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - cmake .. -DUSE_GRPC=ON + cmake .. - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Makefile if: matrix.platform == 'ubuntu-16.04' @@ -112,7 +112,7 @@ jobs: cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - cmake .. -DUSE_GRPC=ON + cmake .. #qmake .. CONFIG+="debug_and_release no_increase_build_number" PREFIX=/usr # -------------------------------------------------------- Build - name: Build Qv2ray diff --git a/cmake/backend.cmake b/cmake/backend.cmake index 5b1ef792..e34be44a 100644 --- a/cmake/backend.cmake +++ b/cmake/backend.cmake @@ -1,4 +1,4 @@ -if(USE_GRPC) +if(NOT USE_LIBQVB) find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin) find_library(GRPC_LIBRARY NAMES grpc) @@ -31,6 +31,7 @@ if(USE_GRPC) DEPENDS "${API_PROTO}" ) else() + add_definitions(-DBACKEND_LIBQVB) if(UNIX AND NOT APPLE) set(QV2RAY_BACKEND_LIBRARIES ${CMAKE_SOURCE_DIR}/libs/libqvb-linux64.a) elseif(APPLE) From bcd72aaf979516d94436a41aa4ab115370207bfe Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 16:17:07 +0800 Subject: [PATCH 162/332] cmake: fixed a missing gRPC header --- src/core/kernel/APIBackend.cpp | 2 +- src/core/kernel/APIBackend.hpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/kernel/APIBackend.cpp b/src/core/kernel/APIBackend.cpp index bea48b1b..3c202a60 100644 --- a/src/core/kernel/APIBackend.cpp +++ b/src/core/kernel/APIBackend.cpp @@ -156,7 +156,7 @@ namespace Qv2ray::core::kernel return 0; } -#ifdef WITH_LIB_GRPCPP +#ifndef BACKEND_LIBQVB GetStatsRequest request; request.set_name(name.toStdString()); request.set_reset(true); diff --git a/src/core/kernel/APIBackend.hpp b/src/core/kernel/APIBackend.hpp index eb8239f3..fe9787b7 100644 --- a/src/core/kernel/APIBackend.hpp +++ b/src/core/kernel/APIBackend.hpp @@ -1,6 +1,7 @@ #pragma once #include "base/Qv2rayBase.hpp" #ifndef BACKEND_LIBQVB + #include "v2ray_api.grpc.pb.h" #include "v2ray_api.pb.h" #include "v2ray_geosite.pb.h" From 1b2318eff7ee7ee4be0ec60604dac9a1998ef4ea Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 16:50:45 +0800 Subject: [PATCH 163/332] add missing sources --- CMakeLists.txt | 2 +- cmake/backend.cmake | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a4909ca9..031152a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,7 +129,7 @@ add_executable(qv2ray ${PROTO_SRCS} ${PROTO_HDRS} ${API_GRPC_SRCS} - ${API_GRPC_HDRS} + ${API_PROTO_SRCS} ${QRC_RESOURCES} ) diff --git a/cmake/backend.cmake b/cmake/backend.cmake index e34be44a..d710b4fe 100644 --- a/cmake/backend.cmake +++ b/cmake/backend.cmake @@ -18,10 +18,12 @@ if(NOT USE_LIBQVB) set(API_PROTO "${CMAKE_SOURCE_DIR}/tools/v2ray_api.proto") set(API_PROTO_PATH "${CMAKE_SOURCE_DIR}/tools") - set(API_GRPC_SRCS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.pb.cc") - set(API_GRPC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.pb.h") + set(API_PROTO_SRCS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.pb.cc") + set(API_PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.pb.h") + set(API_GRPC_SRCS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.grpc.pb.cc") + set(API_GRPC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.grpc.pb.h") add_custom_command( - OUTPUT "${API_GRPC_SRCS}" "${API_GRPC_HDRS}" + OUTPUT "${API_GRPC_SRCS}" "${API_GRPC_HDRS}" "${API_PROTO_HDRS}" "${API_PROTO_SRCS}" COMMAND ${Protobuf_PROTOC_EXECUTABLE} ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" From b33f302a81ed539262465b03f93890da56827e87 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 17:06:36 +0800 Subject: [PATCH 164/332] cmake: fixed missing translation files --- CMakeLists.txt | 1 + cmake/translations.cmake | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 031152a2..a224ee25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,6 +131,7 @@ add_executable(qv2ray ${API_GRPC_SRCS} ${API_PROTO_SRCS} ${QRC_RESOURCES} + ${QM_FILES} ) target_link_libraries(qv2ray diff --git a/cmake/translations.cmake b/cmake/translations.cmake index 01eaab41..b7942211 100644 --- a/cmake/translations.cmake +++ b/cmake/translations.cmake @@ -1,3 +1,3 @@ find_package(Qt5 COMPONENTS LinguistTools) set(TRANSLATIONS_DIR ${CMAKE_SOURCE_DIR}/translations) -qt5_create_translation(QM_FILES ${TRANSLATIONS_DIR}/en_US.ts ${TRANSLATIONS_DIR}/ja_JP.ts ${TRANSLATIONS_DIR}/ru_RU.ts ${TRANSLATIONS_DIR}/zh_CN.ts) \ No newline at end of file +qt5_create_translation(QM_FILES ${TRANSLATIONS_DIR}/en_US.ts ${TRANSLATIONS_DIR}/ja_JP.ts ${TRANSLATIONS_DIR}/ru_RU.ts ${TRANSLATIONS_DIR}/zh_CN.ts) From 4656e7fa29068f2c288f80a6c682c9106e42900a Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 17:12:33 +0800 Subject: [PATCH 165/332] cmake: auto find translation files --- cmake/translations.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/translations.cmake b/cmake/translations.cmake index b7942211..ba1ab118 100644 --- a/cmake/translations.cmake +++ b/cmake/translations.cmake @@ -1,3 +1,4 @@ find_package(Qt5 COMPONENTS LinguistTools) set(TRANSLATIONS_DIR ${CMAKE_SOURCE_DIR}/translations) -qt5_create_translation(QM_FILES ${TRANSLATIONS_DIR}/en_US.ts ${TRANSLATIONS_DIR}/ja_JP.ts ${TRANSLATIONS_DIR}/ru_RU.ts ${TRANSLATIONS_DIR}/zh_CN.ts) +file(GLOB TRANSLATIONS_TS ${TRANSLATIONS_DIR}/**.ts) +qt5_create_translation(QM_FILES ${TRANSLATIONS_TS}) From 5666fb0ca57b45ec39113ad1dceb0b761c2fd50e Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 17:22:19 +0800 Subject: [PATCH 166/332] cmake: prevent installing httplib headers --- CMakeLists.txt | 1 + cmake/cpp-httplib.cmake | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a224ee25..4230e6c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,6 +151,7 @@ target_include_directories(qv2ray PRIVATE ${QZXING_INCLUDE_PATH} ${SINGLEAPPLICATION_DIR} ${Protobuf_INCLUDE_DIRS} + ${cpp-httplib_INCLUDE_DIRS} ) install(TARGETS qv2ray diff --git a/cmake/cpp-httplib.cmake b/cmake/cpp-httplib.cmake index 063e89b8..e09fe015 100644 --- a/cmake/cpp-httplib.cmake +++ b/cmake/cpp-httplib.cmake @@ -1 +1 @@ -add_subdirectory(3rdparty/cpp-httplib) \ No newline at end of file +set(cpp-httplib_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/3rdparty/cpp-httplib) From 6d4233290d2fa0bed4d2fd556fd7e28c27bda0df Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sat, 7 Mar 2020 17:36:40 +0800 Subject: [PATCH 167/332] fixing version string viva la cmake! --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4230e6c9..5201365b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" QV2RAY_BUILD_VERSION) set(PACKAGE_VERSION "${QV2RAY_VERSION}.${QV2RAY_BUILD_VERSION}") project(Qv2ray) -add_definitions(-DQV2RAY_VERSION_STRING="\\\"v${PACKAGE_VERSION}\\\"") +add_definitions(-DQV2RAY_VERSION_STRING="v${PACKAGE_VERSION}") add_definitions(-DXTOSTRUCT_QT) set(CMAKE_CXX_STANDARD 17) @@ -43,8 +43,8 @@ else() set(_QV2RAY_BUILD_EXTRA_INFO_STR_ "Qv2ray v${PACKAGE_VERSION}") endif() -add_definitions(-D_QV2RAY_BUILD_INFO_STR_="\\\"${_QV2RAY_BUILD_INFO_STR_}\\\"") -add_definitions(-D_QV2RAY_BUILD_EXTRA_INFO_STR_="\\\"${_QV2RAY_BUILD_EXTRA_INFO_STR_}\\\"") +add_definitions(-D_QV2RAY_BUILD_INFO_STR_="${_QV2RAY_BUILD_INFO_STR_}") +add_definitions(-D_QV2RAY_BUILD_EXTRA_INFO_STR_="${_QV2RAY_BUILD_EXTRA_INFO_STR_}") message("Qv2ray build info: ${_QV2RAY_BUILD_INFO_STR_}") message("Qv2ray build info ex: ${_QV2RAY_BUILD_EXTRA_INFO_STR_}") From d970d113c1940a3f8f678a66456c0310d9a37275 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 17:47:26 +0800 Subject: [PATCH 168/332] add libiconv for macos --- CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5201365b..5fad4afe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,11 +113,18 @@ set(QT_LIBRARY ) if(APPLE) + find_package(Iconv REQUIRED) set(MACOSX_FRAMEWORK "-framework Carbon" "-framework Cocoa" "-framework Security" ) + set(MACOSX_ICONV_LIBRARY + Iconv::Iconv + ) + set(MACOSX_ICONV_INCLUDE_PATH + ${Iconv_INCLUDE_DIR} + ) endif() add_executable(qv2ray @@ -137,6 +144,7 @@ add_executable(qv2ray target_link_libraries(qv2ray ${QT_LIBRARY} ${MACOSX_FRAMEWORK} + ${MACOSX_ICONV_LIBRARY} ${QV2RAY_PROTOBUF_LIBRARY} ${QV2RAY_BACKEND_LIBRARIES} ) @@ -151,6 +159,7 @@ target_include_directories(qv2ray PRIVATE ${QZXING_INCLUDE_PATH} ${SINGLEAPPLICATION_DIR} ${Protobuf_INCLUDE_DIRS} + ${MACOSX_ICONV_INCLUDE_PATH} ${cpp-httplib_INCLUDE_DIRS} ) From 35f9a8ee5709da36721e72f32fbabbcdb9d06bf4 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 18:15:56 +0800 Subject: [PATCH 169/332] add ts files correctly --- cmake/translations.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/translations.cmake b/cmake/translations.cmake index ba1ab118..7be26088 100644 --- a/cmake/translations.cmake +++ b/cmake/translations.cmake @@ -1,4 +1,4 @@ find_package(Qt5 COMPONENTS LinguistTools) set(TRANSLATIONS_DIR ${CMAKE_SOURCE_DIR}/translations) file(GLOB TRANSLATIONS_TS ${TRANSLATIONS_DIR}/**.ts) -qt5_create_translation(QM_FILES ${TRANSLATIONS_TS}) +qt5_add_translation(QM_FILES ${TRANSLATIONS_TS}) From ffaca123068ba52579895633dbbcbe199b9cbb89 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 19:35:04 +0800 Subject: [PATCH 170/332] update qnodeeditor.cmake --- cmake/qnodeeditor.cmake | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/cmake/qnodeeditor.cmake b/cmake/qnodeeditor.cmake index 7324db56..1563ee0c 100644 --- a/cmake/qnodeeditor.cmake +++ b/cmake/qnodeeditor.cmake @@ -30,7 +30,35 @@ set(QNODEEDITOR_INCLUDE_PATH ${QNODEEDITOR_DIR}/include/nodes/internal ) -file(GLOB_RECURSE HEADERS_TO_MOC ${QNODEEDITOR_DIR}/include/nodes/internal/*.hpp) +set(HEADERS_TO_MOC + ${QNODEEDITOR_DIR}/include/nodes/internal/Compiler.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/Connection.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/ConnectionGeometry.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/ConnectionGraphicsObject.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/ConnectionState.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/ConnectionStyle.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/DataModelRegistry.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/Export.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/FlowScene.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/FlowView.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/FlowViewStyle.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/memory.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/Node.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/NodeData.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/NodeDataModel.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/NodeGeometry.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/NodeGraphicsObject.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/NodePainterDelegate.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/NodeState.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/NodeStyle.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/OperatingSystem.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/PortType.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/QStringStdHash.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/QUuidStdHash.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/Serializable.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/Style.hpp + ${QNODEEDITOR_DIR}/include/nodes/internal/TypeConverter.hpp +) qt5_wrap_cpp(QNODEEDITOR_SOURCES ${HEADERS_TO_MOC} From 021cacd496ee15474643eeca564efa0af0254188 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 20:37:35 +0800 Subject: [PATCH 171/332] cmake: enable cmake packaing on macOS - 1 --- CMakeLists.txt | 50 +++++++------ cmake/macdeploy.cmake | 59 +++++++++++++++ macOS.patch | 163 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 249 insertions(+), 23 deletions(-) create mode 100644 cmake/macdeploy.cmake create mode 100644 macOS.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fad4afe..c727c289 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/VERSION" QV2RAY_VERSION) file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" QV2RAY_BUILD_VERSION) set(PACKAGE_VERSION "${QV2RAY_VERSION}.${QV2RAY_BUILD_VERSION}") -project(Qv2ray) +project(qv2ray) add_definitions(-DQV2RAY_VERSION_STRING="v${PACKAGE_VERSION}") add_definitions(-DXTOSTRUCT_QT) @@ -30,6 +30,21 @@ include(cmake/qzxing.cmake) include(cmake/protobuf.cmake) include(cmake/cpp-httplib.cmake) include(cmake/backend.cmake) +if(APPLE) + find_package(Iconv REQUIRED) + set(MACOSX_FRAMEWORK + "-framework Carbon" + "-framework Cocoa" + "-framework Security" + ) + set(MACOSX_ICONV_LIBRARY + Iconv::Iconv + ) + + set(MACOSX_ICONV_INCLUDE_PATH + ${Iconv_INCLUDE_DIR} + ) +endif() if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) set(_QV2RAY_BUILD_INFO_STR_ "$ENV{_QV2RAY_BUILD_INFO_}") @@ -112,22 +127,7 @@ set(QT_LIBRARY Qt5::Network ) -if(APPLE) - find_package(Iconv REQUIRED) - set(MACOSX_FRAMEWORK - "-framework Carbon" - "-framework Cocoa" - "-framework Security" - ) - set(MACOSX_ICONV_LIBRARY - Iconv::Iconv - ) - set(MACOSX_ICONV_INCLUDE_PATH - ${Iconv_INCLUDE_DIR} - ) -endif() - -add_executable(qv2ray +add_executable(${PROJECT_NAME} ${QV2RAY_SOURCES} ${QNODEEDITOR_SOURCES} ${QNODEEDITOR_QRC_RESOURCES} @@ -141,7 +141,7 @@ add_executable(qv2ray ${QM_FILES} ) -target_link_libraries(qv2ray +target_link_libraries(${PROJECT_NAME} ${QT_LIBRARY} ${MACOSX_FRAMEWORK} ${MACOSX_ICONV_LIBRARY} @@ -150,7 +150,7 @@ target_link_libraries(qv2ray ) -target_include_directories(qv2ray PRIVATE +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_BINARY_DIR} @@ -163,12 +163,16 @@ target_include_directories(qv2ray PRIVATE ${cpp-httplib_INCLUDE_DIRS} ) -install(TARGETS qv2ray - RUNTIME - DESTINATION bin -) +if(APPLE) + set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) + include(cmake/macdeploy.cmake) +endif() if(UNIX AND NOT APPLE) + install(TARGETS ${PROJECT_NAME} + RUNTIME + DESTINATION bin + ) install(FILES assets/qv2ray.metainfo.xml DESTINATION share/metainfo ) diff --git a/cmake/macdeploy.cmake b/cmake/macdeploy.cmake new file mode 100644 index 00000000..605215d5 --- /dev/null +++ b/cmake/macdeploy.cmake @@ -0,0 +1,59 @@ +set(prefix "${PROJECT_NAME}.app/Contents") +set(INSTALL_RUNTIME_DIR "${prefix}/MacOS") +set(INSTALL_CMAKE_DIR "${prefix}/Resources") + +# based on code from CMake's QtDialog/CMakeLists.txt +macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var _prefix) + get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION) + if(EXISTS "${_qt_plugin_path}") + get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME) + get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH) + get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME) + set(_qt_plugin_dest "${_prefix}/PlugIns/${_qt_plugin_type}") + install(FILES "${_qt_plugin_path}" + DESTINATION "${_qt_plugin_dest}") + set(${_qt_plugins_var} + "${${_qt_plugins_var}};\$ENV{DEST_DIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}") + else() + message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found") + endif() +endmacro() + +install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS ${prefix}) +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + "[Paths]\nPlugins = ${_qt_plugin_dir}\n") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + DESTINATION "${INSTALL_CMAKE_DIR}") + +# Destination paths below are relative to ${CMAKE_INSTALL_PREFIX} +install(TARGETS ${PROJECT_NAME} + BUNDLE DESTINATION . COMPONENT Runtime + RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} COMPONENT Runtime + ) + +# Note Mac specific extension .app +set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.app") + +# Directories to look for dependencies +set(DIRS "${CMAKE_BINARY_DIR}") + +# Path used for searching by FIND_XXX(), with appropriate suffixes added +if(CMAKE_PREFIX_PATH) + foreach(dir ${CMAKE_PREFIX_PATH}) + list(APPEND DIRS "${dir}/bin" "${dir}/lib") + endforeach() +endif() + +# Append Qt's lib folder which is two levels above Qt5Widgets_DIR +list(APPEND DIRS "${Qt5Widgets_DIR}/../..") +list(APPEND DIRS "/usr/local/lib") +list(APPEND DIRS "/usr/lib") + +include(InstallRequiredSystemLibraries) + +message(STATUS "APPS: ${APPS}") +message(STATUS "QT_PLUGINS: ${QT_PLUGINS}") +message(STATUS "DIRS: ${DIRS}") + +install(CODE "include(BundleUtilities) + fixup_bundle(\"${APPS}\" \"${QT_PLUGINS}\" \"${DIRS}\")") diff --git a/macOS.patch b/macOS.patch new file mode 100644 index 00000000..448e91b5 --- /dev/null +++ b/macOS.patch @@ -0,0 +1,163 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 5fad4af..c727c28 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -4,7 +4,7 @@ file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/VERSION" QV2RAY_VERSION) + file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" QV2RAY_BUILD_VERSION) + set(PACKAGE_VERSION "${QV2RAY_VERSION}.${QV2RAY_BUILD_VERSION}") + +-project(Qv2ray) ++project(qv2ray) + add_definitions(-DQV2RAY_VERSION_STRING="v${PACKAGE_VERSION}") + add_definitions(-DXTOSTRUCT_QT) + +@@ -30,6 +30,21 @@ include(cmake/qzxing.cmake) + include(cmake/protobuf.cmake) + include(cmake/cpp-httplib.cmake) + include(cmake/backend.cmake) ++if(APPLE) ++ find_package(Iconv REQUIRED) ++ set(MACOSX_FRAMEWORK ++ "-framework Carbon" ++ "-framework Cocoa" ++ "-framework Security" ++ ) ++ set(MACOSX_ICONV_LIBRARY ++ Iconv::Iconv ++ ) ++ ++ set(MACOSX_ICONV_INCLUDE_PATH ++ ${Iconv_INCLUDE_DIR} ++ ) ++endif() + + if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) + set(_QV2RAY_BUILD_INFO_STR_ "$ENV{_QV2RAY_BUILD_INFO_}") +@@ -112,22 +127,7 @@ set(QT_LIBRARY + Qt5::Network + ) + +-if(APPLE) +- find_package(Iconv REQUIRED) +- set(MACOSX_FRAMEWORK +- "-framework Carbon" +- "-framework Cocoa" +- "-framework Security" +- ) +- set(MACOSX_ICONV_LIBRARY +- Iconv::Iconv +- ) +- set(MACOSX_ICONV_INCLUDE_PATH +- ${Iconv_INCLUDE_DIR} +- ) +-endif() +- +-add_executable(qv2ray ++add_executable(${PROJECT_NAME} + ${QV2RAY_SOURCES} + ${QNODEEDITOR_SOURCES} + ${QNODEEDITOR_QRC_RESOURCES} +@@ -141,7 +141,7 @@ add_executable(qv2ray + ${QM_FILES} + ) + +-target_link_libraries(qv2ray ++target_link_libraries(${PROJECT_NAME} + ${QT_LIBRARY} + ${MACOSX_FRAMEWORK} + ${MACOSX_ICONV_LIBRARY} +@@ -150,7 +150,7 @@ target_link_libraries(qv2ray + ) + + +-target_include_directories(qv2ray PRIVATE ++target_include_directories(${PROJECT_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_BINARY_DIR} +@@ -163,12 +163,16 @@ target_include_directories(qv2ray PRIVATE + ${cpp-httplib_INCLUDE_DIRS} + ) + +-install(TARGETS qv2ray +- RUNTIME +- DESTINATION bin +-) ++if(APPLE) ++ set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) ++ include(cmake/macdeploy.cmake) ++endif() + + if(UNIX AND NOT APPLE) ++ install(TARGETS ${PROJECT_NAME} ++ RUNTIME ++ DESTINATION bin ++ ) + install(FILES assets/qv2ray.metainfo.xml + DESTINATION share/metainfo + ) +diff --git a/cmake/macdeploy.cmake b/cmake/macdeploy.cmake +new file mode 100644 +index 0000000..605215d +--- /dev/null ++++ b/cmake/macdeploy.cmake +@@ -0,0 +1,59 @@ ++set(prefix "${PROJECT_NAME}.app/Contents") ++set(INSTALL_RUNTIME_DIR "${prefix}/MacOS") ++set(INSTALL_CMAKE_DIR "${prefix}/Resources") ++ ++# based on code from CMake's QtDialog/CMakeLists.txt ++macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var _prefix) ++ get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION) ++ if(EXISTS "${_qt_plugin_path}") ++ get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME) ++ get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH) ++ get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME) ++ set(_qt_plugin_dest "${_prefix}/PlugIns/${_qt_plugin_type}") ++ install(FILES "${_qt_plugin_path}" ++ DESTINATION "${_qt_plugin_dest}") ++ set(${_qt_plugins_var} ++ "${${_qt_plugins_var}};\$ENV{DEST_DIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}") ++ else() ++ message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found") ++ endif() ++endmacro() ++ ++install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS ${prefix}) ++file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" ++ "[Paths]\nPlugins = ${_qt_plugin_dir}\n") ++install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" ++ DESTINATION "${INSTALL_CMAKE_DIR}") ++ ++# Destination paths below are relative to ${CMAKE_INSTALL_PREFIX} ++install(TARGETS ${PROJECT_NAME} ++ BUNDLE DESTINATION . COMPONENT Runtime ++ RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} COMPONENT Runtime ++ ) ++ ++# Note Mac specific extension .app ++set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.app") ++ ++# Directories to look for dependencies ++set(DIRS "${CMAKE_BINARY_DIR}") ++ ++# Path used for searching by FIND_XXX(), with appropriate suffixes added ++if(CMAKE_PREFIX_PATH) ++ foreach(dir ${CMAKE_PREFIX_PATH}) ++ list(APPEND DIRS "${dir}/bin" "${dir}/lib") ++ endforeach() ++endif() ++ ++# Append Qt's lib folder which is two levels above Qt5Widgets_DIR ++list(APPEND DIRS "${Qt5Widgets_DIR}/../..") ++list(APPEND DIRS "/usr/local/lib") ++list(APPEND DIRS "/usr/lib") ++ ++include(InstallRequiredSystemLibraries) ++ ++message(STATUS "APPS: ${APPS}") ++message(STATUS "QT_PLUGINS: ${QT_PLUGINS}") ++message(STATUS "DIRS: ${DIRS}") ++ ++install(CODE "include(BundleUtilities) ++ fixup_bundle(\"${APPS}\" \"${QT_PLUGINS}\" \"${DIRS}\")") From f9376146f0cfd50c2c036b73c824b2489513458c Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 20:42:14 +0800 Subject: [PATCH 172/332] update qnodeeditor.cmake --- cmake/qnodeeditor.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/qnodeeditor.cmake b/cmake/qnodeeditor.cmake index 7324db56..1ba5624a 100644 --- a/cmake/qnodeeditor.cmake +++ b/cmake/qnodeeditor.cmake @@ -30,7 +30,7 @@ set(QNODEEDITOR_INCLUDE_PATH ${QNODEEDITOR_DIR}/include/nodes/internal ) -file(GLOB_RECURSE HEADERS_TO_MOC ${QNODEEDITOR_DIR}/include/nodes/internal/*.hpp) +file(GLOB_RECURSE HEADERS_TO_MOC include/nodes/internal/*.hpp) qt5_wrap_cpp(QNODEEDITOR_SOURCES ${HEADERS_TO_MOC} From ce9a4ec35c3404a090a9ce1564a8b4679cf73496 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 20:47:34 +0800 Subject: [PATCH 173/332] Revert "update qnodeeditor.cmake" This reverts commit f9376146f0cfd50c2c036b73c824b2489513458c. --- cmake/qnodeeditor.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/qnodeeditor.cmake b/cmake/qnodeeditor.cmake index 1ba5624a..7324db56 100644 --- a/cmake/qnodeeditor.cmake +++ b/cmake/qnodeeditor.cmake @@ -30,7 +30,7 @@ set(QNODEEDITOR_INCLUDE_PATH ${QNODEEDITOR_DIR}/include/nodes/internal ) -file(GLOB_RECURSE HEADERS_TO_MOC include/nodes/internal/*.hpp) +file(GLOB_RECURSE HEADERS_TO_MOC ${QNODEEDITOR_DIR}/include/nodes/internal/*.hpp) qt5_wrap_cpp(QNODEEDITOR_SOURCES ${HEADERS_TO_MOC} From f2f860b7742cec7a52616fb1cdf14f87ef2b7e02 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 21:01:54 +0800 Subject: [PATCH 174/332] cmake: fixing GitHub Action - 1 --- .github/workflows/build-qv2ray-cmake.yml | 9 ++------ assets/info.plist | 26 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 assets/info.plist diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 3f144821..330222a7 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -112,14 +112,13 @@ jobs: cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - cmake .. -#qmake .. CONFIG+="debug_and_release no_increase_build_number" PREFIX=/usr + cmake .. -DCMAKE_INSTALL_PREFIX=./AppDir # -------------------------------------------------------- Build - name: Build Qv2ray shell: bash run: | cd build - cmake --build . --parallel $(nproc) + cmake --install . --parallel $(nproc) # -------------------------------------------------------- Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage if: matrix.platform == 'ubuntu-16.04' @@ -128,7 +127,6 @@ jobs: wget https://github.com/probonopd/linuxdeployqt/releases/download/6/linuxdeployqt-6-x86_64.AppImage chmod +x ./linuxdeployqt-6-x86_64.AppImage ./linuxdeployqt-6-x86_64.AppImage --appimage-extract - make install INSTALL_ROOT=AppDir cd AppDir wget -c https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/AppRun-patched-x86_64 -O AppRun chmod a+x AppRun @@ -161,9 +159,6 @@ jobs: if: matrix.platform == 'macos-latest' run: | cd build - cd qv2ray.app - macdeployqt ./ - cd .. tar czf Qv2ray.app.tar.gz qv2ray.app - name: macOS - ${{ matrix.qt_version }} - Uploading Artifact if: matrix.platform == 'macos-latest' diff --git a/assets/info.plist b/assets/info.plist new file mode 100644 index 00000000..5e488614 --- /dev/null +++ b/assets/info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleExecutable + qv2ray + CFBundleGetInfoString + Created by Qv2ray development team + CFBundleIconFile + qv2ray.icns + CFBundleIdentifier + com.qv2ray.qv2ray + CFBundlePackageType + APPL + CFBundleSignature + ???? + LSMinimumSystemVersion + 10.12 + NOTE + Qv2ray + NSPrincipalClass + NSApplication + NSSupportsAutomaticGraphicsSwitching + + + From 8ba96d166c5b7f005492df4b60c36576a1257894 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 21:04:56 +0800 Subject: [PATCH 175/332] cmake: fixing GitHub Action - 2 --- .github/workflows/build-qv2ray-cmake.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 330222a7..044259b9 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -118,7 +118,8 @@ jobs: shell: bash run: | cd build - cmake --install . --parallel $(nproc) + cmake --build . --parallel $(nproc) + cmake --install . # -------------------------------------------------------- Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage if: matrix.platform == 'ubuntu-16.04' From 6cb66bca867998ce507fadc1a47d12f2e2865247 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 21:05:35 +0800 Subject: [PATCH 176/332] cmake: fixing GitHub Action - 3 --- .github/workflows/build-qv2ray-cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 044259b9..97633bee 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -112,7 +112,7 @@ jobs: cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - cmake .. -DCMAKE_INSTALL_PREFIX=./AppDir + cmake .. -DCMAKE_INSTALL_PREFIX=./AppDir/usr # -------------------------------------------------------- Build - name: Build Qv2ray shell: bash From 34d66b010db54ada7e44e54fd57335e006dae060 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 21:17:00 +0800 Subject: [PATCH 177/332] cmake: fixing GitHub Action - 4 --- .github/workflows/build-qv2ray-cmake.yml | 2 +- CMakeLists.txt | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 97633bee..c947ea89 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -70,7 +70,7 @@ jobs: sudo add-apt-repository ppa:webispy/grpc sudo add-apt-repository ppa:carsten-uppenbrink-net/openssl sudo apt update - sudo apt install -y libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler libgrpc++-dev protobuf-compiler-grpc + sudo apt install -y libgl-dev openssl libx11-dev libxkbcommon-x11-dev libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler libgrpc++-dev protobuf-compiler-grpc - name: macOS - Install Packages if: matrix.platform == 'macos-latest' diff --git a/CMakeLists.txt b/CMakeLists.txt index c727c289..a0917bb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,22 @@ if(CMAKE_VERSION VERSION_LESS "3.7.0") set(CMAKE_INCLUDE_CURRENT_DIR ON) endif() +message(" ") +message("Qv2ray Version: v${PACKAGE_VERSION}") +message("|-------------------------------------------------|") +message("| Qv2ray, A Cross Platform v2ray Qt GUI Client. |") +message("| Licenced under GPLv3 |") +message("| |") +message("| You may only use this program to the extent |") +message("| permitted by local law. |") +message("| |") +message("| See: https://www.gnu.org/licenses/gpl-3.0.html |") +message("|-------------------------------------------------|") +message("| Project Homepage: https://github.com/Qv2ray |") +message("| Welcome to contribute! |") +message("|-------------------------------------------------|") +message(" ") + include(cmake/translations.cmake) include(cmake/qnodeeditor.cmake) include(cmake/singleapplication.cmake) From 5ac17d2b9b9a65638a668e8876cebde2b7b7cab8 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 21:27:53 +0800 Subject: [PATCH 178/332] cmake: fixing GitHub Action - 5 --- .github/workflows/build-qv2ray-cmake.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index c947ea89..9e4e0af0 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -119,6 +119,9 @@ jobs: run: | cd build cmake --build . --parallel $(nproc) + mkdir ./qv2ray.app + mkdir ./qv2ray.app/Contents + cp ../assets/info.plist ./qv2ray.app/Contents cmake --install . # -------------------------------------------------------- Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage From 5a77b76cf711e6edfe5895c1ce8682600f6a1eec Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 21:36:21 +0800 Subject: [PATCH 179/332] cmake: fixing GitHub Action - 6 --- .github/workflows/build-qv2ray-cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 9e4e0af0..11f57fcf 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -122,7 +122,7 @@ jobs: mkdir ./qv2ray.app mkdir ./qv2ray.app/Contents cp ../assets/info.plist ./qv2ray.app/Contents - cmake --install . + sudo cmake --install . # -------------------------------------------------------- Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage if: matrix.platform == 'ubuntu-16.04' From 14f8e1c7fe1daea9a6b14eb03c8be153dac59fad Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 21:40:56 +0800 Subject: [PATCH 180/332] cmake: remove qmake Action --- .github/workflows/build-qv2ray.yml | 211 ----------------------------- 1 file changed, 211 deletions(-) delete mode 100644 .github/workflows/build-qv2ray.yml diff --git a/.github/workflows/build-qv2ray.yml b/.github/workflows/build-qv2ray.yml deleted file mode 100644 index 825bd790..00000000 --- a/.github/workflows/build-qv2ray.yml +++ /dev/null @@ -1,211 +0,0 @@ -name: Qv2ray build matrix - -on: - push: - release: - types: [prereleased] - -jobs: - build: - strategy: - matrix: - qt_version: [5.13.2, 5.14.1] - platform: [ubuntu-16.04, macos-latest, windows-latest] - arch: [x86, x64] - include: - - platform: windows-latest - arch: x86 - qtarch: win32_msvc2017 - - platform: windows-latest - arch: x64 - qtarch: win64_msvc2017_64 - exclude: - - platform: ubuntu-16.04 - arch: x86 - - platform: macos-latest - arch: x86 - fail-fast: false - - runs-on: ${{ matrix.platform }} - - steps: - - name: Get the version - id: get_version - shell: bash - run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3) - - name: Checking out sources - uses: actions/checkout@master - - name: Install Python 3.7 version - uses: actions/setup-python@v1 - with: - python-version: '3.7' - architecture: ${{ matrix.arch }} - - name: Restoring submodules - run: git submodule update --init -# -------------------------------------------------------- - - name: Install MSVC compiler - if: matrix.platform == 'windows-latest' - uses: ilammy/msvc-dev-cmd@v1 - with: - # 14.1 is for vs2017, 14.2 is vs2019, following the upstream vcpkg build from Qv2ray-deps repo - toolset: 14.2 - arch: ${{ matrix.arch }} - - name: Cache Qt - id: cache-qt - uses: actions/cache@v1 - with: - path: ../Qt - key: QtCache-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.qt_version }} - - name: Installing Qt - ${{ matrix.arch }} - uses: jurplel/install-qt-action@v2.5.0 - with: - version: ${{ matrix.qt_version }} - arch: ${{ matrix.qtarch }} - mirror: 'http://mirrors.ocf.berkeley.edu/qt/' - cached: ${{ steps.cache-qt.outputs.cache-hit }} -# -------------------------------------------------------- - - name: Linux - Install Packages - if: matrix.platform == 'ubuntu-16.04' - run: | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test - sudo add-apt-repository ppa:webispy/grpc - sudo add-apt-repository ppa:carsten-uppenbrink-net/openssl - sudo apt update - sudo apt install -y gcc-7 libgl-dev openssl libx11-dev libxkbcommon-x11-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler - - - name: macOS - Install Packages - if: matrix.platform == 'macos-latest' - run: | - brew install protobuf - brew install grpc - - - name: Windows - Install Packages - if: matrix.platform == 'windows-latest' - run: choco install jom -y -# -------------------------------------------------------- - - name: Cross-platform - Download libraries - shell: bash - run: | - curl -o ./libs/libqvb-linux64.a -L https://github.com/Qv2ray/QvRPCBridge/releases/download/v1.1/libqvb-linux64.a - curl -o ./libs/libqvb-darwin.a -L https://github.com/Qv2ray/QvRPCBridge/releases/download/v1.1/libqvb-darwin.a - curl -o ./libs/Qv2ray-deps-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-${{ matrix.arch }}-windows.7z - - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Extract Windows Dependencies - if: matrix.platform == 'windows-latest' - uses: DuckSoft/extract-7z-action@v1.0 - with: - pathSource: ./libs/Qv2ray-deps-${{ matrix.arch }}-windows.7z - pathTarget: ./libs -# -------------------------------------------------------- Generate MakeFile - - name: Cross-platform - ${{ matrix.qt_version }} - Generate Dependencies and Makefile - shell: bash - run: | - mkdir build - cd build - export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" - export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - qmake .. CONFIG+="debug_and_release no_increase_build_number" PREFIX=/usr -# -------------------------------------------------------- Build - - name: Unix - ${{ matrix.qt_version }} - Build Qv2ray - if: matrix.platform != 'windows-latest' - run: | - cd build - make -j2 release $([ "${{ matrix.platform }}" == "ubuntu-16.04" ] && echo "CC=gcc-7 CXX=g++-7" LINK="g++-7" || echo "") - - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Build Qv2ray - if: matrix.platform == 'windows-latest' - run: | - cd build - jom -# -------------------------------------------------------- Deployments - - name: Linux - ${{ matrix.qt_version }} - Generating AppImage - if: matrix.platform == 'ubuntu-16.04' - run: | - cd build - wget https://github.com/probonopd/linuxdeployqt/releases/download/6/linuxdeployqt-6-x86_64.AppImage - chmod +x ./linuxdeployqt-6-x86_64.AppImage - ./linuxdeployqt-6-x86_64.AppImage --appimage-extract - make install INSTALL_ROOT=AppDir - cd AppDir - wget -c https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/AppRun-patched-x86_64 -O AppRun - chmod a+x AppRun - mkdir -p ./usr/{lib,optional}/ - wget -c https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/exec-x86_64.so -O ./usr/optional/exec.so - mkdir -p ./usr/optional/libstdc++/ - cp -fv /usr/lib/x86_64-linux-gnu/libstdc++.so.6 ./usr/optional/libstdc++/ - mkdir -p ./usr/optional/libgcc_s/ - cp -fv /lib/x86_64-linux-gnu/libgcc_s.so.1 ./usr/optional/libgcc_s/ - cp -fv /usr/lib/x86_64-linux-gnu/{libssl.so.1.1,libcrypto.so.1.1} ./usr/lib/ - ../squashfs-root/AppRun usr/share/applications/qv2ray.desktop -appimage -no-strip -always-overwrite - mv ./Qv2ray*.AppImage ./Qv2ray.AppImage - - name: Linux - ${{ matrix.qt_version }} - Uploading artifact - if: matrix.platform == 'ubuntu-16.04' - uses: actions/upload-artifact@master - with: - name: Qv2ray-${{ github.sha }}.linux-${{ matrix.arch }}.qt${{ matrix.qt_version }}.AppImage - path: build/AppDir/Qv2ray.AppImage - - name: Linux - ${{ matrix.qt_version }} - Upload binaries to release - uses: svenstaro/upload-release-action@v1-release - if: github.event_name == 'release' && matrix.platform == 'ubuntu-16.04' && matrix.qt_version == '5.14.1' - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: build/AppDir/Qv2ray.AppImage - asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.linux-${{ matrix.arch }}.AppImage - tag: ${{ github.ref }} - overwrite: true -# == - - name: macOS - ${{ matrix.qt_version }} - Making release tarball - if: matrix.platform == 'macos-latest' - run: | - cd build - cd qv2ray.app - macdeployqt ./ - cd .. - tar czf Qv2ray.app.tar.gz qv2ray.app - - name: macOS - ${{ matrix.qt_version }} - Uploading Artifact - if: matrix.platform == 'macos-latest' - uses: actions/upload-artifact@master - with: - name: Qv2ray-${{ github.sha }}.macOS-${{ matrix.arch }}.qt${{ matrix.qt_version }}.zip - path: build/Qv2ray.app.tar.gz - - name: macOS - ${{ matrix.qt_version }} - Upload binaries to release - uses: svenstaro/upload-release-action@v1-release - if: github.event_name == 'release' && matrix.platform == 'macos-latest' && matrix.qt_version == '5.14.1' - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: build/Qv2ray.app.tar.gz - asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.macOS-${{ matrix.arch }}.tar.gz - tag: ${{ github.ref }} - overwrite: true -# == - - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Copying DLLs to build output folders - if: matrix.platform == 'windows-latest' - run: .\.github\workflows\copy_DLLs.bat - - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Running windeployqt - if: matrix.platform == 'windows-latest' - shell: cmd - run: | - cd build - cd release - del *.cpp *.h *.o *.qrc *.qm *.hpp *.obj - set VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\ - windeployqt ./qv2ray.exe --compiler-runtime --verbose 2 - - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Create 7z Release - if: matrix.platform == 'windows-latest' - uses: DuckSoft/create-7z-action@v1.0 - with: - pathSource: ./build/release/ - pathTarget: ./release.7z - - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Uploading artifact - if: matrix.platform == 'windows-latest' - uses: actions/upload-artifact@master - with: - name: Qv2ray-${{ github.sha }}.Windows-${{ matrix.arch }}.qt${{ matrix.qt_version }}.7z - path: release.7z - - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Upload binaries to release - uses: svenstaro/upload-release-action@v1-release - if: github.event_name == 'release' && matrix.platform == 'windows-latest' && matrix.qt_version == '5.14.1' - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: release.7z - asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.Windows-${{ matrix.arch }}.7z - tag: ${{ github.ref }} - overwrite: true From 8d99a0f240014139d66db0e84bef69fc50d25460 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sat, 7 Mar 2020 21:11:51 +0800 Subject: [PATCH 181/332] [wip] refactored QvTranslator --- src/common/QvTranslator.hpp | 108 ++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 4 deletions(-) diff --git a/src/common/QvTranslator.hpp b/src/common/QvTranslator.hpp index d632d55b..58cf7028 100644 --- a/src/common/QvTranslator.hpp +++ b/src/common/QvTranslator.hpp @@ -1,5 +1,9 @@ #pragma once +#include +#include +#include #include +#include #include #include @@ -8,14 +12,110 @@ namespace Qv2ray::common class QvTranslator { public: - QvTranslator(const QString &lang) + QvTranslator() { - QTranslator *translator = new QTranslator(); - translator->load(lang + ".qm", ":/translations/"); - this->pTranslator.reset(translator); + this->reloadTranslationDirs(); } + public: + static std::optional deduceTranslationDir(); + std::optional getAvailableLanguages(); + void reloadTranslation(const QString &); + inline bool isTranslationAvailable() + { + return this->translationDir.has_value(); + }; + inline void reloadTranslationDirs() + { + this->translationDir = this->deduceTranslationDir(); + }; + + private: + static bool testTranslationDir(const QString &); + public: std::unique_ptr pTranslator; + std::optional translationDir; }; + + /** + * @brief get the available languages. + * @return (if available) languages (zh_CN, en_US, ...) + */ + std::optional QvTranslator::getAvailableLanguages() + { + if (!this->translationDir) + return std::nullopt; + + auto languages = QDir(this->translationDir.value()).entryList(QStringList{ "*.qm" }, QDir::Hidden | QDir::Files); + + if (languages.empty()) + return std::nullopt; + + std::transform(languages.begin(), languages.end(), languages.begin(), [](QString &fileName) { return fileName.replace(".qm", ""); }); + + return languages; + } + + /** + * @brief reload the translation from file + * @param code eg: en_US, zh_CN, ... + */ + void QvTranslator::reloadTranslation(const QString &code) + { + if (!translationDir) + return; + + QTranslator *translatorNew = new QTranslator(); + translatorNew->load(code + ".qm", this->translationDir.value()); + + this->pTranslator.reset(translatorNew); + } + + /** + * @brief search and deduce a directory for translation file + * @return (if any) the deduced path + * + * @author DuckSoft + * @todo add some debug output + */ + std::optional QvTranslator::deduceTranslationDir() + { + // path searching list. + auto searchPaths = { // 1st: application dir + QApplication::applicationDirPath() + "/translations", +#ifdef QV2RAY_TRANSLATION_PATH + // 2nd: platform-specific dir + QString(QV2RAY_TRANSLATION_PATH), +#endif + // 3rd: standard path dirs + QStandardPaths::locate(QStandardPaths::DataLocation, "translations", QStandardPaths::LocateDirectory) + }; + + // iterate through the paths + for (auto path : searchPaths) + { + if (QvTranslator::testTranslationDir(path)) + { + return path; + } + } + + // sadly, none match + return std::nullopt; + } + + /** + * @brief test the translation directory + * @param targetDir the directory to judge + * @return if the translation directory seems good to use + */ + bool QvTranslator::testTranslationDir(const QString &targetDir) + { + const auto translations = QDir(targetDir).entryList(QStringList{ "*.qm" }, QDir::Hidden | QDir::Files); + + /// @todo: add some debug traces + + return !translations.empty(); + } } // namespace Qv2ray::common From 310307513bc03d25ef24e5af614b201ab1317915 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sat, 7 Mar 2020 21:40:19 +0800 Subject: [PATCH 182/332] [wip] first draft --- src/base/GlobalInstances.hpp | 7 +++--- src/main.cpp | 43 ++++++++++++++-------------------- src/ui/w_PreferencesWindow.cpp | 33 ++++++++++---------------- 3 files changed, 34 insertions(+), 49 deletions(-) diff --git a/src/base/GlobalInstances.hpp b/src/base/GlobalInstances.hpp index 3b719f74..7d71b429 100644 --- a/src/base/GlobalInstances.hpp +++ b/src/base/GlobalInstances.hpp @@ -1,10 +1,9 @@ #pragma once -#include "base/models/QvSettingsObject.hpp" #include "base/models/QvRuntimeConfig.hpp" +#include "base/models/QvSettingsObject.hpp" #include "base/models/QvStartupConfig.hpp" - -#include +#include "common/QvTranslator.hpp" // Instantiation for Qv2ray global objects. @@ -17,5 +16,5 @@ namespace Qv2ray inline base::config::Qv2rayConfig GlobalConfig = base::config::Qv2rayConfig(); inline base::QvStartupOptions StartupOption = base::QvStartupOptions(); // - inline std::unique_ptr Qv2rayTranslator; + inline std::unique_ptr Qv2rayTranslator; } // namespace Qv2ray diff --git a/src/main.cpp b/src/main.cpp index a24d1c8d..d19a5fba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -257,7 +257,9 @@ int main(int argc, char *argv[]) std::unique_ptr consoleApp(new QCoreApplication(argc, argv)); // // Install a default translater. From the OS/DE - consoleApp->installTranslator(QvTranslator(QLocale::system().name()).pTranslator.get()); + Qv2rayTranslator.reset(std::move(new QvTranslator())); + Qv2rayTranslator->reloadTranslation(QLocale::system().name()); + consoleApp->installTranslator(Qv2rayTranslator->pTranslator.get()); QvCommandArgParser parser; QString errorMessage; @@ -318,10 +320,10 @@ int main(int argc, char *argv[]) // Not duplicated. // Install a default translater. From the OS/DE auto _lang = QLocale::system().name(); - Qv2rayTranslator = std::move(QvTranslator(_lang).pTranslator); - // + Qv2rayTranslator.reset(std::move(new QvTranslator())); + Qv2rayTranslator->reloadTranslation(_lang); // Do not install en-US as it's the default language. - bool _result_ = _qApp.installTranslator(Qv2rayTranslator.get()); + bool _result_ = _qApp.installTranslator(Qv2rayTranslator->pTranslator.get()); LOG(MODULE_UI, "Installing a tranlator from OS: " + _lang + " -- " + (_result_ ? "OK" : "Failed")) // LOG("LICENCE", NEWLINE @@ -347,21 +349,15 @@ int main(int argc, char *argv[]) #endif // // Load the language translation list. - auto langs = GetFileList(QDir(":/translations")); + // auto translationDir = Qv - if (langs.empty()) - { - LOG(MODULE_INIT, "FAILED to find any translations. THIS IS A BUILD ERROR.") - QvMessageBoxWarn(nullptr, QObject::tr("Cannot load languages"), - QObject::tr("Qv2ray will continue running, but you cannot change the UI language.")); - } - else - { - for (auto lang : langs) - { - LOG(MODULE_INIT, "Found Translator: " + lang) - } - } + // auto translationDir = QvTranslator::deduceTranslationDir(); + // if (!translationDir) + // { + // LOG(MODULE_INIT, "FAILED to find any translations. THIS IS A BUILD ERROR.") + // QvMessageBoxWarn(nullptr, QObject::tr("Cannot load languages"), + // QObject::tr("Qv2ray will continue running, but you cannot change the UI language.")); + // } // Qv2ray Initialize, find possible config paths and verify them. if (!initialiseQv2ray()) @@ -394,7 +390,7 @@ int main(int argc, char *argv[]) // Load config object from upgraded config QJsonObject auto confObject = StructFromJsonString(JsonToString(conf)); // Remove system translator, for loading custom translations. - qApp->removeTranslator(Qv2rayTranslator.get()); + qApp->removeTranslator(Qv2rayTranslator->pTranslator.get()); LOG(MODULE_INIT, "Removed system translations") if (confObject.uiConfig.language.isEmpty()) @@ -404,16 +400,13 @@ int main(int argc, char *argv[]) confObject.uiConfig.language = "en-US"; } - Qv2rayTranslator = std::move(QvTranslator(confObject.uiConfig.language).pTranslator); - - if (qApp->installTranslator(Qv2rayTranslator.get())) + Qv2rayTranslator->reloadTranslation(confObject.uiConfig.language); + if (qApp->installTranslator(Qv2rayTranslator->pTranslator.get())) { - LOG(MODULE_INIT, "Successfully installed a translator for " + confObject.uiConfig.language) + LOG(MODULE_INIT, "Successfully installed a translator for " + confObject.uiConfig.language); } else { - // Do not translate these..... - // If a translator fails to load, pop up a message. QvMessageBoxWarn(nullptr, "Translation Failed", "Cannot load translation for " + confObject.uiConfig.language + ", English is now used." + NEWLINE + NEWLINE + "Please go to Preferences Window to change language or open an Issue"); diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index 8151db47..fe4a064e 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -41,12 +41,14 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), Current } // We add locales - languageComboBox->clear(); - QDirIterator it(":/translations"); - - while (it.hasNext()) + if (auto langs = Qv2rayTranslator->getAvailableLanguages(); langs) { - languageComboBox->addItem(it.next().split("/").last().split(".").first()); + languageComboBox->clear(); + languageComboBox->addItems(langs.value()); + } + else + { + languageComboBox->setDisabled(true); } // Set auto start button state @@ -166,17 +168,11 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), Current auto autoStartConnId = ConnectionId(CurrentConfig.autoStartId); auto autoStartGroupId = GetConnectionGroupId(autoStartConnId); - for (auto group : ConnectionManager->AllGroups()) - { - autoStartSubsCombo->addItem(GetDisplayName(group)); - } + for (auto group : ConnectionManager->AllGroups()) { autoStartSubsCombo->addItem(GetDisplayName(group)); } autoStartSubsCombo->setCurrentText(GetDisplayName(autoStartGroupId)); - for (auto conn : ConnectionManager->Connections(autoStartGroupId)) - { - autoStartConnCombo->addItem(GetDisplayName(conn)); - } + for (auto conn : ConnectionManager->Connections(autoStartGroupId)) { autoStartConnCombo->addItem(GetDisplayName(conn)); } autoStartConnCombo->setCurrentText(GetDisplayName(autoStartConnId)); @@ -262,11 +258,11 @@ void PreferencesWindow::on_buttonBox_accepted() { if (CurrentConfig.uiConfig.language != GlobalConfig.uiConfig.language) { - qApp->removeTranslator(Qv2rayTranslator.get()); - Qv2rayTranslator = std::move(QvTranslator(CurrentConfig.uiConfig.language).pTranslator); + qApp->removeTranslator(Qv2rayTranslator->pTranslator.get()); + Qv2rayTranslator->reloadTranslation(CurrentConfig.uiConfig.language); // Install translator - if (!qApp->installTranslator(Qv2rayTranslator.get())) + if (!qApp->installTranslator(Qv2rayTranslator->pTranslator.get())) { LOG(MODULE_UI, "Failed to translate UI to: " + CurrentConfig.uiConfig.language) } @@ -1029,10 +1025,7 @@ void PreferencesWindow::on_autoStartSubsCombo_currentIndexChanged(const QString auto list = ConnectionManager->Connections(groupId); autoStartConnCombo->clear(); - for (auto id : list) - { - autoStartConnCombo->addItem(GetDisplayName(id)); - } + for (auto id : list) { autoStartConnCombo->addItem(GetDisplayName(id)); } } } From e00e743dc9aa17009c3a0c58f82f5ea7de3b6eb0 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 22:10:46 +0800 Subject: [PATCH 183/332] cmake: translations: some minor improvements --- CMakeLists.txt | 1 + src/common/QvTranslator.cpp | 79 ++++++++++++++++++++++++++ src/common/QvTranslator.hpp | 109 ++++++++---------------------------- 3 files changed, 102 insertions(+), 87 deletions(-) create mode 100644 src/common/QvTranslator.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a0917bb3..4683308e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,7 @@ set(QV2RAY_SOURCES src/common/LogHighlighter.cpp src/common/QJsonModel.cpp src/common/QvHelpers.cpp + src/common/QvTranslator.cpp src/components/autolaunch/QvAutoLaunch.cpp src/components/geosite/QvGeositeReader.cpp src/components/icmping/win/ICMPPinger.cpp diff --git a/src/common/QvTranslator.cpp b/src/common/QvTranslator.cpp new file mode 100644 index 00000000..de8b11ee --- /dev/null +++ b/src/common/QvTranslator.cpp @@ -0,0 +1,79 @@ +#include "QvTranslator.hpp" + +#include "base/Qv2rayLog.hpp" + +#include +#include +#include +#include +#include +#include +#include + +using namespace Qv2ray::base; + +namespace Qv2ray::common +{ + std::optional QvTranslator::getAvailableLanguages() + { + if (!this->translationDir) + return std::nullopt; + + auto languages = QDir(this->translationDir.value()).entryList(QStringList{ "*.qm" }, QDir::Hidden | QDir::Files); + + if (languages.empty()) + return std::nullopt; + + std::transform(languages.begin(), languages.end(), languages.begin(), [](QString &fileName) { return fileName.replace(".qm", ""); }); + LOG(MODULE_UI, "Found translations: " + languages.join(" ")) + return languages; + } + + void QvTranslator::reloadTranslation(const QString &code) + { + if (!translationDir) + return; + + QTranslator *translatorNew = new QTranslator(); + translatorNew->load(code + ".qm", this->translationDir.value()); + + this->pTranslator.reset(translatorNew); + } + + std::optional QvTranslator::deduceTranslationDir() + { + // path searching list. + QStringList searchPaths = { + // 1st: application dir + QApplication::applicationDirPath() + "/translations", +#ifdef QV2RAY_TRANSLATION_PATH + // 2nd: platform-specific dir + QString(QV2RAY_TRANSLATION_PATH), +#endif + }; + // 3rd: standard path dirs + searchPaths << QStandardPaths::locateAll(QStandardPaths::DataLocation, "translations", QStandardPaths::LocateDirectory); + // + // iterate through the paths + for (auto path : searchPaths) + { + DEBUG(MODULE_UI, "Testing for translation path: " + path) + if (QvTranslator::testTranslationDir(path)) + { + return path; + } + } + + // sadly, none match + return std::nullopt; + } + + bool QvTranslator::testTranslationDir(const QString &targetDir) + { + const auto translations = QDir(targetDir).entryList(QStringList{ "*.qm" }, QDir::Hidden | QDir::Files); + + /// @todo: add some debug traces + + return !translations.empty(); + } +} // namespace Qv2ray::common diff --git a/src/common/QvTranslator.hpp b/src/common/QvTranslator.hpp index 58cf7028..f5f1dfbe 100644 --- a/src/common/QvTranslator.hpp +++ b/src/common/QvTranslator.hpp @@ -1,9 +1,5 @@ #pragma once -#include -#include -#include #include -#include #include #include @@ -12,16 +8,31 @@ namespace Qv2ray::common class QvTranslator { public: - QvTranslator() + explicit QvTranslator() { this->reloadTranslationDirs(); } public: + /** + * @brief search and deduce a directory for translation file + * @return (if any) the deduced path + * + * @author DuckSoft + * @todo add some debug output + */ static std::optional deduceTranslationDir(); + /** + * @brief get the available languages. + * @return (if available) languages (zh_CN, en_US, ...) + */ std::optional getAvailableLanguages(); + /** + * @brief reload the translation from file + * @param code eg: en_US, zh_CN, ... + */ void reloadTranslation(const QString &); - inline bool isTranslationAvailable() + inline bool isTranslationAvailable() const { return this->translationDir.has_value(); }; @@ -31,91 +42,15 @@ namespace Qv2ray::common }; private: + /** + * @brief test the translation directory + * @param targetDir the directory to judge + * @return if the translation directory seems good to use + */ static bool testTranslationDir(const QString &); public: std::unique_ptr pTranslator; std::optional translationDir; }; - - /** - * @brief get the available languages. - * @return (if available) languages (zh_CN, en_US, ...) - */ - std::optional QvTranslator::getAvailableLanguages() - { - if (!this->translationDir) - return std::nullopt; - - auto languages = QDir(this->translationDir.value()).entryList(QStringList{ "*.qm" }, QDir::Hidden | QDir::Files); - - if (languages.empty()) - return std::nullopt; - - std::transform(languages.begin(), languages.end(), languages.begin(), [](QString &fileName) { return fileName.replace(".qm", ""); }); - - return languages; - } - - /** - * @brief reload the translation from file - * @param code eg: en_US, zh_CN, ... - */ - void QvTranslator::reloadTranslation(const QString &code) - { - if (!translationDir) - return; - - QTranslator *translatorNew = new QTranslator(); - translatorNew->load(code + ".qm", this->translationDir.value()); - - this->pTranslator.reset(translatorNew); - } - - /** - * @brief search and deduce a directory for translation file - * @return (if any) the deduced path - * - * @author DuckSoft - * @todo add some debug output - */ - std::optional QvTranslator::deduceTranslationDir() - { - // path searching list. - auto searchPaths = { // 1st: application dir - QApplication::applicationDirPath() + "/translations", -#ifdef QV2RAY_TRANSLATION_PATH - // 2nd: platform-specific dir - QString(QV2RAY_TRANSLATION_PATH), -#endif - // 3rd: standard path dirs - QStandardPaths::locate(QStandardPaths::DataLocation, "translations", QStandardPaths::LocateDirectory) - }; - - // iterate through the paths - for (auto path : searchPaths) - { - if (QvTranslator::testTranslationDir(path)) - { - return path; - } - } - - // sadly, none match - return std::nullopt; - } - - /** - * @brief test the translation directory - * @param targetDir the directory to judge - * @return if the translation directory seems good to use - */ - bool QvTranslator::testTranslationDir(const QString &targetDir) - { - const auto translations = QDir(targetDir).entryList(QStringList{ "*.qm" }, QDir::Hidden | QDir::Files); - - /// @todo: add some debug traces - - return !translations.empty(); - } } // namespace Qv2ray::common From 3740345af1771a1e5c7dc87604c6879b28fa2e2d Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 22:16:43 +0800 Subject: [PATCH 184/332] cmake: fixing GitHub Action - 7 --- .github/workflows/build-qv2ray-cmake.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 11f57fcf..a422a76d 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -123,6 +123,7 @@ jobs: mkdir ./qv2ray.app/Contents cp ../assets/info.plist ./qv2ray.app/Contents sudo cmake --install . + sudo chmod a+rw ./ --recursive --changesc # -------------------------------------------------------- Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage if: matrix.platform == 'ubuntu-16.04' From 3c831163ab99b117498cb52c452f8f8052133ff0 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 22:22:44 +0800 Subject: [PATCH 185/332] cmake: fixing GitHub Action - 8 --- .github/workflows/build-qv2ray-cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index a422a76d..d2631391 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -123,7 +123,7 @@ jobs: mkdir ./qv2ray.app/Contents cp ../assets/info.plist ./qv2ray.app/Contents sudo cmake --install . - sudo chmod a+rw ./ --recursive --changesc + sudo chmod a+rw --recursive --changes ./ # -------------------------------------------------------- Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage if: matrix.platform == 'ubuntu-16.04' From c61ef37b92b4e75b706a54f15e04a7e583bc87fa Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 22:34:46 +0800 Subject: [PATCH 186/332] cmake: fixing GitHub Action - 9 --- .github/workflows/build-qv2ray-cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index d2631391..2244232c 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -123,7 +123,7 @@ jobs: mkdir ./qv2ray.app/Contents cp ../assets/info.plist ./qv2ray.app/Contents sudo cmake --install . - sudo chmod a+rw --recursive --changes ./ + sudo chmod -Rv a+rw ./ # -------------------------------------------------------- Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage if: matrix.platform == 'ubuntu-16.04' From c922a17a2e9340d2bea1082d60d09ef9cbfd1463 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 21:15:32 +0800 Subject: [PATCH 187/332] cmake: fixing GitHub Action - 4 --- .github/workflows/build-qv2ray-cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 2244232c..b6b2e2be 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -70,7 +70,7 @@ jobs: sudo add-apt-repository ppa:webispy/grpc sudo add-apt-repository ppa:carsten-uppenbrink-net/openssl sudo apt update - sudo apt install -y libgl-dev openssl libx11-dev libxkbcommon-x11-dev libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler libgrpc++-dev protobuf-compiler-grpc + sudo apt install -y libgl-dev libx11-dev libxkbcommon-x11-dev libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler libgrpc++-dev protobuf-compiler-grpc - name: macOS - Install Packages if: matrix.platform == 'macos-latest' From 62348b0b96bace8271d83d3353f9b92256c57816 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 22:45:34 +0800 Subject: [PATCH 188/332] cmake: fixing GitHub Action - 10 --- .github/workflows/build-qv2ray-cmake.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index b6b2e2be..0c7c83be 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -83,7 +83,7 @@ jobs: run: | curl -o ./libs/libqvb-linux64.a -L https://github.com/Qv2ray/QvRPCBridge/releases/download/v1.1/libqvb-linux64.a curl -o ./libs/libqvb-darwin.a -L https://github.com/Qv2ray/QvRPCBridge/releases/download/v1.1/libqvb-darwin.a - curl -o ./libs/Qv2ray-deps-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-${{ matrix.arch }}-windows.7z + curl -o ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Extract Windows Dependencies if: matrix.platform == 'windows-latest' uses: DuckSoft/extract-7z-action@v1.0 @@ -91,15 +91,25 @@ jobs: pathSource: ./libs/Qv2ray-deps-${{ matrix.arch }}-windows.7z pathTarget: ./libs # -------------------------------------------------------- Generate MakeFile - - name: Cross-platform - ${{ matrix.qt_version }} - Generate Dependencies and Makefile + - name: macOS - ${{ matrix.qt_version }} - Generate Dependencies and Makefile shell: bash - if: matrix.platform != 'ubuntu-16.04' + if: matrix.platform == 'macos-latest' run: | mkdir build cd build export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" cmake .. + + - name: Windows - ${{ matrix.qt_version }} - Generate Dependencies and Makefile + shell: bash + if: matrix.platform == 'windows-latest' + run: | + mkdir build + cd build + export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" + export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" + cmake .. -DCMAKE_TOOLCHAIN_FILE=../libs/${{ matrix.arch }}-windows/scripts/buildsystems/vcpkg.cmake - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Makefile if: matrix.platform == 'ubuntu-16.04' From 7573ed0024f217f8cb2f66a3861e2bf5c766bd12 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sat, 7 Mar 2020 22:48:24 +0800 Subject: [PATCH 189/332] cmake: fixing GitHub Action - 11 --- .github/workflows/build-qv2ray-cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 0c7c83be..4eeeaf3d 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -88,7 +88,7 @@ jobs: if: matrix.platform == 'windows-latest' uses: DuckSoft/extract-7z-action@v1.0 with: - pathSource: ./libs/Qv2ray-deps-${{ matrix.arch }}-windows.7z + pathSource: ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z pathTarget: ./libs # -------------------------------------------------------- Generate MakeFile - name: macOS - ${{ matrix.qt_version }} - Generate Dependencies and Makefile From 67133cab69de92a7136fb8d9408f30c611865a45 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 23:45:07 +0800 Subject: [PATCH 190/332] cmake: fixing GitHub Action - 12 --- .github/workflows/build-qv2ray-cmake.yml | 3 --- cmake/macdeploy.cmake | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 4eeeaf3d..c7a9c093 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -129,9 +129,6 @@ jobs: run: | cd build cmake --build . --parallel $(nproc) - mkdir ./qv2ray.app - mkdir ./qv2ray.app/Contents - cp ../assets/info.plist ./qv2ray.app/Contents sudo cmake --install . sudo chmod -Rv a+rw ./ # -------------------------------------------------------- Deployments diff --git a/cmake/macdeploy.cmake b/cmake/macdeploy.cmake index 605215d5..d886bcb0 100644 --- a/cmake/macdeploy.cmake +++ b/cmake/macdeploy.cmake @@ -30,6 +30,8 @@ install(TARGETS ${PROJECT_NAME} BUNDLE DESTINATION . COMPONENT Runtime RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} COMPONENT Runtime ) +install(FILES ${CMAKE_SOURCE_DIR}/assets/info.plist DESTINATION "${prefix}" ) +install(FILES ${CMAKE_SOURCE_DIR}/assets/icons/qv2ray.icns DESTINATION "${INSTALL_CMAKE_DIR}" ) # Note Mac specific extension .app set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.app") From daa2efde737cfe51e74567d50a670511d212b219 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sat, 7 Mar 2020 23:51:33 +0800 Subject: [PATCH 191/332] cmake: removed qmake files --- Qv2ray.pro | 180 ---------------------------------- makespec/00-deps.pri | 48 --------- makespec/01-sourcesparser.pri | 50 ---------- makespec/02-translations.pri | 24 ----- makespec/03-Windows.pri | 51 ---------- makespec/03-unix.pri | 30 ------ makespec/04-unix-linux.pri | 26 ----- makespec/04-unix-macOS.pri | 16 --- makespec/99-others.pri | 39 -------- 9 files changed, 464 deletions(-) delete mode 100644 Qv2ray.pro delete mode 100644 makespec/00-deps.pri delete mode 100644 makespec/01-sourcesparser.pri delete mode 100644 makespec/02-translations.pri delete mode 100644 makespec/03-Windows.pri delete mode 100644 makespec/03-unix.pri delete mode 100644 makespec/04-unix-linux.pri delete mode 100644 makespec/04-unix-macOS.pri delete mode 100644 makespec/99-others.pri diff --git a/Qv2ray.pro b/Qv2ray.pro deleted file mode 100644 index fea08816..00000000 --- a/Qv2ray.pro +++ /dev/null @@ -1,180 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2019-03-28T08:45:32 -# -#------------------------------------------------- - -QT += core gui widgets network - -TARGET = qv2ray -TEMPLATE = app - -# Now read build number file. -QV2RAY_VERSION=$$cat($$PWD/makespec/VERSION) -QV2RAY_BUILD_VERSION=$$cat($$PWD/makespec/BUILDVERSION) - -VERSION = $${QV2RAY_VERSION}.$${QV2RAY_BUILD_VERSION} - -message(" ") -message("Qv2ray Version: $${VERSION}") -message("|-------------------------------------------------|") -message("| Qv2ray, A Cross Platform v2ray Qt GUI Client. |") -message("| Licenced under GPLv3 |") -message("| |") -message("| You may only use this program to the extent |") -message("| permitted by local law. |") -message("| |") -message("| See: https://www.gnu.org/licenses/gpl-3.0.html |") -message("|-------------------------------------------------|") -message("| Project Homepage: https://github.com/Qv2ray |") -message("| Welcome to contribute! |") -message("|-------------------------------------------------|") -message(" ") - -# Distinguish debug and release builds. -CONFIG(release, debug|release) { - CONFIG+=Qv2ray_release no_increase_build_number -} -CONFIG(debug, debug|release) { - CONFIG+=Qv2ray_debug -} - -# Qv2ray basic configuration -CONFIG += qt c++17 openssl-linked -include($$PWD/makespec/00-deps.pri) - -# lrelease will not work when adding BEFORE 00-deps.pri -CONFIG += lrelease embed_translations -DEFINES += QT_DEPRECATED_WARNINGS QV2RAY_VERSION_STRING=\"\\\"v$${VERSION}\\\"\" QAPPLICATION_CLASS=QApplication XTOSTRUCT_QT - -# Source file parser -include($$PWD/makespec/01-sourcesparser.pri) - -# Main config -Qv2rayAddSource(base, _, GlobalInstances, hpp) -Qv2rayAddSource(base, _, JsonHelpers, hpp) -Qv2rayAddSource(base, _, Qv2rayBase, hpp) -Qv2rayAddSource(base, _, Qv2rayFeatures, hpp) -Qv2rayAddSource(base, _, Qv2rayLog, cpp, hpp) -Qv2rayAddSource(base, models, CoreObjectModels, hpp) -Qv2rayAddSource(base, models, QvSettingsObject, hpp) -Qv2rayAddSource(base, models, QvConfigIdentifier, hpp) -Qv2rayAddSource(base, models, QvSafeType, hpp) -Qv2rayAddSource(base, models, QvRuntimeConfig, hpp) -Qv2rayAddSource(base, models, QvStartupConfig, hpp) -Qv2rayAddSource(common, _, CommandArgs, cpp, hpp) -Qv2rayAddSource(common, _, HTTPRequestHelper, cpp, hpp) -Qv2rayAddSource(common, _, LogHighlighter, cpp, hpp) -Qv2rayAddSource(common, _, QJsonModel, cpp, hpp) -Qv2rayAddSource(common, _, QvHelpers, cpp, hpp) -Qv2rayAddSource(common, _, QvTranslator, hpp) -Qv2rayAddSource(components, autolaunch, QvAutoLaunch, cpp, hpp) -Qv2rayAddSource(components, pac, QvGFWPACConverter, cpp) -Qv2rayAddSource(components, pac, QvPACHandler, cpp, hpp) -Qv2rayAddSource(components, plugins/toolbar, QvToolbar, cpp, hpp) -Qv2rayAddSource(components, plugins/toolbar, QvToolbar_linux, cpp) -Qv2rayAddSource(components, plugins/toolbar, QvToolbar_win, cpp) -Qv2rayAddSource(components, proxy, QvProxyConfigurator, cpp, hpp) -Qv2rayAddSource(components, speedchart, speedwidget, cpp, hpp) -Qv2rayAddSource(components, speedchart, speedplotview, cpp, hpp) -Qv2rayAddSource(components, geosite, QvGeositeReader, cpp, hpp) -Qv2rayAddSource(core, settings, SettingsBackend, cpp, hpp) -Qv2rayAddSource(core, settings, SettingsUpgrade, cpp) -Qv2rayAddSource(core, connection, ConnectionIO, cpp, hpp) -Qv2rayAddSource(core, connection, Generation, cpp, hpp) -# Some serializations -Qv2rayAddSource(core, connection, Serialization, cpp, hpp) -Qv2rayAddSource(core, connection, Serialization_vmess, cpp) -Qv2rayAddSource(core, connection, Serialization_ss, cpp) -Qv2rayAddSource(core, connection, Serialization_ssd, cpp) -# -Qv2rayAddSource(core, kernel, KernelInteractions, cpp, hpp) -Qv2rayAddSource(core, kernel, APIBackend, cpp, hpp) -Qv2rayAddSource(core, tcping, QvTCPing, cpp, hpp) -# Connection Handlers -Qv2rayAddSource(core, handler, ConfigHandler, cpp, hpp) -Qv2rayAddSource(core, handler, V2rayInstanceHandler, cpp) -# -Qv2rayAddSource(core, _, CoreUtils, cpp, hpp) -Qv2rayAddSource(core, _, CoreSafeTypes, hpp) -Qv2rayAddSource(ui, editors, w_InboundEditor, cpp, hpp, ui) -Qv2rayAddSource(ui, editors, w_JsonEditor, cpp, hpp, ui) -Qv2rayAddSource(ui, editors, w_OutboundEditor, cpp, hpp, ui) -Qv2rayAddSource(ui, editors, w_RoutesEditor, cpp, hpp, ui) -Qv2rayAddSource(ui, editors, w_RoutesEditor_extra, cpp) -Qv2rayAddSource(ui, models, InboundNodeModel, cpp, hpp) -Qv2rayAddSource(ui, models, OutboundNodeModel, cpp, hpp) -Qv2rayAddSource(ui, models, RuleNodeModel, cpp, hpp) -Qv2rayAddSource(ui, models, NodeModelsBase, hpp) -Qv2rayAddSource(ui, messaging, QvMessageBus, cpp, hpp) -Qv2rayAddSource(ui, _, w_ExportConfig, cpp, hpp, ui) -Qv2rayAddSource(ui, _, w_ImportConfig, cpp, hpp, ui) -Qv2rayAddSource(ui, _, w_MainWindow, cpp, hpp, ui) -Qv2rayAddSource(ui, _, w_MainWindow_extra, cpp) -Qv2rayAddSource(ui, _, w_PreferencesWindow, cpp, hpp, ui) -Qv2rayAddSource(ui, _, w_ScreenShot_Core, cpp, hpp, ui) -Qv2rayAddSource(ui, _, w_SubscriptionManager, cpp, hpp, ui) -Qv2rayAddSource(ui, widgets, StreamSettingsWidget, cpp, hpp, ui) -Qv2rayAddSource(ui, widgets, ConnectionItemWidget, cpp, hpp, ui) -Qv2rayAddSource(ui, widgets, ConnectionInfoWidget, cpp, hpp, ui) - -SOURCES += $$PWD/src/main.cpp -HEADERS += -FORMS += -INCLUDEPATH += $$PWD/src -RESOURCES += $$PWD/resources.qrc -ICON = $$PWD/assets/icons/qv2ray.icns -RC_ICONS += $$PWD/assets/icons/qv2ray.ico - -include($$PWD/makespec/02-translations.pri) - -unix { - include($$PWD/makespec/03-unix.pri) - # Sub-process of Qv2ray per-OS build - !macx: include($$PWD/makespec/04-unix-linux.pri) - macx: include($$PWD/makespec/04-unix-macOS.pri) -} else { - include($$PWD/makespec/03-Windows.pri) -} - -# ------------------------------------------ Begin checking protobuf domain list headers. -!exists($$PWD/libs/gen/v2ray_geosite.pb.cc) || !exists($$PWD/libs/gen/v2ray_geosite.pb.cc) { - Qv2rayQMakeError("Protobuf headers for v2ray geosite is missing.") -} - -SOURCES += $$PWD/libs/gen/v2ray_geosite.pb.cc -HEADERS += $$PWD/libs/gen/v2ray_geosite.pb.h - -# General header and source files for gRPC and libQvb -message(" ") -use_grpc { - DEFINES += WITH_LIB_GRPCPP - message("Qv2ray will use gRPC as API backend") - - !exists($$PWD/libs/gen/v2ray_api.grpc.pb.h) || !exists($$PWD/libs/gen/v2ray_api.grpc.pb.cc) || !exists($$PWD/libs/gen/v2ray_api.pb.h) || !exists($$PWD/libs/gen/v2ray_api.pb.cc) { - Qv2rayQMakeError("gRPC and protobuf headers for v2ray API is missing.") - } - - SOURCES += $$PWD/libs/gen/v2ray_api.pb.cc $$PWD/libs/gen/v2ray_api.grpc.pb.cc - HEADERS += $$PWD/libs/gen/v2ray_api.pb.h $$PWD/libs/gen/v2ray_api.grpc.pb.h -} else { - message("Qv2ray will use libqvb as API backend") - !exists($$PWD/libs/libqvb/build/libqvb.h) { - Qv2rayQMakeError("libs/libqvb/build/libqvb.h is missing.") - } - HEADERS += $$PWD/libs/libqvb/build/libqvb.h -} - -# Misc steps to build Qv2ray. -include($$PWD/makespec/99-others.pri) - -message(" ") -message("This Qv2ray build contains: ") -message(" --> $${size(SOURCES)} source files") -message(" --> $${size(HEADERS)} header files") -message(" --> $${size(FORMS)} ui files") -message(" --> $${size(TRANSLATIONS)} translation files") -message(" --> $${size(EXTRA_TRANSLATIONS)} extra translation files") -message(" ") -message("Finished configuring Qv2ray project. Build output will be at:" $$OUT_PWD) -message("Type 'make' or 'nmake' to start building Qv2ray") diff --git a/makespec/00-deps.pri b/makespec/00-deps.pri deleted file mode 100644 index 6ab39762..00000000 --- a/makespec/00-deps.pri +++ /dev/null @@ -1,48 +0,0 @@ -message(" ") -message("Configuring Qv2ray Dependencies...") - -defineTest(Qv2rayQMakeError) { - message(" ") - message("-----------------------------------------------") - message("Cannot continue: ") - message(" --> Qv2ray is not properly configured yet: ") - message(" $$ARGS") - message(" --> Please read the build wiki: https://github.com/Qv2ray/Qv2ray/wiki/Manually-Build-Qv2ray") - message("-----------------------------------------------") - message(" ") - warning("IF YOU THINK IT'S A MISTAKE, PLEASE OPEN AN ISSUE") - error("! ABORTING THE BUILD !") - message(" ") -} - -CONFIG += enable_decoder_qr_code enable_encoder_qr_code -include($$PWD/../3rdparty/qzxing/src/QZXing-components.pri) -include($$PWD/../3rdparty/SingleApplication/singleapplication.pri) -include($$PWD/../3rdparty/QNodeEditor/QNodeEditor.pri) - -#include(3rdparty/x2struct/x2struct.pri) - -message("Adding QHttpServer Support") -message(" --> Adding qhttpserver") -HEADERS += \ - $$PWD/../3rdparty/qhttpserver/src/qhttpconnection.h \ - $$PWD/../3rdparty/qhttpserver/src/qhttprequest.h \ - $$PWD/../3rdparty/qhttpserver/src/qhttpresponse.h \ - $$PWD/../3rdparty/qhttpserver/src/qhttpserver.h \ - $$PWD/../3rdparty/qhttpserver/src/qhttpserverapi.h \ - $$PWD/../3rdparty/qhttpserver/src/qhttpserverfwd.h - -SOURCES += \ - $$PWD/../3rdparty/qhttpserver/src/qhttpconnection.cpp \ - $$PWD/../3rdparty/qhttpserver/src/qhttprequest.cpp \ - $$PWD/../3rdparty/qhttpserver/src/qhttpresponse.cpp \ - $$PWD/../3rdparty/qhttpserver/src/qhttpserver.cpp - -INCLUDEPATH += 3rdparty/qhttpserver/src/ - -message(" --> Adding http parser") -HEADERS += $$PWD/../3rdparty/qhttpserver/http-parser/http_parser.h -SOURCES += $$PWD/../3rdparty/qhttpserver/http-parser/http_parser.c -INCLUDEPATH += $$PWD/../3rdparty/qhttpserver/http-parser/ - - diff --git a/makespec/01-sourcesparser.pri b/makespec/01-sourcesparser.pri deleted file mode 100644 index d66b800f..00000000 --- a/makespec/01-sourcesparser.pri +++ /dev/null @@ -1,50 +0,0 @@ -message(" ") -defineTest(Qv2rayAddFile) { - ext = $$take_last(ARGS) - filename = $${take_first(ARGS)}.$${ext} - qmake_debug: message("Qv2rayAddFile: filename: $$filename") - !exists($$filename) { - error("File: \"$$filename\" is not found, Qv2ray build preparation cannot continue") - } - equals(ext, "cpp") { - SOURCES += $$filename - } else { - equals(ext, "hpp") { - HEADERS += $$filename - } else { - equals(ext, "ui") { - FORMS += $$filename - } else { - error("Unknown extension: $${ext}") - } - } - } - export(SOURCES) - export(HEADERS) - export(FORMS) -} - -defineTest(Qv2rayAddSource) { - # Module Compnent Filename extlist - module = $$take_first(ARGS) - component = $$take_first(ARGS) - filename = $$take_first(ARGS) - extlist = $$ARGS - FILEPATH = "$$PWD/src/$${module}" - qmake_debug: message("Qv2rayAddSource: Adding \"$${filename}\" of module \"$${module}\", component \"$${component}\" to the project") - equals(component, "_") { - qmake_debug: message("Qv2rayAddSource: Component is empty, ignore") - FILEPATH += "/$${filename}" - FILEPATH=$$join(FILEPATH) - } else { - FILEPATH += "/$${component}/$${filename}" - FILEPATH=$$join(FILEPATH) - } - qmake_debug: message("Qv2rayAddSource: filepath: $${FILEPATH}, extlist: $${extlist}") - for(iterate, extlist) { - Qv2rayAddFile($$FILEPATH, $$iterate) - } - export(SOURCES) - export(HEADERS) - export(FORMS) -} diff --git a/makespec/02-translations.pri b/makespec/02-translations.pri deleted file mode 100644 index 61eaefda..00000000 --- a/makespec/02-translations.pri +++ /dev/null @@ -1,24 +0,0 @@ -message(" ") -message("Looking for language support.") -QM_FILES_RESOURCE_PREFIX = "translations" -for(var, $$list($$files("$$PWD/../translations/*.ts", true))) { - LOCALE_FILENAME = $$basename(var) - message(" --> Found:" $$LOCALE_FILENAME) - !equals(LOCALE_FILENAME, "en_US.ts") { - # ONLY USED IN LRELEASE CONTEXT - # en_US is not EXTRA... - EXTRA_TRANSLATIONS += $$PWD/../translations/$$LOCALE_FILENAME - } -} - -TRANSLATIONS += $$PWD/../translations/en_US.ts -message("Qv2ray will build with" $${replace(EXTRA_TRANSLATIONS, "$$PWD/../translations/", "")} and $${replace(TRANSLATIONS, "$$PWD/../translations/", "")}) - -qmake_lupdate { - message(" ") - message("Running lupdate...") - message("TRANSLATIONS: $$TRANSLATIONS") - lupdate_output = $$system(lupdate -no-ui-lines $$SOURCES $$HEADERS $$FORMS -ts $$TRANSLATIONS) - message(" $$lupdate_output") - message("lupdate finished.") -} diff --git a/makespec/03-Windows.pri b/makespec/03-Windows.pri deleted file mode 100644 index b97605e8..00000000 --- a/makespec/03-Windows.pri +++ /dev/null @@ -1,51 +0,0 @@ -message(" ") -message("Configuring for Windows environment") -QMAKE_CXXFLAGS += /MP /wo4251 -DEFINES += QHTTPSERVER_EXPORT - -!has_std_byte { - message("WARN: c++17 std::byte is disabled") - DEFINES += _HAS_STD_BYTE=0 -} else { - message("WARN: You are playing with a conflict between c++17 std::byte and Windows.h typedef byte") - message(" --> Be careful and good luck") -} - -CONFIG += Qv2ray_Windows use_grpc -!contains(QMAKE_TARGET.arch, x86_64) { - CONFIG+=Qv2ray_win32 - GRPC_DEPS_PATH=$$PWD/../libs/x86-windows - # - !no_generate_headers: message(" --> Generating gRPC and protobuf headers for Windows x86") - !no_generate_headers: system("$$PWD/../tools/win32-generate-pb.bat") -} else { - CONFIG+=Qv2ray_win64 - GRPC_DEPS_PATH=$$PWD/../libs/x64-windows - # - !no_generate_headers: message(" --> Generating gRPC and protobuf headers for Windows x64") - !no_generate_headers: system("$$PWD/../tools/win64-generate-pb.bat") -} - -message(" --> Applying a hack for protobuf header") -DEFINES += _WIN32_WINNT=0x600 - -DEPENDPATH += $$GRPC_DEPS_PATH/include -INCLUDEPATH += $$GRPC_DEPS_PATH/include - -message(" --> Setting up target descriptions") -QMAKE_TARGET_DESCRIPTION = "Qv2ray, a cross-platform v2ray GUI client." -QMAKE_TARGET_PRODUCT = "Qv2ray" - -Qv2ray_debug: GRPC_LIB_PATH=$$GRPC_DEPS_PATH/debug -Qv2ray_release: GRPC_LIB_PATH=$$GRPC_DEPS_PATH - -message(" --> WIN32: Linking against gRPC library: $$GRPC_LIB_PATH") -Qv2ray_debug: LIBS += -L$$GRPC_LIB_PATH/lib/ -laddress_sorting -lcares -lgrpc++_unsecure -lupb -lzlibd -lgrpc_unsecure -lgpr -labsl_base -labsl_strings -labsl_throw_delegate -Qv2ray_release: LIBS += -L$$GRPC_LIB_PATH/lib/ -laddress_sorting -lcares -lgrpc++_unsecure -lupb -lzlib -lgrpc_unsecure -lgpr -labsl_base -labsl_strings -labsl_throw_delegate - -message(" --> WIN32: Linking against protobuf library: $$GRPC_LIB_PATH") -Qv2ray_release: LIBS += -lmsvcrt -L$$GRPC_LIB_PATH/lib/ -llibprotobuf -Qv2ray_debug: LIBS += -lmsvcrtd -L$$GRPC_LIB_PATH/lib/ -llibprotobufd - -message(" --> Linking against winHTTP and winSock2.") -LIBS += -lwinhttp -lwininet -lws2_32 -luser32 diff --git a/makespec/03-unix.pri b/makespec/03-unix.pri deleted file mode 100644 index 097ff088..00000000 --- a/makespec/03-unix.pri +++ /dev/null @@ -1,30 +0,0 @@ -message(" ") -win32: Qv2rayQMakeError("Do not include this file in Windows platform.") - -# For Linux and macOS -message("Configuring for unix-like environment") - -message(" --> Setting up QMAKE_CXXFLAGS") -QMAKE_CXXFLAGS += -Wno-missing-field-initializers -Wno-unused-parameter -Wno-unused-variable - -# macOS homebrew include path -message(" --> Adding local include folder to search path") -INCLUDEPATH += /usr/local/include/ - -# For protobuf in linux and macOS -message(" --> Linking against protobuf library.") -LIBS += -L/usr/local/lib -lprotobuf - -!no_generate_headers { - message(" --> Generating geosite headers for Unix") - system("$$PWD/../tools/unix-generate-geosite.sh $$PWD") -} - -use_grpc { - no_generate_headers { - message(" --> Skipped generation of protobuf and/or gRPC header files") - } else { - message(" --> Generating gRPC and protobuf headers for Unix") - system("$$PWD/../tools/unix-generate-api.sh $$PWD") - } -} diff --git a/makespec/04-unix-linux.pri b/makespec/04-unix-linux.pri deleted file mode 100644 index 1322c0bd..00000000 --- a/makespec/04-unix-linux.pri +++ /dev/null @@ -1,26 +0,0 @@ -message(" ") -message("Configuring Qv2ray build for Linux") -isEmpty(PREFIX) { - PREFIX=/usr/local -} - -use_grpc { - # For gRPC and protobuf in linux - message(" --> Linking against gRPC and protobuf library.") - LIBS += -L/usr/local/lib -lgrpc++ -lgrpc -} else { - message(" --> Linking libqvb static library, for Linux platform.") - LIBS += -L$$PWD/../libs/ -lqvb-linux64 -} - -message(" --> Generating desktop dependency.") -desktop.files += $$PWD/../assets/qv2ray.desktop -desktop.path = $$PREFIX/share/applications/ - -message(" --> Generating icons dependency.") -icon.files += $$PWD/../assets/icons/qv2ray.png -icon.path = $$PREFIX/share/icons/hicolor/256x256/apps/ - -target.path = $$PREFIX/bin/ -INSTALLS += target desktop icon - diff --git a/makespec/04-unix-macOS.pri b/makespec/04-unix-macOS.pri deleted file mode 100644 index 6c6f0032..00000000 --- a/makespec/04-unix-macOS.pri +++ /dev/null @@ -1,16 +0,0 @@ -message(" ") - -# For Linux and macOS -message("Configuring for macOS specific environment") -LIBS += -framework Carbon -framework Cocoa -message(" --> Linking Security framework, for macOS platform.") -LIBS += -framework Security - -use_grpc { - # For gRPC and protobuf in macOS - message(" --> Linking against gRPC library.") - LIBS += -L/usr/local/lib -lgrpc++ -lgrpc -lgpr -lupb -} else { - message(" --> Linking libqvb static library, for macOS platform.") - LIBS += -L$$PWD/../libs/ -lqvb-darwin -} diff --git a/makespec/99-others.pri b/makespec/99-others.pri deleted file mode 100644 index f16a05ff..00000000 --- a/makespec/99-others.pri +++ /dev/null @@ -1,39 +0,0 @@ -message(" ") -with_metainfo { - message(" --> Generating metainfo dependency.") - appdataXml.files += ./assets/qv2ray.metainfo.xml - appdataXml.path = $$PREFIX/share/metainfo/ - INSTALLS += appdataXml - DEFINES += WITH_FLATHUB_CONFIG_PATH -} - -# Automatically increase build number. -no_increase_build_number | qmake_lupdate { - message("QV2RAY_BUILD_VERSION will not be increased") -} else { - QV2RAY_BUILD_VERSION = $$num_add($$QV2RAY_BUILD_VERSION, 1) - write_file($$PWD/BUILDVERSION, QV2RAY_BUILD_VERSION) -} - -# Qv2ray manual build info -!no_build_info { - _QV2RAY_BUILD_INFO_STR_=$$getenv(_QV2RAY_BUILD_INFO_) - _QV2RAY_BUILD_EXTRA_INFO_STR_=$$getenv(_QV2RAY_BUILD_EXTRA_INFO_) - - isEmpty(_QV2RAY_BUILD_INFO_STR_) { - _QV2RAY_BUILD_INFO_STR_ = "Qv2ray from manual build" - } - - isEmpty(_QV2RAY_BUILD_EXTRA_INFO_STR_) { - _QV2RAY_BUILD_EXTRA_INFO_STR_ = "Qv2ray $$VERSION" - } -} else { - _QV2RAY_BUILD_INFO_STR_ = "No Info" - _QV2RAY_BUILD_EXTRA_INFO_STR_ = "No Extra Info" -} - -message("Qv2ray build info:") -message(" --> $$_QV2RAY_BUILD_INFO_STR_") -message(" --> $$_QV2RAY_BUILD_EXTRA_INFO_STR_") - -DEFINES += _QV2RAY_BUILD_INFO_STR_=\"\\\"$${_QV2RAY_BUILD_INFO_STR_}\\\"\" _QV2RAY_BUILD_EXTRA_INFO_STR_=\"\\\"$${_QV2RAY_BUILD_EXTRA_INFO_STR_}\\\"\" From 9f96d6499b0e9a81f8638e5861d274bd232e5009 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 00:11:00 +0800 Subject: [PATCH 192/332] cmake: rewrite action script --- .github/workflows/build-qv2ray-cmake.yml | 31 ++++++++++++------------ 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index c7a9c093..dfbffa52 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -90,47 +90,48 @@ jobs: with: pathSource: ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z pathTarget: ./libs -# -------------------------------------------------------- Generate MakeFile - - name: macOS - ${{ matrix.qt_version }} - Generate Dependencies and Makefile +# -------------------------------------------------------- Generate MakeFile and Build + - name: macOS - ${{ matrix.qt_version }} - Generate Dependencies and Build shell: bash if: matrix.platform == 'macos-latest' run: | + export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" + export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}-ci.${{ matrix.platform }}" mkdir build cd build - export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" - export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" - cmake .. + cmake --build . --parallel $(nproc) + sudo cmake --install . + sudo chmod -Rv a+rw ./ - - name: Windows - ${{ matrix.qt_version }} - Generate Dependencies and Makefile + - name: Windows - ${{ matrix.qt_version }} - Generate Dependencies and Build shell: bash if: matrix.platform == 'windows-latest' run: | + export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" + export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}-ci.${{ matrix.platform }}" mkdir build cd build - export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" - export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" cmake .. -DCMAKE_TOOLCHAIN_FILE=../libs/${{ matrix.arch }}-windows/scripts/buildsystems/vcpkg.cmake - - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Makefile + - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Build if: matrix.platform == 'ubuntu-16.04' shell: bash env: CC: /usr/bin/gcc-9 CXX: /usr/bin/g++-9 run: | + export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" + export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}-ci.${{ matrix.platform }}" mkdir build cd build - export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" - export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}" cmake .. -DCMAKE_INSTALL_PREFIX=./AppDir/usr + cmake --install . # -------------------------------------------------------- Build - - name: Build Qv2ray + - name: Inspect Build Output shell: bash run: | cd build - cmake --build . --parallel $(nproc) - sudo cmake --install . - sudo chmod -Rv a+rw ./ + ls -lah --recursive --color=always || true # -------------------------------------------------------- Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage if: matrix.platform == 'ubuntu-16.04' From 8f1fa31bcc37c031a84430f8a27ce6a9afb0679d Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 08:43:25 +0800 Subject: [PATCH 193/332] specify build arch for windows --- .github/workflows/build-qv2ray-cmake.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index dfbffa52..efa1943b 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -16,9 +16,11 @@ jobs: - platform: windows-latest arch: x86 qtarch: win32_msvc2017 + buildarch: Win32 - platform: windows-latest arch: x64 qtarch: win64_msvc2017_64 + buildarch: x64 exclude: - platform: ubuntu-16.04 arch: x86 @@ -111,7 +113,7 @@ jobs: export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}-ci.${{ matrix.platform }}" mkdir build cd build - cmake .. -DCMAKE_TOOLCHAIN_FILE=../libs/${{ matrix.arch }}-windows/scripts/buildsystems/vcpkg.cmake + cmake .. -DCMAKE_TOOLCHAIN_FILE=../libs/${{ matrix.arch }}-windows/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.buildarch }} - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Build if: matrix.platform == 'ubuntu-16.04' From 5dd752b9a62ecb3df9c2827bf6630108cafe6acc Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 08:48:08 +0800 Subject: [PATCH 194/332] cmake: update action --- .github/workflows/build-qv2ray-cmake.yml | 44 +++++++++++------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index efa1943b..8236baf3 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -29,6 +29,9 @@ jobs: fail-fast: false runs-on: ${{ matrix.platform }} + env: + _QV2RAY_BUILD_INFO_: "Qv2ray built from Github Action" + _QV2RAY_BUILD_EXTRA_INFO_: "qt${{ matrix.qt_version }}-${{ github.sha }}-ci.${{ matrix.platform }}" steps: - name: Get the version @@ -44,7 +47,7 @@ jobs: architecture: ${{ matrix.arch }} - name: Restoring submodules run: git submodule update --init -# -------------------------------------------------------- +# ========================================================================================================= - name: Install MSVC compiler if: matrix.platform == 'windows-latest' uses: ilammy/msvc-dev-cmd@v1 @@ -65,56 +68,52 @@ jobs: arch: ${{ matrix.qtarch }} mirror: 'http://mirrors.ocf.berkeley.edu/qt/' cached: ${{ steps.cache-qt.outputs.cache-hit }} -# -------------------------------------------------------- - - name: Linux - Install Packages +# ========================================================================================================= + - name: Linux - ${{ matrix.qt_version }} - Build preparation - Install Packages if: matrix.platform == 'ubuntu-16.04' run: | sudo add-apt-repository ppa:webispy/grpc sudo add-apt-repository ppa:carsten-uppenbrink-net/openssl sudo apt update sudo apt install -y libgl-dev libx11-dev libxkbcommon-x11-dev libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler libgrpc++-dev protobuf-compiler-grpc - - - name: macOS - Install Packages +# -------------------------------------------------------- + - name: macOS - ${{ matrix.qt_version }} - Build preparation - Install Packages if: matrix.platform == 'macos-latest' run: | brew install protobuf brew install grpc # -------------------------------------------------------- - - name: Cross-platform - Download libraries + - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Build preparation - Download Dependencies shell: bash + if: matrix.platform == 'windows-latest' run: | - curl -o ./libs/libqvb-linux64.a -L https://github.com/Qv2ray/QvRPCBridge/releases/download/v1.1/libqvb-linux64.a - curl -o ./libs/libqvb-darwin.a -L https://github.com/Qv2ray/QvRPCBridge/releases/download/v1.1/libqvb-darwin.a curl -o ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z - - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Extract Windows Dependencies + - name: Win-${{ matrix.arch }} - Build preparation - Extract Dependencies if: matrix.platform == 'windows-latest' uses: DuckSoft/extract-7z-action@v1.0 with: pathSource: ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z pathTarget: ./libs -# -------------------------------------------------------- Generate MakeFile and Build +# ========================================================================================================= Generate MakeFile and Build - name: macOS - ${{ matrix.qt_version }} - Generate Dependencies and Build shell: bash if: matrix.platform == 'macos-latest' run: | - export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" - export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}-ci.${{ matrix.platform }}" mkdir build cd build cmake --build . --parallel $(nproc) sudo cmake --install . sudo chmod -Rv a+rw ./ - +# -------------------------------------------------------- - name: Windows - ${{ matrix.qt_version }} - Generate Dependencies and Build shell: bash if: matrix.platform == 'windows-latest' run: | - export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" - export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}-ci.${{ matrix.platform }}" mkdir build cd build cmake .. -DCMAKE_TOOLCHAIN_FILE=../libs/${{ matrix.arch }}-windows/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.buildarch }} - + cmake --build . --parallel $(nproc) +# -------------------------------------------------------- - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Build if: matrix.platform == 'ubuntu-16.04' shell: bash @@ -122,19 +121,18 @@ jobs: CC: /usr/bin/gcc-9 CXX: /usr/bin/g++-9 run: | - export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action" - export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}-ci.${{ matrix.platform }}" mkdir build cd build cmake .. -DCMAKE_INSTALL_PREFIX=./AppDir/usr + cmake --build . --parallel $(nproc) cmake --install . -# -------------------------------------------------------- Build +# ========================================================================================================= Build - name: Inspect Build Output shell: bash run: | cd build ls -lah --recursive --color=always || true -# -------------------------------------------------------- Deployments +# ========================================================================================================= Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage if: matrix.platform == 'ubuntu-16.04' run: | @@ -169,7 +167,7 @@ jobs: asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.linux-${{ matrix.arch }}.AppImage tag: ${{ github.ref }} overwrite: true -# == +# -------------------------------------------------------- - name: macOS - ${{ matrix.qt_version }} - Making release tarball if: matrix.platform == 'macos-latest' run: | @@ -190,7 +188,7 @@ jobs: asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.macOS-${{ matrix.arch }}.tar.gz tag: ${{ github.ref }} overwrite: true -# == +# -------------------------------------------------------- - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Copying DLLs to build output folders if: matrix.platform == 'windows-latest' run: .\.github\workflows\copy_DLLs.bat @@ -198,10 +196,10 @@ jobs: if: matrix.platform == 'windows-latest' shell: cmd run: | + set VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\ cd build cd release del *.cpp *.h *.o *.qrc *.qm *.hpp *.obj - set VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\ windeployqt ./qv2ray.exe --compiler-runtime --verbose 2 - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Create 7z Release if: matrix.platform == 'windows-latest' From 8b74093ec34f80165d7b39fece1096b2fa5d1cf6 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 08:52:01 +0800 Subject: [PATCH 195/332] Update build-qv2ray-cmake.yml --- .github/workflows/build-qv2ray-cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 8236baf3..07f7b759 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -101,7 +101,7 @@ jobs: run: | mkdir build cd build - cmake --build . --parallel $(nproc) + cmake --build . --parallel $(sysctl -n hw.logicalcpu) sudo cmake --install . sudo chmod -Rv a+rw ./ # -------------------------------------------------------- From fe9960aa6eb6c0097d49d5111623ac994e79ff70 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 08:54:45 +0800 Subject: [PATCH 196/332] Update build-qv2ray-cmake.yml --- .github/workflows/build-qv2ray-cmake.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 07f7b759..882386f6 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -101,6 +101,7 @@ jobs: run: | mkdir build cd build + cmake .. cmake --build . --parallel $(sysctl -n hw.logicalcpu) sudo cmake --install . sudo chmod -Rv a+rw ./ From fcfadf0a292df90d16ee6870c80beeb9503165e8 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 09:02:04 +0800 Subject: [PATCH 197/332] cmake: update action, use tree --- .github/workflows/build-qv2ray-cmake.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 882386f6..1a6de6b3 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -75,7 +75,7 @@ jobs: sudo add-apt-repository ppa:webispy/grpc sudo add-apt-repository ppa:carsten-uppenbrink-net/openssl sudo apt update - sudo apt install -y libgl-dev libx11-dev libxkbcommon-x11-dev libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler libgrpc++-dev protobuf-compiler-grpc + sudo apt install -y libgl-dev libx11-dev libxkbcommon-x11-dev libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler libgrpc++-dev protobuf-compiler-grpc tree # -------------------------------------------------------- - name: macOS - ${{ matrix.qt_version }} - Build preparation - Install Packages if: matrix.platform == 'macos-latest' @@ -132,7 +132,7 @@ jobs: shell: bash run: | cd build - ls -lah --recursive --color=always || true + tree || true # ========================================================================================================= Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage if: matrix.platform == 'ubuntu-16.04' From bef9e0045ab5029e0576263e2617220e673fad1a Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 09:14:25 +0800 Subject: [PATCH 198/332] set default value for CMAKE_TOOLCHAIN_FILE --- .github/workflows/build-qv2ray-cmake.yml | 2 +- CMakeLists.txt | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 1a6de6b3..e57d6d2b 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -112,7 +112,7 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_TOOLCHAIN_FILE=../libs/${{ matrix.arch }}-windows/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.buildarch }} + cmake .. -A ${{ matrix.buildarch }} cmake --build . --parallel $(nproc) # -------------------------------------------------------- - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Build diff --git a/CMakeLists.txt b/CMakeLists.txt index 4683308e..fef64bf3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,16 @@ if(APPLE) ) endif() +if(WIN32) + if(NOT CMAKE_TOOLCHAIN_FILE) + if(CMAKE_CL_64) + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) + else() + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x86-windows/scripts/buildsystems/vcpkg.cmake) + endif() + endif() +endif() + if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) set(_QV2RAY_BUILD_INFO_STR_ "$ENV{_QV2RAY_BUILD_INFO_}") else() From 5e3e85bddf3128efe9e8792a2a3be56fb0b6d653 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 09:18:17 +0800 Subject: [PATCH 199/332] cmake: removed unused file --- macOS.patch | 163 ---------------------------------------------------- 1 file changed, 163 deletions(-) delete mode 100644 macOS.patch diff --git a/macOS.patch b/macOS.patch deleted file mode 100644 index 448e91b5..00000000 --- a/macOS.patch +++ /dev/null @@ -1,163 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 5fad4af..c727c28 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -4,7 +4,7 @@ file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/VERSION" QV2RAY_VERSION) - file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" QV2RAY_BUILD_VERSION) - set(PACKAGE_VERSION "${QV2RAY_VERSION}.${QV2RAY_BUILD_VERSION}") - --project(Qv2ray) -+project(qv2ray) - add_definitions(-DQV2RAY_VERSION_STRING="v${PACKAGE_VERSION}") - add_definitions(-DXTOSTRUCT_QT) - -@@ -30,6 +30,21 @@ include(cmake/qzxing.cmake) - include(cmake/protobuf.cmake) - include(cmake/cpp-httplib.cmake) - include(cmake/backend.cmake) -+if(APPLE) -+ find_package(Iconv REQUIRED) -+ set(MACOSX_FRAMEWORK -+ "-framework Carbon" -+ "-framework Cocoa" -+ "-framework Security" -+ ) -+ set(MACOSX_ICONV_LIBRARY -+ Iconv::Iconv -+ ) -+ -+ set(MACOSX_ICONV_INCLUDE_PATH -+ ${Iconv_INCLUDE_DIR} -+ ) -+endif() - - if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) - set(_QV2RAY_BUILD_INFO_STR_ "$ENV{_QV2RAY_BUILD_INFO_}") -@@ -112,22 +127,7 @@ set(QT_LIBRARY - Qt5::Network - ) - --if(APPLE) -- find_package(Iconv REQUIRED) -- set(MACOSX_FRAMEWORK -- "-framework Carbon" -- "-framework Cocoa" -- "-framework Security" -- ) -- set(MACOSX_ICONV_LIBRARY -- Iconv::Iconv -- ) -- set(MACOSX_ICONV_INCLUDE_PATH -- ${Iconv_INCLUDE_DIR} -- ) --endif() -- --add_executable(qv2ray -+add_executable(${PROJECT_NAME} - ${QV2RAY_SOURCES} - ${QNODEEDITOR_SOURCES} - ${QNODEEDITOR_QRC_RESOURCES} -@@ -141,7 +141,7 @@ add_executable(qv2ray - ${QM_FILES} - ) - --target_link_libraries(qv2ray -+target_link_libraries(${PROJECT_NAME} - ${QT_LIBRARY} - ${MACOSX_FRAMEWORK} - ${MACOSX_ICONV_LIBRARY} -@@ -150,7 +150,7 @@ target_link_libraries(qv2ray - ) - - --target_include_directories(qv2ray PRIVATE -+target_include_directories(${PROJECT_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/src - ${CMAKE_BINARY_DIR} -@@ -163,12 +163,16 @@ target_include_directories(qv2ray PRIVATE - ${cpp-httplib_INCLUDE_DIRS} - ) - --install(TARGETS qv2ray -- RUNTIME -- DESTINATION bin --) -+if(APPLE) -+ set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) -+ include(cmake/macdeploy.cmake) -+endif() - - if(UNIX AND NOT APPLE) -+ install(TARGETS ${PROJECT_NAME} -+ RUNTIME -+ DESTINATION bin -+ ) - install(FILES assets/qv2ray.metainfo.xml - DESTINATION share/metainfo - ) -diff --git a/cmake/macdeploy.cmake b/cmake/macdeploy.cmake -new file mode 100644 -index 0000000..605215d ---- /dev/null -+++ b/cmake/macdeploy.cmake -@@ -0,0 +1,59 @@ -+set(prefix "${PROJECT_NAME}.app/Contents") -+set(INSTALL_RUNTIME_DIR "${prefix}/MacOS") -+set(INSTALL_CMAKE_DIR "${prefix}/Resources") -+ -+# based on code from CMake's QtDialog/CMakeLists.txt -+macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var _prefix) -+ get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION) -+ if(EXISTS "${_qt_plugin_path}") -+ get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME) -+ get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH) -+ get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME) -+ set(_qt_plugin_dest "${_prefix}/PlugIns/${_qt_plugin_type}") -+ install(FILES "${_qt_plugin_path}" -+ DESTINATION "${_qt_plugin_dest}") -+ set(${_qt_plugins_var} -+ "${${_qt_plugins_var}};\$ENV{DEST_DIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}") -+ else() -+ message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found") -+ endif() -+endmacro() -+ -+install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS ${prefix}) -+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" -+ "[Paths]\nPlugins = ${_qt_plugin_dir}\n") -+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" -+ DESTINATION "${INSTALL_CMAKE_DIR}") -+ -+# Destination paths below are relative to ${CMAKE_INSTALL_PREFIX} -+install(TARGETS ${PROJECT_NAME} -+ BUNDLE DESTINATION . COMPONENT Runtime -+ RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} COMPONENT Runtime -+ ) -+ -+# Note Mac specific extension .app -+set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.app") -+ -+# Directories to look for dependencies -+set(DIRS "${CMAKE_BINARY_DIR}") -+ -+# Path used for searching by FIND_XXX(), with appropriate suffixes added -+if(CMAKE_PREFIX_PATH) -+ foreach(dir ${CMAKE_PREFIX_PATH}) -+ list(APPEND DIRS "${dir}/bin" "${dir}/lib") -+ endforeach() -+endif() -+ -+# Append Qt's lib folder which is two levels above Qt5Widgets_DIR -+list(APPEND DIRS "${Qt5Widgets_DIR}/../..") -+list(APPEND DIRS "/usr/local/lib") -+list(APPEND DIRS "/usr/lib") -+ -+include(InstallRequiredSystemLibraries) -+ -+message(STATUS "APPS: ${APPS}") -+message(STATUS "QT_PLUGINS: ${QT_PLUGINS}") -+message(STATUS "DIRS: ${DIRS}") -+ -+install(CODE "include(BundleUtilities) -+ fixup_bundle(\"${APPS}\" \"${QT_PLUGINS}\" \"${DIRS}\")") From 616ffd81388e63aff8f1d8069908d25d5c751abe Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 09:18:51 +0800 Subject: [PATCH 200/332] update CMakeLists.txt --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fef64bf3..46469539 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,11 +63,11 @@ if(APPLE) endif() if(WIN32) - if(NOT CMAKE_TOOLCHAIN_FILE) + if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) if(CMAKE_CL_64) - set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) + add_definitions(-DCMAKE_TOOLCHAIN_FILE=${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) else() - set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x86-windows/scripts/buildsystems/vcpkg.cmake) + add_definitions(-DCMAKE_TOOLCHAIN_FILE=${CMAKE_SOURCE_DIR}/libs/x86-windows/scripts/buildsystems/vcpkg.cmake) endif() endif() endif() From 08c00c27d9bcec205c61d846b94ecd90ae2f121f Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 09:24:08 +0800 Subject: [PATCH 201/332] Revert "update CMakeLists.txt" This reverts commit 616ffd81388e63aff8f1d8069908d25d5c751abe. --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 46469539..fef64bf3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,11 +63,11 @@ if(APPLE) endif() if(WIN32) - if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) + if(NOT CMAKE_TOOLCHAIN_FILE) if(CMAKE_CL_64) - add_definitions(-DCMAKE_TOOLCHAIN_FILE=${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) else() - add_definitions(-DCMAKE_TOOLCHAIN_FILE=${CMAKE_SOURCE_DIR}/libs/x86-windows/scripts/buildsystems/vcpkg.cmake) + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x86-windows/scripts/buildsystems/vcpkg.cmake) endif() endif() endif() From d052121b7970361abb43c9ed430221a9ff34a10a Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 09:24:13 +0800 Subject: [PATCH 202/332] Revert "set default value for CMAKE_TOOLCHAIN_FILE" This reverts commit bef9e0045ab5029e0576263e2617220e673fad1a. --- .github/workflows/build-qv2ray-cmake.yml | 2 +- CMakeLists.txt | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index e57d6d2b..1a6de6b3 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -112,7 +112,7 @@ jobs: run: | mkdir build cd build - cmake .. -A ${{ matrix.buildarch }} + cmake .. -DCMAKE_TOOLCHAIN_FILE=../libs/${{ matrix.arch }}-windows/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.buildarch }} cmake --build . --parallel $(nproc) # -------------------------------------------------------- - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Build diff --git a/CMakeLists.txt b/CMakeLists.txt index fef64bf3..4683308e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,16 +62,6 @@ if(APPLE) ) endif() -if(WIN32) - if(NOT CMAKE_TOOLCHAIN_FILE) - if(CMAKE_CL_64) - set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) - else() - set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x86-windows/scripts/buildsystems/vcpkg.cmake) - endif() - endif() -endif() - if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) set(_QV2RAY_BUILD_INFO_STR_ "$ENV{_QV2RAY_BUILD_INFO_}") else() From 448e6e84ca966757d263e55d40ae73bd48759f76 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 09:30:42 +0800 Subject: [PATCH 203/332] Revert "Revert "set default value for CMAKE_TOOLCHAIN_FILE"" This reverts commit d052121b7970361abb43c9ed430221a9ff34a10a. --- .github/workflows/build-qv2ray-cmake.yml | 2 +- CMakeLists.txt | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 1a6de6b3..e57d6d2b 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -112,7 +112,7 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_TOOLCHAIN_FILE=../libs/${{ matrix.arch }}-windows/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.buildarch }} + cmake .. -A ${{ matrix.buildarch }} cmake --build . --parallel $(nproc) # -------------------------------------------------------- - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Build diff --git a/CMakeLists.txt b/CMakeLists.txt index 4683308e..fef64bf3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,16 @@ if(APPLE) ) endif() +if(WIN32) + if(NOT CMAKE_TOOLCHAIN_FILE) + if(CMAKE_CL_64) + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) + else() + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x86-windows/scripts/buildsystems/vcpkg.cmake) + endif() + endif() +endif() + if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) set(_QV2RAY_BUILD_INFO_STR_ "$ENV{_QV2RAY_BUILD_INFO_}") else() From 3ef3119ef9a235388b3e8079f7619aa79955b7b8 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 09:31:33 +0800 Subject: [PATCH 204/332] update CMakeLists.txt --- CMakeLists.txt | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fef64bf3..1ce138cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,16 @@ message("| Welcome to contribute! |") message("|-------------------------------------------------|") message(" ") +if(WIN32) + if(NOT CMAKE_TOOLCHAIN_FILE) + if(CMAKE_CL_64) + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) + else() + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x86-windows/scripts/buildsystems/vcpkg.cmake) + endif() + endif() +endif() + include(cmake/translations.cmake) include(cmake/qnodeeditor.cmake) include(cmake/singleapplication.cmake) @@ -62,16 +72,6 @@ if(APPLE) ) endif() -if(WIN32) - if(NOT CMAKE_TOOLCHAIN_FILE) - if(CMAKE_CL_64) - set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) - else() - set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x86-windows/scripts/buildsystems/vcpkg.cmake) - endif() - endif() -endif() - if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) set(_QV2RAY_BUILD_INFO_STR_ "$ENV{_QV2RAY_BUILD_INFO_}") else() From 6b9f0d0267d22ba5c4a4a392e4ca717e9c263848 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 09:46:14 +0800 Subject: [PATCH 205/332] Update CMakeLists.txt --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ce138cd..8fec3d5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,11 +40,11 @@ message("|-------------------------------------------------|") message(" ") if(WIN32) - if(NOT CMAKE_TOOLCHAIN_FILE) + if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) if(CMAKE_CL_64) - set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) + include(${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) else() - set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/libs/x86-windows/scripts/buildsystems/vcpkg.cmake) + include(${CMAKE_SOURCE_DIR}/libs/x86-windows/scripts/buildsystems/vcpkg.cmake) endif() endif() endif() From 79eb753d4bacdfbd475449dd96b01a1e83dbbeef Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 10:17:13 +0800 Subject: [PATCH 206/332] cmake: fixing Windows build --- .gitignore | 1 + .gitmodules | 3 --- CMakeLists.txt | 4 +++- src/common/QvTranslator.hpp | 1 + src/components/icmping/win/ICMPPinger.cpp | 3 +-- src/components/icmping/win/ICMPPinger.hpp | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index cc60618a..8ada73fa 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .DS_Store *.pro.user *.user +.vs/ *.qm ./.vscode diff --git a/.gitmodules b/.gitmodules index 34515e2f..1395dfaf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "3rdparty/x2struct"] path = 3rdparty/x2struct url = https://github.com/xyz347/x2struct -[submodule "3rdparty/qhttpserver"] - path = 3rdparty/qhttpserver - url = https://github.com/nikhilm/qhttpserver [submodule "3rdparty/SingleApplication"] path = 3rdparty/SingleApplication url = https://github.com/itay-grudev/SingleApplication diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fec3d5b..30393e3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5.1) +cmake_minimum_required(VERSION 3.10.1) file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/VERSION" QV2RAY_VERSION) file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" QV2RAY_BUILD_VERSION) @@ -40,6 +40,8 @@ message("|-------------------------------------------------|") message(" ") if(WIN32) + add_compile_options("/std:c++17") + add_definitions(-D_HAS_STD_BYTE=0 -D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS) if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) if(CMAKE_CL_64) include(${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) diff --git a/src/common/QvTranslator.hpp b/src/common/QvTranslator.hpp index f5f1dfbe..4b93a197 100644 --- a/src/common/QvTranslator.hpp +++ b/src/common/QvTranslator.hpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace Qv2ray::common { diff --git a/src/components/icmping/win/ICMPPinger.cpp b/src/components/icmping/win/ICMPPinger.cpp index 287c0cf8..f57cee55 100644 --- a/src/components/icmping/win/ICMPPinger.cpp +++ b/src/components/icmping/win/ICMPPinger.cpp @@ -1,6 +1,5 @@ #include "ICMPPinger.hpp" - -#ifdef Q_OS_WIN +#if 0 ICMPPinger::ICMPPinger(UINT64 timeout = DEFAULT_TIMEOUT) { diff --git a/src/components/icmping/win/ICMPPinger.hpp b/src/components/icmping/win/ICMPPinger.hpp index b657767e..5c5ca460 100644 --- a/src/components/icmping/win/ICMPPinger.hpp +++ b/src/components/icmping/win/ICMPPinger.hpp @@ -1,7 +1,7 @@ #pragma once #include - -#ifdef Q_OS_WIN +#include +#if 0 /** * ICMPPinger - An Implementation of ICMPPing on Windows Platform * Required Windows Version: 2000 / XP / 7 / Vista+ From 40879fe7a62e64d5dc71e9ff76b0e519fdfc0b26 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 14:08:54 +0800 Subject: [PATCH 207/332] update --- .github/workflows/build-qv2ray-cmake.yml | 9 ++++++++- CMakeLists.txt | 15 +++++---------- cmake/iconv.cmake | 7 +++++++ cmake/protobuf.cmake | 3 +++ 4 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 cmake/iconv.cmake diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index e57d6d2b..de2091e5 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -88,12 +88,19 @@ jobs: if: matrix.platform == 'windows-latest' run: | curl -o ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z - - name: Win-${{ matrix.arch }} - Build preparation - Extract Dependencies + curl -o ./libs/Qv2ray-deps-libiconv-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-libiconv-${{ matrix.arch }}-windows.7z + - name: Win-${{ matrix.arch }} - gRPC- Build preparation - Extract Dependencies if: matrix.platform == 'windows-latest' uses: DuckSoft/extract-7z-action@v1.0 with: pathSource: ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z pathTarget: ./libs + - name: Win-${{ matrix.arch }} - Iconv- Build preparation - Extract Dependencies + if: matrix.platform == 'windows-latest' + uses: DuckSoft/extract-7z-action@v1.0 + with: + pathSource: ./libs/Qv2ray-deps-libiconv-${{ matrix.arch }}-windows.7z + pathTarget: ./libs # ========================================================================================================= Generate MakeFile and Build - name: macOS - ${{ matrix.qt_version }} - Generate Dependencies and Build shell: bash diff --git a/CMakeLists.txt b/CMakeLists.txt index 30393e3f..2c2480cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ message(" ") if(WIN32) add_compile_options("/std:c++17") add_definitions(-D_HAS_STD_BYTE=0 -D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS) + include(cmake/iconv.cmake) if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) if(CMAKE_CL_64) include(${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) @@ -58,20 +59,14 @@ include(cmake/qzxing.cmake) include(cmake/protobuf.cmake) include(cmake/cpp-httplib.cmake) include(cmake/backend.cmake) + if(APPLE) - find_package(Iconv REQUIRED) + include(cmake/iconv.cmake) set(MACOSX_FRAMEWORK "-framework Carbon" "-framework Cocoa" "-framework Security" ) - set(MACOSX_ICONV_LIBRARY - Iconv::Iconv - ) - - set(MACOSX_ICONV_INCLUDE_PATH - ${Iconv_INCLUDE_DIR} - ) endif() if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) @@ -173,7 +168,7 @@ add_executable(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} ${QT_LIBRARY} ${MACOSX_FRAMEWORK} - ${MACOSX_ICONV_LIBRARY} + ${ICONV_LIBRARY} ${QV2RAY_PROTOBUF_LIBRARY} ${QV2RAY_BACKEND_LIBRARIES} ) @@ -188,7 +183,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE ${QZXING_INCLUDE_PATH} ${SINGLEAPPLICATION_DIR} ${Protobuf_INCLUDE_DIRS} - ${MACOSX_ICONV_INCLUDE_PATH} + ${ICONV_INCLUDE_PATH} ${cpp-httplib_INCLUDE_DIRS} ) diff --git a/cmake/iconv.cmake b/cmake/iconv.cmake new file mode 100644 index 00000000..bf9a6d68 --- /dev/null +++ b/cmake/iconv.cmake @@ -0,0 +1,7 @@ +find_package(Iconv REQUIRED) +set(ICONV_LIBRARY + Iconv::Iconv +) +set(ICONV_INCLUDE_PATH + ${Iconv_INCLUDE_DIR} +) \ No newline at end of file diff --git a/cmake/protobuf.cmake b/cmake/protobuf.cmake index 39573bbd..05d710a2 100644 --- a/cmake/protobuf.cmake +++ b/cmake/protobuf.cmake @@ -1,4 +1,7 @@ find_package(Protobuf REQUIRED) +if(MSVC) + set(Protobuf_USE_STATIC_LIBS ON) +endif() protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${CMAKE_SOURCE_DIR}/tools/v2ray_geosite.proto) set(QV2RAY_PROTOBUF_LIBRARY protobuf::libprotobuf From 3f1204fcdce4be4694cabe74eb2564ce4d18a0ae Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 14:10:55 +0800 Subject: [PATCH 208/332] fix typo --- .github/workflows/build-qv2ray-cmake.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index de2091e5..1358575f 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -89,13 +89,13 @@ jobs: run: | curl -o ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z curl -o ./libs/Qv2ray-deps-libiconv-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-libiconv-${{ matrix.arch }}-windows.7z - - name: Win-${{ matrix.arch }} - gRPC- Build preparation - Extract Dependencies + - name: Win-${{ matrix.arch }} - gRPC - Build preparation - Extract Dependencies if: matrix.platform == 'windows-latest' uses: DuckSoft/extract-7z-action@v1.0 with: pathSource: ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z pathTarget: ./libs - - name: Win-${{ matrix.arch }} - Iconv- Build preparation - Extract Dependencies + - name: Win-${{ matrix.arch }} - Iconv - Build preparation - Extract Dependencies if: matrix.platform == 'windows-latest' uses: DuckSoft/extract-7z-action@v1.0 with: From f330fb1dfab57c8475c6bd93864eac7bf8302589 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 14:27:05 +0800 Subject: [PATCH 209/332] Revert "fix typo" This reverts commit 3f1204fcdce4be4694cabe74eb2564ce4d18a0ae. --- .github/workflows/build-qv2ray-cmake.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 1358575f..de2091e5 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -89,13 +89,13 @@ jobs: run: | curl -o ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z curl -o ./libs/Qv2ray-deps-libiconv-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-libiconv-${{ matrix.arch }}-windows.7z - - name: Win-${{ matrix.arch }} - gRPC - Build preparation - Extract Dependencies + - name: Win-${{ matrix.arch }} - gRPC- Build preparation - Extract Dependencies if: matrix.platform == 'windows-latest' uses: DuckSoft/extract-7z-action@v1.0 with: pathSource: ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z pathTarget: ./libs - - name: Win-${{ matrix.arch }} - Iconv - Build preparation - Extract Dependencies + - name: Win-${{ matrix.arch }} - Iconv- Build preparation - Extract Dependencies if: matrix.platform == 'windows-latest' uses: DuckSoft/extract-7z-action@v1.0 with: From 972a1550baef909246f58a2cfbb25bf464de0360 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 14:27:06 +0800 Subject: [PATCH 210/332] Revert "update" This reverts commit 40879fe7a62e64d5dc71e9ff76b0e519fdfc0b26. --- .github/workflows/build-qv2ray-cmake.yml | 9 +-------- CMakeLists.txt | 15 ++++++++++----- cmake/iconv.cmake | 7 ------- cmake/protobuf.cmake | 3 --- 4 files changed, 11 insertions(+), 23 deletions(-) delete mode 100644 cmake/iconv.cmake diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index de2091e5..e57d6d2b 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -88,19 +88,12 @@ jobs: if: matrix.platform == 'windows-latest' run: | curl -o ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z - curl -o ./libs/Qv2ray-deps-libiconv-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-libiconv-${{ matrix.arch }}-windows.7z - - name: Win-${{ matrix.arch }} - gRPC- Build preparation - Extract Dependencies + - name: Win-${{ matrix.arch }} - Build preparation - Extract Dependencies if: matrix.platform == 'windows-latest' uses: DuckSoft/extract-7z-action@v1.0 with: pathSource: ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z pathTarget: ./libs - - name: Win-${{ matrix.arch }} - Iconv- Build preparation - Extract Dependencies - if: matrix.platform == 'windows-latest' - uses: DuckSoft/extract-7z-action@v1.0 - with: - pathSource: ./libs/Qv2ray-deps-libiconv-${{ matrix.arch }}-windows.7z - pathTarget: ./libs # ========================================================================================================= Generate MakeFile and Build - name: macOS - ${{ matrix.qt_version }} - Generate Dependencies and Build shell: bash diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c2480cf..30393e3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,6 @@ message(" ") if(WIN32) add_compile_options("/std:c++17") add_definitions(-D_HAS_STD_BYTE=0 -D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS) - include(cmake/iconv.cmake) if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) if(CMAKE_CL_64) include(${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) @@ -59,14 +58,20 @@ include(cmake/qzxing.cmake) include(cmake/protobuf.cmake) include(cmake/cpp-httplib.cmake) include(cmake/backend.cmake) - if(APPLE) - include(cmake/iconv.cmake) + find_package(Iconv REQUIRED) set(MACOSX_FRAMEWORK "-framework Carbon" "-framework Cocoa" "-framework Security" ) + set(MACOSX_ICONV_LIBRARY + Iconv::Iconv + ) + + set(MACOSX_ICONV_INCLUDE_PATH + ${Iconv_INCLUDE_DIR} + ) endif() if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) @@ -168,7 +173,7 @@ add_executable(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} ${QT_LIBRARY} ${MACOSX_FRAMEWORK} - ${ICONV_LIBRARY} + ${MACOSX_ICONV_LIBRARY} ${QV2RAY_PROTOBUF_LIBRARY} ${QV2RAY_BACKEND_LIBRARIES} ) @@ -183,7 +188,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE ${QZXING_INCLUDE_PATH} ${SINGLEAPPLICATION_DIR} ${Protobuf_INCLUDE_DIRS} - ${ICONV_INCLUDE_PATH} + ${MACOSX_ICONV_INCLUDE_PATH} ${cpp-httplib_INCLUDE_DIRS} ) diff --git a/cmake/iconv.cmake b/cmake/iconv.cmake deleted file mode 100644 index bf9a6d68..00000000 --- a/cmake/iconv.cmake +++ /dev/null @@ -1,7 +0,0 @@ -find_package(Iconv REQUIRED) -set(ICONV_LIBRARY - Iconv::Iconv -) -set(ICONV_INCLUDE_PATH - ${Iconv_INCLUDE_DIR} -) \ No newline at end of file diff --git a/cmake/protobuf.cmake b/cmake/protobuf.cmake index 05d710a2..39573bbd 100644 --- a/cmake/protobuf.cmake +++ b/cmake/protobuf.cmake @@ -1,7 +1,4 @@ find_package(Protobuf REQUIRED) -if(MSVC) - set(Protobuf_USE_STATIC_LIBS ON) -endif() protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${CMAKE_SOURCE_DIR}/tools/v2ray_geosite.proto) set(QV2RAY_PROTOBUF_LIBRARY protobuf::libprotobuf From 5679ce56d25045c488fbcf914a593662e8fdf029 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 14:33:41 +0800 Subject: [PATCH 211/332] update qzxing.cmake --- cmake/qzxing.cmake | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmake/qzxing.cmake b/cmake/qzxing.cmake index 921622cf..18b4a2f9 100644 --- a/cmake/qzxing.cmake +++ b/cmake/qzxing.cmake @@ -86,4 +86,11 @@ set(QZXING_SOURCES set(QZXING_INCLUDE_PATH ${QZXING_DIR} ${QZXING_DIR}/zxing -) \ No newline at end of file +) +if(MSVC) + list(APPEND QZXING_SOURCES ${QZXING_DIR}/zxing/win32/zxing/win_iconv.c) + list(APPEND QZXING_INCLUDE_PATH + ${QZXING_DIR}/win32/zxing + ${QZXING_DIR}/zxing/win32/zxing/msvc + ) +endif() \ No newline at end of file From c29aeb438bd2e50a3f2814aae93630dfb463c084 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 14:35:08 +0800 Subject: [PATCH 212/332] linking protobuf statically --- cmake/protobuf.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/protobuf.cmake b/cmake/protobuf.cmake index 39573bbd..05d710a2 100644 --- a/cmake/protobuf.cmake +++ b/cmake/protobuf.cmake @@ -1,4 +1,7 @@ find_package(Protobuf REQUIRED) +if(MSVC) + set(Protobuf_USE_STATIC_LIBS ON) +endif() protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${CMAKE_SOURCE_DIR}/tools/v2ray_geosite.proto) set(QV2RAY_PROTOBUF_LIBRARY protobuf::libprotobuf From 3211dae63195739f35130e47c9b338109c73fa0c Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 14:41:59 +0800 Subject: [PATCH 213/332] add definitions __STDC_LIMIT_MACROS --- cmake/qzxing.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/qzxing.cmake b/cmake/qzxing.cmake index 18b4a2f9..1cd70882 100644 --- a/cmake/qzxing.cmake +++ b/cmake/qzxing.cmake @@ -88,6 +88,7 @@ set(QZXING_INCLUDE_PATH ${QZXING_DIR}/zxing ) if(MSVC) + add_definitions(-D__STDC_LIMIT_MACROS) list(APPEND QZXING_SOURCES ${QZXING_DIR}/zxing/win32/zxing/win_iconv.c) list(APPEND QZXING_INCLUDE_PATH ${QZXING_DIR}/win32/zxing From 9c9cdd731afbca3a112443ef537e2b33c5932dc6 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 14:47:38 +0800 Subject: [PATCH 214/332] Revert "linking protobuf statically" This reverts commit c29aeb438bd2e50a3f2814aae93630dfb463c084. --- cmake/protobuf.cmake | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmake/protobuf.cmake b/cmake/protobuf.cmake index 05d710a2..39573bbd 100644 --- a/cmake/protobuf.cmake +++ b/cmake/protobuf.cmake @@ -1,7 +1,4 @@ find_package(Protobuf REQUIRED) -if(MSVC) - set(Protobuf_USE_STATIC_LIBS ON) -endif() protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${CMAKE_SOURCE_DIR}/tools/v2ray_geosite.proto) set(QV2RAY_PROTOBUF_LIBRARY protobuf::libprotobuf From 4db0a5e0dbab081037fd6da7e5578a22b60fba8d Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 14:54:44 +0800 Subject: [PATCH 215/332] fix typo --- cmake/qzxing.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/qzxing.cmake b/cmake/qzxing.cmake index 1cd70882..5fd5e784 100644 --- a/cmake/qzxing.cmake +++ b/cmake/qzxing.cmake @@ -91,7 +91,7 @@ if(MSVC) add_definitions(-D__STDC_LIMIT_MACROS) list(APPEND QZXING_SOURCES ${QZXING_DIR}/zxing/win32/zxing/win_iconv.c) list(APPEND QZXING_INCLUDE_PATH - ${QZXING_DIR}/win32/zxing + ${QZXING_DIR}/zxing/win32/zxing ${QZXING_DIR}/zxing/win32/zxing/msvc ) endif() \ No newline at end of file From 22f02fb2b915df18a5292d2e4b001a472a5d2a3a Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 15:15:47 +0800 Subject: [PATCH 216/332] cmake: add UNICODE define on Windows --- CMakeLists.txt | 1 + src/components/pac/QvPACHandler.hpp | 4 ++-- src/components/proxy/QvProxyConfigurator.cpp | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 30393e3f..7ab0ce91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ message(" ") if(WIN32) add_compile_options("/std:c++17") + add_definitions(-DUNICODE -D_UNICODE) add_definitions(-D_HAS_STD_BYTE=0 -D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS) if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) if(CMAKE_CL_64) diff --git a/src/components/pac/QvPACHandler.hpp b/src/components/pac/QvPACHandler.hpp index ea92cd51..762b15d5 100644 --- a/src/components/pac/QvPACHandler.hpp +++ b/src/components/pac/QvPACHandler.hpp @@ -6,8 +6,8 @@ namespace httplib { class Server; - class Request; - class Response; + struct Request; + struct Response; } // namespace httplib namespace Qv2ray::components::pac diff --git a/src/components/proxy/QvProxyConfigurator.cpp b/src/components/proxy/QvProxyConfigurator.cpp index 16ad2139..e0fa779c 100644 --- a/src/components/proxy/QvProxyConfigurator.cpp +++ b/src/components/proxy/QvProxyConfigurator.cpp @@ -2,9 +2,9 @@ #include "common/QvHelpers.hpp" #ifdef Q_OS_WIN - #include "wininet.h" + #include - #include + #include #endif namespace Qv2ray::components::proxy From 81667e480e28f531cb02b3a3505ca22d4b201464 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 15:35:13 +0800 Subject: [PATCH 217/332] cmake: fixing Windows build --- CMakeLists.txt | 4 ++++ cmake/backend.cmake | 10 +++++++++- src/core/tcping/QvTCPing.cpp | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ab0ce91..2e2ff548 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -221,3 +221,7 @@ if(UNIX AND NOT WIN32) DESTINATION share/qv2ray/translations ) endif() + +if(WIN32) + target_link_libraries(${PROJECT_NAME} wininet wsock32 ws2_32 user32) +endif() diff --git a/cmake/backend.cmake b/cmake/backend.cmake index d710b4fe..7bfa91f6 100644 --- a/cmake/backend.cmake +++ b/cmake/backend.cmake @@ -10,10 +10,18 @@ if(NOT USE_LIBQVB) find_library(UPB_LIBRARY NAMES upb) set(QV2RAY_BACKEND_LIBRARIES ${GRPCPP_LIBRARY} ${GRPC_LIBRARY} ${UPB_LIBRARY}) elseif(WIN32) + find_library(ADDRESS_SORTING NAMES address_sorting) find_library(ABSL_BASE NAMES absl_base) find_library(ABSL_STR NAMES absl_strings) find_library(ABSL_THROW_DELEGATE NAMES absl_throw_delegate) - set(QV2RAY_BACKEND_LIBRARIES ${GRPCPP_LIBRARY} ${GRPC_LIBRARY} ${ABSL_BASE} ${ABSL_STR} ${ABSL_THROW_DELEGATE}) + find_library(GPR_LIBRARY NAMES gpr) + find_library(ZLIB_LIBRARY NAMES zlib) + find_library(UPB_LIBRARY NAMES upb) + find_library(CARES_LIBRARY NAMES cares) + find_library(GRPC_INSECURE_LIBRARY NAMES grpc_unsecure) + find_library(GRPCPP_INSECURE_LIBRARY NAMES grpc++_unsecure) + set(QV2RAY_BACKEND_LIBRARIES ${GRPC_INSECURE_LIBRARY} ${GRPCPP_INSECURE_LIBRARY} ${ABSL_BASE} ${ABSL_STR} ${ADDRESS_SORTING} + ${ABSL_THROW_DELEGATE} ${GPR_LIBRARY} ${ZLIB_LIBRARY} ${UPB_LIBRARY} ${CARES_LIBRARY}) endif() set(API_PROTO "${CMAKE_SOURCE_DIR}/tools/v2ray_api.proto") diff --git a/src/core/tcping/QvTCPing.cpp b/src/core/tcping/QvTCPing.cpp index 6da38249..fa67b118 100644 --- a/src/core/tcping/QvTCPing.cpp +++ b/src/core/tcping/QvTCPing.cpp @@ -199,7 +199,7 @@ namespace Qv2ray::core::tcping if (::connect(fd, addr->ai_addr, addr->ai_addrlen) == 0) { *end = system_clock::now(); -#ifdef _WIN32 +#ifdef Q_OS_WIN closesocket(fd); #else close(fd); From 206e7a13386cd4cfdc05c8a5ba0978fd9c99d7a1 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 15:45:50 +0800 Subject: [PATCH 218/332] using ninja for windows --- .github/workflows/build-qv2ray-cmake.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index e57d6d2b..a576f6c0 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -87,6 +87,7 @@ jobs: shell: bash if: matrix.platform == 'windows-latest' run: | + choco install -y ninja curl -o ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z - name: Win-${{ matrix.arch }} - Build preparation - Extract Dependencies if: matrix.platform == 'windows-latest' @@ -112,7 +113,7 @@ jobs: run: | mkdir build cd build - cmake .. -A ${{ matrix.buildarch }} + cmake .. -GNinja -A ${{ matrix.buildarch }} cmake --build . --parallel $(nproc) # -------------------------------------------------------- - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Build From cba8a028ad50bb4a2bbd054b7549b5c0a3f7af45 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 15:58:28 +0800 Subject: [PATCH 219/332] cmake: CI: try using ninja --- .github/workflows/build-qv2ray-cmake.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index a576f6c0..475cb77b 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -75,13 +75,14 @@ jobs: sudo add-apt-repository ppa:webispy/grpc sudo add-apt-repository ppa:carsten-uppenbrink-net/openssl sudo apt update - sudo apt install -y libgl-dev libx11-dev libxkbcommon-x11-dev libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler libgrpc++-dev protobuf-compiler-grpc tree + sudo apt install -y libgl-dev libx11-dev libxkbcommon-x11-dev libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler libgrpc++-dev protobuf-compiler-grpc tree ninja-build # -------------------------------------------------------- - name: macOS - ${{ matrix.qt_version }} - Build preparation - Install Packages if: matrix.platform == 'macos-latest' run: | brew install protobuf brew install grpc + brew install ninja # -------------------------------------------------------- - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Build preparation - Download Dependencies shell: bash @@ -102,7 +103,7 @@ jobs: run: | mkdir build cd build - cmake .. + cmake .. -GNinja cmake --build . --parallel $(sysctl -n hw.logicalcpu) sudo cmake --install . sudo chmod -Rv a+rw ./ @@ -113,7 +114,7 @@ jobs: run: | mkdir build cd build - cmake .. -GNinja -A ${{ matrix.buildarch }} + cmake .. -GNinja cmake --build . --parallel $(nproc) # -------------------------------------------------------- - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Build @@ -125,7 +126,7 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_INSTALL_PREFIX=./AppDir/usr + cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./AppDir/usr cmake --build . --parallel $(nproc) cmake --install . # ========================================================================================================= Build From f457be96db224541449663cfb7a4026aae7ca498 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 16:05:25 +0800 Subject: [PATCH 220/332] cmake: CI: try using ninja - Windows CL.exe --- .github/workflows/build-qv2ray-cmake.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 475cb77b..e78dadd9 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -111,6 +111,9 @@ jobs: - name: Windows - ${{ matrix.qt_version }} - Generate Dependencies and Build shell: bash if: matrix.platform == 'windows-latest' + env: + CC: cl.exe + CXX: cl.exe run: | mkdir build cd build From 9c69552ff9b71b41f3811586e4ec2a2b8c5c3aa7 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 16:31:13 +0800 Subject: [PATCH 221/332] cmake: CI: update Windows build script --- .github/workflows/build-qv2ray-cmake.yml | 4 ++++ .github/workflows/copy_DLLs.bat | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index e78dadd9..836a7655 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -204,7 +204,11 @@ jobs: run: | set VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\ cd build + mkdir release cd release + mkdir lang + copy ..\qv2ray.exe .\ + copy ..\*.qm .\lang del *.cpp *.h *.o *.qrc *.qm *.hpp *.obj windeployqt ./qv2ray.exe --compiler-runtime --verbose 2 - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Create 7z Release diff --git a/.github/workflows/copy_DLLs.bat b/.github/workflows/copy_DLLs.bat index f4771566..c5afc78e 100644 --- a/.github/workflows/copy_DLLs.bat +++ b/.github/workflows/copy_DLLs.bat @@ -1,5 +1,5 @@ @echo off echo Copying DLLs for Windows -forfiles /s /p %GITHUB_WORKSPACE%\libs\x86-windows\bin\ /m "*.dll" /c "cmd.exe /c copy @file %GITHUB_WORKSPACE%\build\release\" -forfiles /s /p %GITHUB_WORKSPACE%\libs\x64-windows\bin\ /m "*.dll" /c "cmd.exe /c copy @file %GITHUB_WORKSPACE%\build\release\" +forfiles /s /p %GITHUB_WORKSPACE%\libs\x86-windows\installed\x86-windows\bin\ /m "*.dll" /c "cmd.exe /c copy @file %GITHUB_WORKSPACE%\build\release\" +forfiles /s /p %GITHUB_WORKSPACE%\libs\x64-windows\installed\x64-windows\bin\ /m "*.dll" /c "cmd.exe /c copy @file %GITHUB_WORKSPACE%\build\release\" exit 0 From 6726046a6cdabcb99e72736c677278d11e13689a Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 16:32:20 +0800 Subject: [PATCH 222/332] Reeeevert "cmake: CI: update Windows build script" This reverts commit 9c69552ff9b71b41f3811586e4ec2a2b8c5c3aa7. --- .github/workflows/build-qv2ray-cmake.yml | 4 ---- .github/workflows/copy_DLLs.bat | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 836a7655..e78dadd9 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -204,11 +204,7 @@ jobs: run: | set VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\ cd build - mkdir release cd release - mkdir lang - copy ..\qv2ray.exe .\ - copy ..\*.qm .\lang del *.cpp *.h *.o *.qrc *.qm *.hpp *.obj windeployqt ./qv2ray.exe --compiler-runtime --verbose 2 - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Create 7z Release diff --git a/.github/workflows/copy_DLLs.bat b/.github/workflows/copy_DLLs.bat index c5afc78e..f4771566 100644 --- a/.github/workflows/copy_DLLs.bat +++ b/.github/workflows/copy_DLLs.bat @@ -1,5 +1,5 @@ @echo off echo Copying DLLs for Windows -forfiles /s /p %GITHUB_WORKSPACE%\libs\x86-windows\installed\x86-windows\bin\ /m "*.dll" /c "cmd.exe /c copy @file %GITHUB_WORKSPACE%\build\release\" -forfiles /s /p %GITHUB_WORKSPACE%\libs\x64-windows\installed\x64-windows\bin\ /m "*.dll" /c "cmd.exe /c copy @file %GITHUB_WORKSPACE%\build\release\" +forfiles /s /p %GITHUB_WORKSPACE%\libs\x86-windows\bin\ /m "*.dll" /c "cmd.exe /c copy @file %GITHUB_WORKSPACE%\build\release\" +forfiles /s /p %GITHUB_WORKSPACE%\libs\x64-windows\bin\ /m "*.dll" /c "cmd.exe /c copy @file %GITHUB_WORKSPACE%\build\release\" exit 0 From 07409a11a07445ebef63a45aee3e3007f9409d82 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sun, 8 Mar 2020 16:41:27 +0800 Subject: [PATCH 223/332] "translations" => "lang" (#398) * Update QvTranslator.cpp * Update CMakeLists.txt: $prefix/share/qv2ray/{translations => lang} X-Approved-By: @ymshenyu --- CMakeLists.txt | 2 +- src/common/QvTranslator.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e2ff548..cd4b27a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -218,7 +218,7 @@ endif() if(UNIX AND NOT WIN32) install(FILES ${QM_FILES} - DESTINATION share/qv2ray/translations + DESTINATION share/qv2ray/lang ) endif() diff --git a/src/common/QvTranslator.cpp b/src/common/QvTranslator.cpp index de8b11ee..abe7e2c3 100644 --- a/src/common/QvTranslator.cpp +++ b/src/common/QvTranslator.cpp @@ -45,14 +45,14 @@ namespace Qv2ray::common // path searching list. QStringList searchPaths = { // 1st: application dir - QApplication::applicationDirPath() + "/translations", + QApplication::applicationDirPath() + "/lang", #ifdef QV2RAY_TRANSLATION_PATH // 2nd: platform-specific dir QString(QV2RAY_TRANSLATION_PATH), #endif }; // 3rd: standard path dirs - searchPaths << QStandardPaths::locateAll(QStandardPaths::DataLocation, "translations", QStandardPaths::LocateDirectory); + searchPaths << QStandardPaths::locateAll(QStandardPaths::DataLocation, "lang", QStandardPaths::LocateDirectory); // // iterate through the paths for (auto path : searchPaths) From 4865885f31bc69bab7c1f188a4b9cd9c43302b6c Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 17:21:20 +0800 Subject: [PATCH 224/332] cmake: testing Windows deployment --- .github/workflows/build-qv2ray-cmake.yml | 8 +++--- CMakeLists.txt | 36 ++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index e78dadd9..564ef149 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -117,8 +117,9 @@ jobs: run: | mkdir build cd build - cmake .. -GNinja + cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./deployment cmake --build . --parallel $(nproc) + cmake --install . # -------------------------------------------------------- - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Build if: matrix.platform == 'ubuntu-16.04' @@ -204,14 +205,13 @@ jobs: run: | set VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\ cd build - cd release - del *.cpp *.h *.o *.qrc *.qm *.hpp *.obj + cd deployment windeployqt ./qv2ray.exe --compiler-runtime --verbose 2 - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Create 7z Release if: matrix.platform == 'windows-latest' uses: DuckSoft/create-7z-action@v1.0 with: - pathSource: ./build/release/ + pathSource: ./build/deployment/ pathTarget: ./release.7z - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Uploading artifact if: matrix.platform == 'windows-latest' diff --git a/CMakeLists.txt b/CMakeLists.txt index cd4b27a5..93b35442 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,7 +198,7 @@ if(APPLE) include(cmake/macdeploy.cmake) endif() -if(UNIX AND NOT APPLE) +if(UNIX AND NOT APPLE AND NOT WIN32) install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin @@ -214,9 +214,7 @@ if(UNIX AND NOT APPLE) install(FILES assets/icons/qv2ray.png DESTINATION share/icons/hicolor/256x256/apps/ ) -endif() -if(UNIX AND NOT WIN32) install(FILES ${QM_FILES} DESTINATION share/qv2ray/lang ) @@ -224,4 +222,36 @@ endif() if(WIN32) target_link_libraries(${PROJECT_NAME} wininet wsock32 ws2_32 user32) + install(TARGETS ${PROJECT_NAME} + RUNTIME + DESTINATION . + ) + install(FILES ${QM_FILES} + DESTINATION lang + ) + + set(prefix "${PROJECT_NAME}.exe") + set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${prefix}") + + # Directories to look for dependencies + set(DIRS "${CMAKE_BINARY_DIR}") + # Path used for searching by FIND_XXX(), with appropriate suffixes added + if(CMAKE_PREFIX_PATH) + foreach(dir ${CMAKE_PREFIX_PATH}) + list(APPEND DIRS "${dir}/bin" "${dir}/lib") + endforeach() + endif() + + # Append Qt's lib folder which is two levels above Qt5Widgets_DIR + list(APPEND DIRS "${Qt5Widgets_DIR}/../..") + + include(InstallRequiredSystemLibraries) + + message(STATUS "APPS: ${APPS}") + message(STATUS "QT_PLUGINS: ${QT_PLUGINS}") + message(STATUS "DIRS: ${DIRS}") + + install(CODE "include(BundleUtilities) + fixup_bundle(\"${APPS}\" \"${QT_PLUGINS}\" \"${DIRS}\")") + endif() From 5c8606a2f3f81ab748a1013a65f9013e8cdfea0d Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 17:28:04 +0800 Subject: [PATCH 225/332] install libssl for windows --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 93b35442..2eb3ae0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,6 +230,11 @@ if(WIN32) DESTINATION lang ) + find_package(OpenSSL REQUIRED) + install(FILES OpenSSL::SSL OpenSSL::Crypto + DESTINATION . + ) + set(prefix "${PROJECT_NAME}.exe") set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${prefix}") From 27036add8b2b50e49e3351bf43472401e59710bb Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 17:37:11 +0800 Subject: [PATCH 226/332] cmake: CI: use release build --- .github/workflows/build-qv2ray-cmake.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 564ef149..02f41e87 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -103,7 +103,7 @@ jobs: run: | mkdir build cd build - cmake .. -GNinja + cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release cmake --build . --parallel $(sysctl -n hw.logicalcpu) sudo cmake --install . sudo chmod -Rv a+rw ./ @@ -117,7 +117,7 @@ jobs: run: | mkdir build cd build - cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./deployment + cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./deployment -DCMAKE_BUILD_TYPE=Release cmake --build . --parallel $(nproc) cmake --install . # -------------------------------------------------------- @@ -130,7 +130,7 @@ jobs: run: | mkdir build cd build - cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./AppDir/usr + cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./AppDir/usr -DCMAKE_BUILD_TYPE=Release cmake --build . --parallel $(nproc) cmake --install . # ========================================================================================================= Build From e44e34ebf39dc936996072b3e0c885c4df21256f Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 17:37:14 +0800 Subject: [PATCH 227/332] update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2eb3ae0d..64f045a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -231,7 +231,7 @@ if(WIN32) ) find_package(OpenSSL REQUIRED) - install(FILES OpenSSL::SSL OpenSSL::Crypto + install(FILES ${OPENSSL_LIBRARIES} DESTINATION . ) From a349bb21c612ef70568dc394d36dee4aad80bcfe Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 17:49:05 +0800 Subject: [PATCH 228/332] cmake: CI: auto deployment --- CMakeLists.txt | 27 +++------------------------ cmake/macdeploy.cmake | 27 +++------------------------ deployment.cmake | 23 +++++++++++++++++++++++ 3 files changed, 29 insertions(+), 48 deletions(-) create mode 100644 deployment.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 64f045a0..213ae6c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,6 +196,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE if(APPLE) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) include(cmake/macdeploy.cmake) + include(deployment.cmake) endif() if(UNIX AND NOT APPLE AND NOT WIN32) @@ -235,28 +236,6 @@ if(WIN32) DESTINATION . ) - set(prefix "${PROJECT_NAME}.exe") - set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${prefix}") - - # Directories to look for dependencies - set(DIRS "${CMAKE_BINARY_DIR}") - # Path used for searching by FIND_XXX(), with appropriate suffixes added - if(CMAKE_PREFIX_PATH) - foreach(dir ${CMAKE_PREFIX_PATH}) - list(APPEND DIRS "${dir}/bin" "${dir}/lib") - endforeach() - endif() - - # Append Qt's lib folder which is two levels above Qt5Widgets_DIR - list(APPEND DIRS "${Qt5Widgets_DIR}/../..") - - include(InstallRequiredSystemLibraries) - - message(STATUS "APPS: ${APPS}") - message(STATUS "QT_PLUGINS: ${QT_PLUGINS}") - message(STATUS "DIRS: ${DIRS}") - - install(CODE "include(BundleUtilities) - fixup_bundle(\"${APPS}\" \"${QT_PLUGINS}\" \"${DIRS}\")") - + set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe") + include(deployment.cmake) endif() diff --git a/cmake/macdeploy.cmake b/cmake/macdeploy.cmake index d886bcb0..dc996741 100644 --- a/cmake/macdeploy.cmake +++ b/cmake/macdeploy.cmake @@ -32,30 +32,9 @@ install(TARGETS ${PROJECT_NAME} ) install(FILES ${CMAKE_SOURCE_DIR}/assets/info.plist DESTINATION "${prefix}" ) install(FILES ${CMAKE_SOURCE_DIR}/assets/icons/qv2ray.icns DESTINATION "${INSTALL_CMAKE_DIR}" ) +install(FILES ${QM_FILES} + DESTINATION ${INSTALL_CMAKE_DIR}/lang +) # Note Mac specific extension .app set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.app") - -# Directories to look for dependencies -set(DIRS "${CMAKE_BINARY_DIR}") - -# Path used for searching by FIND_XXX(), with appropriate suffixes added -if(CMAKE_PREFIX_PATH) - foreach(dir ${CMAKE_PREFIX_PATH}) - list(APPEND DIRS "${dir}/bin" "${dir}/lib") - endforeach() -endif() - -# Append Qt's lib folder which is two levels above Qt5Widgets_DIR -list(APPEND DIRS "${Qt5Widgets_DIR}/../..") -list(APPEND DIRS "/usr/local/lib") -list(APPEND DIRS "/usr/lib") - -include(InstallRequiredSystemLibraries) - -message(STATUS "APPS: ${APPS}") -message(STATUS "QT_PLUGINS: ${QT_PLUGINS}") -message(STATUS "DIRS: ${DIRS}") - -install(CODE "include(BundleUtilities) - fixup_bundle(\"${APPS}\" \"${QT_PLUGINS}\" \"${DIRS}\")") diff --git a/deployment.cmake b/deployment.cmake new file mode 100644 index 00000000..9178160d --- /dev/null +++ b/deployment.cmake @@ -0,0 +1,23 @@ +# Directories to look for dependencies +set(DIRS "${CMAKE_BINARY_DIR}") + +# Path used for searching by FIND_XXX(), with appropriate suffixes added +if(CMAKE_PREFIX_PATH) + foreach(dir ${CMAKE_PREFIX_PATH}) + list(APPEND DIRS "${dir}/bin" "${dir}/lib") + endforeach() +endif() + +# Append Qt's lib folder which is two levels above Qt5Widgets_DIR +list(APPEND DIRS "${Qt5Widgets_DIR}/../..") +list(APPEND DIRS "/usr/local/lib") +list(APPEND DIRS "/usr/lib") + +include(InstallRequiredSystemLibraries) + +message(STATUS "APPS: ${APPS}") +message(STATUS "QT_PLUGINS: ${QT_PLUGINS}") +message(STATUS "DIRS: ${DIRS}") + +install(CODE "include(BundleUtilities) + fixup_bundle(\"${APPS}\" \"${QT_PLUGINS}\" \"${DIRS}\")") From c673243d17af942b01b843e46f5ce4500189a3c2 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 18:02:14 +0800 Subject: [PATCH 229/332] update CMakeLists.txt --- CMakeLists.txt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 213ae6c3..6ceec49c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -231,8 +231,21 @@ if(WIN32) DESTINATION lang ) - find_package(OpenSSL REQUIRED) - install(FILES ${OPENSSL_LIBRARIES} + find_library(SSL_LIBRARY + NAMES "libssl-1_1.dll" "libssl-1_1-x64.dll" + PATH_SUFFIXES bin + ) + + find_library(CRYPTO_LIBRARY + NAMES "libcrypto-1_1.dll" "libcrypto-1_1-x64.dll" + PATH_SUFFIXES bin + ) + + install(FILES ${SSL_LIBRARY} + DESTINATION . + ) + + install(FILES ${CRYPTO_LIBRARY} DESTINATION . ) From fde9cbf02710b6bbd2f6488fd168ae78b35aee3a Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 18:03:29 +0800 Subject: [PATCH 230/332] cmake: CI: auto deployment - macOS use macdeployqt --- .github/workflows/build-qv2ray-cmake.yml | 3 +- CMakeLists.txt | 13 +++++++- cmake/macdeploy.cmake | 40 ------------------------ 3 files changed, 14 insertions(+), 42 deletions(-) delete mode 100644 cmake/macdeploy.cmake diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 02f41e87..03bc7549 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -179,7 +179,8 @@ jobs: if: matrix.platform == 'macos-latest' run: | cd build - tar czf Qv2ray.app.tar.gz qv2ray.app + macdeployqt ./qv2ray.app + tar czvf Qv2ray.app.tar.gz qv2ray.app - name: macOS - ${{ matrix.qt_version }} - Uploading Artifact if: matrix.platform == 'macos-latest' uses: actions/upload-artifact@master diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ceec49c..f0798228 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,7 +195,18 @@ target_include_directories(${PROJECT_NAME} PRIVATE if(APPLE) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) - include(cmake/macdeploy.cmake) + set(prefix "${PROJECT_NAME}.app/Contents") + set(INSTALL_RUNTIME_DIR "${prefix}/MacOS") + set(INSTALL_CMAKE_DIR "${prefix}/Resources") + + # Destination paths below are relative to ${CMAKE_INSTALL_PREFIX} + install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} ) + install(FILES ${CMAKE_SOURCE_DIR}/assets/info.plist DESTINATION "${prefix}" ) + install(FILES ${CMAKE_SOURCE_DIR}/assets/icons/qv2ray.icns DESTINATION "${INSTALL_CMAKE_DIR}" ) + install(FILES ${QM_FILES} DESTINATION ${INSTALL_CMAKE_DIR}/lang) + + # Note Mac specific extension .app + set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.app") include(deployment.cmake) endif() diff --git a/cmake/macdeploy.cmake b/cmake/macdeploy.cmake deleted file mode 100644 index dc996741..00000000 --- a/cmake/macdeploy.cmake +++ /dev/null @@ -1,40 +0,0 @@ -set(prefix "${PROJECT_NAME}.app/Contents") -set(INSTALL_RUNTIME_DIR "${prefix}/MacOS") -set(INSTALL_CMAKE_DIR "${prefix}/Resources") - -# based on code from CMake's QtDialog/CMakeLists.txt -macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var _prefix) - get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION) - if(EXISTS "${_qt_plugin_path}") - get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME) - get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH) - get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME) - set(_qt_plugin_dest "${_prefix}/PlugIns/${_qt_plugin_type}") - install(FILES "${_qt_plugin_path}" - DESTINATION "${_qt_plugin_dest}") - set(${_qt_plugins_var} - "${${_qt_plugins_var}};\$ENV{DEST_DIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}") - else() - message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found") - endif() -endmacro() - -install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS ${prefix}) -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" - "[Paths]\nPlugins = ${_qt_plugin_dir}\n") -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" - DESTINATION "${INSTALL_CMAKE_DIR}") - -# Destination paths below are relative to ${CMAKE_INSTALL_PREFIX} -install(TARGETS ${PROJECT_NAME} - BUNDLE DESTINATION . COMPONENT Runtime - RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} COMPONENT Runtime - ) -install(FILES ${CMAKE_SOURCE_DIR}/assets/info.plist DESTINATION "${prefix}" ) -install(FILES ${CMAKE_SOURCE_DIR}/assets/icons/qv2ray.icns DESTINATION "${INSTALL_CMAKE_DIR}" ) -install(FILES ${QM_FILES} - DESTINATION ${INSTALL_CMAKE_DIR}/lang -) - -# Note Mac specific extension .app -set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.app") From ee3757e8dafe783ea5cabe9d0415e5df24074ce9 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 18:12:56 +0800 Subject: [PATCH 231/332] Revert "update CMakeLists.txt" This reverts commit c673243d17af942b01b843e46f5ce4500189a3c2. --- CMakeLists.txt | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f0798228..1d461e8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -242,21 +242,8 @@ if(WIN32) DESTINATION lang ) - find_library(SSL_LIBRARY - NAMES "libssl-1_1.dll" "libssl-1_1-x64.dll" - PATH_SUFFIXES bin - ) - - find_library(CRYPTO_LIBRARY - NAMES "libcrypto-1_1.dll" "libcrypto-1_1-x64.dll" - PATH_SUFFIXES bin - ) - - install(FILES ${SSL_LIBRARY} - DESTINATION . - ) - - install(FILES ${CRYPTO_LIBRARY} + find_package(OpenSSL REQUIRED) + install(FILES ${OPENSSL_LIBRARIES} DESTINATION . ) From ce3353da04cf144116e13386b455bc5ebdf2a0de Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 18:14:12 +0800 Subject: [PATCH 232/332] set CMAKE_FIND_LIBRARY_SUFFIXES to dll --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d461e8b..63d02063 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -242,6 +242,7 @@ if(WIN32) DESTINATION lang ) + set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") find_package(OpenSSL REQUIRED) install(FILES ${OPENSSL_LIBRARIES} DESTINATION . From a4dea25089292e8bd76f3b25928c3e16790aa9d1 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 18:35:37 +0800 Subject: [PATCH 233/332] update CMakeLists.txt --- CMakeLists.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 63d02063..ee559e60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,18 @@ add_definitions(-D_QV2RAY_BUILD_EXTRA_INFO_STR_="${_QV2RAY_BUILD_EXTRA_INFO_STR_ message("Qv2ray build info: ${_QV2RAY_BUILD_INFO_STR_}") message("Qv2ray build info ex: ${_QV2RAY_BUILD_EXTRA_INFO_STR_}") +if(DEFINED QV2RAY_DEFAULT_VASSETS_PATH) + add_definitions(-DQV2RAY_DEFAULT_VASSETS_PATH=${QV2RAY_DEFAULT_VASSETS_PATH}) +endif() + +if(DEFINED QV2RAY_DEFAULT_VCORE_PATH) + add_definitions(-DQV2RAY_DEFAULT_VCORE_PATH=${QV2RAY_DEFAULT_VCORE_PATH}) +endif() + +if(DEFINED QV2RAY_TRANSLATION_PATH) + add_definitions(-DQV2RAY_TRANSLATION_PATH=${QV2RAY_TRANSLATION_PATH}) +endif() + set(QV2RAY_SOURCES src/base/Qv2rayLog.cpp src/common/CommandArgs.cpp From 923caa43c88373589d793c31a3ddb8d852024d6a Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 18:39:52 +0800 Subject: [PATCH 234/332] fix typo --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee559e60..f60e7163 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,15 +93,15 @@ message("Qv2ray build info: ${_QV2RAY_BUILD_INFO_STR_}") message("Qv2ray build info ex: ${_QV2RAY_BUILD_EXTRA_INFO_STR_}") if(DEFINED QV2RAY_DEFAULT_VASSETS_PATH) - add_definitions(-DQV2RAY_DEFAULT_VASSETS_PATH=${QV2RAY_DEFAULT_VASSETS_PATH}) + add_definitions(-DQV2RAY_DEFAULT_VASSETS_PATH="${QV2RAY_DEFAULT_VASSETS_PATH}") endif() if(DEFINED QV2RAY_DEFAULT_VCORE_PATH) - add_definitions(-DQV2RAY_DEFAULT_VCORE_PATH=${QV2RAY_DEFAULT_VCORE_PATH}) + add_definitions(-DQV2RAY_DEFAULT_VCORE_PATH="${QV2RAY_DEFAULT_VCORE_PATH}") endif() if(DEFINED QV2RAY_TRANSLATION_PATH) - add_definitions(-DQV2RAY_TRANSLATION_PATH=${QV2RAY_TRANSLATION_PATH}) + add_definitions(-DQV2RAY_TRANSLATION_PATH="${QV2RAY_TRANSLATION_PATH}") endif() set(QV2RAY_SOURCES From dbf242795b385d72da79e95f13b0389feb1789fd Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 19:23:38 +0800 Subject: [PATCH 235/332] update snapcraft --- snap/plugins/x-cmake.py | 173 ++++++++++++++++++++++++++++++++++++++++ snap/plugins/x_qmake.py | 155 ----------------------------------- snap/snapcraft.yaml | 13 +-- 3 files changed, 181 insertions(+), 160 deletions(-) create mode 100644 snap/plugins/x-cmake.py delete mode 100644 snap/plugins/x_qmake.py diff --git a/snap/plugins/x-cmake.py b/snap/plugins/x-cmake.py new file mode 100644 index 00000000..f24f7d20 --- /dev/null +++ b/snap/plugins/x-cmake.py @@ -0,0 +1,173 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2015-2016 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""The cmake plugin is useful for building cmake based parts. + +These are projects that have a CMakeLists.txt that drives the build. +The plugin requires a CMakeLists.txt in the root of the source tree. + +If the part has a list of build-snaps listed, the part will be set up in +such a way that the paths to those snaps are used as paths for find_package +and find_library by use of `CMAKE_FIND_ROOT_PATH``. +This plugin uses the common plugin keywords as well as those for "sources". +For more information check the 'plugins' topic for the former and the +'sources' topic for the latter. + +Additionally, this plugin uses the following plugin-specific keywords: + + - configflags: + (list of strings) + configure flags to pass to the build using the common cmake semantics. +""" + +import logging +import os +from typing import List, Optional +import subprocess + +import snapcraft +from snapcraft.internal import errors + + +logger = logging.getLogger(name=__name__) + + +class _Flag: + def __str__(self) -> str: + if self.value is None: + flag = self.name + else: + flag = "{}={}".format(self.name, self.value) + return flag + + def __init__(self, flag: str) -> None: + parts = flag.split("=") + self.name = parts[0] + try: + self.value: Optional[str] = parts[1] + except IndexError: + self.value = None + + +class CMakePlugin(snapcraft.BasePlugin): + @classmethod + def schema(cls): + schema = super().schema() + schema["properties"]["configflags"] = { + "type": "array", + "minitems": 1, + "uniqueItems": True, + "items": {"type": "string"}, + "default": [], + } + # For backwards compatibility + schema["properties"]["make-parameters"] = { + "type": "array", + "minitems": 1, + "uniqueItems": True, + "items": {"type": "string"}, + "default": [], + } + schema["required"] = ["source"] + + return schema + + @classmethod + def get_build_properties(cls): + # Inform Snapcraft of the properties associated with building. If these + # change in the YAML Snapcraft will consider the build step dirty. + return super().get_build_properties() + ["configflags"] + + def __init__(self, name, options, project): + super().__init__(name, options, project) + # self.build_packages.append("cmake") + self.out_of_source_build = True + + cmd = ''' + echo 'deb http://archive.neon.kde.org/unstable bionic main' > /etc/apt/sources.list.d/neon.list + echo 'deb http://ppa.launchpad.net/ymshenyu/grpc-1/ubuntu bionic main' > /etc/apt/sources.list.d/grpc.list + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E6D4736255751E5D + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 281f24e574404629aa3bda1a4f10c386c55cdb04 + sudo apt update -qq + ''' + + subprocess.call(cmd, shell=True) + + if project.info.get_build_base() not in ("core", "core16", "core18"): + raise errors.PluginBaseError( + part_name=self.name, base=project.info.get_build_base() + ) + + if options.make_parameters: + logger.warning("make-paramaters is deprecated, ignoring.") + + def build(self): + source_subdir = getattr(self.options, "source_subdir", None) + if source_subdir: + sourcedir = os.path.join(self.sourcedir, source_subdir) + else: + sourcedir = self.sourcedir + + env = self._build_environment() + configflags = self._get_processed_flags() + + self.run(["cmake", sourcedir, "-DCMAKE_INSTALL_PREFIX="] + configflags, env=env) + + # TODO: there is a better way to specify the job count on newer versions of cmake + # https://github.com/Kitware/CMake/commit/1ab3881ec9e809ac5f6cad5cd84048310b8683e2 + self.run( + ["cmake", "--build", ".", "--", "-j{}".format(self.parallel_build_count)], + env=env, + ) + + self.run(["cmake", "--build", ".", "--target", "install"], env=env) + + def _get_processed_flags(self) -> List[str]: + # Return the original if no build_snaps are in options. + if not self.options.build_snaps: + return self.options.configflags + + build_snap_paths = [ + os.path.join(os.path.sep, "snap", snap_name.split("/")[0], "current") + for snap_name in self.options.build_snaps + ] + + flags = [_Flag(f) for f in self.options.configflags] + for flag in flags: + if flag.name == "-DCMAKE_FIND_ROOT_PATH": + flag.value = "{};{}".format(flag.value, ";".join(build_snap_paths)) + break + else: + flags.append( + _Flag("-DCMAKE_FIND_ROOT_PATH={}".format(";".join(build_snap_paths))) + ) + + return [str(f) for f in flags] + + def _build_environment(self): + env = os.environ.copy() + env["DESTDIR"] = self.installdir + env["CMAKE_PREFIX_PATH"] = "$CMAKE_PREFIX_PATH:{}".format( + self.project.stage_dir + ) + env["CMAKE_INCLUDE_PATH"] = "$CMAKE_INCLUDE_PATH:" + ":".join( + ["{0}/include", "{0}/usr/include", "{0}/include/{1}", "{0}/usr/include/{1}"] + ).format(self.project.stage_dir, self.project.arch_triplet) + env["CMAKE_LIBRARY_PATH"] = "$CMAKE_LIBRARY_PATH:" + ":".join( + ["{0}/lib", "{0}/usr/lib", "{0}/lib/{1}", "{0}/usr/lib/{1}"] + ).format(self.project.stage_dir, self.project.arch_triplet) + + return env diff --git a/snap/plugins/x_qmake.py b/snap/plugins/x_qmake.py deleted file mode 100644 index c4d68357..00000000 --- a/snap/plugins/x_qmake.py +++ /dev/null @@ -1,155 +0,0 @@ -# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- -# -# Copyright (C) 2016-2018 Canonical Ltd -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3 as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""The qmake plugin is useful for building qmake-based parts. - -These are projects that are built using .pro files. - -This plugin uses the common plugin keywords as well as those for "sources". -For more information check the 'plugins' topic for the former and the -'sources' topic for the latter. - -Additionally, this plugin uses the following plugin-specific keywords: - - - options: - (list of strings) - additional options to pass to the qmake invocation. - - qt-version: - (string; default: qt5) - Version of Qt to use with qmake. Valid options are: qt4 and qt5 - - project-files: - (list of strings) - list of .pro files to pass to the qmake invocation. -""" - -import os -import subprocess -import snapcraft -from snapcraft import common -from snapcraft.internal import errors - - -class QmakePlugin(snapcraft.BasePlugin): - @classmethod - def schema(cls): - schema = super().schema() - schema["properties"]["options"] = { - "type": "array", - "minitems": 1, - "uniqueItems": True, - "items": {"type": "string"}, - "default": [], - } - schema["properties"]["qt-version"] = { - "type": "string", - "enum": ["qt4", "qt5"], - "default": "qt5", - } - schema["properties"]["project-files"] = { - "type": "array", - "minitems": 1, - "uniqueItems": True, - "items": {"type": "string"}, - "default": [], - } - - schema["required"] = ["source"] - - return schema - - @classmethod - def get_pull_properties(cls): - # Inform Snapcraft of the properties associated with pulling. If these - # change in the YAML Snapcraft will consider the pull step dirty. - return ["qt-version"] - - @classmethod - def get_build_properties(cls): - # Inform Snapcraft of the properties associated with building. If these - # change in the YAML Snapcraft will consider the build step dirty. - return ["options", "project-files"] - - def __init__(self, name, options, project): - super().__init__(name, options, project) - - if project.info.get_build_base() not in ("core", "core16", "core18"): - raise errors.PluginBaseError( - part_name=self.name, base=project.info.get_build_base() - ) - - cmd = ''' - echo 'deb http://archive.neon.kde.org/unstable bionic main' > /etc/apt/sources.list.d/neon.list - echo 'deb http://ppa.launchpad.net/ymshenyu/grpc-1/ubuntu bionic main' > /etc/apt/sources.list.d/grpc.list - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E6D4736255751E5D - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 281f24e574404629aa3bda1a4f10c386c55cdb04 - sudo apt update -qq - ''' - - subprocess.call(cmd, shell=True) - - self.build_packages.append("make") - if self.options.qt_version == "qt5": - self.build_packages.extend(["qt5-qmake", "qtbase5-dev"]) - elif self.options.qt_version == "qt4": - self.build_packages.extend(["qt4-qmake", "libqt4-dev"]) - else: - raise RuntimeError( - "Unsupported Qt version: {!r}".format(self.options.qt_version) - ) - - def build(self): - super().build() - - env = self._build_environment() - - sources = [] - if self.options.project_files: - sourcedir = self.sourcedir - source_subdir = getattr(self.options, "source_subdir", None) - if source_subdir: - sourcedir = os.path.join(sourcedir, source_subdir) - sources = [ - os.path.join(sourcedir, project_file) - for project_file in self.options.project_files - ] - - self.run( - ["qmake"] + self._extra_config() + self.options.options + sources, env=env - ) - - self.run(["make", "-j{}".format(self.parallel_build_count)], env=env) - - self.run(["make", "install", "INSTALL_ROOT=" + self.installdir], env=env) - - def _extra_config(self): - extra_config = [] - - for root in [self.installdir, self.project.stage_dir]: - paths = common.get_library_paths(root, self.project.arch_triplet) - for path in paths: - extra_config.append('LIBS+="-L{}"'.format(path)) - - paths = common.get_include_paths(root, self.project.arch_triplet) - for path in paths: - extra_config.append('INCLUDEPATH+="{}"'.format(path)) - - return extra_config - - def _build_environment(self): - env = os.environ.copy() - env["QT_SELECT"] = self.options.qt_version - - return env diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 2f682cb7..f738f747 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -46,7 +46,7 @@ apps: parts: qv2ray: - plugin: x-qmake + plugin: x-cmake source-type: git source: . parse-info: [usr/share/metainfo/qv2ray.metainfo.xml] @@ -57,6 +57,8 @@ parts: - libgrpc++-dev - libprotobuf-dev - protobuf-compiler-grpc + build-snaps: + - cmake/stable stage-packages: - libgcc1 - libstdc++6 @@ -68,10 +70,11 @@ parts: - libqt5network5 - libqt5widgets5 - libglib2.0-bin - options: - - PREFIX=/usr - - CONFIG+=with_metainfo - - CONFIG+=use_grpc + configflags: + - -DCMAKE_INSTALL_PREFIX=/usr + - -DQV2RAY_TRANSLATION_PATH="/usr/share/qv2ray/lang" + - -DCMAKE_BUILD_TYPE=Release + - -GNinja override-pull: | snapcraftctl pull build_number=$(cat makespec/BUILDVERSION) From 826e7c604e74e8c3baa078d18ac13f83bd7c2f5d Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 19:27:24 +0800 Subject: [PATCH 236/332] rename plugin --- snap/plugins/{x-cmake.py => x_cmake.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename snap/plugins/{x-cmake.py => x_cmake.py} (100%) diff --git a/snap/plugins/x-cmake.py b/snap/plugins/x_cmake.py similarity index 100% rename from snap/plugins/x-cmake.py rename to snap/plugins/x_cmake.py From 265d6ff8be27a0e0fe1f9268136a42a217adbe7b Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 19:40:11 +0800 Subject: [PATCH 237/332] using cmake from ubuntu --- snap/plugins/x_cmake.py | 3 ++- snap/snapcraft.yaml | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/snap/plugins/x_cmake.py b/snap/plugins/x_cmake.py index f24f7d20..0a5c2db8 100644 --- a/snap/plugins/x_cmake.py +++ b/snap/plugins/x_cmake.py @@ -93,7 +93,8 @@ class CMakePlugin(snapcraft.BasePlugin): def __init__(self, name, options, project): super().__init__(name, options, project) - # self.build_packages.append("cmake") + self.build_packages.append("cmake") + self.build_packages.append("ninja-build") self.out_of_source_build = True cmd = ''' diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index f738f747..5fb55a53 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -57,8 +57,6 @@ parts: - libgrpc++-dev - libprotobuf-dev - protobuf-compiler-grpc - build-snaps: - - cmake/stable stage-packages: - libgcc1 - libstdc++6 From 9423b8138902b5a58c294634365046cca660b00b Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 20:01:05 +0800 Subject: [PATCH 238/332] add missing build packages - 1 --- snap/snapcraft.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 5fb55a53..138b5dc8 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -53,6 +53,7 @@ parts: build-packages: - build-essential - qttools5-dev-tools + - qttools5-dev - qt5-default - libgrpc++-dev - libprotobuf-dev From ca7e2862b640aaf1886721afa710a17fc9ebfa40 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 20:10:56 +0800 Subject: [PATCH 239/332] cmake: update action --- .github/workflows/build-qv2ray-cmake.yml | 12 ------- CMakeLists.txt | 43 +++++++----------------- 2 files changed, 12 insertions(+), 43 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 03bc7549..e5a1a967 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -179,7 +179,6 @@ jobs: if: matrix.platform == 'macos-latest' run: | cd build - macdeployqt ./qv2ray.app tar czvf Qv2ray.app.tar.gz qv2ray.app - name: macOS - ${{ matrix.qt_version }} - Uploading Artifact if: matrix.platform == 'macos-latest' @@ -197,17 +196,6 @@ jobs: tag: ${{ github.ref }} overwrite: true # -------------------------------------------------------- - - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Copying DLLs to build output folders - if: matrix.platform == 'windows-latest' - run: .\.github\workflows\copy_DLLs.bat - - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Running windeployqt - if: matrix.platform == 'windows-latest' - shell: cmd - run: | - set VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\ - cd build - cd deployment - windeployqt ./qv2ray.exe --compiler-runtime --verbose 2 - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Create 7z Release if: matrix.platform == 'windows-latest' uses: DuckSoft/create-7z-action@v1.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index f60e7163..640a2a4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,53 +213,34 @@ if(APPLE) # Destination paths below are relative to ${CMAKE_INSTALL_PREFIX} install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} ) - install(FILES ${CMAKE_SOURCE_DIR}/assets/info.plist DESTINATION "${prefix}" ) + install(FILES ${CMAKE_SOURCE_DIR}/assets/Info.plist DESTINATION "${prefix}" ) install(FILES ${CMAKE_SOURCE_DIR}/assets/icons/qv2ray.icns DESTINATION "${INSTALL_CMAKE_DIR}" ) install(FILES ${QM_FILES} DESTINATION ${INSTALL_CMAKE_DIR}/lang) - # Note Mac specific extension .app + # Call macdeployqt + install(CODE "execute_process(COMMAND macdeployqt ${PROJECT_NAME}.app)") set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.app") include(deployment.cmake) endif() if(UNIX AND NOT APPLE AND NOT WIN32) - install(TARGETS ${PROJECT_NAME} - RUNTIME - DESTINATION bin - ) - install(FILES assets/qv2ray.metainfo.xml - DESTINATION share/metainfo - ) - - install(FILES assets/qv2ray.desktop - DESTINATION share/applications - ) - - install(FILES assets/icons/qv2ray.png - DESTINATION share/icons/hicolor/256x256/apps/ - ) - - install(FILES ${QM_FILES} - DESTINATION share/qv2ray/lang - ) + install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) + install(FILES assets/qv2ray.metainfo.xml DESTINATION share/metainfo) + install(FILES assets/qv2ray.desktop DESTINATION share/applications) + install(FILES assets/icons/qv2ray.png DESTINATION share/icons/hicolor/256x256/apps/) + install(FILES ${QM_FILES} DESTINATION share/qv2ray/lang) endif() if(WIN32) target_link_libraries(${PROJECT_NAME} wininet wsock32 ws2_32 user32) - install(TARGETS ${PROJECT_NAME} - RUNTIME - DESTINATION . - ) - install(FILES ${QM_FILES} - DESTINATION lang - ) + install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION .) + install(FILES ${QM_FILES} DESTINATION lang) set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") find_package(OpenSSL REQUIRED) - install(FILES ${OPENSSL_LIBRARIES} - DESTINATION . - ) + install(FILES ${OPENSSL_LIBRARIES} DESTINATION .) + install(CODE "execute_process(COMMAND windeployqt ${PROJECT_NAME}.exe --compiler-runtime --verbose 2)") set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe") include(deployment.cmake) endif() From bd63164781945562de20991fd8cbdf351fdc0f2c Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 20:12:42 +0800 Subject: [PATCH 240/332] cmake: CI: remove unused action step --- .github/workflows/build-qv2ray-cmake.yml | 6 ------ .github/workflows/copy_DLLs.bat | 5 ----- 2 files changed, 11 deletions(-) delete mode 100644 .github/workflows/copy_DLLs.bat diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index e5a1a967..6b51e3a6 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -133,12 +133,6 @@ jobs: cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./AppDir/usr -DCMAKE_BUILD_TYPE=Release cmake --build . --parallel $(nproc) cmake --install . -# ========================================================================================================= Build - - name: Inspect Build Output - shell: bash - run: | - cd build - tree || true # ========================================================================================================= Deployments - name: Linux - ${{ matrix.qt_version }} - Generating AppImage if: matrix.platform == 'ubuntu-16.04' diff --git a/.github/workflows/copy_DLLs.bat b/.github/workflows/copy_DLLs.bat deleted file mode 100644 index f4771566..00000000 --- a/.github/workflows/copy_DLLs.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off -echo Copying DLLs for Windows -forfiles /s /p %GITHUB_WORKSPACE%\libs\x86-windows\bin\ /m "*.dll" /c "cmd.exe /c copy @file %GITHUB_WORKSPACE%\build\release\" -forfiles /s /p %GITHUB_WORKSPACE%\libs\x64-windows\bin\ /m "*.dll" /c "cmd.exe /c copy @file %GITHUB_WORKSPACE%\build\release\" -exit 0 From 480f41861a25e9300a59b6d0c29d9a93617b1525 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 20:11:47 +0800 Subject: [PATCH 241/332] fix snapcraft - 1 --- snap/snapcraft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 138b5dc8..855026bd 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -71,7 +71,7 @@ parts: - libglib2.0-bin configflags: - -DCMAKE_INSTALL_PREFIX=/usr - - -DQV2RAY_TRANSLATION_PATH="/usr/share/qv2ray/lang" + - -DQV2RAY_TRANSLATION_PATH=/usr/share/qv2ray/lang - -DCMAKE_BUILD_TYPE=Release - -GNinja override-pull: | From 8e398f054884326906bec3c28a3af04dcc724db4 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 21:20:22 +0800 Subject: [PATCH 242/332] cmake: fixing windows deployment issue --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 640a2a4c..d1958dab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -240,7 +240,7 @@ if(WIN32) find_package(OpenSSL REQUIRED) install(FILES ${OPENSSL_LIBRARIES} DESTINATION .) - install(CODE "execute_process(COMMAND windeployqt ${PROJECT_NAME}.exe --compiler-runtime --verbose 2)") + install(CODE "execute_process(COMMAND windeployqt ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe --compiler-runtime --verbose 2)") set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe") include(deployment.cmake) endif() From 511c994366a3cbde5ac24d5b506b799875181505 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 21:25:35 +0800 Subject: [PATCH 243/332] CMakeLists.txt --- CMakeLists.txt | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d1958dab..a31b0259 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -236,9 +236,24 @@ if(WIN32) install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION .) install(FILES ${QM_FILES} DESTINATION lang) - set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") - find_package(OpenSSL REQUIRED) - install(FILES ${OPENSSL_LIBRARIES} DESTINATION .) + find_library(OPENSSL_SSL_LIBRARY + NAMES + ssl-1_1-x64 + ssl-1_1 + PATH_SUFFIXES + bin + ) + + find_library(OPENSSL_CRYPTO_LIBRARY + NAMES + crypto-1_1-x64 + crypto-1_1 + PATH_SUFFIXES + bin + ) + + install(FILES ${OPENSSL_SSL_LIBRARY}) + install(FILES ${OPENSSL_CRYPTO_LIBRARY}) install(CODE "execute_process(COMMAND windeployqt ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe --compiler-runtime --verbose 2)") set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe") From b4373acc48037d477ad577cacd6901bacf0764b8 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 21:29:20 +0800 Subject: [PATCH 244/332] fix typo --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a31b0259..13f44768 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -252,8 +252,8 @@ if(WIN32) bin ) - install(FILES ${OPENSSL_SSL_LIBRARY}) - install(FILES ${OPENSSL_CRYPTO_LIBRARY}) + install(FILES ${OPENSSL_SSL_LIBRARY} DESTINATION .) + install(FILES ${OPENSSL_CRYPTO_LIBRARY} DESTINATION .) install(CODE "execute_process(COMMAND windeployqt ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe --compiler-runtime --verbose 2)") set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe") From 5c2003947c6f74469bf6aa39c046edb1510645c5 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 21:33:56 +0800 Subject: [PATCH 245/332] add -pthread to cxx flags for linux --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 13f44768..ca3a6864 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,10 @@ if(WIN32) endif() endif() +if(UNIX AND NOT APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") +endif() + include(cmake/translations.cmake) include(cmake/qnodeeditor.cmake) include(cmake/singleapplication.cmake) From 581aa2e66229a549ab98734a9fd021fb0a93213e Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 21:43:51 +0800 Subject: [PATCH 246/332] update CMakeLists.txt --- CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca3a6864..803e0f1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -244,6 +244,9 @@ if(WIN32) NAMES ssl-1_1-x64 ssl-1_1 + PATHS + ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET} + ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/debug PATH_SUFFIXES bin ) @@ -252,10 +255,13 @@ if(WIN32) NAMES crypto-1_1-x64 crypto-1_1 + PATHS + ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET} + ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/debug PATH_SUFFIXES bin ) - + message(${OPENSSL_SSL_LIBRARY}) install(FILES ${OPENSSL_SSL_LIBRARY} DESTINATION .) install(FILES ${OPENSSL_CRYPTO_LIBRARY} DESTINATION .) From 0ea6157b2183e6b0e94fdd300f404c934e96ab28 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 21:51:40 +0800 Subject: [PATCH 247/332] update CMakeLists.txt --- CMakeLists.txt | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 803e0f1f..b6a1e271 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -244,22 +244,16 @@ if(WIN32) NAMES ssl-1_1-x64 ssl-1_1 - PATHS - ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET} - ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/debug - PATH_SUFFIXES - bin + HINTS + ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin ) find_library(OPENSSL_CRYPTO_LIBRARY NAMES crypto-1_1-x64 crypto-1_1 - PATHS - ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET} - ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/debug - PATH_SUFFIXES - bin + HINTS + ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin ) message(${OPENSSL_SSL_LIBRARY}) install(FILES ${OPENSSL_SSL_LIBRARY} DESTINATION .) From f3e7008f9790fa9fc1c0bf217efff53834996493 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 22:01:11 +0800 Subject: [PATCH 248/332] update CMakeLists.txt --- CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b6a1e271..00519141 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -242,18 +242,20 @@ if(WIN32) find_library(OPENSSL_SSL_LIBRARY NAMES - ssl-1_1-x64 - ssl-1_1 - HINTS + "libssl-1_1-x64.dll" + "libssl-1_1.dll" + PATHS ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin + NO_DEFAULT_PATH ) find_library(OPENSSL_CRYPTO_LIBRARY NAMES - crypto-1_1-x64 - crypto-1_1 - HINTS + "libcrypto-1_1-x64.dll" + "libcrypto-1_1.dll" + PATHS ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin + NO_DEFAULT_PATH ) message(${OPENSSL_SSL_LIBRARY}) install(FILES ${OPENSSL_SSL_LIBRARY} DESTINATION .) From 6bb1d1e0f05dde4bede1ca3f2f3a465c0b1553c4 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 22:04:42 +0800 Subject: [PATCH 249/332] fix typo --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 00519141..bf484fe7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -245,7 +245,7 @@ if(WIN32) "libssl-1_1-x64.dll" "libssl-1_1.dll" PATHS - ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin + "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin" NO_DEFAULT_PATH ) @@ -254,7 +254,7 @@ if(WIN32) "libcrypto-1_1-x64.dll" "libcrypto-1_1.dll" PATHS - ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin + "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin" NO_DEFAULT_PATH ) message(${OPENSSL_SSL_LIBRARY}) From 2fe62c3fdbac2516c1ea7dd92bc36883e105a5ce Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 22:24:51 +0800 Subject: [PATCH 250/332] update CMakeLists.txt --- CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf484fe7..55b68c03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -244,18 +244,12 @@ if(WIN32) NAMES "libssl-1_1-x64.dll" "libssl-1_1.dll" - PATHS - "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin" - NO_DEFAULT_PATH ) find_library(OPENSSL_CRYPTO_LIBRARY NAMES "libcrypto-1_1-x64.dll" "libcrypto-1_1.dll" - PATHS - "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin" - NO_DEFAULT_PATH ) message(${OPENSSL_SSL_LIBRARY}) install(FILES ${OPENSSL_SSL_LIBRARY} DESTINATION .) From 550d1b808374e8e0a85978d6cf0e8bf3fbbc9f39 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Sun, 8 Mar 2020 22:37:01 +0800 Subject: [PATCH 251/332] update CMakeLists.txt --- CMakeLists.txt | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 55b68c03..1c3f2636 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -239,21 +239,14 @@ if(WIN32) target_link_libraries(${PROJECT_NAME} wininet wsock32 ws2_32 user32) install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION .) install(FILES ${QM_FILES} DESTINATION lang) - - find_library(OPENSSL_SSL_LIBRARY - NAMES - "libssl-1_1-x64.dll" - "libssl-1_1.dll" - ) - - find_library(OPENSSL_CRYPTO_LIBRARY - NAMES - "libcrypto-1_1-x64.dll" - "libcrypto-1_1.dll" - ) - message(${OPENSSL_SSL_LIBRARY}) - install(FILES ${OPENSSL_SSL_LIBRARY} DESTINATION .) - install(FILES ${OPENSSL_CRYPTO_LIBRARY} DESTINATION .) + + if(CMAKE_CL_64) + install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libssl-1_1-x64.dll DESTINATION .) + install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libcrypto-1_1-x64.dll DESTINATION .) + else() + install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libssl-1_1.dll DESTINATION .) + install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libcrypto-1_1.dll DESTINATION .) + endif() install(CODE "execute_process(COMMAND windeployqt ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe --compiler-runtime --verbose 2)") set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe") From 9a251a71630b237e1e381884e097ed7c7f06fafc Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 22:54:29 +0800 Subject: [PATCH 252/332] cmake: finalizing cmake migration --- CMakeLists.txt | 46 +++++++++++++++++++++++++++++------------ assets/qv2ray.rc | 48 +++++++++++++++++++++++++++++++++++++++++++ makespec/BUILDVERSION | 2 +- 3 files changed, 82 insertions(+), 14 deletions(-) create mode 100644 assets/qv2ray.rc diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c3f2636..46d62168 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,21 @@ file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" QV2RAY_BUILD_VERSION) set(PACKAGE_VERSION "${QV2RAY_VERSION}.${QV2RAY_BUILD_VERSION}") project(qv2ray) + +set(VERSION_LIST ${PACKAGE_VERSION}) +string(REPLACE "." ";" VERSION_LIST ${VERSION_LIST}) +separate_arguments(VERSION_LIST) + +list(GET VERSION_LIST 0 QV2RAY_VERSION_MAJOR) +list(GET VERSION_LIST 1 QV2RAY_VERSION_MINOR) +list(GET VERSION_LIST 2 QV2RAY_VERSION_BUGFIX) +list(GET VERSION_LIST 3 QV2RAY_VERSION_BUILD) + +add_definitions(-DQV2RAY_VERSION_MAJOR=${QV2RAY_VERSION_MAJOR}) +add_definitions(-DQV2RAY_VERSION_MINOR=${QV2RAY_VERSION_MINOR}) +add_definitions(-DQV2RAY_VERSION_BUGFIX=${QV2RAY_VERSION_BUGFIX}) +add_definitions(-DQV2RAY_VERSION_BUILD=${QV2RAY_VERSION_BUILD}) + add_definitions(-DQV2RAY_VERSION_STRING="v${PACKAGE_VERSION}") add_definitions(-DXTOSTRUCT_QT) @@ -43,6 +58,7 @@ if(WIN32) add_compile_options("/std:c++17") add_definitions(-DUNICODE -D_UNICODE) add_definitions(-D_HAS_STD_BYTE=0 -D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS) + set(GUI_TYPE WIN32) if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) if(CMAKE_CL_64) include(${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake) @@ -63,20 +79,22 @@ include(cmake/qzxing.cmake) include(cmake/protobuf.cmake) include(cmake/cpp-httplib.cmake) include(cmake/backend.cmake) -if(APPLE) - find_package(Iconv REQUIRED) - set(MACOSX_FRAMEWORK - "-framework Carbon" - "-framework Cocoa" - "-framework Security" - ) - set(MACOSX_ICONV_LIBRARY - Iconv::Iconv - ) - set(MACOSX_ICONV_INCLUDE_PATH - ${Iconv_INCLUDE_DIR} - ) +if(APPLE) + set(GUI_TYPE MACOSX_BUNDLE) + find_package(Iconv REQUIRED) + set(MACOSX_FRAMEWORK + "-framework Carbon" + "-framework Cocoa" + "-framework Security" + ) + set(MACOSX_ICONV_LIBRARY + Iconv::Iconv + ) + + set(MACOSX_ICONV_INCLUDE_PATH + ${Iconv_INCLUDE_DIR} + ) endif() if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) @@ -162,6 +180,7 @@ set(QV2RAY_SOURCES src/ui/w_PreferencesWindow.cpp src/ui/w_ScreenShot_Core.cpp src/ui/w_SubscriptionManager.cpp + assets/qv2ray.rc ) set(QRC_RESOURCES ${CMAKE_SOURCE_DIR}/resources.qrc) @@ -174,6 +193,7 @@ set(QT_LIBRARY ) add_executable(${PROJECT_NAME} + ${GUI_TYPE} ${QV2RAY_SOURCES} ${QNODEEDITOR_SOURCES} ${QNODEEDITOR_QRC_RESOURCES} diff --git a/assets/qv2ray.rc b/assets/qv2ray.rc new file mode 100644 index 00000000..93479262 --- /dev/null +++ b/assets/qv2ray.rc @@ -0,0 +1,48 @@ +#ifdef _WIN32 +#include +#include +#include + +#define xstr(s) str(s) +#define str(s) #s + +#define VER_FILEVERSION QV2RAY_VERSION_MAJOR,QV2RAY_VERSION_MINOR,QV2RAY_VERSION_BUGFIX,QV2RAY_VERSION_BUILD +#define VER_FILEVERSION_STR xstr(VER_FILEVERSION) +#define VER_PRODUCTVERSION VER_FILEVERSION +#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR + +IDI_ICON1 ICON DISCARDABLE "assets\\icons\\qv2ray.ico" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VER_FILEVERSION + PRODUCTVERSION VER_PRODUCTVERSION + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Qv2ray Workgroup\0" + VALUE "FileDescription", "Qv2ray, a cross-platform v2ray GUI client.\0" + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "LegalCopyright", "Qv2ray is being distributed under GPLv3\0" + VALUE "OriginalFilename", "qv2ray.exe\0" + VALUE "ProductName", "Qv2ray\0" + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1200 + END + END +/* End of Version info */ +#endif diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 90d39491..9bcafcbd 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4562 +4600 From 1a4da4ddcba8dd92f424d30a844dd86087e64cd0 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 22:57:39 +0800 Subject: [PATCH 253/332] Update CMakeLists.txt --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 46d62168..1d613f0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,6 @@ include(cmake/cpp-httplib.cmake) include(cmake/backend.cmake) if(APPLE) - set(GUI_TYPE MACOSX_BUNDLE) find_package(Iconv REQUIRED) set(MACOSX_FRAMEWORK "-framework Carbon" From af68906b55b44e888edae96050a51adeae8c1cf4 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sun, 8 Mar 2020 22:58:54 +0800 Subject: [PATCH 254/332] [fix] move misplaced tooltip, fixed #397 (#400) --- src/ui/w_MainWindow.ui | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 650007f2..c05dfcd9 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -20,7 +20,7 @@ Qv2ray - Click to toggle show/hide + @@ -246,9 +246,9 @@ 0 - -194 - 480 - 752 + 0 + 459 + 784 @@ -363,6 +363,9 @@ Qt::NoFocus + + Click to toggle show/hide + Text-align:left; From d79f7385e179eb9397fd32828334a44b17dc4956 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sun, 8 Mar 2020 23:17:33 +0800 Subject: [PATCH 255/332] Update snapcraft.yaml Fix QV2RAY_TRANSLATION_PATH --- snap/snapcraft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 855026bd..138b5dc8 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -71,7 +71,7 @@ parts: - libglib2.0-bin configflags: - -DCMAKE_INSTALL_PREFIX=/usr - - -DQV2RAY_TRANSLATION_PATH=/usr/share/qv2ray/lang + - -DQV2RAY_TRANSLATION_PATH="/usr/share/qv2ray/lang" - -DCMAKE_BUILD_TYPE=Release - -GNinja override-pull: | From 59e26dc666c683f6bfafa8c0c1a14b06891b1bef Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sun, 8 Mar 2020 23:20:43 +0800 Subject: [PATCH 256/332] Update build-qv2ray-cmake.yml Fix QV2RAY_TRANSLATION_PATH --- .github/workflows/build-qv2ray-cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 6b51e3a6..b2c3015d 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -130,7 +130,7 @@ jobs: run: | mkdir build cd build - cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./AppDir/usr -DCMAKE_BUILD_TYPE=Release + cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./AppDir/usr -DCMAKE_BUILD_TYPE=Release -DQV2RAY_TRANSLATION_PATH="/usr/share/qv2ray/lang" cmake --build . --parallel $(nproc) cmake --install . # ========================================================================================================= Deployments From 72029a74e908c15135dc349c4f6b050a370c898e Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sun, 8 Mar 2020 23:40:52 +0800 Subject: [PATCH 257/332] Update snapcraft.yaml (#401) Had No Way But To Merge This - TravisCI is too stupid to recognise this --- snap/snapcraft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 138b5dc8..3f64b87f 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -71,7 +71,7 @@ parts: - libglib2.0-bin configflags: - -DCMAKE_INSTALL_PREFIX=/usr - - -DQV2RAY_TRANSLATION_PATH="/usr/share/qv2ray/lang" + - -DQV2RAY_TRANSLATION_PATH="\"/usr/share/qv2ray/lang\"" - -DCMAKE_BUILD_TYPE=Release - -GNinja override-pull: | From b917dbf8b976221f7c49e3b0a985f376c88ffc96 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sun, 8 Mar 2020 23:48:12 +0800 Subject: [PATCH 258/332] AppImage translation dir hacks --- .github/workflows/build-qv2ray-cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index b2c3015d..ab358772 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -130,7 +130,7 @@ jobs: run: | mkdir build cd build - cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./AppDir/usr -DCMAKE_BUILD_TYPE=Release -DQV2RAY_TRANSLATION_PATH="/usr/share/qv2ray/lang" + cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./AppDir/usr -DCMAKE_BUILD_TYPE=Release -DQV2RAY_TRANSLATION_PATH=QApplication::applicationDirPath\(\)+"../../share/qv2ray/lang" cmake --build . --parallel $(nproc) cmake --install . # ========================================================================================================= Deployments From 1035b195930dd2971acdb3b260e135f3cf27cf41 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 8 Mar 2020 23:50:12 +0800 Subject: [PATCH 259/332] cmake: add ui files into CMakeLists --- CMakeLists.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d613f0d..cfc1af9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,6 +179,21 @@ set(QV2RAY_SOURCES src/ui/w_PreferencesWindow.cpp src/ui/w_ScreenShot_Core.cpp src/ui/w_SubscriptionManager.cpp + # ui files + src/ui/w_ExportConfig.ui + src/ui/w_SubscriptionManager.ui + src/ui/editors/w_OutboundEditor.ui + src/ui/editors/w_InboundEditor.ui + src/ui/editors/w_JsonEditor.ui + src/ui/editors/w_RoutesEditor.ui + src/ui/w_ImportConfig.ui + src/ui/widgets/StreamSettingsWidget.ui + src/ui/widgets/ConnectionInfoWidget.ui + src/ui/widgets/ConnectionItemWidget.ui + src/ui/w_MainWindow.ui + src/ui/w_PreferencesWindow.ui + src/ui/w_ScreenShot_Core.ui + assets/qv2ray.rc ) From 38bea9a6875c30d8c75fc5ec5a0e1aee2cc45f33 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sun, 8 Mar 2020 23:55:12 +0800 Subject: [PATCH 260/332] Fight agaist snapcraft (3) --- snap/snapcraft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 3f64b87f..7f158e20 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -71,7 +71,7 @@ parts: - libglib2.0-bin configflags: - -DCMAKE_INSTALL_PREFIX=/usr - - -DQV2RAY_TRANSLATION_PATH="\"/usr/share/qv2ray/lang\"" + - '-DQV2RAY_TRANSLATION_PATH="/usr/share/qv2ray/lang"' - -DCMAKE_BUILD_TYPE=Release - -GNinja override-pull: | From 80483738b1eb512e067fc9a28acf284a99c25f08 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Mon, 9 Mar 2020 00:12:21 +0800 Subject: [PATCH 261/332] hardcode translations path for Linux systems partially solves the stupid snapcraft problem --- snap/snapcraft.yaml | 1 - src/common/QvTranslator.cpp | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 7f158e20..225259c8 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -71,7 +71,6 @@ parts: - libglib2.0-bin configflags: - -DCMAKE_INSTALL_PREFIX=/usr - - '-DQV2RAY_TRANSLATION_PATH="/usr/share/qv2ray/lang"' - -DCMAKE_BUILD_TYPE=Release - -GNinja override-pull: | diff --git a/src/common/QvTranslator.cpp b/src/common/QvTranslator.cpp index abe7e2c3..7ed30d55 100644 --- a/src/common/QvTranslator.cpp +++ b/src/common/QvTranslator.cpp @@ -49,6 +49,10 @@ namespace Qv2ray::common #ifdef QV2RAY_TRANSLATION_PATH // 2nd: platform-specific dir QString(QV2RAY_TRANSLATION_PATH), +#endif +#ifdef Q_OS_LINUX + // 2.5: hard-coded path for Linux systems + QString("/usr/share/qv2ray/lang"), #endif }; // 3rd: standard path dirs From 0ab247deca7975959297366a53831e43d1dc4277 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Mon, 9 Mar 2020 00:21:27 +0800 Subject: [PATCH 262/332] [fix] update AppImage translation search path --- .github/workflows/build-qv2ray-cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index ab358772..a9592f59 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -130,7 +130,7 @@ jobs: run: | mkdir build cd build - cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./AppDir/usr -DCMAKE_BUILD_TYPE=Release -DQV2RAY_TRANSLATION_PATH=QApplication::applicationDirPath\(\)+"../../share/qv2ray/lang" + cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./AppDir/usr -DCMAKE_BUILD_TYPE=Release -DQV2RAY_TRANSLATION_PATH=QApplication::applicationDirPath\(\)+"/../share/qv2ray/lang" cmake --build . --parallel $(nproc) cmake --install . # ========================================================================================================= Deployments From cc069e34b175ef785d74373ddaa9a8685704cc54 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Mon, 9 Mar 2020 10:42:56 +0800 Subject: [PATCH 263/332] add embed translations support --- CMakeLists.txt | 21 +++++++++++++++++---- src/common/QvTranslator.cpp | 3 +++ translations/translations.qrc | 8 ++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 translations/translations.qrc diff --git a/CMakeLists.txt b/CMakeLists.txt index cfc1af9a..a332244d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,7 +132,6 @@ set(QV2RAY_SOURCES src/common/LogHighlighter.cpp src/common/QJsonModel.cpp src/common/QvHelpers.cpp - src/common/QvTranslator.cpp src/components/autolaunch/QvAutoLaunch.cpp src/components/geosite/QvGeositeReader.cpp src/components/icmping/win/ICMPPinger.cpp @@ -197,6 +196,14 @@ set(QV2RAY_SOURCES assets/qv2ray.rc ) +if(NOT EMBED_TRANSLATIONS) + list(APPEND QV2RAY_SOURCES src/common/QvTranslator.cpp) +else() + add_definitions(-DEMBED_TRANSLATIONS) + configure_file(translations/translations.qrc ${CMAKE_BINARY_DIR} COPYONLY) + list(APPEND QV2RAY_SOURCES ${CMAKE_BINARY_DIR}/translations.qrc) +endif() + set(QRC_RESOURCES ${CMAKE_SOURCE_DIR}/resources.qrc) set(QT_LIBRARY @@ -253,7 +260,9 @@ if(APPLE) install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} ) install(FILES ${CMAKE_SOURCE_DIR}/assets/Info.plist DESTINATION "${prefix}" ) install(FILES ${CMAKE_SOURCE_DIR}/assets/icons/qv2ray.icns DESTINATION "${INSTALL_CMAKE_DIR}" ) - install(FILES ${QM_FILES} DESTINATION ${INSTALL_CMAKE_DIR}/lang) + if(NOT EMBED_TRANSLATIONS) + install(FILES ${QM_FILES} DESTINATION ${INSTALL_CMAKE_DIR}/lang) + endif() # Call macdeployqt install(CODE "execute_process(COMMAND macdeployqt ${PROJECT_NAME}.app)") @@ -266,13 +275,17 @@ if(UNIX AND NOT APPLE AND NOT WIN32) install(FILES assets/qv2ray.metainfo.xml DESTINATION share/metainfo) install(FILES assets/qv2ray.desktop DESTINATION share/applications) install(FILES assets/icons/qv2ray.png DESTINATION share/icons/hicolor/256x256/apps/) - install(FILES ${QM_FILES} DESTINATION share/qv2ray/lang) + if(NOT EMBED_TRANSLATIONS) + install(FILES ${QM_FILES} DESTINATION share/qv2ray/lang) + endif() endif() if(WIN32) target_link_libraries(${PROJECT_NAME} wininet wsock32 ws2_32 user32) install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION .) - install(FILES ${QM_FILES} DESTINATION lang) + if(NOT EMBED_TRANSLATIONS) + install(FILES ${QM_FILES} DESTINATION lang) + endif() if(CMAKE_CL_64) install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libssl-1_1-x64.dll DESTINATION .) diff --git a/src/common/QvTranslator.cpp b/src/common/QvTranslator.cpp index 7ed30d55..2aeb71c3 100644 --- a/src/common/QvTranslator.cpp +++ b/src/common/QvTranslator.cpp @@ -46,6 +46,9 @@ namespace Qv2ray::common QStringList searchPaths = { // 1st: application dir QApplication::applicationDirPath() + "/lang", +#ifdef EMBED_TRANSLATIONS + QString(":/translations/"), +#endif #ifdef QV2RAY_TRANSLATION_PATH // 2nd: platform-specific dir QString(QV2RAY_TRANSLATION_PATH), diff --git a/translations/translations.qrc b/translations/translations.qrc new file mode 100644 index 00000000..677e4294 --- /dev/null +++ b/translations/translations.qrc @@ -0,0 +1,8 @@ + + + en_US.qm + ru_RU.qm + ja_JP.qm + zh_CN.qm + + \ No newline at end of file From f6b844ad9c6590ea919dfea422ded8098cd9e351 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Mon, 9 Mar 2020 10:46:32 +0800 Subject: [PATCH 264/332] update --- CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a332244d..b2875720 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,6 +132,7 @@ set(QV2RAY_SOURCES src/common/LogHighlighter.cpp src/common/QJsonModel.cpp src/common/QvHelpers.cpp + src/common/QvTranslator.cpp src/components/autolaunch/QvAutoLaunch.cpp src/components/geosite/QvGeositeReader.cpp src/components/icmping/win/ICMPPinger.cpp @@ -196,9 +197,7 @@ set(QV2RAY_SOURCES assets/qv2ray.rc ) -if(NOT EMBED_TRANSLATIONS) - list(APPEND QV2RAY_SOURCES src/common/QvTranslator.cpp) -else() +if(EMBED_TRANSLATIONS) add_definitions(-DEMBED_TRANSLATIONS) configure_file(translations/translations.qrc ${CMAKE_BINARY_DIR} COPYONLY) list(APPEND QV2RAY_SOURCES ${CMAKE_BINARY_DIR}/translations.qrc) From ba6df9c1224e13bfe087b9d71ac1676d96f7c28c Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Mon, 9 Mar 2020 12:08:16 +0800 Subject: [PATCH 265/332] update CMakeLists.txt --- CMakeLists.txt | 10 +++------- cmake/FindOpenSSL.cmake | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 cmake/FindOpenSSL.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index cfc1af9a..c799904e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -274,13 +274,9 @@ if(WIN32) install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION .) install(FILES ${QM_FILES} DESTINATION lang) - if(CMAKE_CL_64) - install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libssl-1_1-x64.dll DESTINATION .) - install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libcrypto-1_1-x64.dll DESTINATION .) - else() - install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libssl-1_1.dll DESTINATION .) - install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libcrypto-1_1.dll DESTINATION .) - endif() + include(cmake/FindOpenSSL.cmake) + install(FILES ${SSL_LIBRARY} DESTINATION .) + install(FILES ${CRYPTO_LIBRARY} DESTINATION .) install(CODE "execute_process(COMMAND windeployqt ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe --compiler-runtime --verbose 2)") set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe") diff --git a/cmake/FindOpenSSL.cmake b/cmake/FindOpenSSL.cmake new file mode 100644 index 00000000..d865bd23 --- /dev/null +++ b/cmake/FindOpenSSL.cmake @@ -0,0 +1,18 @@ +set(CMAKE_FIND_LIBRARY_SUFFIXES .dll ${CMAKE_FIND_LIBRARY_SUFFIXES}) +find_library(SSL_LIBRARY + NAMES + libssl-1_1-x64 + libssl-1_1 + PATH_SUFFIXES + bin +) +find_library(CRYPTO_LIBRARY + NAMES + libcrypto-1_1-x64 + libcrypto-1_1 + PATH_SUFFIXES + bin +) + +message(${SSL_LIBRARY}) +message(${CRYPTO_LIBRARY}) \ No newline at end of file From b00c8ce3c6738be4629eca8c6f7207d2997361ae Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Mon, 9 Mar 2020 12:21:07 +0800 Subject: [PATCH 266/332] ignore mingw path --- cmake/FindOpenSSL.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/FindOpenSSL.cmake b/cmake/FindOpenSSL.cmake index d865bd23..5c207442 100644 --- a/cmake/FindOpenSSL.cmake +++ b/cmake/FindOpenSSL.cmake @@ -1,4 +1,6 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES .dll ${CMAKE_FIND_LIBRARY_SUFFIXES}) +file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles) +list(APPEND CMAKE_SYSTEM_IGNORE_PATH "${_programfiles}/Git/mingw64") find_library(SSL_LIBRARY NAMES libssl-1_1-x64 From c0735cf704bb7099b00ca33cfe5788b646536e7d Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Mon, 9 Mar 2020 12:26:49 +0800 Subject: [PATCH 267/332] update FindOpenSSL.cmake --- cmake/FindOpenSSL.cmake | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cmake/FindOpenSSL.cmake b/cmake/FindOpenSSL.cmake index 5c207442..4679b77b 100644 --- a/cmake/FindOpenSSL.cmake +++ b/cmake/FindOpenSSL.cmake @@ -1,19 +1,23 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES .dll ${CMAKE_FIND_LIBRARY_SUFFIXES}) -file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles) -list(APPEND CMAKE_SYSTEM_IGNORE_PATH "${_programfiles}/Git/mingw64") find_library(SSL_LIBRARY NAMES libssl-1_1-x64 libssl-1_1 + PATHS + ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET} PATH_SUFFIXES bin + NO_DEFAULT_PATH ) find_library(CRYPTO_LIBRARY NAMES libcrypto-1_1-x64 libcrypto-1_1 + PATHS + ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET} PATH_SUFFIXES bin + NO_DEFAULT_PATH ) message(${SSL_LIBRARY}) From e49fda30b8ac4ab486c3144783170a150a0cf146 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 9 Mar 2020 14:46:56 +0800 Subject: [PATCH 268/332] translation: auto load all available translations --- CMakeLists.txt | 4 +- deployment.cmake => cmake/deployment.cmake | 0 src/base/GlobalInstances.hpp | 2 +- src/common/QvTranslator.cpp | 113 +++++++++++---------- src/common/QvTranslator.hpp | 35 +------ src/main.cpp | 17 +--- src/ui/w_PreferencesWindow.cpp | 33 +++--- 7 files changed, 89 insertions(+), 115 deletions(-) rename deployment.cmake => cmake/deployment.cmake (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index b2875720..d704ab83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -266,7 +266,7 @@ if(APPLE) # Call macdeployqt install(CODE "execute_process(COMMAND macdeployqt ${PROJECT_NAME}.app)") set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.app") - include(deployment.cmake) + include(cmake/deployment.cmake) endif() if(UNIX AND NOT APPLE AND NOT WIN32) @@ -296,5 +296,5 @@ if(WIN32) install(CODE "execute_process(COMMAND windeployqt ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe --compiler-runtime --verbose 2)") set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe") - include(deployment.cmake) + include(cmake/deployment.cmake) endif() diff --git a/deployment.cmake b/cmake/deployment.cmake similarity index 100% rename from deployment.cmake rename to cmake/deployment.cmake diff --git a/src/base/GlobalInstances.hpp b/src/base/GlobalInstances.hpp index 7d71b429..c5b2d7df 100644 --- a/src/base/GlobalInstances.hpp +++ b/src/base/GlobalInstances.hpp @@ -11,7 +11,7 @@ namespace Qv2ray { // Qv2ray runtime config inline bool isExiting = false; - inline QString Qv2rayConfigPath = "/"; + inline QString Qv2rayConfigPath = ""; inline base::Qv2rayRuntimeConfig RuntimeConfig = base::Qv2rayRuntimeConfig(); inline base::config::Qv2rayConfig GlobalConfig = base::config::Qv2rayConfig(); inline base::QvStartupOptions StartupOption = base::QvStartupOptions(); diff --git a/src/common/QvTranslator.cpp b/src/common/QvTranslator.cpp index 2aeb71c3..e9ad98bf 100644 --- a/src/common/QvTranslator.cpp +++ b/src/common/QvTranslator.cpp @@ -1,6 +1,7 @@ #include "QvTranslator.hpp" #include "base/Qv2rayLog.hpp" +#include "common/QvHelpers.hpp" #include #include @@ -12,75 +13,75 @@ using namespace Qv2ray::base; +// path searching list. +QStringList getLanguageSearchPaths() +{ + return { + // Configuration Path + QV2RAY_CONFIG_DIR + "lang", +// +#ifdef EMBED_TRANSLATIONS + // If the translations have been embedded. + QString(":/translations/"), +#endif +#ifdef QV2RAY_TRANSLATION_PATH + // Platform-specific dir, if specified. + QString(QV2RAY_TRANSLATION_PATH), +#endif +#ifdef Q_OS_LINUX + // Linux platform directories. + QString("/usr/local/share/qv2ray/lang"), + QString("/usr/share/qv2ray/lang"), +#elif defined(Q_OS_MAC) + // macOS platform directories. + QDir(QApplication::applicationDirPath() + "/../Resources/lang").absolutePath(), +#else + // This is the default behavior on Windows + QApplication::applicationDirPath() + "/lang", +#endif + }; +}; + namespace Qv2ray::common { - std::optional QvTranslator::getAvailableLanguages() + QvTranslator::QvTranslator() { - if (!this->translationDir) - return std::nullopt; - - auto languages = QDir(this->translationDir.value()).entryList(QStringList{ "*.qm" }, QDir::Hidden | QDir::Files); - - if (languages.empty()) - return std::nullopt; + LOG(MODULE_UI, "QvTranslator constructor.") + GetAvailableLanguages(); + } + QStringList QvTranslator::GetAvailableLanguages() + { + languages.clear(); + for (auto path : getLanguageSearchPaths()) + { + languages << QDir(path).entryList(QStringList{ "*.qm" }, QDir::Hidden | QDir::Files); + } std::transform(languages.begin(), languages.end(), languages.begin(), [](QString &fileName) { return fileName.replace(".qm", ""); }); + languages.removeDuplicates(); LOG(MODULE_UI, "Found translations: " + languages.join(" ")) return languages; } - void QvTranslator::reloadTranslation(const QString &code) + bool QvTranslator::InstallTranslation(const QString &code) { - if (!translationDir) - return; - - QTranslator *translatorNew = new QTranslator(); - translatorNew->load(code + ".qm", this->translationDir.value()); - - this->pTranslator.reset(translatorNew); - } - - std::optional QvTranslator::deduceTranslationDir() - { - // path searching list. - QStringList searchPaths = { - // 1st: application dir - QApplication::applicationDirPath() + "/lang", -#ifdef EMBED_TRANSLATIONS - QString(":/translations/"), -#endif -#ifdef QV2RAY_TRANSLATION_PATH - // 2nd: platform-specific dir - QString(QV2RAY_TRANSLATION_PATH), -#endif -#ifdef Q_OS_LINUX - // 2.5: hard-coded path for Linux systems - QString("/usr/share/qv2ray/lang"), -#endif - }; - // 3rd: standard path dirs - searchPaths << QStandardPaths::locateAll(QStandardPaths::DataLocation, "lang", QStandardPaths::LocateDirectory); - // - // iterate through the paths - for (auto path : searchPaths) + for (auto path : getLanguageSearchPaths()) { - DEBUG(MODULE_UI, "Testing for translation path: " + path) - if (QvTranslator::testTranslationDir(path)) + if (FileExistsIn(QDir(path), code + ".qm")) { - return path; + LOG(MODULE_UI, "Found " + code + " in folder: " + path) + QTranslator *translatorNew = new QTranslator(); + translatorNew->load(code + ".qm", path); + if (pTranslator) + { + LOG(MODULE_INIT, "Removed translations") + qApp->removeTranslator(pTranslator.get()); + } + this->pTranslator.reset(translatorNew); + qApp->installTranslator(pTranslator.get()); + return true; } } - - // sadly, none match - return std::nullopt; - } - - bool QvTranslator::testTranslationDir(const QString &targetDir) - { - const auto translations = QDir(targetDir).entryList(QStringList{ "*.qm" }, QDir::Hidden | QDir::Files); - - /// @todo: add some debug traces - - return !translations.empty(); + return false; } } // namespace Qv2ray::common diff --git a/src/common/QvTranslator.hpp b/src/common/QvTranslator.hpp index 4b93a197..de83aa6e 100644 --- a/src/common/QvTranslator.hpp +++ b/src/common/QvTranslator.hpp @@ -9,49 +9,22 @@ namespace Qv2ray::common class QvTranslator { public: - explicit QvTranslator() - { - this->reloadTranslationDirs(); - } + explicit QvTranslator(); public: - /** - * @brief search and deduce a directory for translation file - * @return (if any) the deduced path - * - * @author DuckSoft - * @todo add some debug output - */ - static std::optional deduceTranslationDir(); /** * @brief get the available languages. * @return (if available) languages (zh_CN, en_US, ...) */ - std::optional getAvailableLanguages(); + QStringList GetAvailableLanguages(); /** * @brief reload the translation from file * @param code eg: en_US, zh_CN, ... */ - void reloadTranslation(const QString &); - inline bool isTranslationAvailable() const - { - return this->translationDir.has_value(); - }; - inline void reloadTranslationDirs() - { - this->translationDir = this->deduceTranslationDir(); - }; + bool InstallTranslation(const QString &); private: - /** - * @brief test the translation directory - * @param targetDir the directory to judge - * @return if the translation directory seems good to use - */ - static bool testTranslationDir(const QString &); - - public: + QStringList languages; std::unique_ptr pTranslator; - std::optional translationDir; }; } // namespace Qv2ray::common diff --git a/src/main.cpp b/src/main.cpp index d19a5fba..3bba42af 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -258,8 +258,7 @@ int main(int argc, char *argv[]) // // Install a default translater. From the OS/DE Qv2rayTranslator.reset(std::move(new QvTranslator())); - Qv2rayTranslator->reloadTranslation(QLocale::system().name()); - consoleApp->installTranslator(Qv2rayTranslator->pTranslator.get()); + Qv2rayTranslator->InstallTranslation(QLocale::system().name()); QvCommandArgParser parser; QString errorMessage; @@ -321,9 +320,7 @@ int main(int argc, char *argv[]) // Install a default translater. From the OS/DE auto _lang = QLocale::system().name(); Qv2rayTranslator.reset(std::move(new QvTranslator())); - Qv2rayTranslator->reloadTranslation(_lang); - // Do not install en-US as it's the default language. - bool _result_ = _qApp.installTranslator(Qv2rayTranslator->pTranslator.get()); + bool _result_ = Qv2rayTranslator->InstallTranslation(_lang); LOG(MODULE_UI, "Installing a tranlator from OS: " + _lang + " -- " + (_result_ ? "OK" : "Failed")) // LOG("LICENCE", NEWLINE @@ -389,19 +386,15 @@ int main(int argc, char *argv[]) // Load config object from upgraded config QJsonObject auto confObject = StructFromJsonString(JsonToString(conf)); - // Remove system translator, for loading custom translations. - qApp->removeTranslator(Qv2rayTranslator->pTranslator.get()); - LOG(MODULE_INIT, "Removed system translations") if (confObject.uiConfig.language.isEmpty()) { // Prevent empty. - LOG(MODULE_UI, "Setting default UI language to en-US") - confObject.uiConfig.language = "en-US"; + LOG(MODULE_UI, "Setting default UI language to en_US") + confObject.uiConfig.language = "en_US"; } - Qv2rayTranslator->reloadTranslation(confObject.uiConfig.language); - if (qApp->installTranslator(Qv2rayTranslator->pTranslator.get())) + if (Qv2rayTranslator->InstallTranslation(confObject.uiConfig.language)) { LOG(MODULE_INIT, "Successfully installed a translator for " + confObject.uiConfig.language); } diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index fe4a064e..a116a731 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -41,10 +41,11 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), Current } // We add locales - if (auto langs = Qv2rayTranslator->getAvailableLanguages(); langs) + auto langs = Qv2rayTranslator->GetAvailableLanguages(); + if (!langs.empty()) { languageComboBox->clear(); - languageComboBox->addItems(langs.value()); + languageComboBox->addItems(langs); } else { @@ -168,11 +169,17 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), Current auto autoStartConnId = ConnectionId(CurrentConfig.autoStartId); auto autoStartGroupId = GetConnectionGroupId(autoStartConnId); - for (auto group : ConnectionManager->AllGroups()) { autoStartSubsCombo->addItem(GetDisplayName(group)); } + for (auto group : ConnectionManager->AllGroups()) + { + autoStartSubsCombo->addItem(GetDisplayName(group)); + } autoStartSubsCombo->setCurrentText(GetDisplayName(autoStartGroupId)); - for (auto conn : ConnectionManager->Connections(autoStartGroupId)) { autoStartConnCombo->addItem(GetDisplayName(conn)); } + for (auto conn : ConnectionManager->Connections(autoStartGroupId)) + { + autoStartConnCombo->addItem(GetDisplayName(conn)); + } autoStartConnCombo->setCurrentText(GetDisplayName(autoStartConnId)); @@ -258,19 +265,16 @@ void PreferencesWindow::on_buttonBox_accepted() { if (CurrentConfig.uiConfig.language != GlobalConfig.uiConfig.language) { - qApp->removeTranslator(Qv2rayTranslator->pTranslator.get()); - Qv2rayTranslator->reloadTranslation(CurrentConfig.uiConfig.language); - // Install translator - if (!qApp->installTranslator(Qv2rayTranslator->pTranslator.get())) - { - LOG(MODULE_UI, "Failed to translate UI to: " + CurrentConfig.uiConfig.language) - } - else + if (Qv2rayTranslator->InstallTranslation(CurrentConfig.uiConfig.language)) { messageBus.EmitGlobalSignal(QvMBMessage::RETRANSLATE); QApplication::processEvents(); } + else + { + LOG(MODULE_UI, "Failed to translate UI to: " + CurrentConfig.uiConfig.language) + } } qApp->setStyle(QStyleFactory::create(CurrentConfig.uiConfig.theme)); @@ -1025,7 +1029,10 @@ void PreferencesWindow::on_autoStartSubsCombo_currentIndexChanged(const QString auto list = ConnectionManager->Connections(groupId); autoStartConnCombo->clear(); - for (auto id : list) { autoStartConnCombo->addItem(GetDisplayName(id)); } + for (auto id : list) + { + autoStartConnCombo->addItem(GetDisplayName(id)); + } } } From 541b38aee02ecf7a720360e31927a739a8dbe937 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 9 Mar 2020 15:36:55 +0800 Subject: [PATCH 269/332] pac: fixing PAC server --- src/components/pac/QvPACHandler.cpp | 18 +++++------------- src/components/pac/QvPACHandler.hpp | 15 +++++++++++---- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/components/pac/QvPACHandler.cpp b/src/components/pac/QvPACHandler.cpp index 8e5c19ad..265ed6be 100644 --- a/src/components/pac/QvPACHandler.cpp +++ b/src/components/pac/QvPACHandler.cpp @@ -7,7 +7,7 @@ namespace Qv2ray::components::pac { - PACServer::PACServer() : QObject() + PACServer::PACServer() : QThread() { pacServer = new httplib::Server(); } @@ -23,7 +23,7 @@ namespace Qv2ray::components::pac DEBUG(MODULE_PROXY, "Setting new PAC proxy string: " + proxyString) this->proxyString = proxyString; } - void PACServer::StartListen() + void PACServer::run() { LOG(MODULE_PROXY, "Starting PAC listener") // @@ -35,11 +35,11 @@ namespace Qv2ray::components::pac QString gfwContent = StringFromFile(QV2RAY_RULES_GFWLIST_PATH); pacContent = ConvertGFWToPAC(gfwContent, proxyString); // + pacServer->Get("", onNewRequest); auto result = pacServer->listen(address.toStdString().c_str(), static_cast(port)); if (result) { - isStarted = true; - DEBUG(MODULE_PROXY, "Started PAC handler") + DEBUG(MODULE_PROXY, "PAC handler stopped.") } else { @@ -50,22 +50,14 @@ namespace Qv2ray::components::pac void PACServer::StopServer() { - if (isStarted) - { - pacServer->stop(); - DEBUG(MODULE_PROXY, "PAC Handler stopped.") - isStarted = false; - } + pacServer->stop(); } void PACServer::onNewRequest(const httplib::Request &req, httplib::Response &rsp) { - rsp.set_header("Server", "Qv2ray/" QV2RAY_VERSION_STRING " PAC_Handler"); - if (req.method == "GET") { - // if (req.path == "/pac") { DEBUG(MODULE_PROXY, "Serving PAC file request.") diff --git a/src/components/pac/QvPACHandler.hpp b/src/components/pac/QvPACHandler.hpp index 762b15d5..b6e052dd 100644 --- a/src/components/pac/QvPACHandler.hpp +++ b/src/components/pac/QvPACHandler.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include namespace httplib @@ -13,24 +14,30 @@ namespace httplib namespace Qv2ray::components::pac { QString ConvertGFWToPAC(const QString &rawContent, const QString &customProxyString); - class PACServer : public QObject + class PACServer : public QThread { Q_OBJECT public: explicit PACServer(); ~PACServer(); void SetProxyString(const QString &proxyString); - void StartListen(); + void StartListen() + { + start(); + } void StopServer(); QString gfwFilePath; private: - void onNewRequest(const httplib::Request &req, httplib::Response &rsp); + void run() override; bool isStarted; httplib::Server *pacServer; - QString pacContent; QString proxyString; + + private: + static void onNewRequest(const httplib::Request &req, httplib::Response &rsp); + static inline QString pacContent; }; } // namespace Qv2ray::components::pac From 9f4f89c102c59a5795770e0bb6a71fc2e3f31fe5 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 9 Mar 2020 15:41:29 +0800 Subject: [PATCH 270/332] pac: fixed PAC server --- makespec/BUILDVERSION | 2 +- src/components/pac/QvPACHandler.cpp | 7 ++----- src/components/pac/QvPACHandler.hpp | 1 - 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 9bcafcbd..a11b74f8 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4600 +4601 diff --git a/src/components/pac/QvPACHandler.cpp b/src/components/pac/QvPACHandler.cpp index 265ed6be..dce127a9 100644 --- a/src/components/pac/QvPACHandler.cpp +++ b/src/components/pac/QvPACHandler.cpp @@ -13,10 +13,7 @@ namespace Qv2ray::components::pac } PACServer::~PACServer() { - if (isStarted) - { - delete pacServer; - } + delete pacServer; } void PACServer::SetProxyString(const QString &proxyString) { @@ -35,7 +32,7 @@ namespace Qv2ray::components::pac QString gfwContent = StringFromFile(QV2RAY_RULES_GFWLIST_PATH); pacContent = ConvertGFWToPAC(gfwContent, proxyString); // - pacServer->Get("", onNewRequest); + pacServer->Get("/pac", onNewRequest); auto result = pacServer->listen(address.toStdString().c_str(), static_cast(port)); if (result) { diff --git a/src/components/pac/QvPACHandler.hpp b/src/components/pac/QvPACHandler.hpp index b6e052dd..e8847167 100644 --- a/src/components/pac/QvPACHandler.hpp +++ b/src/components/pac/QvPACHandler.hpp @@ -31,7 +31,6 @@ namespace Qv2ray::components::pac private: void run() override; - bool isStarted; httplib::Server *pacServer; QString proxyString; From b1567ee20865f074373d4217c004f4172ad39aa8 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Mon, 9 Mar 2020 15:56:34 +0800 Subject: [PATCH 271/332] add docstring for some build options embed translations for snap --- CMakeLists.txt | 11 ++++++++--- snap/snapcraft.yaml | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f67024bc..2306f763 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,15 +113,20 @@ add_definitions(-D_QV2RAY_BUILD_EXTRA_INFO_STR_="${_QV2RAY_BUILD_EXTRA_INFO_STR_ message("Qv2ray build info: ${_QV2RAY_BUILD_INFO_STR_}") message("Qv2ray build info ex: ${_QV2RAY_BUILD_EXTRA_INFO_STR_}") -if(DEFINED QV2RAY_DEFAULT_VASSETS_PATH) +set(QV2RAY_DEFAULT_VASSETS_PATH CACHE STRING "v2ray assets path") +set(QV2RAY_DEFAULT_VCORE_PATH CACHE STRING "v2ray core path") +set(QV2RAY_TRANSLATION_PATH CACHE STRING "Qv2ray translations path") +set(EMBED_TRANSLATIONS OFF CACHE BOOL "Embed translations") + +if(QV2RAY_DEFAULT_VASSETS_PATH) add_definitions(-DQV2RAY_DEFAULT_VASSETS_PATH="${QV2RAY_DEFAULT_VASSETS_PATH}") endif() -if(DEFINED QV2RAY_DEFAULT_VCORE_PATH) +if(QV2RAY_DEFAULT_VCORE_PATH) add_definitions(-DQV2RAY_DEFAULT_VCORE_PATH="${QV2RAY_DEFAULT_VCORE_PATH}") endif() -if(DEFINED QV2RAY_TRANSLATION_PATH) +if(QV2RAY_TRANSLATION_PATH) add_definitions(-DQV2RAY_TRANSLATION_PATH="${QV2RAY_TRANSLATION_PATH}") endif() diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index b360c8f0..dc218105 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -72,6 +72,7 @@ parts: - -DCMAKE_INSTALL_PREFIX=/usr - -DCMAKE_BUILD_TYPE=Release - -GNinja + - -DEMBED_TRANSLATIONS=ON override-pull: | snapcraftctl pull build_number=$(cat makespec/BUILDVERSION) From f9eb546e2c7f67222e441bd777a0ed61591588e0 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 9 Mar 2020 16:03:10 +0800 Subject: [PATCH 272/332] cmake: auto increase the build number if not in Release mode --- CMakeLists.txt | 8 +++++++- makespec/BUILDVERSION | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2306f763..3dda8617 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,14 @@ cmake_minimum_required(VERSION 3.10.1) file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/VERSION" QV2RAY_VERSION) file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" QV2RAY_BUILD_VERSION) -set(PACKAGE_VERSION "${QV2RAY_VERSION}.${QV2RAY_BUILD_VERSION}") +if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Release") + math(EXPR QV2RAY_BUILD_VERSION "1 + ${QV2RAY_BUILD_VERSION}" OUTPUT_FORMAT DECIMAL) + message("Increasing BUILDVERSION") + file(WRITE "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" ${QV2RAY_BUILD_VERSION}) +endif() + +set(PACKAGE_VERSION "${QV2RAY_VERSION}.${QV2RAY_BUILD_VERSION}") project(qv2ray) set(VERSION_LIST ${PACKAGE_VERSION}) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index a11b74f8..1bbd686c 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4601 +4622 \ No newline at end of file From 1d40d593f9adc274dfe956fc9ea94be790dc7ae3 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Mon, 9 Mar 2020 16:24:21 +0800 Subject: [PATCH 273/332] update CMakeLists.txt --- CMakeLists.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3dda8617..ed4c6749 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,18 +102,25 @@ if(APPLE) ) endif() -if(DEFINED ENV{_QV2RAY_BUILD_INFO_}) +if(QV2RAY_BUILD_INFO) + set(_QV2RAY_BUILD_INFO_STR_ "${QV2RAY_BUILD_INFO}") +elseif(DEFINED ENV{_QV2RAY_BUILD_INFO_}) set(_QV2RAY_BUILD_INFO_STR_ "$ENV{_QV2RAY_BUILD_INFO_}") else() set(_QV2RAY_BUILD_INFO_STR_ "Qv2ray from manual build") endif() -if(DEFINED ENV{_QV2RAY_BUILD_EXTRA_INFO_}) +if(QV2RAY_BUILD_EXTRA_INFO) + set(_QV2RAY_BUILD_EXTRA_INFO_STR_ "${QV2RAY_BUILD_EXTRA_INFO}") +elseif(DEFINED ENV{_QV2RAY_BUILD_EXTRA_INFO_}) set(_QV2RAY_BUILD_EXTRA_INFO_STR_ "$ENV{_QV2RAY_BUILD_EXTRA_INFO_}") else() set(_QV2RAY_BUILD_EXTRA_INFO_STR_ "Qv2ray v${PACKAGE_VERSION}") endif() +set(QV2RAY_BUILD_INFO ${_QV2RAY_BUILD_INFO_STR_} CACHE STRING "Qv2ray build info") +set(QV2RAY_BUILD_EXTRA_INFO ${_QV2RAY_BUILD_EXTRA_INFO_STR_} CACHE STRING "Qv2ray build extra info") + add_definitions(-D_QV2RAY_BUILD_INFO_STR_="${_QV2RAY_BUILD_INFO_STR_}") add_definitions(-D_QV2RAY_BUILD_EXTRA_INFO_STR_="${_QV2RAY_BUILD_EXTRA_INFO_STR_}") message("Qv2ray build info: ${_QV2RAY_BUILD_INFO_STR_}") From b3cf4100415f8d569814c958b152513e54ea44d3 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 9 Mar 2020 16:25:17 +0800 Subject: [PATCH 274/332] qt512: removed undefined macro in qt512 --- src/ui/widgets/ConnectionItemWidget.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index 462089ac..e3960af2 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -70,6 +70,4 @@ class ConnectionItemWidget ITEM_TYPE itemType; ConnectionId connectionId; GroupId groupId; - - Q_DISABLE_COPY_MOVE(ConnectionItemWidget) }; From fea7579cd4a520164767738c5ff751058ab618ae Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Mon, 9 Mar 2020 16:32:49 +0800 Subject: [PATCH 275/332] update CMakeLists.txt --- CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ed4c6749..122b3e67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,20 +126,20 @@ add_definitions(-D_QV2RAY_BUILD_EXTRA_INFO_STR_="${_QV2RAY_BUILD_EXTRA_INFO_STR_ message("Qv2ray build info: ${_QV2RAY_BUILD_INFO_STR_}") message("Qv2ray build info ex: ${_QV2RAY_BUILD_EXTRA_INFO_STR_}") -set(QV2RAY_DEFAULT_VASSETS_PATH CACHE STRING "v2ray assets path") -set(QV2RAY_DEFAULT_VCORE_PATH CACHE STRING "v2ray core path") -set(QV2RAY_TRANSLATION_PATH CACHE STRING "Qv2ray translations path") +set(QV2RAY_DEFAULT_VASSETS_PATH "unset" CACHE STRING "v2ray assets path") +set(QV2RAY_DEFAULT_VCORE_PATH "unset" CACHE STRING "v2ray core path") +set(QV2RAY_TRANSLATION_PATH "unset" CACHE STRING "Qv2ray translations path") set(EMBED_TRANSLATIONS OFF CACHE BOOL "Embed translations") -if(QV2RAY_DEFAULT_VASSETS_PATH) +if(QV2RAY_DEFAULT_VASSETS_PATH AND NOT STREQUAL "unset") add_definitions(-DQV2RAY_DEFAULT_VASSETS_PATH="${QV2RAY_DEFAULT_VASSETS_PATH}") endif() -if(QV2RAY_DEFAULT_VCORE_PATH) +if(QV2RAY_DEFAULT_VCORE_PATH AND NOT STREQUAL "unset") add_definitions(-DQV2RAY_DEFAULT_VCORE_PATH="${QV2RAY_DEFAULT_VCORE_PATH}") endif() -if(QV2RAY_TRANSLATION_PATH) +if(QV2RAY_TRANSLATION_PATH AND NOT STREQUAL "unset") add_definitions(-DQV2RAY_TRANSLATION_PATH="${QV2RAY_TRANSLATION_PATH}") endif() From 1c49cf5ae2626f8ed8d5a047469dbe5f6e9d4316 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 9 Mar 2020 23:18:29 +0800 Subject: [PATCH 276/332] win: fixing StringFromFile to read input file in any encoding supported --- makespec/BUILDVERSION | 2 +- src/common/QvHelpers.cpp | 24 +++++++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 1bbd686c..0d7efe04 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4622 \ No newline at end of file +4624 \ No newline at end of file diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 3db8a77a..1999b94c 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -32,12 +32,26 @@ namespace Qv2ray::common QString StringFromFile(QFile *source) { - source->open(QFile::ReadOnly); - QTextStream stream(source); - QString str = stream.readAll(); - source->close(); - return str; + bool wasOpened = source->isOpen(); + if (!wasOpened) + source->open(QFile::ReadOnly); + auto byteArray = source->readAll(); + if (!wasOpened) + source->close(); + // + QTextCodec::ConverterState state; + QTextCodec *codec = QTextCodec::codecForName("UTF-8"); + const QString text = codec->toUnicode(byteArray.constData(), byteArray.size(), &state); + if (state.invalidChars > 0) { + LOG(MODULE_FILEIO, "Not a valid UTF-8 sequence: " + source->fileName()) + return source->readAll(); + } + else + { + return text; + } } + bool StringToFile(const QString &text, const QString &targetpath) { auto file = QFile(targetpath); From b16aa056c13ccab98bade92e3766470256a1db08 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 10 Mar 2020 00:31:59 +0800 Subject: [PATCH 277/332] optimize: use CONFIGROOT cache instead of disk io --- makespec/BUILDVERSION | 2 +- src/core/handler/ConfigHandler.cpp | 46 ++++++++++++++++-------------- src/core/handler/ConfigHandler.hpp | 3 +- src/ui/w_MainWindow_extra.cpp | 4 +-- 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 0d7efe04..ea53445d 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4624 \ No newline at end of file +4626 \ No newline at end of file diff --git a/src/core/handler/ConfigHandler.cpp b/src/core/handler/ConfigHandler.cpp index 49a2faff..bb3db627 100644 --- a/src/core/handler/ConfigHandler.cpp +++ b/src/core/handler/ConfigHandler.cpp @@ -12,13 +12,14 @@ namespace Qv2ray::core::handlers DEBUG(MODULE_CORE_HANDLER, "ConnectionHandler Constructor.") // Do we need to check how many of them are loaded? + // Do not use: for (const auto &key : connections) for (auto i = 0; i < GlobalConfig.connections.count(); i++) { - auto id = ConnectionId(GlobalConfig.connections.keys()[i]); - connections[id] = GlobalConfig.connections.values()[i]; + auto const &id = ConnectionId(GlobalConfig.connections.keys().at(i)); + connections[id] = GlobalConfig.connections.values().at(i); } - for (auto key : GlobalConfig.subscriptions.keys()) + for (const auto &key : GlobalConfig.subscriptions.keys()) { GroupId gkey(key); if (gkey == NullGroupId) @@ -26,7 +27,7 @@ namespace Qv2ray::core::handlers LOG(MODULE_CORE_HANDLER, "Removed a null subscription id") continue; } - auto val = GlobalConfig.subscriptions[key]; + auto const &val = GlobalConfig.subscriptions[key]; groups[gkey] = val; for (auto conn : val.connections) @@ -35,7 +36,7 @@ namespace Qv2ray::core::handlers } } - for (auto key : GlobalConfig.groups.keys()) + for (const auto &key : GlobalConfig.groups.keys()) { GroupId gkey(key); if (gkey == NullGroupId) @@ -43,7 +44,7 @@ namespace Qv2ray::core::handlers LOG(MODULE_CORE_HANDLER, "Removed a null group id") continue; } - auto val = GlobalConfig.groups[key]; + auto const &val = GlobalConfig.groups.value(key); groups[gkey] = val; for (auto conn : val.connections) @@ -52,19 +53,26 @@ namespace Qv2ray::core::handlers } } + for (const auto &id : connections.keys()) + { + DEBUG(MODULE_CORE_HANDLER, "Loading connection: " + connections.value(id).displayName + " to cache.") + auto const &group = connections.value(id).groupId; + auto path = group.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; + path.prepend(groups[group].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR); + // + connectionRootCache[id] = CONFIGROOT(JsonFromString(StringFromFile(path))); + } // // Force default group name. groups[DefaultGroupId].displayName = tr("Default Group"); groups[DefaultGroupId].isSubscription = false; // - vCoreInstance = new V2rayKernelInstance(); connect(vCoreInstance, &V2rayKernelInstance::OnProcessErrored, this, &QvConfigHandler::OnVCoreCrashed); connect(vCoreInstance, &V2rayKernelInstance::OnNewStatsDataArrived, this, &QvConfigHandler::OnStatsDataArrived); // Directly connected to a signal. connect(vCoreInstance, &V2rayKernelInstance::OnProcessOutputReadyRead, this, &QvConfigHandler::OnVCoreLogAvailable); // - // tcpingHelper = new QvTCPingHelper(5, this); httpHelper = new QvHttpRequestHelper(this); connect(tcpingHelper, &QvTCPingHelper::OnLatencyTestCompleted, this, &QvConfigHandler::OnLatencyDataArrived); @@ -294,7 +302,7 @@ namespace Qv2ray::core::handlers StopConnection(); } - CONFIGROOT root = GetConnectionRoot(connections[id].groupId, id); + CONFIGROOT root = GetConnectionRoot(id); return CHStartConnection_p(id, root); } @@ -342,16 +350,7 @@ namespace Qv2ray::core::handlers const CONFIGROOT QvConfigHandler::GetConnectionRoot(const ConnectionId &id) const { CheckConnectionExistanceEx(id, CONFIGROOT()); - return connections.contains(id) ? GetConnectionRoot(connections[id].groupId, id) : CONFIGROOT(); - } - - const CONFIGROOT QvConfigHandler::GetConnectionRoot(const GroupId &group, const ConnectionId &id) const - { - CheckGroupExistanceEx(group, CONFIGROOT()); - CheckConnectionExistanceEx(id, CONFIGROOT()); - auto path = group.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; - path.prepend(groups[group].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR); - return CONFIGROOT(JsonFromString(StringFromFile(path))); + return connectionRootCache.value(id); } void QvConfigHandler::OnLatencyDataArrived(const QvTCPingResultObject &result) @@ -369,12 +368,17 @@ namespace Qv2ray::core::handlers bool QvConfigHandler::UpdateConnection(const ConnectionId &id, const CONFIGROOT &root, bool skipRestart) { - CheckConnectionExistanceEx(id, false); - auto groupId = connections[id].groupId; + CheckConnectionExistance(id); + auto const &groupId = connections[id].groupId; + CheckGroupExistance(groupId); + // auto path = (groups[groupId].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR) + groupId.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; auto content = JsonToString(root); bool result = StringToFile(content, path); + // + connectionRootCache[id] = root; + // emit OnConnectionModified(id); if (!skipRestart && id == currentConnectionId) { diff --git a/src/core/handler/ConfigHandler.hpp b/src/core/handler/ConfigHandler.hpp index 3ed0ac71..5e92e531 100644 --- a/src/core/handler/ConfigHandler.hpp +++ b/src/core/handler/ConfigHandler.hpp @@ -87,7 +87,6 @@ namespace Qv2ray::core::handlers // // Get Conncetion Property const CONFIGROOT GetConnectionRoot(const ConnectionId &id) const; - const CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id) const; // // Misc Connection Operations void StartLatencyTest(); @@ -149,7 +148,7 @@ namespace Qv2ray::core::handlers int pingConnectionTimerId; QHash groups; QHash connections; - // QHash connectionRootCache; + QHash connectionRootCache; private: QvHttpRequestHelper *httpHelper; diff --git a/src/ui/w_MainWindow_extra.cpp b/src/ui/w_MainWindow_extra.cpp index 903745e7..140f8819 100644 --- a/src/ui/w_MainWindow_extra.cpp +++ b/src/ui/w_MainWindow_extra.cpp @@ -78,8 +78,8 @@ void MainWindow::CheckSubscriptionsUpdate() for (auto index = 0; index < GlobalConfig.subscriptions.count(); index++) { - auto subs = GlobalConfig.subscriptions.values()[index]; - auto key = GlobalConfig.subscriptions.keys()[index]; + auto subs = GlobalConfig.subscriptions.values().at(index); + auto key = GlobalConfig.subscriptions.keys().at(index); // auto lastRenewDate = QDateTime::fromTime_t(subs.lastUpdated); auto renewTime = lastRenewDate.addSecs(subs.updateInterval * 86400); From 0746c76de93c774628993d0940446a9fbadf0edc Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 10 Mar 2020 00:37:50 +0800 Subject: [PATCH 278/332] optimize: automatically remove orphaned connections --- src/core/handler/ConfigHandler.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/core/handler/ConfigHandler.cpp b/src/core/handler/ConfigHandler.cpp index bb3db627..7c634e32 100644 --- a/src/core/handler/ConfigHandler.cpp +++ b/src/core/handler/ConfigHandler.cpp @@ -57,10 +57,18 @@ namespace Qv2ray::core::handlers { DEBUG(MODULE_CORE_HANDLER, "Loading connection: " + connections.value(id).displayName + " to cache.") auto const &group = connections.value(id).groupId; - auto path = group.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; - path.prepend(groups[group].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR); - // - connectionRootCache[id] = CONFIGROOT(JsonFromString(StringFromFile(path))); + if (group != NullGroupId) + { + auto path = group.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION; + path.prepend(groups[group].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR); + // + connectionRootCache[id] = CONFIGROOT(JsonFromString(StringFromFile(path))); + } + else + { + connections.remove(id); + LOG(MODULE_CORE_HANDLER, "Dropped connection id: " + id.toString() + " since it's not in a group") + } } // // Force default group name. @@ -82,7 +90,7 @@ namespace Qv2ray::core::handlers // Do not ping all... // pingAllTimerId = startTimer(5 * 60 * 1000); pingConnectionTimerId = startTimer(60 * 1000); - } + } // namespace Qv2ray::core::handlers void QvConfigHandler::CHSaveConfigData_p() { From 2f7fbe3ddca73f998bc1e4a413d30c9d65b1506b Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 10 Mar 2020 00:51:20 +0800 Subject: [PATCH 279/332] Update ConfigHandler.cpp --- src/core/handler/ConfigHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/handler/ConfigHandler.cpp b/src/core/handler/ConfigHandler.cpp index 7c634e32..2fddb0c3 100644 --- a/src/core/handler/ConfigHandler.cpp +++ b/src/core/handler/ConfigHandler.cpp @@ -90,7 +90,7 @@ namespace Qv2ray::core::handlers // Do not ping all... // pingAllTimerId = startTimer(5 * 60 * 1000); pingConnectionTimerId = startTimer(60 * 1000); - } // namespace Qv2ray::core::handlers + } void QvConfigHandler::CHSaveConfigData_p() { From 6e4d588eb201a4b96112f7c31c27c49c213033df Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 10 Mar 2020 09:55:24 +0800 Subject: [PATCH 280/332] ux: automatically set system proxy --- src/base/models/QvSettingsObject.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/models/QvSettingsObject.hpp b/src/base/models/QvSettingsObject.hpp index 20c011d9..031fec82 100644 --- a/src/base/models/QvSettingsObject.hpp +++ b/src/base/models/QvSettingsObject.hpp @@ -89,7 +89,7 @@ namespace Qv2ray::base::config objects::AccountObject httpAccount; Qv2rayInboundsConfig() - : listenip("127.0.0.1"), setSystemProxy(false), pacConfig(), useSocks(true), socks_port(1088), socks_useAuth(false), socksUDP(true), + : listenip("127.0.0.1"), setSystemProxy(true), pacConfig(), useSocks(true), socks_port(1088), socks_useAuth(false), socksUDP(true), socksLocalIP("127.0.0.1"), socksAccount(), useHTTP(true), http_port(8888), http_useAuth(false), httpAccount() { } From cd61b4d6ded70f285410f1c2628e183280268c17 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Tue, 10 Mar 2020 11:38:40 +0800 Subject: [PATCH 281/332] Revert "update CMakeLists.txt" This reverts commit ba6df9c1224e13bfe087b9d71ac1676d96f7c28c. --- CMakeLists.txt | 10 +++++++--- cmake/FindOpenSSL.cmake | 24 ------------------------ 2 files changed, 7 insertions(+), 27 deletions(-) delete mode 100644 cmake/FindOpenSSL.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 122b3e67..d0b133af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -304,9 +304,13 @@ if(WIN32) install(FILES ${QM_FILES} DESTINATION lang) endif() - include(cmake/FindOpenSSL.cmake) - install(FILES ${SSL_LIBRARY} DESTINATION .) - install(FILES ${CRYPTO_LIBRARY} DESTINATION .) + if(CMAKE_CL_64) + install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libssl-1_1-x64.dll DESTINATION .) + install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libcrypto-1_1-x64.dll DESTINATION .) + else() + install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libssl-1_1.dll DESTINATION .) + install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libcrypto-1_1.dll DESTINATION .) + endif() install(CODE "execute_process(COMMAND windeployqt ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe --compiler-runtime --verbose 2)") set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe") diff --git a/cmake/FindOpenSSL.cmake b/cmake/FindOpenSSL.cmake deleted file mode 100644 index 4679b77b..00000000 --- a/cmake/FindOpenSSL.cmake +++ /dev/null @@ -1,24 +0,0 @@ -set(CMAKE_FIND_LIBRARY_SUFFIXES .dll ${CMAKE_FIND_LIBRARY_SUFFIXES}) -find_library(SSL_LIBRARY - NAMES - libssl-1_1-x64 - libssl-1_1 - PATHS - ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET} - PATH_SUFFIXES - bin - NO_DEFAULT_PATH -) -find_library(CRYPTO_LIBRARY - NAMES - libcrypto-1_1-x64 - libcrypto-1_1 - PATHS - ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET} - PATH_SUFFIXES - bin - NO_DEFAULT_PATH -) - -message(${SSL_LIBRARY}) -message(${CRYPTO_LIBRARY}) \ No newline at end of file From 77096b3ef358bd475c3f802a908b202ded19b114 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 10 Mar 2020 14:03:37 +0800 Subject: [PATCH 282/332] core: fixed macOS vAssetsPath settings --- src/base/models/QvSettingsObject.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/models/QvSettingsObject.hpp b/src/base/models/QvSettingsObject.hpp index 031fec82..c293bf6b 100644 --- a/src/base/models/QvSettingsObject.hpp +++ b/src/base/models/QvSettingsObject.hpp @@ -172,7 +172,7 @@ namespace Qv2ray::base::config #undef _VARNAME_VCOREPATH_ #undef _VARNAME_VASSETSPATH_ - XTOSTRUCT(O(v2CorePath_linux, v2AssetsPath_linux, v2CorePath_macx, v2CorePath_macx, v2CorePath_win, v2AssetsPath_win)) + XTOSTRUCT(O(v2CorePath_linux, v2AssetsPath_linux, v2CorePath_macx, v2AssetsPath_macx, v2CorePath_win, v2AssetsPath_win)) }; struct Qv2rayConfig From 571739d99bfee13fe30d402c6fc041840909ae59 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 10 Mar 2020 14:04:28 +0800 Subject: [PATCH 283/332] ui: enable hidpi UI settings --- makespec/BUILDVERSION | 2 +- src/main.cpp | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index ea53445d..869cd632 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4626 \ No newline at end of file +4627 \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 3bba42af..c86176cd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -295,10 +295,10 @@ int main(int argc, char *argv[]) #endif // // finished: command line parsing + // LOG("QV2RAY_BUILD_INFO", QV2RAY_BUILD_INFO) LOG("QV2RAY_BUILD_EXTRA_INFO", QV2RAY_BUILD_EXTRA_INFO) - LOG(MODULE_INIT, - "Qv2ray " QV2RAY_VERSION_STRING " running on " + QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture() + NEWLINE) + LOG(MODULE_INIT, "Qv2ray " QV2RAY_VERSION_STRING " running on " + QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture()) // // This line must be called before any other ones, since we are using these // values to identify instances. @@ -311,8 +311,17 @@ int main(int argc, char *argv[]) // ----------------------------> For debug build... SingleApplication::setApplicationName("Qv2ray - DEBUG"); #endif - SingleApplication _qApp( - argc, argv, false, SingleApplication::Mode::User | SingleApplication::Mode::ExcludeAppPath | SingleApplication::Mode::ExcludeAppVersion); + + if (!qEnvironmentVariableIsSet("QT_DEVICE_PIXEL_RATIO") && // + !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR") && // + !qEnvironmentVariableIsSet("QT_SCALE_FACTOR") && // + !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) + { + DEBUG(MODULE_INIT, "High DPI scaling is enabled.") + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + } + SingleApplication _qApp(argc, argv, false, + SingleApplication::User | SingleApplication::ExcludeAppPath | SingleApplication::ExcludeAppVersion); _qApp.setQuitOnLastWindowClosed(false); // Early initialisation // From 9716e6988f11494477bd06bb04306639ca49bf4b Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 10 Mar 2020 14:44:43 +0800 Subject: [PATCH 284/332] ui: changed internal application name --- src/base/GlobalInstances.hpp | 2 +- src/common/QvTranslator.cpp | 40 +++++++++++++++++++--------------- src/main.cpp | 29 +++++++++++++----------- src/ui/w_PreferencesWindow.cpp | 4 ++-- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/src/base/GlobalInstances.hpp b/src/base/GlobalInstances.hpp index c5b2d7df..b0aac271 100644 --- a/src/base/GlobalInstances.hpp +++ b/src/base/GlobalInstances.hpp @@ -16,5 +16,5 @@ namespace Qv2ray inline base::config::Qv2rayConfig GlobalConfig = base::config::Qv2rayConfig(); inline base::QvStartupOptions StartupOption = base::QvStartupOptions(); // - inline std::unique_ptr Qv2rayTranslator; + inline common::QvTranslator Qv2rayTranslator; } // namespace Qv2ray diff --git a/src/common/QvTranslator.cpp b/src/common/QvTranslator.cpp index e9ad98bf..25057b92 100644 --- a/src/common/QvTranslator.cpp +++ b/src/common/QvTranslator.cpp @@ -16,37 +16,43 @@ using namespace Qv2ray::base; // path searching list. QStringList getLanguageSearchPaths() { - return { - // Configuration Path - QV2RAY_CONFIG_DIR + "lang", + // Configuration Path + QStringList list; + list << QV2RAY_CONFIG_DIR + "lang"; // #ifdef EMBED_TRANSLATIONS - // If the translations have been embedded. - QString(":/translations/"), + // If the translations have been embedded. + list << QString(":/translations/"); #endif + // + // #ifdef QV2RAY_TRANSLATION_PATH - // Platform-specific dir, if specified. - QString(QV2RAY_TRANSLATION_PATH), + // Platform-specific dir, if specified. + list << QString(QV2RAY_TRANSLATION_PATH); #endif + // + // #ifdef Q_OS_LINUX - // Linux platform directories. - QString("/usr/local/share/qv2ray/lang"), - QString("/usr/share/qv2ray/lang"), + // Linux platform directories. + list << QString("/usr/share/qv2ray/lang/"); + list << QString("/usr/local/share/qv2ray/lang/"); + list << QStandardPaths::locateAll(QStandardPaths::AppDataLocation, "lang", QStandardPaths::LocateDirectory); + list << QStandardPaths::locateAll(QStandardPaths::AppConfigLocation, "lang", QStandardPaths::LocateDirectory); #elif defined(Q_OS_MAC) - // macOS platform directories. - QDir(QApplication::applicationDirPath() + "/../Resources/lang").absolutePath(), + // macOS platform directories. + list << QDir(QApplication::applicationDirPath() + "/../Resources/lang").absolutePath(); #else - // This is the default behavior on Windows - QApplication::applicationDirPath() + "/lang", + // This is the default behavior on Windows + list << QApplication::applicationDirPath() + "/lang"; #endif - }; + return list; }; namespace Qv2ray::common { QvTranslator::QvTranslator() { - LOG(MODULE_UI, "QvTranslator constructor.") + DEBUG(MODULE_UI, "QvTranslator constructor.") GetAvailableLanguages(); } @@ -59,7 +65,7 @@ namespace Qv2ray::common } std::transform(languages.begin(), languages.end(), languages.begin(), [](QString &fileName) { return fileName.replace(".qm", ""); }); languages.removeDuplicates(); - LOG(MODULE_UI, "Found translations: " + languages.join(" ")) + DEBUG(MODULE_UI, "Found translations: " + languages.join(" ")) return languages; } diff --git a/src/main.cpp b/src/main.cpp index 3bba42af..93d7c90d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,6 +29,10 @@ void signalHandler(int signum) bool verifyConfigAvaliability(QString path, bool checkExistingConfig) { + if (!path.endsWith("/")) + { + path.append("/"); + } // Does not exist. if (!QDir(path).exists()) return false; @@ -122,7 +126,8 @@ bool initialiseQv2ray() { LOG(MODULE_INIT, "Application exec path: " + QApplication::applicationDirPath()) const QString currentPathConfig = QApplication::applicationDirPath() + "/config" QV2RAY_CONFIG_DIR_SUFFIX; - const QString configQv2ray = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/qv2ray" QV2RAY_CONFIG_DIR_SUFFIX; + // Standard paths already handles the _debug suffix for us. + const QString configQv2ray = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); const QString homeQv2ray = QDir::homePath() + "/.qv2ray" QV2RAY_CONFIG_DIR_SUFFIX; // // @@ -131,11 +136,11 @@ bool initialiseQv2ray() // QStringList configFilePaths; configFilePaths << currentPathConfig; -#ifdef WITH_FLATHUB_CONFIG_PATH - // AppConfigLocation uses 'Q'v2ray instead of `q`v2ray. Keep here as - // backward compatibility. - configFilePaths << QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + QV2RAY_CONFIG_DIR_SUFFIX; -#endif + // Application name changed to `qv2ray`, so these code are now becoming unnecessary. + //#ifdef WITH_FLATHUB_CONFIG_PATH + // // AppConfigLocation uses 'Q'v2ray instead of `q`v2ray. Keep here as backward compatibility. + // configFilePaths << QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + QV2RAY_CONFIG_DIR_SUFFIX; + //#endif configFilePaths << configQv2ray; configFilePaths << homeQv2ray; // @@ -257,8 +262,7 @@ int main(int argc, char *argv[]) std::unique_ptr consoleApp(new QCoreApplication(argc, argv)); // // Install a default translater. From the OS/DE - Qv2rayTranslator.reset(std::move(new QvTranslator())); - Qv2rayTranslator->InstallTranslation(QLocale::system().name()); + Qv2rayTranslator.InstallTranslation(QLocale::system().name()); QvCommandArgParser parser; QString errorMessage; @@ -302,14 +306,14 @@ int main(int argc, char *argv[]) // // This line must be called before any other ones, since we are using these // values to identify instances. - SingleApplication::setApplicationName("Qv2ray"); + SingleApplication::setApplicationName("qv2ray"); SingleApplication::setApplicationVersion(QV2RAY_VERSION_STRING); SingleApplication::setApplicationDisplayName("Qv2ray"); // // #ifdef QT_DEBUG // ----------------------------> For debug build... - SingleApplication::setApplicationName("Qv2ray - DEBUG"); + SingleApplication::setApplicationName("qv2ray_debug"); #endif SingleApplication _qApp( argc, argv, false, SingleApplication::Mode::User | SingleApplication::Mode::ExcludeAppPath | SingleApplication::Mode::ExcludeAppVersion); @@ -319,8 +323,7 @@ int main(int argc, char *argv[]) // Not duplicated. // Install a default translater. From the OS/DE auto _lang = QLocale::system().name(); - Qv2rayTranslator.reset(std::move(new QvTranslator())); - bool _result_ = Qv2rayTranslator->InstallTranslation(_lang); + bool _result_ = Qv2rayTranslator.InstallTranslation(_lang); LOG(MODULE_UI, "Installing a tranlator from OS: " + _lang + " -- " + (_result_ ? "OK" : "Failed")) // LOG("LICENCE", NEWLINE @@ -394,7 +397,7 @@ int main(int argc, char *argv[]) confObject.uiConfig.language = "en_US"; } - if (Qv2rayTranslator->InstallTranslation(confObject.uiConfig.language)) + if (Qv2rayTranslator.InstallTranslation(confObject.uiConfig.language)) { LOG(MODULE_INIT, "Successfully installed a translator for " + confObject.uiConfig.language); } diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index a116a731..2298c68f 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -41,7 +41,7 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), Current } // We add locales - auto langs = Qv2rayTranslator->GetAvailableLanguages(); + auto langs = Qv2rayTranslator.GetAvailableLanguages(); if (!langs.empty()) { languageComboBox->clear(); @@ -266,7 +266,7 @@ void PreferencesWindow::on_buttonBox_accepted() if (CurrentConfig.uiConfig.language != GlobalConfig.uiConfig.language) { // Install translator - if (Qv2rayTranslator->InstallTranslation(CurrentConfig.uiConfig.language)) + if (Qv2rayTranslator.InstallTranslation(CurrentConfig.uiConfig.language)) { messageBus.EmitGlobalSignal(QvMBMessage::RETRANSLATE); QApplication::processEvents(); From 32ab3119ba53724af5f85fd1e31b63fe70f28123 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 10 Mar 2020 14:45:20 +0800 Subject: [PATCH 285/332] core: refactored log function --- src/base/Qv2rayLog.cpp | 46 +++++++++++++++++++----------------------- src/base/Qv2rayLog.hpp | 6 ------ 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/base/Qv2rayLog.cpp b/src/base/Qv2rayLog.cpp index 2cbd4622..c724c495 100644 --- a/src/base/Qv2rayLog.cpp +++ b/src/base/Qv2rayLog.cpp @@ -14,42 +14,38 @@ namespace Qv2ray::base void __QV2RAY_LOG_FUNC__(int type, const std::string &func, int line, const QString &module, const QString &log) { - auto logString = "[" + module + "]: " + log; + auto logString = QString("[" % module % "]: " % log); auto funcPrepend = QString::fromStdString(func + ":" + to_string(line) + " "); - if (isDebugBuild) +#ifdef QT_DEBUG + // Debug build version, we only print info for DEBUG logs and print + // ALL info when debugLog presents, + if (type == QV2RAY_LOG_DEBUG || StartupOption.debugLog) { - // Debug build version, we only print info for DEBUG logs and print - // ALL info when debugLog presents, - if (type == QV2RAY_LOG_DEBUG || StartupOption.debugLog) + logString.prepend(funcPrepend); + } +#else + // We only process DEBUG log in Release mode + if (type == QV2RAY_LOG_DEBUG) + { + if (StartupOption.debugLog) { - logString = logString.prepend(funcPrepend); + logString.prepend(funcPrepend); + } + else + { + // Discard debug log in non-debug Qv2ray version with + // no-debugLog mode. + return; } } - else - { - // We only process DEBUG log in Release mode - if (type == QV2RAY_LOG_DEBUG) - { - if (StartupOption.debugLog) - { - logString = logString.prepend(funcPrepend); - } - else - { - // Discard debug log in non-debug Qv2ray version with - // no-debugLog mode. - return; - } - } - } - +#endif cout << logString.toStdString() << endl; { QMutexLocker _(&__loggerMutex); __loggerBuffer->append(logString + NEWLINE); } - } + } // namespace Qv2ray::base const QString readLastLog() { diff --git a/src/base/Qv2rayLog.hpp b/src/base/Qv2rayLog.hpp index 2043403a..ea775b9b 100644 --- a/src/base/Qv2rayLog.hpp +++ b/src/base/Qv2rayLog.hpp @@ -7,12 +7,6 @@ using namespace std; * Tiny log module. */ -#ifdef QT_DEBUG -inline const bool isDebugBuild = true; -#else -inline const bool isDebugBuild = false; -#endif - namespace Qv2ray::base { void __QV2RAY_LOG_FUNC__(int type, const std::string &func, int line, const QString &module, const QString &log); From b714216b406844fc8bac92bf86322ded86bc8bfd Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 10 Mar 2020 14:46:09 +0800 Subject: [PATCH 286/332] version: bumped version --- makespec/BUILDVERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 869cd632..686eea15 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4627 \ No newline at end of file +4630 From 8b04b14abbd71de35fa01b617856ad412d3a914b Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 10 Mar 2020 15:07:55 +0800 Subject: [PATCH 287/332] add: return; --- src/ui/editors/w_RoutesEditor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index 073e9471..16ee98e2 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -818,6 +818,7 @@ void RouteEditor::on_editBtn_clicked() if (nodeScene->selectedNodes().empty()) { QvMessageBoxWarn(this, tr("Edit Inbound/Outbound"), tr("Please select a node from the graph to continue.")); + return; } auto firstNode = nodeScene->selectedNodes().at(0); From 8f4e9ec7528dbae317b2cab127ab03f9676619b9 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 10 Mar 2020 16:50:26 +0800 Subject: [PATCH 288/332] ui: reverted add a vertical spacer under scrollable widget --- src/ui/w_MainWindow.ui | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index c05dfcd9..bc7b2573 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -246,9 +246,9 @@ 0 - 0 - 459 - 784 + -188 + 480 + 746 @@ -418,22 +418,6 @@ - - - - Qt::Vertical - - - QSizePolicy::MinimumExpanding - - - - 20 - 0 - - - - From 55f65a2a5f8fab71c5a97c701452af2ff4e16db4 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 10 Mar 2020 21:46:55 +0800 Subject: [PATCH 289/332] fix: this fixed #347 --- src/core/CoreUtils.hpp | 6 ++-- src/core/connection/Generation.cpp | 9 ++++- src/core/connection/Serialization.cpp | 9 ++++- src/ui/editors/w_RoutesEditor.cpp | 25 +++++++------- src/ui/editors/w_RoutesEditor.hpp | 6 ++-- src/ui/editors/w_RoutesEditor_extra.cpp | 44 ++++++++++++------------- src/ui/widgets/ConnectionInfoWidget.ui | 3 -- 7 files changed, 55 insertions(+), 47 deletions(-) diff --git a/src/core/CoreUtils.hpp b/src/core/CoreUtils.hpp index a01c9798..b5c1af08 100644 --- a/src/core/CoreUtils.hpp +++ b/src/core/CoreUtils.hpp @@ -12,17 +12,17 @@ namespace Qv2ray::core using namespace Qv2ray::base::safetype; using namespace Qv2ray::base::objects; // - inline QString getTag(const INBOUND &in) + inline const QString getTag(const INBOUND &in) { return in["tag"].toString(); } - inline QString getTag(const OUTBOUND &in) + inline const QString getTag(const OUTBOUND &in) { return in["tag"].toString(); } - inline QString getTag(const RuleObject &in) + inline const QString getTag(const RuleObject &in) { return in.QV2RAY_RULE_TAG; } diff --git a/src/core/connection/Generation.cpp b/src/core/connection/Generation.cpp index f65ff1a2..5ae0c111 100644 --- a/src/core/connection/Generation.cpp +++ b/src/core/connection/Generation.cpp @@ -413,7 +413,14 @@ namespace Qv2ray::core::connection } else { - LOG(MODULE_CONNECTION, "WARNING: Unsupported outbound type: " + fpConf.type) + if (!fpConf.type.isEmpty()) + { + DEBUG(MODULE_CONNECTION, "WARNING: Unsupported outbound type: " + fpConf.type) + } + else + { + DEBUG(MODULE_CONNECTION, "WARNING: Empty outbound type.") + } } } else diff --git a/src/core/connection/Serialization.cpp b/src/core/connection/Serialization.cpp index 6c6bd17b..3b3f0600 100644 --- a/src/core/connection/Serialization.cpp +++ b/src/core/connection/Serialization.cpp @@ -63,7 +63,14 @@ namespace Qv2ray::core::connection } else { - LOG(MODULE_CONNECTION, "Unsupported outbound type: " + type) + if (!type.isEmpty()) + { + // DEBUG(MODULE_CONNECTION, "WARNING: Unsupported outbound type: " + type) + } + else + { + DEBUG(MODULE_CONNECTION, "WARNING: Empty outbound type.") + } } return sharelink; diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index 16ee98e2..65fcbc0f 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -97,24 +97,22 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QDialog(pare // Show connections in the node graph for (auto in : root["inbounds"].toArray()) { - INBOUND _in = INBOUND(in.toObject()); - AddInbound(_in); + AddInbound(INBOUND(in.toObject())); } for (auto out : root["outbounds"].toArray()) { - OUTBOUND _out = OUTBOUND(out.toObject()); - AddOutbound(_out); + AddOutbound(OUTBOUND(out.toObject())); } for (auto item : root["routing"].toObject()["rules"].toArray()) { - auto _rule = StructFromJsonString(JsonToString(item.toObject())); - AddRule(_rule); + AddRule(StructFromJsonString(JsonToString(item.toObject()))); } // Set default outboung combo text AFTER adding all outbounds. - defaultOutboundCombo->setCurrentText(root["outbounds"].toArray().first().toObject()["tag"].toString()); + defaultOutbound = getTag(OUTBOUND(root["outbounds"].toArray().first().toObject())); + defaultOutboundCombo->setCurrentText(defaultOutbound); // Find and add balancers. for (auto _balancer : root["routing"].toObject()["balancers"].toArray()) @@ -123,7 +121,7 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QDialog(pare if (!_balancerObject["tag"].toString().isEmpty()) { - balancers[_balancerObject["tag"].toString()] = _balancerObject["selector"].toVariant().toStringList(); + balancers.insert(_balancerObject["tag"].toString(), _balancerObject["selector"].toVariant().toStringList()); } } @@ -437,10 +435,9 @@ void RouteEditor::ShowCurrentRuleDetail() ruleTagLineEdit->setText(CurrentRule.QV2RAY_RULE_TAG); balancerSelectionCombo->clear(); - // BUG added the wrong items, should be outbound list. for (auto out : outbounds) { - balancerSelectionCombo->addItem((out)["tag"].toString()); + balancerSelectionCombo->addItem(getTag(OUTBOUND(out))); } // @@ -821,7 +818,7 @@ void RouteEditor::on_editBtn_clicked() return; } - auto firstNode = nodeScene->selectedNodes().at(0); + auto firstNode = nodeScene->selectedNodes().front(); auto isInbound = inboundNodes.values().contains(firstNode); auto isOutbound = outboundNodes.values().contains(firstNode); @@ -872,7 +869,7 @@ void RouteEditor::on_editBtn_clicked() DEBUG(MODULE_UI, "Removed old tag: " + getTag(_in)) inbounds.remove(getTag(_in)); DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result)) - inbounds[getTag(_result)] = _result; + inbounds.insert(getTag(_result), _result); } } else if (isOutbound) @@ -886,7 +883,7 @@ void RouteEditor::on_editBtn_clicked() } OUTBOUND _result; - auto _out = outbounds[currentInboundOutboundTag]; + auto _out = outbounds.value(currentInboundOutboundTag); auto protocol = _out["protocol"].toString().toLower(); int _code; @@ -921,7 +918,7 @@ void RouteEditor::on_editBtn_clicked() } DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result)) - outbounds[getTag(_result)] = _result; + outbounds.insert(getTag(_result), _result); statusLabel->setText(tr("OK")); } } diff --git a/src/ui/editors/w_RoutesEditor.hpp b/src/ui/editors/w_RoutesEditor.hpp index 03826885..ade42590 100644 --- a/src/ui/editors/w_RoutesEditor.hpp +++ b/src/ui/editors/w_RoutesEditor.hpp @@ -121,9 +121,9 @@ class RouteEditor // // ---------------------------- Node Graph Impl -------------------------- void SetupNodeWidget(); - QMap inboundNodes; - QMap outboundNodes; - QMap ruleNodes; + QHash inboundNodes; + QHash outboundNodes; + QHash ruleNodes; // FlowScene *nodeScene; // ---------------------------- Extra Source File Headers ---------------- diff --git a/src/ui/editors/w_RoutesEditor_extra.cpp b/src/ui/editors/w_RoutesEditor_extra.cpp index cdbb3b22..c9a414cd 100644 --- a/src/ui/editors/w_RoutesEditor_extra.cpp +++ b/src/ui/editors/w_RoutesEditor_extra.cpp @@ -23,8 +23,8 @@ void RouteEditor::AddInbound(INBOUND in) pos.setX(0 + GRAPH_GLOBAL_OFFSET_X); pos.setY(inboundNodes.count() * 130 + GRAPH_GLOBAL_OFFSET_Y); nodeScene->setNodePosition(node, pos); - inboundNodes[tag] = &node; - inbounds[getTag(in)] = in; + inboundNodes.insert(tag, &node); + inbounds.insert(getTag(in), in); } void RouteEditor::AddOutbound(OUTBOUND out) @@ -43,8 +43,8 @@ void RouteEditor::AddOutbound(OUTBOUND out) pos.setY(pos.y() + outboundNodes.count() * 120 + GRAPH_GLOBAL_OFFSET_Y); auto &node = nodeScene->createNode(std::move(_nodeData)); nodeScene->setNodePosition(node, pos); - outboundNodes[tag] = &node; - outbounds[tag] = out; + outboundNodes.insert(tag, &node); + outbounds.insert(tag, out); defaultOutboundCombo->addItem(tag); } @@ -72,7 +72,7 @@ void RouteEditor::AddRule(RuleObject rule) rule.QV2RAY_RULE_TAG += "-" + GenerateRandomString(5); } - rules[rule.QV2RAY_RULE_TAG] = rule; + rules.insert(rule.QV2RAY_RULE_TAG, rule); auto pos = nodeGraphWidget->pos(); pos.setX(pos.x() + 350 + GRAPH_GLOBAL_OFFSET_X); pos.setY(pos.y() + ruleNodes.count() * 120 + GRAPH_GLOBAL_OFFSET_Y); @@ -90,7 +90,7 @@ void RouteEditor::AddRule(RuleObject rule) } else { - auto inboundNode = inboundNodes[inTag]; + auto inboundNode = inboundNodes.value(inTag); nodeScene->createConnection(node, 0, *inboundNode, 0); } } @@ -101,7 +101,7 @@ void RouteEditor::AddRule(RuleObject rule) if (outboundNodes.contains(rule.outboundTag)) { DEBUG(MODULE_GRAPH, "Found outbound tag: " + rule.outboundTag + ", for rule: " + rule.QV2RAY_RULE_TAG) - nodeScene->createConnection(*outboundNodes[rule.outboundTag], 0, node, 0); + nodeScene->createConnection(*outboundNodes.value(rule.outboundTag), 0, node, 0); } else { @@ -111,7 +111,7 @@ void RouteEditor::AddRule(RuleObject rule) } } - this->ruleNodes[rule.QV2RAY_RULE_TAG] = &node; + this->ruleNodes.insert(rule.QV2RAY_RULE_TAG, &node); ruleListWidget->addItem(rule.QV2RAY_RULE_TAG); } @@ -123,13 +123,13 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, case RENAME_RULE: if (rules.contains(originalTag) && ruleNodes.contains(originalTag)) { - if (rules.contains(newTag) && rules.contains(newTag)) + if (rules.contains(newTag) && ruleNodes.contains(newTag)) { QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a postfix.")); newTag += "_" + GenerateRandomString(5); } - auto node = static_cast(ruleNodes[originalTag]->nodeDataModel()); + auto node = static_cast(ruleNodes.value(originalTag)->nodeDataModel()); if (node == nullptr) { @@ -138,7 +138,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, node->setData(newTag); // - rules[newTag] = rules.take(originalTag); + rules.insert(newTag, rules.take(originalTag)); rules[newTag].QV2RAY_RULE_TAG = newTag; ruleNodes[newTag] = ruleNodes.take(originalTag); // @@ -172,13 +172,13 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, { if (outbounds.contains(newTag) && outboundNodes.contains(newTag)) { - QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a postfix.")); + QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a random string to the tag.")); newTag += "_" + GenerateRandomString(5); } - outbounds[newTag] = outbounds.take(originalTag); - outboundNodes[newTag] = outboundNodes.take(originalTag); - auto node = static_cast(outboundNodes[newTag]->nodeDataModel()); + outbounds.insert(newTag, outbounds.take(originalTag)); + outboundNodes.insert(newTag, outboundNodes.take(originalTag)); + auto node = static_cast(outboundNodes.value(newTag)->nodeDataModel()); if (node == nullptr) { @@ -190,14 +190,14 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, // Change outbound tag in rules accordingly. for (auto k : rules.keys()) { - auto v = rules[k]; + auto v = rules.value(k); if (v.outboundTag == originalTag) { v.outboundTag = newTag; // Put this inside the if block since no need an extra // operation if the condition is false. - rules[k] = v; + rules.insert(k, v); } } @@ -220,9 +220,9 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, newTag += "_" + GenerateRandomString(5); } - inbounds[newTag] = inbounds.take(originalTag); - inboundNodes[newTag] = inboundNodes.take(originalTag); - auto node = static_cast(inboundNodes[newTag]->nodeDataModel()); + inbounds.insert(newTag, inbounds.take(originalTag)); + inboundNodes.insert(newTag, inboundNodes.take(originalTag)); + auto node = static_cast(inboundNodes.value(newTag)->nodeDataModel()); if (node == nullptr) { @@ -236,7 +236,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, // v -> rule object for (auto k : rules.keys()) { - auto v = rules[k]; + auto v = rules.value(k); if (v.inboundTag.contains(originalTag)) { @@ -244,7 +244,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, v.inboundTag.removeAll(originalTag); // Put this inside the if block since no need an extra // operation if the condition is false. - rules[k] = v; + rules.insert(k, v); } } } diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index 8284fef2..4fa59c7d 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -303,9 +303,6 @@ QR Code - - QFrame::Box - From f6378c9e014862456cc5545088c16318f04b7fb6 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Tue, 10 Mar 2020 22:19:44 +0800 Subject: [PATCH 290/332] clang-format: cleaning up Optimized by using a linter. Much thanks to the powerful IntelliJ CLion. --- _clang-format | 62 +++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/_clang-format b/_clang-format index 8586680d..28c9f4b1 100644 --- a/_clang-format +++ b/_clang-format @@ -1,50 +1,50 @@ --- BasedOnStyle: Microsoft -AccessModifierOffset: '-2' +AccessModifierOffset: -2 AlignAfterOpenBracket: Align -AllowAllArgumentsOnNextLine: 'false' -AllowAllConstructorInitializersOnNextLine: 'false' -AllowAllParametersOfDeclarationOnNextLine: 'false' -AllowShortBlocksOnASingleLine: 'false' -AllowShortCaseLabelsOnASingleLine: 'true' +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: 'false' +AllowShortIfStatementsOnASingleLine: Never AllowShortLambdasOnASingleLine: Inline -AllowShortLoopsOnASingleLine: 'true' +AllowShortLoopsOnASingleLine: true AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: 'false' -AlwaysBreakTemplateDeclarations: 'Yes' -BinPackArguments: 'true' -BinPackParameters: 'true' +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true BreakBeforeBraces: Allman -BreakBeforeTernaryOperators: 'false' +BreakBeforeTernaryOperators: false BreakInheritanceList: BeforeComma -BreakStringLiterals: 'false' -ColumnLimit: '145' -CompactNamespaces: 'false' -ConstructorInitializerAllOnOneLineOrOnePerLine: 'false' -Cpp11BracedListStyle: 'false' -ExperimentalAutoDetectBinPacking: 'false' -FixNamespaceComments: 'true' +BreakStringLiterals: false +ColumnLimit: 145 +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +Cpp11BracedListStyle: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true IncludeBlocks: Regroup -IndentCaseLabels: 'true' +IndentCaseLabels: true IndentPPDirectives: BeforeHash -IndentWidth: '4' +IndentWidth: 4 Language: Cpp -MaxEmptyLinesToKeep: '1' +MaxEmptyLinesToKeep: 1 NamespaceIndentation: All -ReflowComments: 'true' -SortIncludes: 'true' -SortUsingDeclarations: 'true' -SpaceAfterCStyleCast: 'true' -SpaceAfterTemplateKeyword: 'false' +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterTemplateKeyword: false SpaceBeforeParens: ControlStatements -SpaceBeforeRangeBasedForLoopColon: 'true' -SpacesInParentheses: 'false' +SpaceBeforeRangeBasedForLoopColon: true +SpacesInParentheses: false Standard: Cpp11 StatementMacros: [ Q_UNUSED LOG DEBUG ] -TabWidth: '4' +TabWidth: 4 UseTab: Never ... From 485d92e5a8d235e5b84a9e923bcb9857a5b68744 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Tue, 10 Mar 2020 22:53:53 +0800 Subject: [PATCH 291/332] fix: this fixed #344 --- src/ui/editors/w_RoutesEditor.cpp | 10 ++--- src/ui/editors/w_RoutesEditor.hpp | 2 +- src/ui/editors/w_RoutesEditor_extra.cpp | 53 +++++++++++++------------ 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index 65fcbc0f..3f9d9c15 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -863,7 +863,8 @@ void RouteEditor::on_editBtn_clicked() if (isTagChanged) { - RenameItemTag(RENAME_INBOUND, getTag(_in), getTag(_result)); + auto newTag = getTag(_result); + RenameItemTag(RENAME_INBOUND, getTag(_in), &newTag); } DEBUG(MODULE_UI, "Removed old tag: " + getTag(_in)) @@ -912,9 +913,8 @@ void RouteEditor::on_editBtn_clicked() if (isTagChanged) { DEBUG(MODULE_UI, "Outbound tag is changed: " + QString(isTagChanged)) - RenameItemTag(RENAME_OUTBOUND, getTag(_out), getTag(_result)); - DEBUG(MODULE_UI, "Removed old tag: " + getTag(_out)) - outbounds.remove(getTag(_out)); + auto newTag = getTag(_result); + RenameItemTag(RENAME_OUTBOUND, getTag(_out), &newTag); } DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result)) @@ -961,6 +961,6 @@ void RouteEditor::on_ruleRenameBtn_clicked() } else { - RenameItemTag(RENAME_RULE, CurrentRule.QV2RAY_RULE_TAG, newTag); + RenameItemTag(RENAME_RULE, CurrentRule.QV2RAY_RULE_TAG, &newTag); } } diff --git a/src/ui/editors/w_RoutesEditor.hpp b/src/ui/editors/w_RoutesEditor.hpp index ade42590..427ea6a1 100644 --- a/src/ui/editors/w_RoutesEditor.hpp +++ b/src/ui/editors/w_RoutesEditor.hpp @@ -103,7 +103,7 @@ class RouteEditor void onConnectionDeleted(QtNodes::Connection const &c); private: - void RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, const QString newTag); + void RenameItemTag(ROUTE_EDIT_MODE mode, const QString &originalTag, QString *newTag); void ShowCurrentRuleDetail(); // QString currentRuleTag; diff --git a/src/ui/editors/w_RoutesEditor_extra.cpp b/src/ui/editors/w_RoutesEditor_extra.cpp index c9a414cd..5c4c31e4 100644 --- a/src/ui/editors/w_RoutesEditor_extra.cpp +++ b/src/ui/editors/w_RoutesEditor_extra.cpp @@ -116,17 +116,17 @@ void RouteEditor::AddRule(RuleObject rule) } // Do not use reference here, we need deep -void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, QString newTag) +void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString &originalTag, QString *newTag) { switch (mode) { case RENAME_RULE: if (rules.contains(originalTag) && ruleNodes.contains(originalTag)) { - if (rules.contains(newTag) && ruleNodes.contains(newTag)) + if (rules.contains(*newTag) && ruleNodes.contains(*newTag)) { QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a postfix.")); - newTag += "_" + GenerateRandomString(5); + *newTag += "_" + GenerateRandomString(5); } auto node = static_cast(ruleNodes.value(originalTag)->nodeDataModel()); @@ -136,11 +136,11 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, LOG(MODULE_GRAPH, "EMPTY NODE WARN") } - node->setData(newTag); + node->setData(*newTag); // - rules.insert(newTag, rules.take(originalTag)); - rules[newTag].QV2RAY_RULE_TAG = newTag; - ruleNodes[newTag] = ruleNodes.take(originalTag); + rules.insert(*newTag, rules.take(originalTag)); + rules[*newTag].QV2RAY_RULE_TAG = *newTag; + ruleNodes[*newTag] = ruleNodes.take(originalTag); // // No other operation needed, but need to rename the one in the // ruleOrder list widget. @@ -152,12 +152,12 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, } else { - items.first()->setText(newTag); + items.first()->setText(*newTag); } if (currentRuleTag == originalTag) { - currentRuleTag = newTag; + currentRuleTag = *newTag; } } else @@ -170,22 +170,24 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, case RENAME_OUTBOUND: if (outbounds.contains(originalTag) && outboundNodes.contains(originalTag)) { - if (outbounds.contains(newTag) && outboundNodes.contains(newTag)) + if (outbounds.contains(*newTag) && outboundNodes.contains(*newTag)) { QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a random string to the tag.")); - newTag += "_" + GenerateRandomString(5); + *newTag += "_" + GenerateRandomString(5); } - outbounds.insert(newTag, outbounds.take(originalTag)); - outboundNodes.insert(newTag, outboundNodes.take(originalTag)); - auto node = static_cast(outboundNodes.value(newTag)->nodeDataModel()); + auto out = outbounds.take(originalTag); + out["tag"] = *newTag; + outbounds.insert(*newTag, out); + outboundNodes.insert(*newTag, outboundNodes.take(originalTag)); + auto node = static_cast(outboundNodes.value(*newTag)->nodeDataModel()); if (node == nullptr) { LOG(MODULE_GRAPH, "EMPTY NODE WARN") } - node->setData(newTag); + node->setData(*newTag); // Change outbound tag in rules accordingly. for (auto k : rules.keys()) @@ -194,7 +196,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, if (v.outboundTag == originalTag) { - v.outboundTag = newTag; + v.outboundTag = *newTag; // Put this inside the if block since no need an extra // operation if the condition is false. rules.insert(k, v); @@ -202,7 +204,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, } // Resolve default outbound. - ResolveDefaultOutboundTag(originalTag, newTag); + ResolveDefaultOutboundTag(originalTag, *newTag); } else { @@ -214,22 +216,23 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, case RENAME_INBOUND: if (inbounds.contains(originalTag) && inboundNodes.contains(originalTag)) { - if (inbounds.contains(newTag) && inboundNodes.contains(newTag)) + if (inbounds.contains(*newTag) && inboundNodes.contains(*newTag)) { QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a postfix.")); - newTag += "_" + GenerateRandomString(5); + *newTag += "_" + GenerateRandomString(5); } - - inbounds.insert(newTag, inbounds.take(originalTag)); - inboundNodes.insert(newTag, inboundNodes.take(originalTag)); - auto node = static_cast(inboundNodes.value(newTag)->nodeDataModel()); + auto in = inbounds.take(originalTag); + in["tag"] = *newTag; + inbounds.insert(*newTag, in); + inboundNodes.insert(*newTag, inboundNodes.take(originalTag)); + auto node = static_cast(inboundNodes.value(*newTag)->nodeDataModel()); if (node == nullptr) { LOG(MODULE_GRAPH, "EMPTY NODE WARN") } - node->setData(newTag); + node->setData(*newTag); // Change inbound tag in rules accordingly. // k -> rule tag @@ -240,7 +243,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, if (v.inboundTag.contains(originalTag)) { - v.inboundTag.append(newTag); + v.inboundTag.append(*newTag); v.inboundTag.removeAll(originalTag); // Put this inside the if block since no need an extra // operation if the condition is false. From f972c7baab1e637fc066c865fd34725b6ae01583 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Wed, 11 Mar 2020 00:01:16 +0800 Subject: [PATCH 292/332] [WIP] Code Cleanup Project Phase 1 (#409) * verifyConfigAvailability: typo fix & const tweak * "openwrite" => open a file for writing * initialiseQv2ray: use const reference in for-loop * typo: "translater" => translator * optimizing std::unique_ptr * readLastLog: removing const qualifier for return type --- src/base/Qv2rayLog.cpp | 4 ++-- src/base/Qv2rayLog.hpp | 2 +- src/main.cpp | 19 ++++++++++--------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/base/Qv2rayLog.cpp b/src/base/Qv2rayLog.cpp index c724c495..3725b256 100644 --- a/src/base/Qv2rayLog.cpp +++ b/src/base/Qv2rayLog.cpp @@ -47,11 +47,11 @@ namespace Qv2ray::base } } // namespace Qv2ray::base - const QString readLastLog() + QString readLastLog() { QMutexLocker _(&__purgerMutex); { - QMutexLocker _(&__loggerMutex); + QMutexLocker locker(&__loggerMutex); __loggerBuffer.swap(__purgerBuffer); } auto result = __purgerBuffer->join(""); diff --git a/src/base/Qv2rayLog.hpp b/src/base/Qv2rayLog.hpp index ea775b9b..98c83378 100644 --- a/src/base/Qv2rayLog.hpp +++ b/src/base/Qv2rayLog.hpp @@ -10,7 +10,7 @@ using namespace std; namespace Qv2ray::base { void __QV2RAY_LOG_FUNC__(int type, const std::string &func, int line, const QString &module, const QString &log); - const QString readLastLog(); + QString readLastLog(); } // namespace Qv2ray::base #define NEWLINE "\r\n" diff --git a/src/main.cpp b/src/main.cpp index c86176cd..994c2f6c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef Q_OS_UNIX // For unix root user check @@ -27,7 +28,7 @@ void signalHandler(int signum) qApp->exit(-99); } -bool verifyConfigAvaliability(QString path, bool checkExistingConfig) +bool verifyConfigAvailability(const QString& path, bool checkExistingConfig) { // Does not exist. if (!QDir(path).exists()) @@ -40,7 +41,7 @@ bool verifyConfigAvaliability(QString path, bool checkExistingConfig) if (!opened) { LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.") - LOG(MODULE_INIT, "---> Cannot create a new file or openwrite a file.") + LOG(MODULE_INIT, "---> Cannot create a new file or open a file for writing.") return false; } else @@ -142,12 +143,12 @@ bool initialiseQv2ray() QString configPath = ""; bool hasExistingConfig = false; - for (auto path : configFilePaths) + for (const auto& path : configFilePaths) { // Verify the config path, check if the config file exists and in the - // correct JSON format. True means we check for config existance as + // correct JSON format. True means we check for config existence as // well. --|HERE | - bool isValidConfigPath = verifyConfigAvaliability(path, true); + bool isValidConfigPath = verifyConfigAvailability(path, true); // If we already found a valid config file. just simply load it... if (hasExistingConfig) @@ -185,7 +186,7 @@ bool initialiseQv2ray() bool mkpathResult = QDir().mkpath(configPath); // Check if the dirs are write-able - if (mkpathResult && verifyConfigAvaliability(configPath, false)) + if (mkpathResult && verifyConfigAvailability(configPath, false)) { // Found a valid config dir, with write permission, but assume no // config is located in it. @@ -256,8 +257,8 @@ int main(int argc, char *argv[]) { std::unique_ptr consoleApp(new QCoreApplication(argc, argv)); // - // Install a default translater. From the OS/DE - Qv2rayTranslator.reset(std::move(new QvTranslator())); + // Install a default translator. From the OS/DE + Qv2rayTranslator = std::make_unique(); Qv2rayTranslator->InstallTranslation(QLocale::system().name()); QvCommandArgParser parser; QString errorMessage; @@ -328,7 +329,7 @@ int main(int argc, char *argv[]) // Not duplicated. // Install a default translater. From the OS/DE auto _lang = QLocale::system().name(); - Qv2rayTranslator.reset(std::move(new QvTranslator())); + Qv2rayTranslator = std::make_unique(); bool _result_ = Qv2rayTranslator->InstallTranslation(_lang); LOG(MODULE_UI, "Installing a tranlator from OS: " + _lang + " -- " + (_result_ ? "OK" : "Failed")) // From df6995e2536add15bde71bf5be9da3d768fb804f Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 00:05:54 +0800 Subject: [PATCH 293/332] fix: used a hack to fix #343 --- makespec/BUILDVERSION | 2 +- src/components/pac/QvPACHandler.cpp | 6 +++++- src/core/handler/ConfigHandler.cpp | 2 +- src/ui/editors/w_RoutesEditor_extra.cpp | 6 ++++-- src/ui/widgets/ConnectionItemWidget.cpp | 12 +++++++----- src/ui/widgets/ConnectionItemWidget.hpp | 1 + 6 files changed, 19 insertions(+), 10 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 686eea15..53d48984 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4630 +4631 \ No newline at end of file diff --git a/src/components/pac/QvPACHandler.cpp b/src/components/pac/QvPACHandler.cpp index dce127a9..0171a59b 100644 --- a/src/components/pac/QvPACHandler.cpp +++ b/src/components/pac/QvPACHandler.cpp @@ -13,6 +13,7 @@ namespace Qv2ray::components::pac } PACServer::~PACServer() { + StopServer(); delete pacServer; } void PACServer::SetProxyString(const QString &proxyString) @@ -47,7 +48,10 @@ namespace Qv2ray::components::pac void PACServer::StopServer() { - pacServer->stop(); + if (pacServer->is_running()) + { + pacServer->stop(); + } } void PACServer::onNewRequest(const httplib::Request &req, httplib::Response &rsp) diff --git a/src/core/handler/ConfigHandler.cpp b/src/core/handler/ConfigHandler.cpp index 2fddb0c3..e9505725 100644 --- a/src/core/handler/ConfigHandler.cpp +++ b/src/core/handler/ConfigHandler.cpp @@ -563,8 +563,8 @@ namespace Qv2ray::core::handlers connections[newId].groupId = groupId; connections[newId].importDate = system_clock::to_time_t(system_clock::now()); connections[newId].displayName = displayName; - UpdateConnection(newId, root); emit OnConnectionCreated(newId, displayName); + UpdateConnection(newId, root); return newId; } diff --git a/src/ui/editors/w_RoutesEditor_extra.cpp b/src/ui/editors/w_RoutesEditor_extra.cpp index 5c4c31e4..bf3738ec 100644 --- a/src/ui/editors/w_RoutesEditor_extra.cpp +++ b/src/ui/editors/w_RoutesEditor_extra.cpp @@ -91,7 +91,8 @@ void RouteEditor::AddRule(RuleObject rule) else { auto inboundNode = inboundNodes.value(inTag); - nodeScene->createConnection(node, 0, *inboundNode, 0); + auto conn = nodeScene->createConnection(node, 0, *inboundNode, 0); + connect(conn.get(), &QtNodes::Connection::connectionCompleted, this, &RouteEditor::onConnectionCreated); } } @@ -101,7 +102,8 @@ void RouteEditor::AddRule(RuleObject rule) if (outboundNodes.contains(rule.outboundTag)) { DEBUG(MODULE_GRAPH, "Found outbound tag: " + rule.outboundTag + ", for rule: " + rule.QV2RAY_RULE_TAG) - nodeScene->createConnection(*outboundNodes.value(rule.outboundTag), 0, node, 0); + auto conn = nodeScene->createConnection(*outboundNodes.value(rule.outboundTag), 0, node, 0); + connect(conn.get(), &QtNodes::Connection::connectionCompleted, this, &RouteEditor::onConnectionCreated); } else { diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index 8663944b..0c5c51af 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -4,7 +4,7 @@ #include -ConnectionItemWidget::ConnectionItemWidget(QWidget *parent) : QWidget(parent), connectionId("null"), groupId("null") +ConnectionItemWidget::ConnectionItemWidget(QWidget *parent) : QWidget(parent), connectionId(NullConnectionId), groupId(NullGroupId) { setupUi(this); connect(ConnectionManager, &QvConfigHandler::OnConnected, this, &ConnectionItemWidget::OnConnected); @@ -39,10 +39,7 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare // // Rename events connect(renameTxt, &QLineEdit::returnPressed, this, &ConnectionItemWidget::on_doRenameBtn_clicked); - connect(ConnectionManager, &QvConfigHandler::OnConnectionModified, [&](const ConnectionId &id) { - if (id == connectionId) - connTypeLabel->setText(tr("Type: ") + GetConnectionProtocolString(id)); // - }); + connect(ConnectionManager, &QvConfigHandler::OnConnectionModified, this, &ConnectionItemWidget::OnConnectionModified); } // ======================================= Initialisation for root nodes. @@ -133,6 +130,11 @@ void ConnectionItemWidget::OnConnectionStatsArrived(const ConnectionId &id, cons dataLabel->setText(FormatBytes(totalUp) + " / " + FormatBytes(totalDown)); } } +void ConnectionItemWidget::OnConnectionModified(const ConnectionId &id) +{ + if (connectionId == id) + connTypeLabel->setText(tr("Type: ") + GetConnectionProtocolString(id)); +} void ConnectionItemWidget::OnLatencyTestStart(const ConnectionId &id) { diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index e3960af2..d5467cd3 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -54,6 +54,7 @@ class ConnectionItemWidget void OnConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id); void OnLatencyTestStart(const ConnectionId &id); + void OnConnectionModified(const ConnectionId &id); void OnLatencyTestFinished(const ConnectionId &id, const uint average); inline void RecalculateConnectionsCount() { From beff148dbf225b12661bd9fabe8f8676eb9a3d7f Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Wed, 11 Mar 2020 08:59:50 +0800 Subject: [PATCH 294/332] use lxd for snapcraft --- .travis.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index bc4bb28f..3443d51d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,12 +19,14 @@ addons: - name: snapcraft channel: stable confinement: classic - - name: multipass + - name: lxd channel: stable - confinement: classic script: - - sudo snapcraft + - sudo apt autoremove lxd --purge + - sudo /snap/bin/lxd waitready + - sudo /snap/bin/lxd init --auto + - sudo snapcraft --use-lxd after_failure: - sudo journalctl -u snapd From aa35609d4a14d11760a4b3d5a9d8e0afa43eb5bb Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Wed, 11 Mar 2020 09:20:39 +0800 Subject: [PATCH 295/332] update cmake plugin for snap --- snap/plugins/x_cmake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/plugins/x_cmake.py b/snap/plugins/x_cmake.py index 0a5c2db8..4680fc11 100644 --- a/snap/plugins/x_cmake.py +++ b/snap/plugins/x_cmake.py @@ -125,7 +125,7 @@ class CMakePlugin(snapcraft.BasePlugin): env = self._build_environment() configflags = self._get_processed_flags() - self.run(["cmake", sourcedir, "-DCMAKE_INSTALL_PREFIX="] + configflags, env=env) + self.run(["cmake", sourcedir] + configflags, env=env) # TODO: there is a better way to specify the job count on newer versions of cmake # https://github.com/Kitware/CMake/commit/1ab3881ec9e809ac5f6cad5cd84048310b8683e2 From f18b683ff1b81727a3f79d3628e202edd366e086 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Wed, 11 Mar 2020 09:36:11 +0800 Subject: [PATCH 296/332] Revert "update cmake plugin for snap" This reverts commit aa35609d4a14d11760a4b3d5a9d8e0afa43eb5bb. --- snap/plugins/x_cmake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/plugins/x_cmake.py b/snap/plugins/x_cmake.py index 4680fc11..0a5c2db8 100644 --- a/snap/plugins/x_cmake.py +++ b/snap/plugins/x_cmake.py @@ -125,7 +125,7 @@ class CMakePlugin(snapcraft.BasePlugin): env = self._build_environment() configflags = self._get_processed_flags() - self.run(["cmake", sourcedir] + configflags, env=env) + self.run(["cmake", sourcedir, "-DCMAKE_INSTALL_PREFIX="] + configflags, env=env) # TODO: there is a better way to specify the job count on newer versions of cmake # https://github.com/Kitware/CMake/commit/1ab3881ec9e809ac5f6cad5cd84048310b8683e2 From 675393e99415936de64e203c35be03ed788fe2d5 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Wed, 11 Mar 2020 09:36:43 +0800 Subject: [PATCH 297/332] update snapcraft.yaml --- snap/snapcraft.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index dc218105..ee7afb20 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -69,7 +69,6 @@ parts: - libqt5widgets5 - libglib2.0-bin configflags: - - -DCMAKE_INSTALL_PREFIX=/usr - -DCMAKE_BUILD_TYPE=Release - -GNinja - -DEMBED_TRANSLATIONS=ON From fca958d7ea9d21acad051b9caf3e78675d0dc049 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Wed, 11 Mar 2020 09:48:26 +0800 Subject: [PATCH 298/332] Revert "update snapcraft.yaml" This reverts commit 675393e99415936de64e203c35be03ed788fe2d5. --- snap/snapcraft.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index ee7afb20..dc218105 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -69,6 +69,7 @@ parts: - libqt5widgets5 - libglib2.0-bin configflags: + - -DCMAKE_INSTALL_PREFIX=/usr - -DCMAKE_BUILD_TYPE=Release - -GNinja - -DEMBED_TRANSLATIONS=ON From d4e35c5ee187a69e6ad992edb3115d89522707bd Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 13:32:15 +0800 Subject: [PATCH 299/332] fix: fixed a swapped default path setting --- src/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 994c2f6c..b54cfe86 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,7 +28,7 @@ void signalHandler(int signum) qApp->exit(-99); } -bool verifyConfigAvailability(const QString& path, bool checkExistingConfig) +bool verifyConfigAvailability(const QString &path, bool checkExistingConfig) { // Does not exist. if (!QDir(path).exists()) @@ -143,7 +143,7 @@ bool initialiseQv2ray() QString configPath = ""; bool hasExistingConfig = false; - for (const auto& path : configFilePaths) + for (const auto &path : configFilePaths) { // Verify the config path, check if the config file exists and in the // correct JSON format. True means we check for config existence as @@ -210,8 +210,8 @@ bool initialiseQv2ray() } Qv2rayConfig conf; - conf.kernelConfig.KernelPath(QString(QV2RAY_DEFAULT_VASSETS_PATH)); - conf.kernelConfig.AssetsPath(QString(QV2RAY_DEFAULT_VCORE_PATH)); + conf.kernelConfig.KernelPath(QString(QV2RAY_DEFAULT_VCORE_PATH)); + conf.kernelConfig.AssetsPath(QString(QV2RAY_DEFAULT_VASSETS_PATH)); conf.logLevel = 3; // // Save initial config. From 726ace5db045b56959fd6aa0bbc6d4acf8f1f5a6 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 13:42:08 +0800 Subject: [PATCH 300/332] rm: removed export config window --- src/ui/w_ExportConfig.cpp | 86 -------------------------- src/ui/w_ExportConfig.hpp | 37 ----------- src/ui/w_ExportConfig.ui | 127 -------------------------------------- 3 files changed, 250 deletions(-) delete mode 100644 src/ui/w_ExportConfig.cpp delete mode 100644 src/ui/w_ExportConfig.hpp delete mode 100644 src/ui/w_ExportConfig.ui diff --git a/src/ui/w_ExportConfig.cpp b/src/ui/w_ExportConfig.cpp deleted file mode 100644 index 49704c06..00000000 --- a/src/ui/w_ExportConfig.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "w_ExportConfig.hpp" - -#include "common/QvHelpers.hpp" -#include "core/connection/Serialization.hpp" - -#include - -// Private initialiser -ConfigExporter::ConfigExporter(QWidget *parent) : QDialog(parent), qzxing(this) -{ - setupUi(this); - QvMessageBusConnect(ConfigExporter); -} - -QvMessageBusSlotImpl(ConfigExporter) -{ - switch (msg) - { - MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl - } -} - -ConfigExporter::~ConfigExporter() -{ -} - -// ConfigExporter::ConfigExporter(QWidget *parent) : ConfigExporter(parent) -//{ -// // WIP -// // /auto &x = connection; -// //message = ConvertConfigToString(root, alias.IdentifierString()); -// // -// QZXingEncoderConfig conf; -// conf.border = true; -// conf.imageSize = QSize(400, 400); -// auto img = qzxing.encodeData(message, conf); -// image = img.copy(); -//} - -void ConfigExporter::OpenExport() -{ - imageLabel->setPixmap(QPixmap::fromImage(image)); - messageTxt->setPlainText(message); - this->exec(); -} - -void ConfigExporter::changeEvent(QEvent *e) -{ - QDialog::changeEvent(e); - - switch (e->type()) - { - case QEvent::LanguageChange: retranslateUi(this); break; - - case QEvent::Resize: imageLabel->setPixmap(QPixmap::fromImage(image)); break; - - default: break; - } -} - -void ConfigExporter::on_closeBtn_clicked() -{ - // OK - close(); -} - -void ConfigExporter::on_saveBtn_clicked() -{ - // Save - auto filePath = QFileDialog().getSaveFileName(this, tr("Save Image"), "", "Images (*.png)"); - auto result = image.save(filePath); - QDesktopServices::openUrl(QUrl::fromUserInput(filePath)); - LOG(MODULE_FILEIO, "Saving an image to: " + filePath + " result: " + (result ? "OK" : "Failed")) -} - -void ConfigExporter::on_copyImageBtn_clicked() -{ - QGuiApplication::clipboard()->setImage(image); - QvMessageBoxInfo(this, tr("Share Connection"), tr("Image has been copied to the clipboard.")); -} - -void ConfigExporter::on_copyVMessBtn_clicked() -{ - QGuiApplication::clipboard()->setText(message); - QvMessageBoxInfo(this, tr("Share Connection"), tr("VMess string has been copied to the clipboard.")); -} diff --git a/src/ui/w_ExportConfig.hpp b/src/ui/w_ExportConfig.hpp deleted file mode 100644 index 44546167..00000000 --- a/src/ui/w_ExportConfig.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "3rdparty/qzxing/src/QZXing.h" -#include "base/Qv2rayBase.hpp" -#include "ui/messaging/QvMessageBus.hpp" -#include "ui_w_ExportConfig.h" - -class ConfigExporter - : public QDialog - , private Ui::ExportConfigWindow -{ - Q_OBJECT - - public: - explicit ConfigExporter(QWidget *parent = nullptr); - ~ConfigExporter(); - void OpenExport(); - - private: - QvMessageBusSlotDecl; - - protected: - void changeEvent(QEvent *e); - private slots: - void on_closeBtn_clicked(); - - void on_saveBtn_clicked(); - - void on_copyImageBtn_clicked(); - - void on_copyVMessBtn_clicked(); - - private: - QZXing qzxing; - QImage image; - QString message; -}; diff --git a/src/ui/w_ExportConfig.ui b/src/ui/w_ExportConfig.ui deleted file mode 100644 index e6b8f64f..00000000 --- a/src/ui/w_ExportConfig.ui +++ /dev/null @@ -1,127 +0,0 @@ - - - ExportConfigWindow - - - - 0 - 0 - 661 - 347 - - - - Export Config - - - - - - true - - - QFrame::Box - - - - - - :/assets/icons/qv2ray.ico - - - false - - - Qt::AlignCenter - - - Qt::NoTextInteraction - - - - - - - Share Options - - - - - - Connection String - - - - - - - true - - - - - - - - - Save Image - - - - - - - Copy Image - - - - - - - Copy Link - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - OK - - - - - - - - - messageTxt - saveBtn - copyImageBtn - copyVMessBtn - closeBtn - - - - - - From 859657ad8028c26bf2ac0b2b24d36e589ba246da Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 15:19:28 +0800 Subject: [PATCH 301/332] fix: fixed build error --- src/ui/messaging/QvMessageBus.hpp | 18 ++-- src/ui/w_ImportConfig.cpp | 11 ++- src/ui/w_ImportConfig.hpp | 1 + src/ui/w_MainWindow.cpp | 115 ++++++++++++------------ src/ui/w_MainWindow.hpp | 34 ++++--- src/ui/w_PreferencesWindow.cpp | 4 +- src/ui/w_PreferencesWindow.hpp | 2 - src/ui/w_SubscriptionManager.cpp | 12 ++- src/ui/w_SubscriptionManager.hpp | 1 + src/ui/widgets/ConnectionInfoWidget.cpp | 59 ++++++++---- src/ui/widgets/ConnectionInfoWidget.hpp | 4 + src/ui/widgets/StreamSettingsWidget.cpp | 20 ++++- src/ui/widgets/StreamSettingsWidget.hpp | 4 +- src/ui/widgets/StreamSettingsWidget.ui | 2 +- 14 files changed, 176 insertions(+), 111 deletions(-) diff --git a/src/ui/messaging/QvMessageBus.hpp b/src/ui/messaging/QvMessageBus.hpp index 4ef11e91..71cfb0e9 100644 --- a/src/ui/messaging/QvMessageBus.hpp +++ b/src/ui/messaging/QvMessageBus.hpp @@ -1,7 +1,7 @@ #pragma once #include -#define QvMessageBusConnect(CLASSNAME) connect(&messageBus, &QvMessageBusObject::QvSendMessage, this, &CLASSNAME::on_QvMessageReceived) +#define QvMessageBusConnect(CLASSNAME) connect(&UIMessageBus, &QvMessageBusObject::QvSendMessage, this, &CLASSNAME::on_QvMessageReceived) #define QvMessageBusSlotSig const QvMBMessage &msg #define QvMessageBusSlotIdentifier on_QvMessageReceived @@ -20,7 +20,12 @@ break; #define MBRetranslateDefaultImpl \ - case RETRANSLATE: this->retranslateUi(this); break; + case RETRANSLATE: \ + this->retranslateUi(this); \ + break; + +#define MBUpdateColorSchemeDefaultImpl \ + case UPDATE_COLORSCHEME: this->UpdateColorScheme(); break; namespace Qv2ray::ui::messaging { @@ -32,11 +37,9 @@ namespace Qv2ray::ui::messaging /// Hide all windows. HIDE_WINDOWS, /// Retranslate User Interface. - RETRANSLATE - /*, + RETRANSLATE, /// Change Color Scheme - CHANGE_COLORSCHEME - */ + UPDATE_COLORSCHEME }; Q_ENUM_NS(QvMBMessage); // @@ -54,8 +57,7 @@ namespace Qv2ray::ui::messaging // void on_QvMessageReceived(QvMessage msg); }; - // Danger, new is used here. Possible memory leak (hope not so much leak) - inline QvMessageBusObject messageBus = QvMessageBusObject(); + inline QvMessageBusObject UIMessageBus = QvMessageBusObject(); } // namespace Qv2ray::ui::messaging using namespace Qv2ray::ui::messaging; diff --git a/src/ui/w_ImportConfig.cpp b/src/ui/w_ImportConfig.cpp index 3154b180..afe6ec67 100644 --- a/src/ui/w_ImportConfig.cpp +++ b/src/ui/w_ImportConfig.cpp @@ -27,11 +27,16 @@ ImportConfigWindow::ImportConfigWindow(QWidget *parent) : QDialog(parent) RESTORE_RUNTIME_CONFIG(screenShotHideQv2ray, hideQv2rayCB->setChecked) } +void ImportConfigWindow::UpdateColorScheme() +{ + // Stub +} + QvMessageBusSlotImpl(ImportConfigWindow) { switch (msg) { - MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl MBUpdateColorSchemeDefaultImpl } } @@ -62,7 +67,7 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() if (hideQv2ray) { - messageBus.EmitGlobalSignal(QvMBMessage::HIDE_WINDOWS); + UIMessageBus.EmitGlobalSignal(QvMBMessage::HIDE_WINDOWS); } QApplication::processEvents(); @@ -74,7 +79,7 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() if (hideQv2ray) { - messageBus.EmitGlobalSignal(QvMBMessage::SHOW_WINDOWS); + UIMessageBus.EmitGlobalSignal(QvMBMessage::SHOW_WINDOWS); // ShowAllGlobalWindow(); } diff --git a/src/ui/w_ImportConfig.hpp b/src/ui/w_ImportConfig.hpp index ef1210d9..3cf02067 100644 --- a/src/ui/w_ImportConfig.hpp +++ b/src/ui/w_ImportConfig.hpp @@ -43,6 +43,7 @@ class ImportConfigWindow void on_hideQv2rayCB_stateChanged(int arg1); private: + void UpdateColorScheme(); QMultiMap connections; QMap linkErrors; }; diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 0ab9f1b5..cac048ef 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -8,7 +8,6 @@ #include "ui/editors/w_OutboundEditor.hpp" #include "ui/editors/w_RoutesEditor.hpp" #include "ui/widgets/ConnectionInfoWidget.hpp" -#include "w_ExportConfig.hpp" #include "w_ImportConfig.hpp" #include "w_PreferencesWindow.hpp" #include "w_SubscriptionManager.hpp" @@ -41,10 +40,27 @@ QvMessageBusSlotImpl(MainWindow) { switch (msg) { - MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl MBUpdateColorSchemeDefaultImpl } } +void MainWindow::UpdateColorScheme() +{ + hTray.setIcon(QIcon(GlobalConfig.uiConfig.useDarkTrayIcon ? ":/assets/icons/ui_dark/tray.png" : ":/assets/icons/ui_light/tray.png")); + // + importConfigButton->setIcon(QICON_R("import.png")); + updownImageBox->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); + updownImageBox_2->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); + // + tray_action_ShowHide->setIcon(this->windowIcon()); + action_RCM_Start->setIcon(QICON_R("connect.png")); + action_RCM_Edit->setIcon(QICON_R("edit.png")); + action_RCM_EditJson->setIcon(QICON_R("json.png")); + action_RCM_EditComplex->setIcon(QICON_R("edit.png")); + action_RCM_Duplicate->setIcon(QICON_R("duplicate.png")); + action_RCM_Delete->setIcon(QICON_R("delete.png")); +} + void MainWindow::MWAddConnectionItem_p(const ConnectionId &connection, const GroupId &groupId) { if (!groupNodes.contains(groupId)) @@ -100,11 +116,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) speedChart->addWidget(speedChartWidget); // this->setWindowIcon(QIcon(":/assets/icons/qv2ray.png")); - hTray.setIcon(QIcon(GlobalConfig.uiConfig.useDarkTrayIcon ? ":/assets/icons/ui_dark/tray.png" : ":/assets/icons/ui_light/tray.png")); - // - importConfigButton->setIcon(QICON_R("import.png")); - updownImageBox->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); - updownImageBox_2->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); + UpdateColorScheme(); // // connect(ConnectionManager, &QvConfigHandler::OnCrashed, [&] { @@ -140,50 +152,40 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) hTray.setToolTip(TRAY_TOOLTIP_PREFIX); // // Basic actions - action_Tray_Start->setEnabled(true); - action_Tray_Stop->setEnabled(false); - action_Tray_Restart->setEnabled(false); + tray_action_Start->setEnabled(true); + tray_action_Stop->setEnabled(false); + tray_action_Restart->setEnabled(false); // tray_SystemProxyMenu->setTitle(tr("System Proxy")); tray_SystemProxyMenu->setEnabled(false); - tray_SystemProxyMenu->addAction(action_Tray_SetSystemProxy); - tray_SystemProxyMenu->addAction(action_Tray_ClearSystemProxy); + tray_SystemProxyMenu->addAction(tray_action_SetSystemProxy); + tray_SystemProxyMenu->addAction(tray_action_ClearSystemProxy); // - tray_RootMenu->addAction(action_Tray_ShowHide); + tray_RootMenu->addAction(tray_action_ShowHide); tray_RootMenu->addSeparator(); - tray_RootMenu->addAction(action_Tray_ShowPreferencesWindow); + tray_RootMenu->addAction(tray_action_ShowPreferencesWindow); tray_RootMenu->addMenu(tray_SystemProxyMenu); tray_RootMenu->addSeparator(); - tray_RootMenu->addAction(action_Tray_Start); - tray_RootMenu->addAction(action_Tray_Stop); - tray_RootMenu->addAction(action_Tray_Restart); + tray_RootMenu->addAction(tray_action_Start); + tray_RootMenu->addAction(tray_action_Stop); + tray_RootMenu->addAction(tray_action_Restart); tray_RootMenu->addSeparator(); - tray_RootMenu->addAction(action_Tray_Quit); + tray_RootMenu->addAction(tray_action_Quit); // - connect(action_Tray_ShowHide, &QAction::triggered, this, &MainWindow::ToggleVisibility); - connect(action_Tray_ShowPreferencesWindow, &QAction::triggered, this, &MainWindow::on_preferencesBtn_clicked); + connect(tray_action_ShowHide, &QAction::triggered, this, &MainWindow::ToggleVisibility); + connect(tray_action_ShowPreferencesWindow, &QAction::triggered, this, &MainWindow::on_preferencesBtn_clicked); // - connect(action_Tray_Start, &QAction::triggered, [&] { ConnectionManager->StartConnection(lastConnectedId); }); - connect(action_Tray_Stop, &QAction::triggered, ConnectionManager, &QvConfigHandler::StopConnection); - connect(action_Tray_Restart, &QAction::triggered, ConnectionManager, &QvConfigHandler::RestartConnection); + connect(tray_action_Start, &QAction::triggered, [&] { ConnectionManager->StartConnection(lastConnectedId); }); + connect(tray_action_Stop, &QAction::triggered, ConnectionManager, &QvConfigHandler::StopConnection); + connect(tray_action_Restart, &QAction::triggered, ConnectionManager, &QvConfigHandler::RestartConnection); // - connect(action_Tray_Quit, &QAction::triggered, this, &MainWindow::on_actionExit_triggered); - connect(action_Tray_SetSystemProxy, &QAction::triggered, this, &MainWindow::MWSetSystemProxy); - connect(action_Tray_ClearSystemProxy, &QAction::triggered, &ClearSystemProxy); + connect(tray_action_Quit, &QAction::triggered, this, &MainWindow::on_actionExit_triggered); + connect(tray_action_SetSystemProxy, &QAction::triggered, this, &MainWindow::MWSetSystemProxy); + connect(tray_action_ClearSystemProxy, &QAction::triggered, &ClearSystemProxy); connect(&hTray, &QSystemTrayIcon::activated, this, &MainWindow::on_activatedTray); // // Actions for right click the connection list // - QAction *action_RCM_Start = new QAction(QICON_R("connect.png"), tr("Connect to this"), this); - // - QAction *action_RCM_Edit = new QAction(QICON_R("edit.png"), tr("Edit"), this); - QAction *action_RCM_EditJson = new QAction(QICON_R("json.png"), tr("Edit as JSON"), this); - QAction *action_RCM_EditComplex = new QAction(QICON_R("edit.png"), tr("Edit as Complex Config"), this); - // - QAction *action_RCM_Rename = new QAction(tr("Rename"), this); - QAction *action_RCM_Duplicate = new QAction(QICON_R("duplicate.png"), tr("Duplicate to the Same Group"), this); - QAction *action_RCM_Delete = new QAction(QICON_R("delete.png"), tr("Delete Connection"), this); - // connect(action_RCM_Start, &QAction::triggered, this, &MainWindow::on_action_StartThis_triggered); // connect(action_RCM_Edit, &QAction::triggered, this, &MainWindow::on_action_RCM_EditThis_triggered); @@ -202,17 +204,16 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) hTray.setContextMenu(tray_RootMenu); hTray.show(); // - connectionListMenu = new QMenu(this); - connectionListMenu->addAction(action_RCM_Start); - connectionListMenu->addSeparator(); - connectionListMenu->addAction(action_RCM_Edit); - connectionListMenu->addAction(action_RCM_EditJson); - connectionListMenu->addAction(action_RCM_EditComplex); - connectionListMenu->addSeparator(); - connectionListMenu->addAction(action_RCM_Rename); - connectionListMenu->addAction(action_RCM_Duplicate); - connectionListMenu->addSeparator(); - connectionListMenu->addAction(action_RCM_Delete); + RCM_Menu->addAction(action_RCM_Start); + RCM_Menu->addSeparator(); + RCM_Menu->addAction(action_RCM_Edit); + RCM_Menu->addAction(action_RCM_EditJson); + RCM_Menu->addAction(action_RCM_EditComplex); + RCM_Menu->addSeparator(); + RCM_Menu->addAction(action_RCM_Rename); + RCM_Menu->addAction(action_RCM_Duplicate); + RCM_Menu->addSeparator(); + RCM_Menu->addAction(action_RCM_Delete); // QMenu *sortMenu = new QMenu(tr("Sort connection list."), this); QAction *sortAction_SortByName_Asc = new QAction(tr("By connection name, A-Z")); @@ -382,7 +383,7 @@ MainWindow::~MainWindow() void MainWindow::closeEvent(QCloseEvent *event) { this->hide(); - action_Tray_ShowHide->setText(tr("Show")); + tray_action_ShowHide->setText(tr("Show")); event->ignore(); } void MainWindow::on_activatedTray(QSystemTrayIcon::ActivationReason reason) @@ -419,12 +420,12 @@ void MainWindow::ToggleVisibility() QThread::msleep(20); SetWindowPos(HWND(this->winId()), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); #endif - action_Tray_ShowHide->setText(tr("Hide")); + tray_action_ShowHide->setText(tr("Hide")); } else { this->hide(); - action_Tray_ShowHide->setText(tr("Show")); + tray_action_ShowHide->setText(tr("Show")); } } @@ -456,7 +457,7 @@ void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint { if (GetItemWidget(item)->IsConnection()) { - connectionListMenu->popup(_pos); + RCM_Menu->popup(_pos); } } } @@ -555,9 +556,9 @@ void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item void MainWindow::OnDisconnected(const ConnectionId &id) { Q_UNUSED(id) - action_Tray_Start->setEnabled(true); - action_Tray_Stop->setEnabled(false); - action_Tray_Restart->setEnabled(false); + tray_action_Start->setEnabled(true); + tray_action_Stop->setEnabled(false); + tray_action_Restart->setEnabled(false); tray_SystemProxyMenu->setEnabled(false); lastConnectedId = id; locateBtn->setEnabled(false); @@ -579,9 +580,9 @@ void MainWindow::OnDisconnected(const ConnectionId &id) void MainWindow::OnConnected(const ConnectionId &id) { Q_UNUSED(id) - action_Tray_Start->setEnabled(false); - action_Tray_Stop->setEnabled(true); - action_Tray_Restart->setEnabled(true); + tray_action_Start->setEnabled(false); + tray_action_Stop->setEnabled(true); + tray_action_Restart->setEnabled(true); tray_SystemProxyMenu->setEnabled(true); lastConnectedId = id; locateBtn->setEnabled(true); diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 0c20cab1..a86c9938 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -109,38 +109,44 @@ class MainWindow private: QHash> groupNodes; QHash> connectionNodes; - // - QTreeWidgetItem *CurrentItem; // Charts SpeedWidget *speedChartWidget; - QMenu *connectionListMenu; #ifndef DISABLE_AUTO_UPDATE QvHttpRequestHelper *requestHelper; #endif QSystemTrayIcon hTray; PACServer pacServer; - // QvTCPingModel tcpingHelper; SyntaxHighlighter *vCoreLogHighlighter; ConnectionInfoWidget *infoWidget; // // Actions in the system tray menu QMenu *tray_RootMenu = new QMenu(this); - QAction *action_Tray_ShowHide = new QAction(this->windowIcon(), tr("Hide"), this); - QAction *action_Tray_ShowPreferencesWindow = new QAction(tr("Preferences"), this); - QAction *action_Tray_Quit = new QAction(tr("Quit"), this); - // --> Connectivities - QAction *action_Tray_Start = new QAction(tr("Connect"), this); - QAction *action_Tray_Restart = new QAction(tr("Reconnect"), this); - QAction *action_Tray_Stop = new QAction(tr("Disconnect"), this); - // --> System proxy settings QMenu *tray_SystemProxyMenu = new QMenu(this); - QAction *action_Tray_SetSystemProxy = new QAction(tr("Enable System Proxy"), this); - QAction *action_Tray_ClearSystemProxy = new QAction(tr("Disable System Proxy"), this); + // + QAction *tray_action_ShowHide = new QAction(tr("Hide"), this); + QAction *tray_action_ShowPreferencesWindow = new QAction(tr("Preferences"), this); + QAction *tray_action_Quit = new QAction(tr("Quit"), this); + QAction *tray_action_Start = new QAction(tr("Connect"), this); + QAction *tray_action_Restart = new QAction(tr("Reconnect"), this); + QAction *tray_action_Stop = new QAction(tr("Disconnect"), this); + QAction *tray_action_SetSystemProxy = new QAction(tr("Enable System Proxy"), this); + QAction *tray_action_ClearSystemProxy = new QAction(tr("Disable System Proxy"), this); + // + QMenu *RCM_Menu = new QMenu(this); + QAction *action_RCM_Start = new QAction(tr("Connect to this"), this); + QAction *action_RCM_Edit = new QAction(tr("Edit"), this); + QAction *action_RCM_EditJson = new QAction(tr("Edit as JSON"), this); + QAction *action_RCM_EditComplex = new QAction(tr("Edit as Complex Config"), this); + QAction *action_RCM_Rename = new QAction(tr("Rename"), this); + QAction *action_RCM_Duplicate = new QAction(tr("Duplicate to the Same Group"), this); + QAction *action_RCM_Delete = new QAction(tr("Delete Connection"), this); // ConnectionId lastConnectedId; void MWSetSystemProxy(); void CheckSubscriptionsUpdate(); // + void UpdateColorScheme(); + // void MWAddConnectionItem_p(const ConnectionId &connection, const GroupId &groupId); void MWAddGroupItem_p(const GroupId &groupId); }; diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index a116a731..89d7af27 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -268,7 +268,7 @@ void PreferencesWindow::on_buttonBox_accepted() // Install translator if (Qv2rayTranslator->InstallTranslation(CurrentConfig.uiConfig.language)) { - messageBus.EmitGlobalSignal(QvMBMessage::RETRANSLATE); + UIMessageBus.EmitGlobalSignal(QvMBMessage::RETRANSLATE); QApplication::processEvents(); } else @@ -279,7 +279,7 @@ void PreferencesWindow::on_buttonBox_accepted() qApp->setStyle(QStyleFactory::create(CurrentConfig.uiConfig.theme)); SaveGlobalConfig(CurrentConfig); - emit s_reload_config(IsConnectionPropertyChanged); + UIMessageBus.EmitGlobalSignal(QvMBMessage::UPDATE_COLORSCHEME); emit accept(); } } diff --git a/src/ui/w_PreferencesWindow.hpp b/src/ui/w_PreferencesWindow.hpp index e45f102c..e7d82c3c 100644 --- a/src/ui/w_PreferencesWindow.hpp +++ b/src/ui/w_PreferencesWindow.hpp @@ -15,8 +15,6 @@ class PreferencesWindow public: explicit PreferencesWindow(QWidget *parent = nullptr); ~PreferencesWindow(); - signals: - void s_reload_config(bool need_restart); private: QvMessageBusSlotDecl; diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index e1cbe321..05c0231b 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -8,9 +8,7 @@ SubscribeEditor::SubscribeEditor(QWidget *parent) : QDialog(parent) { setupUi(this); QvMessageBusConnect(SubscribeEditor); - addSubsButton->setIcon(QICON_R("add.png")); - removeSubsButton->setIcon(QICON_R("delete.png")); - + UpdateColorScheme(); for (auto subs : ConnectionManager->Subscriptions()) { subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList{ GetDisplayName(subs), subs.toString() })); @@ -21,11 +19,17 @@ SubscribeEditor::SubscribeEditor(QWidget *parent) : QDialog(parent) } } +void SubscribeEditor::UpdateColorScheme() +{ + addSubsButton->setIcon(QICON_R("add.png")); + removeSubsButton->setIcon(QICON_R("delete.png")); +} + QvMessageBusSlotImpl(SubscribeEditor) { switch (msg) { - MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl MBUpdateColorSchemeDefaultImpl } } diff --git a/src/ui/w_SubscriptionManager.hpp b/src/ui/w_SubscriptionManager.hpp index b4e60bd8..cf1b6c43 100644 --- a/src/ui/w_SubscriptionManager.hpp +++ b/src/ui/w_SubscriptionManager.hpp @@ -45,6 +45,7 @@ class SubscribeEditor void on_connectionsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous); private: + void UpdateColorScheme(); bool isUpdateInProgress = false; GroupId currentSubId = NullGroupId; ConnectionId currentConnectionId = NullConnectionId; diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index d7fb47d6..90b26eb8 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -5,15 +5,44 @@ #include "core/CoreUtils.hpp" #include "core/connection/Serialization.hpp" -#define INDEX_CONNECTION 0 -#define INDEX_GROUP 1 +constexpr auto INDEX_CONNECTION = 0; +constexpr auto INDEX_GROUP = 1; + +QvMessageBusSlotImpl(ConnectionInfoWidget) +{ + switch (msg) + { + case HIDE_WINDOWS: + case SHOW_WINDOWS: + break; // + MBRetranslateDefaultImpl MBUpdateColorSchemeDefaultImpl + } +} + +void ConnectionInfoWidget::UpdateColorScheme() +{ + latencyBtn->setIcon(QICON_R("ping_gauge.png")); + deleteBtn->setIcon(QICON_R("delete.png")); + editBtn->setIcon(QICON_R("edit.png")); + editJsonBtn->setIcon(QICON_R("json.png")); + shareLinkTxt->setStyleSheet("border-bottom: 1px solid gray; border-radius: 0px; padding: 2px; background-color: " + + this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); + if (ConnectionManager->IsConnected(connectionId)) + { + connectBtn->setIcon(QICON_R("stop.png")); + } + else + { + connectBtn->setIcon(QICON_R("connect.png")); + } +} ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) { setupUi(this); - deleteBtn->setIcon(QICON_R("delete.png")); - editBtn->setIcon(QICON_R("edit.png")); - editJsonBtn->setIcon(QICON_R("json.png")); + // + QvMessageBusConnect(ConnectionInfoWidget); + UpdateColorScheme(); // shareLinkTxt->setAutoFillBackground(true); shareLinkTxt->setCursor(QCursor(Qt::CursorShape::IBeamCursor)); @@ -22,20 +51,12 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) // connect(ConnectionManager, &QvConfigHandler::OnConnected, this, &ConnectionInfoWidget::OnConnected); connect(ConnectionManager, &QvConfigHandler::OnDisconnected, this, &ConnectionInfoWidget::OnDisConnected); - // - connect(ConnectionManager, &QvConfigHandler::OnConnectionModified, [&](const ConnectionId &id) { - if (id == connectionId) - ShowDetails({ GetConnectionGroupId(id), id }); - }); - connect(ConnectionManager, &QvConfigHandler::OnConnectionGroupChanged, [&](const ConnectionId &id) { - if (id == connectionId) - ShowDetails({ GetConnectionGroupId(id), id }); - }); + connect(ConnectionManager, &QvConfigHandler::OnConnectionModified, this, &ConnectionInfoWidget::OnConnectionModified); + connect(ConnectionManager, &QvConfigHandler::OnConnectionGroupChanged, this, &ConnectionInfoWidget::OnConnectionModified); } + void ConnectionInfoWidget::ShowDetails(const tuple &_identifier) { - shareLinkTxt->setStyleSheet("border-bottom: 1px solid gray; border-radius: 0px; padding: 2px; background-color: " + - this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); this->groupId = get<0>(_identifier); this->connectionId = get<1>(_identifier); bool isConnection = connectionId != NullConnectionId; @@ -104,6 +125,12 @@ ConnectionInfoWidget::~ConnectionInfoWidget() { } +void ConnectionInfoWidget::OnConnectionModified(const ConnectionId &id) +{ + if (id == connectionId) + ShowDetails({ GetConnectionGroupId(id), id }); +} + void ConnectionInfoWidget::on_connectBtn_clicked() { if (ConnectionManager->IsConnected(connectionId)) diff --git a/src/ui/widgets/ConnectionInfoWidget.hpp b/src/ui/widgets/ConnectionInfoWidget.hpp index 1ae2c21a..af8a789d 100644 --- a/src/ui/widgets/ConnectionInfoWidget.hpp +++ b/src/ui/widgets/ConnectionInfoWidget.hpp @@ -1,6 +1,7 @@ #pragma once #include "core/handler/ConfigHandler.hpp" +#include "ui/messaging/QvMessageBus.hpp" #include "ui_ConnectionInfoWidget.h" #include @@ -29,11 +30,14 @@ class ConnectionInfoWidget void on_editJsonBtn_clicked(); void on_deleteBtn_clicked(); + void OnConnectionModified(const ConnectionId &id); void OnConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id); void on_latencyBtn_clicked(); private: + void UpdateColorScheme(); + QvMessageBusSlotDecl; ConnectionId connectionId = NullConnectionId; GroupId groupId = NullGroupId; // diff --git a/src/ui/widgets/StreamSettingsWidget.cpp b/src/ui/widgets/StreamSettingsWidget.cpp index b342b30c..0b39a91e 100644 --- a/src/ui/widgets/StreamSettingsWidget.cpp +++ b/src/ui/widgets/StreamSettingsWidget.cpp @@ -6,6 +6,20 @@ StreamSettingsWidget::StreamSettingsWidget(QWidget *parent) : QWidget(parent) { setupUi(this); + QvMessageBusConnect(StreamSettingsWidget); +} + +QvMessageBusSlotImpl(StreamSettingsWidget) +{ + switch (msg) + { + case UPDATE_COLORSCHEME: + case HIDE_WINDOWS: + case SHOW_WINDOWS: + break; + // + MBRetranslateDefaultImpl + } } StreamSettingsObject StreamSettingsWidget::GetStreamSettings() @@ -13,7 +27,7 @@ StreamSettingsObject StreamSettingsWidget::GetStreamSettings() return stream; } -void StreamSettingsWidget::SetStreamObject(StreamSettingsObject sso) +void StreamSettingsWidget::SetStreamObject(const StreamSettingsObject &sso) { stream = sso; // @@ -34,9 +48,9 @@ void StreamSettingsWidget::SetStreamObject(StreamSettingsObject sso) wsPathTxt->setText(stream.wsSettings.path); QString wsHeaders; - for (auto item = stream.wsSettings.headers.begin(); item != stream.wsSettings.headers.end(); item++) + for (int index = 0; stream.wsSettings.headers.count(); index++) { - wsHeaders += item.key() + "|" + item.value() + NEWLINE; + wsHeaders % stream.wsSettings.headers.keys().at(index) % "|" % stream.wsSettings.headers.values().at(index) % NEWLINE; } wsHeadersTxt->setPlainText(wsHeaders); diff --git a/src/ui/widgets/StreamSettingsWidget.hpp b/src/ui/widgets/StreamSettingsWidget.hpp index 5fd4a688..32c309bb 100644 --- a/src/ui/widgets/StreamSettingsWidget.hpp +++ b/src/ui/widgets/StreamSettingsWidget.hpp @@ -2,6 +2,7 @@ #include "QWidget" #include "base/Qv2rayBase.hpp" +#include "ui/messaging/QvMessageBus.hpp" #include "ui_StreamSettingsWidget.h" class StreamSettingsWidget @@ -12,7 +13,7 @@ class StreamSettingsWidget public: explicit StreamSettingsWidget(QWidget *parent = nullptr); - void SetStreamObject(StreamSettingsObject sso); + void SetStreamObject(const StreamSettingsObject &sso); StreamSettingsObject GetStreamSettings(); private slots: @@ -77,5 +78,6 @@ class StreamSettingsWidget void on_alpnTxt_textChanged(); private: + QvMessageBusSlotDecl; StreamSettingsObject stream; }; diff --git a/src/ui/widgets/StreamSettingsWidget.ui b/src/ui/widgets/StreamSettingsWidget.ui index 01befd25..26f16c89 100644 --- a/src/ui/widgets/StreamSettingsWidget.ui +++ b/src/ui/widgets/StreamSettingsWidget.ui @@ -7,7 +7,7 @@ 0 0 384 - 372 + 422 From 4aafcbe15089cefe6907eea1861412382b9377b8 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 17:22:01 +0800 Subject: [PATCH 302/332] fix: several ui fixes, including darkmode icon settings --- CMakeLists.txt | 2 -- makespec/BUILDVERSION | 2 +- src/base/GlobalInstances.hpp | 20 -------------------- src/base/Qv2rayBase.hpp | 10 +++++++--- src/base/Qv2rayLog.cpp | 2 +- src/base/models/QvRuntimeConfig.hpp | 2 +- src/base/models/QvStartupConfig.hpp | 1 + src/common/QvTranslator.hpp | 1 + src/main.cpp | 2 +- src/ui/w_MainWindow.cpp | 7 +++++-- src/ui/w_MainWindow.ui | 7 ++----- src/ui/widgets/ConnectionInfoWidget.cpp | 18 +++++------------- src/ui/widgets/ConnectionInfoWidget.ui | 15 +++------------ src/ui/widgets/StreamSettingsWidget.cpp | 3 +-- 14 files changed, 29 insertions(+), 63 deletions(-) delete mode 100644 src/base/GlobalInstances.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d0b133af..9c61375b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,7 +190,6 @@ set(QV2RAY_SOURCES src/ui/widgets/ConnectionItemWidget.cpp src/ui/widgets/QvAutoCompleteTextEdit.cpp src/ui/widgets/StreamSettingsWidget.cpp - src/ui/w_ExportConfig.cpp src/ui/w_ImportConfig.cpp src/ui/w_MainWindow.cpp src/ui/w_MainWindow_extra.cpp @@ -198,7 +197,6 @@ set(QV2RAY_SOURCES src/ui/w_ScreenShot_Core.cpp src/ui/w_SubscriptionManager.cpp # ui files - src/ui/w_ExportConfig.ui src/ui/w_SubscriptionManager.ui src/ui/editors/w_OutboundEditor.ui src/ui/editors/w_InboundEditor.ui diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 53d48984..05fb9346 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4631 \ No newline at end of file +4633 \ No newline at end of file diff --git a/src/base/GlobalInstances.hpp b/src/base/GlobalInstances.hpp deleted file mode 100644 index c5b2d7df..00000000 --- a/src/base/GlobalInstances.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "base/models/QvRuntimeConfig.hpp" -#include "base/models/QvSettingsObject.hpp" -#include "base/models/QvStartupConfig.hpp" -#include "common/QvTranslator.hpp" - -// Instantiation for Qv2ray global objects. - -namespace Qv2ray -{ - // Qv2ray runtime config - inline bool isExiting = false; - inline QString Qv2rayConfigPath = ""; - inline base::Qv2rayRuntimeConfig RuntimeConfig = base::Qv2rayRuntimeConfig(); - inline base::config::Qv2rayConfig GlobalConfig = base::config::Qv2rayConfig(); - inline base::QvStartupOptions StartupOption = base::QvStartupOptions(); - // - inline std::unique_ptr Qv2rayTranslator; -} // namespace Qv2ray diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index 85ad1908..3b81768a 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -10,7 +10,6 @@ #include #include // Base support. -#include "base/GlobalInstances.hpp" #include "base/JsonHelpers.hpp" #include "base/Qv2rayFeatures.hpp" #include "base/Qv2rayLog.hpp" @@ -98,9 +97,9 @@ using namespace Qv2ray::base::objects::transfer; #define BLACK(obj) obj->setPalette(QWidget::palette()); -#define QV2RAY_UI_RESOURCES_ROOT \ +#define QV2RAY_UI_COLORSCHEME_ROOT \ ((GlobalConfig.uiConfig.useDarkTheme) ? QStringLiteral(":/assets/icons/ui_dark/") : QStringLiteral(":/assets/icons/ui_light/")) -#define QICON_R(file) QIcon(QV2RAY_UI_RESOURCES_ROOT + file) +#define QICON_R(file) QIcon(QV2RAY_UI_COLORSCHEME_ROOT + file) #define QSTRN(num) QString::number(num) @@ -124,6 +123,11 @@ namespace Qv2ray // Extra header for QvConfigUpgrade.cpp QJsonObject UpgradeSettingsVersion(int fromVersion, int toVersion, QJsonObject root); + // Qv2ray runtime config + inline bool isExiting = false; + inline QString Qv2rayConfigPath = ""; + inline base::config::Qv2rayConfig GlobalConfig = base::config::Qv2rayConfig(); + // inline void ExitQv2ray() { isExiting = true; diff --git a/src/base/Qv2rayLog.cpp b/src/base/Qv2rayLog.cpp index 3725b256..c2bb4f21 100644 --- a/src/base/Qv2rayLog.cpp +++ b/src/base/Qv2rayLog.cpp @@ -1,6 +1,6 @@ #include "Qv2rayLog.hpp" -#include "base/GlobalInstances.hpp" +#include "Qv2rayBase.hpp" #include diff --git a/src/base/models/QvRuntimeConfig.hpp b/src/base/models/QvRuntimeConfig.hpp index 8995e7f4..d1dd033c 100644 --- a/src/base/models/QvRuntimeConfig.hpp +++ b/src/base/models/QvRuntimeConfig.hpp @@ -7,7 +7,7 @@ namespace Qv2ray::base { struct Qv2rayRuntimeConfig { - // bool screenShotHideQv2ray = false; }; + inline base::Qv2rayRuntimeConfig RuntimeConfig = base::Qv2rayRuntimeConfig(); } // namespace Qv2ray::base diff --git a/src/base/models/QvStartupConfig.hpp b/src/base/models/QvStartupConfig.hpp index 21c61b0e..04199a18 100644 --- a/src/base/models/QvStartupConfig.hpp +++ b/src/base/models/QvStartupConfig.hpp @@ -16,4 +16,5 @@ namespace Qv2ray bool enableToolbarPlguin; }; } // namespace base + inline base::QvStartupOptions StartupOption = base::QvStartupOptions(); } // namespace Qv2ray diff --git a/src/common/QvTranslator.hpp b/src/common/QvTranslator.hpp index de83aa6e..45b24bba 100644 --- a/src/common/QvTranslator.hpp +++ b/src/common/QvTranslator.hpp @@ -27,4 +27,5 @@ namespace Qv2ray::common QStringList languages; std::unique_ptr pTranslator; }; + inline std::unique_ptr Qv2rayTranslator; } // namespace Qv2ray::common diff --git a/src/main.cpp b/src/main.cpp index b54cfe86..d50f4d53 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -508,7 +508,7 @@ int main(int argc, char *argv[]) // Handler for session logout, shutdown, etc. // Will not block. QGuiApplication::setFallbackSessionManagementEnabled(false); - QObject::connect(&_qApp, &QGuiApplication::commitDataRequest, []() { LOG(MODULE_INIT, "Quit triggered by session manager.") }); + QObject::connect(&_qApp, &QGuiApplication::commitDataRequest, [] { LOG(MODULE_INIT, "Quit triggered by session manager.") }); #ifndef Q_OS_WIN signal(SIGUSR1, [](int) { emit MainWindow::mwInstance->StartConnection(); }); signal(SIGUSR2, [](int) { emit MainWindow::mwInstance->StopConnection(); }); diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index cac048ef..d17ee7d1 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -49,8 +49,8 @@ void MainWindow::UpdateColorScheme() hTray.setIcon(QIcon(GlobalConfig.uiConfig.useDarkTrayIcon ? ":/assets/icons/ui_dark/tray.png" : ":/assets/icons/ui_light/tray.png")); // importConfigButton->setIcon(QICON_R("import.png")); - updownImageBox->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); - updownImageBox_2->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)"); + updownImageBox->setStyleSheet("image: url(" + QV2RAY_UI_COLORSCHEME_ROOT + "netspeed_arrow.png)"); + updownImageBox_2->setStyleSheet("image: url(" + QV2RAY_UI_COLORSCHEME_ROOT + "netspeed_arrow.png)"); // tray_action_ShowHide->setIcon(this->windowIcon()); action_RCM_Start->setIcon(QICON_R("connect.png")); @@ -59,6 +59,9 @@ void MainWindow::UpdateColorScheme() action_RCM_EditComplex->setIcon(QICON_R("edit.png")); action_RCM_Duplicate->setIcon(QICON_R("duplicate.png")); action_RCM_Delete->setIcon(QICON_R("delete.png")); + // + locateBtn->setIcon(QICON_R("locate.png")); + sortBtn->setIcon(QICON_R("sort.png")); } void MainWindow::MWAddConnectionItem_p(const ConnectionId &connection, const GroupId &groupId) diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index bc7b2573..38d0663d 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -246,7 +246,7 @@ 0 - -188 + 0 480 746 @@ -273,9 +273,6 @@ - - 0 - 0 @@ -396,7 +393,7 @@ - 6 + 9 diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 90b26eb8..766554b2 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -27,14 +27,8 @@ void ConnectionInfoWidget::UpdateColorScheme() editJsonBtn->setIcon(QICON_R("json.png")); shareLinkTxt->setStyleSheet("border-bottom: 1px solid gray; border-radius: 0px; padding: 2px; background-color: " + this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); - if (ConnectionManager->IsConnected(connectionId)) - { - connectBtn->setIcon(QICON_R("stop.png")); - } - else - { - connectBtn->setIcon(QICON_R("connect.png")); - } + + connectBtn->setIcon(ConnectionManager->IsConnected(connectionId) ? QICON_R("stop.png") : QICON_R("connect.png")); } ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) @@ -67,9 +61,6 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden stackedWidget->setCurrentIndex(isConnection ? INDEX_CONNECTION : INDEX_GROUP); if (isConnection) { - bool isComplexConfig = IsComplexConfig(connectionId); - qrLabel->setVisible(!isComplexConfig); - // auto shareLink = ConvertConfigToString(connectionId); // shareLinkTxt->setText(shareLink); @@ -94,7 +85,7 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden qrPixmapBlured = BlurImage(LightenImage(QPixmap::fromImage(img), 0.75), 20); // isRealPixmapShown = false; - qrLabel->setPixmap(qrPixmapBlured); + qrLabel->setPixmap(IsComplexConfig(connectionId) ? QPixmap(":/assets/icons/qv2ray.ico") : qrPixmapBlured); qrLabel->setScaledContents(true); // connectBtn->setIcon(ConnectionManager->IsConnected(connectionId) ? QICON_R("stop.png") : QICON_R("connect.png")); @@ -177,7 +168,8 @@ bool ConnectionInfoWidget::eventFilter(QObject *object, QEvent *event) } else if (qrLabel->underMouse() && event->type() == QEvent::MouseButtonRelease) { - qrLabel->setPixmap(isRealPixmapShown ? qrPixmapBlured : qrPixmap); + qrLabel->setPixmap(IsComplexConfig(connectionId) ? QPixmap(":/assets/icons/qv2ray.ico") : + (isRealPixmapShown ? qrPixmapBlured : qrPixmap)); isRealPixmapShown = !isRealPixmapShown; } diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index 4fa59c7d..46779fce 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -6,22 +6,16 @@ 0 0 - 412 - 230 + 375 + 215 - + 0 0 - - - 412 - 230 - - true @@ -29,9 +23,6 @@ Form - - 6 - diff --git a/src/ui/widgets/StreamSettingsWidget.cpp b/src/ui/widgets/StreamSettingsWidget.cpp index 0b39a91e..d1af0ea0 100644 --- a/src/ui/widgets/StreamSettingsWidget.cpp +++ b/src/ui/widgets/StreamSettingsWidget.cpp @@ -47,8 +47,7 @@ void StreamSettingsWidget::SetStreamObject(const StreamSettingsObject &sso) // WS wsPathTxt->setText(stream.wsSettings.path); QString wsHeaders; - - for (int index = 0; stream.wsSettings.headers.count(); index++) + for (auto index = 0; index < stream.wsSettings.headers.count(); index++) { wsHeaders % stream.wsSettings.headers.keys().at(index) % "|" % stream.wsSettings.headers.values().at(index) % NEWLINE; } From 01278f3c335bb1e5b6ed268a44b8a4458332c0b5 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 18:19:58 +0800 Subject: [PATCH 303/332] add: hide tProxy settings currently --- src/ui/w_MainWindow.ui | 8 ++++---- src/ui/w_PreferencesWindow.cpp | 13 +++++++------ src/ui/w_PreferencesWindow.hpp | 2 -- src/ui/w_PreferencesWindow.ui | 12 ++++++------ 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 38d0663d..1d405974 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -248,7 +248,7 @@ 0 0 480 - 746 + 736 @@ -263,13 +263,13 @@ 0 - 230 + 220 16777215 - 230 + 220 @@ -393,7 +393,7 @@ - 9 + 6 diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index 89d7af27..3a422319 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -28,6 +28,10 @@ using Qv2ray::common::validation::IsValidIPAddress; PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), CurrentConfig() { setupUi(this); + // + // We currently don't support this feature. + tProxyGroupBox->setVisible(false); + // QvMessageBusConnect(PreferencesWindow); textBrowser->setHtml(StringFromFile(":/assets/credit.html")); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); @@ -211,7 +215,9 @@ QvMessageBusSlotImpl(PreferencesWindow) { switch (msg) { - MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl + case UPDATE_COLORSCHEME: + break; // + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl } } @@ -890,7 +896,6 @@ void PreferencesWindow::on_darkThemeCB_stateChanged(int arg1) { LOADINGCHECK CurrentConfig.uiConfig.useDarkTheme = arg1 == Qt::Checked; - QvMessageBoxWarn(this, tr("Dark Mode"), tr("Please restart Qv2ray to fully apply this feature.")); #ifdef QV2RAY_USE_BUILTIN_DARKTHEME themeCombo->setEnabled(arg1 != Qt::Checked); @@ -1200,7 +1205,3 @@ void PreferencesWindow::on_enableAPI_stateChanged(int arg1) NEEDRESTART CurrentConfig.apiConfig.enableAPI = arg1 == Qt::Checked; } - -void PreferencesWindow::on_tProxyGroupBox_clicked(bool checked) -{ -} diff --git a/src/ui/w_PreferencesWindow.hpp b/src/ui/w_PreferencesWindow.hpp index e7d82c3c..ec6bbaab 100644 --- a/src/ui/w_PreferencesWindow.hpp +++ b/src/ui/w_PreferencesWindow.hpp @@ -164,8 +164,6 @@ class PreferencesWindow void on_startWithLoginCB_stateChanged(int arg1); - void on_tProxyGroupBox_clicked(bool checked); - private: void SetAutoStartButtonsState(bool isAutoStart); // Set ui parameters for a line; diff --git a/src/ui/w_PreferencesWindow.ui b/src/ui/w_PreferencesWindow.ui index 29d57067..3f3130bb 100644 --- a/src/ui/w_PreferencesWindow.ui +++ b/src/ui/w_PreferencesWindow.ui @@ -43,8 +43,8 @@ 0 0 - 1060 - 574 + 1054 + 556 @@ -405,8 +405,8 @@ - 100 - 0 + 116 + 30 @@ -490,8 +490,8 @@ 0 0 - 1060 - 574 + 1054 + 604 From 1eda28e58951cd674f1c617dd9d4879b32ca2b2e Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 18:23:55 +0800 Subject: [PATCH 304/332] add: ignored link starts with # and // when importing --- src/ui/w_ImportConfig.cpp | 18 ++++++++---------- src/ui/widgets/ConnectionInfoWidget.cpp | 3 ++- src/ui/widgets/ConnectionInfoWidget.ui | 12 +++++++++--- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/ui/w_ImportConfig.cpp b/src/ui/w_ImportConfig.cpp index afe6ec67..909abc78 100644 --- a/src/ui/w_ImportConfig.cpp +++ b/src/ui/w_ImportConfig.cpp @@ -75,20 +75,17 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() ScreenShotWindow w; auto pix = w.DoScreenShot(); auto _r = w.result(); - // Explicitly delete w to call UNREGISTER_WINDOW if (hideQv2ray) { UIMessageBus.EmitGlobalSignal(QvMBMessage::SHOW_WINDOWS); - // ShowAllGlobalWindow(); } if (_r == QDialog::Accepted) { - QZXing decoder; - decoder.setDecoder(QZXing::DecoderFormat_QR_CODE | QZXing::DecoderFormat_EAN_13); - auto str = decoder.decodeImage(pix); - // auto str = QZXing().decodeImage(pix); + QZXing qzxing; + qzxing.setDecoder(QZXing::DecoderFormat_QR_CODE | QZXing::DecoderFormat_EAN_13); + auto str = qzxing.decodeImage(pix); if (str.trimmed().isEmpty()) { @@ -98,8 +95,6 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() else { vmessConnectionStringTxt->appendPlainText(str.trimmed() + NEWLINE); - // QvMessageBoxWarn(this, tr("Capture QRCode"), tr("Successfully - // imported a QR code form the screen.")); this->show(); } } } @@ -107,7 +102,6 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() void ImportConfigWindow::on_beginImportBtn_clicked() { QString aliasPrefix = nameTxt->text(); - // auto conf = GetGlobalConfig(); switch (tabWidget->currentIndex()) { @@ -144,8 +138,12 @@ void ImportConfigWindow::on_beginImportBtn_clicked() { aliasPrefix = nameTxt->text(); auto link = linkList.takeFirst(); + if (link.trimmed().isEmpty() || link.startsWith("#") || link.startsWith("//")) + { + continue; + } QString errMessage; - CONFIGROOT config = ConvertConfigFromString(link, &aliasPrefix, &errMessage); + const CONFIGROOT config = ConvertConfigFromString(link, &aliasPrefix, &errMessage); // If the config is empty or we have any err messages. if (config.isEmpty() || !errMessage.isEmpty()) diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index 766554b2..f55c73b4 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -101,9 +101,10 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden } // auto complexCount = shareLinks.removeAll(QV2RAY_SERIALIZATION_COMPLEX_CONFIG_PLACEHOLDER); + complexCount += shareLinks.removeAll(""); if (complexCount > 0) { - shareLinks << tr("(Ignored %1 complex config(s))").arg(complexCount); + shareLinks << "# " + tr("(Ignored %1 complex config(s))").arg(complexCount); } // groupShareTxt->setPlainText(shareLinks.join(NEWLINE)); diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index 46779fce..62d009b9 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -6,8 +6,8 @@ 0 0 - 375 - 215 + 380 + 220 @@ -16,6 +16,12 @@ 0 + + + 1 + 1 + + true @@ -390,7 +396,7 @@ - + 0 0 From ac2d99cf6141e03e670fe2f86d0472faef794b7b Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Wed, 11 Mar 2020 18:33:29 +0800 Subject: [PATCH 305/332] add lupdate target for cmake --- CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c61375b..68af8f4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,6 +129,7 @@ message("Qv2ray build info ex: ${_QV2RAY_BUILD_EXTRA_INFO_STR_}") set(QV2RAY_DEFAULT_VASSETS_PATH "unset" CACHE STRING "v2ray assets path") set(QV2RAY_DEFAULT_VCORE_PATH "unset" CACHE STRING "v2ray core path") set(QV2RAY_TRANSLATION_PATH "unset" CACHE STRING "Qv2ray translations path") +set(QV2RAY_LUPDATE OFF CACHE BOOL "Run lupdate for qv2ray") set(EMBED_TRANSLATIONS OFF CACHE BOOL "Embed translations") if(QV2RAY_DEFAULT_VASSETS_PATH AND NOT STREQUAL "unset") @@ -219,6 +220,13 @@ if(EMBED_TRANSLATIONS) list(APPEND QV2RAY_SOURCES ${CMAKE_BINARY_DIR}/translations.qrc) endif() +if(QV2RAY_LUPDATE) + qt5_create_translation(QM_FILES ${TRANSLATIONS_TS} ${QV2RAY_SOURCES}) + add_custom_target(lupdate + DEPENDS ${QM_FILES} + ) +endif() + set(QRC_RESOURCES ${CMAKE_SOURCE_DIR}/resources.qrc) set(QT_LIBRARY From d2754fb38a961b259124c2f54b46e254cd786e31 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 20:07:03 +0800 Subject: [PATCH 306/332] update: updated lupdate target --- CMakeLists.txt | 12 +++++------- makespec/BUILDVERSION | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 68af8f4f..47c9120b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,7 +129,6 @@ message("Qv2ray build info ex: ${_QV2RAY_BUILD_EXTRA_INFO_STR_}") set(QV2RAY_DEFAULT_VASSETS_PATH "unset" CACHE STRING "v2ray assets path") set(QV2RAY_DEFAULT_VCORE_PATH "unset" CACHE STRING "v2ray core path") set(QV2RAY_TRANSLATION_PATH "unset" CACHE STRING "Qv2ray translations path") -set(QV2RAY_LUPDATE OFF CACHE BOOL "Run lupdate for qv2ray") set(EMBED_TRANSLATIONS OFF CACHE BOOL "Embed translations") if(QV2RAY_DEFAULT_VASSETS_PATH AND NOT STREQUAL "unset") @@ -220,12 +219,11 @@ if(EMBED_TRANSLATIONS) list(APPEND QV2RAY_SOURCES ${CMAKE_BINARY_DIR}/translations.qrc) endif() -if(QV2RAY_LUPDATE) - qt5_create_translation(QM_FILES ${TRANSLATIONS_TS} ${QV2RAY_SOURCES}) - add_custom_target(lupdate - DEPENDS ${QM_FILES} - ) -endif() +add_custom_target(lupdate + lupdate ${QV2RAY_SOURCES} -ts ${TRANSLATIONS_TS} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + +set_target_properties(lupdate PROPERTIES EXCLUDE_FROM_ALL TRUE) set(QRC_RESOURCES ${CMAKE_SOURCE_DIR}/resources.qrc) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 05fb9346..b840a9e9 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4633 \ No newline at end of file +4658 \ No newline at end of file From 5cd3593194ac45546024b2c11303f7a77e23bd8f Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Wed, 11 Mar 2020 20:25:00 +0800 Subject: [PATCH 307/332] update CMakeLists.txt --- CMakeLists.txt | 33 ++++++++++++--------------------- makespec/BUILDVERSION | 2 +- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 47c9120b..fa272cb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/VERSION" QV2RAY_VERSION) file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" QV2RAY_BUILD_VERSION) if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Release") - math(EXPR QV2RAY_BUILD_VERSION "1 + ${QV2RAY_BUILD_VERSION}" OUTPUT_FORMAT DECIMAL) + math(EXPR QV2RAY_BUILD_VERSION "1 + ${QV2RAY_BUILD_VERSION}") message("Increasing BUILDVERSION") file(WRITE "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" ${QV2RAY_BUILD_VERSION}) endif() @@ -86,22 +86,6 @@ include(cmake/protobuf.cmake) include(cmake/cpp-httplib.cmake) include(cmake/backend.cmake) -if(APPLE) - find_package(Iconv REQUIRED) - set(MACOSX_FRAMEWORK - "-framework Carbon" - "-framework Cocoa" - "-framework Security" - ) - set(MACOSX_ICONV_LIBRARY - Iconv::Iconv - ) - - set(MACOSX_ICONV_INCLUDE_PATH - ${Iconv_INCLUDE_DIR} - ) -endif() - if(QV2RAY_BUILD_INFO) set(_QV2RAY_BUILD_INFO_STR_ "${QV2RAY_BUILD_INFO}") elseif(DEFINED ENV{_QV2RAY_BUILD_INFO_}) @@ -251,8 +235,6 @@ add_executable(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} ${QT_LIBRARY} - ${MACOSX_FRAMEWORK} - ${MACOSX_ICONV_LIBRARY} ${QV2RAY_PROTOBUF_LIBRARY} ${QV2RAY_BACKEND_LIBRARIES} ) @@ -267,11 +249,20 @@ target_include_directories(${PROJECT_NAME} PRIVATE ${QZXING_INCLUDE_PATH} ${SINGLEAPPLICATION_DIR} ${Protobuf_INCLUDE_DIRS} - ${MACOSX_ICONV_INCLUDE_PATH} ${cpp-httplib_INCLUDE_DIRS} ) if(APPLE) + find_package(Iconv REQUIRED) + target_link_libraries(${PROJECT_NAME} + Iconv::Iconv + "-framework Carbon" + "-framework Cocoa" + "-framework Security" + ) + target_include_directories(${PROJECT_NAME} PRIVATE + ${Iconv_INCLUDE_DIR} + ) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) set(prefix "${PROJECT_NAME}.app/Contents") set(INSTALL_RUNTIME_DIR "${prefix}/MacOS") @@ -295,7 +286,7 @@ if(UNIX AND NOT APPLE AND NOT WIN32) install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) install(FILES assets/qv2ray.metainfo.xml DESTINATION share/metainfo) install(FILES assets/qv2ray.desktop DESTINATION share/applications) - install(FILES assets/icons/qv2ray.png DESTINATION share/icons/hicolor/256x256/apps/) + install(FILES assets/icons/qv2ray.png DESTINATION share/icons/hicolor/256x256/apps) if(NOT EMBED_TRANSLATIONS) install(FILES ${QM_FILES} DESTINATION share/qv2ray/lang) endif() diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index b840a9e9..b60249d1 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4658 \ No newline at end of file +4659 \ No newline at end of file From 2929c9bb2b69ec9c686e058f56a9800807d1cfa4 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 20:47:33 +0800 Subject: [PATCH 308/332] update submodules --- .gitmodules | 3 +++ 3rdparty/QNodeEditor | 2 +- 3rdparty/SingleApplication | 2 +- 3rdparty/cpp-httplib | 2 +- 3rdparty/qzxing | 2 +- libs/puresource | 1 + 6 files changed, 8 insertions(+), 4 deletions(-) create mode 160000 libs/puresource diff --git a/.gitmodules b/.gitmodules index 1395dfaf..529abebf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "3rdparty/cpp-httplib"] path = 3rdparty/cpp-httplib url = https://github.com/yhirose/cpp-httplib +[submodule "libs/puresource"] + path = libs/puresource + url = https://github.com/Qv2ray/PureSource/ diff --git a/3rdparty/QNodeEditor b/3rdparty/QNodeEditor index 0f368335..c93f1c18 160000 --- a/3rdparty/QNodeEditor +++ b/3rdparty/QNodeEditor @@ -1 +1 @@ -Subproject commit 0f368335943cc8b84a8b52c5ad7cfd9c25ebb6d6 +Subproject commit c93f1c1826d46d5d60f118688cd830b39af8b9c6 diff --git a/3rdparty/SingleApplication b/3rdparty/SingleApplication index 0f6695e2..4abe20af 160000 --- a/3rdparty/SingleApplication +++ b/3rdparty/SingleApplication @@ -1 +1 @@ -Subproject commit 0f6695e2a9d8fdaa336e7ad941855c46c61f218a +Subproject commit 4abe20afbfa5695ac7a9bce1298943b645aeffe9 diff --git a/3rdparty/cpp-httplib b/3rdparty/cpp-httplib index bf7700d1..26deffe0 160000 --- a/3rdparty/cpp-httplib +++ b/3rdparty/cpp-httplib @@ -1 +1 @@ -Subproject commit bf7700d1924e12a27faa5d346a5b8a9f8e163b61 +Subproject commit 26deffe0c6a1e177e393416b94cdc0f340ca79bd diff --git a/3rdparty/qzxing b/3rdparty/qzxing index ee50acba..dac9480a 160000 --- a/3rdparty/qzxing +++ b/3rdparty/qzxing @@ -1 +1 @@ -Subproject commit ee50acba1f10e70ef23c593971621ed7a9f4c5a1 +Subproject commit dac9480a652d591c41ec9ef6f6c966c59a252142 diff --git a/libs/puresource b/libs/puresource new file mode 160000 index 00000000..4af54ebc --- /dev/null +++ b/libs/puresource @@ -0,0 +1 @@ +Subproject commit 4af54ebc77fed903781e9224303bdec646a7c9be From a5cf9222ff4823c3d81a63bfa41484777c7e4be2 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 20:55:52 +0800 Subject: [PATCH 309/332] add: added support with comment-json --- src/common/QvHelpers.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 1999b94c..1bca9224 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -1,5 +1,7 @@ #include "common/QvHelpers.hpp" +#include "libs/puresource/src/PureJson.hpp" + #include #include #include @@ -42,7 +44,8 @@ namespace Qv2ray::common QTextCodec::ConverterState state; QTextCodec *codec = QTextCodec::codecForName("UTF-8"); const QString text = codec->toUnicode(byteArray.constData(), byteArray.size(), &state); - if (state.invalidChars > 0) { + if (state.invalidChars > 0) + { LOG(MODULE_FILEIO, "Not a valid UTF-8 sequence: " + source->fileName()) return source->readAll(); } @@ -73,7 +76,7 @@ namespace Qv2ray::common QJsonObject JSONFromFile(QFile *sourceFile) { - QString json = StringFromFile(sourceFile); + QString json = RemoveComment(StringFromFile(sourceFile)); return JsonFromString(json); } From 8d7ac0a70809d546599f13adb8bb577c8b7e17f7 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 20:57:04 +0800 Subject: [PATCH 310/332] Revert "add: added support with comment-json" This reverts commit a5cf9222ff4823c3d81a63bfa41484777c7e4be2. --- src/common/QvHelpers.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 1bca9224..1999b94c 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -1,7 +1,5 @@ #include "common/QvHelpers.hpp" -#include "libs/puresource/src/PureJson.hpp" - #include #include #include @@ -44,8 +42,7 @@ namespace Qv2ray::common QTextCodec::ConverterState state; QTextCodec *codec = QTextCodec::codecForName("UTF-8"); const QString text = codec->toUnicode(byteArray.constData(), byteArray.size(), &state); - if (state.invalidChars > 0) - { + if (state.invalidChars > 0) { LOG(MODULE_FILEIO, "Not a valid UTF-8 sequence: " + source->fileName()) return source->readAll(); } @@ -76,7 +73,7 @@ namespace Qv2ray::common QJsonObject JSONFromFile(QFile *sourceFile) { - QString json = RemoveComment(StringFromFile(sourceFile)); + QString json = StringFromFile(sourceFile); return JsonFromString(json); } From 26aaa14c9ac6eba3d61bca547d5a68b38fdeb263 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 21:10:04 +0800 Subject: [PATCH 311/332] add: added support with comment-json - fix --- src/common/QvHelpers.cpp | 33 +++++++++++++++++++++------------ src/common/QvHelpers.hpp | 20 ++++++++++---------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 1999b94c..9fd2fa1f 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -1,5 +1,7 @@ #include "common/QvHelpers.hpp" +#include "libs/puresource/src/PureJson.hpp" + #include #include #include @@ -42,7 +44,8 @@ namespace Qv2ray::common QTextCodec::ConverterState state; QTextCodec *codec = QTextCodec::codecForName("UTF-8"); const QString text = codec->toUnicode(byteArray.constData(), byteArray.size(), &state); - if (state.invalidChars > 0) { + if (state.invalidChars > 0) + { LOG(MODULE_FILEIO, "Not a valid UTF-8 sequence: " + source->fileName()) return source->readAll(); } @@ -77,14 +80,14 @@ namespace Qv2ray::common return JsonFromString(json); } - QString JsonToString(QJsonObject json, QJsonDocument::JsonFormat format) + QString JsonToString(const QJsonObject &json, QJsonDocument::JsonFormat format) { QJsonDocument doc; doc.setObject(json); return doc.toJson(format); } - QString JsonToString(QJsonArray array, QJsonDocument::JsonFormat format) + QString JsonToString(const QJsonArray &array, QJsonDocument::JsonFormat format) { QJsonDocument doc; doc.setArray(array); @@ -108,19 +111,24 @@ namespace Qv2ray::common } } - QJsonObject JsonFromString(QString string) + QJsonObject JsonFromString(const QString &string) { - QJsonDocument doc = QJsonDocument::fromJson(string.toUtf8()); + auto removeComment = RemoveComment(string); + if (removeComment != string) + { + LOG(MODULE_FILEIO, "Some comments have been removed from the json.") + } + QJsonDocument doc = QJsonDocument::fromJson(removeComment.toUtf8()); return doc.object(); } - QString Base64Encode(QString string) + QString Base64Encode(const QString &string) { QByteArray ba = string.toUtf8(); return ba.toBase64(); } - QString Base64Decode(QString string) + QString Base64Decode(const QString &string) { QByteArray ba = string.toUtf8(); return QString(QByteArray::fromBase64(ba)); @@ -143,27 +151,28 @@ namespace Qv2ray::common return list; } - QStringList GetFileList(QDir dir) + QStringList GetFileList(const QDir &dir) { return dir.entryList(QStringList{ "*", "*.*" }, QDir::Hidden | QDir::Files); } - bool FileExistsIn(QDir dir, QString fileName) + bool FileExistsIn(const QDir &dir, const QString &fileName) { return GetFileList(dir).contains(fileName); } - void QvMessageBoxWarn(QWidget *parent, QString title, QString text) + void QvMessageBoxWarn(QWidget *parent, const QString &title, const QString &text) { QMessageBox::warning(parent, title, text, QMessageBox::Ok | QMessageBox::Default, 0); } - void QvMessageBoxInfo(QWidget *parent, QString title, QString text) + void QvMessageBoxInfo(QWidget *parent, const QString &title, const QString &text) { QMessageBox::information(parent, title, text, QMessageBox::Ok | QMessageBox::Default, 0); } - QMessageBox::StandardButton QvMessageBoxAsk(QWidget *parent, QString title, QString text, QMessageBox::StandardButton extraButtons) + QMessageBox::StandardButton QvMessageBoxAsk(QWidget *parent, const QString &title, const QString &text, + QMessageBox::StandardButton extraButtons) { return QMessageBox::question(parent, title, text, QMessageBox::Yes | QMessageBox::No | extraButtons); } diff --git a/src/common/QvHelpers.hpp b/src/common/QvHelpers.hpp index 3cefd584..a13d75b5 100644 --- a/src/common/QvHelpers.hpp +++ b/src/common/QvHelpers.hpp @@ -12,17 +12,17 @@ namespace Qv2ray::common { - QStringList GetFileList(QDir dir); - QString Base64Encode(QString string); - QString Base64Decode(QString string); + QStringList GetFileList(const QDir &dir); + QString Base64Encode(const QString &string); + QString Base64Decode(const QString &string); QStringList SplitLines(const QString &str); list SplitLines_std(const QString &_string); - bool FileExistsIn(QDir dir, QString fileName); + bool FileExistsIn(const QDir &dir, const QString &fileName); const QString GenerateRandomString(int len = 12); // - void QvMessageBoxWarn(QWidget *parent, QString title, QString text); - void QvMessageBoxInfo(QWidget *parent, QString title, QString text); - QMessageBox::StandardButton QvMessageBoxAsk(QWidget *parent, QString title, QString text, + void QvMessageBoxWarn(QWidget *parent, const QString &title, const QString &text); + void QvMessageBoxInfo(QWidget *parent, const QString &title, const QString &text); + QMessageBox::StandardButton QvMessageBoxAsk(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButton extraButtons = QMessageBox::NoButton); // QString StringFromFile(const QString &filePath); @@ -30,9 +30,9 @@ namespace Qv2ray::common bool StringToFile(const QString &text, QFile &target); bool StringToFile(const QString &text, const QString &targetpath); // - QJsonObject JsonFromString(QString string); - QString JsonToString(QJsonObject json, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented); - QString JsonToString(QJsonArray array, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented); + QJsonObject JsonFromString(const QString &string); + QString JsonToString(const QJsonObject &json, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented); + QString JsonToString(const QJsonArray &array, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented); QString VerifyJsonString(const QString &source); // QString FormatBytes(const int64_t bytes); From c90710f78684e78878c3ae5a25f583e5e1b5c198 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Wed, 11 Mar 2020 21:26:18 +0800 Subject: [PATCH 312/332] update CMakeLists.txt --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5abfb9a8..85ec6314 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,7 @@ message("Qv2ray build info ex: ${_QV2RAY_BUILD_EXTRA_INFO_STR_}") set(QV2RAY_DEFAULT_VASSETS_PATH "unset" CACHE STRING "v2ray assets path") set(QV2RAY_DEFAULT_VCORE_PATH "unset" CACHE STRING "v2ray core path") set(QV2RAY_TRANSLATION_PATH "unset" CACHE STRING "Qv2ray translations path") +set(QV2RAY_DISABLE_AUTO_UPDATE OFF CACHE BOOL "Disable update checker") set(EMBED_TRANSLATIONS OFF CACHE BOOL "Embed translations") if(QV2RAY_DEFAULT_VASSETS_PATH AND NOT STREQUAL "unset") @@ -127,6 +128,10 @@ if(QV2RAY_TRANSLATION_PATH AND NOT STREQUAL "unset") add_definitions(-DQV2RAY_TRANSLATION_PATH="${QV2RAY_TRANSLATION_PATH}") endif() +if(QV2RAY_DISABLE_AUTO_UPDATE) + add_definitions(-DDISABLE_AUTO_UPDATE) +endif() + set(QV2RAY_SOURCES src/base/Qv2rayLog.cpp src/common/CommandArgs.cpp From fb04ce62326d47c15e0e08b8bf23cf915ab5661d Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 21:29:28 +0800 Subject: [PATCH 313/332] fix: adjusted minimum size for smaller screens --- makespec/BUILDVERSION | 2 +- src/ui/w_MainWindow.ui | 127 +++++++++++++++++++---------------------- 2 files changed, 60 insertions(+), 69 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 4c7368f7..36aa6d66 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4661 \ No newline at end of file +4662 \ No newline at end of file diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 1d405974..d688c68e 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -6,14 +6,14 @@ 0 0 - 900 - 650 + 880 + 660 - 900 - 650 + 780 + 530 @@ -23,18 +23,6 @@ - - - 0 - 0 - - - - - 680 - 530 - - @@ -116,58 +104,6 @@ - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - Import Connection - - - Add - - - - 22 - 22 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - @@ -227,6 +163,58 @@ + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Import Connection + + + Add + + + + 22 + 22 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + @@ -273,6 +261,9 @@ + + 0 + 0 From 23b23bb4af021e66b354179c748e42f22db9b471 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 22:03:26 +0800 Subject: [PATCH 314/332] fix: use cmake to determine the darktheme settings flag --- src/base/Qv2rayBase.hpp | 7 ------- src/main.cpp | 2 +- src/ui/w_PreferencesWindow.cpp | 4 ++-- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/base/Qv2rayBase.hpp b/src/base/Qv2rayBase.hpp index 3b81768a..832a6cb6 100644 --- a/src/base/Qv2rayBase.hpp +++ b/src/base/Qv2rayBase.hpp @@ -31,13 +31,6 @@ using namespace Qv2ray::base::objects; using namespace Qv2ray::base::objects::protocol; using namespace Qv2ray::base::objects::transfer; -// Linux users and DEs should handle the darkMode UI themselves. -#ifndef QV2RAY_USE_BUILTIN_DARKTHEME - #ifndef Q_OS_LINUX - #define QV2RAY_USE_BUILTIN_DARKTHEME - #endif -#endif - #define QV2RAY_BUILD_INFO QString(_QV2RAY_BUILD_INFO_STR_) #define QV2RAY_BUILD_EXTRA_INFO QString(_QV2RAY_BUILD_EXTRA_INFO_STR_) diff --git a/src/main.cpp b/src/main.cpp index ca956d11..a14e4633 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -449,7 +449,7 @@ int main(int argc, char *argv[]) font.setFamily("Microsoft YaHei"); _qApp.setFont(font); #endif -#ifdef QV2RAY_USE_BUILTIN_DARKTHEME +#if (QV2RAY_USE_BUILTIN_DARKTHEME) LOG(MODULE_UI, "Using built-in theme.") if (confObject.uiConfig.useDarkTheme) diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index 3a422319..4daa76fa 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -73,7 +73,7 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent), Current themeCombo->setCurrentText(CurrentConfig.uiConfig.theme); darkThemeCB->setChecked(CurrentConfig.uiConfig.useDarkTheme); darkTrayCB->setChecked(CurrentConfig.uiConfig.useDarkTrayIcon); -#ifdef QV2RAY_USE_BUILTIN_DARKTHEME +#if (QV2RAY_USE_BUILTIN_DARKTHEME) // If we use built in theme, it should always be fusion. themeCombo->setEnabled(!CurrentConfig.uiConfig.useDarkTheme); darkThemeLabel->setText(tr("Use Darkmode Theme")); @@ -896,7 +896,7 @@ void PreferencesWindow::on_darkThemeCB_stateChanged(int arg1) { LOADINGCHECK CurrentConfig.uiConfig.useDarkTheme = arg1 == Qt::Checked; -#ifdef QV2RAY_USE_BUILTIN_DARKTHEME +#if (QV2RAY_USE_BUILTIN_DARKTHEME) themeCombo->setEnabled(arg1 != Qt::Checked); if (arg1 == Qt::Checked) From dc8431a1a45719deb6e910bed9282c1816690763 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Wed, 11 Mar 2020 22:39:33 +0800 Subject: [PATCH 315/332] add QV2RAY_USE_BUILTIN_DARKTHEME args to cmake --- CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 85ec6314..e61117a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,7 @@ set(QV2RAY_DEFAULT_VASSETS_PATH "unset" CACHE STRING "v2ray assets path") set(QV2RAY_DEFAULT_VCORE_PATH "unset" CACHE STRING "v2ray core path") set(QV2RAY_TRANSLATION_PATH "unset" CACHE STRING "Qv2ray translations path") set(QV2RAY_DISABLE_AUTO_UPDATE OFF CACHE BOOL "Disable update checker") +set(QV2RAY_USE_BUILTIN_DARKTHEME OFF CACHE BOOL "Use built-in dark theme instead of followed by the system settings") set(EMBED_TRANSLATIONS OFF CACHE BOOL "Embed translations") if(QV2RAY_DEFAULT_VASSETS_PATH AND NOT STREQUAL "unset") @@ -128,6 +129,14 @@ if(QV2RAY_TRANSLATION_PATH AND NOT STREQUAL "unset") add_definitions(-DQV2RAY_TRANSLATION_PATH="${QV2RAY_TRANSLATION_PATH}") endif() +if(APPLE OR WIN32) + set(QV2RAY_USE_BUILTIN_DARKTHEME ON) +endif() + +if(QV2RAY_USE_BUILTIN_DARKTHEME) + add_definitions(-DQV2RAY_USE_BUILTIN_DARKTHEME=true) +endif() + if(QV2RAY_DISABLE_AUTO_UPDATE) add_definitions(-DDISABLE_AUTO_UPDATE) endif() From 60af0ab8bbdef68dfa0173cdf7d670ec9f163d72 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Wed, 11 Mar 2020 23:45:32 +0800 Subject: [PATCH 316/332] fix: fixed a custom outbound issue --- makespec/BUILDVERSION | 2 +- src/core/connection/Generation.cpp | 46 +++++++++++++------------ src/core/connection/Generation.hpp | 2 +- src/ui/w_MainWindow.cpp | 33 ++++++++++-------- src/ui/widgets/StreamSettingsWidget.cpp | 2 +- 5 files changed, 46 insertions(+), 39 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 36aa6d66..66be7d9d 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4662 \ No newline at end of file +4663 \ No newline at end of file diff --git a/src/core/connection/Generation.cpp b/src/core/connection/Generation.cpp index 5ae0c111..5be659a5 100644 --- a/src/core/connection/Generation.cpp +++ b/src/core/connection/Generation.cpp @@ -9,7 +9,7 @@ namespace Qv2ray::core::connection { // -------------------------- BEGIN CONFIG GENERATIONS // ---------------------------------------------------------------------------- - ROUTING GenerateRoutes(bool enableProxy, bool proxyCN) + ROUTING GenerateRoutes(bool enableProxy, bool proxyCN, const QString &proxyTag, const QString &directTag) { ROUTING root; root.insert("domainStrategy", "IPIfNonMatch"); @@ -21,15 +21,15 @@ namespace Qv2ray::core::connection { // This is added to disable all proxies, as a alternative // influence of #64 - rulesList.append(GenerateSingleRouteRule("regexp:.*", true, OUTBOUND_TAG_DIRECT)); + rulesList.append(GenerateSingleRouteRule("regexp:.*", true, directTag)); } // Private IPs should always NOT TO PROXY! - rulesList.append(GenerateSingleRouteRule("geoip:private", false, OUTBOUND_TAG_DIRECT)); + rulesList.append(GenerateSingleRouteRule("geoip:private", false, directTag)); // // Check if CN needs proxy, or direct. - rulesList.append(GenerateSingleRouteRule("geoip:cn", false, proxyCN ? OUTBOUND_TAG_DIRECT : OUTBOUND_TAG_PROXY)); - rulesList.append(GenerateSingleRouteRule("geosite:cn", true, proxyCN ? OUTBOUND_TAG_DIRECT : OUTBOUND_TAG_PROXY)); + rulesList.append(GenerateSingleRouteRule("geoip:cn", false, proxyCN ? directTag : proxyTag)); + rulesList.append(GenerateSingleRouteRule("geosite:cn", true, proxyCN ? directTag : proxyTag)); // // As a bug fix of #64, this default rule has been disabled. // rulesList.append(GenerateSingleRouteRule(QStringList({"regexp:.*"}), @@ -120,7 +120,7 @@ namespace Qv2ray::core::connection INBOUNDSETTING root; QJsonArray accounts; - foreach (auto account, _accounts) + for (auto account : _accounts) { if (account.user.isEmpty() && account.pass.isEmpty()) { @@ -208,7 +208,7 @@ namespace Qv2ray::core::connection QJsonObject allocate) { INBOUND root; - LOG(MODULE_CONNECTION, "allocation is not used here.") + DEBUG(MODULE_CONNECTION, "Allocation is not used here, Not Implemented") Q_UNUSED(allocate) JADD(listen, port, protocol, settings, tag, sniffing) RROOT @@ -238,13 +238,13 @@ namespace Qv2ray::core::connection CONFIGROOT GenerateRuntimeConfig(CONFIGROOT root) { + // Check if is complex BEFORE adding anything. bool isComplex = IsComplexConfig(root); + // QJsonObject logObject; // - // logObject.insert("access", QV2RAY_CONFIG_PATH + - // QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ACCESS_LOG_FILENAME); - // logObject.insert("error", QV2RAY_CONFIG_PATH + - // QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ERROR_LOG_FILENAME); + // logObject.insert("access", QV2RAY_CONFIG_PATH + QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ACCESS_LOG_FILENAME); + // logObject.insert("error", QV2RAY_CONFIG_PATH + QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ERROR_LOG_FILENAME); // logObject.insert("loglevel", vLogLevels[GlobalConfig.logLevel]); root.insert("log", logObject); @@ -257,7 +257,7 @@ namespace Qv2ray::core::connection // If inbounds list is empty we append our global configured // inbounds to the config. - if (!root.contains("inbounds") || root["inbounds"].toArray().empty()) + if (!root.contains("inbounds") || root.value("inbounds").toArray().empty()) { INBOUNDS inboundsList; @@ -319,7 +319,9 @@ namespace Qv2ray::core::connection // // Note: The part below always makes the whole functionality in // trouble...... BE EXTREME CAREFUL when changing these code - // below... See: https://github.com/lhy0403/Qv2ray/issues/129 + // below... + // + // See: https://github.com/Qv2ray/Qv2ray/issues/129 // routeCountLabel in Mainwindow makes here failed to ENOUGH-ly // check the routing tables @@ -331,7 +333,7 @@ namespace Qv2ray::core::connection // HOWEVER, we need to verify the QV2RAY_RULE_ENABLED entry. // And what's more, process (by removing unused items) from a // rule object. - ROUTING routing = ROUTING(root["routing"].toObject()); + ROUTING routing(root["routing"].toObject()); ROUTERULELIST rules; LOG(MODULE_CONNECTION, "Processing an existing routing table.") @@ -354,7 +356,7 @@ namespace Qv2ray::core::connection } else { - LOG(MODULE_SETTINGS, "We found a rule without QV2RAY_RULE_USE_BALANCER, so don't process it.") + LOG(MODULE_SETTINGS, "We found a rule without QV2RAY_RULE_USE_BALANCER, so didn't process it.") } // If this entry has been disabled. @@ -373,7 +375,6 @@ namespace Qv2ray::core::connection } else { - // LOG(MODULE_CONNECTION, "Inserting default values to simple config") if (root["outbounds"].toArray().count() != 1) @@ -383,8 +384,10 @@ namespace Qv2ray::core::connection LOG(MODULE_CONNECTION, "WARN: This message usually indicates the config file has logic errors:") LOG(MODULE_CONNECTION, "WARN: --> The config file has NO routing section, however more than 1 outbounds are detected.") } + auto outboundTag = getTag(OUTBOUND(root["outbounds"].toArray().first().toObject())); - auto routeObject = GenerateRoutes(GlobalConfig.connectionConfig.enableProxy, GlobalConfig.connectionConfig.bypassCN); + auto routeObject = + GenerateRoutes(GlobalConfig.connectionConfig.enableProxy, GlobalConfig.connectionConfig.bypassCN, outboundTag); root.insert("routing", routeObject); // // Process forward proxy @@ -408,8 +411,8 @@ namespace Qv2ray::core::connection { fpOutbound = GenerateHTTPSOCKSOut(fpConf.serverAddress, fpConf.port, fpConf.useAuth, fpConf.username, fpConf.password); - outboundArray.push_back(GenerateOutboundEntry(fpConf.type.toLower(), fpOutbound, QJsonObject(), QJsonObject(), - "0.0.0.0", OUTBOUND_TAG_FORWARD_PROXY)); + outboundArray.push_back( + GenerateOutboundEntry(fpConf.type.toLower(), fpOutbound, {}, {}, "0.0.0.0", OUTBOUND_TAG_FORWARD_PROXY)); } else { @@ -435,8 +438,7 @@ namespace Qv2ray::core::connection #undef fpConf OUTBOUNDS outbounds = OUTBOUNDS(root["outbounds"].toArray()); - outbounds.append(GenerateOutboundEntry("freedom", GenerateFreedomOUT("AsIs", ":0", 0), QJsonObject(), QJsonObject(), "0.0.0.0", - OUTBOUND_TAG_DIRECT)); + outbounds.append(GenerateOutboundEntry("freedom", GenerateFreedomOUT("AsIs", ":0", 0), {}, {}, "0.0.0.0", OUTBOUND_TAG_DIRECT)); root["outbounds"] = outbounds; } @@ -474,7 +476,7 @@ namespace Qv2ray::core::connection // // Inbounds // - INBOUNDS inbounds = INBOUNDS(root["inbounds"].toArray()); + INBOUNDS inbounds(root["inbounds"].toArray()); INBOUNDSETTING fakeDocodemoDoor; fakeDocodemoDoor["address"] = "127.0.0.1"; QJsonObject apiInboundsRoot = diff --git a/src/core/connection/Generation.hpp b/src/core/connection/Generation.hpp index c40b32d3..8a002f03 100644 --- a/src/core/connection/Generation.hpp +++ b/src/core/connection/Generation.hpp @@ -6,7 +6,7 @@ namespace Qv2ray::core::connection { // Important config generation algorithms. const QStringList vLogLevels = { "none", "debug", "info", "warning", "error" }; - ROUTING GenerateRoutes(bool enableProxy, bool cnProxy); + ROUTING GenerateRoutes(bool enableProxy, bool cnProxy, const QString &proxyTag, const QString &directTag = OUTBOUND_TAG_DIRECT); ROUTERULE GenerateSingleRouteRule(QString str, bool isDomain, QString outboundTag, QString type = "field"); ROUTERULE GenerateSingleRouteRule(QStringList list, bool isDomain, QString outboundTag, QString type = "field"); QJsonObject GenerateDNS(bool withLocalhost, QStringList dnsServers); diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index d17ee7d1..64d6b847 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -70,7 +70,7 @@ void MainWindow::MWAddConnectionItem_p(const ConnectionId &connection, const Gro { MWAddGroupItem_p(groupId); } - auto groupItem = groupNodes[groupId]; + auto groupItem = groupNodes.value(groupId); auto connectionItem = make_shared(QStringList{ "", // GetDisplayName(connection), // @@ -79,7 +79,7 @@ void MainWindow::MWAddConnectionItem_p(const ConnectionId &connection, const Gro "LAST_CONNECTED_NOT_SUPPORTED", // NumericString(GetConnectionTotalData(connection)) // }); - connectionNodes[connection] = connectionItem; + connectionNodes.insert(connection, connectionItem); groupItem->addChild(connectionItem.get()); auto widget = new ConnectionItemWidget(connection, connectionListWidget); connect(widget, &ConnectionItemWidget::RequestWidgetFocus, this, &MainWindow::OnConnectionWidgetFocusRequested); @@ -89,7 +89,7 @@ void MainWindow::MWAddConnectionItem_p(const ConnectionId &connection, const Gro void MainWindow::MWAddGroupItem_p(const GroupId &groupId) { auto groupItem = make_shared(QStringList{ "", GetDisplayName(groupId) }); - groupNodes[groupId] = groupItem; + groupNodes.insert(groupId, groupItem); connectionListWidget->addTopLevelItem(groupItem.get()); connectionListWidget->setItemWidget(groupItem.get(), 0, new ConnectionItemWidget(groupId, connectionListWidget)); } @@ -142,10 +142,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) connect(ConnectionManager, &QvConfigHandler::OnGroupDeleted, this, &MainWindow::OnGroupDeleted); // connect(ConnectionManager, &QvConfigHandler::OnConnectionRenamed, [&](const ConnectionId &id, const QString &, const QString &newName) { - connectionNodes[id]->setText(MW_ITEM_COL_NAME, newName); // + if (connectionNodes.contains(id)) + connectionNodes.value(id)->setText(MW_ITEM_COL_NAME, newName); // }); connect(ConnectionManager, &QvConfigHandler::OnLatencyTestFinished, [&](const ConnectionId &id, const uint avg) { - connectionNodes[id]->setText(MW_ITEM_COL_PING, NumericString(avg)); // + if (connectionNodes.contains(id)) + connectionNodes.value(id)->setText(MW_ITEM_COL_PING, NumericString(avg)); // }); // connect(infoWidget, &ConnectionInfoWidget::OnEditRequested, this, &MainWindow::OnEditRequested); @@ -743,7 +745,10 @@ void MainWindow::OnStatsAvailable(const ConnectionId &id, const quint64 upS, con NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); // // Set data accordingly - connectionNodes[id]->setText(MW_ITEM_COL_DATA, NumericString(GetConnectionTotalData(id))); + if (connectionNodes.contains(id)) + { + connectionNodes.value(id)->setText(MW_ITEM_COL_DATA, NumericString(GetConnectionTotalData(id))); + } } void MainWindow::OnVCoreLogAvailable(const ConnectionId &id, const QString &log) @@ -824,14 +829,14 @@ void MainWindow::OnConnectionCreated(const ConnectionId &id, const QString &disp } void MainWindow::OnConnectionDeleted(const ConnectionId &id, const GroupId &groupId) { - auto &child = connectionNodes[id]; - groupNodes[groupId]->removeChild(child.get()); + auto &child = connectionNodes.value(id); + groupNodes.value(groupId)->removeChild(child.get()); connectionNodes.remove(id); } void MainWindow::OnConnectionGroupChanged(const ConnectionId &id, const GroupId &originalGroup, const GroupId &newGroup) { - delete GetItemWidget(connectionNodes[id].get()); - groupNodes[originalGroup]->removeChild(connectionNodes[id].get()); + delete GetItemWidget(connectionNodes.value(id).get()); + groupNodes.value(originalGroup)->removeChild(connectionNodes.value(id).get()); connectionNodes.remove(id); MWAddConnectionItem_p(id, newGroup); } @@ -844,7 +849,7 @@ void MainWindow::OnGroupDeleted(const GroupId &id, const QList &co { for (auto conn : connections) { - groupNodes[id]->removeChild(connectionNodes[conn].get()); + groupNodes.value(id)->removeChild(connectionNodes.value(conn).get()); } groupNodes.remove(id); } @@ -854,9 +859,9 @@ void MainWindow::on_locateBtn_clicked() auto id = ConnectionManager->CurrentConnection(); if (id != NullConnectionId) { - connectionListWidget->setCurrentItem(connectionNodes[id].get()); - connectionListWidget->scrollToItem(connectionNodes[id].get()); - on_connectionListWidget_itemClicked(connectionNodes[id].get(), 0); + connectionListWidget->setCurrentItem(connectionNodes.value(id).get()); + connectionListWidget->scrollToItem(connectionNodes.value(id).get()); + on_connectionListWidget_itemClicked(connectionNodes.value(id).get(), 0); } } diff --git a/src/ui/widgets/StreamSettingsWidget.cpp b/src/ui/widgets/StreamSettingsWidget.cpp index d1af0ea0..a0f1825c 100644 --- a/src/ui/widgets/StreamSettingsWidget.cpp +++ b/src/ui/widgets/StreamSettingsWidget.cpp @@ -49,7 +49,7 @@ void StreamSettingsWidget::SetStreamObject(const StreamSettingsObject &sso) QString wsHeaders; for (auto index = 0; index < stream.wsSettings.headers.count(); index++) { - wsHeaders % stream.wsSettings.headers.keys().at(index) % "|" % stream.wsSettings.headers.values().at(index) % NEWLINE; + wsHeaders = wsHeaders % stream.wsSettings.headers.keys().at(index) % "|" % stream.wsSettings.headers.values().at(index) % NEWLINE; } wsHeadersTxt->setPlainText(wsHeaders); From a57b1417f9cb8ec4fed463d5ed6f2fab9e2950c4 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 12 Mar 2020 09:50:57 +0800 Subject: [PATCH 317/332] fix: fixed autostart when using AppImage --- makespec/BUILDVERSION | 2 +- src/components/autolaunch/QvAutoLaunch.cpp | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 66be7d9d..547a10ee 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4663 \ No newline at end of file +4664 \ No newline at end of file diff --git a/src/components/autolaunch/QvAutoLaunch.cpp b/src/components/autolaunch/QvAutoLaunch.cpp index 96a672fd..cdf2f006 100644 --- a/src/components/autolaunch/QvAutoLaunch.cpp +++ b/src/components/autolaunch/QvAutoLaunch.cpp @@ -155,8 +155,11 @@ namespace Qv2ray::components::autolaunch } #elif defined Q_OS_LINUX - // From - // https://github.com/nextcloud/desktop/blob/master/src/common/utility_unix.cpp + // + // For AppImage packaging. + auto binPath = qEnvironmentVariableIsSet("APPIMAGE") ? qEnvironmentVariable("APPIMAGE") : QCoreApplication::applicationFilePath(); + // + // From https://github.com/nextcloud/desktop/blob/master/src/common/utility_unix.cpp QString appName = QApplication::applicationName(); QString userAutoStartPath = getUserAutostartDir_private(); QString desktopFileLocation = userAutoStartPath + appName + QLatin1String(".desktop"); @@ -184,7 +187,7 @@ namespace Qv2ray::components::autolaunch ts << QLatin1String("[Desktop Entry]") << endl << QLatin1String("Name=") << QApplication::applicationName() << endl << QLatin1String("GenericName=") << QLatin1String("V2ray Frontend") << endl - << QLatin1String("Exec=") << QCoreApplication::applicationFilePath() << endl + << QLatin1String("Exec=") << binPath << endl << QLatin1String("Terminal=") << "false" << endl << QLatin1String("Icon=") << "qv2ray" << endl // always use lowercase for icons << QLatin1String("Categories=") << "Network" << endl From 3b5e3cc758ebe1b4d0a4243f0aa2a66064dad211 Mon Sep 17 00:00:00 2001 From: Guobang Bi <373318510@qq.com> Date: Thu, 12 Mar 2020 10:06:46 +0800 Subject: [PATCH 318/332] update CMakeLists.txt --- CMakeLists.txt | 10 +++++----- makespec/BUILDVERSION | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e61117a2..9b0b99e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,11 @@ set(QV2RAY_DEFAULT_VASSETS_PATH "unset" CACHE STRING "v2ray assets path") set(QV2RAY_DEFAULT_VCORE_PATH "unset" CACHE STRING "v2ray core path") set(QV2RAY_TRANSLATION_PATH "unset" CACHE STRING "Qv2ray translations path") set(QV2RAY_DISABLE_AUTO_UPDATE OFF CACHE BOOL "Disable update checker") -set(QV2RAY_USE_BUILTIN_DARKTHEME OFF CACHE BOOL "Use built-in dark theme instead of followed by the system settings") +if(UNIX AND NOT APPLE) + set(QV2RAY_USE_BUILTIN_DARKTHEME OFF CACHE BOOL "Use built-in dark theme instead of followed by the system settings") +else() + set(QV2RAY_USE_BUILTIN_DARKTHEME ON CACHE BOOL "Use built-in dark theme instead of followed by the system settings") +endif() set(EMBED_TRANSLATIONS OFF CACHE BOOL "Embed translations") if(QV2RAY_DEFAULT_VASSETS_PATH AND NOT STREQUAL "unset") @@ -129,10 +133,6 @@ if(QV2RAY_TRANSLATION_PATH AND NOT STREQUAL "unset") add_definitions(-DQV2RAY_TRANSLATION_PATH="${QV2RAY_TRANSLATION_PATH}") endif() -if(APPLE OR WIN32) - set(QV2RAY_USE_BUILTIN_DARKTHEME ON) -endif() - if(QV2RAY_USE_BUILTIN_DARKTHEME) add_definitions(-DQV2RAY_USE_BUILTIN_DARKTHEME=true) endif() diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 547a10ee..8eef87f3 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4664 \ No newline at end of file +4664 From 1a61e7fdd00c3be74fe77cecdda67a03b0b76b9c Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 12 Mar 2020 10:18:57 +0800 Subject: [PATCH 319/332] Test against multiple qt version. (#413) * Update build-qv2ray-cmake.yml * Update build-qv2ray-cmake.yml * Update build-qv2ray-cmake.yml * Update build-qv2ray-cmake.yml * Update build-qv2ray-cmake.yml * Update build-qv2ray-cmake.yml --- .github/workflows/build-qv2ray-cmake.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index a9592f59..4b059d87 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -9,23 +9,25 @@ jobs: build: strategy: matrix: - qt_version: [5.13.2, 5.14.1] + qt_version: [5.11.3, 5.12.7, 5.13.2, 5.14.2] platform: [ubuntu-16.04, macos-latest, windows-latest] arch: [x86, x64] include: - platform: windows-latest arch: x86 qtarch: win32_msvc2017 - buildarch: Win32 - platform: windows-latest arch: x64 qtarch: win64_msvc2017_64 - buildarch: x64 exclude: - platform: ubuntu-16.04 arch: x86 - platform: macos-latest arch: x86 + - platform: windows-latest + qt_version: 5.11.3 + - platform: windows-latest + qt_version: 5.12.7 fail-fast: false runs-on: ${{ matrix.platform }} @@ -161,7 +163,7 @@ jobs: path: build/AppDir/Qv2ray.AppImage - name: Linux - ${{ matrix.qt_version }} - Upload binaries to release uses: svenstaro/upload-release-action@v1-release - if: github.event_name == 'release' && matrix.platform == 'ubuntu-16.04' && matrix.qt_version == '5.14.1' + if: github.event_name == 'release' && matrix.platform == 'ubuntu-16.04' && matrix.qt_version == '5.14.2' with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: build/AppDir/Qv2ray.AppImage @@ -182,7 +184,7 @@ jobs: path: build/Qv2ray.app.tar.gz - name: macOS - ${{ matrix.qt_version }} - Upload binaries to release uses: svenstaro/upload-release-action@v1-release - if: github.event_name == 'release' && matrix.platform == 'macos-latest' && matrix.qt_version == '5.14.1' + if: github.event_name == 'release' && matrix.platform == 'macos-latest' && matrix.qt_version == '5.14.2' with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: build/Qv2ray.app.tar.gz @@ -204,7 +206,7 @@ jobs: path: release.7z - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Upload binaries to release uses: svenstaro/upload-release-action@v1-release - if: github.event_name == 'release' && matrix.platform == 'windows-latest' && matrix.qt_version == '5.14.1' + if: github.event_name == 'release' && matrix.platform == 'windows-latest' && matrix.qt_version == '5.14.2' with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: release.7z From e81e575d54d870105a2570d02c04bd9706bf6789 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 12 Mar 2020 10:35:48 +0800 Subject: [PATCH 320/332] fix: fixed connection issue with empty outbound tag --- makespec/BUILDVERSION | 2 +- src/core/connection/Generation.cpp | 18 ++++++++++-------- src/core/connection/Generation.hpp | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 8eef87f3..4a25a85f 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4664 +4665 \ No newline at end of file diff --git a/src/core/connection/Generation.cpp b/src/core/connection/Generation.cpp index 5be659a5..b57f69b2 100644 --- a/src/core/connection/Generation.cpp +++ b/src/core/connection/Generation.cpp @@ -9,7 +9,7 @@ namespace Qv2ray::core::connection { // -------------------------- BEGIN CONFIG GENERATIONS // ---------------------------------------------------------------------------- - ROUTING GenerateRoutes(bool enableProxy, bool proxyCN, const QString &proxyTag, const QString &directTag) + ROUTING GenerateRoutes(bool enableProxy, bool bypassCN) { ROUTING root; root.insert("domainStrategy", "IPIfNonMatch"); @@ -21,16 +21,19 @@ namespace Qv2ray::core::connection { // This is added to disable all proxies, as a alternative // influence of #64 - rulesList.append(GenerateSingleRouteRule("regexp:.*", true, directTag)); + rulesList.append(GenerateSingleRouteRule("regexp:.*", true, OUTBOUND_TAG_DIRECT)); } // Private IPs should always NOT TO PROXY! - rulesList.append(GenerateSingleRouteRule("geoip:private", false, directTag)); + rulesList.append(GenerateSingleRouteRule("geoip:private", false, OUTBOUND_TAG_DIRECT)); // // Check if CN needs proxy, or direct. - rulesList.append(GenerateSingleRouteRule("geoip:cn", false, proxyCN ? directTag : proxyTag)); - rulesList.append(GenerateSingleRouteRule("geosite:cn", true, proxyCN ? directTag : proxyTag)); - // + if (bypassCN) + { + // No proxy agains CN addresses. + rulesList.append(GenerateSingleRouteRule("geoip:cn", false, OUTBOUND_TAG_DIRECT)); + rulesList.append(GenerateSingleRouteRule("geosite:cn", true, OUTBOUND_TAG_DIRECT)); + } // As a bug fix of #64, this default rule has been disabled. // rulesList.append(GenerateSingleRouteRule(QStringList({"regexp:.*"}), // true, globalProxy ? OUTBOUND_TAG_PROXY : OUTBOUND_TAG_DIRECT)); @@ -386,8 +389,7 @@ namespace Qv2ray::core::connection } auto outboundTag = getTag(OUTBOUND(root["outbounds"].toArray().first().toObject())); - auto routeObject = - GenerateRoutes(GlobalConfig.connectionConfig.enableProxy, GlobalConfig.connectionConfig.bypassCN, outboundTag); + auto routeObject = GenerateRoutes(GlobalConfig.connectionConfig.enableProxy, GlobalConfig.connectionConfig.bypassCN); root.insert("routing", routeObject); // // Process forward proxy diff --git a/src/core/connection/Generation.hpp b/src/core/connection/Generation.hpp index 8a002f03..bdceaa10 100644 --- a/src/core/connection/Generation.hpp +++ b/src/core/connection/Generation.hpp @@ -6,7 +6,7 @@ namespace Qv2ray::core::connection { // Important config generation algorithms. const QStringList vLogLevels = { "none", "debug", "info", "warning", "error" }; - ROUTING GenerateRoutes(bool enableProxy, bool cnProxy, const QString &proxyTag, const QString &directTag = OUTBOUND_TAG_DIRECT); + ROUTING GenerateRoutes(bool enableProxy, bool bypassCN); ROUTERULE GenerateSingleRouteRule(QString str, bool isDomain, QString outboundTag, QString type = "field"); ROUTERULE GenerateSingleRouteRule(QStringList list, bool isDomain, QString outboundTag, QString type = "field"); QJsonObject GenerateDNS(bool withLocalhost, QStringList dnsServers); From 690ee1d250b671702558d6cb1dfac34710322b44 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 12 Mar 2020 11:21:29 +0800 Subject: [PATCH 321/332] fix: fixed complex editor renaming with a QString reference issue --- makespec/BUILDVERSION | 2 +- src/ui/editors/w_RoutesEditor.hpp | 2 +- src/ui/editors/w_RoutesEditor_extra.cpp | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 4a25a85f..1144753c 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4665 \ No newline at end of file +4668 diff --git a/src/ui/editors/w_RoutesEditor.hpp b/src/ui/editors/w_RoutesEditor.hpp index 427ea6a1..620e9655 100644 --- a/src/ui/editors/w_RoutesEditor.hpp +++ b/src/ui/editors/w_RoutesEditor.hpp @@ -103,7 +103,7 @@ class RouteEditor void onConnectionDeleted(QtNodes::Connection const &c); private: - void RenameItemTag(ROUTE_EDIT_MODE mode, const QString &originalTag, QString *newTag); + void RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, QString *newTag); void ShowCurrentRuleDetail(); // QString currentRuleTag; diff --git a/src/ui/editors/w_RoutesEditor_extra.cpp b/src/ui/editors/w_RoutesEditor_extra.cpp index bf3738ec..adba0e6d 100644 --- a/src/ui/editors/w_RoutesEditor_extra.cpp +++ b/src/ui/editors/w_RoutesEditor_extra.cpp @@ -117,8 +117,8 @@ void RouteEditor::AddRule(RuleObject rule) ruleListWidget->addItem(rule.QV2RAY_RULE_TAG); } -// Do not use reference here, we need deep -void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString &originalTag, QString *newTag) +// Do not use reference here, we need deep copy of EVERY QString. +void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, QString *newTag) { switch (mode) { @@ -140,9 +140,10 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString &originalTag node->setData(*newTag); // - rules.insert(*newTag, rules.take(originalTag)); - rules[*newTag].QV2RAY_RULE_TAG = *newTag; - ruleNodes[*newTag] = ruleNodes.take(originalTag); + auto rule = rules.take(originalTag); + rule.QV2RAY_RULE_TAG = *newTag; + rules.insert(*newTag, rule); + ruleNodes.insert(*newTag, ruleNodes.take(originalTag)); // // No other operation needed, but need to rename the one in the // ruleOrder list widget. From fa3e8484ac9cfc173f03f96671a70067503492fe Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 12 Mar 2020 16:27:55 +0800 Subject: [PATCH 322/332] add: added a better JsonEditor --- makespec/BUILDVERSION | 2 +- src/common/JsonHighlighter.cpp | 111 ++++++++++++++++++++++ src/common/JsonHighlighter.hpp | 29 ++++++ src/main.cpp | 1 + src/ui/editors/w_JsonEditor.cpp | 22 ++++- src/ui/editors/w_JsonEditor.hpp | 5 + src/ui/editors/w_JsonEditor.ui | 158 +++++++++++++++++++------------- 7 files changed, 259 insertions(+), 69 deletions(-) create mode 100644 src/common/JsonHighlighter.cpp create mode 100644 src/common/JsonHighlighter.hpp diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 1144753c..707965dd 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4668 +4673 \ No newline at end of file diff --git a/src/common/JsonHighlighter.cpp b/src/common/JsonHighlighter.cpp new file mode 100644 index 00000000..a981d423 --- /dev/null +++ b/src/common/JsonHighlighter.cpp @@ -0,0 +1,111 @@ +#include "JsonHighlighter.hpp" + +#include "core/settings/SettingsBackend.hpp" + +namespace Qv2ray::common +{ + vCoreConfigJsonHighlighter::vCoreConfigJsonHighlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) + { + QTextCharFormat keywordFormat; + keywordFormat.setForeground(GlobalConfig.uiConfig.useDarkTheme ? Qt::GlobalColor::magenta : Qt::darkMagenta); + keywordFormat.setFontWeight(QFont::Bold); + // It's holy a dirty hack here, we'll fully ultilize the vCoreConfig models. + auto keywordPatterns = { "inbounds", + "outbounds", + "routing", + "settings", + "transport", + "request", + "headers", + "ip", + "tag", + "protocol", + "listen", + "rules", + "port", + "reverse", + "dsSettings", + "httpSettings", + "kcpSettings", + "network", + "quicSettings", + "security", + "sockopt", + "tcpSettings", + "tlsSettings", + "wsSettings", + "streamSettings", + "mux", + "sendThrough", + "vnext", + "address", + "users", + "alterId", + "id", + "level", + "path", + "host", + "congestion", + "downlinkCapacity", + "header", + "type", + "mtu", + "readBufferSize", + "tti", + "uplinkCapacity", + "writeBufferSize", + "key", + "mark", + "tcpFastOpen", + "tproxy", + "allowInsecure", + "alpn", + "disableSystemRoot", + "certificates", + "serverName", + "QV2RAY_RULE_ENABLED", + "QV2RAY_RULE_TAG", + "QV2RAY_RULE_USE_BALANCER" }; + int i = 0; + for (const QString &pattern : keywordPatterns) + { + SetRule(QString("00_KeyWord_%1").arg(i), "\"" + pattern + "\"", keywordFormat); + ++i; + } + // + // Values + QTextCharFormat valueFormat, classFormat; + valueFormat.setForeground(Qt::blue); + SetRule("03_Values", "\\btrue\\b|\\bfalse\\b|\\b[0-9]+\\b", valueFormat); + // + // Single Line Comments + QTextCharFormat singleLineCommentFormat; + singleLineCommentFormat.setForeground(Qt::darkGreen); + SetRule("z2_SingleLineComments", "//[^\n]*", singleLineCommentFormat); + } + void vCoreConfigJsonHighlighter::SetRule(const QString &kind, const QString &pattern, QTextCharFormat format) + { + JsonHighlightingRule rule; + rule.name = kind; + rule.pattern = QRegularExpression(pattern); + rule.format = format; + highlightingRules.append(rule); + } + + void vCoreConfigJsonHighlighter::highlightBlock(const QString &text) + { + for (const auto &rule : std::as_const(highlightingRules)) + { + QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); + + while (matchIterator.hasNext()) + { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + } + } + + setCurrentBlockState(0); + } + +} // namespace Qv2ray::common diff --git a/src/common/JsonHighlighter.hpp b/src/common/JsonHighlighter.hpp new file mode 100644 index 00000000..d8eac5c0 --- /dev/null +++ b/src/common/JsonHighlighter.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace Qv2ray::common +{ + struct JsonHighlightingRule + { + QString name; + QRegularExpression pattern; + QTextCharFormat format; + }; + class vCoreConfigJsonHighlighter : public QSyntaxHighlighter + { + Q_OBJECT + public: + vCoreConfigJsonHighlighter(QTextDocument *parent = nullptr); + + private: + QVector highlightingRules; + void SetRule(const QString &kind, const QString &pattern, QTextCharFormat format); + void highlightBlock(const QString &text) override; + }; +} // namespace Qv2ray::common +using namespace Qv2ray::common; diff --git a/src/main.cpp b/src/main.cpp index a14e4633..1a059de0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -317,6 +317,7 @@ int main(int argc, char *argv[]) #ifdef QT_DEBUG // ----------------------------> For debug build... SingleApplication::setApplicationName("qv2ray_debug"); + SingleApplication::setApplicationDisplayName("Qv2ray - " + QObject::tr("Debug version")); #endif if (!qEnvironmentVariableIsSet("QT_DEVICE_PIXEL_RATIO") && // diff --git a/src/ui/editors/w_JsonEditor.cpp b/src/ui/editors/w_JsonEditor.cpp index cf5c414d..e72d8c0c 100644 --- a/src/ui/editors/w_JsonEditor.cpp +++ b/src/ui/editors/w_JsonEditor.cpp @@ -4,8 +4,10 @@ JsonEditor::JsonEditor(QJsonObject rootObject, QWidget *parent) : QDialog(parent) { - QvMessageBusConnect(JsonEditor); setupUi(this); + QvMessageBusConnect(JsonEditor); + highlighter = make_unique(jsonEditor->document()); + // original = rootObject; final = rootObject; QString jsonString = JsonToString(rootObject); @@ -30,7 +32,11 @@ QvMessageBusSlotImpl(JsonEditor) { switch (msg) { - MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl + MBShowDefaultImpl MBHideDefaultImpl MBRetranslateDefaultImpl // + case UPDATE_COLORSCHEME: + { + highlighter.reset(new vCoreConfigJsonHighlighter(jsonEditor->document())); + } } } @@ -83,10 +89,20 @@ void JsonEditor::on_formatJsonBtn_clicked() { BLACK(jsonEditor) jsonEditor->setPlainText(JsonToString(JsonFromString(string))); + LOG(MODULE_UI, "Reloading JSON model") + model.loadJson(QJsonDocument(JsonFromString(string)).toJson()); + jsonTree->setModel(&model); + jsonTree->expandAll(); + jsonTree->resizeColumnToContents(0); } else { RED(jsonEditor) - QvMessageBoxWarn(this, tr("Syntax Errors"), tr("Please fix the JSON errors before continue")); + QvMessageBoxWarn(this, tr("Syntax Errors"), tr("Please fix the JSON errors or remove the comments before continue")); } } + +void JsonEditor::on_removeCommentsBtn_clicked() +{ + jsonEditor->setPlainText(JsonToString(JsonFromString(jsonEditor->toPlainText()))); +} diff --git a/src/ui/editors/w_JsonEditor.hpp b/src/ui/editors/w_JsonEditor.hpp index 01a155fc..53b171d3 100644 --- a/src/ui/editors/w_JsonEditor.hpp +++ b/src/ui/editors/w_JsonEditor.hpp @@ -1,6 +1,7 @@ #pragma once #include "base/Qv2rayBase.hpp" +#include "common/JsonHighlighter.hpp" #include "common/QJsonModel.hpp" #include "ui/messaging/QvMessageBus.hpp" #include "ui_w_JsonEditor.h" @@ -27,8 +28,12 @@ class JsonEditor void on_formatJsonBtn_clicked(); + void on_removeCommentsBtn_clicked(); + private: QJsonModel model; QJsonObject original; QJsonObject final; + // + unique_ptr highlighter; }; diff --git a/src/ui/editors/w_JsonEditor.ui b/src/ui/editors/w_JsonEditor.ui index db0cb289..400e27ba 100644 --- a/src/ui/editors/w_JsonEditor.ui +++ b/src/ui/editors/w_JsonEditor.ui @@ -2,6 +2,9 @@ JsonEditor + + Qt::ApplicationModal + 0 @@ -11,30 +14,106 @@ - Dialog - - - true + JSON Editor true - - + + + + + Qt::Horizontal + + + false + + + + + + + Json Editor + + + + + + + + Monospace + + + + QTextEdit::NoWrap + + + + + + + Format JSON + + + + + + + Remove All Comments + + + + + + + + + + + Json Structure Preview + + + + + + + QAbstractItemView::NoEditTriggers + + + true + + + 15 + + + true + + + true + + + true + + + 132 + + + 152 + + + + + + + + OK - - - - Json Structure Preview - - - - + Qt::Horizontal @@ -44,57 +123,6 @@ - - - - - - - Format JSON - - - - - - - Json Editor - - - - - - - QAbstractScrollArea::AdjustToContents - - - QAbstractItemView::NoEditTriggers - - - true - - - 0 - - - 15 - - - true - - - true - - - true - - - 132 - - - 152 - - - From 88a495c717e1f7818e0c99de882871170130f520 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 12 Mar 2020 16:28:31 +0800 Subject: [PATCH 323/332] fix: some fixes --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b0b99e3..b3b82173 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,6 +146,7 @@ set(QV2RAY_SOURCES src/common/CommandArgs.cpp src/common/HTTPRequestHelper.cpp src/common/LogHighlighter.cpp + src/common/JsonHighlighter.cpp src/common/QJsonModel.cpp src/common/QvHelpers.cpp src/common/QvTranslator.cpp From 85c158cf63eb4450dee2b3eb6644d9ba2537411b Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 12 Mar 2020 21:45:08 +0800 Subject: [PATCH 324/332] fix: fixed wechat-video and other quic protocols being expressed as a net="TCP" obfs, fixed #378 --- makespec/BUILDVERSION | 2 +- src/core/connection/Serialization_vmess.cpp | 175 ++++++++++---------- src/ui/editors/w_JsonEditor.ui | 2 +- src/ui/editors/w_OutboundEditor.cpp | 3 +- 4 files changed, 87 insertions(+), 95 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 707965dd..a44cea40 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4673 \ No newline at end of file +4676 \ No newline at end of file diff --git a/src/core/connection/Serialization_vmess.cpp b/src/core/connection/Serialization_vmess.cpp index 572e1452..6ffb78ce 100644 --- a/src/core/connection/Serialization_vmess.cpp +++ b/src/core/connection/Serialization_vmess.cpp @@ -9,8 +9,7 @@ namespace Qv2ray::core::connection namespace Serialization::vmess { - // From - // https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2) + // From https://github.com/2dust/v2rayN/wiki/分享链接格式说明(ver-2) const QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &server, const QString &alias) { QJsonObject vmessUriRoot; @@ -80,88 +79,72 @@ namespace Qv2ray::core::connection return default; } - try + QStringRef vmessJsonB64(&vmess, 8, vmess.length() - 8); + auto b64Str = vmessJsonB64.toString(); + + if (b64Str.isEmpty()) { - QStringRef vmessJsonB64(&vmess, 8, vmess.length() - 8); - auto b64Str = vmessJsonB64.toString(); - - if (b64Str.isEmpty()) - { - *errMessage = QObject::tr("VMess string should be a valid base64 string"); - return default; - } - - auto vmessString = Base64Decode(b64Str); - auto jsonErr = VerifyJsonString(vmessString); - - if (!jsonErr.isEmpty()) - { - *errMessage = jsonErr; - return default; - } - - auto vmessConf = JsonFromString(vmessString); - - if (vmessConf.isEmpty()) - { - *errMessage = QObject::tr("JSON should not be empty"); - return default; - } - - bool flag = true; - // C is a quick hack... -#define C(k) vmessConf.contains(k) - // id, aid, port and add are mandatory fields of a vmess:// - // link. - flag = flag && C("id") && C("aid") && C("port") && C("add"); - // Stream Settings - auto net = C("net") ? vmessConf["net"].toString() : "tcp"; - - if (net == "http" || net == "ws") - flag = flag && C("host") && C("path"); - else if (net == "domainsocket") - flag = flag && C("path"); - else if (net == "quic") - flag = flag && C("host") && C("type") && C("path"); - -#undef C - // return flag ? 0 : 1; - } - catch (exception *e) - { - *errMessage = e->what(); - LOG(MODULE_IMPORT, "Failed to decode vmess string: " + *errMessage) - delete e; + *errMessage = QObject::tr("VMess string should be a valid base64 string"); return default; } + auto vmessString = Base64Decode(b64Str); + auto jsonErr = VerifyJsonString(vmessString); + + if (!jsonErr.isEmpty()) + { + *errMessage = jsonErr; + return default; + } + + auto vmessConf = JsonFromString(vmessString); + + if (vmessConf.isEmpty()) + { + *errMessage = QObject::tr("JSON should not be empty"); + return default; + } + + bool flag = true; + // C is a quick hack... +#define C(k) (flag = (vmessConf.contains(k) ? true : (*errMessage += (k " does not exist"), false))) + // id, aid, port and add are mandatory fields of a vmess:// + // link. + flag = flag && C("id") && C("aid") && C("port") && C("add"); + // Stream Settings + auto net = vmessConf["net"].toString(); + + if (net == "http" || net == "ws") + flag = flag && C("host") && C("path"); + else if (net == "domainsocket") + flag = flag && C("path"); + else if (net == "quic") + flag = flag && C("host") && C("type") && C("path"); + else + { + LOG(MODULE_CONNECTION, "VMess protocol has an empty `net` option, we'll try to deduce it from the obfs type.") + } + +#undef C + // return flag ? 0 : 1; + // -------------------------------------------------------------------------------------- CONFIGROOT root; - auto b64String = QStringRef(&vmess, 8, vmess.length() - 8).toString(); - auto vmessConf = JsonFromString(Base64Decode(b64String)); - // - QString ps, add, id, net, type, host, path, tls; + QString ps, add, id, /*net,*/ type, host, path, tls; int port, aid; // - // key = key in JSON and the variable name. - // values = Candidate variable list, if not match, the first one is - // used as default. - // [[val.size() <= 1]] is used when only the default value - // exists. - /// - // - It can be empty, if so, if the key is not in - // the JSON, or the value is empty, it'll report an error. + // __vmess_checker__func(key, values) // - // - Else if it contains one thing. if the key is not in - // the JSON, or the value is empty, it'll use that one. + // - Key = Key in JSON and the variable name. + // - Values = Candidate variable list, if not match, the first one is used as default. // - // - Else if it contains many things, when the key IS in - // the JSON but not in those THINGS, it'll use the first - // one in the THINGS + // - [[val.size() <= 1]] is used when only the default value exists. // - // - Else, it'll use the value found from the JSON object. + // - It can be empty, if so, if the key is not in the JSON, or the value is empty, report an error. + // - Else if it contains one thing. if the key is not in the JSON, or the value is empty, use that one. + // - Else if it contains many things, when the key IS in the JSON but not within the THINGS, use the first in the THINGS + // - Else, use the JSON value // -#define empty_arg #define __vmess_checker__func(key, values) \ { \ auto val = QStringList() values; \ @@ -188,30 +171,40 @@ namespace Qv2ray::core::connection // // Get Alias (AKA ps) from address and port. { - __vmess_checker__func(ps, << vmessConf["add"].toVariant().toString() + ":" + vmessConf["port"].toVariant().toString()) // - __vmess_checker__func(add, empty_arg) // - __vmess_checker__func(id, empty_arg) // - __vmess_checker__func(net, << "tcp" // - << "http" // - << "h2" // - << "ws" // - << "kcp" // - << "domainsocket" // - << "quic") // - __vmess_checker__func(type, << "none" // - << "http" // - << "srtp" // - << "utp" // - << "wechat-video") // - __vmess_checker__func(path, << "") // - __vmess_checker__func(host, << "") // - __vmess_checker__func(tls, << "") // + __vmess_checker__func(ps, << vmessConf["add"].toVariant().toString() + ":" + vmessConf["port"].toVariant().toString()); // + __vmess_checker__func(add, nothing); // + __vmess_checker__func(id, nothing); // + __vmess_checker__func(type, << "none" // + << "http" // + << "srtp" // + << "utp" // + << "wechat-video"); // + // + /*Deduce net type from obfs type*/ // + if (QStringList{ "srtp", "utp", "wechat-video" }.contains(type)) // + { // + if (net != "quic") // + { // + LOG(MODULE_CONNECTION, "Reset net settings from " + net + " to quic") // + net = "quic"; // + } // + } // + __vmess_checker__func(net, << "tcp" // + << "http" // + << "h2" // + << "ws" // + << "kcp" // + << "domainsocket" // + << "quic"); // + __vmess_checker__func(path, << ""); // + __vmess_checker__func(host, << ""); // + __vmess_checker__func(tls, << ""); // } // port = vmessConf["port"].toVariant().toInt(); aid = vmessConf["aid"].toVariant().toInt(); - // Apply the settings. // + // Apply the settings. // User VMessServerObject::UserObject user; user.id = id; diff --git a/src/ui/editors/w_JsonEditor.ui b/src/ui/editors/w_JsonEditor.ui index 400e27ba..edfc93ef 100644 --- a/src/ui/editors/w_JsonEditor.ui +++ b/src/ui/editors/w_JsonEditor.ui @@ -28,7 +28,7 @@ false - + diff --git a/src/ui/editors/w_OutboundEditor.cpp b/src/ui/editors/w_OutboundEditor.cpp index 995ae79f..792e6a06 100644 --- a/src/ui/editors/w_OutboundEditor.cpp +++ b/src/ui/editors/w_OutboundEditor.cpp @@ -1,5 +1,4 @@ -#include -#include "w_OutboundEditor.hpp" +#include "w_OutboundEditor.hpp" #include "core/connection/Generation.hpp" #include "ui/editors/w_JsonEditor.hpp" From 9e57f7b767512bf9038fe6b63e59a774e649ac1e Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Tue, 10 Mar 2020 21:23:40 +0800 Subject: [PATCH 325/332] [stub] basic framework for darkmode detection --- CMakeLists.txt | 4 +++- src/components/darkmode/DarkmodeDetector.hpp | 7 +++++++ src/components/darkmode/DarkmodeDetector_linux.cpp | 13 +++++++++++++ src/components/darkmode/DarkmodeDetector_mac.cpp | 13 +++++++++++++ src/components/darkmode/DarkmodeDetector_win.cpp | 13 +++++++++++++ 5 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/components/darkmode/DarkmodeDetector.hpp create mode 100644 src/components/darkmode/DarkmodeDetector_linux.cpp create mode 100644 src/components/darkmode/DarkmodeDetector_mac.cpp create mode 100644 src/components/darkmode/DarkmodeDetector_win.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b3b82173..de276946 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,6 +161,9 @@ set(QV2RAY_SOURCES src/components/proxy/QvProxyConfigurator.cpp src/components/speedchart/speedplotview.cpp src/components/speedchart/speedwidget.cpp + src/components/darkmode/DarkmodeDetector_linux.cpp + src/components/darkmode/DarkmodeDetector_win.cpp + src/components/darkmode/DarkmodeDetector_mac.cpp src/core/connection/ConnectionIO.cpp src/core/connection/Generation.cpp src/core/connection/Serialization.cpp @@ -208,7 +211,6 @@ set(QV2RAY_SOURCES src/ui/w_MainWindow.ui src/ui/w_PreferencesWindow.ui src/ui/w_ScreenShot_Core.ui - assets/qv2ray.rc ) diff --git a/src/components/darkmode/DarkmodeDetector.hpp b/src/components/darkmode/DarkmodeDetector.hpp new file mode 100644 index 00000000..ad16b7bf --- /dev/null +++ b/src/components/darkmode/DarkmodeDetector.hpp @@ -0,0 +1,7 @@ +#pragma once +#include + +namespace Qv2ray::components::darkmode +{ + bool detectDarkmode(); +} diff --git a/src/components/darkmode/DarkmodeDetector_linux.cpp b/src/components/darkmode/DarkmodeDetector_linux.cpp new file mode 100644 index 00000000..d26f6a39 --- /dev/null +++ b/src/components/darkmode/DarkmodeDetector_linux.cpp @@ -0,0 +1,13 @@ +#include "DarkmodeDetector.hpp" +#ifdef Q_OS_LINUX + +namespace Qv2ray::components::darkmode +{ + bool detectDarkmode() + { + // TODO: expand this stub + return false; + } +} // namespace Qv2ray::components::darkmode + +#endif diff --git a/src/components/darkmode/DarkmodeDetector_mac.cpp b/src/components/darkmode/DarkmodeDetector_mac.cpp new file mode 100644 index 00000000..d5d6a4ce --- /dev/null +++ b/src/components/darkmode/DarkmodeDetector_mac.cpp @@ -0,0 +1,13 @@ +#include "DarkmodeDetector.hpp" +#ifdef Q_OS_DARWIN + +namespace Qv2ray::components::darkmode +{ + bool detectDarkmode() + { + // TODO: expand this stub + return false; + } +} // namespace Qv2ray::components::darkmode + +#endif diff --git a/src/components/darkmode/DarkmodeDetector_win.cpp b/src/components/darkmode/DarkmodeDetector_win.cpp new file mode 100644 index 00000000..0b0f29ab --- /dev/null +++ b/src/components/darkmode/DarkmodeDetector_win.cpp @@ -0,0 +1,13 @@ +#include "DarkmodeDetector.hpp" +#ifdef Q_OS_WIN32 + +namespace Qv2ray::components::darkmode +{ + bool detectDarkmode() + { + // TODO: expand this stub + return false; + } +} // namespace Qv2ray::components::darkmode + +#endif From 1fafee72b6baf54ad0177dfeb9e5f27d2f390f19 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Tue, 10 Mar 2020 21:34:33 +0800 Subject: [PATCH 326/332] [impl] linux implementation of darkmode detector --- src/components/darkmode/DarkmodeDetector_linux.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/darkmode/DarkmodeDetector_linux.cpp b/src/components/darkmode/DarkmodeDetector_linux.cpp index d26f6a39..9445ef96 100644 --- a/src/components/darkmode/DarkmodeDetector_linux.cpp +++ b/src/components/darkmode/DarkmodeDetector_linux.cpp @@ -1,12 +1,19 @@ #include "DarkmodeDetector.hpp" #ifdef Q_OS_LINUX + #include + #include namespace Qv2ray::components::darkmode { + // Referenced from github.com/keepassxreboot/keepassxc. Licensed under GPL2/3. + // Copyright (C) 2020 KeePassXC Team bool detectDarkmode() { - // TODO: expand this stub - return false; + if (!qApp || !qApp->style()) + { + return false; + } + return qApp->style()->standardPalette().color(QPalette::Window).toHsl().lightness() < 110; } } // namespace Qv2ray::components::darkmode From 692d9229c7812e5a25d367ce9bdc102d0ca60db2 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Tue, 10 Mar 2020 21:38:34 +0800 Subject: [PATCH 327/332] [impl] windows implementation of darkmode detector --- src/components/darkmode/DarkmodeDetector_win.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/darkmode/DarkmodeDetector_win.cpp b/src/components/darkmode/DarkmodeDetector_win.cpp index 0b0f29ab..ecfa6838 100644 --- a/src/components/darkmode/DarkmodeDetector_win.cpp +++ b/src/components/darkmode/DarkmodeDetector_win.cpp @@ -1,12 +1,15 @@ #include "DarkmodeDetector.hpp" #ifdef Q_OS_WIN32 + #include namespace Qv2ray::components::darkmode { + // Referenced from github.com/keepassxreboot/keepassxc. Licensed under GPL2/3. + // Copyright (C) 2020 KeePassXC Team bool detectDarkmode() { - // TODO: expand this stub - return false; + QSettings settings(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)", QSettings::NativeFormat); + return settings.value("AppsUseLightTheme", 1).toInt() == 0; } } // namespace Qv2ray::components::darkmode From cd3e56b65ccbea26ff92647c284c10c1d7d6fd7c Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 12 Mar 2020 22:14:14 +0800 Subject: [PATCH 328/332] change: merged linux, win, mac cpp to one DarkmodeDetector --- CMakeLists.txt | 4 +--- makespec/BUILDVERSION | 2 +- ...etector_linux.cpp => DarkmodeDetector.cpp} | 22 +++++++++++++++---- src/components/darkmode/DarkmodeDetector.hpp | 3 +-- .../darkmode/DarkmodeDetector_mac.cpp | 13 ----------- .../darkmode/DarkmodeDetector_win.cpp | 16 -------------- 6 files changed, 21 insertions(+), 39 deletions(-) rename src/components/darkmode/{DarkmodeDetector_linux.cpp => DarkmodeDetector.cpp} (53%) delete mode 100644 src/components/darkmode/DarkmodeDetector_mac.cpp delete mode 100644 src/components/darkmode/DarkmodeDetector_win.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index de276946..82ed892e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,9 +161,7 @@ set(QV2RAY_SOURCES src/components/proxy/QvProxyConfigurator.cpp src/components/speedchart/speedplotview.cpp src/components/speedchart/speedwidget.cpp - src/components/darkmode/DarkmodeDetector_linux.cpp - src/components/darkmode/DarkmodeDetector_win.cpp - src/components/darkmode/DarkmodeDetector_mac.cpp + src/components/darkmode/DarkmodeDetector.cpp src/core/connection/ConnectionIO.cpp src/core/connection/Generation.cpp src/core/connection/Serialization.cpp diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index a44cea40..5d3c1d34 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4676 \ No newline at end of file +4680 \ No newline at end of file diff --git a/src/components/darkmode/DarkmodeDetector_linux.cpp b/src/components/darkmode/DarkmodeDetector.cpp similarity index 53% rename from src/components/darkmode/DarkmodeDetector_linux.cpp rename to src/components/darkmode/DarkmodeDetector.cpp index 9445ef96..33e7c089 100644 --- a/src/components/darkmode/DarkmodeDetector_linux.cpp +++ b/src/components/darkmode/DarkmodeDetector.cpp @@ -1,20 +1,34 @@ #include "DarkmodeDetector.hpp" + +#include #ifdef Q_OS_LINUX #include #include +#elif defined(Q_OS_WIN32) + #include +#else +// TODO: macOS headers. +#endif namespace Qv2ray::components::darkmode { // Referenced from github.com/keepassxreboot/keepassxc. Licensed under GPL2/3. // Copyright (C) 2020 KeePassXC Team - bool detectDarkmode() + bool isDarkMode() { +#if defined(Q_OS_LINUX) if (!qApp || !qApp->style()) { return false; } return qApp->style()->standardPalette().color(QPalette::Window).toHsl().lightness() < 110; - } -} // namespace Qv2ray::components::darkmode - +#elif defined(Q_OS_WIN32) + QSettings settings(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)", QSettings::NativeFormat); + return settings.value("AppsUseLightTheme", 1).toInt() == 0; +#elif defined(Q_OS_DARWIN) + // TODO: expand this stub + return false; #endif + } + +} // namespace Qv2ray::components::darkmode diff --git a/src/components/darkmode/DarkmodeDetector.hpp b/src/components/darkmode/DarkmodeDetector.hpp index ad16b7bf..0c49bc23 100644 --- a/src/components/darkmode/DarkmodeDetector.hpp +++ b/src/components/darkmode/DarkmodeDetector.hpp @@ -1,7 +1,6 @@ #pragma once -#include namespace Qv2ray::components::darkmode { - bool detectDarkmode(); + bool isDarkMode(); } diff --git a/src/components/darkmode/DarkmodeDetector_mac.cpp b/src/components/darkmode/DarkmodeDetector_mac.cpp deleted file mode 100644 index d5d6a4ce..00000000 --- a/src/components/darkmode/DarkmodeDetector_mac.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "DarkmodeDetector.hpp" -#ifdef Q_OS_DARWIN - -namespace Qv2ray::components::darkmode -{ - bool detectDarkmode() - { - // TODO: expand this stub - return false; - } -} // namespace Qv2ray::components::darkmode - -#endif diff --git a/src/components/darkmode/DarkmodeDetector_win.cpp b/src/components/darkmode/DarkmodeDetector_win.cpp deleted file mode 100644 index ecfa6838..00000000 --- a/src/components/darkmode/DarkmodeDetector_win.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "DarkmodeDetector.hpp" -#ifdef Q_OS_WIN32 - #include - -namespace Qv2ray::components::darkmode -{ - // Referenced from github.com/keepassxreboot/keepassxc. Licensed under GPL2/3. - // Copyright (C) 2020 KeePassXC Team - bool detectDarkmode() - { - QSettings settings(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)", QSettings::NativeFormat); - return settings.value("AppsUseLightTheme", 1).toInt() == 0; - } -} // namespace Qv2ray::components::darkmode - -#endif From ba32111169169d761808c3c4b3365ad189b47193 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 12 Mar 2020 22:48:33 +0800 Subject: [PATCH 329/332] refactor: some minor refactors to the main.cpp --- makespec/BUILDVERSION | 2 +- src/core/settings/SettingsBackend.cpp | 97 +++++++++++++ src/core/settings/SettingsBackend.hpp | 1 + src/main.cpp | 188 +++++++------------------- 4 files changed, 146 insertions(+), 142 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index a44cea40..5d3c1d34 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4676 \ No newline at end of file +4680 \ No newline at end of file diff --git a/src/core/settings/SettingsBackend.cpp b/src/core/settings/SettingsBackend.cpp index be7f98fd..0d61488b 100644 --- a/src/core/settings/SettingsBackend.cpp +++ b/src/core/settings/SettingsBackend.cpp @@ -20,6 +20,103 @@ namespace Qv2ray::core::config Qv2rayConfigPath += "/"; } } + + bool CheckSettingsPathAvailability(const QString &_path, bool checkExistingConfig) + { + auto path = _path; + if (!path.endsWith("/")) + { + path.append("/"); + } + // Does not exist. + if (!QDir(path).exists()) + return false; + + // A temp file used to test file permissions in that folder. + QFile testFile(path + ".qv2ray_file_write_test_file" + QSTRN(QTime::currentTime().msecsSinceStartOfDay())); + bool opened = testFile.open(QFile::OpenModeFlag::ReadWrite); + + if (!opened) + { + LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.") + LOG(MODULE_SETTINGS, "---> Cannot create a new file or open a file for writing.") + return false; + } + else + { + testFile.write("Qv2ray test file, feel free to remove."); + testFile.flush(); + testFile.close(); + bool removed = testFile.remove(); + + if (!removed) + { + // This is rare, as we can create a file but failed to remove it. + LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.") + LOG(MODULE_SETTINGS, "---> Cannot remove a file.") + return false; + } + } + + if (checkExistingConfig) + { + // Check if an existing config is found. + QFile configFile(path + "Qv2ray.conf"); + + // No such config file. + if (!configFile.exists()) + return false; + + bool opened2 = configFile.open(QIODevice::ReadWrite); + + try + { + if (opened2) + { + // Verify if the config can be loaded. + // Failed to parse if we changed the file structure... + // Original: + // -- auto conf = + // StructFromJsonString(configFile.readAll()); + // + // Verify JSON file format. (only) because this file version may + // not be upgraded and may contain unsupported structure. + auto err = VerifyJsonString(StringFromFile(&configFile)); + + if (!err.isEmpty()) + { + LOG(MODULE_INIT, "Json parse returns: " + err) + return false; + } + else + { + // If the file format is valid. + auto conf = JsonFromString(StringFromFile(&configFile)); + LOG(MODULE_SETTINGS, + "Path: " + path + " contains a config file, in version " + conf["config_version"].toVariant().toString()) + configFile.close(); + return true; + } + } + else + { + LOG(MODULE_SETTINGS, "File: " + configFile.fileName() + " cannot be opened!") + return false; + } + } + catch (...) + { + LOG(MODULE_SETTINGS, "Exception raised when checking config: " + configFile.fileName()) + // LOG(INIT, e->what()) + QvMessageBoxWarn(nullptr, QObject::tr("Warning"), + QObject::tr("Qv2ray cannot load the config file from here:") + NEWLINE + configFile.fileName()); + return false; + } + } + else + return true; + } + } // namespace Qv2ray::core::config using namespace Qv2ray::core::config; diff --git a/src/core/settings/SettingsBackend.hpp b/src/core/settings/SettingsBackend.hpp index 6ea855b8..2c61bfaf 100644 --- a/src/core/settings/SettingsBackend.hpp +++ b/src/core/settings/SettingsBackend.hpp @@ -4,6 +4,7 @@ namespace Qv2ray::core::config { void SaveGlobalConfig(const Qv2rayConfig &conf); void SetConfigDirPath(const QString &path); + bool CheckSettingsPathAvailability(const QString &_path, bool checkExistingConfig); } // namespace Qv2ray::core::config using namespace Qv2ray::core; diff --git a/src/main.cpp b/src/main.cpp index 1a059de0..06d3ad3b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,102 +28,6 @@ void signalHandler(int signum) qApp->exit(-99); } -bool verifyConfigAvailability(const QString &_path, bool checkExistingConfig) -{ - auto path = _path; - if (!path.endsWith("/")) - { - path.append("/"); - } - // Does not exist. - if (!QDir(path).exists()) - return false; - - // A temp file used to test file permissions in that folder. - QFile testFile(path + ".qv2ray_file_write_test_file" + QSTRN(QTime::currentTime().msecsSinceStartOfDay())); - bool opened = testFile.open(QFile::OpenModeFlag::ReadWrite); - - if (!opened) - { - LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.") - LOG(MODULE_INIT, "---> Cannot create a new file or open a file for writing.") - return false; - } - else - { - testFile.write("Qv2ray test file, feel free to remove."); - testFile.flush(); - testFile.close(); - bool removed = testFile.remove(); - - if (!removed) - { - // This is rare, as we can create a file but failed to remove it. - LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.") - LOG(MODULE_INIT, "---> Cannot remove a file.") - return false; - } - } - - if (checkExistingConfig) - { - // Check if an existing config is found. - QFile configFile(path + "Qv2ray.conf"); - - // No such config file. - if (!configFile.exists()) - return false; - - bool opened2 = configFile.open(QIODevice::ReadWrite); - - try - { - if (opened2) - { - // Verify if the config can be loaded. - // Failed to parse if we changed the file structure... - // Original: - // -- auto conf = - // StructFromJsonString(configFile.readAll()); - // - // Verify JSON file format. (only) because this file version may - // not be upgraded and may contain unsupported structure. - auto err = VerifyJsonString(StringFromFile(&configFile)); - - if (!err.isEmpty()) - { - LOG(MODULE_INIT, "Json parse returns: " + err) - return false; - } - else - { - // If the file format is valid. - auto conf = JsonFromString(StringFromFile(&configFile)); - LOG(MODULE_SETTINGS, - "Path: " + path + " contains a config file, in version " + conf["config_version"].toVariant().toString()) - configFile.close(); - return true; - } - } - else - { - LOG(MODULE_SETTINGS, "File: " + configFile.fileName() + " cannot be opened!") - return false; - } - } - catch (...) - { - LOG(MODULE_SETTINGS, "Exception raised when checking config: " + configFile.fileName()) - // LOG(INIT, e->what()) - QvMessageBoxWarn(nullptr, QObject::tr("Warning"), - QObject::tr("Qv2ray cannot load the config file from here:") + NEWLINE + configFile.fileName()); - return false; - } - } - else - return true; -} - bool initialiseQv2ray() { LOG(MODULE_INIT, "Application exec path: " + QApplication::applicationDirPath()) @@ -153,8 +57,8 @@ bool initialiseQv2ray() { // Verify the config path, check if the config file exists and in the // correct JSON format. True means we check for config existence as - // well. --|HERE | - bool isValidConfigPath = verifyConfigAvailability(path, true); + // well. ----------------------------------------------|HERE| + bool isValidConfigPath = CheckSettingsPathAvailability(path, true); // If we already found a valid config file. just simply load it... if (hasExistingConfig) @@ -172,7 +76,6 @@ bool initialiseQv2ray() } } - // If there's no existing config. if (hasExistingConfig) { // Use the config path found by the checks above @@ -181,6 +84,7 @@ bool initialiseQv2ray() } else { + // If there's no existing config. // // Create new config at these dirs, these are default values for each // platform. @@ -190,53 +94,55 @@ bool initialiseQv2ray() configPath = configQv2ray; #endif bool mkpathResult = QDir().mkpath(configPath); - + bool hasPossibleNewLocation = mkpathResult && CheckSettingsPathAvailability(configPath, false); // Check if the dirs are write-able - if (mkpathResult && verifyConfigAvailability(configPath, false)) + if (!hasPossibleNewLocation) { - // Found a valid config dir, with write permission, but assume no - // config is located in it. - LOG(MODULE_INIT, "Set " + configPath + " as the config path.") - SetConfigDirPath(configPath); - - if (QFile::exists(QV2RAY_CONFIG_FILE)) - { - // As we already tried to load config from every possible dir. - // This condition branch (!hasExistingConfig check) holds the - // fact that current config dir, should NOT contain any valid - // file (at least in the same name) It usually means that - // QV2RAY_CONFIG_FILE here is corrupted, in JSON format. - // Otherwise Qv2ray would have loaded this config already - // instead of notifying to create a new config in this folder. - LOG(MODULE_INIT, "This should not occur: Qv2ray config exists but failed to load.") - QvMessageBoxWarn(nullptr, QObject::tr("Failed to initialise Qv2ray"), - QObject::tr("Failed to determine the location of config file.") + NEWLINE + - QObject::tr("Qv2ray will now exit.") + NEWLINE + QObject::tr("Please report if you think it's a bug.")); - return false; - } - - Qv2rayConfig conf; - conf.kernelConfig.KernelPath(QString(QV2RAY_DEFAULT_VCORE_PATH)); - conf.kernelConfig.AssetsPath(QString(QV2RAY_DEFAULT_VASSETS_PATH)); - conf.logLevel = 3; // - // Save initial config. - SaveGlobalConfig(conf); - LOG(MODULE_INIT, "Created initial config file.") - } - else - { // None of the path above can be used as a dir for storing config. // Even the last folder failed to pass the check. LOG(MODULE_INIT, "FATAL") LOG(MODULE_INIT, " ---> CANNOT find a proper place to store Qv2ray config files.") - QString searchPath = configFilePaths.join(NEWLINE); QvMessageBoxWarn(nullptr, QObject::tr("Cannot Start Qv2ray"), QObject::tr("Cannot find a place to store config files.") + NEWLINE + - QObject::tr("Qv2ray has searched these paths below:") + NEWLINE + NEWLINE + searchPath + NEWLINE + + QObject::tr("Qv2ray has searched these paths below:") + NEWLINE + NEWLINE + // + configFilePaths.join(NEWLINE) + NEWLINE + + QObject::tr("It usually means you don't have the write permission to all of those locations.") + QObject::tr("Qv2ray will now exit.")); return false; } + // Found a valid config dir, with write permission, but assume no config is located in it. + LOG(MODULE_INIT, "Set " + configPath + " as the config path.") + SetConfigDirPath(configPath); + + if (QFile::exists(QV2RAY_CONFIG_FILE)) + { + // As we already tried to load config from every possible dir. + // + // This condition branch (!hasExistingConfig check) holds the fact that current config dir, + // should NOT contain any valid file (at least in the same name) + // + // It usually means that QV2RAY_CONFIG_FILE here has a corrupted JSON format. + // + // Otherwise Qv2ray would have loaded this config already instead of notifying to create a new config in this folder. + // + LOG(MODULE_INIT, "This should not occur: Qv2ray config exists but failed to load.") + QvMessageBoxWarn(nullptr, QObject::tr("Failed to initialise Qv2ray"), + QObject::tr("Failed to determine the location of config file:") + NEWLINE + + QObject::tr("Qv2ray has found a config file, but it failed to be loaded due to some errors.") + NEWLINE + + QObject::tr("A workaround is to remove the this file and restart Qv2ray:") + NEWLINE + QV2RAY_CONFIG_FILE + + QObject::tr("Qv2ray will now exit.") + NEWLINE + QObject::tr("Please report if you think it's a bug.")); + return false; + } + + Qv2rayConfig conf; + conf.kernelConfig.KernelPath(QString(QV2RAY_DEFAULT_VCORE_PATH)); + conf.kernelConfig.AssetsPath(QString(QV2RAY_DEFAULT_VASSETS_PATH)); + conf.logLevel = 2; + // + // Save initial config. + SaveGlobalConfig(conf); + LOG(MODULE_INIT, "Created initial config file.") } if (!QDir(QV2RAY_GENERATED_DIR).exists()) @@ -480,8 +386,8 @@ int main(int argc, char *argv[]) darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218)); darkPalette.setColor(QPalette::HighlightedText, Qt::black); darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, disabledColor); - qApp->setPalette(darkPalette); - qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }"); + _qApp.setPalette(darkPalette); + _qApp.setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }"); } #else @@ -491,7 +397,7 @@ int main(int argc, char *argv[]) if (themes.contains(confObject.uiConfig.theme)) { - _qApp.setStyle(confObject.uiConfig.theme); + qApp->setStyle(confObject.uiConfig.theme); LOG(MODULE_INIT + " " + MODULE_UI, "Setting Qv2ray UI themes: " + confObject.uiConfig.theme) } @@ -504,6 +410,10 @@ int main(int argc, char *argv[]) //_qApp.setAttribute(Qt::AA_DontUseNativeMenuBar); // Initialise Connection Handler ConnectionManager = new QvConfigHandler(); + // Handler for session logout, shutdown, etc. + // Will not block. + QGuiApplication::setFallbackSessionManagementEnabled(false); + QObject::connect(&_qApp, &QGuiApplication::commitDataRequest, [] { LOG(MODULE_INIT, "Quit triggered by session manager.") }); // Show MainWindow MainWindow w; QObject::connect(&_qApp, &SingleApplication::instanceStarted, [&]() { @@ -512,10 +422,6 @@ int main(int argc, char *argv[]) w.raise(); w.activateWindow(); }); - // Handler for session logout, shutdown, etc. - // Will not block. - QGuiApplication::setFallbackSessionManagementEnabled(false); - QObject::connect(&_qApp, &QGuiApplication::commitDataRequest, [] { LOG(MODULE_INIT, "Quit triggered by session manager.") }); #ifndef Q_OS_WIN signal(SIGUSR1, [](int) { emit MainWindow::mwInstance->StartConnection(); }); signal(SIGUSR2, [](int) { emit MainWindow::mwInstance->StopConnection(); }); From b125eb41c3f8db2d34cac8f86c01589fc6d35f9b Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 12 Mar 2020 23:26:21 +0800 Subject: [PATCH 330/332] fix: fixed a comment removal issue --- libs/puresource | 2 +- makespec/BUILDVERSION | 2 +- src/common/QvHelpers.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/puresource b/libs/puresource index 4af54ebc..bd4f9335 160000 --- a/libs/puresource +++ b/libs/puresource @@ -1 +1 @@ -Subproject commit 4af54ebc77fed903781e9224303bdec646a7c9be +Subproject commit bd4f9335bb89e7b1199282c685d49dd5ae4ce1fa diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 5d3c1d34..607f57d7 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4680 \ No newline at end of file +4681 \ No newline at end of file diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 9fd2fa1f..4683d52d 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -113,8 +113,8 @@ namespace Qv2ray::common QJsonObject JsonFromString(const QString &string) { - auto removeComment = RemoveComment(string); - if (removeComment != string) + auto removeComment = RemoveComment(string.trimmed()).trimmed(); + if (removeComment != string.trimmed()) { LOG(MODULE_FILEIO, "Some comments have been removed from the json.") } From d8db105ee87639e63acd685fd4452cbf4a24058e Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 12 Mar 2020 23:44:24 +0800 Subject: [PATCH 331/332] add: let blurred QR adapt darkModeSettings --- src/common/QvHelpers.cpp | 4 ++-- src/common/QvHelpers.hpp | 2 +- src/ui/widgets/ConnectionInfoWidget.cpp | 13 +++++++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/common/QvHelpers.cpp b/src/common/QvHelpers.cpp index 4683d52d..31d409d9 100644 --- a/src/common/QvHelpers.cpp +++ b/src/common/QvHelpers.cpp @@ -246,12 +246,12 @@ namespace Qv2ray::common return view.grab(); } - QPixmap LightenImage(const QPixmap &pixmap, const qreal factor) + QPixmap ColorizeImage(const QPixmap &pixmap, const QColor &color, const qreal factor) { QGraphicsView view; QGraphicsScene scene; QGraphicsColorizeEffect pColor; - pColor.setColor(QColor(Qt::white)); + pColor.setColor(color); pColor.setStrength(factor); // view.setScene(&scene); diff --git a/src/common/QvHelpers.hpp b/src/common/QvHelpers.hpp index a13d75b5..100fb86b 100644 --- a/src/common/QvHelpers.hpp +++ b/src/common/QvHelpers.hpp @@ -39,7 +39,7 @@ namespace Qv2ray::common void DeducePossibleFileName(const QString &baseDir, QString *fileName, const QString &extension); // QPixmap BlurImage(const QPixmap &pixmap, const double rad = 50); - QPixmap LightenImage(const QPixmap &pixmap, const qreal factor); + QPixmap ColorizeImage(const QPixmap &pixmap, const QColor &color, const qreal factor); // This function cannot be marked as inline. QString RemoveInvalidFileName(const QString &fileName); bool IsValidFileName(const QString &fileName); diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index f55c73b4..bfa6be73 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -27,7 +27,12 @@ void ConnectionInfoWidget::UpdateColorScheme() editJsonBtn->setIcon(QICON_R("json.png")); shareLinkTxt->setStyleSheet("border-bottom: 1px solid gray; border-radius: 0px; padding: 2px; background-color: " + this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); - + // + auto isDarkTheme = GlobalConfig.uiConfig.useDarkTheme; + qrPixmapBlured = BlurImage(ColorizeImage(qrPixmap, isDarkTheme ? QColor(Qt::black) : QColor(Qt::white), 0.7), 35); + // + qrLabel->setPixmap(IsComplexConfig(connectionId) ? QPixmap(":/assets/icons/qv2ray.ico") : (isRealPixmapShown ? qrPixmap : qrPixmapBlured)); + // connectBtn->setIcon(ConnectionManager->IsConnected(connectionId) ? QICON_R("stop.png") : QICON_R("connect.png")); } @@ -79,10 +84,10 @@ void ConnectionInfoWidget::ShowDetails(const tuple &_iden conf.imageSize = QSize(400, 400); conf.errorCorrectionLevel = QZXing::EncodeErrorCorrectionLevel_M; QZXing qzx; - auto img = qzx.encodeData(shareLink, conf); + qrPixmap = QPixmap::fromImage(qzx.encodeData(shareLink, conf)); // - qrPixmap = QPixmap::fromImage(img); - qrPixmapBlured = BlurImage(LightenImage(QPixmap::fromImage(img), 0.75), 20); + auto isDarkTheme = GlobalConfig.uiConfig.useDarkTheme; + qrPixmapBlured = BlurImage(ColorizeImage(qrPixmap, isDarkTheme ? QColor(Qt::black) : QColor(Qt::white), 0.7), 35); // isRealPixmapShown = false; qrLabel->setPixmap(IsComplexConfig(connectionId) ? QPixmap(":/assets/icons/qv2ray.ico") : qrPixmapBlured); From 737a7ffd3802c34cf48fe95675782a3a80eb052a Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Fri, 13 Mar 2020 13:51:37 +0800 Subject: [PATCH 332/332] Updating Translation (#412) * updating translations * ja_JP: translating some items * ja_JP: finishing * fix: removed translations line numbers from the TS files * add headers to sources * updating translations Co-authored-by: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Co-authored-by: Guobang Bi <373318510@qq.com> --- CMakeLists.txt | 56 +- translations/en_US.ts | 894 ++++++++--------- translations/ja_JP.ts | 2157 +++++++++++++++++++++++++---------------- translations/ru_RU.ts | 1423 ++++++++++++++++++--------- translations/zh_CN.ts | 1515 +++++++++++++++++++---------- 5 files changed, 3743 insertions(+), 2302 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82ed892e..09674fb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,6 +209,60 @@ set(QV2RAY_SOURCES src/ui/w_MainWindow.ui src/ui/w_PreferencesWindow.ui src/ui/w_ScreenShot_Core.ui + # headers + src/base/JsonHelpers.hpp + src/base/models/CoreObjectModels.hpp + src/base/models/QvConfigIdentifier.hpp + src/base/models/QvRuntimeConfig.hpp + src/base/models/QvSafeType.hpp + src/base/models/QvSettingsObject.hpp + src/base/models/QvStartupConfig.hpp + src/base/Qv2rayBase.hpp + src/base/Qv2rayFeatures.hpp + src/base/Qv2rayLog.hpp + src/common/CommandArgs.hpp + src/common/HTTPRequestHelper.hpp + src/common/JsonHighlighter.hpp + src/common/LogHighlighter.hpp + src/common/QJsonModel.hpp + src/common/QvHelpers.hpp + src/common/QvTranslator.hpp + src/components/autolaunch/QvAutoLaunch.hpp + src/components/darkmode/DarkmodeDetector.hpp + src/components/geosite/QvGeositeReader.hpp + src/components/icmping/win/ICMPPinger.hpp + src/components/pac/QvPACHandler.hpp + src/components/plugins/toolbar/QvToolbar.hpp + src/components/proxy/QvProxyConfigurator.hpp + src/components/speedchart/speedplotview.hpp + src/components/speedchart/speedwidget.hpp + src/core/connection/ConnectionIO.hpp + src/core/connection/Generation.hpp + src/core/connection/Serialization.hpp + src/core/CoreSafeTypes.hpp + src/core/CoreUtils.hpp + src/core/handler/ConfigHandler.hpp + src/core/kernel/APIBackend.hpp + src/core/kernel/KernelInteractions.hpp + src/core/settings/SettingsBackend.hpp + src/core/tcping/QvTCPing.hpp + src/ui/editors/w_InboundEditor.hpp + src/ui/editors/w_JsonEditor.hpp + src/ui/editors/w_OutboundEditor.hpp + src/ui/editors/w_RoutesEditor.hpp + src/ui/messaging/QvMessageBus.hpp + src/ui/models/InboundNodeModel.hpp + src/ui/models/NodeModelsBase.hpp + src/ui/models/OutboundNodeModel.hpp + src/ui/models/RuleNodeModel.hpp + src/ui/widgets/ConnectionInfoWidget.hpp + src/ui/widgets/ConnectionItemWidget.hpp + src/ui/widgets/StreamSettingsWidget.hpp + src/ui/w_ImportConfig.hpp + src/ui/w_MainWindow.hpp + src/ui/w_PreferencesWindow.hpp + src/ui/w_ScreenShot_Core.hpp + src/ui/w_SubscriptionManager.hpp assets/qv2ray.rc ) @@ -219,7 +273,7 @@ if(EMBED_TRANSLATIONS) endif() add_custom_target(lupdate - COMMAND lupdate ${QV2RAY_SOURCES} -ts ${TRANSLATIONS_TS} + COMMAND lupdate ${QV2RAY_SOURCES} -ts ${TRANSLATIONS_TS} -no-ui-lines WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) set_target_properties(lupdate PROPERTIES EXCLUDE_FROM_ALL TRUE) diff --git a/translations/en_US.ts b/translations/en_US.ts index dc2c39fe..a279b8d1 100644 --- a/translations/en_US.ts +++ b/translations/en_US.ts @@ -2,26 +2,10 @@ - ConfigExporter + AutoCompleteTextEdit - - Save Image - - - - - - Share Connection - - - - - Image has been copied to the clipboard. - - - - - VMess string has been copied to the clipboard. + + This TextEdit provides autocompletions for words that have more than 3 characters. You can trigger autocompletion using @@ -128,22 +112,22 @@ - + (Ignored %1 complex config(s)) - + Not a subscription - + Delete an item - + Are you sure to delete the current item? @@ -156,33 +140,34 @@ - - + + ms - + + Type: - + Testing... - + Error - + connection - + connections @@ -220,59 +205,6 @@ - - ExportConfigWindow - - - Export Config - - - - - Share Options - - - - - Connection String - - - - - Copy Link - - - - - Save Image - - - - - Copy Image - - - - - OK - - - - - FlowScene - - - - Open Flow Scene - - - - - - Flow Scene Files (*.flow) - - - ImportConfigWindow @@ -426,64 +358,64 @@ - + Select file to import - + Capture QRCode - + Cannot find a valid QRCode from this region. - + Import config file - + Failed to check the validity of the config file. - + Select an image to import - + QRCode scanning failed - + Cannot find any QRCode from the image. - - - + + + Edit file as JSON - + Provided file not found: - + The file you selected has json syntax error. Continue editing may make you lose data. Would you like to continue? - + Failed to save file, please check if you have proper permissions @@ -762,11 +694,6 @@ JsonEditor - - - Dialog - - OK @@ -788,30 +715,40 @@ - - + + Json Contains Syntax Errors - + Original Json may contain syntax errors. Json tree is disabled. - + You must correct these errors before continue. - + Syntax Errors - - Please fix the JSON errors before continue - + + Please fix the JSON errors or remove the comments before continue + + + + + JSON Editor + + + + + Remove All Comments + @@ -821,36 +758,11 @@ Qv2ray - - - Connect - - - - - Disconnect - - - - - Reconnect - - - - - Clear Log - - Subscriptions - - - Import connection - - Add @@ -858,25 +770,55 @@ - + Preferences - - Edit - + + Import Connection + - Speed Graph - + Sort + + + + + Click to toggle show/hide + + + + + Speed Graph + + + + + Clear chart data + + + + + Log + + + + + Clear log + Speed + + + Upload/Download speed + + 0.00 B/s @@ -888,6 +830,11 @@ Data + + + Upload/Download Data + + 0.00 B @@ -895,138 +842,103 @@ - - + + Hide - - Quit - - - - - Rename - - - - - Connect to this - - - - - Edit as JSON - - - - - Edit as Complex Config - - - - - + + Show - - Duplicate to the Same Group - - - - - Delete Connection - - - - + Sort connection list. - + By connection name, A-Z - + By connection name, Z-A - + By data, Ascending - + By data, Descending - + By latency, Ascending - + By latency, Descending - + Update - + Found a new version: - + Download Link: - - - - + + + + Connected: - - + + Configuring PAC - + Could not start PAC server as it is configured to use SOCKS, but it is not enabled - + Could not start PAC server as it is configured to use HTTP, but it is not enabled - + Duplicating Connection(s) - + Are you sure to duplicate these connection(s)? - + (Copy) @@ -1076,47 +988,37 @@ - + V2ray vcore terminated. - + V2ray vcore terminated unexpectedly. - + To solve the problem, read the V2ray log in the log text browser. - - Enable System Proxy - - - - - Disable System Proxy - - - - + System Proxy - + Disconnected from: - + Removing Connection(s) - + Are you sure to remove selected connection(s)? @@ -1132,13 +1034,73 @@ - Log + + Not Connected - - - Not Connected + + Quit + + + + + Connect + + + + + Reconnect + + + + + Disconnect + + + + + Enable System Proxy + + + + + Disable System Proxy + + + + + Connect to this + + + + + Edit + + + + + Edit as JSON + + + + + Edit as Complex Config + + + + + Rename + + + + + Duplicate to the Same Group + + + + + Delete Connection @@ -1274,11 +1236,11 @@ PreferencesWindow - - - - - + + + + + Preferences @@ -1684,13 +1646,13 @@ - + Bold - + Italic @@ -1800,156 +1762,146 @@ - + Use Darkmode Theme - + Page - + Item(s) - - + + Enable tProxy Support - + to this path: - + Qv2ray Network Toolbar is disabled and still under test. Add --withToolbarPlugin to enable. - + Duplicated port numbers detected, please check the port number settings. - + Invalid inbound listening address. - + Open V2ray assets folder - + Open V2ray core file - + This will append capabilities to the V2ray executable. - + Qv2ray will copy your V2ray core to this path: - + If anything goes wrong after enabling this, please check issue #57 or the link below: - + Qv2ray cannot copy one or both V2ray files from: - - + + Failed to setcap onto V2ray executable. You may need to run `setcap` manually. - + tProxy is not supported on macOS and Windows - + Apply network toolbar settings - + All other modified settings will be applied as well after this object. - + Do you want to continue? - - Dark Mode - - - - - Please restart Qv2ray to fully apply this feature. - - - - + Select GFWList in base64 - - + + Download GFWList - + Operation is cancelled. - + Successfully downloaded GFWList. - + Start with boot - + Failed to set auto start option. - - + + V2ray Core Settings - + V2ray path configuration check passed. - + Current version of V2ray is: @@ -2067,202 +2019,142 @@ p, li { white-space: pre-wrap; } - + VMess string should start with 'vmess://' - + VMess string should be a valid base64 string - + JSON should not be empty - + Warning - + Qv2ray cannot load the config file from here: - + Cannot Start Qv2ray - + Cannot find a place to store config files. - + Qv2ray has searched these paths below: - - - + + It usually means you don't have the write permission to all of those locations. + + + + + + Qv2ray will now exit. - + Failed to initialise Qv2ray - - Failed to determine the location of config file. - - - - + Please report if you think it's a bug. - + You cannot run Qv2ray as root, please use --I-just-wanna-run-with-root if you REALLY want to do so. - + --> USE IT AT YOUR OWN RISK! - - Cannot load languages - + + Debug version + - - Qv2ray will continue running, but you cannot change the UI language. - - - - + Qv2ray Cannot Continue - + You are running a lower version of Qv2ray compared to the current config file. - + Please check if there's an issue explaining about it. - + Or submit a new issue if you think this is an error. - + Dependency Missing - + This could be caused by a missing of `openssl` package in your system. - + If you are using an AppImage from Github Action, please report a bug. - + Cannot find openssl libs - + + Failed to determine the location of config file: + + + + + Qv2ray has found a config file, but it failed to be loaded due to some errors. + + + + + A workaround is to remove the this file and restart Qv2ray: + + + + Technical Details - - - Custom Text - - - - - Current Time - - - - - Current Date - - - - - Current Qv2ray Version - - - - - Current Connection Name - - - - - Current Connection Status - - - - - Total Upload Speed - - - - - Total Download Speed - - - - - Upload Speed for Specific Tag - - - - - Download Speed for Specific Tag - - - - - Total Uploaded Data - - - - - Total Downloaded Data - - - - - Uploaded Data for Specific Tag - - - - - Downloaded Data for Specific Tag - - @@ -2270,12 +2162,6 @@ p, li { white-space: pre-wrap; } N/A - - - - (Guessed) - - Qv2ray - A cross-platform Qt frontend for V2ray. @@ -2302,100 +2188,165 @@ p, li { white-space: pre-wrap; } - + Default Group - + Configuration Upgrade Failed - + Unsupported config version number: - + Please upgrade firstly up to Qv2ray v2.0/v2.1 and try again. - + invalid ssd link: json: field %1 must exist - + invalid ssd link: json: field %1 must be valid port number - + invalid ssd link: json: field %1 must be of type 'string' - + invalid ssd link: json: field %1 must be an array - + skipping invalid ssd server: server must be an object - + skipping invalid ssd server: missing required field %1 - + skipping invalid ssd server: field %1 should be of type 'string' - + Invalid ssd link: should begin with ssd:// - + Invalid ssd link: base64 parse failed - + Invalid ssd link: json parse failed: - + Invalid ssd link: found non-object json, aborting - + Invalid ssd link: rc4-md5 encryption is not supported by v2ray-core - + Invalid port encountered. using fallback value. - + Invalid name encountered. using fallback value. - + Invalid ratio encountered. using fallback value. + + + Not connected + + + + + Connected + + + + + Custom Text + + + + + Current Time + + + + + Current Date + + + + + Current Qv2ray Version + + + + + Current Connection Name + + + + + Current Connection Status + + + + + Total Upload Speed + + + + + Total Download Speed + + + + + Total Uploaded Data + + + + + Total Downloaded Data + + + + + Current Connection Latency + + %1 - %2 (rate %3) @@ -2410,12 +2361,12 @@ p, li { white-space: pre-wrap; } Qv2ray::components::pac::PACServer - + PAC Handler - + Failed to listen PAC request on this port, please verify the permissions @@ -2423,23 +2374,18 @@ p, li { white-space: pre-wrap; } Qv2ray::core::handlers::QvConfigHandler - - + + Default Group - - Connection doesn't exist - - - - + File does not exist. - + Group does not exist @@ -2483,32 +2429,32 @@ p, li { white-space: pre-wrap; } - + Configuration Error - + Cannot start V2ray - + V2ray core settings is incorrect. - + The error is: - + Invalid V2ray Instance Status. - + V2ray kernel failed to start. @@ -2541,7 +2487,7 @@ p, li { white-space: pre-wrap; } RouteEditor - + Route Editor @@ -2781,182 +2727,186 @@ p, li { white-space: pre-wrap; } - - - + + + OK - + Cannot Edit - + This outbound entry is not supported by the GUI editor. - - + + We will launch Json Editor instead. - + Show rule details - + A rule cannot be found: - - - + + + Protocol list changed: - + Balancer is empty, not processing. - + Default rule - + rule - + No Inbound - + No inbound item found: - - - + + The new tag has been used, we appended a postfix. - + + The new tag has been used, we appended a random string to the tag. + + + + To make this rule ready to use, you need to connect it to an outbound node. - + Remove Items - - + + Please select a node from the graph to continue. - + Error - + Qv2ray entered an unknown state. - + Edit Inbound/Outbound - - + + Edit Inbound - - + + No inbound tag found: - - + + Opening JSON editor - + Unsupported Outbound Type - + Opening default outbound editor. + + - - Renaming a tag - + New tag is empty, please try another. - + New tag is the same as the original one. - + Duplicate rule tag detected, please try another. - + Added DIRECT outbound - + Currently, this type of outbound is not supported by the editor. - + Opening default inbound editor - + Removed a balancer entry. - - - + + + Rename tags @@ -3188,22 +3138,22 @@ p, li { white-space: pre-wrap; } SubscribeEditor - + Reload Subscription - + Would you like to reload the subscription? - + Deleting a subscription - + All connections will be moved to default group, do you want to continue? diff --git a/translations/ja_JP.ts b/translations/ja_JP.ts index 46fb4207..e58eddb1 100644 --- a/translations/ja_JP.ts +++ b/translations/ja_JP.ts @@ -1,79 +1,269 @@ - + + + - ConfigExporter + AutoCompleteTextEdit - - Save Image - 画像を保存 - - - - - Share Connection - 接続を共有 - - - - Image has been copied to the clipboard. - 画像がクリップボードにコピーされました。 - - - - VMess string has been copied to the clipboard. - VMess文字列がクリップボードにコピーされました。 + + This TextEdit provides autocompletions for words that have more than 3 characters. You can trigger autocompletion using + - ExportConfigWindow + ConfigExporter - - Export Config - エクスポート設定 - - - - Share Options - 共有オプション - - - - Connection String - 接続文字列 - - - - Copy Link - リンクをコピー - - - Save Image - 画像を保存 + 画像を保存 - - Copy Image - 画像をコピー + Share Connection + 接続を共有 - + Image has been copied to the clipboard. + 画像がクリップボードにコピーされました。 + + + VMess string has been copied to the clipboard. + VMess文字列がクリップボードにコピーされました。 + + + + ConnectionInfoWidget + + + Form + Form + + + + Configuration Details + 構成の詳細 + + + + Connect/Disconnect + 接続/切断 + + + + Edit Connection + 接続を編集 + + + + Edit Connection as JSON + 接続をJSONとして編集 + + + + Latency Test + 潜時テスト + + + + Delete Connection + 接続を削除 + + + + Group + グループ + + + + type + type + + + + Protocol + プロトコル + + + + proto + proto + + + + Address + アドレス + + + + addr + addr + + + + Port + ポート + + + + port + port + + + + Link + リンク + + + + QR Code + QRコード + + + + Group Name + グループ名 + + + + Subscription Link + サブスクリプションリンク + + + + Share Link + リンクを共有 + + + + (Ignored %1 complex config(s)) + (%1の複雑構成は無視されました) + + + + Not a subscription + サブスクリプションではありません + + + + Delete an item + アイテムを削除する + + + + Are you sure to delete the current item? + 現在のアイテムを削除してもよろしいですか? + + + + ConnectionItemWidget + + + Not Tested + 未検証 + + + + + ms + ms + + + + + Type: + 種類: + + + + Testing... + テスト中... + + + + Error + エラー + + + + connection + + + + + connections + + + + + ConnectionWidget + + + Form + Form + + + + Connection Name + 接続名 + + + + 500ms + 500ms + + + + Type: vmess + tls + ws + 種類: vmess + tls + ws + + + + 0KB / 0KB + 0KB / 0KB + + + OK よし - FlowScene + ExportConfigWindow - - - Open Flow Scene - フローシーンを開く + Export Config + エクスポート設定 + + + Share Options + 共有オプション + + + Connection String + 接続文字列 + + + Copy Link + リンクをコピー + + + Save Image + 画像を保存 + + + Copy Image + 画像をコピー + + + OK + よし + + + + FlowScene + + Open Flow Scene + フローシーンを開く - - Flow Scene Files (*.flow) - フローシーンファイル (*.flow) + フローシーンファイル (*.flow) @@ -101,7 +291,7 @@ secs - + @@ -111,7 +301,7 @@ Share Link - リンクを共有 + 共有されたリンク @@ -134,14 +324,12 @@ 選択 - Inbound - インバウンド + インバウンド - Keep imported inbound settings - インポートされたインバウンド設定を保持する + インポートされたインバウンド設定を保持する @@ -153,6 +341,11 @@ Open in JSON Editor JSONエディターで開く + + + Import as Complex Config (Manually edit route rules and inbounds) + 複雑な構成としてインポート(ルートルールとインバウンドを手動で編集) + VMess / QRCode @@ -236,67 +429,67 @@ Cancel - 取り消し + 取り消し - + Select file to import インポートするファイルを選択 - + Capture QRCode QRCodeをキャプチャ - + Cannot find a valid QRCode from this region. この地域から有効なQRコードが見つかりません。 - + Import config file 設定ファイルをインポートする - + Failed to check the validity of the config file. 構成ファイルの有効性を確認できませんでした。 - + Select an image to import インポートする画像を選択してください - + QRCode scanning failed QRコードのスキャンに失敗しました - + Cannot find any QRCode from the image. 画像からQRコードが見つかりません。 - - - + + + Edit file as JSON ファイルをJSONとして編集 - + Provided file not found: - 指定されたファイルが見つかりません: + 指定されたファイルが見つかりません: - + The file you selected has json syntax error. Continue editing may make you lose data. Would you like to continue? 選択したファイルにはJSON構文エラーがあります。編集を続けると、データが失われる可能性があります。続行しますか? - + Failed to save file, please check if you have proper permissions ファイルを保存できませんでした。適切な権限があるかどうかを確認してください @@ -529,41 +722,41 @@ SECRET - + Inbound type not supported インバウンドタイプがサポートされていません - + The inbound type is not supported by Qv2ray (yet). Please use JsonEditor to change the settings このインバウンドタイプは、Qv2rayでは(まだ)サポートされていません。 JsonEditorを使用して設定を変更してください - + Inbound: Inbound: - - + + Removing a user - Removing a user + ユーザーを削除する - - + + You haven't selected a user yet. - You haven't selected a user yet. + まだユーザーを選択していません。 - - + + Add a user - Add a user + ユーザーを追加する - - + + This user exists already. This user exists already. @@ -571,14 +764,13 @@ JsonEditor - Dialog - Dialog + Dialog OK - OK + よし @@ -588,38 +780,52 @@ Format JSON - JSONのフォーマット + JSONのプリティファイ Json Editor - JSONエディター  + JSONエディター - - + + Json Contains Syntax Errors JSONに構文エラーが含まれる - + Original Json may contain syntax errors. Json tree is disabled. 元のJSONには構文エラーが含まれる場合があります。 JSONツリーは無効です。 - + You must correct these errors before continue. 続行する前にこれらのエラーを修正する必要があります。 - + Syntax Errors 構文エラー - + + Please fix the JSON errors or remove the comments before continue + JSONエラーを修正するか、コメントを削除してから続行してください + + Please fix the JSON errors before continue - Please fix the JSON errors before continue + 続行する前にJSONエラーを修正してください + + + + JSON Editor + JSONエディター + + + + Remove All Comments + コメントを全削除 @@ -630,27 +836,23 @@ Qv2ray - - + Connect 接続 - - + Disconnect 切断 - - + Reconnect 再接 - Clear Log - ログをクリア + ログをクリア @@ -658,79 +860,64 @@ サブスクリプション - Stopped - 停止 + 停止 - Host List - ホストリスト + ホストリスト - Import connection - 接続をインポート + 接続をインポート - Duplicate connection - 接続を重複 + 接続を重複 - Delete a connection - 接続を削除 + 接続を削除 - Edit connection - 接続を編集 + 接続を編集 - Config Details - 構成の詳細 + 構成の詳細 - Config Type - 構成の種類 + 構成の種類 - Protocol - プロトコル + プロトコル - Address - アドレス + アドレス - Port Number - ポート番号 + ポート番号 - Latency - 潜時 + 潜時 - Operations - 操作 + 操作 - Edit connection as JSON - 接続をJSONとして編集 + 接続をJSONとして編集 - Log (click to switch log source) - ログ(クリックしてログソースを切り替えます) + ログ(クリックしてログソースを切り替えます) @@ -739,50 +926,100 @@ - + Preferences 設定 - Duplicate - 複写 + 複写 - Delete - 削除 + 削除 - + Edit 編集 - Edit JSON - JSONを編集 + JSONを編集 - Ping Test - Pingテスト + Pingテスト - Share - 共有 + 共有 + + + Speed Graph + 速度図 - Speed Graph - 速度図 + Locate Current Connection + 現在の接続を見つける + + + + Search + 捜索 + + + + Import Connection + 接続をインポート + + + + Sort + 並べ替える + + + + Click to toggle show/hide + クリックして表示/非表示を切り替えます + + + + Speed Graph + 速度図 + + + + Clear chart data + チャートデータをクリア + + + + Log + ログ + + + + Clear log + ログをクリア + + + + + Not Connected + 接続されていません Speed 速度 + + + Upload/Download speed + アップロード/ダウンロード速度 + 0.00 B/s @@ -793,7 +1030,12 @@ Data - Data + データ + + + + Upload/Download Data + アップロード/ダウンロードのデータ @@ -803,398 +1045,406 @@ 0.00 B - #ManuallyCreateConnection - #ManuallyCreateConnection + #ManuallyCreateConnection - #ImportConnection - #ImportConnection + #ImportConnection - #Exit - #Exit + #Exit - #Preferences - #Preferences + #Preferences - #Start - #Start + #Start - #Stop - #Stop + #Stop - #Restart - #Restart + #Restart - - + + Hide - Hide + 非表示 - + Quit - Quit + 終了 - + + Edit as JSON + JSONとして編集 + + + Rename Rename - + + Duplicate to the Same Group + 同じグループに複製 + + + + Delete Connection + 接続を削除 + + + Connect to this Connect to this - + Edit as Complex Config Edit as Complex Config - Edit as Json - Edit as Json + Edit as Json - Share as QRCode/VMess URL - Share as QRCode/VMess URL + Share as QRCode/VMess URL - Subscription: - Subscription: + Subscription: - - - + + Show - Show + 表示 - Autostarting a config - Autostarting a config + Autostarting a config - Could not find a specified config named: - Could not find a specified config named: + Could not find a specified config named: - - No connection selected! - No connection selected! + No connection selected! - - Please select a config from the list. - Please select a config from the list. + Please select a config from the list. - + + Sort connection list. + 接続リストを並べ替えます。 + + + + By connection name, A-Z + 接続名で、A-Z + + + + By connection name, Z-A + 接続名で、Z-A + + + + By latency, Ascending + レイテンシー、昇順 + + + + By latency, Descending + レイテンシー、降順 + + + + By data, Ascending + データ別、昇順 + + + + By data, Descending + データ別、降順 + + + Update - Update + 更新 - + Found a new version: - Found a new version: + 新しいバージョンが見つかりました: - + Download Link: - Download Link: + ダウンロードリンク: - - - - + + + + Connected: - Connected: + 接続済み: - - + + Configuring PAC - Configuring PAC + PACの構成 - + Could not start PAC server as it is configured to use SOCKS, but it is not enabled - Could not start PAC server as it is configured to use SOCKS, but it is not enabled + SOCKSを使用するように構成されているため、PACサーバーを起動できませんでしたが、有効になっていません - + Could not start PAC server as it is configured to use HTTP, but it is not enabled - Could not start PAC server as it is configured to use HTTP, but it is not enabled + HTTPを使用するように設定されているため、PACサーバーを起動できませんでしたが、有効になっていません - + + Duplicating Connection(s) + 接続を重複 + + + + Are you sure to duplicate these connection(s)? + これらの接続を複製してもよろしいですか? + + + + (Copy) + (コピー) + + + PAC Processing Failed - PAC Processing Failed + PAC処理に失敗しました - Please reset the settings in Preference Window - Please reset the settings in Preference Window + Please reset the settings in Preference Window - System proxy cleared. - System proxy cleared. + System proxy cleared. - + HTTP or SOCKS inbound is not properly configured for PAC - HTTP or SOCKS inbound is not properly configured for PAC + HTTPまたはSOCKSインバウンドがPAC用に適切に構成されていません - + Qv2ray will continue, but will not set system proxy. - Qv2ray will continue, but will not set system proxy. + Qv2rayは続行されますが、システムプロキシは設定されません。 - + Cannot set system proxy Cannot set system proxy - + Both HTTP and SOCKS inbounds are not enabled - Both HTTP and SOCKS inbounds are not enabled + HTTPインバウンドとSOCKSインバウンドの両方が有効になっていません + + + + Didn't set proxy for complex config. + 複雑な構成のプロキシを設定しませんでした。 - System proxy settings applied. - System proxy settings applied. + System proxy settings applied. - Cannot set proxy for complex config. - Cannot set proxy for complex config. + Cannot set proxy for complex config. - + Update Subscriptions - Update Subscriptions + サブスクリプションを更新 - + There are subscriptions need to be updated, please go to subscriptions window to update them. - There are subscriptions need to be updated, please go to subscriptions window to update them. + 更新が必要なサブスクリプションがあります。サブスクリプションウィンドウに移動して更新してください。 - + These subscriptions are out-of-date: - These subscriptions are out-of-date: + これらのサブスクリプションは最新ではありません: - Disconnected - Disconnected + Disconnected - Complex - Complex + Complex - Simple - Simple + Simple - No data - No data + No data - ms - ms + ms - There're no support of sharing configs other than vmess and shadowsocks - There're no support of sharing configs other than vmess and shadowsocks + There're no support of sharing configs other than vmess and shadowsocks - - - - - - N/A - N/A + N/A - - - Rename a Connection - Rename a Connection + Rename a Connection - + V2ray vcore terminated. - V2ray vcore terminated. + V2ray コアが終了しました。 - + V2ray vcore terminated unexpectedly. - V2ray vcore terminated unexpectedly. + V2rayコアが予期せず終了しました。 - + To solve the problem, read the V2ray log in the log text browser. - To solve the problem, read the V2ray log in the log text browser. + 問題を解決するには、ログテキストブラウザーでV2rayログを読みます。 - + Enable System Proxy Enable System Proxy - + Disable System Proxy Disable System Proxy - + System Proxy - System Proxy + システムプロキシ - Ping - Ping + Ping - Ping All - Ping All + Ping All - - Subscription - Subscription + Subscription - Already connected to: - Already connected to: + Already connected to: - + Disconnected from: - Disconnected from: + 次から切断: - The name cannot be empty - The name cannot be empty + The name cannot be empty - The name has been used already, Please choose another. - The name has been used already, Please choose another. + The name has been used already, Please choose another. - The name you suggested is not valid, please try another. - The name you suggested is not valid, please try another. + The name you suggested is not valid, please try another. - + Removing Connection(s) - Removing Connection(s) + 接続の削除 - + Are you sure to remove selected connection(s)? - Are you sure to remove selected connection(s)? + 選択した接続を削除してもよろしいですか? - - Removing this Connection - Removing this Connection + Removing this Connection - - Failed to delete connection file, please delete manually. - Failed to delete connection file, please delete manually. + Failed to delete connection file, please delete manually. - Removing a subscription config - Removing a subscription config + Removing a subscription config - Do you want to remove the config loaded from a subscription? - Do you want to remove the config loaded from a subscription? + Do you want to remove the config loaded from a subscription? - - - No Config Selected - No Config Selected + No Config Selected - - - Please Select a Config - Please Select a Config + Please Select a Config - You are about to run latency test on all servers, do you want to continue? - You are about to run latency test on all servers, do you want to continue? + You are about to run latency test on all servers, do you want to continue? - Testing... - Testing... + Testing... - - Latency Test - Latency Test + Latency Test - Failed to test latency for this connection. - Failed to test latency for this connection. + Failed to test latency for this connection. - Share Connection - Share Connection + Share Connection @@ -1202,32 +1452,32 @@ Tag - Tag + タグ Tag of this outbound setting - Tag of this outbound setting + このアウトバウンド設定のタグ Host - Host + ホスト Hostname or IP/IPv6 Address - Hostname or IP/IPv6 Address + ホスト名またはIPv4 / IPv6アドレス Port - Port + ポート Type - Type + 種類 @@ -1237,42 +1487,42 @@ Use Mux - Use Mux + Muxを使う Enabled - Enabled + 有効 Edit Connection Settings - Edit Connection Settings + 接続設定の編集 Stream Settings - Stream Settings + ストリーム設定 Misc Settings - Misc Settings + その他の設定 Mux Concurrency - Mux Concurrency + Muxの同時実行 Use Forward Proxy - Use Forward Proxy + フォワードプロキシを使う Outbound Settings - Outbound Settings + アウトバウンド設定 @@ -1282,27 +1532,27 @@ Alter ID - Alter ID + アルターID Security - Security + セキュリティ Email - Email + 電子メール Password - Password + 暗号 Encryption Method - Encryption Method + 暗号化方法 @@ -1312,7 +1562,7 @@ Level - Level + レベル @@ -1322,60 +1572,60 @@ Username - Username + ユーザー名 PreferencesWindow - - - - - + + + + + Preferences - Preferences + 設定 UI Theme - UI Theme + UIテーマ Enabled - Enabled + 有効 Darkmode UI Icons - Darkmode UI Icons + ダークモードUIアイコン Darkmode Tray Icon - Darkmode Tray Icon + ダークモードトレイアイコン Language - Language + 言語 Log Level - Log Level + ログレベル none - none + なし debug - debug + デバッグ @@ -1385,42 +1635,42 @@ warning - warning + 警告 error - error + エラー Config - Config + 構成 Subscription - Subscription + サブスクリプション Select - Select + 選択 Auto Connect - Auto Connect + 自動接続 Inbound Settings - Inbound Settings + インバウンド設定 Listening Address - Listening Address + リスニングアドレス @@ -1435,47 +1685,47 @@ Set System Proxy - Set System Proxy + システムプロキシを設定する SOCKS Settings - SOCKS Settings + SOCKS設定 Port - Port + ポート UDP Support - UDP Support + UDPサポート Launch at Login - Launch at Login + ログイン時に起動 API Subsystem - API Subsystem + APIサブシステム Authentication - Authentication + 認証 Username - Username + ユーザー名 Password - Password + 暗号 @@ -1485,17 +1735,17 @@ PAC Settings - PAC Settings + PAC設定 The system proxy will be configured to use the PAC instead of HTTP and SOCKS. - The system proxy will be configured to use the PAC instead of HTTP and SOCKS. + システムプロキシは、HTTPおよびSOCKSの代わりにPACを使用するように構成されます。 Local IP for PAC - Local IP for PAC + PACのローカルIP @@ -1505,12 +1755,12 @@ Use Proxy - Use Proxy + プロキシを使う Import GFWList - Import GFWList + GFWListをインポートする @@ -1545,92 +1795,92 @@ GFWList File - GFWList File + GFWListファイル Download with System Proxy - Download with System Proxy + システムプロキシでダウンロード Go - Go + 実行 Edit PAC - Edit PAC + PACを編集 Open PAC Folder - Open PAC Folder + PACフォルダーを開く PAC Access Path - PAC Access Path + PACアクセスパス Connection Settings - Connection Settings + 接続設定 General Connection Settings - General Connection Settings + 一般接続設定 Enable Proxy - Enable Proxy + プロキシを有効にする Bypass Chinese Mainland - Bypass Chinese Mainland + 中国本土をバイパス API Port - API Port + APIポート Use Local DNS - Use Local DNS + ローカルDNSを使用する Custom DNS List - Custom DNS List + カスタムDNSリスト Forward Proxy - Forward Proxy + フォワードプロキシ Only simple config is supported. - Only simple config is supported. + 単純な構成のみがサポートされています。 Build Info - Build Info + ビルド情報 Extra Build Info - Extra Build Info + 追加ビルド情報 Type - Type + 種類 @@ -1640,62 +1890,127 @@ Host Address - Host Address + ホストアドレス Network Toolbar Settings - Network Toolbar Settings + ネットワークツールバーの設定 Apply Network Speed Bar UI Settings - Apply Network Speed Bar UI Settings + ネットワークスピードバーのUI設定を適用する Items - Items + アイテム General Settings - General Settings + 一般設定 Maximum log lines - Maximum log lines + 最大ログ行 lines - lines + V2ray Settings - V2ray Settings + V2ray設定 Core Executable Path - Core Executable Path + コア実行可能パス V2ray Assets Directory - V2ray Assets Directory + V2rayアセットディレクトリ Check V2ray Core Settings - Check V2ray Core Settings + V2ray Core設定を確認する UDP Local IP - UDP Local IP + UDP ローカル IP + + + + Transparent Proxy Settings + 透過プロキシ設定 + + + + All settings below will only be applied onto simple connection. + 以下のすべての設定は、単純な接続にのみ適用されます。 + + + + Add Docodemo-door inbound + どこでもドアインバウンドを追加 + + + + Address + アドレス + + + + TCP + TCP + + + + UDP + UDP + + + + Follow Redirect + リダイレクトに従う + + + + Override Connection SockOpt Settings + 接続SockOpt設定のオーバーライド + + + + TCP Fast Open + TCP Fast Open + + + + Mark + マーク + + + + Match Contains + 一致するもの + + + + TProxy Mode + tProxy モード + + + + Settings will be added to the StreamSettings for matched connections. + 一致した接続の設定がStreamSettingsに追加されます。 @@ -1710,54 +2025,54 @@ Page Y Offset - Page Y Offset + ページYオフセット Pages - Pages + ページ数 Lines - Lines + This feature is not stable and no documentation is provided, please use it at your own risk! - This feature is not stable and no documentation is provided, please use it at your own risk! + この機能は安定しておらず、ドキュメントも提供されていません。ご自身の責任で使用してください! Text Style - Text Style + テキストスタイル Font - Font + 字体 - + Bold Bold - + Italic - Italic + 斜体 Size - Size + サイズ Color - Color + @@ -1787,32 +2102,32 @@ Style - Style + スタイル Content - Content + コンテンツ Content Type - Content Type + コンテンツタイプ Text/Tag - Text/Tag + テキスト/タグ You can config how the network speed toolbar looks like in this panel - You can config how the network speed toolbar looks like in this panel + このパネルでは、ネットワーク速度ツールバーの外観を設定できます About - About + このソフトについて @@ -1822,208 +2137,206 @@ Version: - Version: + バージョン: Official Repo: - Official Repo: + 公式レポ: License: - License: + ライセンス: Built Time: - Built Time: + ビルド時間: Ignore Next Version - Ignore Next Version + 次のバージョンを無視 Cancel - Cancel + 取り消し About Qt - About Qt + Qtについて - + Use Darkmode Theme - Use Darkmode Theme + ダークモードテーマを使用する - + Page - Page + ページ - + Item(s) - Item(s) - - - - - Enable tProxy Support - Enable tProxy Support + アイテム + + Enable tProxy Support + tProxyサポートを有効にする + + + to this path: - to this path: + このパスへ: - + Qv2ray Network Toolbar is disabled and still under test. Add --withToolbarPlugin to enable. - Qv2ray Network Toolbar is disabled and still under test. Add --withToolbarPlugin to enable. + Qv2rayネットワークツールバーは無効になっており、まだテスト中です。 --withToolbarPluginを追加して有効にします。 - + Duplicated port numbers detected, please check the port number settings. - Duplicated port numbers detected, please check the port number settings. + 重複したポート番号が検出されました。ポート番号の設定を確認してください。 - + Invalid inbound listening address. - Invalid inbound listening address. + 無効なインバウンドリスニングアドレス。 - + Open V2ray assets folder - Open V2ray assets folder + V2rayアセットフォルダーを開く - + Open V2ray core file - Open V2ray core file + V2rayコアファイルを開く - + This will append capabilities to the V2ray executable. - This will append capabilities to the V2ray executable. + これにより、V2ray実行可能ファイルに機能が追加されます。 - + Qv2ray will copy your V2ray core to this path: - Qv2ray will copy your V2ray core to this path: + Qv2rayは、V2rayコアを次のパスにコピーします: - + If anything goes wrong after enabling this, please check issue #57 or the link below: - If anything goes wrong after enabling this, please check issue #57 or the link below: + これを有効にした後に何か問題が発生した場合は、問題#57または以下のリンクを確認してください: - + Qv2ray cannot copy one or both V2ray files from: - Qv2ray cannot copy one or both V2ray files from: + Qv2rayは、V2rayファイルの一方または両方を以下からコピーできません: - - + + Failed to setcap onto V2ray executable. You may need to run `setcap` manually. - Failed to setcap onto V2ray executable. You may need to run `setcap` manually. + V2ray実行可能ファイルへのsetcapに失敗しました。`setcap`を手動で実行する必要がある場合があります。 - + tProxy is not supported on macOS and Windows - tProxy is not supported on macOS and Windows + tProxyはmacOSおよびWindowsではサポートされていません - + Apply network toolbar settings - Apply network toolbar settings + ネットワークツールバー設定を適用する - + All other modified settings will be applied as well after this object. All other modified settings will be applied as well after this object. - + Do you want to continue? - Do you want to continue? + 続けますか? - Dark Mode - Dark Mode + Dark Mode - Please restart Qv2ray to fully apply this feature. - Please restart Qv2ray to fully apply this feature. + Please restart Qv2ray to fully apply this feature. - + Select GFWList in base64 - Select GFWList in base64 + Base64でGFWListを選択します - - + + Download GFWList - Download GFWList + GFWListをダウンロードする - + Operation is cancelled. - Operation is cancelled. + 操作はキャンセルされます。 - + Successfully downloaded GFWList. - Successfully downloaded GFWList. + GFWListを正常にダウンロードしました。 - + Start with boot - Start with boot + ブート時に起動します - + Failed to set auto start option. - Failed to set auto start option. + 自動開始オプションの設定に失敗しました。 - - + + V2ray Core Settings - V2ray Core Settings + V2ray Core設定 - + V2ray path configuration check passed. - V2ray path configuration check passed. + V2rayパス構成チェックに合格しました。 - + Current version of V2ray is: - Current version of V2ray is: + V2rayの現在のバージョンは次のとおりです: Transparent Proxy Support - Transparent Proxy Support + 透過プロキシのサポート Status - Status + 状態 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'WenQuanYi Micro Hei'; font-size:10pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'WenQuanYi Micro Hei'; font-size:10pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -2035,167 +2348,193 @@ p, li { white-space: pre-wrap; } QObject - + Unsupported share link format. - Unsupported share link format. + サポートされていない共有リンク形式。 - + SS URI is too short - SS URI is too short + SS URIが短すぎます - - + + Can't find the colon separator between method and password - Can't find the colon separator between method and password + メソッドとパスワードの間にコロン区切り文字が見つかりません - + Can't find the at separator between password and hostname - Can't find the at separator between password and hostname + パスワードとホスト名の間の「アット」セパレーターが見つかりません - + Can't find the colon separator between hostname and port - Can't find the colon separator between hostname and port + ホスト名とポートの間にコロン区切り文字が見つかりません - + VMess string should start with 'vmess://' - VMess string should start with 'vmess://' + VMess文字列は「vmess://」で始まる必要があります - + VMess string should be a valid base64 string - VMess string should be a valid base64 string + VMess文字列は有効なbase64文字列でなければなりません - + JSON should not be empty - JSON should not be empty + JSONは空にしないでください - + Warning - Warning + 警告 - + Qv2ray cannot load the config file from here: - Qv2ray cannot load the config file from here: + Qv2rayはここから設定ファイルをロードできません: - + Cannot Start Qv2ray - Cannot Start Qv2ray + Qv2rayを起動できません - + Cannot find a place to store config files. - Cannot find a place to store config files. + 設定ファイルを保存する場所が見つかりません。 - + Qv2ray has searched these paths below: - Qv2ray has searched these paths below: + Qv2rayは以下のパスを検索しました: - - - + + It usually means you don't have the write permission to all of those locations. + 通常、これらの場所すべてに対する書き込み権限がないことを意味します。 + + + + + Qv2ray will now exit. - Qv2ray will now exit. + Qv2rayは終了します。 - + Failed to initialise Qv2ray - Failed to initialise Qv2ray + Qv2rayの初期化に失敗しました - Failed to determine the location of config file. - Failed to determine the location of config file. + 構成ファイルの場所を特定できませんでした。 - + Please report if you think it's a bug. - Please report if you think it's a bug. + バグだと思われる場合は報告してください。 - + You cannot run Qv2ray as root, please use --I-just-wanna-run-with-root if you REALLY want to do so. - You cannot run Qv2ray as root, please use --I-just-wanna-run-with-root if you REALLY want to do so. + Qv2rayをルートとして実行することはできません。本当に実行したい場合は、--I-just-wanna-run-with-rootを使用してください。 - + --> USE IT AT YOUR OWN RISK! - --> USE IT AT YOUR OWN RISK! + --> 自分の責任で使用してください! - Cannot load languages - Cannot load languages + Cannot load languages - Qv2ray will continue running, but you cannot change the UI language. - Qv2ray will continue running, but you cannot change the UI language. + Qv2ray will continue running, but you cannot change the UI language. - + Qv2ray Cannot Continue - Qv2ray Cannot Continue + Qv2rayを続行できません - + You are running a lower version of Qv2ray compared to the current config file. - You are running a lower version of Qv2ray compared to the current config file. + 現在の構成ファイルと比較して、より低いバージョンのQv2rayを実行しています。 - + Please check if there's an issue explaining about it. - Please check if there's an issue explaining about it. + それについて説明する問題があるかどうかを確認してください。 - + Or submit a new issue if you think this is an error. - Or submit a new issue if you think this is an error. + または、これがエラーだと思われる場合は、新しい問題を送信してください。 - + Dependency Missing - Dependency Missing + 依存関係がありません - + This could be caused by a missing of `openssl` package in your system. - This could be caused by a missing of `openssl` package in your system. + これは、システムに `openssl`パッケージが存在しないことが原因である可能性があります。 - + If you are using an AppImage from Github Action, please report a bug. - If you are using an AppImage from Github Action, please report a bug. + Github ActionsのAppImageを使用している場合は、バグを報告してください。 - + Cannot find openssl libs - Cannot find openssl libs + OpenSSLライブラリが見つかりません - + + Failed to determine the location of config file: + 構成ファイルの場所を特定できませんでした: + + + + Qv2ray has found a config file, but it failed to be loaded due to some errors. + Qv2rayは設定ファイルを見つけましたが、いくつかのエラーのためにロードに失敗しました。 + + + + A workaround is to remove the this file and restart Qv2ray: + 回避策は、このファイルを削除してQv2rayを再起動することです: + + + + Debug version + デバッグバージョン + + + Technical Details - Technical Details + 技術的な詳細 - + + Not connected + 接続されていません + + + Connected - Connected + 接続済み - Disconnected - Disconnected + Disconnected @@ -2238,14 +2577,17 @@ p, li { white-space: pre-wrap; } Total Download Speed - - Upload Speed for Specific Tag - Upload Speed for Specific Tag + + Current Connection Latency + 現在の接続遅延 + + + Upload Speed for Specific Tag + Upload Speed for Specific Tag - Download Speed for Specific Tag - Download Speed for Specific Tag + Download Speed for Specific Tag @@ -2258,149 +2600,276 @@ p, li { white-space: pre-wrap; } Total Downloaded Data - Uploaded Data for Specific Tag - Uploaded Data for Specific Tag + Uploaded Data for Specific Tag - Downloaded Data for Specific Tag - Downloaded Data for Specific Tag + Downloaded Data for Specific Tag - - Editing a subscription config - Editing a subscription config + Editing a subscription config - You are trying to edit a config loaded from subscription. - You are trying to edit a config loaded from subscription. + You are trying to edit a config loaded from subscription. - All changes will be overwritten when the subscriptions are updated next time. - All changes will be overwritten when the subscriptions are updated next time. + All changes will be overwritten when the subscriptions are updated next time. - Are you still going to do so? - Are you still going to do so? + Are you still going to do so? - You should not modity this property of a config from a subscription - You should not modity this property of a config from a subscription + You should not modity this property of a config from a subscription - + - + N/A - N/A + なし - + Qv2ray - A cross-platform Qt frontend for V2ray. - Qv2ray - A cross-platform Qt frontend for V2ray. - - - - Disable gRPC API subsystems. - Disable gRPC API subsystems. + Qv2ray - V2ray用のクロスプラットフォームQtフロントエンド。 - Explicitly run Qv2ray as root. - Explicitly run Qv2ray as root. + Disable gRPC API subsystems. + gRPC APIサブシステムを無効にします。 - Enable Debug Output - Enable Debug Output + Explicitly run Qv2ray as root. + ルートとしてQv2rayを明示的に実行します。 + Enable Debug Output + デバッグ出力を有効にする + + + Enable Qv2ray network toolbar plugin - Enable Qv2ray network toolbar plugin + Qv2rayネットワークツールバープラグインを有効にする + + + + invalid ssd link: json: field %1 must exist + 無効なssdリンク:json:フィールド%1が存在する必要があります + + + + invalid ssd link: json: field %1 must be valid port number + 無効なssdリンク:json:フィールド%1は有効なポート番号でなければなりません + + + + invalid ssd link: json: field %1 must be of type 'string' + 無効なssdリンク:json:フィールド%1は 'string'型でなければなりません + + + + invalid ssd link: json: field %1 must be an array + 無効なssdリンク:json:フィールド%1は配列でなければなりません + + + + skipping invalid ssd server: server must be an object + 無効なssdサーバーをスキップ:serverはオブジェクトでなければなりません + + + + skipping invalid ssd server: missing required field %1 + 無効なssdサーバーをスキップしています:必須フィールド%1がありません + + + + skipping invalid ssd server: field %1 should be of type 'string' + 無効なssdサーバーをスキップしています:フィールド%1はstring型でなければなりません + + + + Invalid ssd link: should begin with ssd:// + 無効なssdリンク:「ssd://」で始まる必要があります + + + + Invalid ssd link: base64 parse failed + 無効なssdリンク:base64の解析に失敗しました + + + + Invalid ssd link: json parse failed: + 無効なssdリンク:JSON解析に失敗しました: + + + + Invalid ssd link: found non-object json, aborting + 無効なssdリンク:非オブジェクトjsonが見つかりました + + + + Invalid ssd link: rc4-md5 encryption is not supported by v2ray-core + 無効なssdリンク:rc4-md5暗号化はv2ray-coreでサポートされていません + + + + Invalid port encountered. using fallback value. + 無効なポートが見つかりました。 フォールバック値を使用します。 + + + + Invalid name encountered. using fallback value. + 無効な名前が見つかりました。 フォールバック値を使用します。 + + + + Invalid ratio encountered. using fallback value. + 無効な比率が見つかりました。 フォールバック値を使用します。 + + + + Default Group + デフォルトグループ + + + + Configuration Upgrade Failed + 構成のアップグレードに失敗しました + + + + Unsupported config version number: + サポートされていない構成バージョン番号: + + + + Please upgrade firstly up to Qv2ray v2.0/v2.1 and try again. + まずQv2ray v2.0 / v2.1にアップグレードしてから、もう一度試してください。 + + + + %1 - %2 (rate %3) + %1 - %2 (%3 倍数) + + + + (Complex config) + (複雑構成) Qv2ray::components::pac::PACServer - + PAC Handler - PAC Handler + PACハンドラー - + Failed to listen PAC request on this port, please verify the permissions - Failed to listen PAC request on this port, please verify the permissions + このポートでPACリクエストをリッスンできませんでした、権限を確認してください + + + + Qv2ray::core::handlers::QvConfigHandler + + + + Default Group + デフォルトグループ + + + + File does not exist. + ファイルが存在しません。 + + + + + Group does not exist + グループが存在しません Qv2ray::core::kernel::V2rayKernelInstance - + V2ray core executable not found. - V2ray core executable not found. + V2rayコア実行可能ファイルが見つかりません。 - + V2ray core file cannot be opened, please ensure there's a file instead of a folder. - V2ray core file cannot be opened, please ensure there's a file instead of a folder. + V2rayコアファイルを開けません。フォルダーの代わりにファイルがあることを確認してください。 - + V2ray assets path is not valid. - V2ray assets path is not valid. + V2rayアセットのパスが無効です。 - + No geoip.dat in assets path. - No geoip.dat in assets path. + アセットパスにgeoip.datはありません。 - + No geosite.dat in assets path. - No geosite.dat in assets path. + アセットパスにgeosite.datはありません。 - + V2ray core failed with an exit code: - V2ray core failed with an exit code: + V2rayコアは終了コードで失敗しました: - + V2ray core returns empty string. - V2ray core returns empty string. + V2rayコアは空の文字列を返します。 - + Configuration Error - Configuration Error + 構成エラー - + Cannot start V2ray - Cannot start V2ray + V2rayを起動できません - + V2ray core settings is incorrect. - V2ray core settings is incorrect. + V2rayコアの設定が正しくありません。 - + The error is: - The error is: + エラーは次のとおりです: + + + + Invalid V2ray Instance Status. + 無効なV2rayインスタンスステータス。 + + + + V2ray kernel failed to start. + V2rayカーネルの起動に失敗しました。 QvInboundNodeModel - + Missing or incorrect inputs Missing or incorrect inputs @@ -2408,7 +2877,7 @@ p, li { white-space: pre-wrap; } QvOutboundNodeModel - + Missing or incorrect inputs Missing or incorrect inputs @@ -2416,7 +2885,7 @@ p, li { white-space: pre-wrap; } QvRuleNodeDataModel - + Missing or incorrect inputs Missing or incorrect inputs @@ -2425,89 +2894,89 @@ p, li { white-space: pre-wrap; } RouteEditor - + Route Editor - Route Editor + ルートエディター Route Detail Settings - Route Detail Settings + ルート詳細設定 Source IP Matches - Source IP Matches + ソースIPマッチング Status - Status + 状態 Add default inbound from global config - Add default inbound from global config + グローバル設定からデフォルトのインバウンドを追加 Port - Port + ポート Tag - Tag + タグ Add outbound - Add outbound + アウトバウンドを追加 Delete outbound - Delete outbound + アウトバウンドを削除 Edit outbound - Edit outbound + アウトバウンドを編集 Add Freedom outbound - Add Freedom outbound + 自由アウトバウンドを追加 Add blackhole outbound - Add blackhole outbound + ブラックホールアウトバウンドを追加 Routes - Routes + ルート Enabled - Enabled + 有効 Outbound - Outbound + アウトバウンド Add new route - Add new route + 新しいルートを追加 Use Balancers - Use Balancers + バランサーを使用する @@ -2517,17 +2986,17 @@ p, li { white-space: pre-wrap; } Target IP List - Target IP List + ターゲットIPリスト Target Domain List - Target Domain List + ターゲットドメインリスト Network - Network + ネットワーク @@ -2542,97 +3011,97 @@ p, li { white-space: pre-wrap; } Both - Both + どちらも Protocol - Protocol + プロトコル Inbound - Inbound + インバウンド Add From Global Settings - Add From Global Settings + グローバル設定から追加 Add Black Hole - Add Black Hole + ブラックホールを追加 Add Direct - Add Direct + 直接接続を追加 Selected Inbound/Outbound Info - Selected Inbound/Outbound Info + 選択したインバウンド/アウトバウンドの情報 Host - Host + ホスト A rule with no inbound connected means there's no inbound restriction. - A rule with no inbound connected means there's no inbound restriction. + インバウンドが接続されていないルールは、インバウンドの制限がないことを意味します。 Edit Selection - Edit Selection + 選択を編集 Delete Selection - Delete Selection + 選択を削除 General Settings - General Settings + 一般設定 Domain Strategy - Domain Strategy + ドメイン名戦略 Default Outbound - Default Outbound + デフォルトのアウトバウンド Rule Order Settings - Rule Order Settings + ルールの順序設定 Drag and drop to re-order the rules. - Drag and drop to re-order the rules. + ルールを並べ替えるには、ドラッグアンドドロップします。 Rule Settings - Rule Settings + ルール設定 Rule Status - Rule Status + ルールステータス Rule Tag - Rule Tag + ルールタグ @@ -2652,222 +3121,226 @@ p, li { white-space: pre-wrap; } e.g. 80, 443, 8000-8080 - e.g. 80, 443, 8000-8080 + 例えば 80, 443, 8000-8080 Balancers - Balancers + バランサー Users List - Users List + ユーザーリスト - - - + + + OK - OK + よし - + Cannot Edit - Cannot Edit + 編集できません - + This outbound entry is not supported by the GUI editor. - This outbound entry is not supported by the GUI editor. + このアウトバウンドエントリは、GUIエディタでサポートされていません。 - - + + We will launch Json Editor instead. - We will launch Json Editor instead. + 代わりにJson Editorを起動します。 - + Show rule details - Show rule details + ルールの詳細を表示 - + A rule cannot be found: - A rule cannot be found: + ルールが見つかりません: - - - + + + Protocol list changed: - Protocol list changed: + 変更されたプロトコルリスト: - + Balancer is empty, not processing. - Balancer is empty, not processing. + バランサーは空であり、処理されていません。 - + Default rule - Default rule + デフォルトルール - + rule - rule + ルール - + No Inbound - No Inbound + インバウンドなし - + No inbound item found: - No inbound item found: + インバウンドアイテムが見つかりませんでした: - - - + + The new tag has been used, we appended a postfix. - The new tag has been used, we appended a postfix. + 新しいタグが使用されているため、後置記号を追加します。 - + + The new tag has been used, we appended a random string to the tag. + 新しいタグが使用されたため、ランダムな文字列をタグに追加します。 + + + To make this rule ready to use, you need to connect it to an outbound node. - To make this rule ready to use, you need to connect it to an outbound node. + このルールを使用できるようにするには、アウトバウンドノードに接続する必要があります。 - + Remove Items - Remove Items + アイテムを削除する - - + + Please select a node from the graph to continue. - Please select a node from the graph to continue. + 続行するには、グラフからノードを選択してください。 - + Error - Error + エラー - + Qv2ray entered an unknown state. - Qv2ray entered an unknown state. + Qv2rayが不明な状態になりました。 - + Edit Inbound/Outbound - Edit Inbound/Outbound + インバウンド/アウトバウンドの編集 - - + + Edit Inbound - Edit Inbound + インバウンドを編集 - - + + No inbound tag found: - No inbound tag found: + 受信タグが見つかりません: - - + + Opening JSON editor - Opening JSON editor + JSONエディターを開く - + Unsupported Outbound Type - Unsupported Outbound Type + サポートされていないアウトバウンドタイプ - + Opening default outbound editor. - Opening default outbound editor. + デフォルトのアウトバウンドエディターを開きます。 - - - + + + Renaming a tag - Renaming a tag + タグの名前を変更する - + New tag is empty, please try another. - New tag is empty, please try another. + 新しいタグが空です。別のタグを試してください。 - + New tag is the same as the original one. - New tag is the same as the original one. + 新しいタグは元のタグと同じです。 - + Duplicate rule tag detected, please try another. - Duplicate rule tag detected, please try another. + 重複したルールタグが検出されました。別のタグを試してください。 - + Added DIRECT outbound - Added DIRECT outbound + DIRECTアウトバウンドを追加しました - + Currently, this type of outbound is not supported by the editor. - Currently, this type of outbound is not supported by the editor. + 現在、このタイプのアウトバウンドはエディターでサポートされていません。 - + Opening default inbound editor - Opening default inbound editor + デフォルトのインバウンドエディターを開く - + Removed a balancer entry. - Removed a balancer entry. + バランサーエントリを削除しました。 - - - + + + Rename tags - Rename tags + タグの名前を変更する Add Rule - Add Rule + ルールを追加 Add an Inbound - Add an Inbound + インバウンドを追加する Add an Outbound - Add an Outbound + アウトバウンドを追加する Misc Settings - Misc Settings + その他の設定 Rename - Rename + 改称する @@ -2875,12 +3348,12 @@ p, li { white-space: pre-wrap; } ScreenShot - ScreenShot + スクリーンショット Size - Size + サイズ @@ -2890,20 +3363,20 @@ p, li { white-space: pre-wrap; } Screen Shot - Screen Shot + スクリーンショット SpeedPlotView - + Total Upload - Total Upload + 合計アップロード - + Total Download - Total Download + 合計ダウンロード @@ -2911,12 +3384,12 @@ p, li { white-space: pre-wrap; } Stream Settings Widget - Stream Settings Widget + ストリーム設定ウィジェット Transport Protocol - Transport Protocol + 転送プロトコル @@ -2926,17 +3399,17 @@ p, li { white-space: pre-wrap; } Enabled - Enabled + 有効 TLS Settings - TLS Settings + TLS設定 Server - Server + サーバ @@ -2946,12 +3419,12 @@ p, li { white-space: pre-wrap; } SOCK Options - SOCK Options + SOCKオプション Mark - Mark + マーク @@ -2961,32 +3434,32 @@ p, li { white-space: pre-wrap; } Protocol Settings - Protocol Settings + プロトコル設定 Request - Request + リクエスト Type - Type + 種類 Response - Response + レスポンス Path - Path + パス Host - Host + ホスト @@ -2996,7 +3469,7 @@ p, li { white-space: pre-wrap; } Headers - Headers + ヘッダー @@ -3011,37 +3484,37 @@ p, li { white-space: pre-wrap; } Uplink Capacity (MB/s) - Uplink Capacity (MB/s) + アップリンク容量 (MB/s) Congestion - Congestion + 輻輳制御 Downlink Capacity (MB/s) - Downlink Capacity (MB/s) + ダウンリンク容量 (MB/s) Read Buffer Size (MB) - Read Buffer Size (MB) + 読み取りバッファサイズ (MB) Write Buffer Size (MB) - Write Buffer Size (MB) + 書き込みバッファサイズ (MB) Security - Security + セキュリティ Key - Key + キー @@ -3051,115 +3524,123 @@ p, li { white-space: pre-wrap; } Edit - Edit + 編集 Reset - Reset + リセット Allow Insecure Certificates - Allow Insecure Certificates + 安全でない証明書を許可する tProxy Mode - tProxy Mode + tProxy モード SubscribeEditor - - - - Renaming a subscription - Renaming a subscription + Renaming a subscription - The subscription name is invalid, please try another. - The subscription name is invalid, please try another. + The subscription name is invalid, please try another. - New name of this subscription has been used already, please suggest another one - New name of this subscription has been used already, please suggest another one + New name of this subscription has been used already, please suggest another one - Failed to rename a subscription, this is an unknown error. - Failed to rename a subscription, this is an unknown error. + Failed to rename a subscription, this is an unknown error. - Successfully renamed a subscription - Successfully renamed a subscription + Successfully renamed a subscription - Update Subscription - Update Subscription + Update Subscription - Would you like to reload this subscription from the Url? - Would you like to reload this subscription from the Url? + Would you like to reload this subscription from the Url? - Updating subscriptions - Updating subscriptions + Updating subscriptions - Failed to process the result from the upstream, please check your Url. - Failed to process the result from the upstream, please check your Url. + Failed to process the result from the upstream, please check your Url. + + + + Reload Subscription + サブスクリプションを更新 + + + + Would you like to reload the subscription? + サブスクリプションを更新しますか? + + + + Deleting a subscription + サブスクリプションを削除する + + + + All connections will be moved to default group, do you want to continue? + すべての接続がデフォルトグループに移動します。続行しますか? misc - + B bytes B - + KiB kibibytes (1024 bytes) KiB - + MiB mebibytes (1024 kibibytes) MiB - + GiB gibibytes (1024 mibibytes) GiB - + TiB tebibytes (1024 gibibytes) TiB - + PiB pebibytes (1024 tebibytes) PiB - + EiB exbibytes (1024 pebibytes) EiB @@ -3181,72 +3662,70 @@ p, li { white-space: pre-wrap; } Subscription List - Subscription List + サブスクリプションの一覧 - A - A + A Add Subscription - Add Subscription + サブスクリプションを追加 Remove Subscription - Remove Subscription + サブスクリプションを削除 - D - D + D Subscription Details - Subscription Details + サブスクリプションの詳細 Subscription Name - Subscription Name + 名称 Subscription Address - Subscription Address + アドレス Update Interval - Update Interval + 更新間隔 Days - Days + 日ごと Last Updated - Last Updated + 最終更新 Connection List - Connection List + 接続リスト Update Subscription With System Proxy - Update Subscription With System Proxy + システムプロキシを使用したサブスクリプションの更新 Update Subscription Data - Update Subscription Data + サブスクリプションデータの更新 - \ No newline at end of file + diff --git a/translations/ru_RU.ts b/translations/ru_RU.ts index 6d46f6c7..69b4522c 100644 --- a/translations/ru_RU.ts +++ b/translations/ru_RU.ts @@ -1,79 +1,269 @@ - + + + + + AutoCompleteTextEdit + + + This TextEdit provides autocompletions for words that have more than 3 characters. You can trigger autocompletion using + + + ConfigExporter - Save Image - Сохранить изображение + Сохранить изображение - - Share Connection - Поделиться подключением + Поделиться подключением - Image has been copied to the clipboard. - Изображение было скопировано в буфер обмена. + Изображение было скопировано в буфер обмена. - VMess string has been copied to the clipboard. - Строка VMess была скопирована в буфер обмена. + Строка VMess была скопирована в буфер обмена. + + + + ConnectionInfoWidget + + + Form + + + + + Configuration Details + + + + + Connect/Disconnect + + + + + Edit Connection + + + + + Edit Connection as JSON + + + + + Latency Test + Тест задержки + + + + Delete Connection + + + + + Group + + + + + type + + + + + Protocol + Протокол + + + + proto + + + + + Address + Адрес + + + + addr + + + + + Port + Порт + + + + port + + + + + Link + + + + + QR Code + + + + + Group Name + + + + + Subscription Link + Подписка + + + + Share Link + Поделитесь ссылкой + + + + (Ignored %1 complex config(s)) + + + + + Not a subscription + + + + + Delete an item + + + + + Are you sure to delete the current item? + + + + + ConnectionItemWidget + + + Not Tested + + + + + + ms + мс + + + + + Type: + + + + + Testing... + Тестирование... + + + + Error + ошибка + + + + connection + + + + + connections + + + + + ConnectionWidget + + + Form + + + + + Connection Name + + + + + 500ms + + + + + Type: vmess + tls + ws + + + + + 0KB / 0KB + + + + + OK + OK ExportConfigWindow - Export Config - Экспорт конфигурации + Экспорт конфигурации - Share Options - Открыть совместный доступ к опциям + Открыть совместный доступ к опциям - Connection String - Строка подключения + Строка подключения - Copy Link - Скопируйте ссылку + Скопируйте ссылку - Save Image - Сохранить изображение + Сохранить изображение - Copy Image - Копировать изображение + Копировать изображение - OK - OK + OK FlowScene - - Open Flow Scene - Файл сцены открытого потока + Файл сцены открытого потока - - Flow Scene Files (*.flow) - Файл сцены потока (*.flow) + Файл сцены потока (*.flow) @@ -134,14 +324,12 @@ Выбрать - Inbound - Входящее + Входящее - Keep imported inbound settings - Сохранить импортированные параметры + Сохранить импортированные параметры @@ -153,6 +341,11 @@ Open in JSON Editor Открыть в JSON редакторе + + + Import as Complex Config (Manually edit route rules and inbounds) + + VMess / QRCode @@ -239,64 +432,64 @@ Отмена - + Select file to import Выберите файл для Импорта - + Capture QRCode Захват QRCode - + Cannot find a valid QRCode from this region. Не удается найти QRCode из этой области. - + Import config file Выберите файл конфигурации - + Failed to check the validity of the config file. Не удалось проверить правильность файла конфигурации. - + Select an image to import Выберите изображение для импорта - + QRCode scanning failed Ошибка сканирования QRCode - + Cannot find any QRCode from the image. Не удается найти QRCode в изображении. - - - + + + Edit file as JSON Изменить JSON файл - + Provided file not found: Предоставленный файл не найден: - + The file you selected has json syntax error. Continue editing may make you lose data. Would you like to continue? Выбранный вами файл содержит синтаксическую ошибку json. Изменение может привести к потере данных. Вы хотите продолжить? - + Failed to save file, please check if you have proper permissions Не удалось сохранить файл, пожалуйста, проверьте, есть ли у вас необходимые разрешения @@ -529,41 +722,41 @@ СЕКРЕТ - + Inbound type not supported Тип файла не поддерживается - + The inbound type is not supported by Qv2ray (yet). Please use JsonEditor to change the settings Входящий тип не поддерживается Qv2ray (еще). Пожалуйста, используйте JsonEditor для изменения настроек - + Inbound: Входящий: - - + + Removing a user Удаление пользователя - - + + You haven't selected a user yet. Вы еще выбрали пользователя'т. - - + + Add a user Добавить пользователя - - + + This user exists already. Этот пользователь уже существует. @@ -571,9 +764,8 @@ JsonEditor - Dialog - Диалог + Диалог @@ -596,30 +788,44 @@ Редактор Json - - + + Json Contains Syntax Errors Json содержит ошибки синтаксиса - + Original Json may contain syntax errors. Json tree is disabled. Оригинальный Json может содержать ошибки синтаксиса. Структура Json отключена. - + You must correct these errors before continue. Вы должны исправить эти ошибки перед продолжением. - + Syntax Errors Синтаксические ошибки - + + Please fix the JSON errors or remove the comments before continue + + + Please fix the JSON errors before continue - Пожалуйста, исправьте JSON ошибки перед продолжением + Пожалуйста, исправьте JSON ошибки перед продолжением + + + + JSON Editor + + + + + Remove All Comments + @@ -630,27 +836,23 @@ Qv2ray - - + Connect Подключение - - + Disconnect Отключен - - + Reconnect Переподключить - Clear Log - Очистить логи + Очистить логи @@ -658,79 +860,64 @@ Подписки - Stopped - Остановлен + Остановлен - Host List - Список Узлов + Список Узлов - Import connection - Импорт соединения + Импорт соединения - Duplicate connection - Дублировать подключение + Дублировать подключение - Delete a connection - Удалить подключение + Удалить подключение - Edit connection - Изменить подключение + Изменить подключение - Config Details - Детали конфигурации + Детали конфигурации - Config Type - Тип конфигурации + Тип конфигурации - Protocol - Протокол + Протокол - Address - Адрес + Адрес - Port Number - Порт + Порт - Latency - Задержка + Задержка - Operations - Операции + Операции - Edit connection as JSON - Изменить соединение как JSON + Изменить соединение как JSON - Log (click to switch log source) - Журнал (нажмите, чтобы переключить источник журнала) + Журнал (нажмите, чтобы переключить источник журнала) @@ -739,50 +926,100 @@ - + Preferences Настройки - Duplicate - Дублировать + Дублировать - Delete - Удалить + Удалить - + Edit Изменить - Edit JSON - Изменить JSON + Изменить JSON - Ping Test - Ping Тест + Ping Тест - Share - Поделиться + Поделиться + + + Speed Graph + График скорости - Speed Graph - График скорости + Locate Current Connection + + + + + Search + + + + + Import Connection + + + + + Sort + + + + + Click to toggle show/hide + + + + + Speed Graph + + + + + Clear chart data + + + + + Log + + + + + Clear log + + + + + + Not Connected + Speed Скорость + + + Upload/Download speed + + 0.00 B/s @@ -795,6 +1032,11 @@ Data Данные + + + Upload/Download Data + + 0.00 B @@ -803,398 +1045,406 @@ 0.00 B - #ManuallyCreateConnection - #ManuallyCreateConnection + #ManuallyCreateConnection - #ImportConnection - #ImportConnection + #ImportConnection - #Exit - #Выход + #Выход - #Preferences - #Параметры + #Параметры - #Start - #Запустить + #Запустить - #Stop - #Стоп + #Стоп - #Restart - #Перезапуск + #Перезапуск - - + + Hide Скрыть - + Quit Выход - + + Edit as JSON + + + + Rename Переименование - + + Duplicate to the Same Group + + + + + Delete Connection + + + + Connect to this Подключиться к этому - + Edit as Complex Config Изменить как Complex Config - Edit as Json - Изменить как Json + Изменить как Json - Share as QRCode/VMess URL - Поделиться QRCode/VMess URL + Поделиться QRCode/VMess URL - Subscription: - Подписка: + Подписка: - - - + + Show Показать - Autostarting a config - Автозапуск конфигурации + Автозапуск конфигурации - Could not find a specified config named: - Не удалось найти указанное имя конфигурации: + Не удалось найти указанное имя конфигурации: - - No connection selected! - Не выбрано соединение! + Не выбрано соединение! - - Please select a config from the list. - Пожалуйста, выберите конфигурацию из списка + Пожалуйста, выберите конфигурацию из списка - + + Sort connection list. + + + + + By connection name, A-Z + + + + + By connection name, Z-A + + + + + By latency, Ascending + + + + + By latency, Descending + + + + + By data, Ascending + + + + + By data, Descending + + + + Update Обновить - + Found a new version: Найдена новая версия: - + Download Link: Ссылка для скачивания: - - - - + + + + Connected: Подключен: - - + + Configuring PAC Настройка PAC - + Could not start PAC server as it is configured to use SOCKS, but it is not enabled Не удалось запустить PAC сервер, так как он настроен на использование SOCKS, но он не включен - + Could not start PAC server as it is configured to use HTTP, but it is not enabled Не удалось запустить PAC сервер, так как он настроен на использование HTTP, но он не включен - + + Duplicating Connection(s) + + + + + Are you sure to duplicate these connection(s)? + + + + + (Copy) + + + + PAC Processing Failed Ошибка обработки PAC - Please reset the settings in Preference Window - Пожалуйста, сбросьте настройки в окне Preference + Пожалуйста, сбросьте настройки в окне Preference - System proxy cleared. - Системный прокси очищен. + Системный прокси очищен. - + HTTP or SOCKS inbound is not properly configured for PAC Входящие HTTP или SOCKS не настроены должным образом для PAC - + Qv2ray will continue, but will not set system proxy. Qv2ray будет работать, но не сможет изменить системный прокси. - + Cannot set system proxy Не удается задать системный прокси - + Both HTTP and SOCKS inbounds are not enabled И HTTP, и SOCKS отключены - + + Didn't set proxy for complex config. + + + System proxy settings applied. - Применены настройки системного прокси. + Применены настройки системного прокси. - Cannot set proxy for complex config. - Не удается установить прокси для комплексной конфигурации. + Не удается установить прокси для комплексной конфигурации. - + Update Subscriptions Обновить подписку - + There are subscriptions need to be updated, please go to subscriptions window to update them. Есть подписки, которые необходимо обновить, перейдите в окно подписок, чтобы обновить их. - + These subscriptions are out-of-date: Эти подписки устарели: - Disconnected - Отключен + Отключен - Complex - Сложный + Сложный - Simple - Простой + Простой - No data - Нет данных + Нет данных - ms - мс + мс - There're no support of sharing configs other than vmess and shadowsocks - Нет поддержки обмена конфигами кроме VMess и Shadowsocks. + Нет поддержки обмена конфигами кроме VMess и Shadowsocks. - - - - - - N/A - N/A + N/A - - - Rename a Connection - Переименовать соединение + Переименовать соединение - + V2ray vcore terminated. V2ray ядро прекращено. - + V2ray vcore terminated unexpectedly. Ядро V2ray неожиданно прервано. - + To solve the problem, read the V2ray log in the log text browser. Чтобы решить эту проблему, прочитайте журнал V2ray в текстовом браузере журнала. - + Enable System Proxy Включить системный прокси - + Disable System Proxy Отключить системный прокси - + System Proxy Системный прокси - Ping - Ping + Ping - Ping All - Пингуть все + Пингуть все - - Subscription - Подписка + Подписка - Already connected to: - Уже подключен к: + Уже подключен к: - + Disconnected from: Отключен от: - The name cannot be empty - Имя не может быть пустым + Имя не может быть пустым - The name has been used already, Please choose another. - Имя уже используется, пожалуйста, выберите другое. + Имя уже используется, пожалуйста, выберите другое. - The name you suggested is not valid, please try another. - Предложенное вами имя неверно, пожалуйста, попробуйте другое. + Предложенное вами имя неверно, пожалуйста, попробуйте другое. - + Removing Connection(s) Удаление подключения(й) - + Are you sure to remove selected connection(s)? Вы уверены, что хотите удалить выбранные подключение(и)? - - Removing this Connection - Удаление этого соединения + Удаление этого соединения - - Failed to delete connection file, please delete manually. - Не удалось удалить файл подключения, пожалуйста, удалите вручную. + Не удалось удалить файл подключения, пожалуйста, удалите вручную. - Removing a subscription config - Удаление конфигурации подписки + Удаление конфигурации подписки - Do you want to remove the config loaded from a subscription? - Вы хотите удалить конфигурацию, загруженную из подписок? + Вы хотите удалить конфигурацию, загруженную из подписок? - - - No Config Selected - Не выбрана конфигурация + Не выбрана конфигурация - - - Please Select a Config - Пожалуйста, выберите конфигурацию + Пожалуйста, выберите конфигурацию - You are about to run latency test on all servers, do you want to continue? - Вы собираетесь запустить тест задержки на всех серверах, вы хотите продолжить? + Вы собираетесь запустить тест задержки на всех серверах, вы хотите продолжить? - Testing... - Тестирование... + Тестирование... - - Latency Test - Тест задержки + Тест задержки - Failed to test latency for this connection. - Не удалось протестировать задержку для этого подключения. + Не удалось протестировать задержку для этого подключения. - Share Connection - Поделиться подключением + Поделиться подключением @@ -1329,11 +1579,11 @@ PreferencesWindow - - - - - + + + + + Preferences Настройки @@ -1697,6 +1947,71 @@ UDP Local IP UDP Локальный IP-адрес + + + Transparent Proxy Settings + + + + + All settings below will only be applied onto simple connection. + + + + + Add Docodemo-door inbound + + + + + Address + Адрес + + + + TCP + TCP + + + + UDP + UDP + + + + Follow Redirect + Использовать переадресацию + + + + Override Connection SockOpt Settings + + + + + TCP Fast Open + TCP Fast Open + + + + Mark + Mark + + + + Match Contains + + + + + TProxy Mode + + + + + Settings will be added to the StreamSettings for matched connections. + + - @@ -1739,13 +2054,13 @@ - + Bold Жирный - + Italic Курсив @@ -1855,156 +2170,154 @@ Об инструментарии Qt - + Use Darkmode Theme Использовать темную тему - + Page Стр. - + Item(s) Объекты - - + + Enable tProxy Support Включить tProxy поддержку - + to this path: на этот путь: - + Qv2ray Network Toolbar is disabled and still under test. Add --withToolbarPlugin to enable. Панель инструментов сети Qv2ray отключена и все еще тестируется. Добавьте --withToolbarPlugin для включения. - + Duplicated port numbers detected, please check the port number settings. Обнаружены дублированные номера портов, проверьте настройки номера порта. - + Invalid inbound listening address. Неверный входящий адрес прослушивания. - + Open V2ray assets folder Откройте папку активов v2ray - + Open V2ray core file Открыть основной файл V2ray - + This will append capabilities to the V2ray executable. Это добавит возможности к исполняемому файлу V2ray. - + Qv2ray will copy your V2ray core to this path: Qv2ray скопирует ваше ядро V2ray по этому пути: - + If anything goes wrong after enabling this, please check issue #57 or the link below: Если после включения этого параметра что-то пойдет не так, проверьте проблему № 57 или ссылку ниже: - + Qv2ray cannot copy one or both V2ray files from: Qv2ray не может скопировать один или оба файла V2ray из: - - + + Failed to setcap onto V2ray executable. You may need to run `setcap` manually. Не удалось установить setcap на исполняемый файл V2ray. Возможно, вам придется запустить `setcap` вручную. - + tProxy is not supported on macOS and Windows tProxy не поддерживается на macOS и Windows - + Apply network toolbar settings Применить настройки панели инструментов сети - + All other modified settings will be applied as well after this object. Все остальные измененные настройки будут применены и после этого объекта. - + Do you want to continue? Вы хотите продолжить? - Dark Mode - Тёмный режим + Тёмный режим - Please restart Qv2ray to fully apply this feature. - Пожалуйста, перезапустите Qv2ray, чтобы полностью применить эту функцию. + Пожалуйста, перезапустите Qv2ray, чтобы полностью применить эту функцию. - + Select GFWList in base64 Выберите GFWList в base64 - - + + Download GFWList Скачать GFWList - + Operation is cancelled. Операция отменена. - + Successfully downloaded GFWList. Успешно загружено %1$s. - + Start with boot Автозапуск - + Failed to set auto start option. Не удалось установить опцию автозапуска. - - + + V2ray Core Settings Настройки ядра V2ray - + V2ray path configuration check passed. Проверка конфигурации пути V2ray пройдена. - + Current version of V2ray is: Текущая версия V2ray: @@ -2023,7 +2336,7 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'WenQuanYi Micro Hei'; font-size:10pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'WenQuanYi Micro Hei'; font-size:10pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -2035,167 +2348,193 @@ p, li { white-space: pre-wrap; } QObject - + Unsupported share link format. Неподдерживаемый формат ссылки. - + SS URI is too short URI Shadowsocks слишком короткий. - - + + Can't find the colon separator between method and password Не удается найти разделитель двоеточий между методом и паролем - + Can't find the at separator between password and hostname Не удается найти разделитель между паролем и именем хоста - + Can't find the colon separator between hostname and port Не удается найти разделитель двоеточий между именем хоста и портом - + VMess string should start with 'vmess://' VMess строка должна начинаться с 'vmess://' - + VMess string should be a valid base64 string VMess строка должна быть корректной строкой base64 - + JSON should not be empty JSON не должен быть пустым - + Warning Внимание - + Qv2ray cannot load the config file from here: Qv2ray не может загрузить файл конфигурации отсюда: - + Cannot Start Qv2ray Невозможно запустить Qv2ray - + Cannot find a place to store config files. Не удается найти место для хранения конфигурационных файлов. - + Qv2ray has searched these paths below: Qv2ray искал эти пути ниже: - - - + + It usually means you don't have the write permission to all of those locations. + + + + + + Qv2ray will now exit. Qv2ray теперь выйдет. - + Failed to initialise Qv2ray Не удалось инициализировать Qv2ray - Failed to determine the location of config file. - Не удалось определить местоположение конфигурационного файла. + Не удалось определить местоположение конфигурационного файла. - + Please report if you think it's a bug. Пожалуйста, сообщите, если вы считаете об этом, если это ошибка. - + You cannot run Qv2ray as root, please use --I-just-wanna-run-with-root if you REALLY want to do so. Вы не можете запустить Qv2ray как root, пожалуйста, используйте --I-just-wanna-run-with-root, если вы хотите это сделать. - + --> USE IT AT YOUR OWN RISK! --> ИСПОЛЬЗУЙТЕ ЕГО НА СВОЙ СТРАХ И РИСК! - Cannot load languages - Не удается загрузить языки + Не удается загрузить языки - Qv2ray will continue running, but you cannot change the UI language. - Qv2ray продолжит работу, но вы не сможете изменить язык интерфейса. + Qv2ray продолжит работу, но вы не сможете изменить язык интерфейса. - + Qv2ray Cannot Continue Qv2ray не может продолжить - + You are running a lower version of Qv2ray compared to the current config file. Вы используете более низкую версию Qv2ray по сравнению с текущим файлом конфигурации. - + Please check if there's an issue explaining about it. Пожалуйста, проверьте, есть ли проблема с объяснением этого. - + Or submit a new issue if you think this is an error. Или отправьте новую проблему, если вы считаете, что это ошибка. - + Dependency Missing Зависимость отсутствует - + This could be caused by a missing of `openssl` package in your system. Это может быть вызвано отсутствием пакета `openssl` в вашей системе. - + If you are using an AppImage from Github Action, please report a bug. Если вы используете AppImage из Github Action, пожалуйста, сообщите об ошибке. - + Cannot find openssl libs Не удается найти openssl libs - + + Failed to determine the location of config file: + + + + + Qv2ray has found a config file, but it failed to be loaded due to some errors. + + + + + A workaround is to remove the this file and restart Qv2ray: + + + + + Debug version + + + + Technical Details Технические детали - + + Not connected + + + + Connected Подключено - Disconnected - Отключен + Отключен @@ -2238,14 +2577,17 @@ p, li { white-space: pre-wrap; } Общая скорость загрузки - - Upload Speed for Specific Tag - Скорость отдачи для конкретного тега + + Current Connection Latency + + + + Upload Speed for Specific Tag + Скорость отдачи для конкретного тега - Download Speed for Specific Tag - Скорость отдачи для конкретного тега + Скорость отдачи для конкретного тега @@ -2258,149 +2600,276 @@ p, li { white-space: pre-wrap; } Всего загружено данных - Uploaded Data for Specific Tag - Загруженные данные для конкретного тега + Загруженные данные для конкретного тега - Downloaded Data for Specific Tag - Загруженные данные для конкретного тега + Загруженные данные для конкретного тега - - Editing a subscription config - Редактирование конфигурации подписки + Редактирование конфигурации подписки - You are trying to edit a config loaded from subscription. - Вы пытаетесь изменить конфигурацию, загруженную из подписок. + Вы пытаетесь изменить конфигурацию, загруженную из подписок. - All changes will be overwritten when the subscriptions are updated next time. - Все изменения будут перезаписаны при следующем обновлении подписки. + Все изменения будут перезаписаны при следующем обновлении подписки. - Are you still going to do so? - Вы все еще собираетесь сделать это? + Вы все еще собираетесь сделать это? - You should not modity this property of a config from a subscription - Вы не должны модифицировать это свойство конфигурации из подписки + Вы не должны модифицировать это свойство конфигурации из подписки - + - + N/A N/A - + Qv2ray - A cross-platform Qt frontend for V2ray. Qv2ray - кросс-платформенный Qt фронтенд для V2ray. - + Disable gRPC API subsystems. Отключить подсистемы gRPC API. - + Explicitly run Qv2ray as root. Явно запускайте Qv2ray как root. - + Enable Debug Output Включить отладочный вывод - + Enable Qv2ray network toolbar plugin Включить плагин панели инструментов сети Qv2ray + + + invalid ssd link: json: field %1 must exist + + + + + invalid ssd link: json: field %1 must be valid port number + + + + + invalid ssd link: json: field %1 must be of type 'string' + + + + + invalid ssd link: json: field %1 must be an array + + + + + skipping invalid ssd server: server must be an object + + + + + skipping invalid ssd server: missing required field %1 + + + + + skipping invalid ssd server: field %1 should be of type 'string' + + + + + Invalid ssd link: should begin with ssd:// + + + + + Invalid ssd link: base64 parse failed + + + + + Invalid ssd link: json parse failed: + + + + + Invalid ssd link: found non-object json, aborting + + + + + Invalid ssd link: rc4-md5 encryption is not supported by v2ray-core + + + + + Invalid port encountered. using fallback value. + + + + + Invalid name encountered. using fallback value. + + + + + Invalid ratio encountered. using fallback value. + + + + + Default Group + + + + + Configuration Upgrade Failed + + + + + Unsupported config version number: + + + + + Please upgrade firstly up to Qv2ray v2.0/v2.1 and try again. + + + + + %1 - %2 (rate %3) + + + + + (Complex config) + + Qv2ray::components::pac::PACServer - + PAC Handler PAC Handler - + Failed to listen PAC request on this port, please verify the permissions Не удалось прослушать PAC-запрос для этого порта, проверьте разрешения + + Qv2ray::core::handlers::QvConfigHandler + + + + Default Group + + + + + File does not exist. + + + + + + Group does not exist + + + Qv2ray::core::kernel::V2rayKernelInstance - + V2ray core executable not found. Исполняемый файл ядра V2ray не найден. - + V2ray core file cannot be opened, please ensure there's a file instead of a folder. Файл ядра V2ray не может быть открыт, убедитесь, что вместо папки есть файл. - + V2ray assets path is not valid. Недопустимый путь к ресурсам V2ray. - + No geoip.dat in assets path. Нет geoip.dat в пути активов. - + No geosite.dat in assets path. Нет geosite.dat в пути активов. - + V2ray core failed with an exit code: Ядро V2ray вышло из строя с кодом выхода: - + V2ray core returns empty string. Ядро V2ray возвращает пустую строку. - + Configuration Error Ошибка конфигурации - + Cannot start V2ray Невозможно запустить V2ray - + V2ray core settings is incorrect. Настройки ядра V2ray неверны. - + The error is: Ошибка: + + + Invalid V2ray Instance Status. + + + + + V2ray kernel failed to start. + + QvInboundNodeModel - + Missing or incorrect inputs Отсутствующие или неправильные входы @@ -2408,7 +2877,7 @@ p, li { white-space: pre-wrap; } QvOutboundNodeModel - + Missing or incorrect inputs Отсутствующие или неправильные входы @@ -2416,7 +2885,7 @@ p, li { white-space: pre-wrap; } QvRuleNodeDataModel - + Missing or incorrect inputs Отсутствующие или неправильные входы @@ -2425,7 +2894,7 @@ p, li { white-space: pre-wrap; } RouteEditor - + Route Editor Редактор маршрута @@ -2665,182 +3134,186 @@ p, li { white-space: pre-wrap; } Список пользователей - - - + + + OK OK - + Cannot Edit Не удается изменить - + This outbound entry is not supported by the GUI editor. Эта исходящая запись не поддерживается редактором GUI. - - + + We will launch Json Editor instead. Запущен Json редактор. - + Show rule details Показать подробности правила - + A rule cannot be found: Правило не может быть найдено: - - - + + + Protocol list changed: Список протоколов изменен: - + Balancer is empty, not processing. Балансер пуст и не обрабатывается. - + Default rule Правило по умолчанию - + rule равило - + No Inbound Входящий не найден - + No inbound item found: Входящий элемент не найден: - - - + + The new tag has been used, we appended a postfix. Новый тег был использован, поэтому мы добавили постфикс. - + + The new tag has been used, we appended a random string to the tag. + + + + To make this rule ready to use, you need to connect it to an outbound node. Чтобы это правило было готовым к использованию, необходимо подключить его к исходящему узлу. - + Remove Items Удалить элементы - - + + Please select a node from the graph to continue. Пожалуйста, выберите узел на графике для продолжения. - + Error ошибка - + Qv2ray entered an unknown state. Qv2ray вошел в неизвестное состояние. - + Edit Inbound/Outbound Тип: входящий / исходящий - - + + Edit Inbound Изменить входящий - - + + No inbound tag found: Входящий тег не найден: - - + + Opening JSON editor Открыть в JSON редакторе - + Unsupported Outbound Type Неподдерживаемый исходящий тип - + Opening default outbound editor. Открытие стандартного редактора исходящих соединений. - - - + + + Renaming a tag Переименовать тег - + New tag is empty, please try another. Новый тег пуст, попробуйте другой. - + New tag is the same as the original one. Новый тег такой же, как и оригинальный. - + Duplicate rule tag detected, please try another. Обнаружен повторяющийся тег правила, попробуйте другой. - + Added DIRECT outbound Добавлен исходящий DIRECT - + Currently, this type of outbound is not supported by the editor. В настоящее время этот тип outbound не поддерживается в этой версии программы. - + Opening default inbound editor Открытие стандартного входящего редактора - + Removed a balancer entry. Удалена запись балансировщика. - - - + + + Rename tags Переименовать теги @@ -2896,12 +3369,12 @@ p, li { white-space: pre-wrap; } SpeedPlotView - + Total Upload Всего загружено - + Total Download Всего скачать @@ -3072,94 +3545,102 @@ p, li { white-space: pre-wrap; } SubscribeEditor - - - - Renaming a subscription - Переименование подписки + Переименование подписки - The subscription name is invalid, please try another. - Недопустимое имя подписки, пожалуйста, попробуйте другое. + Недопустимое имя подписки, пожалуйста, попробуйте другое. - New name of this subscription has been used already, please suggest another one - Новое имя этой подписки уже используется, пожалуйста, выберите другое имя + Новое имя этой подписки уже используется, пожалуйста, выберите другое имя - Failed to rename a subscription, this is an unknown error. - Не удалось переименовать подписку, это неизвестная ошибка. + Не удалось переименовать подписку, это неизвестная ошибка. - Successfully renamed a subscription - Подписка успешно переименована + Подписка успешно переименована - Update Subscription - Обновить подписку + Обновить подписку - Would you like to reload this subscription from the Url? - Вы хотите перезагрузить эту подписку с Url? + Вы хотите перезагрузить эту подписку с Url? - Updating subscriptions - Обновление подписок + Обновление подписок - Failed to process the result from the upstream, please check your Url. - Не удалось обработать результат из апстрима, проверьте ваш URL. + Не удалось обработать результат из апстрима, проверьте ваш URL. + + + + Reload Subscription + + + + + Would you like to reload the subscription? + + + + + Deleting a subscription + + + + + All connections will be moved to default group, do you want to continue? + misc - + B bytes B - + KiB kibibytes (1024 bytes) KiB - + MiB mebibytes (1024 kibibytes) MiB - + GiB gibibytes (1024 mibibytes) GiB - + TiB tebibytes (1024 gibibytes) TiB - + PiB pebibytes (1024 tebibytes) PiB - + EiB exbibytes (1024 pebibytes) EiB @@ -3184,9 +3665,8 @@ p, li { white-space: pre-wrap; } Список подписок - A - A + A @@ -3199,9 +3679,8 @@ p, li { white-space: pre-wrap; } Удалить подписку - D - D + D @@ -3249,4 +3728,4 @@ p, li { white-space: pre-wrap; } Обновить данные подписки - \ No newline at end of file + diff --git a/translations/zh_CN.ts b/translations/zh_CN.ts index 9b1177f3..bb565394 100644 --- a/translations/zh_CN.ts +++ b/translations/zh_CN.ts @@ -1,79 +1,269 @@ - + + + - ConfigExporter + AutoCompleteTextEdit - - Save Image - 保存图片 - - - - - Share Connection - 分享连接 - - - - Image has been copied to the clipboard. - 图像已复制到剪贴板。 - - - - VMess string has been copied to the clipboard. - VMess 链接已复制到剪贴板。 + + This TextEdit provides autocompletions for words that have more than 3 characters. You can trigger autocompletion using + This TextEdit provides autocompletions for words that have more than 3 characters. You can trigger autocompletion using - ExportConfigWindow + ConfigExporter - - Export Config - 导出配置 - - - - Share Options - 分享选项 - - - - Connection String - 连接字符串 - - - - Copy Link - 复制链接 - - - Save Image - 保存图片 + 保存图片 - - Copy Image - 复制图像 + Share Connection + 分享连接 - + Image has been copied to the clipboard. + 图像已复制到剪贴板。 + + + VMess string has been copied to the clipboard. + VMess 链接已复制到剪贴板。 + + + + ConnectionInfoWidget + + + Form + 窗体 + + + + Configuration Details + 配置详情 + + + + Connect/Disconnect + 连接/断开 + + + + Edit Connection + 编辑连接 + + + + Edit Connection as JSON + 将连接编辑为 JSON + + + + Latency Test + 测试延迟 + + + + Delete Connection + 删除连接 + + + + Group + 分组 + + + + type + + + + + Protocol + 协议 + + + + proto + + + + + Address + 地址 + + + + addr + + + + + Port + 端口 + + + + port + + + + + Link + 链接 + + + + QR Code + 二维码 + + + + Group Name + 分组名称 + + + + Subscription Link + 订阅链接 + + + + Share Link + 分享链接 + + + + (Ignored %1 complex config(s)) + (已忽略 %1 个复杂配置) + + + + Not a subscription + 不是订阅 + + + + Delete an item + 删除项目 + + + + Are you sure to delete the current item? + 您确定要删除当前项目吗? + + + + ConnectionItemWidget + + + Not Tested + 未测试 + + + + + ms + ms + + + + + Type: + 类型: + + + + Testing... + 正在测试… + + + + Error + 错误 + + + + connection + + + + + connections + + + + + ConnectionWidget + + + Form + 窗体 + + + + Connection Name + 连接名称 + + + + 500ms + 500ms + + + + Type: vmess + tls + ws + 类型: vmess + tls + ws + + + + 0KB / 0KB + 0KB / 0KB + + + OK - FlowScene + ExportConfigWindow - - - Open Flow Scene - 打开流场景 + Export Config + 导出配置 + + + Share Options + 分享选项 + + + Connection String + 连接字符串 + + + Copy Link + 复制链接 + + + Save Image + 保存图片 + + + Copy Image + 复制图像 + + + OK + + + + + FlowScene + + Open Flow Scene + 打开流场景 - - Flow Scene Files (*.flow) - 流场景文件 (*.flow) + 流场景文件 (*.flow) @@ -101,7 +291,7 @@ secs - + @@ -134,14 +324,12 @@ 选择 - Inbound - 入站 + 入站 - Keep imported inbound settings - 保留导入的入站设置 + 保留导入的入站设置 @@ -153,6 +341,11 @@ Open in JSON Editor 在 JSON 编辑器中打开 + + + Import as Complex Config (Manually edit route rules and inbounds) + 作为复杂配置导入(手动编辑路由规则与入站) + VMess / QRCode @@ -239,66 +432,66 @@ 取消 - + Select file to import 选择要导入的文件 - + Capture QRCode 抓取二维码 - + Cannot find a valid QRCode from this region. 无法从这个区域找到有效的二维码。 - + Import config file 导入配置文件 - + Failed to check the validity of the config file. 检查配置文件有效性时失败。 - + Select an image to import 选择要导入的图像 - + QRCode scanning failed 二维码扫描失败 - + Cannot find any QRCode from the image. 无法从图像中找到任何二维码。 - - - + + + Edit file as JSON 以 JSON 格式编辑文件 - + Provided file not found: 找不到提供的文件: - + The file you selected has json syntax error. Continue editing may make you lose data. Would you like to continue? 您选择的文件有 json 语法错误。继续编辑可能会使您丢失数据。您想要继续吗? - + Failed to save file, please check if you have proper permissions - 保存文件失败,请检查您是否拥有所需的权限。 + 保存文件失败,请检查您是否拥有所需的权限 @@ -529,41 +722,41 @@ SECRET - + Inbound type not supported 不支持入站类型 - + The inbound type is not supported by Qv2ray (yet). Please use JsonEditor to change the settings Qv2ray (暂时)不支持这个入站类型。请使用 JsonEditor 更改设置 - + Inbound: 入站: - - + + Removing a user 移除用户 - - + + You haven't selected a user yet. 你尚未选择一个用户。 - - + + Add a user 添加用户 - - + + This user exists already. 此用户已存在。 @@ -571,9 +764,8 @@ JsonEditor - Dialog - 对话框 + 对话框 @@ -596,30 +788,44 @@ Json 编辑器 - - + + Json Contains Syntax Errors JSON 包含语法错误 - + Original Json may contain syntax errors. Json tree is disabled. 原 JSON 可能包含语法错误,JSON 树被禁用。 - + You must correct these errors before continue. 您必须先更正这些错误才能继续。 - + Syntax Errors 语法错误 - + + Please fix the JSON errors or remove the comments before continue + 请先修复 JSON 错误或移除其中的注释再继续 + + Please fix the JSON errors before continue - 请先修复 JSON 错误,然后继续。 + 请先修复 JSON 错误,然后继续。 + + + + JSON Editor + JSON 编辑器 + + + + Remove All Comments + 移除所有注释 @@ -630,27 +836,23 @@ Qv2ray - - + Connect 连接 - - + Disconnect 断开连接 - - + Reconnect 重新连接 - Clear Log - 清除日志 + 清除日志 @@ -658,79 +860,64 @@ 订阅 - Stopped - 已停止 + 已停止 - Host List - 主机列表 + 主机列表 - Import connection - 导入连接 + 导入连接 - Duplicate connection - 复制连接 + 复制连接 - Delete a connection - 删除连接 + 删除连接 - Edit connection - 编辑连接 + 编辑连接 - Config Details - 配置详细信息 + 配置详细信息 - Config Type - 配置类型 + 配置类型 - Protocol - 协议 + 协议 - Address - 地址 + 地址 - Port Number - 端口号 + 端口号 - Latency - 延迟 + 延迟 - Operations - 操作 + 操作 - Edit connection as JSON - 将连接编辑为 JSON + 将连接编辑为 JSON - Log (click to switch log source) - 日志 (点击切换日志源) + 日志 (点击切换日志源) @@ -739,50 +926,100 @@ - + Preferences 首选项 - Duplicate - 复制 + 复制 - Delete - 删除 + 删除 - + Edit 编辑 - Edit JSON - 编辑 JSON + 编辑 JSON - Ping Test - Ping 测试 + Ping 测试 - Share - 分享 + 分享 + + + Speed Graph + 速度图像 - Speed Graph - 速度图像 + Locate Current Connection + 定位到当前连接 + + + + Search + 搜索 + + + + Import Connection + 导入连接 + + + + Sort + 排序 + + + + Click to toggle show/hide + 点击切换显示/隐藏 + + + + Speed Graph + 速度图像 + + + + Clear chart data + 清除图表数据 + + + + Log + 日志 + + + + Clear log + 清除日志 + + + + + Not Connected + 未连接 Speed 速度 + + + Upload/Download speed + 上传/下载速度 + 0.00 B/s @@ -795,6 +1032,11 @@ Data 数据 + + + Upload/Download Data + 上传/下载流量 + 0.00 B @@ -803,398 +1045,406 @@ 0.00 B - #ManuallyCreateConnection - 手动添加连接配置 + 手动添加连接配置 - #ImportConnection - 导入连接 + 导入连接 - #Exit - 退出 + 退出 - #Preferences - 首选项 + 首选项 - #Start - 开始 + 开始 - #Stop - 停止 + 停止 - #Restart - 重启 + 重启 - - + + Hide 隐藏 - + Quit 退出 - + + Edit as JSON + 编辑为 JSON + + + Rename 重命名 - + + Duplicate to the Same Group + 复制到同组 + + + + Delete Connection + 删除连接 + + + Connect to this 连接到此服务器 - + Edit as Complex Config 编辑为复杂配置 - Edit as Json - 编辑为 Json + 编辑为 Json - Share as QRCode/VMess URL - 以二维码或 VMess 链接分享 + 以二维码或 VMess 链接分享 - Subscription: - 订阅: + 订阅: - - - + + Show 显示 - Autostarting a config - 自动启动配置 + 自动启动配置 - Could not find a specified config named: - 找不到指定的配置: + 找不到指定的配置: - - No connection selected! - 没有选择连接! + 没有选择连接! - - Please select a config from the list. - 请从列表中选择一个配置。 + 请从列表中选择一个配置。 - + + Sort connection list. + 排序连接列表。 + + + + By connection name, A-Z + 按名称,顺序 + + + + By connection name, Z-A + 按名称,逆序 + + + + By latency, Ascending + 低延迟优先 + + + + By latency, Descending + 高延迟优先 + + + + By data, Ascending + 低数据使用量优先 + + + + By data, Descending + 高数据使用量优先 + + + Update 更新 - + Found a new version: 找到新的版本: - + Download Link: 下载链接: - - - - + + + + Connected: 已连接: - - + + Configuring PAC 配置 PAC - + Could not start PAC server as it is configured to use SOCKS, but it is not enabled 无法启动 PAC 服务器,因为它被配置为使用 SOCKS,但它没有启用 - + Could not start PAC server as it is configured to use HTTP, but it is not enabled 无法启动 PAC 服务器,因为它被配置为使用 HTTP ,但它尚未启用 - + + Duplicating Connection(s) + 复制连接 + + + + Are you sure to duplicate these connection(s)? + 您确定要复制这(些)连接吗? + + + + (Copy) + (副本) + + + PAC Processing Failed PAC 处理失败 - Please reset the settings in Preference Window - 请重置首选项窗口的设置 + 请重置首选项窗口的设置 - System proxy cleared. - 系统代理已清除。 + 系统代理已清除。 - + HTTP or SOCKS inbound is not properly configured for PAC HTTP 或 SOCKS 入站配置不正确 - + Qv2ray will continue, but will not set system proxy. Qv2ray 将继续,但不会设置系统代理。 - + Cannot set system proxy 无法设置系统代理 - + Both HTTP and SOCKS inbounds are not enabled HTTP 和 SOCKS 都没有启用 - + + Didn't set proxy for complex config. + 未对复杂配置设置代理。 + + System proxy settings applied. - 系统代理设置已应用。 + 系统代理设置已应用。 - Cannot set proxy for complex config. - 无法设置复杂配置的代理。 + 无法设置复杂配置的代理。 - + Update Subscriptions 更新订阅 - + There are subscriptions need to be updated, please go to subscriptions window to update them. 有订阅需要更新,请转到订阅窗口进行更新。 - + These subscriptions are out-of-date: 这些订阅已过期: - Disconnected - 已断开 + 已断开 - Complex - 复杂 + 复杂 - Simple - 简单 + 简单 - No data - 没有数据 + 没有数据 - ms - ms + ms - There're no support of sharing configs other than vmess and shadowsocks - 不支持分享除 Vmess 和 Shadowsocks 之外的链接 + 不支持分享除 Vmess 和 Shadowsocks 之外的链接 - - - - - - N/A - 不适用 + 不适用 - - - Rename a Connection - 重命名连接 + 重命名连接 - + V2ray vcore terminated. V2ray 核心已终止。 - + V2ray vcore terminated unexpectedly. V2ray 核心意外终止。 - + To solve the problem, read the V2ray log in the log text browser. 要解决问题,请阅读日志文本浏览器中的 V2ray 日志。 - + Enable System Proxy 启用系统代理 - + Disable System Proxy 禁用系统代理 - + System Proxy 系统代理 - Ping - Ping 测试 + Ping 测试 - Ping All - Ping 测试所有连接 + Ping 测试所有连接 - - Subscription - 订阅 + 订阅 - Already connected to: - 已经连接到: + 已经连接到: - + Disconnected from: - 已断开连接: + 已断开连接: - The name cannot be empty - 名称不能为空 + 名称不能为空 - The name has been used already, Please choose another. - 名称已被使用,请选择其他名称。 + 名称已被使用,请选择其他名称。 - The name you suggested is not valid, please try another. - 您建议的名称无效,请尝试其他名称。 + 您建议的名称无效,请尝试其他名称。 - + Removing Connection(s) 删除连接 - + Are you sure to remove selected connection(s)? 您确定要删除这(些)连接吗? - - Removing this Connection - 正在删除此连接 + 正在删除此连接 - - Failed to delete connection file, please delete manually. - 删除连接文件失败,请手动删除。 + 删除连接文件失败,请手动删除。 - Removing a subscription config - 删除订阅配置 + 删除订阅配置 - Do you want to remove the config loaded from a subscription? - 您是否要删除从订阅中加载的配置? + 您是否要删除从订阅中加载的配置? - - - No Config Selected - 未选择配置 + 未选择配置 - - - Please Select a Config - 请选择一个配置 + 请选择一个配置 - You are about to run latency test on all servers, do you want to continue? - 您将在所有服务器上运行延迟测试,是否继续? + 您将在所有服务器上运行延迟测试,是否继续? - Testing... - 正在测试… + 正在测试… - - Latency Test - 测试延迟 + 测试延迟 - Failed to test latency for this connection. - 无法测试此连接的延迟。 + 无法测试此连接的延迟。 - Share Connection - 分享连接 + 分享连接 @@ -1329,11 +1579,11 @@ PreferencesWindow - - - - - + + + + + Preferences 首选项 @@ -1697,6 +1947,71 @@ UDP Local IP UDP 本地IP + + + Transparent Proxy Settings + 透明代理设置 + + + + All settings below will only be applied onto simple connection. + 下面的所有设置仅会在简单配置中生效。 + + + + Add Docodemo-door inbound + 添加任意门入站 + + + + Address + 地址 + + + + TCP + TCP + + + + UDP + UDP + + + + Follow Redirect + 跟随重定向 + + + + Override Connection SockOpt Settings + 覆盖连接 SockOpt 选项 + + + + TCP Fast Open + TCP 快速打开 + + + + Mark + 标记 + + + + Match Contains + 标记包含 + + + + TProxy Mode + tProxy 工作模式 + + + + Settings will be added to the StreamSettings for matched connections. + 本设置将会添加到对应连接中的流设定。 + - @@ -1739,13 +2054,13 @@ - + Bold 粗体 - + Italic 斜体 @@ -1855,156 +2170,154 @@ 关于 Qt - + Use Darkmode Theme 使用暗色模式主题 - + Page - + Item(s) 项目 - - + + Enable tProxy Support 启用 tProxy 支持 - + to this path: 到此路径: - + Qv2ray Network Toolbar is disabled and still under test. Add --withToolbarPlugin to enable. Qv2ray 的网络工具栏已被禁用,请使用 --withToolbarPlugin 来启用 - + Duplicated port numbers detected, please check the port number settings. 检测到重复的端口号,请检查端口号设置。 - + Invalid inbound listening address. 入站监听地址不可用 - + Open V2ray assets folder 打开 V2ray 资源文件夹 - + Open V2ray core file 打开 V2ray 核心文件 - + This will append capabilities to the V2ray executable. 这会将功能附加到 V2ray 可执行文件。 - + Qv2ray will copy your V2ray core to this path: Qv2ray 会将您的 V2ray 核心复制到以下路径: - + If anything goes wrong after enabling this, please check issue #57 or the link below: 如果有出现任何问题,请参阅 issue #57 或以下链接 - + Qv2ray cannot copy one or both V2ray files from: Qv2ray 无法从以下位置复制一个或两个 V2ray 文件: - - + + Failed to setcap onto V2ray executable. You may need to run `setcap` manually. 无法将 Capcap 设置到 V2ray 可执行文件上。 您可能需要手动运行“ setcap”。 - + tProxy is not supported on macOS and Windows 在 macOS 和 Windows 上不支持 tProxy - + Apply network toolbar settings 应用网络工具栏设置 - + All other modified settings will be applied as well after this object. 已经编辑的其它设置也会被同时应用 - + Do you want to continue? 你想继续吗? - Dark Mode - 深色模式 + 深色模式 - Please restart Qv2ray to fully apply this feature. - 请重启 Qv2ray 以充分应用此功能。 + 请重启 Qv2ray 以充分应用此功能。 - + Select GFWList in base64 选择 base64 格式的 GFWList - - + + Download GFWList 下载 GFWList - + Operation is cancelled. 操作已经取消 - + Successfully downloaded GFWList. 下载 GFWList 成功。 - + Start with boot 开机启动 - + Failed to set auto start option. 无法设置自动启动选项。 - - + + V2ray Core Settings V2ray 核心设置 - + V2ray path configuration check passed. V2ray 路径配置检查通过。 - + Current version of V2ray is: V2ray 当前版本是: @@ -2023,7 +2336,7 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'WenQuanYi Micro Hei'; font-size:10pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'WenQuanYi Micro Hei'; font-size:10pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'WenQuanYi Micro Hei'; font-size:10pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> @@ -2031,167 +2344,193 @@ p, li { white-space: pre-wrap; } QObject - + Unsupported share link format. 不支持的分享链接格式 - + SS URI is too short SS URI 太短了 - - + + Can't find the colon separator between method and password 无法找到 method 和 password 之间的冒号分隔符 - + Can't find the at separator between password and hostname 无法找到 password 和 hostname 之间的分隔符 - + Can't find the colon separator between hostname and port 无法找到 host 和 port 之间的冒号分隔符 - + VMess string should start with 'vmess://' VMess 链接应以 'vmess://' 开始 - + VMess string should be a valid base64 string VMess 链接应该是一个有效的 base64 字符串 - + JSON should not be empty JSON 不应该为空 - + Warning 警告 - + Qv2ray cannot load the config file from here: Qv2ray 无法从这里加载配置文件: - + Cannot Start Qv2ray 无法启动 Qv2ray - + Cannot find a place to store config files. 找不到保存配置文件的地方。 - + Qv2ray has searched these paths below: Qv2ray 搜索了以下路径: - - - + + It usually means you don't have the write permission to all of those locations. + 这通常意味着您没有所有这些位置的文件写入权限。 + + + + + Qv2ray will now exit. Qv2ray 现在将退出。 - + Failed to initialise Qv2ray 初始化 Qv2ray 失败 - Failed to determine the location of config file. - 无法确定配置文件的位置。 + 无法确定配置文件的位置。 - + Please report if you think it's a bug. 如果您认为它是一个bug,请'报告。 - + You cannot run Qv2ray as root, please use --I-just-wanna-run-with-root if you REALLY want to do so. 您不能以root用户身份运行Qv2ray,如果您确实想这样做,请使用 --I-just-wanna-run-with-root。 - + --> USE IT AT YOUR OWN RISK! --> 请自负风险! - Cannot load languages - 无法加载语言 + 无法加载语言 - Qv2ray will continue running, but you cannot change the UI language. - Qv2ray 将继续运行,但您不能更改界面语言。 + Qv2ray 将继续运行,但您不能更改界面语言。 - + Qv2ray Cannot Continue Qv2ray 无法继续 - + You are running a lower version of Qv2ray compared to the current config file. 与当前配置文件相比,您正在运行一个较低版本的 Qv2ray - + Please check if there's an issue explaining about it. 请检查是否存在'有关此问题的说明。 - + Or submit a new issue if you think this is an error. 或者如果你认为这是一个错误,请提交一个新问题。 - + Dependency Missing 缺少依赖关系 - + This could be caused by a missing of `openssl` package in your system. 这可能是系统中缺少`openssl`软件包造成的。 - + If you are using an AppImage from Github Action, please report a bug. 如果您使用的是来自 Github Action 的 AppImage,请报告错误。 - + Cannot find openssl libs 找不到 OpenSSL 库 - + + Failed to determine the location of config file: + 无法确定配置文件的位置: + + + + Qv2ray has found a config file, but it failed to be loaded due to some errors. + Qv2ray已找到配置文件,但由于某些错误而无法加载。 + + + + A workaround is to remove the this file and restart Qv2ray: + 一种解决方法是删除此文件并重新启动Qv2ray: + + + + Debug version + 调试版 + + + Technical Details 技术细节 - + + Not connected + 未连接 + + + Connected 已连接 - Disconnected - 未连接 + 未连接 @@ -2234,14 +2573,17 @@ p, li { white-space: pre-wrap; } 总下载速度 - - Upload Speed for Specific Tag - 上传特定标签的速度 + + Current Connection Latency + 当前连接延迟 + + + Upload Speed for Specific Tag + 上传特定标签的速度 - Download Speed for Specific Tag - 下载特定标签的速度 + 下载特定标签的速度 @@ -2254,149 +2596,276 @@ p, li { white-space: pre-wrap; } 总下载数据 - Uploaded Data for Specific Tag - 上传特定标签的数据 + 上传特定标签的数据 - Downloaded Data for Specific Tag - 下载特定标签的数据 + 下载特定标签的数据 - - Editing a subscription config - 编辑订阅配置 + 编辑订阅配置 - You are trying to edit a config loaded from subscription. - 您正在尝试编辑从订阅中加载的配置。 + 您正在尝试编辑从订阅中加载的配置。 - All changes will be overwritten when the subscriptions are updated next time. - 下次更新订阅时,所有更改都会覆盖。 + 下次更新订阅时,所有更改都会覆盖。 - Are you still going to do so? - 你还要这样做吗? + 你还要这样做吗? - You should not modity this property of a config from a subscription - 您不应从订阅中修改配置的此属性 + 您不应从订阅中修改配置的此属性 - + - + N/A 不适用 - + Qv2ray - A cross-platform Qt frontend for V2ray. Qv2ray - V2ray的跨平台Qt前端。 - + Disable gRPC API subsystems. 禁用 gRPC API 子系统。 - + Explicitly run Qv2ray as root. 以 root 身份运行 Qv2ray。 - + Enable Debug Output 启用调试输出 - + Enable Qv2ray network toolbar plugin 启用 Qv2ray 网络工具栏插件 + + + invalid ssd link: json: field %1 must exist + SSD 链接无效: json: 必选字段 %1 不存在 + + + + invalid ssd link: json: field %1 must be valid port number + SSD 链接无效: json: 字段 %1 应为有效的端口号 + + + + invalid ssd link: json: field %1 must be of type 'string' + SSD 链接无效: json: 字段 %1 必须为字符串类型 + + + + invalid ssd link: json: field %1 must be an array + SSD 链接无效: json: 字段 %1 必须为数组类型 + + + + skipping invalid ssd server: server must be an object + 跳过无效的 ssd 服务器: 服务器必须是一个对象 + + + + skipping invalid ssd server: missing required field %1 + 跳过无效的 ssd 服务器: 必选字段 %1 缺失 + + + + skipping invalid ssd server: field %1 should be of type 'string' + 跳过无效的 ssd 服务器: 字段 %1 须为字符串类型 + + + + Invalid ssd link: should begin with ssd:// + SSD 链接无效: 必须以 ssd:// 开头 + + + + Invalid ssd link: base64 parse failed + SSD 链接无效: 无法作为 Base64 解析 + + + + Invalid ssd link: json parse failed: + SSD 链接无效: JSON 语法分析失败: + + + + Invalid ssd link: found non-object json, aborting + SSD 链接无效: 解析到非对象的 JSON,已终止 + + + + Invalid ssd link: rc4-md5 encryption is not supported by v2ray-core + SSD 链接无效: v2ray-core 不支持 rc4-md5 加密方式 + + + + Invalid port encountered. using fallback value. + 遇到无效端口。已使用默认值。 + + + + Invalid name encountered. using fallback value. + 遇到无效名称。已使用默认值。 + + + + Invalid ratio encountered. using fallback value. + 遇到无效流量比率。已使用默认值。 + + + + Default Group + 默认分组 + + + + Configuration Upgrade Failed + 配置升级失败 + + + + Unsupported config version number: + 不支持的配置文件版本: + + + + Please upgrade firstly up to Qv2ray v2.0/v2.1 and try again. + 请先升级到 Qv2ray v2.0/v2.1 再重试。 + + + + %1 - %2 (rate %3) + %1 - %2 (%3倍) + + + + (Complex config) + (复杂配置) + Qv2ray::components::pac::PACServer - + PAC Handler PAC 处理器 - + Failed to listen PAC request on this port, please verify the permissions 无法在此端口监听 PAC 请求,请检查是否具有足够的权限 + + Qv2ray::core::handlers::QvConfigHandler + + + + Default Group + 默认分组 + + + + File does not exist. + 文件不存在。 + + + + + Group does not exist + 分组不存在 + + Qv2ray::core::kernel::V2rayKernelInstance - + V2ray core executable not found. - V2ray 核心可执行文件未找到 + V2ray 核心可执行文件未找到。 - + V2ray core file cannot be opened, please ensure there's a file instead of a folder. - 无法打开 V2ray 核心文件,请检查对应的文件存在而不是文件夹 + 无法打开 V2ray 核心文件,请检查对应的文件存在而不是文件夹。 - + V2ray assets path is not valid. - V2ray Assets 路径不可用 + V2ray Assets 路径不可用。 - + No geoip.dat in assets path. - 没有在 Assets 路径找到 geoip.dat + 没有在 Assets 路径找到 geoip.dat。 - + No geosite.dat in assets path. - 没有在 Assets 路径找到 geosite.dat + 没有在 Assets 路径找到 geosite.dat。 - + V2ray core failed with an exit code: - V2ray 核心退出代码: + V2ray 核心退出代码: - + V2ray core returns empty string. - V2ray 核心返回空字符串 + V2ray 核心返回空字符串。 - + Configuration Error 配置错误 - + Cannot start V2ray 无法启动 V2ray - + V2ray core settings is incorrect. - V2ray 核心设置不正确 + V2ray 核心设置不正确。 - + The error is: - 错误是: + 错误是: + + + + Invalid V2ray Instance Status. + V2ray 实例状态无效。 + + + + V2ray kernel failed to start. + V2ray 核心启动失败。 QvInboundNodeModel - + Missing or incorrect inputs 输入丢失或不正确 @@ -2404,7 +2873,7 @@ p, li { white-space: pre-wrap; } QvOutboundNodeModel - + Missing or incorrect inputs 输入丢失或不正确 @@ -2412,7 +2881,7 @@ p, li { white-space: pre-wrap; } QvRuleNodeDataModel - + Missing or incorrect inputs 输入丢失或不正确 @@ -2421,7 +2890,7 @@ p, li { white-space: pre-wrap; } RouteEditor - + Route Editor 路由编辑器 @@ -2661,182 +3130,186 @@ p, li { white-space: pre-wrap; } 用户列表 - - - + + + OK - + Cannot Edit 无法编辑 - + This outbound entry is not supported by the GUI editor. 此出站条目不支持GUI编辑。 - - + + We will launch Json Editor instead. 我们将启动 Json 编辑器。 - + Show rule details 查看规则细节 - + A rule cannot be found: - 规则未找到: + 规则未找到: - - - + + + Protocol list changed: 协议列表已更改: - + Balancer is empty, not processing. 负载均衡器列表是空的,不处理。 - + Default rule 默认规则 - + rule 规则 - + No Inbound 无入站 - + No inbound item found: - 入站项目未找到: + 入站项目未找到: - - - + + The new tag has been used, we appended a postfix. 原标签被占用,自动添加后缀。 - + + The new tag has been used, we appended a random string to the tag. + 原标签被占用,自动添加随机字符串以避免重复。 + + + To make this rule ready to use, you need to connect it to an outbound node. 要使这条规则可以使用,您需要将它连接到一个出站节点。 - + Remove Items 移除项目 - - + + Please select a node from the graph to continue. 请从图表中选择要继续的节点。 - + Error 错误 - + Qv2ray entered an unknown state. - Qv2ray 进入了未知状态 + Qv2ray 进入了未知状态。 - + Edit Inbound/Outbound 编辑入站/出站 - - + + Edit Inbound 编辑入站 - - + + No inbound tag found: - 入站标签未找到: + 入站标签未找到: - - + + Opening JSON editor 正在打开 JSON 编辑器 - + Unsupported Outbound Type 不支持的出站类型 - + Opening default outbound editor. 打开默认出站编辑器。 - - - + + + Renaming a tag 重命名标签 - + New tag is empty, please try another. - 新的标签是空的,请尝试另外一个 + 新的标签是空的,请尝试另外一个。 - + New tag is the same as the original one. - 新的标签与旧标签相同 + 新的标签与旧标签相同。 - + Duplicate rule tag detected, please try another. - 检测到重复的标签,请重试 + 检测到重复的标签,请重试。 - + Added DIRECT outbound 已添加直连出站 - + Currently, this type of outbound is not supported by the editor. - 目前不支持此类型的出站 + 目前不支持此类型的出站。 - + Opening default inbound editor 打开默认的入站编辑器 - + Removed a balancer entry. 删除了一个平衡条目。 - - - + + + Rename tags 重命名标签 @@ -2892,12 +3365,12 @@ p, li { white-space: pre-wrap; } SpeedPlotView - + Total Upload 总上传量 - + Total Download 总下载量 @@ -3068,94 +3541,102 @@ p, li { white-space: pre-wrap; } SubscribeEditor - - - - Renaming a subscription - 重命名订阅 + 重命名订阅 - The subscription name is invalid, please try another. - 订阅名称无效,请重试。 + 订阅名称无效,请重试。 - New name of this subscription has been used already, please suggest another one - 此订阅的新名称已被使用,请尝试另一个 + 此订阅的新名称已被使用,请尝试另一个 - Failed to rename a subscription, this is an unknown error. - 无法重命名订阅,这是一个未知错误。 + 无法重命名订阅,这是一个未知错误。 - Successfully renamed a subscription - 成功重命名订阅 + 成功重命名订阅 - Update Subscription - 更新订阅 + 更新订阅 - Would you like to reload this subscription from the Url? - 您要从 Url 重新加载此订阅吗? + 您要从 Url 重新加载此订阅吗? - Updating subscriptions + 更新订阅 + + + Failed to process the result from the upstream, please check your Url. + 无法处理源自上游的结果,请检查您的URL。 + + + + Reload Subscription 更新订阅 - - Failed to process the result from the upstream, please check your Url. - 无法处理源自上游的结果,请检查您的URL。 + + Would you like to reload the subscription? + 您要更新此订阅吗? + + + + Deleting a subscription + 删除订阅 + + + + All connections will be moved to default group, do you want to continue? + 本订阅中的所有连接都将移动到默认分组,您确定要继续吗? misc - + B bytes B - + KiB kibibytes (1024 bytes) KiB - + MiB mebibytes (1024 kibibytes) MiB - + GiB gibibytes (1024 mibibytes) GiB - + TiB tebibytes (1024 gibibytes) TiB - + PiB pebibytes (1024 tebibytes) PiB - + EiB exbibytes (1024 pebibytes) EiB @@ -3180,9 +3661,8 @@ p, li { white-space: pre-wrap; } 订阅列表 - A - A + A @@ -3195,9 +3675,8 @@ p, li { white-space: pre-wrap; } 删除订阅 - D - D + D @@ -3245,4 +3724,4 @@ p, li { white-space: pre-wrap; } 更新订阅数据 - \ No newline at end of file +