diff --git a/Build.Counter b/Build.Counter index b9e5dd76..32884547 100644 --- a/Build.Counter +++ b/Build.Counter @@ -1 +1 @@ -540 +682 diff --git a/Qv2ray.pro b/Qv2ray.pro index f540a4c8..a0723880 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -25,8 +25,8 @@ write_file("Build.Counter", _BUILD_NUMBER) DEFINES += QT_DEPRECATED_WARNINGS QV2RAY_VERSION_STRING=\"\\\"v$${VERSION}\\\"\" SOURCES += \ - src/QvCoreConfigOperations.cpp \ src/main.cpp \ + src/QvCoreConfigOperations.cpp \ src/QvConfigUpgrade.cpp \ src/QvCoreConfigOperations_Convertion.cpp \ src/QvCoreConfigOperations_Generation.cpp \ @@ -57,7 +57,6 @@ INCLUDEPATH += \ src/ui/ \ src/utils/ \ libs/gen/ - HEADERS += \ src/Qv2rayBase.hpp \ src/QvCoreConfigObjects.hpp \ @@ -74,6 +73,7 @@ HEADERS += \ src/ui/w_RoutesEditor.hpp \ src/ui/w_SubscriptionEditor.hpp \ src/ui/w_ScreenShot_Core.hpp \ + src/utils/QvTinyLog.hpp \ src/utils/QJsonModel.hpp \ src/utils/QJsonObjectInsertMacros.h \ src/utils/QObjectMessageProxy.hpp \ @@ -82,8 +82,7 @@ HEADERS += \ src/utils/QvPingModel.hpp \ src/utils/QvRunguard.hpp \ libs/gen/v2ray_api_commands.pb.h \ - libs/gen/v2ray_api_commands.grpc.pb.h \ - src/utils/QvTinyLog.hpp + libs/gen/v2ray_api_commands.grpc.pb.h FORMS += \ src/ui/w_ExportConfig.ui \ @@ -94,8 +93,8 @@ FORMS += \ src/ui/w_OutboundEditor.ui \ src/ui/w_PrefrencesWindow.ui \ src/ui/w_RoutesEditor.ui \ - src/ui/w_SubscriptionEditor.ui \ - src/ui/w_ScreenShot_Core.ui + src/ui/w_ScreenShot_Core.ui \ + src/ui/w_SubscriptionEditor.ui RESOURCES += \ resources.qrc @@ -113,8 +112,10 @@ message("| |") message("| See: https://www.gnu.org/licenses/gpl-3.0.html |") message("|-------------------------------------------------|") message(" ") -RC_ICONS += ./icons/Qv2ray.ico -ICON = ./icons/Qv2ray.icns + + +RC_ICONS += ./icons/qv2ray.ico +ICON = ./icons/qv2ray.icns # ------------------------------------------ Begin checking gRPC and protobuf headers. !exists(libs/gen/v2ray_api_commands.grpc.pb.h) || !exists(libs/gen/v2ray_api_commands.grpc.pb.cc) || !exists(libs/gen/v2ray_api_commands.pb.h) || !exists(libs/gen/v2ray_api_commands.pb.cc) { diff --git a/icons/add_connection_btn.png b/icons/add_connection_btn.png deleted file mode 100644 index 5c19da4b..00000000 Binary files a/icons/add_connection_btn.png and /dev/null differ diff --git a/icons/add_connection_btn.svg b/icons/add_connection_btn.svg deleted file mode 100644 index 140c385a..00000000 --- a/icons/add_connection_btn.svg +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/icons/designs/Applogo_Circle.svg b/icons/designs/Applogo_Circle.svg new file mode 100644 index 00000000..738f6b41 --- /dev/null +++ b/icons/designs/Applogo_Circle.svg @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + V2ray + + diff --git a/icons/designs/Applogo_Frameless.svg b/icons/designs/Applogo_Frameless.svg new file mode 100644 index 00000000..8bb81ca8 --- /dev/null +++ b/icons/designs/Applogo_Frameless.svg @@ -0,0 +1,271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + V2ray + + diff --git a/icons/designs/Applogo_Square.svg b/icons/designs/Applogo_Square.svg new file mode 100644 index 00000000..b8c4c283 --- /dev/null +++ b/icons/designs/Applogo_Square.svg @@ -0,0 +1,383 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + V2ray + + diff --git a/icons/designs/banner.svg b/icons/designs/banner.svg new file mode 100644 index 00000000..5c2af858 --- /dev/null +++ b/icons/designs/banner.svg @@ -0,0 +1,471 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + QV2ray + The V2ray GUI client using Qt + Windows / Linux / macOS + + + + + + + + + + + + + + + + + V2ray + + + diff --git a/icons/designs/banner.svg.png b/icons/designs/banner.svg.png new file mode 100644 index 00000000..d9e4a98f Binary files /dev/null and b/icons/designs/banner.svg.png differ diff --git a/icons/edit_connection_btn.png b/icons/edit_connection_btn.png deleted file mode 100644 index c201cb29..00000000 Binary files a/icons/edit_connection_btn.png and /dev/null differ diff --git a/icons/edit_connection_btn.svg b/icons/edit_connection_btn.svg deleted file mode 100644 index df6019df..00000000 --- a/icons/edit_connection_btn.svg +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/icons/import_connection_btn.png b/icons/import_connection_btn.png deleted file mode 100644 index efb21c3b..00000000 Binary files a/icons/import_connection_btn.png and /dev/null differ diff --git a/icons/import_connection_btn.svg b/icons/import_connection_btn.svg deleted file mode 100644 index 00972496..00000000 --- a/icons/import_connection_btn.svg +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/icons/netspeed-arrows.svg b/icons/netspeed-arrows.svg deleted file mode 100644 index cf0d0029..00000000 --- a/icons/netspeed-arrows.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - diff --git a/icons/qv2ray.icns b/icons/qv2ray.icns index 9102bdfb..a3d54215 100644 Binary files a/icons/qv2ray.icns and b/icons/qv2ray.icns differ diff --git a/icons/qv2ray.ico b/icons/qv2ray.ico index 39157eb7..ba3d41bc 100644 Binary files a/icons/qv2ray.ico and b/icons/qv2ray.ico differ diff --git a/icons/qv2ray.png b/icons/qv2ray.png index d1c3e07d..e12ad919 100644 Binary files a/icons/qv2ray.png and b/icons/qv2ray.png differ diff --git a/icons/qv2ray.xcf b/icons/qv2ray.xcf deleted file mode 100644 index ec0ce043..00000000 Binary files a/icons/qv2ray.xcf and /dev/null differ diff --git a/icons/remove_connection_btn.png b/icons/remove_connection_btn.png deleted file mode 100644 index aebcf977..00000000 Binary files a/icons/remove_connection_btn.png and /dev/null differ diff --git a/icons/remove_connection_btn.svg b/icons/remove_connection_btn.svg deleted file mode 100644 index 4cefec16..00000000 --- a/icons/remove_connection_btn.svg +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/icons/remove_connection_btn_red.png b/icons/remove_connection_btn_red.png deleted file mode 100644 index 5bfc94ba..00000000 Binary files a/icons/remove_connection_btn_red.png and /dev/null differ diff --git a/icons/ui_dark/add.png b/icons/ui_dark/add.png new file mode 100644 index 00000000..fa0f056e Binary files /dev/null and b/icons/ui_dark/add.png differ diff --git a/icons/ui_dark/delete.png b/icons/ui_dark/delete.png new file mode 100644 index 00000000..ffef336b Binary files /dev/null and b/icons/ui_dark/delete.png differ diff --git a/icons/ui_dark/design/add.svg b/icons/ui_dark/design/add.svg new file mode 100644 index 00000000..08beefbd --- /dev/null +++ b/icons/ui_dark/design/add.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/icons/ui_dark/design/delete.svg b/icons/ui_dark/design/delete.svg new file mode 100644 index 00000000..3838d69f --- /dev/null +++ b/icons/ui_dark/design/delete.svg @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/icons/ui_dark/design/duplicate.svg b/icons/ui_dark/design/duplicate.svg new file mode 100644 index 00000000..e00d526f --- /dev/null +++ b/icons/ui_dark/design/duplicate.svg @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/icons/ui_dark/design/edit.svg b/icons/ui_dark/design/edit.svg new file mode 100644 index 00000000..11102a86 --- /dev/null +++ b/icons/ui_dark/design/edit.svg @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/icons/ui_dark/design/import.svg b/icons/ui_dark/design/import.svg new file mode 100644 index 00000000..9044bde1 --- /dev/null +++ b/icons/ui_dark/design/import.svg @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/icons/ui_dark/design/json.svg b/icons/ui_dark/design/json.svg new file mode 100644 index 00000000..9460eeeb --- /dev/null +++ b/icons/ui_dark/design/json.svg @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/icons/ui_dark/design/netspeed_arrow.svg b/icons/ui_dark/design/netspeed_arrow.svg new file mode 100644 index 00000000..f03da8b7 --- /dev/null +++ b/icons/ui_dark/design/netspeed_arrow.svg @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/icons/ui_dark/design/ping_gauge.svg b/icons/ui_dark/design/ping_gauge.svg new file mode 100644 index 00000000..32b47d3e --- /dev/null +++ b/icons/ui_dark/design/ping_gauge.svg @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/icons/ui_dark/design/share.svg b/icons/ui_dark/design/share.svg new file mode 100644 index 00000000..e5d027a6 --- /dev/null +++ b/icons/ui_dark/design/share.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/icons/ui_dark/design/tray.svg b/icons/ui_dark/design/tray.svg new file mode 100644 index 00000000..bd679ad8 --- /dev/null +++ b/icons/ui_dark/design/tray.svg @@ -0,0 +1,292 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/icons/ui_dark/duplicate.png b/icons/ui_dark/duplicate.png new file mode 100644 index 00000000..98ba56f4 Binary files /dev/null and b/icons/ui_dark/duplicate.png differ diff --git a/icons/ui_dark/edit.png b/icons/ui_dark/edit.png new file mode 100644 index 00000000..63442afe Binary files /dev/null and b/icons/ui_dark/edit.png differ diff --git a/icons/ui_dark/import.png b/icons/ui_dark/import.png new file mode 100644 index 00000000..76255de2 Binary files /dev/null and b/icons/ui_dark/import.png differ diff --git a/icons/ui_dark/json.png b/icons/ui_dark/json.png new file mode 100644 index 00000000..f95ed9e7 Binary files /dev/null and b/icons/ui_dark/json.png differ diff --git a/icons/ui_dark/netspeed_arrow.png b/icons/ui_dark/netspeed_arrow.png new file mode 100644 index 00000000..cb62e58e Binary files /dev/null and b/icons/ui_dark/netspeed_arrow.png differ diff --git a/icons/ui_dark/ping_gauge.png b/icons/ui_dark/ping_gauge.png new file mode 100644 index 00000000..4699a059 Binary files /dev/null and b/icons/ui_dark/ping_gauge.png differ diff --git a/icons/ui_dark/share.png b/icons/ui_dark/share.png new file mode 100644 index 00000000..ef8c18e6 Binary files /dev/null and b/icons/ui_dark/share.png differ diff --git a/icons/ui_dark/tray.png b/icons/ui_dark/tray.png new file mode 100644 index 00000000..704297f5 Binary files /dev/null and b/icons/ui_dark/tray.png differ diff --git a/icons/ui_light/add.png b/icons/ui_light/add.png new file mode 100644 index 00000000..fadb12d8 Binary files /dev/null and b/icons/ui_light/add.png differ diff --git a/icons/ui_light/delete.png b/icons/ui_light/delete.png new file mode 100644 index 00000000..0a7c766b Binary files /dev/null and b/icons/ui_light/delete.png differ diff --git a/icons/ui_light/design/add.svg b/icons/ui_light/design/add.svg new file mode 100644 index 00000000..fc4951ba --- /dev/null +++ b/icons/ui_light/design/add.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/icons/ui_light/design/delete.svg b/icons/ui_light/design/delete.svg new file mode 100644 index 00000000..e56c7d69 --- /dev/null +++ b/icons/ui_light/design/delete.svg @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/icons/ui_light/design/duplicate.svg b/icons/ui_light/design/duplicate.svg new file mode 100644 index 00000000..19b420b8 --- /dev/null +++ b/icons/ui_light/design/duplicate.svg @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/icons/ui_light/design/edit.svg b/icons/ui_light/design/edit.svg new file mode 100644 index 00000000..8da1cf51 --- /dev/null +++ b/icons/ui_light/design/edit.svg @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/icons/ui_light/design/import.svg b/icons/ui_light/design/import.svg new file mode 100644 index 00000000..49228e6a --- /dev/null +++ b/icons/ui_light/design/import.svg @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/icons/ui_light/design/json.svg b/icons/ui_light/design/json.svg new file mode 100644 index 00000000..40f87b22 --- /dev/null +++ b/icons/ui_light/design/json.svg @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/icons/ui_light/design/netspeed_arrow.svg b/icons/ui_light/design/netspeed_arrow.svg new file mode 100644 index 00000000..67f15913 --- /dev/null +++ b/icons/ui_light/design/netspeed_arrow.svg @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/icons/ui_light/design/ping_gauge.svg b/icons/ui_light/design/ping_gauge.svg new file mode 100644 index 00000000..66c608cd --- /dev/null +++ b/icons/ui_light/design/ping_gauge.svg @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/icons/ui_light/design/share.svg b/icons/ui_light/design/share.svg new file mode 100644 index 00000000..1bbbec0c --- /dev/null +++ b/icons/ui_light/design/share.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/icons/ui_light/design/tray.svg b/icons/ui_light/design/tray.svg new file mode 100644 index 00000000..3126b9ac --- /dev/null +++ b/icons/ui_light/design/tray.svg @@ -0,0 +1,344 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/icons/ui_light/duplicate.png b/icons/ui_light/duplicate.png new file mode 100644 index 00000000..41dce418 Binary files /dev/null and b/icons/ui_light/duplicate.png differ diff --git a/icons/ui_light/edit.png b/icons/ui_light/edit.png new file mode 100644 index 00000000..c1a49da0 Binary files /dev/null and b/icons/ui_light/edit.png differ diff --git a/icons/ui_light/import.png b/icons/ui_light/import.png new file mode 100644 index 00000000..f66ab848 Binary files /dev/null and b/icons/ui_light/import.png differ diff --git a/icons/ui_light/json.png b/icons/ui_light/json.png new file mode 100644 index 00000000..264c3d4d Binary files /dev/null and b/icons/ui_light/json.png differ diff --git a/icons/ui_light/netspeed_arrow.png b/icons/ui_light/netspeed_arrow.png new file mode 100644 index 00000000..0913db08 Binary files /dev/null and b/icons/ui_light/netspeed_arrow.png differ diff --git a/icons/ui_light/ping_gauge.png b/icons/ui_light/ping_gauge.png new file mode 100644 index 00000000..f380662d Binary files /dev/null and b/icons/ui_light/ping_gauge.png differ diff --git a/icons/ui_light/share.png b/icons/ui_light/share.png new file mode 100644 index 00000000..dfa6a4f9 Binary files /dev/null and b/icons/ui_light/share.png differ diff --git a/icons/ui_light/tray.png b/icons/ui_light/tray.png new file mode 100644 index 00000000..dbcc105d Binary files /dev/null and b/icons/ui_light/tray.png differ diff --git a/resources.qrc b/resources.qrc index 357ea761..4b17395d 100644 --- a/resources.qrc +++ b/resources.qrc @@ -1,10 +1,27 @@ + icons/qv2ray.icns + icons/qv2ray.png icons/qv2ray.ico - icons/add_connection_btn.png - icons/import_connection_btn.png - icons/remove_connection_btn.png - icons/edit_connection_btn.png - icons/netspeed-arrows.svg + icons/ui_dark/add.png + icons/ui_dark/delete.png + icons/ui_dark/duplicate.png + icons/ui_dark/edit.png + icons/ui_dark/import.png + icons/ui_dark/json.png + icons/ui_dark/netspeed_arrow.png + icons/ui_dark/ping_gauge.png + icons/ui_dark/share.png + icons/ui_light/add.png + icons/ui_light/delete.png + icons/ui_light/duplicate.png + icons/ui_light/edit.png + icons/ui_light/import.png + icons/ui_light/json.png + icons/ui_light/netspeed_arrow.png + icons/ui_light/ping_gauge.png + icons/ui_light/share.png + icons/ui_light/tray.png + icons/ui_dark/tray.png diff --git a/src/Qv2rayBase.hpp b/src/Qv2rayBase.hpp index 2281e718..9a80ef71 100644 --- a/src/Qv2rayBase.hpp +++ b/src/Qv2rayBase.hpp @@ -1,14 +1,22 @@ #ifndef QV2RAYBASE_H #define QV2RAYBASE_H #include +#include #include +#include #include "QvTinyLog.hpp" #include "QvCoreConfigObjects.hpp" -#include "QvNetSpeedPlugin.hpp" #include "QObjectMessageProxy.hpp" #define QV2RAY_CONFIG_VERSION 9 + +// Linux DEs should handle the ui schemes themselves. +// --> Or.. should we change this into a modifyable setting? +#ifdef Q_OS_LINUX +#define QV2RAY_USE_BUILTIN_DARKTHEME false +#else #define QV2RAY_USE_BUILTIN_DARKTHEME true +#endif // Base folder suffix. #ifdef QT_DEBUG @@ -39,19 +47,21 @@ #define QV2RAY_VCORE_ERROR_LOG_FILENAME "error.log" // GUI TOOLS +#define QV2RAY_IS_DARKTHEME (GetGlobalConfig().UISettings.useDarkTheme) #define RED(obj) \ auto _temp = obj->palette(); \ _temp.setColor(QPalette::Text, Qt::red); \ obj->setPalette(_temp); -// TODO: Dark mode support. #define BLACK(obj) \ auto _temp = obj->palette(); \ - _temp.setColor(QPalette::Text, Qt::blue); \ + _temp.setColor(QPalette::Text, QV2RAY_IS_DARKTHEME ? Qt::white : Qt::black); \ obj->setPalette(_temp); -#define QSTRING(std_string) QString::fromStdString(std_string) +#define QV2RAY_UI_RESOURCES_ROOT QSTRING(QV2RAY_IS_DARKTHEME ? ":/icons/ui_dark/" : ":/icons/ui_light/") +#define QICON_R(file) QIcon(QV2RAY_UI_RESOURCES_ROOT + file) +#define QSTRING(std_string) QString::fromStdString(std_string) #define NEWLINE "\r\n" #ifndef MAX @@ -60,6 +70,44 @@ namespace Qv2ray { + // Extra header for QvConfigUpgrade.cpp + QJsonObject UpgradeConfig(int fromVersion, int toVersion, QJsonObject root); + + + struct QvBarLine { + std::string Family; + bool Bold; + bool Italic; + int ColorA; + int ColorR; + int ColorG; + int ColorB; + int ContentType; + double Size; + std::string 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; + vector Lines; + XTOSTRUCT(O(OffsetYpx, Lines)) + QvBarPage() : OffsetYpx(5) { } + }; + + struct QvNetSpeedBarConfig { + std::vector Pages; + XTOSTRUCT(O(Pages)) + }; + namespace QvConfigModels { struct Qv2rayCoreInboundsConfig { @@ -90,7 +138,8 @@ namespace Qv2ray string theme; string language; bool useDarkTheme; - XTOSTRUCT(O(theme, language, useDarkTheme)) + bool useDarkTrayIcon; + XTOSTRUCT(O(theme, language, useDarkTheme, useDarkTrayIcon)) }; struct Qv2rayConfig { @@ -182,8 +231,6 @@ namespace Qv2ray speedBarConfig)) }; - // Extra header for QvConfigUpgrade.cpp - QJsonObject UpgradeConfig(int fromVersion, int toVersion, QJsonObject root); } } diff --git a/src/QvConfigUpgrade.cpp b/src/QvConfigUpgrade.cpp index f3a8984d..81eee249 100644 --- a/src/QvConfigUpgrade.cpp +++ b/src/QvConfigUpgrade.cpp @@ -9,110 +9,106 @@ namespace Qv2ray { - namespace QvConfigModels + // Private member + QJsonObject UpgradeConfig_Inc(int fromVersion, QJsonObject root) { - // Private member - 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; - UPDATELOG("Upgrading config_version from old value " + v1_oldConfigVersion.toStdString() + " to 2") - break; - } + 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; + UPDATELOG("Upgrading config_version from old value " + v1_oldConfigVersion.toStdString() + " to 2") + break; + } - case 2 : { - // We copied those files. - auto vCoreFilePath = root["v2CorePath"].toString(); - auto vCoreDestPath = QV2RAY_DEFAULT_VCORE_PATH; - // We also need v2ctl - auto v2CtlFilePath = QFileInfo(vCoreFilePath).dir().path() + "/v2ctl"; - auto v2CtlDestPath = QFileInfo(vCoreDestPath).dir().path() + "/v2ctl"; + case 2 : { + // We copied those files. + auto vCoreFilePath = root["v2CorePath"].toString(); + auto vCoreDestPath = 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"); + v2CtlFilePath = v2CtlFilePath.append(".exe"); + v2CtlDestPath = v2CtlDestPath.append(".exe"); #endif - QFile::copy(vCoreFilePath, vCoreDestPath); - QFile::copy(v2CtlFilePath, v2CtlDestPath); - root.remove("v2CorePath"); - UPDATELOG("v2CorePath value from: " + vCoreFilePath.toStdString() + " to " + vCoreDestPath.toStdString()) - UPDATELOG("v2CtlFilePath value from: " + v2CtlFilePath.toStdString() + " to " + v2CtlDestPath.toStdString()) - 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 - UPDATELOG("key: proxyDefault->enableProxy, value from: " + to_string(oldProxyDefault) + " to " + to_string(oldProxyDefault)) - break; - } - - // -------------------------------------------------------------------------------------- - // Below is for version 2 - case 4: { - // From 2 to 3, we changed the "proxyCN" to "bypassCN" as it's easier to understand.... - auto v2_oldProxyCN = root["proxyCN"].toBool(); - root.remove("proxyCN"); - root.insert("bypassCN", !v2_oldProxyCN); - UPDATELOG("Upgrading proxyCN to bypassCN and changed the value to " + to_string(!v2_oldProxyCN)) - break; - } - - case 5: { - auto v3_oldrunAsRoot = root["runAsRoot"].toBool(); - // From 3 to 4, we changed 'runAsRoot' to 'tProxySupport' - root.remove("runAsRoot"); - root.insert("tProxySupport", v3_oldrunAsRoot); - UPDATELOG("Upgrading runAsRoot to tProxySupport, the value is not changed: " + to_string(v3_oldrunAsRoot)) - break; - } - - case 6: { - root["enableStats"] = true; - UPDATELOG("Default statistics enabled.") - break; - } - - case 7: { - QString path; - path = QV2RAY_DEFAULT_VCORE_PATH; - root["v2CorePath"] = path; - UPDATELOG("Added v2CorePath to the config file.") - break; - } - - case 8: { - auto lang = root["language"].toString(); - QJsonObject uiSettings; - uiSettings["language"] = lang; - root["UISettings"] = uiSettings; - UPDATELOG("Reconstructing config file.") - break; - } + QFile::copy(vCoreFilePath, vCoreDestPath); + QFile::copy(v2CtlFilePath, v2CtlDestPath); + root.remove("v2CorePath"); + UPDATELOG("v2CorePath value from: " + vCoreFilePath.toStdString() + " to " + vCoreDestPath.toStdString()) + UPDATELOG("v2CtlFilePath value from: " + v2CtlFilePath.toStdString() + " to " + v2CtlDestPath.toStdString()) + break; } - root["config_version"] = root["config_version"].toInt() + 1; - return root; - } - - // Exported function - QJsonObject UpgradeConfig(int fromVersion, int toVersion, QJsonObject root) - { - LOG(MODULE_CONFIG, "Migrating config from version " + to_string(fromVersion) + " to " + to_string(toVersion)) - - for (int i = fromVersion; i < toVersion; i++) { - root = UpgradeConfig_Inc(i, root); + case 3 : { + // We changed a key name in the config file. + //proxyDefault + auto oldProxyDefault = root["proxyDefault"].toBool(); + root.remove("proxyDefault"); + root["enableProxy"] = oldProxyDefault; + //enableProxy + UPDATELOG("key: proxyDefault->enableProxy, value from: " + to_string(oldProxyDefault) + " to " + to_string(oldProxyDefault)) + break; } - return root; + // -------------------------------------------------------------------------------------- + // Below is for version 2 + case 4: { + // From 2 to 3, we changed the "proxyCN" to "bypassCN" as it's easier to understand.... + auto v2_oldProxyCN = root["proxyCN"].toBool(); + root.remove("proxyCN"); + root.insert("bypassCN", !v2_oldProxyCN); + UPDATELOG("Upgrading proxyCN to bypassCN and changed the value to " + to_string(!v2_oldProxyCN)) + break; + } + + case 5: { + auto v3_oldrunAsRoot = root["runAsRoot"].toBool(); + // From 3 to 4, we changed 'runAsRoot' to 'tProxySupport' + root.remove("runAsRoot"); + root.insert("tProxySupport", v3_oldrunAsRoot); + UPDATELOG("Upgrading runAsRoot to tProxySupport, the value is not changed: " + to_string(v3_oldrunAsRoot)) + break; + } + + case 6: { + root["enableStats"] = true; + UPDATELOG("Default statistics enabled.") + break; + } + + case 7: { + QString path; + path = QV2RAY_DEFAULT_VCORE_PATH; + root["v2CorePath"] = path; + UPDATELOG("Added v2CorePath to the config file.") + break; + } + + case 8: { + auto lang = root["language"].toString(); + QJsonObject uiSettings; + uiSettings["language"] = lang; + root["UISettings"] = uiSettings; + UPDATELOG("Reconstructing config file.") + break; + } } + root["config_version"] = root["config_version"].toInt() + 1; + return root; + } + + // Exported function + QJsonObject UpgradeConfig(int fromVersion, int toVersion, QJsonObject root) + { + LOG(MODULE_CONFIG, "Migrating config from version " + to_string(fromVersion) + " to " + to_string(toVersion)) + + for (int i = fromVersion; i < toVersion; i++) { + root = UpgradeConfig_Inc(i, root); + } + + return root; } } diff --git a/src/main.cpp b/src/main.cpp index 3dd9ce1f..08bed569 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "QvUtils.hpp" @@ -136,32 +137,40 @@ int main(int argc, char *argv[]) { // This line must be called before any other ones. QApplication _qApp(argc, argv); + // + // Install a default translater. From the OS/DE + auto _lang = QLocale::system().name().replace("_", "-"); + bool _result_ = qApp->installTranslator(getTranslator(_lang)); + LOG(MODULE_UI, "Installing a tranlator from OS: " + _lang.toStdString() + " -- " + (_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 NEWLINE - "Libraries that are used in Qv2ray and their authors are listed below:" NEWLINE - "QJsonModel: Copyright (c) 2011 SCHUTZ Sacha" NEWLINE - "Qv2ray Current Developer Copyright (C) 2019 Leroy.H.Y (@lhy0403)" NEWLINE - "Hv2ray Initial Designs & gRPC implementation Copyright (C) 2019 Hork (@aliyuchang33)" NEWLINE - "Hv2ray/Qv2ray HTTP Request Helper (partial) Copyright 2019 (C) SOneWinstone (@SoneWinstone)" NEWLINE + "under certain conditions." NEWLINE NEWLINE + "Copyright (C) 2019 Leroy.H.Y (@lhy0403): Qv2ray Current Developer" NEWLINE + "Copyright (C) 2019 Hork (@aliyuchang33): Hv2ray Initial Designs & gRPC implementation " NEWLINE + "Copyright (C) 2019 SOneWinstone (@SoneWinstone): Hv2ray/Qv2ray HTTP Request Helper" NEWLINE "Qv2ray ArtWork Done By ArielAxionL (@axionl)" NEWLINE - "Qv2ray Russian Translations By TheBadGateway (@thebadgateway)" NEWLINE - "Qv2ray patch 8a8c1a By Riko (@rikakomoe)" NEWLINE + "TheBadGateway (@thebadgateway): Qv2ray Russian Translations" NEWLINE + "Riko (@rikakomoe): Qv2ray patch 8a8c1a/PR115" + NEWLINE NEWLINE + "Libraries that have been used in Qv2ray are listed below (Sorted by date added):" NEWLINE + "Copyright (c) 2019 dridk (@dridk): X2Struct (Apache)" NEWLINE + "Copyright (c) 2011 SCHUTZ Sacha (@dridk): QJsonModel (MIT)" NEWLINE + "Copyright (c) 2019 Nikolaos Ftylitakis (@ftylitak): QZXing (Apache2)" NEWLINE + "Copyright (c) 2016 Singein (@Singein): ScreenShot (MIT)" NEWLINE NEWLINE "Qv2ray " QV2RAY_VERSION_STRING " running on " + - (QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture()).toStdString() + - NEWLINE) + (QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture()).toStdString() + NEWLINE) // LOG(MODULE_INIT, "Qv2ray Start Time: " + QString::number(QTime::currentTime().msecsSinceStartOfDay()).toStdString()) - DEBUG("DEBUG", "============================== This is a debug build, many features are not stable enough. ==============================") + DEBUG("DEBUG", "WARNING: ============================== This is a debug build, many features are not stable enough. ==============================") // // Initialise the language list. auto langs = GetFileList(QDir(":/translations")); if (langs.empty()) { LOG(MODULE_INIT, "FAILED to find any translations. THIS IS A BUILD ERROR.") - QvMessageBox(nullptr, "Cannot load languages", "Qv2ray will continue running, but you cannot change the UI language."); + QvMessageBox(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.toStdString()) @@ -201,7 +210,7 @@ int main(int argc, char *argv[]) QObject::tr("Qv2ray will now exit.")); return -3; } else if (confVersion != newVersion) { - conf = UpgradeConfig(confVersion.toInt(), QV2RAY_CONFIG_VERSION, conf); + conf = Qv2ray::UpgradeConfig(confVersion.toInt(), QV2RAY_CONFIG_VERSION, conf); } auto confObject = StructFromJsonString(JsonToString(conf)); @@ -291,6 +300,7 @@ int main(int argc, char *argv[]) MainWindow w; return _qApp.exec(); } catch (std::exception *ex) { + QvMessageBox(nullptr, "ERROR", QSTRING(ex->what())); LOG(MODULE_INIT, ex->what()) return -9; } diff --git a/src/ui/w_ExportConfig.ui b/src/ui/w_ExportConfig.ui index 5eae2daf..13b27563 100644 --- a/src/ui/w_ExportConfig.ui +++ b/src/ui/w_ExportConfig.ui @@ -6,8 +6,8 @@ 0 0 - 549 - 493 + 532 + 666 @@ -23,7 +23,7 @@ - :/icons/qv2ray.ico + :/icons/qv2ray.png false diff --git a/src/ui/w_ImportConfig.cpp b/src/ui/w_ImportConfig.cpp index 257be1f3..b90df9f1 100644 --- a/src/ui/w_ImportConfig.cpp +++ b/src/ui/w_ImportConfig.cpp @@ -39,7 +39,7 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() { // QRubberBand QThread::msleep(static_cast(doubleSpinBox->value() * 1000)); - bool hasVmessDetected = false; + //bool hasVmessDetected = false; //for (auto screen : qApp->screens()) { // if (!screen) { // LOG(MODULE_UI, "Cannot even find a screen. RARE") @@ -54,8 +54,9 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() if (w.result() == QDialog::Accepted) { auto str = QZXing().decodeImage(pix); - if (str.isEmpty()) { + if (str.trimmed().isEmpty()) { LOG(MODULE_UI, "Cannot decode QR Code from an image, size: h=" + to_string(pix.width()) + ", v=" + to_string(pix.height())) + QvMessageBox(this, tr("Capture QRCode"), tr("Cannot find a valid QRCode from this region.")); // continue; } else { vmessConnectionStringTxt->appendPlainText(str.trimmed() + NEWLINE); @@ -240,3 +241,31 @@ void ImportConfigWindow::on_editFileBtn_clicked() LOG(MODULE_FILE, "Canceled saving a file.") } } + +void ImportConfigWindow::on_connectionEditBtn_clicked() +{ + OutboundEditor *w = new OutboundEditor(this); + auto outboundEntry = w->OpenEditor(); + bool isChanged = w->result() == QDialog::Accepted; + QString alias = w->GetFriendlyName(); + delete w; + + if (isChanged) { + QJsonArray outboundsList; + outboundsList.push_back(outboundEntry); + QJsonObject root; + root.insert("outbounds", outboundsList); + // + // WARN This one will change the connection name, because of some duplicates. + SaveConnectionConfig(root, &alias, false); + // + auto conf = GetGlobalConfig(); + auto connectionList = conf.configs; + connectionList.push_back(alias.toStdString()); + conf.configs = connectionList; + SetGlobalConfig(conf); + close(); + } else { + return; + } +} diff --git a/src/ui/w_ImportConfig.hpp b/src/ui/w_ImportConfig.hpp index 0be46d33..315ddffc 100644 --- a/src/ui/w_ImportConfig.hpp +++ b/src/ui/w_ImportConfig.hpp @@ -25,6 +25,8 @@ class ImportConfigWindow : public QDialog, private Ui::ImportConfigWindow void on_editFileBtn_clicked(); + void on_connectionEditBtn_clicked(); + private: QMap vmessErrors; }; diff --git a/src/ui/w_ImportConfig.ui b/src/ui/w_ImportConfig.ui index 5cecb7d3..34f9071b 100644 --- a/src/ui/w_ImportConfig.ui +++ b/src/ui/w_ImportConfig.ui @@ -68,6 +68,11 @@ Subscription Link + + + Manually Input + + @@ -154,7 +159,7 @@ - From QRCode + From QRCode File @@ -278,14 +283,14 @@ - TextLabel + Error List - TextLabel + VMess @@ -325,6 +330,31 @@ + + + + + + Connection Editor + + + + + + + Open Connection Editor + + + + + + + Maunally input connection details + + + + + diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 3fd7a05d..a066bc70 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -37,8 +37,20 @@ MainWindow::MainWindow(QWidget *parent) auto conf = GetGlobalConfig(); vinstance = new Qv2Instance(this); setupUi(this); - this->setWindowIcon(QIcon(":/icons/qv2ray.ico")); - hTray->setIcon(this->windowIcon()); + // + this->setWindowIcon(QIcon(":/icons/qv2ray.png")); + hTray->setIcon(QIcon(conf.UISettings.useDarkTrayIcon ? ":/icons/ui_dark/tray.png" : ":/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)"); + // hTray->setToolTip(TRAY_TOOLTIP_PREFIX); // QAction *action_Tray_ShowHide = new QAction(this->windowIcon(), tr("Hide"), this); @@ -49,8 +61,8 @@ MainWindow::MainWindow(QWidget *parent) // QAction *action_RCM_RenameConnection = new QAction(tr("Rename"), this); QAction *action_RCM_StartThis = new QAction(tr("Connect to this"), this); - QAction *action_RCM_EditJson = new QAction(tr("Edit as Json"), this); - QAction *action_RCM_ShareQR = new QAction(tr("Share as QRCode/vmess Uri"), 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); // action_Tray_Start->setEnabled(true); action_Tray_Stop->setEnabled(false); @@ -91,7 +103,7 @@ MainWindow::MainWindow(QWidget *parent) LoadConnections(); QObject::connect(&HTTPRequestHelper, &QvHttpRequestHelper::httpRequestFinished, this, &MainWindow::VersionUpdate); HTTPRequestHelper.get("https://api.github.com/repos/lhy0403/Qv2ray/releases/latest"); - bool hasAutoStart = false; + bool hasAutoStart = false; // // For charts uploadSerie = new QSplineSeries(this); @@ -571,40 +583,11 @@ void MainWindow::on_removeConfigButton_clicked() void MainWindow::on_importConfigButton_clicked() { - // TODO ImportConfigWindow *w = new ImportConfigWindow(this); w->exec(); OnConfigListChanged(false); } -void MainWindow::on_addConfigButton_clicked() -{ - OutboundEditor *w = new OutboundEditor(this); - connect(w, &OutboundEditor::s_reload_config, this, &MainWindow::OnConfigListChanged); - auto outboundEntry = w->OpenEditor(); - bool isChanged = w->result() == QDialog::Accepted; - QString alias = w->GetFriendlyName(); - delete w; - - if (isChanged) { - QJsonArray outboundsList; - outboundsList.push_back(outboundEntry); - QJsonObject root; - root.insert("outbounds", outboundsList); - // - // WARN This one will change the connection name, because of some duplicates. - SaveConnectionConfig(root, &alias, false); - // - auto conf = GetGlobalConfig(); - auto connectionList = conf.configs; - connectionList.push_back(alias.toStdString()); - conf.configs = connectionList; - SetGlobalConfig(conf); - OnConfigListChanged(false); - ShowAndSetConnection(CurrentConnectionName, false, false); - } -} - void MainWindow::on_editConfigButton_clicked() { // Check if we have a connection selected... @@ -705,7 +688,7 @@ void MainWindow::on_shareBtn_clicked() } } -void MainWindow::on_action_RCM_ShareQR_triggered() +void MainWindow::on_action_RCM_ShareQR_triggered(bool checked) { on_shareBtn_clicked(); } diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 6c46429d..aca8a00b 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -27,7 +27,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow void UpdateLog(); void OnConfigListChanged(bool need_restart); private slots: - void on_action_RCM_ShareQR_triggered(); + void on_action_RCM_ShareQR_triggered(bool checked = false); void on_startButton_clicked(); void on_stopButton_clicked(); void on_reconnectButton_clicked(); @@ -56,8 +56,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow void on_importConfigButton_clicked(); - void on_addConfigButton_clicked(); - void on_editConfigButton_clicked(); void on_editJsonBtn_clicked(); diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index 88b7d54b..b6be494f 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -9,8 +9,8 @@ 0 0 - 680 - 585 + 740 + 590 @@ -21,8 +21,8 @@ - 680 - 585 + 740 + 590 @@ -41,7 +41,7 @@ 530 - + @@ -175,27 +175,7 @@ - - - - 0 - 0 - - - - Add new connection manually - - - A - - - - :/icons/add_connection_btn.png:/icons/add_connection_btn.png - - - - - + 0 @@ -206,26 +186,34 @@ Import connection - I + Add - - - :/icons/import_connection_btn.png:/icons/import_connection_btn.png + + + 22 + 22 + - + Duplicate connection - D + Duplicate + + + + 22 + 22 + - + 0 @@ -236,35 +224,29 @@ Delete a connection - R + Delete - - - :/icons/remove_connection_btn.png:/icons/remove_connection_btn.png + + + 22 + 22 + - + Edit connection - ... + Edit - - - :/icons/edit_connection_btn.png:/icons/edit_connection_btn.png - - - - - - - Edit connection as JSON - - - { } + + + 22 + 22 + @@ -290,7 +272,7 @@ Config Details - + @@ -365,6 +347,13 @@ + + + + Actions + + + @@ -381,17 +370,45 @@ - + + + Edit connection as JSON + - Ping + Edit JSON + + + + 22 + 22 + - + + + Ping Test + + + + 22 + 22 + + + + + + Share + + + 22 + 22 + + @@ -462,134 +479,124 @@ - + - - - Speed - - - - - - - - 32 - 32 - - - - - 25 - 25 - - - - border-image: url(:/icons/netspeed-arrows.svg) 0 0 0 0 stretch stretch;background-repeat: no-repeat; - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - 8 - - - - 0.00 B/s + + + + + Speed + + + + + + + + 32 + 32 + + + + + 25 + 25 + + + + + + + + + 8 + + + + 0.00 B/s 0.00 B/s - - + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Data - - - - - - - - 32 - 32 - - - - - 25 - 25 - - - - border-image: url(:/icons/netspeed-arrows.svg) 0 0 0 0 stretch stretch;background-repeat: no-repeat; - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - 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 + + + + + @@ -637,8 +644,6 @@ stopButton clearlogButton - - - + diff --git a/src/ui/w_PrefrencesWindow.cpp b/src/ui/w_PrefrencesWindow.cpp index 745dd3f8..f7f81e22 100644 --- a/src/ui/w_PrefrencesWindow.cpp +++ b/src/ui/w_PrefrencesWindow.cpp @@ -5,8 +5,9 @@ #include "QvUtils.hpp" #include "QvCoreInteractions.hpp" -#include "w_PrefrencesWindow.hpp" +#include "QvNetSpeedPlugin.hpp" +#include "w_PrefrencesWindow.hpp" #define LOADINGCHECK if(!finishedLoading) return; #define NEEDRESTART if(finishedLoading) IsConnectionPropertyChanged = true; @@ -29,13 +30,16 @@ PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent), themeCombo->addItems(QStyleFactory::keys()); // qvVersion->setText(QV2RAY_VERSION_STRING); + qvBuildTime->setText(__DATE__ " " __TIME__); CurrentConfig = GetGlobalConfig(); // themeCombo->setCurrentText(QSTRING(CurrentConfig.UISettings.theme)); - darkChartThemeCB->setChecked(CurrentConfig.UISettings.useDarkTheme); + darkThemeCB->setChecked(CurrentConfig.UISettings.useDarkTheme); + darkTrayCB->setChecked(CurrentConfig.UISettings.useDarkTrayIcon); #if QV2RAY_USE_BUILTIN_DARKTHEME // If we use built in theme, it should always be fusion. themeCombo->setEnabled(!CurrentConfig.UISettings.useDarkTheme); + darkThemeLabel->setText(tr("Use Dark Theme")); #endif languageComboBox->setCurrentText(QSTRING(CurrentConfig.UISettings.language)); logLevelComboBox->setCurrentIndex(CurrentConfig.logLevel); @@ -339,7 +343,7 @@ void PrefrencesWindow::on_tProxyCheckBox_stateChanged(int arg1) auto v2ctlPath = QFileInfo(QSTRING(CurrentConfig.v2CorePath)).path() + "/v2ctl"; auto newPath = QFileInfo(QV2RAY_DEFAULT_VCORE_PATH).path(); // - LOG(MODULE_FILE, " --> Origin v2ray core file is at: " + v2ctlPath.toStdString() + "/v2ctl") + LOG(MODULE_FILE, " --> Origin v2ctl file is at: " + v2ctlPath.toStdString()) LOG(MODULE_FILE, " --> New v2ray files will be placed in: " << newPath.toStdString()) // LOG(MODULE_FILE, " --> Copying files....") @@ -712,10 +716,11 @@ void PrefrencesWindow::on_themeCombo_currentTextChanged(const QString &arg1) CurrentConfig.UISettings.theme = arg1.toStdString(); } -void PrefrencesWindow::on_darkChartThemeCB_stateChanged(int arg1) +void PrefrencesWindow::on_darkThemeCB_stateChanged(int arg1) { LOADINGCHECK CurrentConfig.UISettings.useDarkTheme = arg1 == Qt::Checked; + QvMessageBox(this, tr("Dark Mode"), tr("Please restart Qv2ray to fully apply this feature.")); #if QV2RAY_USE_BUILTIN_DARKTHEME themeCombo->setEnabled(arg1 != Qt::Checked); @@ -726,3 +731,8 @@ void PrefrencesWindow::on_darkChartThemeCB_stateChanged(int arg1) #endif } + +void PrefrencesWindow::on_darkTrayCB_stateChanged(int arg1) +{ + CurrentConfig.UISettings.useDarkTrayIcon = arg1 == Qt::Checked; +} diff --git a/src/ui/w_PrefrencesWindow.hpp b/src/ui/w_PrefrencesWindow.hpp index 5e13fd81..bb0b2e4b 100644 --- a/src/ui/w_PrefrencesWindow.hpp +++ b/src/ui/w_PrefrencesWindow.hpp @@ -116,7 +116,9 @@ class PrefrencesWindow : public QDialog, private Ui::PrefrencesWindow void on_themeCombo_currentTextChanged(const QString &arg1); - void on_darkChartThemeCB_stateChanged(int arg1); + void on_darkThemeCB_stateChanged(int arg1); + + void on_darkTrayCB_stateChanged(int arg1); private: // Set ui parameters for a line; diff --git a/src/ui/w_PrefrencesWindow.ui b/src/ui/w_PrefrencesWindow.ui index 30e5e916..6ef68607 100644 --- a/src/ui/w_PrefrencesWindow.ui +++ b/src/ui/w_PrefrencesWindow.ui @@ -6,20 +6,14 @@ 0 0 - 789 - 500 + 797 + 560 - - - 0 - 0 - - 780 - 500 + 560 @@ -70,27 +64,27 @@ - + - Use Dark Theme + Dark Theme Support - + Enabled - + Language - + @@ -116,14 +110,14 @@ - + Log Level - + @@ -164,14 +158,14 @@ - + Automatically Connect To - + @@ -186,28 +180,28 @@ - + Transparent Proxy Support - + Enabled - + v2ray Core Path - + @@ -221,14 +215,14 @@ - + v2ray Assets Path - + @@ -242,6 +236,27 @@ + + + + Dark Tray Icon + + + + + + + Enabled + + + + + + + CheckBox + + + @@ -757,23 +772,39 @@ - - ... + + + 0 + 0 + - - - :/icons/remove_connection_btn.png:/icons/remove_connection_btn.png + + + 26 + 26 + + + + - - - ... + + + 0 + 0 + - - - :/icons/add_connection_btn.png:/icons/add_connection_btn.png + + + 26 + 26 + + + + + @@ -820,23 +851,39 @@ - - ... + + + 0 + 0 + - - - :/icons/remove_connection_btn.png:/icons/remove_connection_btn.png + + + 26 + 26 + + + + - - - ... + + + 0 + 0 + - - - :/icons/add_connection_btn.png:/icons/add_connection_btn.png + + + 26 + 26 + + + + + @@ -1051,31 +1098,42 @@ About - + - - - - 0 - 0 - - - - - 256 - 256 - - - - background-image: url(:/icons/qv2ray.ico);background-repeat: no-repeat; - - - QFrame::StyledPanel - - - QFrame::Raised - - + + + + + + 0 + 0 + + + + + 256 + 256 + + + + image: url(:/icons/qv2ray.ico); + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + @@ -1084,7 +1142,7 @@ - 17 + 24 @@ -1096,6 +1154,11 @@ + + + 15 + + Version: @@ -1105,7 +1168,7 @@ - 10 + 15 @@ -1126,51 +1189,29 @@ - - + + + + + + + + + Built Time - - - - - 10 - - - - TIME - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - + - Official Repo: + Official Repo - + @@ -1178,11 +1219,6 @@ 0 - - - 10 - - <html><head/><body><p><a href="https://github.com/lhy0403/Qv2ray"><span style=" text-decoration: underline; color:#2980b9;">https://github.com/lhy0403/Qv2ray</span></a></p></body></html> @@ -1197,21 +1233,21 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -1264,24 +1300,41 @@ - - - Qt::Vertical + + + QTextEdit::NoWrap - - - 20 - 40 - + + true - + + <!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:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Noto Sans'; color:#d69545;">This</span><span style=" font-family:'Noto Sans'; color:#bec0c2;"> </span><span style=" font-family:'Noto Sans'; color:#d69545;">program</span><span style=" font-family:'Noto Sans'; color:#bec0c2;"> </span><span style=" font-family:'Noto Sans'; color:#d69545;">comes</span><span style=" font-family:'Noto Sans'; color:#bec0c2;"> </span><span style=" font-family:'Noto Sans'; color:#d69545;">with</span><span style=" font-family:'Noto Sans'; color:#bec0c2;"> </span><span style=" font-family:'Noto Sans'; color:#d69545;">ABSOLUTELY</span><span style=" font-family:'Noto Sans'; color:#bec0c2;"> </span><span style=" font-family:'Noto Sans'; color:#d69545;">NO</span><span style=" font-family:'Noto Sans'; color:#bec0c2;"> </span><span style=" font-family:'Noto Sans'; color:#d69545;">WARRANTY.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">This</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">is</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">free</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">software,</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">and</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">you</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">are</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">welcome</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">to</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">redistribute</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">it under</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">certain</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">conditions.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(C)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2019</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Leroy.H.Y</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@lhy0403):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Qv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Current</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Developer</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(C)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2019</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Hork</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@aliyuchang33):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Hv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Initial</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Designs</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">&amp;</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">gRPC</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">implementation</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(C)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2019</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">SOneWinstone</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@SoneWinstone):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Hv2ray/Qv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">HTTP</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Request</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Helper</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Qv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">ArtWork</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Done</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">By</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">ArielAxionL</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@axionl)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">TheBadGateway</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@thebadgateway):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Qv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Russian</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Translations</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Riko</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@rikakomoe):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Qv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">patch</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">8a8c1a/PR115</span></p> +<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; font-family:'Hack';"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Libraries</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">that</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">have</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">been</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">used</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">in</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Qv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">are</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">listed</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">below</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(Sorted</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">by</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">date</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">added):</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(c)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2019</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">dridk</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@dridk):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">X2Struct</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(Apache)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(c)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2011</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">SCHUTZ</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Sacha</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@dridk):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">QJsonModel</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(MIT)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(c)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2019</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Nikolaos</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Ftylitakis</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@ftylitak):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">QZXing</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(Apache2)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(c)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2016</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Singein</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@Singein):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">ScreenShot</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(MIT)</span></p></body></html> + + - Ingore Next Version + Ignore Next Version @@ -1336,9 +1389,7 @@ - - - + buttonBox diff --git a/src/ui/w_RoutesEditor.cpp b/src/ui/w_RoutesEditor.cpp index c9eefb5a..8498967c 100644 --- a/src/ui/w_RoutesEditor.cpp +++ b/src/ui/w_RoutesEditor.cpp @@ -12,8 +12,13 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : root(connection), original(connection) { - // TODO Balancer will not be removed if an rule has been removed. setupUi(this); + addInboundBtn->setIcon(QICON_R("add.png")); + addOutboundBtn->setIcon(QICON_R("add.png")); + editInboundBtn->setIcon(QICON_R("edit.png")); + editOutboundBtn->setIcon(QICON_R("edit.png")); + delInboundBtn->setIcon(QICON_R("delete.png")); + delOutboundBtn->setIcon(QICON_R("delete.png")); // inbounds = root["inbounds"].toArray(); outbounds = root["outbounds"].toArray(); diff --git a/src/ui/w_RoutesEditor.ui b/src/ui/w_RoutesEditor.ui index e1facff9..bee3c8ed 100644 --- a/src/ui/w_RoutesEditor.ui +++ b/src/ui/w_RoutesEditor.ui @@ -67,33 +67,21 @@ - ... - - - - :/icons/add_connection_btn.png:/icons/add_connection_btn.png + A - ... - - - - :/icons/remove_connection_btn.png:/icons/remove_connection_btn.png + D - - - - - :/icons/edit_connection_btn.png:/icons/edit_connection_btn.png + E @@ -218,33 +206,21 @@ - ... - - - - :/icons/add_connection_btn.png:/icons/add_connection_btn.png + A - ... - - - - :/icons/remove_connection_btn.png:/icons/remove_connection_btn.png + D - - - - - :/icons/edit_connection_btn.png:/icons/edit_connection_btn.png + E @@ -441,7 +417,7 @@ ... - + :/icons/add_connection_btn.png:/icons/add_connection_btn.png @@ -452,7 +428,7 @@ ... - + :/icons/remove_connection_btn.png:/icons/remove_connection_btn.png @@ -669,7 +645,7 @@ ... - + :/icons/remove_connection_btn.png:/icons/remove_connection_btn.png @@ -693,7 +669,7 @@ ... - + :/icons/add_connection_btn.png:/icons/add_connection_btn.png @@ -726,9 +702,7 @@ - - - + buttonBox diff --git a/src/ui/w_ScreenShot_Core.cpp b/src/ui/w_ScreenShot_Core.cpp index 6786d935..56380921 100644 --- a/src/ui/w_ScreenShot_Core.cpp +++ b/src/ui/w_ScreenShot_Core.cpp @@ -2,19 +2,45 @@ #include "QvUtils.hpp" #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 + this->setStyle(QStyleFactory::create("Fusion")); + // + LOG(MODULE_IMPORT, "We currently only support the primary screen.") QRect deskRect = qApp->screens().first()->geometry(); - width = deskRect.width(); - height = deskRect.height(); // setMouseTracking(true); - resize(width, height); - setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowType::Dialog); + resize(deskRect.size()); + setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); + // + desktopImage = QGuiApplication::primaryScreen()->grabWindow(0); + int w = desktopImage.width(); + int h = desktopImage.height(); + QImage bg_grey(w, h, QImage::Format_RGB32); + // + int r, g, b; + auto _xdesktopImg = desktopImage.toImage(); + + 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); + bg_grey.setPixel(i, j, qRgb(r, g, b)); + } + } + + this->showFullScreen(); + auto p = this->palette(); + p.setBrush(QPalette::Background, bg_grey); + setPalette(p); // - setBackground(width, height, 0.6f); label->setAttribute(Qt::WA_TranslucentBackground); startBtn->setAttribute(Qt::WA_TranslucentBackground); // @@ -23,8 +49,8 @@ ScreenShotWindow::ScreenShotWindow() : QDialog(), rubber(new QRubberBand(QRubber label->setPalette(pal); startBtn->setPalette(pal); // - label->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); - startBtn->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); + label->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint); + startBtn->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint); // label->hide(); startBtn->hide(); @@ -37,55 +63,61 @@ QImage ScreenShotWindow::DoScreenShot() return resultImage; } -void ScreenShotWindow::pSize() //获取截图位置坐标 +void ScreenShotWindow::pSize() { - pw = abs(end.x() - origin.x()); - ph = abs(end.y() - origin.y()); - px = origin.x() < end.x() ? origin.x() : end.x(); - py = origin.y() < end.y() ? origin.y() : end.y(); + imgW = abs(end.x() - origin.x()); + 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", to_string(imgW) + " " + to_string(imgH) + " " + to_string(imgX) + " " + to_string(imgY)) + fg->setPixmap(desktopImage.copy(imgX, imgY, imgW, imgH)); + fg->setGeometry(imgX, imgY, imgW, imgH); + rubber->setGeometry(imgX, imgY, imgW, imgH); } void ScreenShotWindow::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Escape) { - this->close(); + reject(); + } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { + on_startBtn_clicked(); } } -void ScreenShotWindow::mousePressEvent(QMouseEvent *e) //鼠标按下 +void ScreenShotWindow::mousePressEvent(QMouseEvent *e) { origin = e->pos(); LOG(MODULE_UI, "Start capturing mouse") rubber->setGeometry(origin.x(), origin.y(), 0, 0); rubber->show(); - label->show(); - startBtn->show(); + rubber->raise(); + label->hide(); + startBtn->hide(); } -void ScreenShotWindow::mouseMoveEvent(QMouseEvent *e) //鼠标移动 +void ScreenShotWindow::mouseMoveEvent(QMouseEvent *e) { if (e->buttons() & Qt::LeftButton) { end = e->pos(); pSize(); - rubber->setGeometry(px, py, pw, ph); // - QString size = QString("%1x%2").arg(pw).arg(ph); - label->setText(size); + label->setText(QString("%1x%2").arg(imgW).arg(imgH)); + // // QRect labelRect(label->contentsRect()); QRect btnRect(startBtn->contentsRect()); - if (py > labelRect.height()) { - label->move(QPoint(px, py - labelRect.height())); + if (imgY > labelRect.height()) { + label->move(QPoint(imgX, imgY - labelRect.height())); } else { - label->move(QPoint(px, py)); + label->move(QPoint(imgX, imgY)); } - if (height - py - ph > btnRect.height()) { - startBtn->move(QPoint(px + pw - btnRect.width(), py + ph)); - } else { - startBtn->move(QPoint(px + pw - btnRect.width(), py + ph - btnRect.height())); + if (height() - imgY - imgH > btnRect.height()) { + startBtn->move(QPoint(imgX + imgW - btnRect.width(), imgY + imgH)); + } else { + startBtn->move(QPoint(imgX + imgW - btnRect.width(), imgY + imgH - btnRect.height())); } label->show(); @@ -94,41 +126,17 @@ void ScreenShotWindow::mouseMoveEvent(QMouseEvent *e) //鼠标移动 } -void ScreenShotWindow::mouseReleaseEvent(QMouseEvent *e) //鼠标松开 +void ScreenShotWindow::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == Qt::RightButton) { - close(); + reject(); } } -void ScreenShotWindow::setBackground(int w, int h, float n) //定格当前屏幕 -{ - QScreen *screen = QGuiApplication::primaryScreen(); - bg = screen->grabWindow(0).toImage(); - QImage bg_grey(w, h, QImage::Format_RGB32); - // - int r, g, b; - - for (int i = 0; i < w; i++) { - for (int j = 0; j < h; j++) { - // - r = static_cast(qRed(bg.pixel(i, j)) * n); - g = static_cast(qGreen(bg.pixel(i, j)) * n); - b = static_cast(qBlue(bg.pixel(i, j)) * n); - // - bg_grey.setPixel(i, j, qRgb(r, g, b)); - } - } - - QPalette palette; - palette.setBrush(this->backgroundRole(), QBrush(bg_grey)); - this->setPalette(palette); - this->showFullScreen(); -} void ScreenShotWindow::on_startBtn_clicked() { - resultImage = bg.copy(px, py, pw, ph); + resultImage = desktopImage.copy(imgX, imgY, imgW, imgH).toImage(); rubber->hide(); - close(); + accept(); } diff --git a/src/ui/w_ScreenShot_Core.hpp b/src/ui/w_ScreenShot_Core.hpp index 3e8f0c0b..921409fe 100644 --- a/src/ui/w_ScreenShot_Core.hpp +++ b/src/ui/w_ScreenShot_Core.hpp @@ -25,23 +25,21 @@ class ScreenShotWindow : public QDialog, private Ui::ScreenShot void mousePressEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; void keyPressEvent(QKeyEvent *e) override; - void setBackground(int w, int h, float n); private slots: void on_startBtn_clicked(); private: + QRubberBand *rubber; + // Desktop Image + QPixmap desktopImage; + QImage windowBg; QImage resultImage; // - QRubberBand *rubber; - // - QPoint origin;//鼠标起始位置 - QPoint end;//鼠标结束位置 - QImage bg;//存贮当前桌面截图 - - int width, height; - int pw, ph, px, py; + QPoint origin; + QPoint end; + int imgW, imgH, imgX, imgY; void pSize(); }; diff --git a/src/ui/w_ScreenShot_Core.ui b/src/ui/w_ScreenShot_Core.ui index 35905a04..8275875a 100644 --- a/src/ui/w_ScreenShot_Core.ui +++ b/src/ui/w_ScreenShot_Core.ui @@ -32,14 +32,14 @@ - TextLabel + Size 20 - 40 + 60 80 26 @@ -48,6 +48,19 @@ Screen Shot + + + + 30 + 140 + 58 + 18 + + + + FG + + diff --git a/src/utils/QvNetSpeedPlugin.hpp b/src/utils/QvNetSpeedPlugin.hpp index cf4d7234..44a87915 100644 --- a/src/utils/QvNetSpeedPlugin.hpp +++ b/src/utils/QvNetSpeedPlugin.hpp @@ -1,8 +1,7 @@ #ifndef QVNETSPEEDBARJSON_H #define QVNETSPEEDBARJSON_H -#include "x2struct/x2struct.hpp" -#include +#include "Qv2rayBase.hpp" // // For Windows #ifdef Q_OS_WIN @@ -58,40 +57,6 @@ namespace Qv2ray } #endif - struct QvBarLine { - std::string Family; - bool Bold; - bool Italic; - int ColorA; - int ColorR; - int ColorG; - int ColorB; - int ContentType; - double Size; - std::string 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; - std::vector Lines; - XTOSTRUCT(O(OffsetYpx, Lines)) - QvBarPage() : OffsetYpx(5) { } - }; - - struct QvNetSpeedBarConfig { - std::vector Pages; - XTOSTRUCT(O(Pages)) - }; - QString GetAnswerToRequest(const QString &pchRequest); } diff --git a/src/utils/QvTinyLog.hpp b/src/utils/QvTinyLog.hpp index 40698d3d..7517fea9 100644 --- a/src/utils/QvTinyLog.hpp +++ b/src/utils/QvTinyLog.hpp @@ -11,7 +11,7 @@ using namespace std; #define XLOG(module, level, msg) LOG(module, level << msg) #ifdef QT_DEBUG -#define DEBUG(module, msg) LOG(module, msg) +#define DEBUG(module, msg) LOG("[DEBUG] - " module, msg) #else #define DEBUG(module, msg) #endif diff --git a/translations/en-US.ts b/translations/en-US.ts index 8d83ae32..05d09eb1 100644 --- a/translations/en-US.ts +++ b/translations/en-US.ts @@ -13,26 +13,21 @@ ExportConfigWindow - Dialog + Export Config - - Image - - - - + Text Message - + Save - + OK @@ -46,7 +41,7 @@ - Name + Name/Prefix @@ -54,12 +49,6 @@ Import Source - - - - Subscription Link - - Existing File @@ -70,9 +59,15 @@ VMess and QRCode + + + + Subscription Link + + - + Import @@ -123,87 +118,119 @@ - - Delay in secs - - - - - Place your vmess:// here, one line for each. - - - - - Cancel - - - - - TO DO IN VERSION 2 - - - - - GroupBox - - - - + Go - + + After + + + + + second(s). + + + + + Place your vmess:// here, one line for each. + + + + + Error List + + + + + VMess + + + + + TO DO IN VERSION 2 + + + + + GroupBox + + + + + Cancel + + + + Select file to import - - - QRCode Scanning Failed - - - - - Cannot find a screen, it's rare. - - - - - Cannot find a qrcode from the primary screen. - - - - + + Import config file - + + Import from file failed, for more information, please check the log file. + + + + Failed to check the validity of the config file. - - - VMess String Check + + + Assertion Failed - - VMess string is not valid. + + Assertion failed: ::SaveConnectionConfig should returns false. - - VMess config is not valid. - - - - + 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 the required permissions + + InboundEditor @@ -484,6 +511,11 @@ Dialog + + + OK + + Json Structure Preview @@ -499,11 +531,6 @@ Json Editor - - - OK - - @@ -536,19 +563,19 @@ - + Connect - + Disconnect - + Reconnect @@ -577,292 +604,302 @@ Add new connection manually - - - Import connection - - - - - Duplicate connection - - - - - D - - - - - Delete a connection - - - - - Edit connection - - - - - Edit connection as JSON - - - - - { } - - - - - Config Details - - - - - Ping - - A - - Share + + Import connection - - #ImportConnection + + Imp - - I + + Duplicate connection - - ... + + Dup - - R + + Delete a connection - + + D + + + + + Edit connection + + + + + E + + + + + Config Details + + + + Config Type - + Protocol - + Address - + Port Number - + Mux - + + Edit connection as JSON + + + + + J + + + + + P + + + + + S + + + + Log - + Speed Graph - + Speed - + 0.00 B/s 0.00 B/s - + Data - + 0.00 B 0.00 B - + #ManuallyCreateConnection - + + #ImportConnection + + + + #Exit - + #Preferences - + #Start - + #Stop - + #Restart - - + + Hide - + Quit - + Rename - + Connect to this - + Edit as Json - - Share as QRCode/vmess Uri + + Share as QRCode/VMess URL - - - + + + Show - - Update - - - - - Found a new version: - - - - - Download Link: - - - - - + + No connection selected! - - + + Please select a config from the list. - - - + + Update + + + + + Found a new version: + + + + + Download Link: + + + + + + Connected To Server: - + + Connected + + + + Disconnected - - + + Rename a Connection - + The name cannot be empty - + + The name has been used already, Please choose another. + + + + Removing this Connection + Are you sure to remove this connection? + + + + Failed to delete connection file, please delete manually. - - + + No Config Selected - - + + Please Select a Config - - The name has been used already, Please choose another. + + Share Connection - - Connected - - - - - Are you sure to remove this connection? + + There're no support of sharing configs other than vmess @@ -1107,565 +1144,554 @@ PrefrencesWindow - - - - - + + + + + Prefrences - + General - + UI Theme - - Dark Chart Theme + + Dark Theme Support - - Language - - - - - zh-CN - - - - - en-US - - - - - Log Level - - - - - none - - - - - debug - - - - - info - - - - - warning - - - - - error - - - - - Automatically Connect To - - - - - Transparent Proxy Support - - - - - - - - - - - - - - - - + + + + + + + + + + + + + Enabled - - v2ray Assets Path + + Language - - - Select + + zh-CN - - Connection Settings + + en-US - - General Connection Settings + + Log Level - - Statistics + + none - - API Port + + debug - + + info + + + + + warning + + + + + error + + + + + Automatically Connect To + + + + + Transparent Proxy Support + + + + v2ray Core Path - - - - Port + + + Select - - - - Authentication + + v2ray Assets Path - - - - Username - - - - - - - Password - - - - - Listening Address - - - - + Inbound Settings - + + Listening Address + + + + + Enable PAC + + + + + LISTEN_ADDR + + + + + /pac.txt + + + + + Choose File + + + + SOCKS Inbound Settings - + + + + Port + + + + SOCKS UDP - + Local IP - + + + + Authentication + + + + + + + Username + + + + + + + Password + + + + HTTP Inbound Settings - + + Connection Settings + + + + + General Connection Settings + + + + Enable Proxy - + Bypass Chinese Mainland - + + Statistics + + + + + API Port + + + + Use Local DNS - + DNS List - - Items - - - - - - - - - ... - - - - - Page Y Offset - - - - - Pages - - - - - Lines - - - - - Text Style - - - - - Font - - - - - - Bold - - - - - - Italic - - - - - Size - - - - - Color - - - - - A: - - - - - R: - - - - - G: - - - - - B: - - - - - Style - - - - - Content - - - - - Content Type - - - - - Text/Tag - - - - - You can config how the network speed toolbar looks like in this panel - - - - - Apply Network Speed Bar UI Settings - - - - - About - - - - - Qv2ray - - - - - Version: - - - - - TIME - - - - - Official Repo: - - - - - <html><head/><body><p><a href="https://github.com/lhy0403/Qv2ray"><span style=" text-decoration: underline; color:#2980b9;">https://github.com/lhy0403/Qv2ray</span></a></p></body></html> - - - - - License: - - - - - <html><head/><body><p><a href="https://www.gnu.org/licenses/gpl-3.0.txt"><span style=" text-decoration: underline; color:#2980b9;">GPLv3 (https://www.gnu.org/licenses/gpl-3.0.txt)</span></a></p></body></html> - - - - - About Qt - - - - - Ingore Next Version - - - - + Forward Proxy - + Status - + Type - + HTTP - + Socks - + Host Address - + Network Toolbar Settings - - Cancel + + Items - + + + - + + + + + + + + + + + + Page Y Offset + + + + + Pages + + + + + Lines + + + + + Text Style + + + + + Font + + + + + + Bold + + + + + + Italic + + + + + Size + + + + + Color + + + + + A: + + + + + R: + + + + + G: + + + + + B: + + + + + ... + + + + + Style + + + + + Content + + + + + Content Type + + + + + Text/Tag + + + + + You can config how the network speed toolbar looks like in this panel + + + + + Apply Network Speed Bar UI Settings + + + + + About + + + + + Qv2ray + + + + + Version: + + + + Built Time - + + Official Repo: + + + + + <html><head/><body><p><a href="https://github.com/lhy0403/Qv2ray"><span style=" text-decoration: underline; color:#2980b9;">https://github.com/lhy0403/Qv2ray</span></a></p></body></html> + + + + + License: + + + + + <html><head/><body><p><a href="https://www.gnu.org/licenses/gpl-3.0.txt"><span style=" text-decoration: underline; color:#2980b9;">GPLv3 (https://www.gnu.org/licenses/gpl-3.0.txt)</span></a></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:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Noto Sans'; color:#d69545;">This</span><span style=" font-family:'Noto Sans'; color:#bec0c2;"> </span><span style=" font-family:'Noto Sans'; color:#d69545;">program</span><span style=" font-family:'Noto Sans'; color:#bec0c2;"> </span><span style=" font-family:'Noto Sans'; color:#d69545;">comes</span><span style=" font-family:'Noto Sans'; color:#bec0c2;"> </span><span style=" font-family:'Noto Sans'; color:#d69545;">with</span><span style=" font-family:'Noto Sans'; color:#bec0c2;"> </span><span style=" font-family:'Noto Sans'; color:#d69545;">ABSOLUTELY</span><span style=" font-family:'Noto Sans'; color:#bec0c2;"> </span><span style=" font-family:'Noto Sans'; color:#d69545;">NO</span><span style=" font-family:'Noto Sans'; color:#bec0c2;"> </span><span style=" font-family:'Noto Sans'; color:#d69545;">WARRANTY.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">This</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">is</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">free</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">software,</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">and</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">you</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">are</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">welcome</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">to</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">redistribute</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">it under</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">certain</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">conditions.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(C)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2019</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Leroy.H.Y</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@lhy0403):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Qv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Current</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Developer</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(C)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2019</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Hork</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@aliyuchang33):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Hv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Initial</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Designs</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">&amp;</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">gRPC</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">implementation</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(C)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2019</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">SOneWinstone</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@SoneWinstone):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Hv2ray/Qv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">HTTP</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Request</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Helper</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Qv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">ArtWork</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Done</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">By</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">ArielAxionL</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@axionl)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">TheBadGateway</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@thebadgateway):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Qv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Russian</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Translations</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Riko</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@rikakomoe):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Qv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">patch</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">8a8c1a/PR115&quot;</span></p> +<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; font-family:'Hack';"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Libraries</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">that</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">have</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">been</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">used</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">in</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Qv2ray</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">are</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">listed</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">below</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(Sorted</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">by</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">date</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">added):</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(c)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2019</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">dridk</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@dridk):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">X2Struct</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(Apache)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(c)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2011</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">SCHUTZ</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Sacha</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@dridk):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">QJsonModel</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(MIT)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(c)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2019</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Nikolaos</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Ftylitakis</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@ftylitak):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">QZXing</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(Apache2)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Hack'; color:#d69545;">Copyright</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(c)</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">2016</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">Singein</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(@Singein):</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">ScreenShot</span><span style=" font-family:'Hack'; color:#bec0c2;"> </span><span style=" font-family:'Hack'; color:#d69545;">(MIT)</span></p></body></html> + + + + + Ingore Next Version + + + + + Cancel + + + + + About Qt + + + + + Use Dark Theme + + + + Page - + Item(s) - + Port numbers cannot be the same + Open v2ray assets folder + + + + Open v2ray core file - - + + Enable tProxy Support - + 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 refer to issue #57 or the link below: - + Qv2ray cannot copy one or both v2ray files from: - + to this path: - - + + Failed to setcap onto v2ray executable. You may need to run `setcap` manually. - + tProxy is not supported on macOS and Windows - - - Open v2ray assets folder - - QObject - - Qv2ray Cannot Continue + + VMess string should start with 'vmess://' - - You are running a lower version of Qv2ray compared to the current config file. + + VMess string should be a valid base64 string - - Please report if you think this is an error. - - - - - - Qv2ray will now exit. - - - - - Cannot Start Qv2ray - - - - - Cannot find a place to store config files. - - - - - Qv2ray has searched these paths below: - - - - - DependencyMissing - - - - - Cannot find openssl libs - - - - - This could be caused by a missing of `openssl` package in your system. Or an AppImage issue. - - - - - If you are using AppImage, please report a bug. - - - - - Please refer to Github Issue #65 to check for solutions. - - - - - Github Issue Link: - - - - - Technical Details - - - - - Another instance of Qv2ray is already running. + + JSON should not be empty @@ -1693,6 +1719,92 @@ Or put v2ray core file in the location above. + + + Cannot Start Qv2ray + + + + + Cannot find a place to store config files. + + + + + Qv2ray has searched these paths below: + + + + + + Qv2ray will now exit. + + + + + Cannot load languages + + + + + Qv2ray will continue running, but you cannot change the UI language. + + + + + Another instance of Qv2ray is already running. + + + + + Qv2ray Cannot Continue + + + + + You are running a lower version of Qv2ray compared to the current config file. + + + + + Please report if you think this is an error. + + + + + DependencyMissing + + + + + Cannot find openssl libs + + + + + This could be caused by a missing of `openssl` package in your system. Or an AppImage issue. + + + + + If you are using AppImage, please report a bug. + + + + + Please refer to Github Issue #65 to check for solutions. + + + + + Github Issue Link: + + + + + Technical Details + + Stats is not enabled @@ -1714,367 +1826,395 @@ - + 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 RouteEditor - - - - - Enabled - - - - - InBounds - - - - - Outbound - - - - - Source IP Matching List - - - - - Target Domain List - - - - - Protocol - - - - - HTTP - - - - - TLS - - - - - BitTorrent - - - - - e.g. 80, 443, 8000-8080 - - - - - Enable Balancers - - - - - Balancers - - - - - Outbound Tag - - - - - Users List - - - - - Network - - - - - TCP - - - - - UDP - - - - - Both - - - - - - - - - - - - ... - - - - - Inbound List - - - - - Inbound Information - - - - - - Tag - - - - - - Type - - - - - - Address - - - - - - - Port - - - + Route Editor - - - D - - - - - F - - - - - B - - - - - Routes - - - - - Domain/IP - - - - - Route Details - - - - - Target IP List - - - - - Outbound List - - - - - Outbound Information - - Status - - - - + + Inbound List + + + + + + A + + + + + + + D + + + + + + E + + + + + Inbound Information + + + + + + Type + + + + + + + Port + + + + + + Address + + + + + + Tag + + + + + Outbound List + + + + + F + + + + + B + + + + + Outbound Information + + + + + Routes + + + + + + + Enabled + + + + + InBounds + + + + + Domain/IP + + + + + Outbound + + + + + + + + ... + + + + + Route Details + + + + + Target IP List + + + + + Source IP Matching List + + + + + Target Domain List + + + + + Network + + + + + TCP + + + + + UDP + + + + + Both + + + + + Protocol + + + + + HTTP + + + + + TLS + + + + + BitTorrent + + + + + e.g. 80, 443, 8000-8080 + + + + + Enable Balancers + + + + + Balancers + + + + + Outbound Tag + + + + + Users List + + + + + + + No Tag - - + + Any - - + + Items - + Cannot find an inbound by tag: - + Index Out Of Range - - + + Cannot Edit - + This outbound entry is not supported by the GUI editor. - + + + We will launch Json Editor instead. + + + + Currently, this type of outbound is not supported by the editor. - - - - + + + + Changing route inbound/outbound - + You didn't select an outbound. - + Banlancer will be used. - - + + One or more inbound config(s) have no tag configured, do you still want to continue? - + Are you sure to change the inbound/outbound of currently selected route? - + Current inbound/outbound combinations: - + Inbounds: - + Outbound: + + + ScreenShot - - - We will launch Json Editor instead. + + ScreenShot + + + + + TextLabel + + + + + Screen Shot