diff --git a/.github/workflows/build-qv2ray-cmake.yml b/.github/workflows/build-qv2ray-cmake.yml index 12103f5..65c3caf 100644 --- a/.github/workflows/build-qv2ray-cmake.yml +++ b/.github/workflows/build-qv2ray-cmake.yml @@ -77,12 +77,14 @@ jobs: # 14.1 is for vs2017, 14.2 is vs2019, following the upstream vcpkg build from Qv2ray-deps repo toolset: 14.2 arch: ${{ matrix.arch }} - - name: Download Artifacts + - name: Download Artifacts for macOS if: matrix.platform == 'macos-10.15' uses: actions/download-artifact@v3 with: path: download-artifact - - name: Install Qt + # ========================================================================================================= Qt Install + - name: macOS - Install Qt 5.15 + if: matrix.platform == 'macos-10.15' uses: jurplel/install-qt-action@v3 with: version: ${{ matrix.qt_version }} @@ -91,10 +93,24 @@ jobs: setup-python: false cache: true cache-key-prefix: QtCache-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.qt_version }} - # ========================================================================================================= Other install + - name: Windows - Download Custom Qt 5.15 SDK + shell: bash + if: matrix.platform == 'windows-2022' + run: | + mkdir qtsdk ; cd qtsdk + curl -LSO https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/Qt5.15.7-Windows-x86_64-VS2019-16.11.20-20221103.7z + 7z x *.7z + rm *.7z + mv Qt* Qt + - name: Linux - Install Qt 5.12 via apt + shell: bash + if: matrix.platform == 'ubuntu-20.04' + run: | + sudo apt-get update + sudo apt-get install -y zlib1g-dev fcitx-frontend-qt5 qtbase5-dev qttools5-dev libqt5svg5-dev libqt5x11extras5-dev + # ========================================================================================================= 编译与 Qt 无关的依赖 - name: Install ninja-build tool uses: seanmiddleditch/gha-setup-ninja@v3 - # ========================================================================================================= 编译与 Qt 无关的依赖 - name: Cache Download id: cache-deps uses: actions/cache@v3 @@ -114,6 +130,7 @@ jobs: CC: cl.exe CXX: cl.exe run: | + source libs/env_qtsdk.sh $PWD/qtsdk/Qt mkdir build cd build cmake -GNinja -DCMAKE_BUILD_TYPE=Release .. diff --git a/.gitignore b/.gitignore index 8b8ef4e..587b7e9 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,4 @@ CMakeLists.txt.user* # Deploy /deployment /neko*.sh +/qtsdk/ diff --git a/3rdparty/base64.cpp b/3rdparty/base64.cpp new file mode 100644 index 0000000..7bb5ead --- /dev/null +++ b/3rdparty/base64.cpp @@ -0,0 +1,88 @@ +#include "base64.h" + +namespace Qt515Base64 { + namespace { + struct fromBase64_helper_result { + qsizetype decodedLength; + Base64DecodingStatus status; + }; + + fromBase64_helper_result fromBase64_helper(const char *input, qsizetype inputSize, + char *output /* may alias input */, + Base64Options options) { + fromBase64_helper_result result{0, Base64DecodingStatus::Ok}; + + unsigned int buf = 0; + int nbits = 0; + + qsizetype offset = 0; + for (qsizetype i = 0; i < inputSize; ++i) { + int ch = input[i]; + int d; + + if (ch >= 'A' && ch <= 'Z') { + d = ch - 'A'; + } else if (ch >= 'a' && ch <= 'z') { + d = ch - 'a' + 26; + } else if (ch >= '0' && ch <= '9') { + d = ch - '0' + 52; + } else if (ch == '+' && (options & Base64UrlEncoding) == 0) { + d = 62; + } else if (ch == '-' && (options & Base64UrlEncoding) != 0) { + d = 62; + } else if (ch == '/' && (options & Base64UrlEncoding) == 0) { + d = 63; + } else if (ch == '_' && (options & Base64UrlEncoding) != 0) { + d = 63; + } else { + if (options & AbortOnBase64DecodingErrors) { + if (ch == '=') { + // can have 1 or 2 '=' signs, in both cases padding base64Size to + // a multiple of 4. Any other case is illegal. + if ((inputSize % 4) != 0) { + result.status = Base64DecodingStatus::IllegalInputLength; + return result; + } else if ((i == inputSize - 1) || + (i == inputSize - 2 && input[++i] == '=')) { + d = -1; // ... and exit the loop, normally + } else { + result.status = Base64DecodingStatus::IllegalPadding; + return result; + } + } else { + result.status = Base64DecodingStatus::IllegalCharacter; + return result; + } + } else { + d = -1; + } + } + + if (d != -1) { + buf = (buf << 6) | d; + nbits += 6; + if (nbits >= 8) { + nbits -= 8; + Q_ASSERT(offset < i); + output[offset++] = buf >> nbits; + buf &= (1 << nbits) - 1; + } + } + } + + result.decodedLength = offset; + return result; + } + } // namespace + + FromBase64Result QByteArray_fromBase64Encoding(const QByteArray &base64, Base64Options options) { + const auto base64Size = base64.size(); + QByteArray result((base64Size * 3) / 4, Qt::Uninitialized); + const auto base64result = fromBase64_helper(base64.data(), + base64Size, + const_cast(result.constData()), + options); + result.truncate(int(base64result.decodedLength)); + return {std::move(result), base64result.status}; + } +} // namespace Qt515Base64 diff --git a/3rdparty/base64.h b/3rdparty/base64.h new file mode 100644 index 0000000..1211304 --- /dev/null +++ b/3rdparty/base64.h @@ -0,0 +1,47 @@ +#include + +namespace Qt515Base64 { + enum Base64Option { + Base64Encoding = 0, + Base64UrlEncoding = 1, + + KeepTrailingEquals = 0, + OmitTrailingEquals = 2, + + IgnoreBase64DecodingErrors = 0, + AbortOnBase64DecodingErrors = 4, + }; + Q_DECLARE_FLAGS(Base64Options, Base64Option) + Q_DECLARE_OPERATORS_FOR_FLAGS(Base64Options) + + enum class Base64DecodingStatus { + Ok, + IllegalInputLength, + IllegalCharacter, + IllegalPadding, + }; + + class FromBase64Result { + public: + QByteArray decoded; + Base64DecodingStatus decodingStatus; + + void swap(FromBase64Result &other) noexcept { + qSwap(decoded, other.decoded); + qSwap(decodingStatus, other.decodingStatus); + } + + explicit operator bool() const noexcept { return decodingStatus == Base64DecodingStatus::Ok; } + +#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(Q_QDOC) + QByteArray &operator*() &noexcept { return decoded; } + const QByteArray &operator*() const &noexcept { return decoded; } + QByteArray &&operator*() &&noexcept { return std::move(decoded); } +#else + QByteArray &operator*() noexcept { return decoded; } + const QByteArray &operator*() const noexcept { return decoded; } +#endif + }; + + FromBase64Result QByteArray_fromBase64Encoding(const QByteArray &base64, Base64Options options); +} // namespace Qt515Base64 diff --git a/CMakeLists.txt b/CMakeLists.txt index f1b1a93..1aa8c34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,10 +40,16 @@ include("cmake/fuck_windows/fuck.cmake") # default prefix path if (NKR_PACKAGE) - list(APPEND CMAKE_PREFIX_PATH ${CMAKE_SOURCE_DIR}/libs/deps/package) + list(APPEND NKR_LIBS ${CMAKE_SOURCE_DIR}/libs/deps/package) else () - list(APPEND CMAKE_PREFIX_PATH ${CMAKE_SOURCE_DIR}/libs/deps/built) + list(APPEND NKR_LIBS ${CMAKE_SOURCE_DIR}/libs/deps/built) endif () + +if (NKR_DISABLE_LIBS) +else () + list(APPEND CMAKE_PREFIX_PATH ${NKR_LIBS}) +endif () + message("[CMAKE_PREFIX_PATH] ${CMAKE_PREFIX_PATH}") # for some cross toolchain @@ -100,6 +106,7 @@ set(PROJECT_SOURCES main/NekoRay.cpp main/NekoRay_Utils.cpp + 3rdparty/base64.cpp 3rdparty/qrcodegen.cpp 3rdparty/QtExtKeySequenceEdit.cpp @@ -207,14 +214,6 @@ set(PROJECT_SOURCES ${QV2RAY_RC} ) -# Translations -set(TS_FILES - translations/zh_CN.ts - ) -qt_create_translation(QM_FILES ${PROJECT_SOURCES} ${TS_FILES} OPTIONS -locations none) -configure_file(translations/translations.qrc ${CMAKE_BINARY_DIR} COPYONLY) -set(PROJECT_SOURCES ${PROJECT_SOURCES} ${TS_FILES} ${QM_FILES} ${CMAKE_BINARY_DIR}/translations.qrc) - # Qt exe if (${QT_VERSION_MAJOR} GREATER_EQUAL 6) qt_add_executable(nekoray @@ -245,21 +244,12 @@ set_property(TARGET nekoray PROPERTY AUTOUIC ON) set_property(TARGET nekoray PROPERTY AUTOMOC ON) set_property(TARGET nekoray PROPERTY AUTORCC ON) -# Target Link - -target_link_libraries(nekoray PRIVATE - Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Svg - Threads::Threads - ${NKR_EXTERNAL_TARGETS} - ${PLATFORM_FUCKING_LIBRARIES} - ) +# Target Source macOS set(MACOSX_ICON ${CMAKE_SOURCE_DIR}/res/nekoray.icns) - if (APPLE) target_sources(nekoray PRIVATE ${MACOSX_ICON}) endif () - set_target_properties(nekoray PROPERTIES MACOSX_BUNDLE_ICON_FILE "nekoray.icns" RESOURCE ${MACOSX_ICON} @@ -269,6 +259,29 @@ set_target_properties(nekoray PROPERTIES WIN32_EXECUTABLE TRUE ) +# Target Source Translations + +set(TS_FILES + translations/zh_CN.ts + ) +if (${QT_VERSION_MAJOR} GREATER_EQUAL 6) + qt_add_lupdate(nekoray TS_FILES ${TS_FILES}) + qt_add_lrelease(nekoray TS_FILES ${TS_FILES} QM_FILES_OUTPUT_VARIABLE QM_FILES) +else () + qt5_create_translation(QM_FILES ${PROJECT_SOURCES} ${TS_FILES} OPTIONS -locations none) +endif () +configure_file(translations/translations.qrc ${CMAKE_BINARY_DIR} COPYONLY) +target_sources(nekoray PRIVATE ${CMAKE_BINARY_DIR}/translations.qrc) + +# Target Link + +target_link_libraries(nekoray PRIVATE + Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Svg + Threads::Threads + ${NKR_EXTERNAL_TARGETS} + ${PLATFORM_FUCKING_LIBRARIES} + ) + if (QT_VERSION_MAJOR EQUAL 6) qt_finalize_executable(nekoray) endif () diff --git a/README.md b/README.md index df62770..63bc287 100644 --- a/README.md +++ b/README.md @@ -60,22 +60,7 @@ https://matsuridayo.github.io ## Linux 运行 -**使用 Linux 系统相信您已具备基本的排错能力, -本项目不提供特定发行版/架构的支持,预编译文件不能满足您的需求时,请自行编译/适配。** - -要求:已安装主流的发行版和 xcb 桌面环境。 - -运行: `./launcher` 或 部分系统可双击打开 - -launcher 参数 - -* `./launcher -- -appdata` ( `--` 后的参数传递给主程序 ) -* `-debug` Debug mode -* `-theme` Use local QT theme (unstable) (1.0+) - -已知部分 Linux 发行版无法使用预编译版、非 x86_64 暂无适配,可以尝试自行编译。 - -Ubuntu 22.04: `sudo apt install libxcb-xinerama0` +[Linux 运行教程](examples/docs/Run_Linux.md) ## 编译教程 diff --git a/db/TrafficLooper.cpp b/db/TrafficLooper.cpp index 10b7aeb..178f1f9 100644 --- a/db/TrafficLooper.cpp +++ b/db/TrafficLooper.cpp @@ -4,6 +4,10 @@ #include "ui/mainwindow_interface.h" #include +#include +#include +#include +#include namespace NekoRay::traffic { diff --git a/examples/docs/Run_Linux.md b/examples/docs/Run_Linux.md new file mode 100644 index 0000000..7bd3c25 --- /dev/null +++ b/examples/docs/Run_Linux.md @@ -0,0 +1,30 @@ +## Linux 运行 + +**使用 Linux 系统相信您已具备基本的排错能力, +本项目不提供特定发行版/架构的支持,预编译文件不能满足您的需求时,请自行编译/适配。** + +已知部分 Linux 发行版无法使用、非 x86_64 暂无适配,可以尝试自行编译。 + +目前 Release 便携包解压后,有两种使用方法: + +1. System: 若要使用系统的 Qt5 运行库,请执行 `./nekoray` +2. Bundle: 若要使用预编译的 Qt 运行库,请执行 `./launcher` + +### Bundle + +要求:已安装主流的发行版和 xcb 桌面环境。 + +运行: `./launcher` 或 部分系统可双击打开 + +launcher 参数 + +* `./launcher -- -appdata` ( `--` 后的参数传递给主程序 ) +* `-debug` Debug mode + +Ubuntu 22.04: `sudo apt install libxcb-xinerama0` + +### System + +要求:已安装主流的发行版和 xcb 桌面环境,已安装 Qt5.12 ~ Qt5.15 环境。 + +运行: `./nekoray` 或 部分系统可双击打开。如果无法运行,建议使用 Bundle 版。 diff --git a/fmt/AbstractBean.cpp b/fmt/AbstractBean.cpp index ea1a7b7..fe7251b 100644 --- a/fmt/AbstractBean.cpp +++ b/fmt/AbstractBean.cpp @@ -1,9 +1,8 @@ #include "includes.h" -#include - #include #include +#include namespace NekoRay::fmt { AbstractBean::AbstractBean(int version) { diff --git a/fmt/AbstractBean.hpp b/fmt/AbstractBean.hpp index 28e4570..27ff737 100644 --- a/fmt/AbstractBean.hpp +++ b/fmt/AbstractBean.hpp @@ -1,5 +1,8 @@ #pragma once +#include +#include + #include "main/NekoRay.hpp" namespace NekoRay::fmt { diff --git a/go/cmd/updater/launcher_linux.go b/go/cmd/updater/launcher_linux.go index 0593d8d..d9ad958 100644 --- a/go/cmd/updater/launcher_linux.go +++ b/go/cmd/updater/launcher_linux.go @@ -6,7 +6,6 @@ import ( "os" "os/exec" "path/filepath" - "runtime" ) var local_qt_theme bool @@ -16,18 +15,19 @@ func Launcher() { wd, _ := filepath.Abs(".") _debug := flag.Bool("debug", false, "Debug mode") - flag.BoolVar(&local_qt_theme, "theme", false, "Use local QT theme (unstable)") flag.Parse() - // Find & symlink some Qt Plugin to enable system theme - tryLinkQtPlugin("styles", !local_qt_theme) - tryLinkQtPlugin("platformthemes", !local_qt_theme) - cmd := exec.Command("./nekoray", flag.Args()...) - cmd.Env = os.Environ() + ld_env := "LD_LIBRARY_PATH=" + filepath.Join(wd, "./usr/lib") - cmd.Env = append(cmd.Env, ld_env) - log.Println(ld_env, cmd) + qt_plugin_env := "QT_PLUGIN_PATH=" + filepath.Join(wd, "./usr/plugins") + + // Qt 5.12 abi is usually compatible with system Qt 5.15 + // But use package Qt 5.12 by default. + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, "NKR_FROM_LAUNCHER=1") + cmd.Env = append(cmd.Env, ld_env, qt_plugin_env) + log.Println(ld_env, qt_plugin_env, cmd) if *_debug { cmd.Env = append(cmd.Env, "QT_DEBUG_PLUGINS=1") @@ -39,39 +39,3 @@ func Launcher() { cmd.Start() } } - -func tryLinkQtPlugin(sub string, remove bool) { - wd_plugins_sub := filepath.Join("./usr/plugins", sub) - - if Exist(wd_plugins_sub) { - if remove { - os.RemoveAll(wd_plugins_sub) - } - } else { - if remove { - return - } - - arch := "x86_64" - if runtime.GOARCH == "arm64" { - arch = "aarch64" - } - - paths := []string{ - filepath.Join("/usr/lib/qt5/plugins", sub), - filepath.Join("/usr/lib64/qt5/plugins", sub), - filepath.Join("/usr/lib/"+arch+"-linux-gnu/qt5/plugins", sub), - filepath.Join("/usr/lib/qt/plugins", sub), - } - path := FindExist(paths) - if path == "" { - log.Println("warning:", sub, "not found") - return - } - - err := os.Symlink(path, wd_plugins_sub) - if err != nil { - log.Println("symlink failed:", err.Error()) - } - } -} diff --git a/libs/deploy_linux64.sh b/libs/deploy_linux64.sh index 4196649..0ccdb14 100755 --- a/libs/deploy_linux64.sh +++ b/libs/deploy_linux64.sh @@ -9,8 +9,33 @@ mkdir -p $DEST #### copy binary #### cp $BUILD/nekoray $DEST -#### Download: prebuilt runtime #### -curl -Lso usr.zip https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/20220705-5.15.2-linux64.zip -unzip usr.zip -rm usr.zip +#### copy so #### +USR_LIB=/usr/lib/x86_64-linux-gnu +mkdir usr +pushd usr +mkdir lib +pushd lib +cp $USR_LIB/libQt5Core.so.5 . +cp $USR_LIB/libQt5DBus.so.5 . +cp $USR_LIB/libQt5Gui.so.5 . +cp $USR_LIB/libQt5Network.so.5 . +cp $USR_LIB/libQt5Svg.so.5 . +cp $USR_LIB/libQt5Widgets.so.5 . +cp $USR_LIB/libQt5X11Extras.so.5 . +cp $USR_LIB/libQt5XcbQpa.so.5 . +cp $USR_LIB/libxcb-util.so.1 . +cp $USR_LIB/libicuuc.so.?? . +cp $USR_LIB/libicui18n.so.?? . +cp $USR_LIB/libicudata.so.?? . +popd +mkdir plugins +pushd plugins +cp -r $USR_LIB/qt5/plugins/bearer . +cp -r $USR_LIB/qt5/plugins/iconengines . +cp -r $USR_LIB/qt5/plugins/imageformats . +cp -r $USR_LIB/qt5/plugins/platforminputcontexts . +cp -r $USR_LIB/qt5/plugins/platforms . +cp -r $USR_LIB/qt5/plugins/xcbglintegrations . +popd +popd mv usr $DEST diff --git a/libs/deploy_windows64.sh b/libs/deploy_windows64.sh index 3ee8415..5706ecd 100755 --- a/libs/deploy_windows64.sh +++ b/libs/deploy_windows64.sh @@ -12,8 +12,6 @@ cp $BUILD/nekoray.exe $DEST #### deploy qt & DLL runtime #### pushd $DEST windeployqt nekoray.exe --no-compiler-runtime --no-system-d3d-compiler --no-opengl-sw --verbose 2 -curl -LSsO https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/libcrypto-1_1-x64.dll -curl -LSsO https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/libssl-1_1-x64.dll rm -rf translations popd diff --git a/libs/env_qtsdk.sh b/libs/env_qtsdk.sh new file mode 100644 index 0000000..0cf6eaa --- /dev/null +++ b/libs/env_qtsdk.sh @@ -0,0 +1,8 @@ +echo "Setting Qt Sdk Dir to" "$1" +export Qt5_DIR="$1" +export Qt6_DIR=$Qt5_DIR +export PATH=$PATH:$Qt5_DIR/bin +export LD_LIBRARY_PATH=$Qt5_DIR/lib +export PKG_CONFIG_PATH=$Qt5_DIR/lib/pkgconfig +export QT_PLUGIN_PATH=$Qt5_DIR/plugins +export QML2_IMPORT_PATH=$Qt5_DIR/lib/qml diff --git a/main/NekoRay.cpp b/main/NekoRay.cpp index 3fbd1cb..948085d 100644 --- a/main/NekoRay.cpp +++ b/main/NekoRay.cpp @@ -4,6 +4,10 @@ #include #include #include +#include +#include +#include +#include namespace NekoRay { diff --git a/main/NekoRay_Utils.cpp b/main/NekoRay_Utils.cpp index 0fe9d7a..08e457d 100644 --- a/main/NekoRay_Utils.cpp +++ b/main/NekoRay_Utils.cpp @@ -1,5 +1,6 @@ #include "NekoRay_Utils.hpp" +#include "3rdparty/base64.h" #include "3rdparty/QThreadCreateThread.hpp" #include @@ -9,6 +10,40 @@ #include #include #include +#include +#include +#include +#include +#include +#include + +QStringList SplitLines(const QString &_string) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + return _string.split(QRegularExpression("[\r\n]"), Qt::SplitBehaviorFlags::SkipEmptyParts); +#else + return _string.split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts); +#endif +} + +QString DecodeB64IfValid(const QString &input, QByteArray::Base64Options options) { + Qt515Base64::Base64Options newOptions = Qt515Base64::Base64Option::AbortOnBase64DecodingErrors; + if (options.testFlag(QByteArray::Base64UrlEncoding)) newOptions |= Qt515Base64::Base64Option::Base64UrlEncoding; + if (options.testFlag(QByteArray::OmitTrailingEquals)) newOptions |= Qt515Base64::Base64Option::OmitTrailingEquals; + auto result = Qt515Base64::QByteArray_fromBase64Encoding(input.toUtf8(), newOptions); + if (result) { + return result.decoded; + } + return {}; +} + +QString QStringList2Command(const QStringList &list) { + QStringList new_list; + for (auto str: list) { + auto q = "\"" + str.replace("\"", "\\\"") + "\""; + new_list << q; + } + return new_list.join(" "); +} QString GetQueryValue(const QUrlQuery &q, const QString &key, const QString &def) { auto a = q.queryItemValue(key); @@ -34,6 +69,43 @@ QString GetRandomString(int randomStringLength) { return randomString; } +// QString >> QJson +QJsonObject QString2QJsonObject(const QString &jsonString) { + QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonString.toUtf8()); + QJsonObject jsonObject = jsonDocument.object(); + return jsonObject; +} + +// QJson >> QString +QString QJsonObject2QString(const QJsonObject &jsonObject, bool compact) { + return QJsonDocument(jsonObject).toJson(compact ? QJsonDocument::Compact : QJsonDocument::Indented); +} + +template +QJsonArray QList2QJsonArray(const QList &list) { + QVariantList list2; + for (auto &item: list) + list2.append(item); + return QJsonArray::fromVariantList(list2); +} + +template QJsonArray QList2QJsonArray(const QList &list); +template QJsonArray QList2QJsonArray(const QList &list); + +QList QJsonArray2QListInt(const QJsonArray &arr) { + QList list2; + for (auto item: arr) + list2.append(item.toInt()); + return list2; +} + +QList QJsonArray2QListString(const QJsonArray &arr) { + QList list2; + for (auto item: arr) + list2.append(item.toString()); + return list2; +} + QByteArray ReadFile(const QString &path) { QFile file(path); file.open(QFile::ReadOnly); @@ -76,6 +148,12 @@ bool IsIpAddressV6(const QString &str) { return false; } +QString DisplayTime(long long time, int formatType) { + QDateTime t; + t.setSecsSinceEpoch(time); + return QLocale().toString(t, QLocale::FormatType(formatType)); +} + QWidget *GetMessageBoxParent() { if (mainwindow == nullptr) return nullptr; if (mainwindow->isVisible()) return mainwindow; diff --git a/main/NekoRay_Utils.hpp b/main/NekoRay_Utils.hpp index 1a1150c..7fe01e1 100644 --- a/main/NekoRay_Utils.hpp +++ b/main/NekoRay_Utils.hpp @@ -1,9 +1,10 @@ // DO NOT INCLUDE THIS +#include +#include +#include #include -#include -#include -#include +#include // @@ -15,23 +16,14 @@ inline QString software_core_name = "V2Ray"; inline std::function MF_release_runguard; // MainWindow functions - +class QWidget; inline QWidget *mainwindow; inline std::function MW_show_log; inline std::function MW_show_log_ext; inline std::function MW_show_log_ext_vt100; inline std::function MW_dialog_message; -// Utils - -#define QJSONARRAY_ADD(arr, add) \ - for (const auto &a: (add)) { \ - (arr) += a; \ - } -#define QJSONOBJECT_COPY(src, dst, key) \ - if (src.contains(key)) dst[key] = src[key]; -#define QJSONOBJECT_COPY2(src, dst, src_key, dst_key) \ - if (src.contains(src_key)) dst[dst_key] = src[src_key]; +// String #define Int2String(num) QString::number(num) @@ -45,24 +37,17 @@ inline QString SubStrAfter(QString str, const QString &sub) { return str.right(str.length() - str.indexOf(sub) - sub.length()); } -inline QString QStringList2Command(const QStringList &list) { - QStringList new_list; - for (auto str: list) { - auto q = "\"" + str.replace("\"", "\\\"") + "\""; - new_list << q; - } - return new_list.join(" "); -} +QString QStringList2Command(const QStringList &list); -inline QString -DecodeB64IfValid(const QString &input, QByteArray::Base64Option options = QByteArray::Base64Option::Base64Encoding) { - auto result = QByteArray::fromBase64Encoding(input.toUtf8(), - options | QByteArray::Base64Option::AbortOnBase64DecodingErrors); - if (result) { - return result.decoded; - } - return ""; -} +QStringList SplitLines(const QString &_string); + +// Base64 + +QString DecodeB64IfValid(const QString &input, QByteArray::Base64Options options = QByteArray::Base64Option::Base64Encoding); + +// URL + +class QUrlQuery; #define GetQuery(url) QUrlQuery((url).query(QUrl::ComponentFormattingOption::FullyDecoded)); @@ -70,51 +55,34 @@ QString GetQueryValue(const QUrlQuery &q, const QString &key, const QString &def QString GetRandomString(int randomStringLength); -// QString >> QJson -inline QJsonObject QString2QJsonObject(const QString &jsonString) { - QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonString.toUtf8()); - QJsonObject jsonObject = jsonDocument.object(); - return jsonObject; -} - -// QJson >> QString -inline QString QJsonObject2QString(const QJsonObject &jsonObject, bool compact) { - return QString(QJsonDocument(jsonObject).toJson(compact ? QJsonDocument::Compact : QJsonDocument::Indented)); -} - -template -inline QJsonArray QList2QJsonArray(const QList &list) { - QVariantList list2; - for (auto &item: list) - list2.append(item); - return QJsonArray::fromVariantList(list2); -} - -inline QList QJsonArray2QListInt(const QJsonArray &arr) { - QList list2; - for (auto item: arr) - list2.append(item.toInt()); - return list2; -} - -inline QList QJsonArray2QListString(const QJsonArray &arr) { - QList list2; - for (auto item: arr) - list2.append(item.toString()); - return list2; -} - inline QString UrlSafe_encode(const QString &s) { return s.toUtf8().toPercentEncoding().replace(" ", "%20"); } -inline bool InRange(unsigned x, unsigned low, unsigned high) { - return (low <= x && x <= high); -} +// JSON -inline QStringList SplitLines(const QString &_string) { - return _string.split(QRegularExpression("[\r\n]"), Qt::SplitBehaviorFlags::SkipEmptyParts); -} +class QJsonObject; +class QJsonArray; + +QJsonObject QString2QJsonObject(const QString &jsonString); + +QString QJsonObject2QString(const QJsonObject &jsonObject, bool compact); + +template +QJsonArray QList2QJsonArray(const QList &list); + +QList QJsonArray2QListInt(const QJsonArray &arr); + +#define QJSONARRAY_ADD(arr, add) \ + for (const auto &a: (add)) { \ + (arr) += a; \ + } +#define QJSONOBJECT_COPY(src, dst, key) \ + if (src.contains(key)) dst[key] = src[key]; +#define QJSONOBJECT_COPY2(src, dst, src_key, dst_key) \ + if (src.contains(src_key)) dst[dst_key] = src[src_key]; + +QList QJsonArray2QListString(const QJsonArray &arr); // Files @@ -122,10 +90,6 @@ QByteArray ReadFile(const QString &path); QString ReadFileText(const QString &path); -// Net - -int MkPort(); - // Validators bool IsIpAddress(const QString &str); @@ -150,13 +114,11 @@ inline QString DisplayAddress(QString serverAddress, int serverPort) { return WrapIPV6Host(serverAddress) + ":" + Int2String(serverPort); }; -// Format +// Format & Misc -inline QString DisplayTime(long long time, QLocale::FormatType formatType = QLocale::LongFormat) { - QDateTime t; - t.setSecsSinceEpoch(time); - return QLocale().toString(t, formatType); -} +int MkPort(); + +QString DisplayTime(long long time, int formatType = 0); inline QString ReadableSize(const qint64 &size) { double sizeAsDouble = size; @@ -180,6 +142,10 @@ inline QString ReadableSize(const qint64 &size) { return QString::fromLatin1("%1 %2").arg(sizeAsDouble, 0, 'f', 2).arg(measure); } +inline bool InRange(unsigned x, unsigned low, unsigned high) { + return (low <= x && x <= high); +} + // UI QWidget *GetMessageBoxParent(); diff --git a/qv2ray/wrapper.hpp b/qv2ray/wrapper.hpp index 3d4ee80..e68d771 100644 --- a/qv2ray/wrapper.hpp +++ b/qv2ray/wrapper.hpp @@ -3,6 +3,7 @@ // Qv2ray wrapper #include +#include #define LOG(...) Qv2ray::base::log_internal(__VA_ARGS__) #define DEBUG(...) Qv2ray::base::log_internal(__VA_ARGS__) diff --git a/sys/AutoRun.cpp b/sys/AutoRun.cpp index b614735..d17b5e6 100644 --- a/sys/AutoRun.cpp +++ b/sys/AutoRun.cpp @@ -167,9 +167,8 @@ void AutoRun_SetEnabled(bool enable) { QStringList appCmdList = {QApplication::applicationFilePath(), "-tray"}; // nekoray: launcher - auto launcherPath = QApplication::applicationDirPath() + "/launcher"; - if (QFile::exists(launcherPath)) { - appCmdList = QStringList{launcherPath, "--", "-tray"}; + if (qEnvironmentVariable("NKR_FROM_LAUNCHER") == "1") { + appCmdList = QStringList{QApplication::applicationDirPath() + "/launcher", "--", "-tray"}; } if (enable) { diff --git a/ui/mainwindow.h b/ui/mainwindow.h index a6f216c..ceffda8 100644 --- a/ui/mainwindow.h +++ b/ui/mainwindow.h @@ -6,6 +6,7 @@ #ifndef MW_INTERFACE +#include #include #include #include