Full Code of MatsuriDayo/nekoray for AI

main adef6cd4af7d cached
230 files
1.1 MB
322.4k tokens
621 symbols
1 requests
Download .txt
Showing preview only (1,210K chars total). Download the full file or copy to clipboard to get everything.
Repository: MatsuriDayo/nekoray
Branch: main
Commit: adef6cd4af7d
Files: 230
Total size: 1.1 MB

Directory structure:
gitextract_ivvmk2ct/

├── .clang-format
├── .clang-tidy
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report-en.md
│   │   ├── bug-report-zh_cn.md
│   │   ├── feature_request-en.md
│   │   └── feature_request-zh_cn.md
│   └── workflows/
│       ├── build-nekoray-cmake.yml
│       └── update-pkgbuild.yml
├── .gitignore
├── .gitmodules
├── 3rdparty/
│   ├── QThreadCreateThread.hpp
│   ├── QtExtKeySequenceEdit.cpp
│   ├── QtExtKeySequenceEdit.h
│   ├── RunGuard.hpp
│   ├── VT100Parser.hpp
│   ├── WinCommander.cpp
│   ├── WinCommander.hpp
│   ├── ZxingQtReader.hpp
│   ├── base64.cpp
│   ├── base64.h
│   ├── fix_old_qt.h
│   ├── qrcodegen.cpp
│   ├── qrcodegen.hpp
│   ├── qscopeguard.h
│   └── qv2ray/
│       ├── v2/
│       │   ├── components/
│       │   │   └── proxy/
│       │   │       ├── QvProxyConfigurator.cpp
│       │   │       └── QvProxyConfigurator.hpp
│       │   └── ui/
│       │       ├── QvAutoCompleteTextEdit.cpp
│       │       ├── QvAutoCompleteTextEdit.hpp
│       │       └── widgets/
│       │           ├── common/
│       │           │   ├── QJsonModel.cpp
│       │           │   └── QJsonModel.hpp
│       │           └── editors/
│       │               ├── w_JsonEditor.cpp
│       │               ├── w_JsonEditor.hpp
│       │               └── w_JsonEditor.ui
│       ├── v3/
│       │   └── components/
│       │       └── GeositeReader/
│       │           ├── GeositeReader.cpp
│       │           ├── GeositeReader.hpp
│       │           ├── picoproto.cpp
│       │           └── picoproto.hpp
│       └── wrapper.hpp
├── CMakeLists.txt
├── LICENSE
├── README.md
├── cmake/
│   ├── linux/
│   │   └── linux.cmake
│   ├── myproto.cmake
│   ├── nkr.cmake
│   ├── print.cmake
│   └── windows/
│       ├── VersionInfo.in
│       ├── VersionResource.rc
│       ├── generate_product_version.cmake
│       └── windows.cmake
├── db/
│   ├── ConfigBuilder.cpp
│   ├── ConfigBuilder.hpp
│   ├── Database.cpp
│   ├── Database.hpp
│   ├── Group.hpp
│   ├── ProfileFilter.cpp
│   ├── ProfileFilter.hpp
│   ├── ProxyEntity.hpp
│   └── traffic/
│       ├── TrafficData.hpp
│       ├── TrafficLooper.cpp
│       └── TrafficLooper.hpp
├── docs/
│   ├── Build_Core.md
│   ├── Build_Linux.md
│   ├── Build_Windows.md
│   ├── RunFlags.md
│   ├── Run_Linux.md
│   └── readme.md
├── fmt/
│   ├── AbstractBean.cpp
│   ├── AbstractBean.hpp
│   ├── Bean2CoreObj_box.cpp
│   ├── Bean2External.cpp
│   ├── Bean2Link.cpp
│   ├── ChainBean.hpp
│   ├── CustomBean.hpp
│   ├── Link2Bean.cpp
│   ├── NaiveBean.hpp
│   ├── Preset.hpp
│   ├── QUICBean.hpp
│   ├── ShadowSocksBean.hpp
│   ├── SocksHttpBean.hpp
│   ├── TrojanVLESSBean.hpp
│   ├── V2RayStreamSettings.hpp
│   ├── VMessBean.hpp
│   └── includes.h
├── go/
│   ├── .gitignore
│   ├── cmd/
│   │   ├── nekobox_core/
│   │   │   ├── core_box.go
│   │   │   ├── go.mod
│   │   │   ├── go.sum
│   │   │   ├── grpc_box.go
│   │   │   └── main.go
│   │   └── updater/
│   │       ├── .gitignore
│   │       ├── go.mod
│   │       ├── go.sum
│   │       ├── launcher.go
│   │       ├── launcher_linux.go
│   │       ├── main.go
│   │       ├── msgbox.go
│   │       ├── msgbox_windows.go
│   │       └── updater.go
│   └── grpc_server/
│       ├── auth/
│       │   └── auth.go
│       ├── fulltest.go
│       ├── gen/
│       │   ├── libcore.pb.go
│       │   ├── libcore.proto
│       │   ├── libcore_grpc.pb.go
│       │   └── update_proto.sh
│       ├── go.mod
│       ├── go.sum
│       ├── grpc.go
│       └── update.go
├── libs/
│   ├── .gitignore
│   ├── build_deps_all.sh
│   ├── build_go.sh
│   ├── build_public_res.sh
│   ├── deploy_linux64.sh
│   ├── deploy_windows64.sh
│   ├── download_qtsdk_win.sh
│   ├── env_deploy.sh
│   ├── env_qtsdk.sh
│   ├── format_cpp.sh
│   ├── get_source.sh
│   ├── get_source_env.sh
│   ├── package_appimage.sh
│   └── package_debian.sh
├── main/
│   ├── Const.hpp
│   ├── GuiUtils.hpp
│   ├── HTTPRequestHelper.cpp
│   ├── HTTPRequestHelper.hpp
│   ├── NekoGui.cpp
│   ├── NekoGui.hpp
│   ├── NekoGui_ConfigItem.hpp
│   ├── NekoGui_DataStore.hpp
│   ├── NekoGui_Utils.cpp
│   ├── NekoGui_Utils.hpp
│   └── main.cpp
├── nekoray_version.txt
├── res/
│   ├── dashboard-notice.html
│   ├── neko.css
│   ├── neko.qrc
│   ├── public/
│   │   └── qtbase_zh_CN.qm
│   ├── theme/
│   │   └── feiyangqingyun/
│   │       ├── qss/
│   │       │   ├── blacksoft.css
│   │       │   ├── flatgray.css
│   │       │   └── lightblue.css
│   │       └── qss.qrc
│   └── vpn/
│       ├── sing-box-vpn.json
│       └── vpn-run-root.sh
├── rpc/
│   ├── gRPC.cpp
│   └── gRPC.h
├── sub/
│   ├── GroupUpdater.cpp
│   └── GroupUpdater.hpp
├── sys/
│   ├── AutoRun.cpp
│   ├── AutoRun.hpp
│   ├── ExternalProcess.cpp
│   ├── ExternalProcess.hpp
│   ├── linux/
│   │   ├── LinuxCap.cpp
│   │   └── LinuxCap.h
│   └── windows/
│       ├── MiniDump.cpp
│       ├── MiniDump.h
│       ├── guihelper.cpp
│       └── guihelper.h
├── test/
│   ├── test-qt512-sdk-build.sh
│   └── test-qt6-build.sh
├── translations/
│   ├── fa_IR.ts
│   ├── ru_RU.ts
│   ├── translations.qrc
│   └── zh_CN.ts
└── ui/
    ├── GroupSort.hpp
    ├── Icon.cpp
    ├── Icon.hpp
    ├── ThemeManager.cpp
    ├── ThemeManager.hpp
    ├── dialog_basic_settings.cpp
    ├── dialog_basic_settings.h
    ├── dialog_basic_settings.ui
    ├── dialog_hotkey.cpp
    ├── dialog_hotkey.h
    ├── dialog_hotkey.ui
    ├── dialog_manage_groups.cpp
    ├── dialog_manage_groups.h
    ├── dialog_manage_groups.ui
    ├── dialog_manage_routes.cpp
    ├── dialog_manage_routes.h
    ├── dialog_manage_routes.ui
    ├── dialog_vpn_settings.cpp
    ├── dialog_vpn_settings.h
    ├── dialog_vpn_settings.ui
    ├── edit/
    │   ├── dialog_edit_group.cpp
    │   ├── dialog_edit_group.h
    │   ├── dialog_edit_group.ui
    │   ├── dialog_edit_profile.cpp
    │   ├── dialog_edit_profile.h
    │   ├── dialog_edit_profile.ui
    │   ├── edit_chain.cpp
    │   ├── edit_chain.h
    │   ├── edit_chain.ui
    │   ├── edit_custom.cpp
    │   ├── edit_custom.h
    │   ├── edit_custom.ui
    │   ├── edit_naive.cpp
    │   ├── edit_naive.h
    │   ├── edit_naive.ui
    │   ├── edit_quic.cpp
    │   ├── edit_quic.h
    │   ├── edit_quic.ui
    │   ├── edit_shadowsocks.cpp
    │   ├── edit_shadowsocks.h
    │   ├── edit_shadowsocks.ui
    │   ├── edit_socks_http.cpp
    │   ├── edit_socks_http.h
    │   ├── edit_socks_http.ui
    │   ├── edit_trojan_vless.cpp
    │   ├── edit_trojan_vless.h
    │   ├── edit_trojan_vless.ui
    │   ├── edit_vmess.cpp
    │   ├── edit_vmess.h
    │   ├── edit_vmess.ui
    │   └── profile_editor.h
    ├── mainwindow.cpp
    ├── mainwindow.h
    ├── mainwindow.ui
    ├── mainwindow_grpc.cpp
    ├── mainwindow_interface.h
    └── widget/
        ├── FloatCheckBox.h
        ├── GroupItem.cpp
        ├── GroupItem.h
        ├── GroupItem.ui
        ├── MessageBoxTimer.h
        ├── MyLineEdit.h
        ├── MyTableWidget.h
        ├── ProxyItem.cpp
        ├── ProxyItem.h
        └── ProxyItem.ui

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
BasedOnStyle: Google
ColumnLimit: 0
IndentWidth: 4
SortIncludes: Never
SpacesBeforeTrailingComments: 1
NamespaceIndentation: All
AccessModifierOffset: -4
SpaceAfterCStyleCast: true
SpaceAfterTemplateKeyword: false
SpaceBeforeRangeBasedForLoopColon: false


================================================
FILE: .clang-tidy
================================================
# Generated from CLion Inspection settings
---
Checks: '-*,
bugprone-argument-comment,
bugprone-assert-side-effect,
bugprone-bad-signal-to-kill-thread,
bugprone-branch-clone,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-fold-init-type,
bugprone-forward-declaration-namespace,
bugprone-forwarding-reference-overload,
bugprone-inaccurate-erase,
bugprone-incorrect-roundings,
bugprone-integer-division,
bugprone-lambda-function-name,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-pointer-arithmetic-in-alloc,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multiple-statement-macro,
bugprone-no-escape,
bugprone-not-null-terminated-result,
bugprone-parent-virtual-call,
bugprone-posix-return,
bugprone-reserved-identifier,
bugprone-sizeof-container,
bugprone-sizeof-expression,
bugprone-spuriously-wake-up-functions,
bugprone-string-constructor,
bugprone-string-integer-assignment,
bugprone-string-literal-with-embedded-nul,
bugprone-suspicious-enum-usage,
bugprone-suspicious-include,
bugprone-suspicious-memory-comparison,
bugprone-suspicious-memset-usage,
bugprone-suspicious-missing-comma,
bugprone-suspicious-semicolon,
bugprone-suspicious-string-compare,
bugprone-swapped-arguments,
bugprone-terminating-continue,
bugprone-throw-keyword-missing,
bugprone-too-small-loop-variable,
bugprone-undefined-memory-manipulation,
bugprone-undelegated-constructor,
bugprone-unhandled-self-assignment,
bugprone-unused-raii,
bugprone-unused-return-value,
bugprone-use-after-move,
bugprone-virtual-near-miss,
cert-dcl21-cpp,
cert-dcl58-cpp,
cert-err34-c,
cert-err52-cpp,
cert-err60-cpp,
cert-flp30-c,
cert-msc50-cpp,
cert-msc51-cpp,
cert-str34-c,
cppcoreguidelines-interfaces-global-init,
cppcoreguidelines-narrowing-conversions,
cppcoreguidelines-pro-type-member-init,
cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-slicing,
google-default-arguments,
google-explicit-constructor,
google-runtime-operator,
hicpp-exception-baseclass,
hicpp-multiway-paths-covered,
misc-misplaced-const,
misc-new-delete-overloads,
misc-no-recursion,
misc-non-copyable-objects,
misc-throw-by-value-catch-by-reference,
misc-unconventional-assign-operator,
misc-uniqueptr-reset-release,
modernize-avoid-bind,
modernize-concat-nested-namespaces,
modernize-deprecated-headers,
modernize-deprecated-ios-base-aliases,
modernize-loop-convert,
modernize-make-shared,
modernize-make-unique,
modernize-pass-by-value,
modernize-raw-string-literal,
modernize-redundant-void-arg,
modernize-replace-auto-ptr,
modernize-replace-disallow-copy-and-assign-macro,
modernize-replace-random-shuffle,
modernize-return-braced-init-list,
modernize-shrink-to-fit,
modernize-unary-static-assert,
modernize-use-auto,
modernize-use-bool-literals,
modernize-use-emplace,
modernize-use-equals-default,
modernize-use-equals-delete,
modernize-use-nodiscard,
modernize-use-noexcept,
modernize-use-nullptr,
modernize-use-override,
modernize-use-transparent-functors,
modernize-use-uncaught-exceptions,
mpi-buffer-deref,
mpi-type-mismatch,
openmp-use-default-none,
performance-faster-string-find,
performance-for-range-copy,
performance-implicit-conversion-in-loop,
performance-inefficient-algorithm,
performance-inefficient-string-concatenation,
performance-inefficient-vector-operation,
performance-move-const-arg,
performance-move-constructor-init,
performance-no-automatic-move,
performance-noexcept-move-constructor,
performance-trivially-destructible,
performance-type-promotion-in-math-fn,
performance-unnecessary-copy-initialization,
performance-unnecessary-value-param,
portability-simd-intrinsics,
readability-avoid-const-params-in-decls,
readability-const-return-type,
readability-container-size-empty,
readability-convert-member-functions-to-static,
readability-delete-null-pointer,
readability-deleted-default,
readability-inconsistent-declaration-parameter-name,
readability-make-member-function-const,
readability-misleading-indentation,
readability-misplaced-array-index,
readability-non-const-parameter,
readability-redundant-control-flow,
readability-redundant-declaration,
readability-redundant-function-ptr-dereference,
readability-redundant-smartptr-get,
readability-redundant-string-cstr,
readability-redundant-string-init,
readability-simplify-subscript-expr,
readability-static-accessed-through-instance,
readability-static-definition-in-anonymous-namespace,
readability-string-compare,
readability-uniqueptr-delete-release,
readability-use-anyofallof'

================================================
FILE: .github/ISSUE_TEMPLATE/bug-report-en.md
================================================
---
name: 'Bug Report'
about: 'Please troubleshoot server-side issues and upgrade to the latest client before raising a question.'
title: 'BUG: '
labels: ''
assignees: ''

---

## Describe the problem

Expected behavior:

Actual behavior:

## How to reproduce

Provide helpful screenshots, videos, text descriptions, subscription links, etc.

## log

If you have logs, please upload them. Please see the detailed steps for exporting logs in the documentation.

================================================
FILE: .github/ISSUE_TEMPLATE/bug-report-zh_cn.md
================================================
---
name: '问题反馈'
about: '在提出问题前请先自行排除服务器端问题和升级到最新客户端。'
title: 'BUG: '
labels: ''
assignees: ''

---

## 描述问题

预期行为:

实际行为:

## 如何复现

提供有帮助的截图,录像,文字说明,订阅链接等。

## 日志

如果有日志,请上传。请在文档内查看导出日志的详细步骤。


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request-en.md
================================================
---
name: 'Feature Request'
about: 'Make suggestions for new features of the software'
title: ''
labels: ''
assignees: ''

---

## Description suggestions

## Necessity of recommendations


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request-zh_cn.md
================================================
---
name: '功能请求'
about: '对软件的新功能提出建议。'
title: ''
labels: ''
assignees: ''

---

## 描述建议

## 建议的必要性


================================================
FILE: .github/workflows/build-nekoray-cmake.yml
================================================
name: Nekoray build matrix - cmake

on:
  workflow_dispatch:
    inputs:
      tag:
        description: "Release Tag"
        required: true
      publish:
        description: "Publish: If want ignore"
        required: false
      artifact-pack:
        description: "artifact-pack: If want ignore"
        required: false
jobs:
  build-go:
    strategy:
      matrix:
        cross_os: [windows, linux]
        cross_arch: [amd64]
        include:
          - cross_os: public_res
            cross_arch: public_res
      fail-fast: false
    runs-on: ubuntu-latest
    steps:
      - name: Checking out sources
        uses: actions/checkout@v3
      - name: Go Status
        run: git ls-files go | xargs cat | sha1sum > go_status
      - name: Cache Common Download
        id: cache-common
        uses: actions/cache@v3
        with:
          path: artifacts.tgz
          key: CommonCache-${{ matrix.cross_os }}-${{ matrix.cross_arch }}-${{ hashFiles('libs/*.sh', 'go_status', '*.txt') }}
      - name: Install Golang
        if: steps.cache-common.outputs.cache-hit != 'true'
        uses: actions/setup-go@v3
        with:
          go-version: ^1.22
      - name: Build golang parts
        if: steps.cache-common.outputs.cache-hit != 'true'
        shell: bash
        run: |
          [ ${{ matrix.cross_os }} == public_res ] || ./libs/get_source.sh
          [ ${{ matrix.cross_os }} == public_res ] || GOOS=${{ matrix.cross_os }} GOARCH=${{ matrix.cross_arch }} ./libs/build_go.sh
          [ ${{ matrix.cross_os }} == public_res ] || exit 0
          ./libs/build_public_res.sh
      - name: Tar files
        if: steps.cache-common.outputs.cache-hit != 'true'
        run: tar czvf artifacts.tgz ./deployment
      - name: Uploading Artifact
        uses: actions/upload-artifact@v3
        with:
          name: NekoRay-${{ github.sha }}-Common-${{ matrix.cross_os }}-${{ matrix.cross_arch }}
          path: artifacts.tgz
  build-cpp:
    strategy:
      matrix:
        include:
          - platform: windows-2022
            arch: x64
            qt_version: "6.7"
          - platform: ubuntu-20.04
            arch: x64
            qt_version: "5.12"
      fail-fast: false

    runs-on: ${{ matrix.platform }}
    env:
      ACTIONS_ALLOW_UNSECURE_COMMANDS: true
    steps:
      - name: Checking out sources
        uses: actions/checkout@v3
        with:
          submodules: "recursive"
      - name: Install MSVC compiler
        if: matrix.platform == 'windows-2022'
        uses: ilammy/msvc-dev-cmd@v1
        with:
          # 14.1 is for vs2017, 14.2 is vs2019, following the upstream vcpkg build from Qv2ray-deps repo
          toolset: 14.2
          arch: ${{ matrix.arch }}
      # ========================================================================================================= Qt Install
      - name: Windows - Download Custom Qt ${{ matrix.qt_version }} SDK
        shell: bash
        if: matrix.platform == 'windows-2022'
        env:
          DL_QT_VER: ${{ matrix.qt_version }}
        run: bash ./libs/download_qtsdk_win.sh
      # ========================================================================================================= 编译与 Qt 无关的依赖
      - name: Install ninja-build tool
        uses: seanmiddleditch/gha-setup-ninja@v3
      - name: Cache Download
        id: cache-deps
        uses: actions/cache@v3
        with:
          path: libs/deps
          key: DepsCache-${{ matrix.platform }}-${{ matrix.arch }}-${{ hashFiles('libs/build_deps_*.sh') }}-Qt${{ matrix.qt_version }}
      - name: Build Dependencies
        shell: bash
        if: steps.cache-deps.outputs.cache-hit != 'true' && matrix.platform != 'ubuntu-20.04'
        run: ./libs/build_deps_all.sh
      - name: Build Dependencies (Docker)
        shell: bash
        if: steps.cache-deps.outputs.cache-hit != 'true' && matrix.platform == 'ubuntu-20.04'
        run: |
          docker run --rm \
            -v $PWD:/nekoray \
            -w /nekoray \
            ghcr.io/matsuridayo/debian10-qt5:20230131 \
            bash -c "./libs/build_deps_all.sh"
      # ========================================================================================================= Generate MakeFile and Build
      - name: Windows - Generate MakeFile and Build
        shell: bash
        if: matrix.platform == 'windows-2022'
        env:
          DL_QT_VER: ${{ matrix.qt_version }}
          CC: cl.exe
          CXX: cl.exe
        run: |
          source libs/env_qtsdk.sh $PWD/qtsdk/Qt
          mkdir build
          cd build
          cmake -GNinja -DQT_VERSION_MAJOR=6 -DCMAKE_BUILD_TYPE=Release ..
          ninja -j2
          cd ..
          ./libs/deploy_windows64.sh
      - name: Linux - Generate MakeFile and Build
        shell: bash
        if: matrix.platform == 'ubuntu-20.04'
        run: |
          docker run --rm \
            -v $PWD:/nekoray \
            -w /nekoray \
            ghcr.io/matsuridayo/debian10-qt5:20230131 \
            bash -c "mkdir build && pushd build && cmake -GNinja -DCMAKE_BUILD_TYPE=Release .. && ninja && popd &&./libs/deploy_linux64.sh"
      # ========================================================================================================= Deployments
      - name: Tar files
        shell: bash
        run: tar czvf artifacts.tgz ./deployment
      - name: Uploading Artifact
        uses: actions/upload-artifact@v3
        with:
          name: NekoRay-${{ github.sha }}-${{ matrix.platform }}-${{ matrix.arch }}-Qt${{ matrix.qt_version }}
          path: artifacts.tgz
  publish:
    name: Pack & Publish Release
    if: github.event.inputs.artifact-pack != 'y'
    runs-on: ubuntu-latest
    needs:
      - build-cpp
      - build-go
    steps:
      - name: Checking out sources
        uses: actions/checkout@v3
      - name: Download Artifacts
        uses: actions/download-artifact@v3
        with:
          path: download-artifact
      - name: Pack
        run: |
          curl -Lo - https://github.com/tcnksm/ghr/releases/download/v0.13.0/ghr_v0.13.0_linux_amd64.tar.gz | tar xzv
          mv ghr*linux_amd64/ghr .
          ####
          source libs/env_deploy.sh
          find . -name artifacts.tgz | xargs -n1 tar xvzf
          cd deployment
          cp -r public_res/* linux64
          cp -r public_res/* windows64
          rm -rf public_res *.pdb
          ####
          mv linux64 nekoray
          zip -r $version_standalone-linux64.zip nekoray
          rm -rf nekoray
          ####
          mv windows64 nekoray
          zip -r $version_standalone-windows64.zip nekoray
          rm -rf nekoray
      - name: Pack Debian
        run: |
          source libs/env_deploy.sh
          find . -name artifacts.tgz | xargs -n1 tar xvzf
          cd deployment
          cp -r public_res/* linux64
          ####
          bash ../libs/package_debian.sh ${{ github.event.inputs.tag }}
          mv nekoray.deb $version_standalone-debian-x64.deb
          sudo rm -rf nekoray
      - name: Pack AppImage
        run: |
          source libs/env_deploy.sh
          find . -name artifacts.tgz | xargs -n1 tar xvzf
          cd deployment
          cp -r public_res/* linux64
          ####
          bash ../libs/package_appimage.sh
          mv nekobox-x86_64.AppImage $version_standalone-linux-x64.AppImage
      - name: Clean Up
        run: |
          cd deployment
          rm -rf linux64
          rm -rf windows64
          rm -rf public_res
          rm -rf *.pdb
      - name: Uploading Artifact
        uses: actions/upload-artifact@v3
        with:
          name: Deployment-${{ github.sha }}
          path: deployment
      - name: Release
        if: github.event.inputs.publish != 'y'
        run: |
          ./ghr -delete -t "${{ github.token }}" -n "${{ github.event.inputs.tag }}" "${{ github.event.inputs.tag }}" deployment


================================================
FILE: .github/workflows/update-pkgbuild.yml
================================================
name: AUR CI
on:
  push:
    branches:
      - main
    paths-ignore:
      - '**.md'
      - 'LICENSE'
      - '!.github/workflows/**'

jobs:
  update:
    runs-on: ubuntu-latest
    steps:
      - uses: chitang233/aur-pkgbuild-builder@main
        with:
          deploy_key: ${{ secrets.DEPLOY_KEY }}
          package_name: 'nekoray-git'

================================================
FILE: .gitignore
================================================
# This file is used to ignore files which are generated
# ----------------------------------------------------------------------------

*~
*.autosave
*.a
*.core
*.moc
*.o
*.obj
*.orig
*.rej
*.so
*.so.*
*_pch.h.cpp
*_resource.rc
.#*
*.*#
core
!core/
tags
.DS_Store
.directory
*.debug
/Makefile*
*.prl
*.app
moc_*.cpp
ui_*.h
qrc_*.cpp
Thumbs.db
*.res
/.qmake.cache
/.qmake.stash

# qtcreator generated files
*.pro.user*

# xemacs temporary files
*.flc

# Vim temporary files
.*.swp

# Visual Studio generated files
*.ib_pdb_index
*.idb
*.ilk
*.pdb
*.sln
*.suo
*.vcproj
*vcproj.*.*.user
*.ncb
*.sdf
*.opensdf
*.vcxproj
*vcxproj.*

# MinGW generated files
*.Debug
*.Release

# Python byte code
*.pyc

# Binaries
# --------
*.dll
*.exe

# Custom
/nekoray
/build
CMakeLists.txt.user*
/cmake-build-*
/build-*
.vscode
.idea

# Deploy
/deployment
/neko*.sh
/qtsdk

.vs
out

================================================
FILE: .gitmodules
================================================
[submodule "3rdparty/QHotkey"]
	path = 3rdparty/QHotkey
	url = https://github.com/Skycoder42/QHotkey.git


================================================
FILE: 3rdparty/QThreadCreateThread.hpp
================================================
#pragma once

#include <future>
#include <QThread>

// FOR OLD QT

class QThreadCreateThread : public QThread {
public:
    explicit QThreadCreateThread(std::future<void> &&future)
            : m_future(std::move(future)) {
        // deleteLater
        connect(this, &QThread::finished, this, &QThread::deleteLater);
    }

private:
    void run() override {
        m_future.get();
    }

    std::future<void> m_future;
};

inline QThread *createThreadImpl(std::future<void> &&future) {
    return new QThreadCreateThread(std::move(future));
}

template<typename Function, typename... Args>
QThread *createQThread(Function &&f, Args &&... args) {
    using DecayedFunction = typename std::decay<Function>::type;
    auto threadFunction =
            [f = static_cast<DecayedFunction>(std::forward<Function>(f))](auto &&... largs) mutable -> void {
                (void) std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
            };

    return createThreadImpl(std::async(std::launch::deferred,
                                       std::move(threadFunction),
                                       std::forward<Args>(args)...));
}


================================================
FILE: 3rdparty/QtExtKeySequenceEdit.cpp
================================================
#include "QtExtKeySequenceEdit.h"

QtExtKeySequenceEdit::QtExtKeySequenceEdit(QWidget *parent)
        : QKeySequenceEdit(parent) {
}

QtExtKeySequenceEdit::~QtExtKeySequenceEdit() {
}

void QtExtKeySequenceEdit::keyPressEvent(QKeyEvent *pEvent) {
    QKeySequenceEdit::keyPressEvent(pEvent);

    QKeySequence keySeq = keySequence();
    if (keySeq.count() <= 0) {
        return;
    }
    int key = keySeq[0];
    if (key == Qt::Key_Backspace || key == Qt::Key_Delete) {
        key = 0;
    }
    setKeySequence(key);
}


================================================
FILE: 3rdparty/QtExtKeySequenceEdit.h
================================================
#include <QKeySequenceEdit>

class QtExtKeySequenceEdit : public QKeySequenceEdit {
public:
    QtExtKeySequenceEdit(QWidget *parent);

    ~QtExtKeySequenceEdit();

protected:
    virtual void keyPressEvent(QKeyEvent *pEvent);
};


================================================
FILE: 3rdparty/RunGuard.hpp
================================================
#ifndef RUNGUARD_H
#define RUNGUARD_H

#include <QObject>
#include <QSharedMemory>
#include <QSystemSemaphore>
#include <QCryptographicHash>

class RunGuard {
public:
    RunGuard(const QString &key);

    ~RunGuard();

    bool isAnotherRunning(quint64 *data_out);

    bool tryToRun(quint64 *data_in);

    void release();

private:
    const QString key;
    const QString memLockKey;
    const QString sharedmemKey;

    QSharedMemory sharedMem;
    QSystemSemaphore memLock;

    Q_DISABLE_COPY(RunGuard)
};

namespace {

    QString generateKeyHash(const QString &key, const QString &salt) {
        QByteArray data;

        data.append(key.toUtf8());
        data.append(salt.toUtf8());
        data = QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex();

        return data;
    }

} // namespace

RunGuard::RunGuard(const QString &key)
    : key(key), memLockKey(generateKeyHash(key, "_memLockKey")), sharedmemKey(generateKeyHash(key, "_sharedmemKey")), sharedMem(sharedmemKey), memLock(memLockKey, 1) {
    memLock.acquire();
    {
        QSharedMemory fix(sharedmemKey); // Fix for *nix: http://habrahabr.ru/post/173281/
        fix.attach();
    }
    memLock.release();
}

RunGuard::~RunGuard() {
    release();
}

bool RunGuard::isAnotherRunning(quint64 *data_out) {
    if (sharedMem.isAttached())
        return false;

    memLock.acquire();
    const bool isRunning = sharedMem.attach();
    if (isRunning) {
        if (data_out != nullptr) {
            memcpy(data_out, sharedMem.data(), sizeof(quint64));
        }
        sharedMem.detach();
    }
    memLock.release();

    return isRunning;
}

bool RunGuard::tryToRun(quint64 *data_in) {
    memLock.acquire();
    const bool result = sharedMem.create(sizeof(quint64));
    if (result) memcpy(sharedMem.data(), data_in, sizeof(quint64));
    memLock.release();

    if (!result) {
        release();
        return false;
    }

    return true;
}

void RunGuard::release() {
    memLock.acquire();
    if (sharedMem.isAttached())
        sharedMem.detach();
    memLock.release();
}

#endif // RUNGUARD_H


================================================
FILE: 3rdparty/VT100Parser.hpp
================================================
#pragma once

#include <QString>

inline QString cleanVT100String(const QString &in) {
    QString out;
    bool in_033 = false;
    for (auto &&chr: in) {
        if (chr == '\033') {
            in_033 = true;
            continue;
        }
        if (in_033) {
            if (chr == 'm') {
                in_033 = false;
            }
            continue;
        }
        out += chr;
    }
    return out;
}


================================================
FILE: 3rdparty/WinCommander.cpp
================================================
/****************************************************************************
**
** Copyright (C) 2014 UpdateNode UG (haftungsbeschränkt)
** Contact: code@updatenode.com
**
** This file is part of the UpdateNode Client.
**
** Commercial License Usage
** Licensees holding valid commercial UpdateNode license may use this file
** under the terms of the the Apache License, Version 2.0
** Full license description file: LICENSE.COM
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation. Please review the following information to ensure the
** GNU General Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
** Full license description file: LICENSE.GPL
**
****************************************************************************/

#include "WinCommander.hpp"

#include <QSysInfo>
#include <QDir>

#ifdef Q_OS_WIN
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <shellapi.h>
#include <sddl.h>
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383
#endif


/*!
Executes a command elevated specified by \apath , using paramters \aparameters.
\n
Parameter /aaWait decides if the function should return immediatelly after it's\n
execution or wait for the exit of the launched process
\n
Returns the return value of the executed command
*/
uint WinCommander::runProcessElevated(const QString &path,
                                      const QStringList &parameters,
                                      const QString &workingDir,
                                      int nShow, bool aWait) {
    uint result = 0;

#ifdef Q_OS_WIN
    QString params;
    HWND hwnd = NULL;
    LPCTSTR pszPath = (LPCTSTR)path.utf16();
    foreach(QString item, parameters)
        params += "\"" + item + "\" ";

    LPCTSTR pszParameters = (LPCTSTR)params.utf16();
    QString dir;
    if (workingDir.count() == 0)
        dir = QDir::toNativeSeparators(QDir::currentPath());
    else
        dir = QDir::toNativeSeparators(workingDir);
    LPCTSTR pszDirectory = (LPCTSTR)dir.utf16();

    SHELLEXECUTEINFO shex;
    DWORD dwCode  =   0;

    ZeroMemory(&shex, sizeof(shex));

    shex.cbSize       = sizeof(shex);
    shex.fMask        = SEE_MASK_NOCLOSEPROCESS;
    shex.hwnd         = hwnd;
    shex.lpVerb       = TEXT("runas");
    shex.lpFile       = pszPath;
    shex.lpParameters = pszParameters;
    shex.lpDirectory  = pszDirectory;
    // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
    shex.nShow        = nShow;

    ShellExecuteEx(&shex);
    if (shex.hProcess)
    {
        if(aWait)
        {
            WaitForSingleObject(shex.hProcess, INFINITE );
            GetExitCodeProcess(shex.hProcess, &dwCode);
        }
        CloseHandle (shex.hProcess) ;
    }
    else
        return -1;

    result = (uint)dwCode;
#else
    Q_UNUSED(path);
    Q_UNUSED(parameters);
    Q_UNUSED(workingDir);
    Q_UNUSED(aWait);
#endif
    return result;
}


================================================
FILE: 3rdparty/WinCommander.hpp
================================================
/****************************************************************************
**
** Copyright (C) 2014 UpdateNode UG (haftungsbeschränkt)
** Contact: code@updatenode.com
**
** This file is part of the UpdateNode Client.
**
** Commercial License Usage
** Licensees holding valid commercial UpdateNode license may use this file
** under the terms of the the Apache License, Version 2.0
** Full license description file: LICENSE.COM
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation. Please review the following information to ensure the
** GNU General Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
** Full license description file: LICENSE.GPL
**
****************************************************************************/

#ifndef WINCOMMANDER_H
#define WINCOMMANDER_H

#include <QString>
#include <QStringList>

class WinCommander {
public:
    static const int SW_HIDE = 0;
    static const int SW_NORMAL = 1;
    static const int SW_SHOWMINIMIZED = 2;

    static uint runProcessElevated(const QString &path,
                                   const QStringList &parameters = QStringList(),
                                   const QString &workingDir = QString(),
                                   int nShow = SW_SHOWMINIMIZED, bool aWait = true);
};

#endif // WINCOMMANDER_H

================================================
FILE: 3rdparty/ZxingQtReader.hpp
================================================
/*
 * Copyright 2020 Axel Waggershauser
 */
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "ZXing/ReadBarcode.h"

#include <QImage>
#include <QDebug>
#include <QMetaType>
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
#include "qscopeguard.h"
#else
#include <QScopeGuard>
#endif

#ifdef QT_MULTIMEDIA_LIB
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <QAbstractVideoFilter>
#else
#include <QVideoFrame>
#include <QVideoSink>
#endif
#include <QElapsedTimer>
#endif

// This is some sample code to start a discussion about how a minimal and header-only Qt wrapper/helper could look like.

namespace ZXingQt {

Q_NAMESPACE

//TODO: find a better way to export these enums to QML than to duplicate their definition
// #ifdef Q_MOC_RUN produces meta information in the moc output but it does end up working in qml
#ifdef QT_QML_LIB
enum class BarcodeFormat
{
	None            = 0,         ///< Used as a return value if no valid barcode has been detected
	Aztec           = (1 << 0),  ///< Aztec
	Codabar         = (1 << 1),  ///< Codabar
	Code39          = (1 << 2),  ///< Code39
	Code93          = (1 << 3),  ///< Code93
	Code128         = (1 << 4),  ///< Code128
	DataBar         = (1 << 5),  ///< GS1 DataBar, formerly known as RSS 14
	DataBarExpanded = (1 << 6),  ///< GS1 DataBar Expanded, formerly known as RSS EXPANDED
	DataMatrix      = (1 << 7),  ///< DataMatrix
	EAN8            = (1 << 8),  ///< EAN-8
	EAN13           = (1 << 9),  ///< EAN-13
	ITF             = (1 << 10), ///< ITF (Interleaved Two of Five)
	MaxiCode        = (1 << 11), ///< MaxiCode
	PDF417          = (1 << 12), ///< PDF417 or
	QRCode          = (1 << 13), ///< QR Code
	UPCA            = (1 << 14), ///< UPC-A
	UPCE            = (1 << 15), ///< UPC-E
	MicroQRCode     = (1 << 16), ///< Micro QR Code

	LinearCodes = Codabar | Code39 | Code93 | Code128 | EAN8 | EAN13 | ITF | DataBar | DataBarExpanded | UPCA | UPCE,
	MatrixCodes = Aztec | DataMatrix | MaxiCode | PDF417 | QRCode | MicroQRCode,
};

enum class ContentType { Text, Binary, Mixed, GS1, ISO15434, UnknownECI };

#else
using ZXing::BarcodeFormat;
using ZXing::ContentType;
#endif

using ZXing::DecodeHints;
using ZXing::Binarizer;
using ZXing::BarcodeFormats;

Q_ENUM_NS(BarcodeFormat)
Q_ENUM_NS(ContentType)

template<typename T, typename = decltype(ZXing::ToString(T()))>
QDebug operator<<(QDebug dbg, const T& v)
{
	return dbg.noquote() << QString::fromStdString(ToString(v));
}

class Position : public ZXing::Quadrilateral<QPoint>
{
	Q_GADGET

	Q_PROPERTY(QPoint topLeft READ topLeft)
	Q_PROPERTY(QPoint topRight READ topRight)
	Q_PROPERTY(QPoint bottomRight READ bottomRight)
	Q_PROPERTY(QPoint bottomLeft READ bottomLeft)

	using Base = ZXing::Quadrilateral<QPoint>;

public:
	using Base::Base;
};

class Result : private ZXing::Result
{
	Q_GADGET

	Q_PROPERTY(BarcodeFormat format READ format)
	Q_PROPERTY(QString formatName READ formatName)
	Q_PROPERTY(QString text READ text)
	Q_PROPERTY(QByteArray bytes READ bytes)
	Q_PROPERTY(bool isValid READ isValid)
	Q_PROPERTY(ContentType contentType READ contentType)
	Q_PROPERTY(Position position READ position)

	QString _text;
	QByteArray _bytes;
	Position _position;

public:
	Result() = default; // required for qmetatype machinery

	explicit Result(ZXing::Result&& r) : ZXing::Result(std::move(r)) {
		_text = QString::fromStdString(ZXing::Result::text());
		_bytes = QByteArray(reinterpret_cast<const char*>(ZXing::Result::bytes().data()), Size(ZXing::Result::bytes()));
		auto& pos = ZXing::Result::position();
		auto qp = [&pos](int i) { return QPoint(pos[i].x, pos[i].y); };
		_position = {qp(0), qp(1), qp(2), qp(3)};
	}

	using ZXing::Result::isValid;

	BarcodeFormat format() const { return static_cast<BarcodeFormat>(ZXing::Result::format()); }
	ContentType contentType() const { return static_cast<ContentType>(ZXing::Result::contentType()); }
	QString formatName() const { return QString::fromStdString(ZXing::ToString(ZXing::Result::format())); }
	const QString& text() const { return _text; }
	const QByteArray& bytes() const { return _bytes; }
	const Position& position() const { return _position; }

	// For debugging/development
	int runTime = 0;
	Q_PROPERTY(int runTime MEMBER runTime)
};

inline QList<Result> QListResults(ZXing::Results&& zxres)
{
	QList<Result> res;
	for (auto&& r : zxres)
		res.push_back(Result(std::move(r)));
	return res;
}

inline QList<Result> ReadBarcodes(const QImage& img, const DecodeHints& hints = {})
{
	using namespace ZXing;

	auto ImgFmtFromQImg = [](const QImage& img) {
		switch (img.format()) {
		case QImage::Format_ARGB32:
		case QImage::Format_RGB32:
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
			return ImageFormat::BGRX;
#else
			return ImageFormat::XRGB;
#endif
		case QImage::Format_RGB888: return ImageFormat::RGB;
		case QImage::Format_RGBX8888:
		case QImage::Format_RGBA8888: return ImageFormat::RGBX;
		case QImage::Format_Grayscale8: return ImageFormat::Lum;
		default: return ImageFormat::None;
		}
	};

	auto exec = [&](const QImage& img) {
		return QListResults(ZXing::ReadBarcodes(
			{img.bits(), img.width(), img.height(), ImgFmtFromQImg(img), static_cast<int>(img.bytesPerLine())}, hints));
	};

	return ImgFmtFromQImg(img) == ImageFormat::None ? exec(img.convertToFormat(QImage::Format_Grayscale8)) : exec(img);
}

inline Result ReadBarcode(const QImage& img, const DecodeHints& hints = {})
{
	auto res = ReadBarcodes(img, DecodeHints(hints).setMaxNumberOfSymbols(1));
	return !res.isEmpty() ? res.takeFirst() : Result();
}

#ifdef QT_MULTIMEDIA_LIB
inline QList<Result> ReadBarcodes(const QVideoFrame& frame, const DecodeHints& hints = {})
{
	using namespace ZXing;

	ImageFormat fmt = ImageFormat::None;
	int pixStride = 0;
	int pixOffset = 0;

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#define FORMAT(F5, F6) QVideoFrame::Format_##F5
#define FIRST_PLANE
#else
#define FORMAT(F5, F6) QVideoFrameFormat::Format_##F6
#define FIRST_PLANE 0
#endif

	switch (frame.pixelFormat()) {
	case FORMAT(ARGB32, ARGB8888):
	case FORMAT(ARGB32_Premultiplied, ARGB8888_Premultiplied):
	case FORMAT(RGB32, RGBX8888):
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
		fmt = ImageFormat::BGRX;
#else
		fmt = ImageFormat::XRGB;
#endif
		break;

	case FORMAT(BGRA32, BGRA8888):
	case FORMAT(BGRA32_Premultiplied, BGRA8888_Premultiplied):
	case FORMAT(BGR32, BGRX8888):
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
		fmt = ImageFormat::RGBX;
#else
		fmt = ImageFormat::XBGR;
#endif
		break;

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
	case QVideoFrame::Format_RGB24: fmt = ImageFormat::RGB; break;
	case QVideoFrame::Format_BGR24: fmt = ImageFormat::BGR; break;
	case QVideoFrame::Format_YUV444: fmt = ImageFormat::Lum, pixStride = 3; break;
#else
	case QVideoFrameFormat::Format_P010:
	case QVideoFrameFormat::Format_P016: fmt = ImageFormat::Lum, pixStride = 1; break;
#endif

	case FORMAT(AYUV444, AYUV):
	case FORMAT(AYUV444_Premultiplied, AYUV_Premultiplied):
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
		fmt = ImageFormat::Lum, pixStride = 4, pixOffset = 3;
#else
		fmt = ImageFormat::Lum, pixStride = 4, pixOffset = 2;
#endif
		break;

	case FORMAT(YUV420P, YUV420P):
	case FORMAT(NV12, NV12):
	case FORMAT(NV21, NV21):
	case FORMAT(IMC1, IMC1):
	case FORMAT(IMC2, IMC2):
	case FORMAT(IMC3, IMC3):
	case FORMAT(IMC4, IMC4):
	case FORMAT(YV12, YV12): fmt = ImageFormat::Lum; break;
	case FORMAT(UYVY, UYVY): fmt = ImageFormat::Lum, pixStride = 2, pixOffset = 1; break;
	case FORMAT(YUYV, YUYV): fmt = ImageFormat::Lum, pixStride = 2; break;

	case FORMAT(Y8, Y8): fmt = ImageFormat::Lum; break;
	case FORMAT(Y16, Y16): fmt = ImageFormat::Lum, pixStride = 2, pixOffset = 1; break;

#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
	case FORMAT(ABGR32, ABGR8888):
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
		fmt = ImageFormat::RGBX;
#else
		fmt = ImageFormat::XBGR;
#endif
		break;
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
	case FORMAT(YUV422P, YUV422P): fmt = ImageFormat::Lum; break;
#endif
	default: break;
	}

	if (fmt != ImageFormat::None) {
		auto img = frame; // shallow copy just get access to non-const map() function
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
		if (!img.isValid() || !img.map(QAbstractVideoBuffer::ReadOnly)){
#else
		if (!img.isValid() || !img.map(QVideoFrame::ReadOnly)){
#endif
			qWarning() << "invalid QVideoFrame: could not map memory";
			return {};
		}
		QScopeGuard unmap([&] { img.unmap(); });

		return QListResults(ZXing::ReadBarcodes(
			{img.bits(FIRST_PLANE) + pixOffset, img.width(), img.height(), fmt, img.bytesPerLine(FIRST_PLANE), pixStride}, hints));
	}
	else {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
		if (QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat()) != QImage::Format_Invalid) {
			qWarning() << "unsupported QVideoFrame::pixelFormat";
			return {};
		}
		auto qimg = frame.image();
#else
		auto qimg = frame.toImage();
#endif
		if (qimg.format() != QImage::Format_Invalid)
			return ReadBarcodes(qimg, hints);
		qWarning() << "failed to convert QVideoFrame to QImage";
		return {};
	}
}

inline Result ReadBarcode(const QVideoFrame& frame, const DecodeHints& hints = {})
{
	auto res = ReadBarcodes(frame, DecodeHints(hints).setMaxNumberOfSymbols(1));
	return !res.isEmpty() ? res.takeFirst() : Result();
}

#define ZQ_PROPERTY(Type, name, setter) \
public: \
	Q_PROPERTY(Type name READ name WRITE setter NOTIFY name##Changed) \
	Type name() const noexcept { return DecodeHints::name(); } \
	Q_SLOT void setter(const Type& newVal) \
	{ \
		if (name() != newVal) { \
			DecodeHints::setter(newVal); \
			emit name##Changed(); \
		} \
	} \
	Q_SIGNAL void name##Changed();


#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
class BarcodeReader : public QAbstractVideoFilter, private DecodeHints
#else
class BarcodeReader : public QObject, private DecodeHints
#endif
{
	Q_OBJECT

public:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
	BarcodeReader(QObject* parent = nullptr) : QAbstractVideoFilter(parent) {}
#else
	BarcodeReader(QObject* parent = nullptr) : QObject(parent) {}
#endif

	// TODO: find out how to properly expose QFlags to QML
	// simply using ZQ_PROPERTY(BarcodeFormats, formats, setFormats)
	// results in the runtime error "can't assign int to formats"
	Q_PROPERTY(int formats READ formats WRITE setFormats NOTIFY formatsChanged)
	int formats() const noexcept
	{
		auto fmts = DecodeHints::formats();
		return *reinterpret_cast<int*>(&fmts);
	}
	Q_SLOT void setFormats(int newVal)
	{
		if (formats() != newVal) {
			DecodeHints::setFormats(static_cast<ZXing::BarcodeFormat>(newVal));
			emit formatsChanged();
			qDebug() << DecodeHints::formats();
		}
	}
	Q_SIGNAL void formatsChanged();

	ZQ_PROPERTY(bool, tryRotate, setTryRotate)
	ZQ_PROPERTY(bool, tryHarder, setTryHarder)
	ZQ_PROPERTY(bool, tryDownscale, setTryDownscale)

public slots:
	ZXingQt::Result process(const QVideoFrame& image)
	{
		QElapsedTimer t;
		t.start();

		auto res = ReadBarcode(image, *this);

		res.runTime = t.elapsed();

		emit newResult(res);
		if (res.isValid())
			emit foundBarcode(res);
		return res;
	}

signals:
	void newResult(ZXingQt::Result result);
	void foundBarcode(ZXingQt::Result result);

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
public:
	QVideoFilterRunnable *createFilterRunnable() override;
#else
private:
	QVideoSink *_sink = nullptr;

public:
	void setVideoSink(QVideoSink* sink) {
		if (_sink == sink)
			return;

		if (_sink)
			disconnect(_sink, nullptr, this, nullptr);

		_sink = sink;
		connect(_sink, &QVideoSink::videoFrameChanged, this, &BarcodeReader::process);
	}
	Q_PROPERTY(QVideoSink* videoSink WRITE setVideoSink)
#endif

};

#undef ZX_PROPERTY

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
class VideoFilterRunnable : public QVideoFilterRunnable
{
	BarcodeReader* _filter = nullptr;

public:
	explicit VideoFilterRunnable(BarcodeReader* filter) : _filter(filter) {}

	QVideoFrame run(QVideoFrame* input, const QVideoSurfaceFormat& /*surfaceFormat*/, RunFlags /*flags*/) override
	{
		_filter->process(*input);
		return *input;
	}
};

inline QVideoFilterRunnable* BarcodeReader::createFilterRunnable()
{
	return new VideoFilterRunnable(this);
}
#endif

#endif // QT_MULTIMEDIA_LIB

} // namespace ZXingQt


Q_DECLARE_METATYPE(ZXingQt::Position)
Q_DECLARE_METATYPE(ZXingQt::Result)

#ifdef QT_QML_LIB

#include <QQmlEngine>

namespace ZXingQt {

inline void registerQmlAndMetaTypes()
{
	qRegisterMetaType<ZXingQt::BarcodeFormat>("BarcodeFormat");
	qRegisterMetaType<ZXingQt::ContentType>("ContentType");

	// supposedly the Q_DECLARE_METATYPE should be used with the overload without a custom name
	// but then the qml side complains about "unregistered type"
	qRegisterMetaType<ZXingQt::Position>("Position");
	qRegisterMetaType<ZXingQt::Result>("Result");

	qmlRegisterUncreatableMetaObject(
		ZXingQt::staticMetaObject, "ZXing", 1, 0, "ZXing", "Access to enums & flags only");
	qmlRegisterType<ZXingQt::BarcodeReader>("ZXing", 1, 0, "BarcodeReader");
}

} // namespace ZXingQt

#endif // QT_QML_LIB

================================================
FILE: 3rdparty/base64.cpp
================================================
#include "base64.h"

#ifndef qsizetype
#define qsizetype size_t
#endif

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<char *>(result.constData()),
                                                    options);
        result.truncate(int(base64result.decodedLength));
        return {std::move(result), base64result.status};
    }
} // namespace Qt515Base64


================================================
FILE: 3rdparty/base64.h
================================================
#include <QByteArray>

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


================================================
FILE: 3rdparty/fix_old_qt.h
================================================
#pragma once

#include <QString>

#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)

inline QString qEnvironmentVariable(const char *varName) {
    return qgetenv(varName);
}

#endif


================================================
FILE: 3rdparty/qrcodegen.cpp
================================================
/* 
 * QR Code generator library (C++)
 * 
 * Copyright (c) Project Nayuki. (MIT License)
 * https://www.nayuki.io/page/qr-code-generator-library
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 * - The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 * - The Software is provided "as is", without warranty of any kind, express or
 *   implied, including but not limited to the warranties of merchantability,
 *   fitness for a particular purpose and noninfringement. In no event shall the
 *   authors or copyright holders be liable for any claim, damages or other
 *   liability, whether in an action of contract, tort or otherwise, arising from,
 *   out of or in connection with the Software or the use or other dealings in the
 *   Software.
 */

#include <algorithm>
#include <cassert>
#include <climits>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <utility>
#include "qrcodegen.hpp"

using std::int8_t;
using std::uint8_t;
using std::size_t;
using std::vector;


namespace qrcodegen {

/*---- Class QrSegment ----*/

QrSegment::Mode::Mode(int mode, int cc0, int cc1, int cc2) :
		modeBits(mode) {
	numBitsCharCount[0] = cc0;
	numBitsCharCount[1] = cc1;
	numBitsCharCount[2] = cc2;
}


int QrSegment::Mode::getModeBits() const {
	return modeBits;
}


int QrSegment::Mode::numCharCountBits(int ver) const {
	return numBitsCharCount[(ver + 7) / 17];
}


const QrSegment::Mode QrSegment::Mode::NUMERIC     (0x1, 10, 12, 14);
const QrSegment::Mode QrSegment::Mode::ALPHANUMERIC(0x2,  9, 11, 13);
const QrSegment::Mode QrSegment::Mode::BYTE        (0x4,  8, 16, 16);
const QrSegment::Mode QrSegment::Mode::KANJI       (0x8,  8, 10, 12);
const QrSegment::Mode QrSegment::Mode::ECI         (0x7,  0,  0,  0);


QrSegment QrSegment::makeBytes(const vector<uint8_t> &data) {
	if (data.size() > static_cast<unsigned int>(INT_MAX))
		throw std::length_error("Data too long");
	BitBuffer bb;
	for (uint8_t b : data)
		bb.appendBits(b, 8);
	return QrSegment(Mode::BYTE, static_cast<int>(data.size()), std::move(bb));
}


QrSegment QrSegment::makeNumeric(const char *digits) {
	BitBuffer bb;
	int accumData = 0;
	int accumCount = 0;
	int charCount = 0;
	for (; *digits != '\0'; digits++, charCount++) {
		char c = *digits;
		if (c < '0' || c > '9')
			throw std::domain_error("String contains non-numeric characters");
		accumData = accumData * 10 + (c - '0');
		accumCount++;
		if (accumCount == 3) {
			bb.appendBits(static_cast<uint32_t>(accumData), 10);
			accumData = 0;
			accumCount = 0;
		}
	}
	if (accumCount > 0)  // 1 or 2 digits remaining
		bb.appendBits(static_cast<uint32_t>(accumData), accumCount * 3 + 1);
	return QrSegment(Mode::NUMERIC, charCount, std::move(bb));
}


QrSegment QrSegment::makeAlphanumeric(const char *text) {
	BitBuffer bb;
	int accumData = 0;
	int accumCount = 0;
	int charCount = 0;
	for (; *text != '\0'; text++, charCount++) {
		const char *temp = std::strchr(ALPHANUMERIC_CHARSET, *text);
		if (temp == nullptr)
			throw std::domain_error("String contains unencodable characters in alphanumeric mode");
		accumData = accumData * 45 + static_cast<int>(temp - ALPHANUMERIC_CHARSET);
		accumCount++;
		if (accumCount == 2) {
			bb.appendBits(static_cast<uint32_t>(accumData), 11);
			accumData = 0;
			accumCount = 0;
		}
	}
	if (accumCount > 0)  // 1 character remaining
		bb.appendBits(static_cast<uint32_t>(accumData), 6);
	return QrSegment(Mode::ALPHANUMERIC, charCount, std::move(bb));
}


vector<QrSegment> QrSegment::makeSegments(const char *text) {
	// Select the most efficient segment encoding automatically
	vector<QrSegment> result;
	if (*text == '\0');  // Leave result empty
	else if (isNumeric(text))
		result.push_back(makeNumeric(text));
	else if (isAlphanumeric(text))
		result.push_back(makeAlphanumeric(text));
	else {
		vector<uint8_t> bytes;
		for (; *text != '\0'; text++)
			bytes.push_back(static_cast<uint8_t>(*text));
		result.push_back(makeBytes(bytes));
	}
	return result;
}


QrSegment QrSegment::makeEci(long assignVal) {
	BitBuffer bb;
	if (assignVal < 0)
		throw std::domain_error("ECI assignment value out of range");
	else if (assignVal < (1 << 7))
		bb.appendBits(static_cast<uint32_t>(assignVal), 8);
	else if (assignVal < (1 << 14)) {
		bb.appendBits(2, 2);
		bb.appendBits(static_cast<uint32_t>(assignVal), 14);
	} else if (assignVal < 1000000L) {
		bb.appendBits(6, 3);
		bb.appendBits(static_cast<uint32_t>(assignVal), 21);
	} else
		throw std::domain_error("ECI assignment value out of range");
	return QrSegment(Mode::ECI, 0, std::move(bb));
}


QrSegment::QrSegment(const Mode &md, int numCh, const std::vector<bool> &dt) :
		mode(&md),
		numChars(numCh),
		data(dt) {
	if (numCh < 0)
		throw std::domain_error("Invalid value");
}


QrSegment::QrSegment(const Mode &md, int numCh, std::vector<bool> &&dt) :
		mode(&md),
		numChars(numCh),
		data(std::move(dt)) {
	if (numCh < 0)
		throw std::domain_error("Invalid value");
}


int QrSegment::getTotalBits(const vector<QrSegment> &segs, int version) {
	int result = 0;
	for (const QrSegment &seg : segs) {
		int ccbits = seg.mode->numCharCountBits(version);
		if (seg.numChars >= (1L << ccbits))
			return -1;  // The segment's length doesn't fit the field's bit width
		if (4 + ccbits > INT_MAX - result)
			return -1;  // The sum will overflow an int type
		result += 4 + ccbits;
		if (seg.data.size() > static_cast<unsigned int>(INT_MAX - result))
			return -1;  // The sum will overflow an int type
		result += static_cast<int>(seg.data.size());
	}
	return result;
}


bool QrSegment::isNumeric(const char *text) {
	for (; *text != '\0'; text++) {
		char c = *text;
		if (c < '0' || c > '9')
			return false;
	}
	return true;
}


bool QrSegment::isAlphanumeric(const char *text) {
	for (; *text != '\0'; text++) {
		if (std::strchr(ALPHANUMERIC_CHARSET, *text) == nullptr)
			return false;
	}
	return true;
}


const QrSegment::Mode &QrSegment::getMode() const {
	return *mode;
}


int QrSegment::getNumChars() const {
	return numChars;
}


const std::vector<bool> &QrSegment::getData() const {
	return data;
}


const char *QrSegment::ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";



/*---- Class QrCode ----*/

int QrCode::getFormatBits(Ecc ecl) {
	switch (ecl) {
		case Ecc::LOW     :  return 1;
		case Ecc::MEDIUM  :  return 0;
		case Ecc::QUARTILE:  return 3;
		case Ecc::HIGH    :  return 2;
		default:  throw std::logic_error("Unreachable");
	}
}


QrCode QrCode::encodeText(const char *text, Ecc ecl) {
	vector<QrSegment> segs = QrSegment::makeSegments(text);
	return encodeSegments(segs, ecl);
}


QrCode QrCode::encodeBinary(const vector<uint8_t> &data, Ecc ecl) {
	vector<QrSegment> segs{QrSegment::makeBytes(data)};
	return encodeSegments(segs, ecl);
}


QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
		int minVersion, int maxVersion, int mask, bool boostEcl) {
	if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7)
		throw std::invalid_argument("Invalid value");
	
	// Find the minimal version number to use
	int version, dataUsedBits;
	for (version = minVersion; ; version++) {
		int dataCapacityBits = getNumDataCodewords(version, ecl) * 8;  // Number of data bits available
		dataUsedBits = QrSegment::getTotalBits(segs, version);
		if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
			break;  // This version number is found to be suitable
		if (version >= maxVersion) {  // All versions in the range could not fit the given data
			std::ostringstream sb;
			if (dataUsedBits == -1)
				sb << "Segment too long";
			else {
				sb << "Data length = " << dataUsedBits << " bits, ";
				sb << "Max capacity = " << dataCapacityBits << " bits";
			}
			throw data_too_long(sb.str());
		}
	}
	assert(dataUsedBits != -1);
	
	// Increase the error correction level while the data still fits in the current version number
	for (Ecc newEcl : {Ecc::MEDIUM, Ecc::QUARTILE, Ecc::HIGH}) {  // From low to high
		if (boostEcl && dataUsedBits <= getNumDataCodewords(version, newEcl) * 8)
			ecl = newEcl;
	}
	
	// Concatenate all segments to create the data bit string
	BitBuffer bb;
	for (const QrSegment &seg : segs) {
		bb.appendBits(static_cast<uint32_t>(seg.getMode().getModeBits()), 4);
		bb.appendBits(static_cast<uint32_t>(seg.getNumChars()), seg.getMode().numCharCountBits(version));
		bb.insert(bb.end(), seg.getData().begin(), seg.getData().end());
	}
	assert(bb.size() == static_cast<unsigned int>(dataUsedBits));
	
	// Add terminator and pad up to a byte if applicable
	size_t dataCapacityBits = static_cast<size_t>(getNumDataCodewords(version, ecl)) * 8;
	assert(bb.size() <= dataCapacityBits);
	bb.appendBits(0, std::min(4, static_cast<int>(dataCapacityBits - bb.size())));
	bb.appendBits(0, (8 - static_cast<int>(bb.size() % 8)) % 8);
	assert(bb.size() % 8 == 0);
	
	// Pad with alternating bytes until data capacity is reached
	for (uint8_t padByte = 0xEC; bb.size() < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
		bb.appendBits(padByte, 8);
	
	// Pack bits into bytes in big endian
	vector<uint8_t> dataCodewords(bb.size() / 8);
	for (size_t i = 0; i < bb.size(); i++)
		dataCodewords.at(i >> 3) |= (bb.at(i) ? 1 : 0) << (7 - (i & 7));
	
	// Create the QR Code object
	return QrCode(version, ecl, dataCodewords, mask);
}


QrCode::QrCode(int ver, Ecc ecl, const vector<uint8_t> &dataCodewords, int msk) :
		// Initialize fields and check arguments
		version(ver),
		errorCorrectionLevel(ecl) {
	if (ver < MIN_VERSION || ver > MAX_VERSION)
		throw std::domain_error("Version value out of range");
	if (msk < -1 || msk > 7)
		throw std::domain_error("Mask value out of range");
	size = ver * 4 + 17;
	size_t sz = static_cast<size_t>(size);
	modules    = vector<vector<bool> >(sz, vector<bool>(sz));  // Initially all light
	isFunction = vector<vector<bool> >(sz, vector<bool>(sz));
	
	// Compute ECC, draw modules
	drawFunctionPatterns();
	const vector<uint8_t> allCodewords = addEccAndInterleave(dataCodewords);
	drawCodewords(allCodewords);
	
	// Do masking
	if (msk == -1) {  // Automatically choose best mask
		long minPenalty = LONG_MAX;
		for (int i = 0; i < 8; i++) {
			applyMask(i);
			drawFormatBits(i);
			long penalty = getPenaltyScore();
			if (penalty < minPenalty) {
				msk = i;
				minPenalty = penalty;
			}
			applyMask(i);  // Undoes the mask due to XOR
		}
	}
	assert(0 <= msk && msk <= 7);
	mask = msk;
	applyMask(msk);  // Apply the final choice of mask
	drawFormatBits(msk);  // Overwrite old format bits
	
	isFunction.clear();
	isFunction.shrink_to_fit();
}


int QrCode::getVersion() const {
	return version;
}


int QrCode::getSize() const {
	return size;
}


QrCode::Ecc QrCode::getErrorCorrectionLevel() const {
	return errorCorrectionLevel;
}


int QrCode::getMask() const {
	return mask;
}


bool QrCode::getModule(int x, int y) const {
	return 0 <= x && x < size && 0 <= y && y < size && module(x, y);
}


void QrCode::drawFunctionPatterns() {
	// Draw horizontal and vertical timing patterns
	for (int i = 0; i < size; i++) {
		setFunctionModule(6, i, i % 2 == 0);
		setFunctionModule(i, 6, i % 2 == 0);
	}
	
	// Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)
	drawFinderPattern(3, 3);
	drawFinderPattern(size - 4, 3);
	drawFinderPattern(3, size - 4);
	
	// Draw numerous alignment patterns
	const vector<int> alignPatPos = getAlignmentPatternPositions();
	size_t numAlign = alignPatPos.size();
	for (size_t i = 0; i < numAlign; i++) {
		for (size_t j = 0; j < numAlign; j++) {
			// Don't draw on the three finder corners
			if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)))
				drawAlignmentPattern(alignPatPos.at(i), alignPatPos.at(j));
		}
	}
	
	// Draw configuration data
	drawFormatBits(0);  // Dummy mask value; overwritten later in the constructor
	drawVersion();
}


void QrCode::drawFormatBits(int msk) {
	// Calculate error correction code and pack bits
	int data = getFormatBits(errorCorrectionLevel) << 3 | msk;  // errCorrLvl is uint2, msk is uint3
	int rem = data;
	for (int i = 0; i < 10; i++)
		rem = (rem << 1) ^ ((rem >> 9) * 0x537);
	int bits = (data << 10 | rem) ^ 0x5412;  // uint15
	assert(bits >> 15 == 0);
	
	// Draw first copy
	for (int i = 0; i <= 5; i++)
		setFunctionModule(8, i, getBit(bits, i));
	setFunctionModule(8, 7, getBit(bits, 6));
	setFunctionModule(8, 8, getBit(bits, 7));
	setFunctionModule(7, 8, getBit(bits, 8));
	for (int i = 9; i < 15; i++)
		setFunctionModule(14 - i, 8, getBit(bits, i));
	
	// Draw second copy
	for (int i = 0; i < 8; i++)
		setFunctionModule(size - 1 - i, 8, getBit(bits, i));
	for (int i = 8; i < 15; i++)
		setFunctionModule(8, size - 15 + i, getBit(bits, i));
	setFunctionModule(8, size - 8, true);  // Always dark
}


void QrCode::drawVersion() {
	if (version < 7)
		return;
	
	// Calculate error correction code and pack bits
	int rem = version;  // version is uint6, in the range [7, 40]
	for (int i = 0; i < 12; i++)
		rem = (rem << 1) ^ ((rem >> 11) * 0x1F25);
	long bits = static_cast<long>(version) << 12 | rem;  // uint18
	assert(bits >> 18 == 0);
	
	// Draw two copies
	for (int i = 0; i < 18; i++) {
		bool bit = getBit(bits, i);
		int a = size - 11 + i % 3;
		int b = i / 3;
		setFunctionModule(a, b, bit);
		setFunctionModule(b, a, bit);
	}
}


void QrCode::drawFinderPattern(int x, int y) {
	for (int dy = -4; dy <= 4; dy++) {
		for (int dx = -4; dx <= 4; dx++) {
			int dist = std::max(std::abs(dx), std::abs(dy));  // Chebyshev/infinity norm
			int xx = x + dx, yy = y + dy;
			if (0 <= xx && xx < size && 0 <= yy && yy < size)
				setFunctionModule(xx, yy, dist != 2 && dist != 4);
		}
	}
}


void QrCode::drawAlignmentPattern(int x, int y) {
	for (int dy = -2; dy <= 2; dy++) {
		for (int dx = -2; dx <= 2; dx++)
			setFunctionModule(x + dx, y + dy, std::max(std::abs(dx), std::abs(dy)) != 1);
	}
}


void QrCode::setFunctionModule(int x, int y, bool isDark) {
	size_t ux = static_cast<size_t>(x);
	size_t uy = static_cast<size_t>(y);
	modules   .at(uy).at(ux) = isDark;
	isFunction.at(uy).at(ux) = true;
}


bool QrCode::module(int x, int y) const {
	return modules.at(static_cast<size_t>(y)).at(static_cast<size_t>(x));
}


vector<uint8_t> QrCode::addEccAndInterleave(const vector<uint8_t> &data) const {
	if (data.size() != static_cast<unsigned int>(getNumDataCodewords(version, errorCorrectionLevel)))
		throw std::invalid_argument("Invalid argument");
	
	// Calculate parameter numbers
	int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[static_cast<int>(errorCorrectionLevel)][version];
	int blockEccLen = ECC_CODEWORDS_PER_BLOCK  [static_cast<int>(errorCorrectionLevel)][version];
	int rawCodewords = getNumRawDataModules(version) / 8;
	int numShortBlocks = numBlocks - rawCodewords % numBlocks;
	int shortBlockLen = rawCodewords / numBlocks;
	
	// Split data into blocks and append ECC to each block
	vector<vector<uint8_t> > blocks;
	const vector<uint8_t> rsDiv = reedSolomonComputeDivisor(blockEccLen);
	for (int i = 0, k = 0; i < numBlocks; i++) {
		vector<uint8_t> dat(data.cbegin() + k, data.cbegin() + (k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1)));
		k += static_cast<int>(dat.size());
		const vector<uint8_t> ecc = reedSolomonComputeRemainder(dat, rsDiv);
		if (i < numShortBlocks)
			dat.push_back(0);
		dat.insert(dat.end(), ecc.cbegin(), ecc.cend());
		blocks.push_back(std::move(dat));
	}
	
	// Interleave (not concatenate) the bytes from every block into a single sequence
	vector<uint8_t> result;
	for (size_t i = 0; i < blocks.at(0).size(); i++) {
		for (size_t j = 0; j < blocks.size(); j++) {
			// Skip the padding byte in short blocks
			if (i != static_cast<unsigned int>(shortBlockLen - blockEccLen) || j >= static_cast<unsigned int>(numShortBlocks))
				result.push_back(blocks.at(j).at(i));
		}
	}
	assert(result.size() == static_cast<unsigned int>(rawCodewords));
	return result;
}


void QrCode::drawCodewords(const vector<uint8_t> &data) {
	if (data.size() != static_cast<unsigned int>(getNumRawDataModules(version) / 8))
		throw std::invalid_argument("Invalid argument");
	
	size_t i = 0;  // Bit index into the data
	// Do the funny zigzag scan
	for (int right = size - 1; right >= 1; right -= 2) {  // Index of right column in each column pair
		if (right == 6)
			right = 5;
		for (int vert = 0; vert < size; vert++) {  // Vertical counter
			for (int j = 0; j < 2; j++) {
				size_t x = static_cast<size_t>(right - j);  // Actual x coordinate
				bool upward = ((right + 1) & 2) == 0;
				size_t y = static_cast<size_t>(upward ? size - 1 - vert : vert);  // Actual y coordinate
				if (!isFunction.at(y).at(x) && i < data.size() * 8) {
					modules.at(y).at(x) = getBit(data.at(i >> 3), 7 - static_cast<int>(i & 7));
					i++;
				}
				// If this QR Code has any remainder bits (0 to 7), they were assigned as
				// 0/false/light by the constructor and are left unchanged by this method
			}
		}
	}
	assert(i == data.size() * 8);
}


void QrCode::applyMask(int msk) {
	if (msk < 0 || msk > 7)
		throw std::domain_error("Mask value out of range");
	size_t sz = static_cast<size_t>(size);
	for (size_t y = 0; y < sz; y++) {
		for (size_t x = 0; x < sz; x++) {
			bool invert;
			switch (msk) {
				case 0:  invert = (x + y) % 2 == 0;                    break;
				case 1:  invert = y % 2 == 0;                          break;
				case 2:  invert = x % 3 == 0;                          break;
				case 3:  invert = (x + y) % 3 == 0;                    break;
				case 4:  invert = (x / 3 + y / 2) % 2 == 0;            break;
				case 5:  invert = x * y % 2 + x * y % 3 == 0;          break;
				case 6:  invert = (x * y % 2 + x * y % 3) % 2 == 0;    break;
				case 7:  invert = ((x + y) % 2 + x * y % 3) % 2 == 0;  break;
				default:  throw std::logic_error("Unreachable");
			}
			modules.at(y).at(x) = modules.at(y).at(x) ^ (invert & !isFunction.at(y).at(x));
		}
	}
}


long QrCode::getPenaltyScore() const {
	long result = 0;
	
	// Adjacent modules in row having same color, and finder-like patterns
	for (int y = 0; y < size; y++) {
		bool runColor = false;
		int runX = 0;
		std::array<int,7> runHistory = {};
		for (int x = 0; x < size; x++) {
			if (module(x, y) == runColor) {
				runX++;
				if (runX == 5)
					result += PENALTY_N1;
				else if (runX > 5)
					result++;
			} else {
				finderPenaltyAddHistory(runX, runHistory);
				if (!runColor)
					result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
				runColor = module(x, y);
				runX = 1;
			}
		}
		result += finderPenaltyTerminateAndCount(runColor, runX, runHistory) * PENALTY_N3;
	}
	// Adjacent modules in column having same color, and finder-like patterns
	for (int x = 0; x < size; x++) {
		bool runColor = false;
		int runY = 0;
		std::array<int,7> runHistory = {};
		for (int y = 0; y < size; y++) {
			if (module(x, y) == runColor) {
				runY++;
				if (runY == 5)
					result += PENALTY_N1;
				else if (runY > 5)
					result++;
			} else {
				finderPenaltyAddHistory(runY, runHistory);
				if (!runColor)
					result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
				runColor = module(x, y);
				runY = 1;
			}
		}
		result += finderPenaltyTerminateAndCount(runColor, runY, runHistory) * PENALTY_N3;
	}
	
	// 2*2 blocks of modules having same color
	for (int y = 0; y < size - 1; y++) {
		for (int x = 0; x < size - 1; x++) {
			bool  color = module(x, y);
			if (  color == module(x + 1, y) &&
			      color == module(x, y + 1) &&
			      color == module(x + 1, y + 1))
				result += PENALTY_N2;
		}
	}
	
	// Balance of dark and light modules
	int dark = 0;
	for (const vector<bool> &row : modules) {
		for (bool color : row) {
			if (color)
				dark++;
		}
	}
	int total = size * size;  // Note that size is odd, so dark/total != 1/2
	// Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)%
	int k = static_cast<int>((std::abs(dark * 20L - total * 10L) + total - 1) / total) - 1;
	assert(0 <= k && k <= 9);
	result += k * PENALTY_N4;
	assert(0 <= result && result <= 2568888L);  // Non-tight upper bound based on default values of PENALTY_N1, ..., N4
	return result;
}


vector<int> QrCode::getAlignmentPatternPositions() const {
	if (version == 1)
		return vector<int>();
	else {
		int numAlign = version / 7 + 2;
		int step = (version == 32) ? 26 :
			(version * 4 + numAlign * 2 + 1) / (numAlign * 2 - 2) * 2;
		vector<int> result;
		for (int i = 0, pos = size - 7; i < numAlign - 1; i++, pos -= step)
			result.insert(result.begin(), pos);
		result.insert(result.begin(), 6);
		return result;
	}
}


int QrCode::getNumRawDataModules(int ver) {
	if (ver < MIN_VERSION || ver > MAX_VERSION)
		throw std::domain_error("Version number out of range");
	int result = (16 * ver + 128) * ver + 64;
	if (ver >= 2) {
		int numAlign = ver / 7 + 2;
		result -= (25 * numAlign - 10) * numAlign - 55;
		if (ver >= 7)
			result -= 36;
	}
	assert(208 <= result && result <= 29648);
	return result;
}


int QrCode::getNumDataCodewords(int ver, Ecc ecl) {
	return getNumRawDataModules(ver) / 8
		- ECC_CODEWORDS_PER_BLOCK    [static_cast<int>(ecl)][ver]
		* NUM_ERROR_CORRECTION_BLOCKS[static_cast<int>(ecl)][ver];
}


vector<uint8_t> QrCode::reedSolomonComputeDivisor(int degree) {
	if (degree < 1 || degree > 255)
		throw std::domain_error("Degree out of range");
	// Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
	// For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}.
	vector<uint8_t> result(static_cast<size_t>(degree));
	result.at(result.size() - 1) = 1;  // Start off with the monomial x^0
	
	// Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
	// and drop the highest monomial term which is always 1x^degree.
	// Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).
	uint8_t root = 1;
	for (int i = 0; i < degree; i++) {
		// Multiply the current product by (x - r^i)
		for (size_t j = 0; j < result.size(); j++) {
			result.at(j) = reedSolomonMultiply(result.at(j), root);
			if (j + 1 < result.size())
				result.at(j) ^= result.at(j + 1);
		}
		root = reedSolomonMultiply(root, 0x02);
	}
	return result;
}


vector<uint8_t> QrCode::reedSolomonComputeRemainder(const vector<uint8_t> &data, const vector<uint8_t> &divisor) {
	vector<uint8_t> result(divisor.size());
	for (uint8_t b : data) {  // Polynomial division
		uint8_t factor = b ^ result.at(0);
		result.erase(result.begin());
		result.push_back(0);
		for (size_t i = 0; i < result.size(); i++)
			result.at(i) ^= reedSolomonMultiply(divisor.at(i), factor);
	}
	return result;
}


uint8_t QrCode::reedSolomonMultiply(uint8_t x, uint8_t y) {
	// Russian peasant multiplication
	int z = 0;
	for (int i = 7; i >= 0; i--) {
		z = (z << 1) ^ ((z >> 7) * 0x11D);
		z ^= ((y >> i) & 1) * x;
	}
	assert(z >> 8 == 0);
	return static_cast<uint8_t>(z);
}


int QrCode::finderPenaltyCountPatterns(const std::array<int,7> &runHistory) const {
	int n = runHistory.at(1);
	assert(n <= size * 3);
	bool core = n > 0 && runHistory.at(2) == n && runHistory.at(3) == n * 3 && runHistory.at(4) == n && runHistory.at(5) == n;
	return (core && runHistory.at(0) >= n * 4 && runHistory.at(6) >= n ? 1 : 0)
	     + (core && runHistory.at(6) >= n * 4 && runHistory.at(0) >= n ? 1 : 0);
}


int QrCode::finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, std::array<int,7> &runHistory) const {
	if (currentRunColor) {  // Terminate dark run
		finderPenaltyAddHistory(currentRunLength, runHistory);
		currentRunLength = 0;
	}
	currentRunLength += size;  // Add light border to final run
	finderPenaltyAddHistory(currentRunLength, runHistory);
	return finderPenaltyCountPatterns(runHistory);
}


void QrCode::finderPenaltyAddHistory(int currentRunLength, std::array<int,7> &runHistory) const {
	if (runHistory.at(0) == 0)
		currentRunLength += size;  // Add light border to initial run
	std::copy_backward(runHistory.cbegin(), runHistory.cend() - 1, runHistory.end());
	runHistory.at(0) = currentRunLength;
}


bool QrCode::getBit(long x, int i) {
	return ((x >> i) & 1) != 0;
}


/*---- Tables of constants ----*/

const int QrCode::PENALTY_N1 =  3;
const int QrCode::PENALTY_N2 =  3;
const int QrCode::PENALTY_N3 = 40;
const int QrCode::PENALTY_N4 = 10;


const int8_t QrCode::ECC_CODEWORDS_PER_BLOCK[4][41] = {
	// Version: (note that index 0 is for padding, and is set to an illegal value)
	//0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40    Error correction level
	{-1,  7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30},  // Low
	{-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28},  // Medium
	{-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30},  // Quartile
	{-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30},  // High
};

const int8_t QrCode::NUM_ERROR_CORRECTION_BLOCKS[4][41] = {
	// Version: (note that index 0 is for padding, and is set to an illegal value)
	//0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40    Error correction level
	{-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4,  4,  4,  4,  4,  6,  6,  6,  6,  7,  8,  8,  9,  9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25},  // Low
	{-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5,  5,  8,  9,  9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49},  // Medium
	{-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8,  8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68},  // Quartile
	{-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81},  // High
};


data_too_long::data_too_long(const std::string &msg) :
	std::length_error(msg) {}



/*---- Class BitBuffer ----*/

BitBuffer::BitBuffer()
	: std::vector<bool>() {}


void BitBuffer::appendBits(std::uint32_t val, int len) {
	if (len < 0 || len > 31 || val >> len != 0)
		throw std::domain_error("Value out of range");
	for (int i = len - 1; i >= 0; i--)  // Append bit by bit
		this->push_back(((val >> i) & 1) != 0);
}

}


================================================
FILE: 3rdparty/qrcodegen.hpp
================================================
/* 
 * QR Code generator library (C++)
 * 
 * Copyright (c) Project Nayuki. (MIT License)
 * https://www.nayuki.io/page/qr-code-generator-library
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 * - The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 * - The Software is provided "as is", without warranty of any kind, express or
 *   implied, including but not limited to the warranties of merchantability,
 *   fitness for a particular purpose and noninfringement. In no event shall the
 *   authors or copyright holders be liable for any claim, damages or other
 *   liability, whether in an action of contract, tort or otherwise, arising from,
 *   out of or in connection with the Software or the use or other dealings in the
 *   Software.
 */

#pragma once

#include <array>
#include <cstdint>
#include <stdexcept>
#include <string>
#include <vector>


namespace qrcodegen {

/* 
 * A segment of character/binary/control data in a QR Code symbol.
 * Instances of this class are immutable.
 * The mid-level way to create a segment is to take the payload data
 * and call a static factory function such as QrSegment::makeNumeric().
 * The low-level way to create a segment is to custom-make the bit buffer
 * and call the QrSegment() constructor with appropriate values.
 * This segment class imposes no length restrictions, but QR Codes have restrictions.
 * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data.
 * Any segment longer than this is meaningless for the purpose of generating QR Codes.
 */
class QrSegment final {
	
	/*---- Public helper enumeration ----*/
	
	/* 
	 * Describes how a segment's data bits are interpreted. Immutable.
	 */
	public: class Mode final {
		
		/*-- Constants --*/
		
		public: static const Mode NUMERIC;
		public: static const Mode ALPHANUMERIC;
		public: static const Mode BYTE;
		public: static const Mode KANJI;
		public: static const Mode ECI;
		
		
		/*-- Fields --*/
		
		// The mode indicator bits, which is a uint4 value (range 0 to 15).
		private: int modeBits;
		
		// Number of character count bits for three different version ranges.
		private: int numBitsCharCount[3];
		
		
		/*-- Constructor --*/
		
		private: Mode(int mode, int cc0, int cc1, int cc2);
		
		
		/*-- Methods --*/
		
		/* 
		 * (Package-private) Returns the mode indicator bits, which is an unsigned 4-bit value (range 0 to 15).
		 */
		public: int getModeBits() const;
		
		/* 
		 * (Package-private) Returns the bit width of the character count field for a segment in
		 * this mode in a QR Code at the given version number. The result is in the range [0, 16].
		 */
		public: int numCharCountBits(int ver) const;
		
	};
	
	
	
	/*---- Static factory functions (mid level) ----*/
	
	/* 
	 * Returns a segment representing the given binary data encoded in
	 * byte mode. All input byte vectors are acceptable. Any text string
	 * can be converted to UTF-8 bytes and encoded as a byte mode segment.
	 */
	public: static QrSegment makeBytes(const std::vector<std::uint8_t> &data);
	
	
	/* 
	 * Returns a segment representing the given string of decimal digits encoded in numeric mode.
	 */
	public: static QrSegment makeNumeric(const char *digits);
	
	
	/* 
	 * Returns a segment representing the given text string encoded in alphanumeric mode.
	 * The characters allowed are: 0 to 9, A to Z (uppercase only), space,
	 * dollar, percent, asterisk, plus, hyphen, period, slash, colon.
	 */
	public: static QrSegment makeAlphanumeric(const char *text);
	
	
	/* 
	 * Returns a list of zero or more segments to represent the given text string. The result
	 * may use various segment modes and switch modes to optimize the length of the bit stream.
	 */
	public: static std::vector<QrSegment> makeSegments(const char *text);
	
	
	/* 
	 * Returns a segment representing an Extended Channel Interpretation
	 * (ECI) designator with the given assignment value.
	 */
	public: static QrSegment makeEci(long assignVal);
	
	
	/*---- Public static helper functions ----*/
	
	/* 
	 * Tests whether the given string can be encoded as a segment in numeric mode.
	 * A string is encodable iff each character is in the range 0 to 9.
	 */
	public: static bool isNumeric(const char *text);
	
	
	/* 
	 * Tests whether the given string can be encoded as a segment in alphanumeric mode.
	 * A string is encodable iff each character is in the following set: 0 to 9, A to Z
	 * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.
	 */
	public: static bool isAlphanumeric(const char *text);
	
	
	
	/*---- Instance fields ----*/
	
	/* The mode indicator of this segment. Accessed through getMode(). */
	private: const Mode *mode;
	
	/* The length of this segment's unencoded data. Measured in characters for
	 * numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.
	 * Always zero or positive. Not the same as the data's bit length.
	 * Accessed through getNumChars(). */
	private: int numChars;
	
	/* The data bits of this segment. Accessed through getData(). */
	private: std::vector<bool> data;
	
	
	/*---- Constructors (low level) ----*/
	
	/* 
	 * Creates a new QR Code segment with the given attributes and data.
	 * The character count (numCh) must agree with the mode and the bit buffer length,
	 * but the constraint isn't checked. The given bit buffer is copied and stored.
	 */
	public: QrSegment(const Mode &md, int numCh, const std::vector<bool> &dt);
	
	
	/* 
	 * Creates a new QR Code segment with the given parameters and data.
	 * The character count (numCh) must agree with the mode and the bit buffer length,
	 * but the constraint isn't checked. The given bit buffer is moved and stored.
	 */
	public: QrSegment(const Mode &md, int numCh, std::vector<bool> &&dt);
	
	
	/*---- Methods ----*/
	
	/* 
	 * Returns the mode field of this segment.
	 */
	public: const Mode &getMode() const;
	
	
	/* 
	 * Returns the character count field of this segment.
	 */
	public: int getNumChars() const;
	
	
	/* 
	 * Returns the data bits of this segment.
	 */
	public: const std::vector<bool> &getData() const;
	
	
	// (Package-private) Calculates the number of bits needed to encode the given segments at
	// the given version. Returns a non-negative number if successful. Otherwise returns -1 if a
	// segment has too many characters to fit its length field, or the total bits exceeds INT_MAX.
	public: static int getTotalBits(const std::vector<QrSegment> &segs, int version);
	
	
	/*---- Private constant ----*/
	
	/* The set of all legal characters in alphanumeric mode, where
	 * each character value maps to the index in the string. */
	private: static const char *ALPHANUMERIC_CHARSET;
	
};



/* 
 * A QR Code symbol, which is a type of two-dimension barcode.
 * Invented by Denso Wave and described in the ISO/IEC 18004 standard.
 * Instances of this class represent an immutable square grid of dark and light cells.
 * The class provides static factory functions to create a QR Code from text or binary data.
 * The class covers the QR Code Model 2 specification, supporting all versions (sizes)
 * from 1 to 40, all 4 error correction levels, and 4 character encoding modes.
 * 
 * Ways to create a QR Code object:
 * - High level: Take the payload data and call QrCode::encodeText() or QrCode::encodeBinary().
 * - Mid level: Custom-make the list of segments and call QrCode::encodeSegments().
 * - Low level: Custom-make the array of data codeword bytes (including
 *   segment headers and final padding, excluding error correction codewords),
 *   supply the appropriate version number, and call the QrCode() constructor.
 * (Note that all ways require supplying the desired error correction level.)
 */
class QrCode final {
	
	/*---- Public helper enumeration ----*/
	
	/* 
	 * The error correction level in a QR Code symbol.
	 */
	public: enum class Ecc {
		LOW = 0 ,  // The QR Code can tolerate about  7% erroneous codewords
		MEDIUM  ,  // The QR Code can tolerate about 15% erroneous codewords
		QUARTILE,  // The QR Code can tolerate about 25% erroneous codewords
		HIGH    ,  // The QR Code can tolerate about 30% erroneous codewords
	};
	
	
	// Returns a value in the range 0 to 3 (unsigned 2-bit integer).
	private: static int getFormatBits(Ecc ecl);
	
	
	
	/*---- Static factory functions (high level) ----*/
	
	/* 
	 * Returns a QR Code representing the given Unicode text string at the given error correction level.
	 * As a conservative upper bound, this function is guaranteed to succeed for strings that have 2953 or fewer
	 * UTF-8 code units (not Unicode code points) if the low error correction level is used. The smallest possible
	 * QR Code version is automatically chosen for the output. The ECC level of the result may be higher than
	 * the ecl argument if it can be done without increasing the version.
	 */
	public: static QrCode encodeText(const char *text, Ecc ecl);
	
	
	/* 
	 * Returns a QR Code representing the given binary data at the given error correction level.
	 * This function always encodes using the binary segment mode, not any text mode. The maximum number of
	 * bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
	 * The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
	 */
	public: static QrCode encodeBinary(const std::vector<std::uint8_t> &data, Ecc ecl);
	
	
	/*---- Static factory functions (mid level) ----*/
	
	/* 
	 * Returns a QR Code representing the given segments with the given encoding parameters.
	 * The smallest possible QR Code version within the given range is automatically
	 * chosen for the output. Iff boostEcl is true, then the ECC level of the result
	 * may be higher than the ecl argument if it can be done without increasing the
	 * version. The mask number is either between 0 to 7 (inclusive) to force that
	 * mask, or -1 to automatically choose an appropriate mask (which may be slow).
	 * This function allows the user to create a custom sequence of segments that switches
	 * between modes (such as alphanumeric and byte) to encode text in less space.
	 * This is a mid-level API; the high-level API is encodeText() and encodeBinary().
	 */
	public: static QrCode encodeSegments(const std::vector<QrSegment> &segs, Ecc ecl,
		int minVersion=1, int maxVersion=40, int mask=-1, bool boostEcl=true);  // All optional parameters
	
	
	
	/*---- Instance fields ----*/
	
	// Immutable scalar parameters:
	
	/* The version number of this QR Code, which is between 1 and 40 (inclusive).
	 * This determines the size of this barcode. */
	private: int version;
	
	/* The width and height of this QR Code, measured in modules, between
	 * 21 and 177 (inclusive). This is equal to version * 4 + 17. */
	private: int size;
	
	/* The error correction level used in this QR Code. */
	private: Ecc errorCorrectionLevel;
	
	/* The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive).
	 * Even if a QR Code is created with automatic masking requested (mask = -1),
	 * the resulting object still has a mask value between 0 and 7. */
	private: int mask;
	
	// Private grids of modules/pixels, with dimensions of size*size:
	
	// The modules of this QR Code (false = light, true = dark).
	// Immutable after constructor finishes. Accessed through getModule().
	private: std::vector<std::vector<bool> > modules;
	
	// Indicates function modules that are not subjected to masking. Discarded when constructor finishes.
	private: std::vector<std::vector<bool> > isFunction;
	
	
	
	/*---- Constructor (low level) ----*/
	
	/* 
	 * Creates a new QR Code with the given version number,
	 * error correction level, data codeword bytes, and mask number.
	 * This is a low-level API that most users should not use directly.
	 * A mid-level API is the encodeSegments() function.
	 */
	public: QrCode(int ver, Ecc ecl, const std::vector<std::uint8_t> &dataCodewords, int msk);
	
	
	
	/*---- Public instance methods ----*/
	
	/* 
	 * Returns this QR Code's version, in the range [1, 40].
	 */
	public: int getVersion() const;
	
	
	/* 
	 * Returns this QR Code's size, in the range [21, 177].
	 */
	public: int getSize() const;
	
	
	/* 
	 * Returns this QR Code's error correction level.
	 */
	public: Ecc getErrorCorrectionLevel() const;
	
	
	/* 
	 * Returns this QR Code's mask, in the range [0, 7].
	 */
	public: int getMask() const;
	
	
	/* 
	 * Returns the color of the module (pixel) at the given coordinates, which is false
	 * for light or true for dark. The top left corner has the coordinates (x=0, y=0).
	 * If the given coordinates are out of bounds, then false (light) is returned.
	 */
	public: bool getModule(int x, int y) const;
	
	
	
	/*---- Private helper methods for constructor: Drawing function modules ----*/
	
	// Reads this object's version field, and draws and marks all function modules.
	private: void drawFunctionPatterns();
	
	
	// Draws two copies of the format bits (with its own error correction code)
	// based on the given mask and this object's error correction level field.
	private: void drawFormatBits(int msk);
	
	
	// Draws two copies of the version bits (with its own error correction code),
	// based on this object's version field, iff 7 <= version <= 40.
	private: void drawVersion();
	
	
	// Draws a 9*9 finder pattern including the border separator,
	// with the center module at (x, y). Modules can be out of bounds.
	private: void drawFinderPattern(int x, int y);
	
	
	// Draws a 5*5 alignment pattern, with the center module
	// at (x, y). All modules must be in bounds.
	private: void drawAlignmentPattern(int x, int y);
	
	
	// Sets the color of a module and marks it as a function module.
	// Only used by the constructor. Coordinates must be in bounds.
	private: void setFunctionModule(int x, int y, bool isDark);
	
	
	// Returns the color of the module at the given coordinates, which must be in range.
	private: bool module(int x, int y) const;
	
	
	/*---- Private helper methods for constructor: Codewords and masking ----*/
	
	// Returns a new byte string representing the given data with the appropriate error correction
	// codewords appended to it, based on this object's version and error correction level.
	private: std::vector<std::uint8_t> addEccAndInterleave(const std::vector<std::uint8_t> &data) const;
	
	
	// Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
	// data area of this QR Code. Function modules need to be marked off before this is called.
	private: void drawCodewords(const std::vector<std::uint8_t> &data);
	
	
	// XORs the codeword modules in this QR Code with the given mask pattern.
	// The function modules must be marked and the codeword bits must be drawn
	// before masking. Due to the arithmetic of XOR, calling applyMask() with
	// the same mask value a second time will undo the mask. A final well-formed
	// QR Code needs exactly one (not zero, two, etc.) mask applied.
	private: void applyMask(int msk);
	
	
	// Calculates and returns the penalty score based on state of this QR Code's current modules.
	// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
	private: long getPenaltyScore() const;
	
	
	
	/*---- Private helper functions ----*/
	
	// Returns an ascending list of positions of alignment patterns for this version number.
	// Each position is in the range [0,177), and are used on both the x and y axes.
	// This could be implemented as lookup table of 40 variable-length lists of unsigned bytes.
	private: std::vector<int> getAlignmentPatternPositions() const;
	
	
	// Returns the number of data bits that can be stored in a QR Code of the given version number, after
	// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
	// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.
	private: static int getNumRawDataModules(int ver);
	
	
	// Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
	// QR Code of the given version number and error correction level, with remainder bits discarded.
	// This stateless pure function could be implemented as a (40*4)-cell lookup table.
	private: static int getNumDataCodewords(int ver, Ecc ecl);
	
	
	// Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be
	// implemented as a lookup table over all possible parameter values, instead of as an algorithm.
	private: static std::vector<std::uint8_t> reedSolomonComputeDivisor(int degree);
	
	
	// Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials.
	private: static std::vector<std::uint8_t> reedSolomonComputeRemainder(const std::vector<std::uint8_t> &data, const std::vector<std::uint8_t> &divisor);
	
	
	// Returns the product of the two given field elements modulo GF(2^8/0x11D).
	// All inputs are valid. This could be implemented as a 256*256 lookup table.
	private: static std::uint8_t reedSolomonMultiply(std::uint8_t x, std::uint8_t y);
	
	
	// Can only be called immediately after a light run is added, and
	// returns either 0, 1, or 2. A helper function for getPenaltyScore().
	private: int finderPenaltyCountPatterns(const std::array<int,7> &runHistory) const;
	
	
	// Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().
	private: int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, std::array<int,7> &runHistory) const;
	
	
	// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
	private: void finderPenaltyAddHistory(int currentRunLength, std::array<int,7> &runHistory) const;
	
	
	// Returns true iff the i'th bit of x is set to 1.
	private: static bool getBit(long x, int i);
	
	
	/*---- Constants and tables ----*/
	
	// The minimum version number supported in the QR Code Model 2 standard.
	public: static constexpr int MIN_VERSION =  1;
	
	// The maximum version number supported in the QR Code Model 2 standard.
	public: static constexpr int MAX_VERSION = 40;
	
	
	// For use in getPenaltyScore(), when evaluating which mask is best.
	private: static const int PENALTY_N1;
	private: static const int PENALTY_N2;
	private: static const int PENALTY_N3;
	private: static const int PENALTY_N4;
	
	
	private: static const std::int8_t ECC_CODEWORDS_PER_BLOCK[4][41];
	private: static const std::int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41];
	
};



/*---- Public exception class ----*/

/* 
 * Thrown when the supplied data does not fit any QR Code version. Ways to handle this exception include:
 * - Decrease the error correction level if it was greater than Ecc::LOW.
 * - If the encodeSegments() function was called with a maxVersion argument, then increase
 *   it if it was less than QrCode::MAX_VERSION. (This advice does not apply to the other
 *   factory functions because they search all versions up to QrCode::MAX_VERSION.)
 * - Split the text data into better or optimal segments in order to reduce the number of bits required.
 * - Change the text or binary data to be shorter.
 * - Change the text to fit the character set of a particular segment mode (e.g. alphanumeric).
 * - Propagate the error upward to the caller/user.
 */
class data_too_long : public std::length_error {
	
	public: explicit data_too_long(const std::string &msg);
	
};



/* 
 * An appendable sequence of bits (0s and 1s). Mainly used by QrSegment.
 */
class BitBuffer final : public std::vector<bool> {
	
	/*---- Constructor ----*/
	
	// Creates an empty bit buffer (length 0).
	public: BitBuffer();
	
	
	
	/*---- Method ----*/
	
	// Appends the given number of low-order bits of the given value
	// to this buffer. Requires 0 <= len <= 31 and val < 2^len.
	public: void appendBits(std::uint32_t val, int len);
	
};

}


================================================
FILE: 3rdparty/qscopeguard.h
================================================
/****************************************************************************
**
** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#ifndef QSCOPEGUARD_H
#define QSCOPEGUARD_H

#include <QtCore/qglobal.h>


QT_BEGIN_NAMESPACE


template <typename F> class QScopeGuard;
template <typename F> QScopeGuard<F> qScopeGuard(F f);

template <typename F>
class QScopeGuard
{
public:
    QScopeGuard(QScopeGuard &&other) Q_DECL_NOEXCEPT
        : m_func(std::move(other.m_func))
        , m_invoke(other.m_invoke)
    {
        other.dismiss();
    }

    ~QScopeGuard()
    {
        if (m_invoke)
            m_func();
    }

    void dismiss() Q_DECL_NOEXCEPT
    {
        m_invoke = false;
    }

private:
    explicit QScopeGuard(F f) Q_DECL_NOEXCEPT
        : m_func(std::move(f))
    {
    }

    Q_DISABLE_COPY(QScopeGuard)

    F m_func;
    bool m_invoke = true;
    friend QScopeGuard qScopeGuard<F>(F);
};


template <typename F>
QScopeGuard<F> qScopeGuard(F f)
{
    return QScopeGuard<F>(std::move(f));
}

QT_END_NAMESPACE

#endif // QSCOPEGUARD_H


================================================
FILE: 3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp
================================================
#include "QvProxyConfigurator.hpp"

#ifdef Q_OS_WIN
//
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
//
#include <wininet.h>
#include <ras.h>
#include <raserror.h>
#include <vector>
#endif

#include <QStandardPaths>
#include <QProcess>

#include "3rdparty/fix_old_qt.h"
#include "3rdparty/qv2ray/wrapper.hpp"
#include "fmt/Preset.hpp"
#include "main/NekoGui.hpp"

#define QV_MODULE_NAME "SystemProxy"

#define QSTRN(num) QString::number(num)

namespace Qv2ray::components::proxy {

    using ProcessArgument = QPair<QString, QStringList>;
#ifdef Q_OS_MACOS
    QStringList macOSgetNetworkServices() {
        QProcess p;
        p.setProgram("/usr/sbin/networksetup");
        p.setArguments(QStringList{"-listallnetworkservices"});
        p.start();
        p.waitForStarted();
        p.waitForFinished();
        LOG(p.errorString());
        auto str = p.readAllStandardOutput();
        auto lines = SplitLines(str);
        QStringList result;

        // Start from 1 since first line is unneeded.
        for (auto i = 1; i < lines.count(); i++) {
            // * means disabled.
            if (!lines[i].contains("*")) {
                result << lines[i];
            }
        }

        LOG("Found " + QSTRN(result.size()) + " network services: " + result.join(";"));
        return result;
    }
#endif
#ifdef Q_OS_WIN
#define NO_CONST(expr) const_cast<wchar_t *>(expr)
    // static auto DEFAULT_CONNECTION_NAME =
    // NO_CONST(L"DefaultConnectionSettings");
    ///
    /// INTERNAL FUNCTION
    bool __QueryProxyOptions() {
        INTERNET_PER_CONN_OPTION_LIST List;
        INTERNET_PER_CONN_OPTION Option[5];
        //
        unsigned long nSize = sizeof(INTERNET_PER_CONN_OPTION_LIST);
        Option[0].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL;
        Option[1].dwOption = INTERNET_PER_CONN_AUTODISCOVERY_FLAGS;
        Option[2].dwOption = INTERNET_PER_CONN_FLAGS;
        Option[3].dwOption = INTERNET_PER_CONN_PROXY_BYPASS;
        Option[4].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
        //
        List.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LIST);
        List.pszConnection = nullptr; // NO_CONST(DEFAULT_CONNECTION_NAME);
        List.dwOptionCount = 5;
        List.dwOptionError = 0;
        List.pOptions = Option;

        if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) {
            LOG("InternetQueryOption failed, GLE=" + QSTRN(GetLastError()));
        }

        LOG("System default proxy info:");

        if (Option[0].Value.pszValue != nullptr) {
            LOG(QString::fromWCharArray(Option[0].Value.pszValue));
        }

        if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL) == PROXY_TYPE_AUTO_PROXY_URL) {
            LOG("PROXY_TYPE_AUTO_PROXY_URL");
        }

        if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_DETECT) == PROXY_TYPE_AUTO_DETECT) {
            LOG("PROXY_TYPE_AUTO_DETECT");
        }

        if ((Option[2].Value.dwValue & PROXY_TYPE_DIRECT) == PROXY_TYPE_DIRECT) {
            LOG("PROXY_TYPE_DIRECT");
        }

        if ((Option[2].Value.dwValue & PROXY_TYPE_PROXY) == PROXY_TYPE_PROXY) {
            LOG("PROXY_TYPE_PROXY");
        }

        if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) {
            LOG("InternetQueryOption failed,GLE=" + QSTRN(GetLastError()));
        }

        if (Option[4].Value.pszValue != nullptr) {
            LOG(QString::fromStdWString(Option[4].Value.pszValue));
        }

        INTERNET_VERSION_INFO Version;
        nSize = sizeof(INTERNET_VERSION_INFO);
        InternetQueryOption(nullptr, INTERNET_OPTION_VERSION, &Version, &nSize);

        if (Option[0].Value.pszValue != nullptr) {
            GlobalFree(Option[0].Value.pszValue);
        }

        if (Option[3].Value.pszValue != nullptr) {
            GlobalFree(Option[3].Value.pszValue);
        }

        if (Option[4].Value.pszValue != nullptr) {
            GlobalFree(Option[4].Value.pszValue);
        }

        return false;
    }
    bool __SetProxyOptions(LPWSTR proxy_full_addr, bool isPAC) {
        INTERNET_PER_CONN_OPTION_LIST list;
        DWORD dwBufSize = sizeof(list);
        // Fill the list structure.
        list.dwSize = sizeof(list);
        // NULL == LAN, otherwise connectoid name.
        list.pszConnection = nullptr;

        if (nullptr == proxy_full_addr) {
            LOG("Clearing system proxy");
            //
            list.dwOptionCount = 1;
            list.pOptions = new INTERNET_PER_CONN_OPTION[1];

            // Ensure that the memory was allocated.
            if (nullptr == list.pOptions) {
                // Return if the memory wasn't allocated.
                return false;
            }

            // Set flags.
            list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS;
            list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT;
        } else if (isPAC) {
            LOG("Setting system proxy for PAC");
            //
            list.dwOptionCount = 2;
            list.pOptions = new INTERNET_PER_CONN_OPTION[2];

            if (nullptr == list.pOptions) {
                return false;
            }

            // Set flags.
            list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS;
            list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_AUTO_PROXY_URL;
            // Set proxy name.
            list.pOptions[1].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL;
            list.pOptions[1].Value.pszValue = proxy_full_addr;
        } else {
            LOG("Setting system proxy for Global Proxy");
            //
            list.dwOptionCount = 2;
            list.pOptions = new INTERNET_PER_CONN_OPTION[2];

            if (nullptr == list.pOptions) {
                return false;
            }

            // Set flags.
            list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS;
            list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_PROXY;
            // Set proxy name.
            list.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
            list.pOptions[1].Value.pszValue = proxy_full_addr;
            // Set proxy override.
            // list.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS;
            // auto localhost = L"localhost";
            // list.pOptions[2].Value.pszValue = NO_CONST(localhost);
        }

        // Set proxy for LAN.
        if (!InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize)) {
            LOG("InternetSetOption failed for LAN, GLE=" + QSTRN(GetLastError()));
        }

        RASENTRYNAME entry;
        entry.dwSize = sizeof(entry);
        std::vector<RASENTRYNAME> entries;
        DWORD size = sizeof(entry), count;
        LPRASENTRYNAME entryAddr = &entry;
        auto ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count);
        if (ERROR_BUFFER_TOO_SMALL == ret) {
            entries.resize(count);
            entries[0].dwSize = sizeof(RASENTRYNAME);
            entryAddr = entries.data();
            ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count);
        }
        if (ERROR_SUCCESS != ret) {
            LOG("Failed to list entry names");
            return false;
        }

        // Set proxy for each connectoid.
        for (DWORD i = 0; i < count; ++i) {
            list.pszConnection = entryAddr[i].szEntryName;
            if (!InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize)) {
                LOG("InternetSetOption failed for connectoid " + QString::fromWCharArray(list.pszConnection) + ", GLE=" + QSTRN(GetLastError()));
            }
        }

        delete[] list.pOptions;
        InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0);
        InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0);
        return true;
    }
#endif

    void SetSystemProxy(int httpPort, int socksPort) {
        const QString &address = "127.0.0.1";
        bool hasHTTP = (httpPort > 0 && httpPort < 65536);
        bool hasSOCKS = (socksPort > 0 && socksPort < 65536);

#ifdef Q_OS_WIN
        if (!hasHTTP) {
            LOG("Nothing?");
            return;
        } else {
            LOG("Qv2ray will set system proxy to use HTTP");
        }
#else
        if (!hasHTTP && !hasSOCKS) {
            LOG("Nothing?");
            return;
        }

        if (hasHTTP) {
            LOG("Qv2ray will set system proxy to use HTTP");
        }

        if (hasSOCKS) {
            LOG("Qv2ray will set system proxy to use SOCKS");
        }
#endif

#ifdef Q_OS_WIN
        QString str = NekoGui::dataStore->system_proxy_format;
        if (str.isEmpty()) str = Preset::Windows::system_proxy_format[0];
        str = str.replace("{ip}", address)
                  .replace("{http_port}", Int2String(httpPort))
                  .replace("{socks_port}", Int2String(socksPort));
        //
        LOG("Windows proxy string: " + str);
        auto proxyStrW = new WCHAR[str.length() + 1];
        wcscpy(proxyStrW, str.toStdWString().c_str());
        //
        __QueryProxyOptions();

        if (!__SetProxyOptions(proxyStrW, false)) {
            LOG("Failed to set proxy.");
        }

        __QueryProxyOptions();
#elif defined(Q_OS_LINUX)
        QList<ProcessArgument> actions;
        actions << ProcessArgument{"gsettings", {"set", "org.gnome.system.proxy", "mode", "manual"}};
        //
        bool isKDE = qEnvironmentVariable("XDG_SESSION_DESKTOP") == "KDE" ||
                     qEnvironmentVariable("XDG_SESSION_DESKTOP") == "plasma";
        const auto configPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);

        //
        // Configure HTTP Proxies for HTTP, FTP and HTTPS
        if (hasHTTP) {
            // iterate over protocols...
            for (const auto &protocol: QStringList{"http", "ftp", "https"}) {
                // for GNOME:
                {
                    actions << ProcessArgument{"gsettings",
                                               {"set", "org.gnome.system.proxy." + protocol, "host", address}};
                    actions << ProcessArgument{"gsettings",
                                               {"set", "org.gnome.system.proxy." + protocol, "port", QSTRN(httpPort)}};
                }

                // for KDE:
                if (isKDE) {
                    actions << ProcessArgument{"kwriteconfig5",
                                               {"--file", configPath + "/kioslaverc", //
                                                "--group", "Proxy Settings",          //
                                                "--key", protocol + "Proxy",          //
                                                "http://" + address + " " + QSTRN(httpPort)}};
                }
            }
        }

        // Configure SOCKS5 Proxies
        if (hasSOCKS) {
            // for GNOME:
            {
                actions << ProcessArgument{"gsettings", {"set", "org.gnome.system.proxy.socks", "host", address}};
                actions << ProcessArgument{"gsettings",
                                           {"set", "org.gnome.system.proxy.socks", "port", QSTRN(socksPort)}};

                // for KDE:
                if (isKDE) {
                    actions << ProcessArgument{"kwriteconfig5",
                                               {"--file", configPath + "/kioslaverc", //
                                                "--group", "Proxy Settings",          //
                                                "--key", "socksProxy",                //
                                                "socks://" + address + " " + QSTRN(socksPort)}};
                }
            }
        }
        // Setting Proxy Mode to Manual
        {
            // for GNOME:
            {
                actions << ProcessArgument{"gsettings", {"set", "org.gnome.system.proxy", "mode", "manual"}};
            }

            // for KDE:
            if (isKDE) {
                actions << ProcessArgument{"kwriteconfig5",
                                           {"--file", configPath + "/kioslaverc", //
                                            "--group", "Proxy Settings",          //
                                            "--key", "ProxyType", "1"}};
            }
        }

        // Notify kioslaves to reload system proxy configuration.
        if (isKDE) {
            actions << ProcessArgument{"dbus-send",
                                       {"--type=signal", "/KIO/Scheduler",                 //
                                        "org.kde.KIO.Scheduler.reparseSlaveConfiguration", //
                                        "string:''"}};
        }
        // Execute them all!
        //
        // note: do not use std::all_of / any_of / none_of,
        // because those are short-circuit and cannot guarantee atomicity.
        QList<bool> results;
        for (const auto &action: actions) {
            // execute and get the code
            const auto returnCode = QProcess::execute(action.first, action.second);
            // print out the commands and result codes
            DEBUG(QStringLiteral("[%1] Program: %2, Args: %3").arg(returnCode).arg(action.first).arg(action.second.join(";")));
            // give the code back
            results << (returnCode == QProcess::NormalExit);
        }

        if (results.count(true) != actions.size()) {
            LOG("Something wrong when setting proxies.");
        }
#else

        for (const auto &service: macOSgetNetworkServices()) {
            LOG("Setting proxy for interface: " + service);
            if (hasHTTP) {
                QProcess::execute("/usr/sbin/networksetup", {"-setwebproxystate", service, "on"});
                QProcess::execute("/usr/sbin/networksetup", {"-setsecurewebproxystate", service, "on"});
                QProcess::execute("/usr/sbin/networksetup", {"-setwebproxy", service, address, QSTRN(httpPort)});
                QProcess::execute("/usr/sbin/networksetup", {"-setsecurewebproxy", service, address, QSTRN(httpPort)});
            }

            if (hasSOCKS) {
                QProcess::execute("/usr/sbin/networksetup", {"-setsocksfirewallproxystate", service, "on"});
                QProcess::execute("/usr/sbin/networksetup", {"-setsocksfirewallproxy", service, address, QSTRN(socksPort)});
            }
        }

#endif
    }

    void ClearSystemProxy() {
        LOG("Clearing System Proxy");

#ifdef Q_OS_WIN
        if (!__SetProxyOptions(nullptr, false)) {
            LOG("Failed to clear proxy.");
        }
#elif defined(Q_OS_LINUX)
        QList<ProcessArgument> actions;
        const bool isKDE = qEnvironmentVariable("XDG_SESSION_DESKTOP") == "KDE" ||
                           qEnvironmentVariable("XDG_SESSION_DESKTOP") == "plasma";
        const auto configRoot = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);

        // Setting System Proxy Mode to: None
        {
            // for GNOME:
            {
                actions << ProcessArgument{"gsettings", {"set", "org.gnome.system.proxy", "mode", "none"}};
            }

            // for KDE:
            if (isKDE) {
                actions << ProcessArgument{"kwriteconfig5",
                                           {"--file", configRoot + "/kioslaverc", //
                                            "--group", "Proxy Settings",          //
                                            "--key", "ProxyType", "0"}};
            }
        }

        // Notify kioslaves to reload system proxy configuration.
        if (isKDE) {
            actions << ProcessArgument{"dbus-send",
                                       {"--type=signal", "/KIO/Scheduler",                 //
                                        "org.kde.KIO.Scheduler.reparseSlaveConfiguration", //
                                        "string:''"}};
        }

        // Execute the Actions
        for (const auto &action: actions) {
            // execute and get the code
            const auto returnCode = QProcess::execute(action.first, action.second);
            // print out the commands and result codes
            DEBUG(QStringLiteral("[%1] Program: %2, Args: %3").arg(returnCode).arg(action.first).arg(action.second.join(";")));
        }

#else
        for (const auto &service: macOSgetNetworkServices()) {
            LOG("Clearing proxy for interface: " + service);
            QProcess::execute("/usr/sbin/networksetup", {"-setautoproxystate", service, "off"});
            QProcess::execute("/usr/sbin/networksetup", {"-setwebproxystate", service, "off"});
            QProcess::execute("/usr/sbin/networksetup", {"-setsecurewebproxystate", service, "off"});
            QProcess::execute("/usr/sbin/networksetup", {"-setsocksfirewallproxystate", service, "off"});
        }

#endif
    }
} // namespace Qv2ray::components::proxy


================================================
FILE: 3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.hpp
================================================
#pragma once
#include <QHostAddress>
#include <QObject>
#include <QString>
//
namespace Qv2ray::components::proxy {
    void ClearSystemProxy();
    void SetSystemProxy(int http_port, int socks_port);
} // namespace Qv2ray::components::proxy

using namespace Qv2ray::components;
using namespace Qv2ray::components::proxy;


================================================
FILE: 3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.cpp
================================================
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "QvAutoCompleteTextEdit.hpp"

#include <QAbstractItemModel>
#include <QAbstractItemView>
#include <QApplication>
#include <QCompleter>
#include <QKeyEvent>
#include <QModelIndex>
#include <QScrollBar>
#include <QStringListModel>
#include <QToolTip>
#include <QtDebug>

namespace Qv2ray::ui::widgets {
    AutoCompleteTextEdit::AutoCompleteTextEdit(const QString &prefix, const QStringList &sourceStrings, QWidget *parent) : QPlainTextEdit(parent) {
        this->prefix = prefix;
        this->setLineWrapMode(QPlainTextEdit::NoWrap);
        c = new QCompleter(this);
        c->setModel(new QStringListModel(sourceStrings, c));
        c->setWidget(this);
        c->setCompletionMode(QCompleter::PopupCompletion);
        c->setCaseSensitivity(Qt::CaseInsensitive);
        QObject::connect(c, static_cast<void (QCompleter::*)(const QString &)>(&QCompleter::activated), this, &AutoCompleteTextEdit::insertCompletion);
    }

    AutoCompleteTextEdit::~AutoCompleteTextEdit() {
    }

    void AutoCompleteTextEdit::insertCompletion(const QString &completion) {
        QTextCursor tc = textCursor();
        int extra = completion.length() - c->completionPrefix().length();
        tc.movePosition(QTextCursor::Left);
        tc.movePosition(QTextCursor::EndOfWord);
        tc.insertText(completion.right(extra).toLower());
        setTextCursor(tc);
    }

    QString AutoCompleteTextEdit::lineUnderCursor() const {
        QTextCursor tc = textCursor();
        tc.select(QTextCursor::LineUnderCursor);
        return tc.selectedText();
    }

    QString AutoCompleteTextEdit::wordUnderCursor() const {
        QTextCursor tc = textCursor();
        tc.select(QTextCursor::WordUnderCursor);
        return tc.selectedText();
    }

    void AutoCompleteTextEdit::focusInEvent(QFocusEvent *e) {
        if (c)
            c->setWidget(this);

        QPlainTextEdit::focusInEvent(e);
    }

    void AutoCompleteTextEdit::keyPressEvent(QKeyEvent *e) {
        const bool hasCtrlOrShiftModifier = e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::ShiftModifier);
        const bool hasOtherModifiers = (e->modifiers() != Qt::NoModifier) && !hasCtrlOrShiftModifier; // has other modifiers
        //
        const bool isSpace = (e->modifiers().testFlag(Qt::ShiftModifier) || e->modifiers().testFlag(Qt::NoModifier)) //
                             && e->key() == Qt::Key_Space;
        const bool isTab = (e->modifiers().testFlag(Qt::NoModifier) && e->key() == Qt::Key_Tab);
        const bool isOtherSpace = e->text() == " ";
        //
        if (isSpace || isTab || isOtherSpace) {
            QToolTip::showText(this->mapToGlobal(QPoint(0, 0)), tr("You can not input space characters here."), this, QRect{}, 2000);
            return;
        }
        //
        if (c && c->popup()->isVisible()) {
            // The following keys are forwarded by the completer to the widget
            switch (e->key()) {
                case Qt::Key_Enter:
                case Qt::Key_Return:
                case Qt::Key_Escape:
                case Qt::Key_Tab:
                case Qt::Key_Backtab:
                    e->ignore();
                    return; // let the completer do default behavior

                default:
                    break;
            }
        }

        QPlainTextEdit::keyPressEvent(e);

        if (!c || (hasCtrlOrShiftModifier && e->text().isEmpty()))
            return;

        // if we have other modifiers, or the text is empty, or the line does not start with our prefix.
        if (hasOtherModifiers || e->text().isEmpty() || !lineUnderCursor().startsWith(prefix)) {
            c->popup()->hide();
            return;
        }

        if (auto word = wordUnderCursor(); word != c->completionPrefix()) {
            c->setCompletionPrefix(word);
            c->popup()->setCurrentIndex(c->completionModel()->index(0, 0));
        }

        QRect cr = cursorRect();
        cr.setWidth(c->popup()->sizeHintForColumn(0) + c->popup()->verticalScrollBar()->sizeHint().width());
        c->complete(cr); // popup it up!
    }
} // namespace Qv2ray::ui::widgets


================================================
FILE: 3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.hpp
================================================
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#pragma once
#include <QAbstractItemModel>
#include <QPlainTextEdit>
QT_BEGIN_NAMESPACE
class QCompleter;
QT_END_NAMESPACE

namespace Qv2ray {
    namespace ui {
        namespace widgets {
            class AutoCompleteTextEdit : public QPlainTextEdit {
                Q_OBJECT

            public:
                AutoCompleteTextEdit(const QString &prefix, const QStringList &sourceStrings, QWidget *parent = nullptr);
                ~AutoCompleteTextEdit();

            protected:
                void keyPressEvent(QKeyEvent *e) override;
                void focusInEvent(QFocusEvent *e) override;

            private slots:
                void insertCompletion(const QString &completion);

            private:
                QString lineUnderCursor() const;
                QString wordUnderCursor() const;

                QString prefix;
                QCompleter *c = nullptr;
            };
        } // namespace widgets
    }     // namespace ui
} // namespace Qv2ray
using namespace Qv2ray::ui::widgets;


================================================
FILE: 3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.cpp
================================================
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2011 SCHUTZ Sacha
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "QJsonModel.hpp"

#include <QDebug>
#include <QFile>

QJsonTreeItem::QJsonTreeItem(QJsonTreeItem *parent) {
    mParent = parent;
}

QJsonTreeItem::~QJsonTreeItem() {
    qDeleteAll(mChilds);
}

void QJsonTreeItem::appendChild(QJsonTreeItem *item) {
    mChilds.append(item);
}

QJsonTreeItem *QJsonTreeItem::child(int row) {
    return mChilds.value(row);
}

QJsonTreeItem *QJsonTreeItem::parent() {
    return mParent;
}

int QJsonTreeItem::childCount() const {
    return mChilds.count();
}

int QJsonTreeItem::row() const {
    if (mParent)
        return mParent->mChilds.indexOf(const_cast<QJsonTreeItem *>(this));

    return 0;
}

void QJsonTreeItem::setKey(const QString &key) {
    mKey = key;
}

void QJsonTreeItem::setValue(const QString &value) {
    mValue = value;
}

void QJsonTreeItem::setType(const QJsonValue::Type &type) {
    mType = type;
}

QString QJsonTreeItem::key() const {
    return mKey;
}

QString QJsonTreeItem::value() const {
    return mValue;
}

QJsonValue::Type QJsonTreeItem::type() const {
    return mType;
}

QJsonTreeItem *QJsonTreeItem::load(const QJsonValue &value, QJsonTreeItem *parent) {
    QJsonTreeItem *rootItem = new QJsonTreeItem(parent);
    rootItem->setKey("root");

    if (value.isObject()) {
        // Get all QJsonValue childs
        for (QString key: value.toObject().keys()) {
            QJsonValue v = value.toObject().value(key);
            QJsonTreeItem *child = load(v, rootItem);
            child->setKey(key);
            child->setType(v.type());
            rootItem->appendChild(child);
        }
    } else if (value.isArray()) {
        // Get all QJsonValue childs
        int index = 0;

        for (QJsonValue v: value.toArray()) {
            QJsonTreeItem *child = load(v, rootItem);
            child->setKey(QString::number(index));
            child->setType(v.type());
            rootItem->appendChild(child);
            ++index;
        }
    } else {
        rootItem->setValue(value.toVariant().toString());
        rootItem->setType(value.type());
    }

    return rootItem;
}

//=========================================================================

QJsonModel::QJsonModel(QObject *parent) : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} {
    mHeaders.append("key");
    mHeaders.append("value");
}

QJsonModel::QJsonModel(const QString &fileName, QObject *parent) : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} {
    mHeaders.append("key");
    mHeaders.append("value");
    load(fileName);
}

QJsonModel::QJsonModel(QIODevice *device, QObject *parent) : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} {
    mHeaders.append("key");
    mHeaders.append("value");
    load(device);
}

QJsonModel::QJsonModel(const QByteArray &json, QObject *parent) : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} {
    mHeaders.append("key");
    mHeaders.append("value");
    loadJson(json);
}

QJsonModel::~QJsonModel() {
    delete mRootItem;
}

bool QJsonModel::load(const QString &fileName) {
    QFile file(fileName);
    bool success = false;

    if (file.open(QIODevice::ReadOnly)) {
        success = load(&file);
        file.close();
    } else
        success = false;

    return success;
}

bool QJsonModel::load(QIODevice *device) {
    return loadJson(device->readAll());
}

bool QJsonModel::loadJson(const QByteArray &json) {
    auto const &jdoc = QJsonDocument::fromJson(json);

    if (!jdoc.isNull()) {
        beginResetModel();
        delete mRootItem;

        if (jdoc.isArray()) {
            mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.array()));
            mRootItem->setType(QJsonValue::Array);
        } else {
            mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.object()));
            mRootItem->setType(QJsonValue::Object);
        }

        endResetModel();
        return true;
    }

    qDebug() << Q_FUNC_INFO << "cannot load json";
    return false;
}

QVariant QJsonModel::data(const QModelIndex &index, int role) const {
    if (!index.isValid())
        return QVariant();

    QJsonTreeItem *item = static_cast<QJsonTreeItem *>(index.internalPointer());

    if (role == Qt::DisplayRole) {
        if (index.column() == 0)
            return QStringLiteral("%1").arg(item->key());

        if (index.column() == 1)
            return QStringLiteral("%1").arg(item->value());
    } else if (Qt::EditRole == role) {
        if (index.column() == 1) {
            return QStringLiteral("%1").arg(item->value());
        }
    }

    return QVariant();
}

bool QJsonModel::setData(const QModelIndex &index, const QVariant &value, int role) {
    int col = index.column();

    if (Qt::EditRole == role) {
        if (col == 1) {
            QJsonTreeItem *item = static_cast<QJsonTreeItem *>(index.internalPointer());
            item->setValue(value.toString());
            emit dataChanged(index, index, {Qt::EditRole});
            return true;
        }
    }

    return false;
}

QVariant QJsonModel::headerData(int section, Qt::Orientation orientation, int role) const {
    if (role != Qt::DisplayRole)
        return QVariant();

    if (orientation == Qt::Horizontal) {
        return mHeaders.value(section);
    } else
        return QVariant();
}

QModelIndex QJsonModel::index(int row, int column, const QModelIndex &parent) const {
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    QJsonTreeItem *parentItem;

    if (!parent.isValid())
        parentItem = mRootItem;
    else
        parentItem = static_cast<QJsonTreeItem *>(parent.internalPointer());

    QJsonTreeItem *childItem = parentItem->child(row);

    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

QModelIndex QJsonModel::parent(const QModelIndex &index) const {
    if (!index.isValid())
        return QModelIndex();

    QJsonTreeItem *childItem = static_cast<QJsonTreeItem *>(index.internalPointer());
    QJsonTreeItem *parentItem = childItem->parent();

    if (parentItem == mRootItem)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}

int QJsonModel::rowCount(const QModelIndex &parent) const {
    QJsonTreeItem *parentItem;

    if (parent.column() > 0)
        return 0;

    if (!parent.isValid())
        parentItem = mRootItem;
    else
        parentItem = static_cast<QJsonTreeItem *>(parent.internalPointer());

    return parentItem->childCount();
}

int QJsonModel::columnCount(const QModelIndex &parent) const {
    Q_UNUSED(parent)
    return 2;
}

Qt::ItemFlags QJsonModel::flags(const QModelIndex &index) const {
    int col = index.column();
    auto item = static_cast<QJsonTreeItem *>(index.internalPointer());
    auto isArray = QJsonValue::Array == item->type();
    auto isObject = QJsonValue::Object == item->type();

    if ((col == 1) && !(isArray || isObject)) {
        return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
    } else {
        return QAbstractItemModel::flags(index);
    }
}

QJsonDocument QJsonModel::json() const {
    auto v = genJson(mRootItem);
    QJsonDocument doc;

    if (v.isObject()) {
        doc = QJsonDocument(v.toObject());
    } else {
        doc = QJsonDocument(v.toArray());
    }

    return doc;
}

QJsonValue QJsonModel::genJson(QJsonTreeItem *item) const {
    auto type = item->type();
    int nchild = item->childCount();

    if (QJsonValue::Object == type) {
        QJsonObject jo;

        for (int i = 0; i < nchild; ++i) {
            auto ch = item->child(i);
            auto key = ch->key();
            jo.insert(key, genJson(ch));
        }

        return jo;
    } else if (QJsonValue::Array == type) {
        QJsonArray arr;

        for (int i = 0; i < nchild; ++i) {
            auto ch = item->child(i);
            arr.append(genJson(ch));
        }

        return arr;
    } else {
        QJsonValue va(item->value());
        return va;
    }
}


================================================
FILE: 3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.hpp
================================================
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2011 SCHUTZ Sacha
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#pragma once

#include <QAbstractItemModel>
#include <QByteArray>
#include <QIODevice>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
class QJsonModel;
class QJsonItem;

class QJsonTreeItem {
public:
    QJsonTreeItem(QJsonTreeItem *parent = nullptr);
    ~QJsonTreeItem();
    void appendChild(QJsonTreeItem *item);
    QJsonTreeItem *child(int row);
    QJsonTreeItem *parent();
    int childCount() const;
    int row() const;
    void setKey(const QString &key);
    void setValue(const QString &value);
    void setType(const QJsonValue::Type &type);
    QString key() const;
    QString value() const;
    QJsonValue::Type type() const;

    static QJsonTreeItem *load(const QJsonValue &value, QJsonTreeItem *parent = 0);

protected:
private:
    QString mKey;
    QString mValue;
    QJsonValue::Type mType;
    QList<QJsonTreeItem *> mChilds;
    QJsonTreeItem *mParent;
};

//---------------------------------------------------

class QJsonModel : public QAbstractItemModel {
    Q_OBJECT
public:
    explicit QJsonModel(QObject *parent = nullptr);
    QJsonModel(const QString &fileName, QObject *parent = nullptr);
    QJsonModel(QIODevice *device, QObject *parent = nullptr);
    QJsonModel(const QByteArray &json, QObject *parent = nullptr);
    ~QJsonModel();
    bool load(const QString &fileName);
    bool load(QIODevice *device);
    bool loadJson(const QByteArray &json);
    QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE;
    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
    QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE;
    int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
    int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
    Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
    QJsonDocument json() const;

private:
    QJsonValue genJson(QJsonTreeItem *) const;

    QJsonTreeItem *mRootItem;
    QStringList mHeaders;
};


================================================
FILE: 3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.cpp
================================================
#include "w_JsonEditor.hpp"

#include "main/NekoGui.hpp"

JsonEditor::JsonEditor(const QJsonObject& rootObject, QWidget* parent) : QDialog(parent) {
    setupUi(this);
    //    QvMessageBusConnect(JsonEditor);
    //
    original = rootObject;
    final = rootObject;
    QString jsonString = JsonToString(rootObject);

    if (VerifyJsonString(jsonString).isEmpty()) {
        jsonTree->setModel(&model);
        model.loadJson(QJsonDocument(rootObject).toJson());
    } else {
        QvMessageBoxWarn(this, tr("Json Contains Syntax Errors"),
                         tr("Original Json may contain syntax errors. Json tree is disabled."));
    }

    jsonEditor->setText(JsonToString(rootObject));
    jsonTree->expandAll();
    jsonTree->resizeColumnToContents(0);
}

// QvMessageBusSlotImpl(JsonEditor)
//         {
//                 switch (msg)
//                 {
//                     MBShowDefaultImpl;
//                     MBHideDefaultImpl;
//                     MBRetranslateDefaultImpl;
//                     case UPDATE_COLORSCHEME:
//                         break;
//                 }
//         }

QJsonObject JsonEditor::OpenEditor() {
    int resultCode = this->exec();
    auto string = jsonEditor->toPlainText();

    while (resultCode == QDialog::Accepted && !VerifyJsonString(string).isEmpty()) {
        if (string.isEmpty()) {
            resultCode = QDialog::Accepted;
            final = {};
            break;
        }
        QvMessageBoxWarn(this, tr("Json Contains Syntax Errors"),
                         tr("You must correct these errors before continuing."));
        resultCode = this->exec();
        string = jsonEditor->toPlainText();
    }

    return resultCode == QDialog::Accepted ? final : original;
}

JsonEditor::~JsonEditor() {
}

void JsonEditor::on_jsonEditor_textChanged() {
    auto string = jsonEditor->toPlainText();
    auto VerifyResult = VerifyJsonString(string);
    jsonValidateStatus->setText(VerifyResult);

    if (VerifyResult.isEmpty()) {
        BLACK(jsonEditor);
        final = JsonFromString(string);
        model.loadJson(QJsonDocument(final).toJson());
        jsonTree->expandAll();
        jsonTree->resizeColumnToContents(0);
    } else {
        RED(jsonEditor);
    }
}

void JsonEditor::on_formatJsonBtn_clicked() {
    auto string = jsonEditor->toPlainText();
    auto VerifyResult = VerifyJsonString(string);
    jsonValidateStatus->setText(VerifyResult);

    if (VerifyResult.isEmpty()) {
        BLACK(jsonEditor);
        jsonEditor->setPlainText(JsonToString(JsonFromString(string)));
        model.loadJson(QJsonDocument(JsonFromString(string)).toJson());
        jsonTree->setModel(&model);
        jsonTree->expandAll();
        jsonTree->resizeColumnToContents(0);
    } else {
        RED(jsonEditor);
        QvMessageBoxWarn(this, tr("Syntax Errors"),
                         tr("Please fix the JSON errors or remove the comments before continue"));
    }
}

void JsonEditor::on_removeCommentsBtn_clicked() {
    jsonEditor->setPlainText(JsonToString(JsonFromString(jsonEditor->toPlainText())));
}


================================================
FILE: 3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp
================================================
#pragma once

#include "3rdparty/qv2ray/wrapper.hpp"
#include "3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.hpp"
#include "ui_w_JsonEditor.h"

#include <QDialog>

class JsonEditor
    : public QDialog,
      private Ui::JsonEditor {
    Q_OBJECT

public:
    explicit JsonEditor(const QJsonObject& rootObject, QWidget* parent = nullptr);
    ~JsonEditor();
    QJsonObject OpenEditor();

private slots:
    void on_jsonEditor_textChanged();

    void on_formatJsonBtn_clicked();

    void on_removeCommentsBtn_clicked();

private:
    QJsonModel model;
    QJsonObject original;
    QJsonObject final;
};


================================================
FILE: 3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>JsonEditor</class>
 <widget class="QDialog" name="JsonEditor">
  <property name="windowModality">
   <enum>Qt::ApplicationModal</enum>
  </property>
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>889</width>
    <height>572</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>JSON Editor</string>
  </property>
  <property name="modal">
   <bool>true</bool>
  </property>
  <layout class="QGridLayout" name="gridLayout_3">
   <item row="0" column="0" colspan="2">
    <widget class="QSplitter" name="splitter">
     <property name="orientation">
      <enum>Qt::Horizontal</enum>
     </property>
     <property name="childrenCollapsible">
      <bool>false</bool>
     </property>
     <widget class="QWidget" name="layoutWidgetx">
      <layout class="QGridLayout" name="gridLayout">
       <item row="1" column="0" colspan="2">
        <widget class="QTextEdit" name="jsonEditor">
         <property name="font">
          <font>
           <family>Monospace</family>
          </font>
         </property>
         <property name="lineWrapMode">
          <enum>QTextEdit::NoWrap</enum>
         </property>
         <property name="acceptRichText">
          <bool>false</bool>
         </property>
        </widget>
       </item>
       <item row="2" column="0">
        <widget class="QPushButton" name="formatJsonBtn">
         <property name="text">
          <string>Format JSON</string>
         </property>
        </widget>
       </item>
       <item row="2" column="1">
        <widget class="QPushButton" name="removeCommentsBtn">
         <property name="text">
          <string>Remove All Comments</string>
         </property>
        </widget>
       </item>
       <item row="0" column="0" colspan="2">
        <widget class="QLabel" name="label">
         <property name="text">
          <string>Json Editor</string>
         </property>
        </widget>
       </item>
      </layout>
     </widget>
     <widget class="QWidget" name="layoutWidget">
      <layout class="QGridLayout" name="gridLayout_2">
       <item row="0" column="0">
        <widget class="QLabel" name="label_2">
         <property name="text">
          <string>Structure Preview</string>
         </property>
        </widget>
       </item>
       <item row="1" column="0">
        <widget class="QTreeView" name="jsonTree">
         <property name="editTriggers">
          <set>QAbstractItemView::NoEditTriggers</set>
         </property>
         <property name="alternatingRowColors">
          <bool>true</bool>
         </property>
         <property name="indentation">
          <number>15</number>
         </property>
         <property name="uniformRowHeights">
          <bool>true</bool>
         </property>
         <property name="allColumnsShowFocus">
          <bool>true</bool>
         </property>
         <attribute name="headerCascadingSectionResizes">
          <bool>true</bool>
         </attribute>
         <attribute name="headerMinimumSectionSize">
          <number>132</number>
         </attribute>
         <attribute name="headerDefaultSectionSize">
          <number>152</number>
         </attribute>
        </widget>
       </item>
      </layout>
     </widget>
    </widget>
   </item>
   <item row="1" column="0">
    <widget class="QLabel" name="jsonValidateStatus">
     <property name="text">
      <string>OK</string>
     </property>
    </widget>
   </item>
   <item row="1" column="1">
    <widget class="QDialogButtonBox" name="buttonBox">
     <property name="orientation">
      <enum>Qt::Horizontal</enum>
     </property>
     <property name="standardButtons">
      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <tabstops>
  <tabstop>jsonEditor</tabstop>
  <tabstop>formatJsonBtn</tabstop>
  <tabstop>removeCommentsBtn</tabstop>
  <tabstop>jsonTree</tabstop>
 </tabstops>
 <resources/>
 <connections>
  <connection>
   <sender>buttonBox</sender>
   <signal>accepted()</signal>
   <receiver>JsonEditor</receiver>
   <slot>accept()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>248</x>
     <y>254</y>
    </hint>
    <hint type="destinationlabel">
     <x>157</x>
     <y>274</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>buttonBox</sender>
   <signal>rejected()</signal>
   <receiver>JsonEditor</receiver>
   <slot>reject()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>316</x>
     <y>260</y>
    </hint>
    <hint type="destinationlabel">
     <x>286</x>
     <y>274</y>
    </hint>
   </hints>
  </connection>
 </connections>
</ui>


================================================
FILE: 3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.cpp
================================================
#include "GeositeReader.hpp"

#include "3rdparty/qv2ray/wrapper.hpp"
#include "picoproto.hpp"

#include <QFile>
#include <QMap>

namespace Qv2ray::components::GeositeReader {
    QMap<QString, QStringList> GeositeEntries;

    QStringList ReadGeoSiteFromFile(const QString &filepath, bool allowCache) {
        if (GeositeEntries.contains(filepath) && allowCache)
            return GeositeEntries.value(filepath);

        QStringList list;
        qInfo() << "Reading geosites from:" << filepath;
        QFile f(filepath);
        bool opened = f.open(QFile::OpenModeFlag::ReadOnly);

        if (!opened) {
            qInfo() << "File cannot be opened:" << filepath;
            return list;
        }

        const auto content = f.readAll();
        f.close();
        {
            picoproto::Message root;
            root.ParseFromBytes((unsigned char *) content.data(), content.size());

            list.reserve(root.GetMessageArray(1).size());
            for (const auto &geosite: root.GetMessageArray(1))
                list << QString::fromStdString(geosite->GetString(1));
        }

        qInfo() << "Loaded" << list.count() << "geosite entries from data file.";
        list.sort();
        GeositeEntries[filepath] = list;
        return list;
    }
} // namespace Qv2ray::components::GeositeReader


================================================
FILE: 3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.hpp
================================================
#pragma once

#include <QString>

namespace Qv2ray::components::GeositeReader {
    QStringList ReadGeoSiteFromFile(const QString &filepath, bool allowCache = true);
} // namespace Qv2ray::components::GeositeReader


================================================
FILE: 3rdparty/qv2ray/v3/components/GeositeReader/picoproto.cpp
================================================
/* Copyright 2016 Pete Warden. All Rights Reserved.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 ==============================================================================*/

#include "picoproto.hpp"

namespace picoproto {

    namespace {

        // To keep the dependencies down, here's a local copy of the widespread bit_cast
        // operator. This is necessary because in practice weird things can happen if
        // you just try to use reinterpret_cast.
        template<class Dest, class Source>
        inline Dest bit_cast(const Source &source) {
            static_assert(sizeof(Dest) == sizeof(Source), "Sizes do not match");
            Dest dest;
            memcpy(&dest, &source, sizeof(dest));
            return dest;
        }

        // These are defined in:
        // https://developers.google.com/protocol-buffers/docs/encoding
        enum WireType {
            WIRETYPE_VARINT = 0,
            WIRETYPE_64BIT = 1,
            WIRETYPE_LENGTH_DELIMITED = 2,
            WIRETYPE_GROUP_START = 3,
            WIRETYPE_GROUP_END = 4,
            WIRETYPE_32BIT = 5,
        };

        // Pull bytes from the stream, updating the state.
        bool ConsumeBytes(uint8_t **current, size_t how_many, size_t *remaining) {
            if (how_many > *remaining) {
                PP_LOG(ERROR) << "ReadBytes overrun!";
                return false;
            }
            *current += how_many;
            *remaining -= how_many;
            return true;
        }

        // Grabs a particular type from the byte stream.
        template<class T>
        T ReadFromBytes(uint8_t **current, size_t *remaining) {
            PP_CHECK(ConsumeBytes(current, sizeof(T), remaining));
            const T result = *(bit_cast<T *>(*current - sizeof(T)));
            return result;
        }

        uint64_t ReadVarInt(uint8_t **current, size_t *remaining) {
            uint64_t result = 0;
            bool keep_going;
            int shift = 0;
            do {
                const uint8_t next_number = ReadFromBytes<uint8_t>(current, remaining);
                keep_going = (next_number >= 128);
                result += (uint64_t) (next_number & 0x7f) << shift;
                shift += 7;
            } while (keep_going);
            return result;
        }

        void ReadWireTypeAndFieldNumber(uint8_t **current, size_t *remaining, uint8_t *wire_type, uint32_t *field_number) {
            uint64_t wire_type_and_field_number = ReadVarInt(current, remaining);
            *wire_type = wire_type_and_field_number & 0x07;
            *field_number = wire_type_and_field_number >> 3;
        }

    } // namespace

    std::string FieldTypeDebugString(enum FieldType type) {
        switch (type) {
            case FIELD_UNSET:
                return "UNSET";
                break;
            case FIELD_UINT32:
                return "UINT32";
                break;
            case FIELD_UINT64:
                return "UINT64";
                break;
            case FIELD_BYTES:
                return "BYTES";
                break;
            default:
                return "Unknown field type";
                break;
        }
        return "Should never get here";
    }

    Field::Field(FieldType type, bool owns_data) : type(type), owns_data(owns_data) {
        cached_messages = nullptr;
        switch (type) {
            case FIELD_UINT32: {
                value.v_uint32 = new std::vector<uint32_t>();
            } break;
            case FIELD_UINT64: {
                value.v_uint64 = new std::vector<uint64_t>();
            } break;
            case FIELD_BYTES: {
                value.v_bytes = new std::vector<std::pair<uint8_t *, size_t>>();
                cached_messages = new std::vector<Message *>();
            } break;
            default: {
                PP_LOG(ERROR) << "Bad field type when constructing field: " << type;
            } break;
        }
    }

    Field::Field(const Field &other) : type(other.type), owns_data(other.owns_data) {
        switch (type) {
            case FIELD_UINT32: {
                value.v_uint32 = new std::vector<uint32_t>(*other.value.v_uint32);
            } break;
            case FIELD_UINT64: {
                value.v_uint64 = new std::vector<uint64_t>(*other.value.v_uint64);
            } break;
            case FIELD_BYTES: {
                if (owns_data) {
                    value.v_bytes = new std::vector<std::pair<uint8_t *, size_t>>();
                    for (std::pair<uint8_t *, size_t> data_info: *other.value.v_bytes) {
                        uint8_t *new_data = new uint8_t[data_info.second];
                        std::copy_n(data_info.first, data_info.second, new_data);
                        value.v_bytes->push_back({new_data, data_info.second});
                    }
                } else {
                    value.v_bytes = new std::vector<std::pair<uint8_t *, size_t>>(*other.value.v_bytes);
                }
                cached_messages = new std::vector<Message *>();
                cached_messages->reserve(other.cached_messages->size());
                for (Message *other_cached_message: *other.cached_messages) {
                    Message *cached_message;
                    if (other_cached_message) {
                        cached_message = new Message(*other_cached_message);
                    } else {
                        cached_message = nullptr;
                    }
                    cached_messages->push_back(cached_message);
                }
            } break;
            default: {
                PP_LOG(ERROR) << "Bad field type when constructing field: " << type;
            } break;
        }
    }

    Field::~Field() {
        switch (type) {
            case FIELD_UINT32:
                delete value.v_uint32;
                break;
            case FIELD_UINT64:
                delete value.v_uint64;
                break;
            case FIELD_BYTES: {
                if (owns_data)
                    for (std::pair<uint8_t *, size_t> data_info: *value.v_bytes)
                        delete[] data_info.first;
                delete value.v_bytes;

                for (Message *cached_message: *cached_messages)
                    if (cached_message)
                        delete cached_message;
                delete cached_messages;
                break;
            }
            default:
                PP_LOG(ERROR) << "Bad field type when destroying field: " << type;
                break;
        }
    }

    Message::Message() : Message(true){};

    Message::Message(bool copy_arrays) : copy_arrays(copy_arrays){};

    Message::Message(const Message &other) : field_map(other.field_map), fields(other.fields), copy_arrays(other.copy_arrays){};

    Message::~Message(){};

    bool Message::ParseFromBytes(uint8_t *bytes, size_t bytes_size) {
        uint8_t *current = bytes;
        size_t remaining = bytes_size;
        while (remaining > 0) {
            uint8_t wire_type;
            uint32_t field_number;
            ReadWireTypeAndFieldNumber(&current, &remaining, &wire_type, &field_number);
            switch (wire_type) {
                case WIRETYPE_VARINT: {
                    Field *field = AddField(field_number, FIELD_UINT64);
                    const uint64_t varint = ReadVarInt(&current, &remaining);
                    field->value.v_uint64->push_back(varint);
                    break;
                }
                case WIRETYPE_64BIT: {
                    Field *field = AddField(field_number, FIELD_UINT64);
                    const uint64_t value = ReadFromBytes<uint64_t>(&current, &remaining);
                    field->value.v_uint64->push_back(value);
                    break;
                }
                case WIRETYPE_LENGTH_DELIMITED: {
                    Field *field = AddField(field_number, FIELD_BYTES);
                    const uint64_t size = ReadVarInt(&current, &remaining);
                    uint8_t *data;
                    if (copy_arrays) {
                        data = new uint8_t[size];
                        std::copy_n(current, size, data);
                        field->owns_data = true;
                    } else {
                        data = current;
                        field->owns_data = false;
                    }
                    field->value.v_bytes->push_back({data, size});
                    field->cached_messages->push_back(nullptr);
                    current += size;
                    remaining -= size;
                    break;
                }
                case WIRETYPE_GROUP_START: {
                    PP_LOG(INFO) << field_number << ": GROUPSTART" << std::endl;
                    PP_LOG(ERROR) << "Unhandled wire type encountered";
                    break;
                }
                case WIRETYPE_GROUP_END: {
                    PP_LOG(INFO) << field_number << ": GROUPEND" << std::endl;
                    PP_LOG(ERROR) << "Unhandled wire type encountered";
                    break;
                }
                case WIRETYPE_32BIT: {
                    Field *field = AddField(field_number, FIELD_UINT32);
                    const uint32_t value = ReadFromBytes<uint32_t>(&current, &remaining);
                    field->value.v_uint32->push_back(value);
                    break;
                }
                default: {
                    PP_LOG(ERROR) << "Unknown wire type encountered: " << static_cast<int>(wire_type) << " at offset" << (bytes_size - remaining);
                    return false;
                    break;
                }
            }
        }
        return true;
    }

    Field *Message::AddField(int32_t number, enum FieldType type) {
        Field *field = GetField(number);
        if (!field) {
            fields.push_back(Field(type, copy_arrays));
            field = &fields.back();
            field_map.insert({number, fields.size() - 1});
        }
        return field;
    }

    Field *Message::GetField(int32_t number) {
        if (field_map.count(number) == 0)
            return nullptr;
        return &(fields[field_map[number]]);
    }

    Field *Message::GetFieldAndCheckType(int32_t number, enum FieldType type) {
        Field *field = GetField(number);
        PP_CHECK(field) << "No field for " << number;
        PP_CHECK(field->type == type) << "For field " << number << " wanted type " << FieldTypeDebugString(type) << " but found " << FieldTypeDebugString(field->type);
        return field;
    }

    int32_t Message::GetInt32(int32_t number) {
        Field *field = GetFieldAndCheckType(number, FIELD_UINT32);
        uint32_t first_value = (*(field->value.v_uint32))[0];
        int32_t zig_zag_decoded = static_cast<int32_t>((first_value >> 1) ^ (-(first_value & 1)));
        return zig_zag_decoded;
    }

    int64_t Message::GetInt64(int32_t number) {
        Field *field = GetFieldAndCheckType(number, FIELD_UINT64);
        uint64_t first_value = (*(field->value.v_uint64))[0];
        int64_t zig_zag_decoded = static_cast<int64_t>((first_value >> 1) ^ (-(first_value & 1)));
        return zig_zag_decoded;
    }

    uint32_t Message::GetUInt32(int32_t number) {
        Field *field = GetFieldAndCheckType(number, FIELD_UINT32);
        uint32_t first_value = (*(field->value.v_uint32))[0];
        return first_value;
    }

    uint64_t Message::GetUInt64(int32_t number) {
        Field *field = GetFieldAndCheckType(number, FIELD_UINT64);
        uint64_t first_value = (*(field->value.v_uint64))[0];
        return first_value;
    }

    int64_t Message::GetInt(int32_t number) {
        Field *field = GetField(number);
        PP_CHECK(field) << "No field for " << number;
        PP_CHECK((field->type == FIELD_UINT32) || (field->type == FIELD_UINT64))
            << "For field " << number << " wanted integer type but found " << FieldTypeDebugString(field->type);
        switch (field->type) {
            case FIELD_UINT32:
                return GetInt32(number);
                break;
            case FIELD_UINT64:
                return GetInt64(number);
                break;
            default: {
                // Should never get here.
            } break;
        }
        // Should never get here.
        return 0;
    }

    bool Message::GetBool(int32_t number) {
        return (GetInt(number) != 0);
    }

    float Message::GetFloat(int32_t number) {
        uint32_t int_value = GetUInt32(number);
        float float_value = *(bit_cast<float *>(&int_value));
        return float_value;
    }

    double Message::GetDouble(int32_t number) {
        uint64_t int_value = GetUInt64(number);
        return *(bit_cast<double *>(&int_value));
    }

    std::pair<uint8_t *, size_t> Message::GetBytes(int32_t number) {
        Field *field = GetFieldAndCheckType(number, FIELD_BYTES);
        std::pair<uint8_t *, size_t> first_value = (*(field->value.v_bytes))[0];
        return first_value;
    }

    std::string Message::GetString(int32_t number) {
        Field *field = GetFieldAndCheckType(number, FIELD_BYTES);
        std::pair<uint8_t *, size_t> first_value = (*(field->value.v_bytes))[0];
        std::string result(first_value.first, first_value.first + first_value.second);
        return result;
    }

    Message *Message::GetMessage(int32_t number) {
        Field *field = GetFieldAndCheckType(number, FIELD_BYTES);
        Message *cached_message = field->cached_messages->at(0);
        if (!cached_message) {
            std::pair<uint8_t *, size_t> first_value = (*(field->value.v_bytes))[0];
            cached_message = new Message(copy_arrays);
            cached_message->ParseFromBytes(first_value.first, first_value.second);
            field->cached_messages->at(0) = cached_message;
        }
        return cached_message;
    }

    std::vector<int32_t> Message::GetInt32Array(int32_t number) {
        std::vector<uint64_t> raw_array = GetUInt64Array(number);
        std::vector<int32_t> result;
        result.reserve(raw_array.size());
        for (uint64_t raw_value: raw_array) {
            int32_t zig_zag_decoded = static_cast<int32_t>((raw_value >> 1) ^ (-(raw_value & 1)));
            result.push_back(zig_zag_decoded);
        }
        return result;
    }

    std::vector<int64_t> Message::GetInt64Array(int32_t number) {
        std::vector<uint64_t> raw_array = GetUInt64Array(number);
        std::vector<int64_t> result;
        result.reserve(raw_array.size());
        for (uint64_t raw_value: raw_array) {
            int64_t zig_zag_decoded = static_cast<int64_t>((raw_value >> 1) ^ (-(raw_value & 1)));
            result.push_back(zig_zag_decoded);
        }
        return result;
    }

    std::vector<uint32_t> Message::GetUInt32Array(int32_t number) {
        std::vector<uint64_t> raw_array = GetUInt64Array(number);
        std::vector<uint32_t> result;
        result.reserve(raw_array.size());
        for (uint64_t raw_value: raw_array) {
            result.push_back(static_cast<uint32_t>(raw_value));
        }
        return result;
    }

    std::vector<uint64_t> Message::GetUInt64Array(int32_t number) {
        std::vector<uint64_t> result;
        Field *field = GetField(number);
        if (!field) {
            return result;
        }
        if (field->type == FIELD_UINT64) {
            result.reserve(field->value.v_uint64->size());
            for (uint64_t value: *field->value.v_uint64) {
                result.push_back(static_cast<uint64_t>(value));
            }
        } else if (field->type == FIELD_UINT32) {
            result.reserve(field->value.v_uint32->size());
            for (uint32_t value: *field->value.v_uint32) {
                result.push_back(static_cast<uint64_t>(value));
            }
        } else if (field->type == FIELD_BYTES) {
            for (std::pair<uint8_t *, size_t> data_info: *field->value.v_bytes) {
                uint8_t *current = data_info.first;
                size_t remaining = data_info.second;
                while (remaining > 0) {
                    const uint64_t varint = ReadVarInt(&current, &remaining);
                    result.push_back(static_cast<int64_t>(varint));
                }
            }
        } else {
            PP_LOG(ERROR) << "Expected field type UINT32, UINT64, or BYTES but got " << FieldTypeDebugString(field->type);
        }
        return result;
    }

    std::vector<bool> Message::GetBoolArray(int32_t number) {
        std::vector<uint64_t> raw_array = GetUInt64Array(number);
        std::vector<bool> result;
        result.reserve(raw_array.size());
        for (uint64_t raw_value: raw_array) {
            result.push_back(raw_value != 0);
        }
        return result;
    }

    std::vector<float> Message::GetFloatArray(int32_t number) {
        std::vector<float> result;
        Field *field = GetField(number);
        if (!field) {
            return result;
        }
        if (field->type == FIELD_UINT32) {
            result.reserve(field->value.v_uint32->size());
            for (uint32_t value: *field->value.v_uint32) {
                result.push_back(bit_cast<float>(value));
            }
        } else if (field->type == FIELD_BYTES) {
            for (std::pair<uint8_t *, size_t> data_info: *field->value.v_bytes) {
                uint8_t *current = data_info.first;
                size_t remaining = data_info.second;
                while (remaining > 0) {
                    const uint64_t varint = ReadVarInt(&current, &remaining);
                    const uint32_t varint32 = static_cast<uint32_t>(varint & 0xffffffff);
                    result.push_back(bit_cast<float>(varint32));
                }
            }
        } else {
            PP_LOG(ERROR) << "Expected field type UINT32 or BYTES but got " << FieldTypeDebugString(field->type);
        }
        return result;
    }

    std::vector<double> Message::GetDoubleArray(int32_t number) {
        std::vector<double> result;
        Field *field = GetField(number);
        if (!field) {
            return result;
        }
        if (field->type == FIELD_UINT64) {
            result.reserve(field->value.v_uint64->size());
            for (uint64_t value: *field->value.v_uint64) {
                result.push_back(bit_cast<double>(value));
            }
        } else if (field->type == FIELD_BYTES) {
            for (std::pair<uint8_t *, size_t> data_info: *field->value.v_bytes) {
                uint8_t *current = data_info.first;
                size_t remaining = data_info.second;
                while (remaining > 0) {
                    const uint64_t varint = ReadVarInt(&current, &remaining);
                    result.push_back(bit_cast<double>(varint));
                }
            }
        } else {
            PP_LOG(ERROR) << "Expected field type UINT64 or BYTES but got " << FieldTypeDebugString(field->type);
        }
        return result;
    }

    std::vector<std::pair<uint8_t *, size_t>> Message::GetByteArray(int32_t number) {
        std::vector<std::pair<uint8_t *, size_t>> result;
        Field *field = GetField(number);
        if (!field) {
            return result;
        }
        if (field->type == FIELD_BYTES) {
            result.reserve(field->value.v_bytes->size());
            for (std::pair<uint8_t *, size_t> data_info: *field->value.v_bytes) {
                result.push_back(data_info);
            }
        } else {
            PP_LOG(ERROR) << "Expected field type BYTES but got " << FieldTypeDebugString(field->type);
        }
        return result;
    }

    std::vector<std::string> Message::GetStringArray(int32_t number) {
        std::vector<std::string> result;
        Field *field = GetField(number);
        if (!field)
            return result;
        if (field->type == FIELD_BYTES) {
            result.reserve(field->value.v_bytes->size());
            for (std::pair<uint8_t *, size_t> data_info: *field->value.v_bytes) {
                result.push_back(std::string(data_info.first, data_info.first + data_info.second));
            }
        } else {
            PP_LOG(ERROR) << "Expected field type BYTES but got " << FieldTypeDebugString(field->type);
        }
        return result;
    }

    std::vector<Message *> Message::GetMessageArray(int32_t number) {
        std::vector<Message *> result;
        Field *field = GetField(number);
        if (!field)
            return result;

        if (field->type == FIELD_BYTES) {
            result.reserve(field->value.v_bytes->size());
            for (size_t i = 0; i < field->value.v_bytes->size(); ++i) {
                Message *cached_message = field->cached_messages->at(i);
                if (!cached_message) {
                    std::pair<uint8_t *, size_t> value = field->value.v_bytes->at(i);
                    cached_message = new Message(copy_arrays);
                    cached_message->ParseFromBytes(value.first, value.second);
                    field->cached_messages->at(i) = cached_message;
                }
                result.push_back(cached_message);
            }
        } else {
            PP_LOG(ERROR) << "Expected field type BYTES but got " << FieldTypeDebugString(field->type);
        }
        return result;
    }

} // namespace picoproto


================================================
FILE: 3rdparty/qv2ray/v3/components/GeositeReader/picoproto.hpp
================================================
/* Copyright 2016 Pete Warden. All Rights Reserved.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 ==============================================================================*/

/*
 See the README for full details, but this module lets you read in protobuf
 encoded files with a minimal code footprint.

 It doesn't create classes for each kind of message it encounters, it just has a
 single Message interface that lets you access the members of the protobuf as a
 key/value store. This loses a lot of the convenience of type-checked classes,
 but it does mean that very little code is needed to access data from files.

 As a simple example, if you had read a `bytes_size` long file into `bytes` that
 contained a TensorFlow GraphDef proto:

 Message graph_def;
 graph_def.ParseFromBytes(bytes, bytes_size);

 You can then access the different fields of the GraphDef using the field
 numbers assigned in the .proto file:

 std::vector<picoproto::Message*> nodes = graph_def.GetMessageArray(1);

 One big difference between this minimal approach and normal protobufs is that
 the calling code has to already know the field number and type of any members
 it's trying to access. Here I know that the `node` field is number 1, and that
 it should contain a repeated list of NodeDefs. Since they are not primitive
 types like numbers or strings, they are accessed as an array of Messages.

 Here are the design goals of this module:
  - Keep the code size tiny (single-digit kilobytes on most platforms).
  - Minimize memory usage (for example allow in-place references to byte data).
  - Provide a simple, readable implementation that can be ported easily.
  - Deserialize all saved protobuf files into a usable representation.
  - No dependencies other than the standard C++ library.
  - No build-time support (e.g. protoc) required.

 Here's what it's explicitly not offering:
  - Providing a readable and transparent way of accessing serialized data.
  - Saving out data to protobuf format.

*/

#ifndef INCLUDE_PICOPROTO_H
#define INCLUDE_PICOPROTO_H

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <map>
#include <string>
#include <vector>

// To keep dependencies minimal, some bare-bones macros to make logging easier.
#define PP_LOG(X) PP_LOG_##X
#define PP_LOG_INFO std::cerr << __FILE__ << ":" << __LINE__ << " - INFO: "
#define PP_LOG_WARN std::cerr << __FILE__ << ":" << __LINE__ << " - WARN: "
#define PP_LOG_ERROR std::cerr << __FILE__ << ":" << __LINE__ << " - ERROR: "
#define PP_CHECK(X) \
    if (!(X))       \
    PP_LOG(ERROR) << "PP_CHECK(" << #X << ") failed. "

namespace picoproto {

    // These roughly correspond to the wire types used to save data in protobuf
    // files. The best reference to understand the full format is:
    // https://developers.google.com/protocol-buffers/docs/encoding
    // Because we don't know the bit-depth of VarInts, they're always stored as
    // uint64 values, which is why there's no specific type for them.
    enum FieldType {
        FIELD_UNSET,
        FIELD_UINT32,
        FIELD_UINT64,
        FIELD_BYTES,
    };

    // Gives a readable name for the field type for logging purposes.
    std::string FieldTypeDebugString(enum FieldType type);

    // Forward declare the main message class, since fields can contain them.
    class Message;

    // Fields are the building blocks of messages. They contain the values for each
    // data member, and handle all the allocation and deallocation of storage.
    // It's unlikely you'll want to access this class directly, since you'll
    // normally want to use Message below to pull typed values.
    class Field {
    public:
        // You need to specify the type of a Field on creation, so that the right
        // storage can be set up for the values. You also need to indicate whether the
        // underlying memory will be around for the lifetime of the message (in which
        // case no copies are needed) or whether the class should make copies and take
        // ownership in case the data goes away.
        Field(FieldType type, bool owns_data);
        Field(const Field &other);
        ~Field();

        enum FieldType type;
        // I know, this isn't very OOP, but the simplicity of keeping track of a type
        // and deciding how to initialize and access the data based on that persuaded
        // me this was the best approach. The `value` member contains whatever data
        // the field should be holding.
        union {
            std::vector<uint32_t> *v_uint32;
            std::vector<uint64_t> *v_uint64;
            std::vector<std::pair<uint8_t *, size_t>> *v_bytes;
        } value;
        // One of the drawbacks of not requiring .proto files ahead of time is that I
        // don't know if a length-delimited field contains raw bytes, strings, or
        // sub-messages. The only time we know that a field should be interpreted as a
        // message is when client code requests it in that form. Because parsing can
        // be costly, here we cache the results of any such calls for subsequent
        // accesses.
        std::vector<Message *> *cached_messages;
        // If this is set, then the object will allocate its own storage for
        // length-delimited values, and copy from the input stream. If you know the
        // underlying data will be around for the lifetime of the message, you can
        // save memory and copies by leaving this as false.
        bool owns_data;
    };

    // The main interface for loading and accessing serialized protobuf data.
    class Message {
    public:
        // If you're not sure about the lifetime of any binary data you're reading
        // from, just call this default constructor.
        Message();
        // In the case when you're sure the lifetime of the byte stream you'll be
        // decoding is longer than the lifetime of the message, you can set
        // copy_arrays to false. This is especially useful if you have a memory
        // mapped file to read from containing large binary blobs, since you'll skip
        // a lot of copying and extra allocation.
        Message(bool copy_arrays);
        Message(const Message &other);
        ~Message();

        // Populates fields with all of the data from this stream of bytes.
        // You can call this repeatedly with new messages, and the results will be
        // merged together.
        bool ParseFromBytes(uint8_t *binary, size_t binary_size);

        // These are the accessor functions if you're expecting exactly one value in a
        // field. As discussed above, the burden is on the client code to know the
        // field number and type of each member it's trying to access, and so pick the
        // correct accessor function.
        // If the field isn't present, this will raise an error, so if it's optional
        // you should use the array accessors below.
        int32_t GetInt32(int32_t number);
        int64_t GetInt64(int32_t number);
        uint32_t GetUInt32(int32_t number);
        uint64_t GetUInt64(int32_t number);
        int64_t GetInt(int32_t number);
        bool GetBool(int32_t number);
        float GetFloat(int32_t number);
        double GetDouble(int32_t number);
        std::pair<uint8_t *, size_t> GetBytes(int32_t number);
        std::string GetString(int32_t number);
        Message *GetMessage(int32_t number);

        // If you're not sure if a value will be present, or if it is repeated, you
        // should call these array functions. If no such field has been seen, then the
        // result will be an empty vector, otherwise you'll get back one or more
        // entries.
        std::vector<int32_t> GetInt32Array(int32_t number);
        std::vector<int64_t> GetInt64Array(int32_t number);
        std::vector<uint32_t> GetUInt32Array(int32_t number);
        std::vector<uint64_t> GetUInt64Array(int32_t number);
        std::vector<bool> GetBoolArray(int32_t number);
        std::vector<float> GetFloatArray(int32_t number);
        std::vector<double> GetDoubleArray(int32_t number);
        std::vector<std::pair<uint8_t *, size_t>> GetByteArray(int32_t number);
        std::vector<std::string> GetStringArray(int32_t number);
        std::vector<Message *> GetMessageArray(int32_t number);

        // It's unlikely you'll want to access fields directly, but here's an escape
        // hatch in case you do have to manipulate them more directly.
        Field *GetField(int32_t number);

    private:
        // Inserts a new field, updating all the internal data structures.
        Field *AddField(int32_t number, enum FieldType type);

        Field *GetFieldAndCheckType(int32_t number, enum FieldType type);

        // Maps from a field number to an index in the `fields` vector.
        std::map<int32_t, size_t> field_map;
        // The core list of fields that have been parsed.
        std::vector<Field> fields;
        bool copy_arrays;
    };

} // namespace picoproto

#endif // INCLUDE_PICOPROTO_H


================================================
FILE: 3rdparty/qv2ray/wrapper.hpp
================================================
#pragma once

// Qv2ray wrapper

#include <QJsonDocument>
#include <QDebug>

#define LOG(...) Qv2ray::base::log_internal(__VA_ARGS__)
#define DEBUG(...) Qv2ray::base::log_internal(__VA_ARGS__)
namespace Qv2ray {
    namespace base {
        template<typename... T>
        inline void log_internal(T... v) {}
    } // namespace base
} // namespace Qv2ray

#define JsonToString(a) QJsonObject2QString(a, false)
#define JsonFromString(a) QString2QJsonObject(a)
#define QvMessageBoxWarn(a, b, c) MessageBoxWarning(b, c)

inline QString VerifyJsonString(const QString &source) {
    QJsonParseError error{};
    QJsonDocument doc = QJsonDocument::fromJson(source.toUtf8(), &error);
    Q_UNUSED(doc)

    if (error.error == QJsonParseError::NoError) {
        return "";
    } else {
        // LOG("WARNING: Json parse returns: " + error.errorString());
        return error.errorString();
    }
}

#define RED(obj)                                 \
    {                                            \
        auto _temp = obj->palette();             \
        _temp.setColor(QPalette::Text, Qt::red); \
        obj->setPalette(_temp);                  \
    }

#define BLACK(obj) obj->setPalette(QWidget::palette());


================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.5)

project(nekobox VERSION 0.1 LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# WINDOWS PDB FILE
if (WIN32)
    if (MSVC)
        set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
        set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")
    endif ()
endif ()

# Find Qt
if (NOT QT_VERSION_MAJOR)
    set(QT_VERSION_MAJOR 5)
endif ()
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Network Svg LinguistTools)

if (NKR_CROSS)
    set_property(TARGET Qt5::moc PROPERTY IMPORTED_LOCATION /usr/bin/moc)
    set_property(TARGET Qt5::uic PROPERTY IMPORTED_LOCATION /usr/bin/uic)
    set_property(TARGET Qt5::rcc PROPERTY IMPORTED_LOCATION /usr/bin/rcc)
    set_property(TARGET Qt5::lrelease PROPERTY IMPORTED_LOCATION /usr/bin/lrelease)
    set_property(TARGET Qt5::lupdate PROPERTY IMPORTED_LOCATION /usr/bin/lupdate)
endif ()

#### Platform Variables ####
if (WIN32)
    include("cmake/windows/windows.cmake")
else ()
    include("cmake/linux/linux.cmake")
endif ()

#### default prefix path ####

if (NOT NKR_LIBS)
    if (NKR_PACKAGE)
        list(APPEND NKR_LIBS ${CMAKE_SOURCE_DIR}/libs/deps/package)
    else ()
        list(APPEND NKR_LIBS ${CMAKE_SOURCE_DIR}/libs/deps/built)
    endif ()
endif ()

if (NOT NKR_DISABLE_LIBS)
    list(APPEND CMAKE_PREFIX_PATH ${NKR_LIBS})
endif ()

message("[CMAKE_PREFIX_PATH] ${CMAKE_PREFIX_PATH}")

# for some cross toolchain
list(APPEND CMAKE_FIND_ROOT_PATH ${CMAKE_PREFIX_PATH})
message("[CMAKE_FIND_ROOT_PATH] ${CMAKE_FIND_ROOT_PATH}")

#### NKR ####

include("cmake/print.cmake")
include("cmake/nkr.cmake")

find_package(Threads)

#### NKR EXTERNAL ####

if (NKR_NO_EXTERNAL)
    set(NKR_NO_GRPC 1)
    set(NKR_NO_YAML 1)
    set(NKR_NO_ZXING 1)
    set(NKR_NO_QHOTKEY 1)
endif ()

# grpc
if (NKR_NO_GRPC)
    nkr_add_compile_definitions(NKR_NO_GRPC)
else ()
    # My proto
    include("cmake/myproto.cmake")
    list(APPEND NKR_EXTERNAL_TARGETS myproto)
endif ()

# yaml-cpp
if (NKR_NO_YAML)
    nkr_add_compile_definitions(NKR_NO_YAML)
else ()
    find_package(yaml-cpp CONFIG REQUIRED) # only Release is built
    list(APPEND NKR_EXTERNAL_TARGETS yaml-cpp)
endif ()

# zxing-cpp
if (NKR_NO_ZXING)
    nkr_add_compile_definitions(NKR_NO_ZXING)
else ()
    find_package(ZXing CONFIG REQUIRED)
    list(APPEND NKR_EXTERNAL_TARGETS ZXing::ZXing)
endif ()

# QHotkey (static submodule)
if (NKR_NO_QHOTKEY)
    nkr_add_compile_definitions(NKR_NO_QHOTKEY)
else ()
    set(QHOTKEY_INSTALL OFF)
    set(BUILD_SHARED_LIBS OFF)
    add_subdirectory(3rdparty/QHotkey)
    list(APPEND NKR_EXTERNAL_TARGETS qhotkey)
endif ()

#### debug print ####

if (DBG_CMAKE)
    print_all_variables()
    print_target_properties(myproto)
    print_target_properties(yaml-cpp)
    print_target_properties(ZXing::ZXing)
    set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time")
    set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CMAKE_COMMAND} -E time")
endif ()

# Sources
set(PROJECT_SOURCES
        ${PLATFORM_SOURCES}

        main/main.cpp
        main/NekoGui.cpp
        main/NekoGui_Utils.cpp
        main/HTTPRequestHelper.cpp

        3rdparty/base64.cpp
        3rdparty/qrcodegen.cpp
        3rdparty/QtExtKeySequenceEdit.cpp

        3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.cpp
        3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp
        3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.cpp
        3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.cpp
        3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp
        3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.ui

        3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.cpp
        3rdparty/qv2ray/v3/components/GeositeReader/picoproto.cpp

        rpc/gRPC.cpp

        db/Database.cpp
        db/traffic/TrafficLooper.cpp
        db/ProfileFilter.cpp
        db/ConfigBuilder.cpp

        fmt/AbstractBean.cpp
        fmt/Bean2CoreObj_box.cpp
        fmt/Bean2External.cpp
        fmt/Bean2Link.cpp
        fmt/Link2Bean.cpp
        fmt/ChainBean.hpp # translate

        sub/GroupUpdater.cpp

        sys/ExternalProcess.cpp
        sys/AutoRun.cpp

        ui/ThemeManager.cpp
        ui/Icon.cpp

        ui/mainwindow_grpc.cpp
        ui/mainwindow.cpp
        ui/mainwindow.h
        ui/mainwindow.ui

        ui/edit/dialog_edit_profile.h
        ui/edit/dialog_edit_profile.cpp
        ui/edit/dialog_edit_profile.ui
        ui/edit/dialog_edit_group.h
        ui/edit/dialog_edit_group.cpp
        ui/edit/dialog_edit_group.ui

        ui/edit/edit_chain.h
        ui/edit/edit_chain.cpp
        ui/edit/edit_chain.ui
        ui/edit/edit_socks_http.h
        ui/edit/edit_socks_http.cpp
        ui/edit/edit_socks_http.ui
        ui/edit/edit_shadowsocks.h
        ui/edit/edit_shadowsocks.cpp
        ui/edit/edit_shadowsocks.ui
        ui/edit/edit_vmess.h
        ui/edit/edit_vmess.cpp
        ui/edit/edit_vmess.ui
        ui/edit/edit_trojan_vless.h
        ui/edit/edit_trojan_vless.cpp
        ui/edit/edit_trojan_vless.ui

        ui/edit/edit_naive.h
        ui/edit/edit_naive.cpp
        ui/edit/edit_naive.ui

        ui/edit/edit_quic.h
        ui/edit/edit_quic.cpp
        ui/edit/edit_quic.ui

        ui/edit/edit_custom.h
        ui/edit/edit_custom.cpp
        ui/edit/edit_custom.ui

        ui/dialog_basic_settings.cpp
        ui/dialog_basic_settings.h
        ui/dialog_basic_settings.ui

        ui/dialog_manage_groups.cpp
        ui/dialog_manage_groups.h
        ui/dialog_manage_groups.ui

        ui/dialog_manage_routes.cpp
        ui/dialog_manage_routes.h
        ui/dialog_manage_routes.ui

        ui/dialog_vpn_settings.cpp
        ui/dialog_vpn_settings.h
        ui/dialog_vpn_settings.ui

        ui/dialog_hotkey.cpp
        ui/dialog_hotkey.h
        ui/dialog_hotkey.ui

        ui/widget/ProxyItem.cpp
        ui/widget/ProxyItem.h
        ui/widget/ProxyItem.ui
        ui/widget/GroupItem.cpp
        ui/widget/GroupItem.h
        ui/widget/GroupItem.ui

        res/neko.qrc
        res/theme/feiyangqingyun/qss.qrc
        ${QV2RAY_RC}
)

# Qt exe
if (${QT_VERSION_MAJOR} GREATER_EQUAL 6)
    qt_add_executable(nekobox
            MANUAL_FINALIZATION
            ${PROJECT_SOURCES}
    )
    # Define target properties for Android with Qt 6 as:
    #    set_property(TARGET nekobox APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
    #                 ${CMAKE_CURRENT_SOURCE_DIR}/android)
    # For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
else ()
    if (ANDROID)
        add_library(nekobox SHARED
                ${PROJECT_SOURCES}
        )
        # Define properties for Android with Qt 5 after find_package() calls as:
        #    set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
    else ()
        add_executable(nekobox
                ${PROJECT_SOURCES}
        )
    endif ()
endif ()

# Target

set_property(TARGET nekobox PROPERTY AUTOUIC ON)
set_property(TARGET nekobox PROPERTY AUTOMOC ON)
set_property(TARGET nekobox PROPERTY AUTORCC ON)

set_target_properties(nekobox PROPERTIES
        WIN32_EXECUTABLE TRUE
)

# Target Source Translations

set(TS_FILES
        translations/zh_CN.ts
        translations/fa_IR.ts
        translations/ru_RU.ts
)
set(LUPDATE_OPTIONS
        -locations none -no-obsolete
)
if (${QT_VERSION_MAJOR} GREATER_EQUAL 6)
    qt_add_lupdate(nekobox TS_FILES ${TS_FILES} OPTIONS ${LUPDATE_OPTIONS})
    qt_add_lrelease(nekobox TS_FILES ${TS_FILES} QM_FILES_OUTPUT_VARIABLE QM_FILES)
else ()
    qt5_create_translation(QM_FILES ${PROJECT_SOURCES} ${TS_FILES} OPTIONS ${LUPDATE_OPTIONS})
endif ()
configure_file(translations/translations.qrc ${CMAKE_BINARY_DIR} COPYONLY)
target_sources(nekobox PRIVATE ${CMAKE_BINARY_DIR}/translations.qrc)

# Target Link

target_link_libraries(nekobox PRIVATE
        Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Svg
        Threads::Threads
        ${NKR_EXTERNAL_TARGETS}
        ${PLATFORM_LIBRARIES}
)

if (QT_VERSION_MAJOR EQUAL 6)
    qt_finalize_executable(nekobox)
endif ()


================================================
FILE: LICENSE
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versio
Download .txt
gitextract_ivvmk2ct/

├── .clang-format
├── .clang-tidy
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report-en.md
│   │   ├── bug-report-zh_cn.md
│   │   ├── feature_request-en.md
│   │   └── feature_request-zh_cn.md
│   └── workflows/
│       ├── build-nekoray-cmake.yml
│       └── update-pkgbuild.yml
├── .gitignore
├── .gitmodules
├── 3rdparty/
│   ├── QThreadCreateThread.hpp
│   ├── QtExtKeySequenceEdit.cpp
│   ├── QtExtKeySequenceEdit.h
│   ├── RunGuard.hpp
│   ├── VT100Parser.hpp
│   ├── WinCommander.cpp
│   ├── WinCommander.hpp
│   ├── ZxingQtReader.hpp
│   ├── base64.cpp
│   ├── base64.h
│   ├── fix_old_qt.h
│   ├── qrcodegen.cpp
│   ├── qrcodegen.hpp
│   ├── qscopeguard.h
│   └── qv2ray/
│       ├── v2/
│       │   ├── components/
│       │   │   └── proxy/
│       │   │       ├── QvProxyConfigurator.cpp
│       │   │       └── QvProxyConfigurator.hpp
│       │   └── ui/
│       │       ├── QvAutoCompleteTextEdit.cpp
│       │       ├── QvAutoCompleteTextEdit.hpp
│       │       └── widgets/
│       │           ├── common/
│       │           │   ├── QJsonModel.cpp
│       │           │   └── QJsonModel.hpp
│       │           └── editors/
│       │               ├── w_JsonEditor.cpp
│       │               ├── w_JsonEditor.hpp
│       │               └── w_JsonEditor.ui
│       ├── v3/
│       │   └── components/
│       │       └── GeositeReader/
│       │           ├── GeositeReader.cpp
│       │           ├── GeositeReader.hpp
│       │           ├── picoproto.cpp
│       │           └── picoproto.hpp
│       └── wrapper.hpp
├── CMakeLists.txt
├── LICENSE
├── README.md
├── cmake/
│   ├── linux/
│   │   └── linux.cmake
│   ├── myproto.cmake
│   ├── nkr.cmake
│   ├── print.cmake
│   └── windows/
│       ├── VersionInfo.in
│       ├── VersionResource.rc
│       ├── generate_product_version.cmake
│       └── windows.cmake
├── db/
│   ├── ConfigBuilder.cpp
│   ├── ConfigBuilder.hpp
│   ├── Database.cpp
│   ├── Database.hpp
│   ├── Group.hpp
│   ├── ProfileFilter.cpp
│   ├── ProfileFilter.hpp
│   ├── ProxyEntity.hpp
│   └── traffic/
│       ├── TrafficData.hpp
│       ├── TrafficLooper.cpp
│       └── TrafficLooper.hpp
├── docs/
│   ├── Build_Core.md
│   ├── Build_Linux.md
│   ├── Build_Windows.md
│   ├── RunFlags.md
│   ├── Run_Linux.md
│   └── readme.md
├── fmt/
│   ├── AbstractBean.cpp
│   ├── AbstractBean.hpp
│   ├── Bean2CoreObj_box.cpp
│   ├── Bean2External.cpp
│   ├── Bean2Link.cpp
│   ├── ChainBean.hpp
│   ├── CustomBean.hpp
│   ├── Link2Bean.cpp
│   ├── NaiveBean.hpp
│   ├── Preset.hpp
│   ├── QUICBean.hpp
│   ├── ShadowSocksBean.hpp
│   ├── SocksHttpBean.hpp
│   ├── TrojanVLESSBean.hpp
│   ├── V2RayStreamSettings.hpp
│   ├── VMessBean.hpp
│   └── includes.h
├── go/
│   ├── .gitignore
│   ├── cmd/
│   │   ├── nekobox_core/
│   │   │   ├── core_box.go
│   │   │   ├── go.mod
│   │   │   ├── go.sum
│   │   │   ├── grpc_box.go
│   │   │   └── main.go
│   │   └── updater/
│   │       ├── .gitignore
│   │       ├── go.mod
│   │       ├── go.sum
│   │       ├── launcher.go
│   │       ├── launcher_linux.go
│   │       ├── main.go
│   │       ├── msgbox.go
│   │       ├── msgbox_windows.go
│   │       └── updater.go
│   └── grpc_server/
│       ├── auth/
│       │   └── auth.go
│       ├── fulltest.go
│       ├── gen/
│       │   ├── libcore.pb.go
│       │   ├── libcore.proto
│       │   ├── libcore_grpc.pb.go
│       │   └── update_proto.sh
│       ├── go.mod
│       ├── go.sum
│       ├── grpc.go
│       └── update.go
├── libs/
│   ├── .gitignore
│   ├── build_deps_all.sh
│   ├── build_go.sh
│   ├── build_public_res.sh
│   ├── deploy_linux64.sh
│   ├── deploy_windows64.sh
│   ├── download_qtsdk_win.sh
│   ├── env_deploy.sh
│   ├── env_qtsdk.sh
│   ├── format_cpp.sh
│   ├── get_source.sh
│   ├── get_source_env.sh
│   ├── package_appimage.sh
│   └── package_debian.sh
├── main/
│   ├── Const.hpp
│   ├── GuiUtils.hpp
│   ├── HTTPRequestHelper.cpp
│   ├── HTTPRequestHelper.hpp
│   ├── NekoGui.cpp
│   ├── NekoGui.hpp
│   ├── NekoGui_ConfigItem.hpp
│   ├── NekoGui_DataStore.hpp
│   ├── NekoGui_Utils.cpp
│   ├── NekoGui_Utils.hpp
│   └── main.cpp
├── nekoray_version.txt
├── res/
│   ├── dashboard-notice.html
│   ├── neko.css
│   ├── neko.qrc
│   ├── public/
│   │   └── qtbase_zh_CN.qm
│   ├── theme/
│   │   └── feiyangqingyun/
│   │       ├── qss/
│   │       │   ├── blacksoft.css
│   │       │   ├── flatgray.css
│   │       │   └── lightblue.css
│   │       └── qss.qrc
│   └── vpn/
│       ├── sing-box-vpn.json
│       └── vpn-run-root.sh
├── rpc/
│   ├── gRPC.cpp
│   └── gRPC.h
├── sub/
│   ├── GroupUpdater.cpp
│   └── GroupUpdater.hpp
├── sys/
│   ├── AutoRun.cpp
│   ├── AutoRun.hpp
│   ├── ExternalProcess.cpp
│   ├── ExternalProcess.hpp
│   ├── linux/
│   │   ├── LinuxCap.cpp
│   │   └── LinuxCap.h
│   └── windows/
│       ├── MiniDump.cpp
│       ├── MiniDump.h
│       ├── guihelper.cpp
│       └── guihelper.h
├── test/
│   ├── test-qt512-sdk-build.sh
│   └── test-qt6-build.sh
├── translations/
│   ├── fa_IR.ts
│   ├── ru_RU.ts
│   ├── translations.qrc
│   └── zh_CN.ts
└── ui/
    ├── GroupSort.hpp
    ├── Icon.cpp
    ├── Icon.hpp
    ├── ThemeManager.cpp
    ├── ThemeManager.hpp
    ├── dialog_basic_settings.cpp
    ├── dialog_basic_settings.h
    ├── dialog_basic_settings.ui
    ├── dialog_hotkey.cpp
    ├── dialog_hotkey.h
    ├── dialog_hotkey.ui
    ├── dialog_manage_groups.cpp
    ├── dialog_manage_groups.h
    ├── dialog_manage_groups.ui
    ├── dialog_manage_routes.cpp
    ├── dialog_manage_routes.h
    ├── dialog_manage_routes.ui
    ├── dialog_vpn_settings.cpp
    ├── dialog_vpn_settings.h
    ├── dialog_vpn_settings.ui
    ├── edit/
    │   ├── dialog_edit_group.cpp
    │   ├── dialog_edit_group.h
    │   ├── dialog_edit_group.ui
    │   ├── dialog_edit_profile.cpp
    │   ├── dialog_edit_profile.h
    │   ├── dialog_edit_profile.ui
    │   ├── edit_chain.cpp
    │   ├── edit_chain.h
    │   ├── edit_chain.ui
    │   ├── edit_custom.cpp
    │   ├── edit_custom.h
    │   ├── edit_custom.ui
    │   ├── edit_naive.cpp
    │   ├── edit_naive.h
    │   ├── edit_naive.ui
    │   ├── edit_quic.cpp
    │   ├── edit_quic.h
    │   ├── edit_quic.ui
    │   ├── edit_shadowsocks.cpp
    │   ├── edit_shadowsocks.h
    │   ├── edit_shadowsocks.ui
    │   ├── edit_socks_http.cpp
    │   ├── edit_socks_http.h
    │   ├── edit_socks_http.ui
    │   ├── edit_trojan_vless.cpp
    │   ├── edit_trojan_vless.h
    │   ├── edit_trojan_vless.ui
    │   ├── edit_vmess.cpp
    │   ├── edit_vmess.h
    │   ├── edit_vmess.ui
    │   └── profile_editor.h
    ├── mainwindow.cpp
    ├── mainwindow.h
    ├── mainwindow.ui
    ├── mainwindow_grpc.cpp
    ├── mainwindow_interface.h
    └── widget/
        ├── FloatCheckBox.h
        ├── GroupItem.cpp
        ├── GroupItem.h
        ├── GroupItem.ui
        ├── MessageBoxTimer.h
        ├── MyLineEdit.h
        ├── MyTableWidget.h
        ├── ProxyItem.cpp
        ├── ProxyItem.h
        └── ProxyItem.ui
Download .txt
SYMBOL INDEX (621 symbols across 123 files)

FILE: 3rdparty/QThreadCreateThread.hpp
  class QThreadCreateThread (line 8) | class QThreadCreateThread : public QThread {
    method QThreadCreateThread (line 10) | explicit QThreadCreateThread(std::future<void> &&future)
    method run (line 17) | void run() override {
  function QThread (line 24) | inline QThread *createThreadImpl(std::future<void> &&future) {
  function QThread (line 29) | QThread *createQThread(Function &&f, Args &&... args) {

FILE: 3rdparty/QtExtKeySequenceEdit.h
  function class (line 3) | class QtExtKeySequenceEdit : public QKeySequenceEdit {

FILE: 3rdparty/RunGuard.hpp
  class RunGuard (line 9) | class RunGuard {
  function QString (line 34) | QString generateKeyHash(const QString &key, const QString &salt) {

FILE: 3rdparty/VT100Parser.hpp
  function QString (line 5) | inline QString cleanVT100String(const QString &in) {

FILE: 3rdparty/WinCommander.cpp
  function uint (line 48) | uint WinCommander::runProcessElevated(const QString &path,

FILE: 3rdparty/WinCommander.hpp
  class WinCommander (line 29) | class WinCommander {

FILE: 3rdparty/ZxingQtReader.hpp
  type BarcodeFormat (line 38) | enum class BarcodeFormat
  type ContentType (line 63) | enum class ContentType { Text, Binary, Mixed, GS1, ISO15434, UnknownECI }
  function QDebug (line 78) | QDebug operator<<(QDebug dbg, const T& v)
  class Position (line 83) | class Position : public ZXing::Quadrilateral<QPoint>
  function Result (line 115) | Result() = default;
  function Result (line 117) | explicit Result(ZXing::Result&& r) : ZXing::Result(std::move(r)) {
  function BarcodeFormat (line 127) | BarcodeFormat format() const { return static_cast<BarcodeFormat>(ZXing::...
  function ContentType (line 128) | ContentType contentType() const { return static_cast<ContentType>(ZXing:...
  function QString (line 129) | QString formatName() const { return QString::fromStdString(ZXing::ToStri...
  function QString (line 130) | const QString& text() const { return _text; }
  function QByteArray (line 131) | const QByteArray& bytes() const { return _bytes; }
  function Position (line 132) | const Position& position() const { return _position; }
  function QListResults (line 139) | inline QList<Result> QListResults(ZXing::Results&& zxres)
  function ReadBarcodes (line 147) | inline QList<Result> ReadBarcodes(const QImage& img, const DecodeHints& ...
  function Result (line 176) | inline Result ReadBarcode(const QImage& img, const DecodeHints& hints = {})
  function Result (line 299) | inline Result ReadBarcode(const QVideoFrame& frame, const DecodeHints& h...
  class BarcodeReader (line 322) | class BarcodeReader : public QObject, private DecodeHints
    method BarcodeReader (line 329) | BarcodeReader(QObject* parent = nullptr) : QAbstractVideoFilter(parent...
    method BarcodeReader (line 331) | BarcodeReader(QObject* parent = nullptr) : QObject(parent) {}
    method formats (line 338) | int formats() const noexcept
    method Q_SLOT (line 343) | Q_SLOT void setFormats(int newVal)
    method ZQ_PROPERTY (line 355) | ZQ_PROPERTY(bool, tryDownscale, setTryDownscale)
    method setVideoSink (line 385) | void setVideoSink(QVideoSink* sink) {
  class VideoFilterRunnable (line 403) | class VideoFilterRunnable : public QVideoFilterRunnable
    method VideoFilterRunnable (line 408) | explicit VideoFilterRunnable(BarcodeReader* filter) : _filter(filter) {}
    method QVideoFrame (line 410) | QVideoFrame run(QVideoFrame* input, const QVideoSurfaceFormat& /*surfa...
  function QVideoFilterRunnable (line 417) | inline QVideoFilterRunnable* BarcodeReader::createFilterRunnable()
  type ZXingQt (line 435) | namespace ZXingQt {
    function registerQmlAndMetaTypes (line 437) | inline void registerQmlAndMetaTypes()

FILE: 3rdparty/base64.cpp
  type Qt515Base64 (line 7) | namespace Qt515Base64 {
    type fromBase64_helper_result (line 9) | struct fromBase64_helper_result {
    function fromBase64_helper_result (line 14) | fromBase64_helper_result fromBase64_helper(const char *input, qsizetyp...
    function FromBase64Result (line 82) | FromBase64Result QByteArray_fromBase64Encoding(const QByteArray &base6...

FILE: 3rdparty/base64.h
  type Base64Option (line 4) | enum Base64Option {
  function swap (line 29) | void swap(FromBase64Result &other) noexcept {

FILE: 3rdparty/fix_old_qt.h
  function QString (line 7) | inline QString qEnvironmentVariable(const char *varName) {

FILE: 3rdparty/qrcodegen.cpp
  type qrcodegen (line 40) | namespace qrcodegen {
    function QrSegment (line 69) | QrSegment QrSegment::makeBytes(const vector<uint8_t> &data) {
    function QrSegment (line 79) | QrSegment QrSegment::makeNumeric(const char *digits) {
    function QrSegment (line 102) | QrSegment QrSegment::makeAlphanumeric(const char *text) {
    function QrSegment (line 143) | QrSegment QrSegment::makeEci(long assignVal) {
    function QrCode (line 247) | QrCode QrCode::encodeText(const char *text, Ecc ecl) {
    function QrCode (line 253) | QrCode QrCode::encodeBinary(const vector<uint8_t> &data, Ecc ecl) {
    function QrCode (line 259) | QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,

FILE: 3rdparty/qrcodegen.hpp
  type qrcodegen (line 33) | namespace qrcodegen {
    class QrSegment (line 46) | class QrSegment final {
      class Mode (line 53) | class Mode final {
    class QrCode (line 236) | class QrCode final {
      type Ecc (line 243) | enum class Ecc {
    class data_too_long (line 521) | class data_too_long : public std::length_error {
    class BitBuffer (line 532) | class BitBuffer final : public std::vector<bool> {

FILE: 3rdparty/qscopeguard.h
  function dismiss (line 69) | void dismiss() Q_DECL_NOEXCEPT

FILE: 3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp
  type Qv2ray::components::proxy (line 28) | namespace Qv2ray::components::proxy {
    function QStringList (line 32) | QStringList macOSgetNetworkServices() {
    function __QueryProxyOptions (line 62) | bool __QueryProxyOptions() {
    function __SetProxyOptions (line 131) | bool __SetProxyOptions(LPWSTR proxy_full_addr, bool isPAC) {
    function SetSystemProxy (line 229) | void SetSystemProxy(int httpPort, int socksPort) {
    function ClearSystemProxy (line 384) | void ClearSystemProxy() {

FILE: 3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.hpp
  type Qv2ray::components::proxy (line 6) | namespace Qv2ray::components::proxy {

FILE: 3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.cpp
  type Qv2ray::ui::widgets (line 64) | namespace Qv2ray::ui::widgets {
    function QString (line 88) | QString AutoCompleteTextEdit::lineUnderCursor() const {
    function QString (line 94) | QString AutoCompleteTextEdit::wordUnderCursor() const {

FILE: 3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.hpp
  function QT_END_NAMESPACE (line 56) | QT_END_NAMESPACE

FILE: 3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.cpp
  function QJsonTreeItem (line 42) | QJsonTreeItem *QJsonTreeItem::child(int row) {
  function QJsonTreeItem (line 46) | QJsonTreeItem *QJsonTreeItem::parent() {
  function QString (line 73) | QString QJsonTreeItem::key() const {
  function QString (line 77) | QString QJsonTreeItem::value() const {
  function QJsonTreeItem (line 85) | QJsonTreeItem *QJsonTreeItem::load(const QJsonValue &value, QJsonTreeIte...
  function QVariant (line 186) | QVariant QJsonModel::data(const QModelIndex &index, int role) const {
  function QVariant (line 222) | QVariant QJsonModel::headerData(int section, Qt::Orientation orientation...
  function QModelIndex (line 232) | QModelIndex QJsonModel::index(int row, int column, const QModelIndex &pa...
  function QModelIndex (line 251) | QModelIndex QJsonModel::parent(const QModelIndex &index) const {
  function QJsonDocument (line 296) | QJsonDocument QJsonModel::json() const {
  function QJsonValue (line 309) | QJsonValue QJsonModel::genJson(QJsonTreeItem *item) const {

FILE: 3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.hpp
  class QJsonModel (line 34) | class QJsonModel
  class QJsonItem (line 35) | class QJsonItem
  class QJsonTreeItem (line 37) | class QJsonTreeItem {
  class QJsonModel (line 66) | class QJsonModel : public QAbstractItemModel {

FILE: 3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.cpp
  function QJsonObject (line 38) | QJsonObject JsonEditor::OpenEditor() {

FILE: 3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp
  class JsonEditor (line 9) | class JsonEditor

FILE: 3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.cpp
  type Qv2ray::components::GeositeReader (line 9) | namespace Qv2ray::components::GeositeReader {
    function QStringList (line 12) | QStringList ReadGeoSiteFromFile(const QString &filepath, bool allowCac...

FILE: 3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.hpp
  type Qv2ray::components::GeositeReader (line 5) | namespace Qv2ray::components::GeositeReader {

FILE: 3rdparty/qv2ray/v3/components/GeositeReader/picoproto.cpp
  type picoproto (line 18) | namespace picoproto {
    function Dest (line 26) | inline Dest bit_cast(const Source &source) {
    type WireType (line 35) | enum WireType {
    function ConsumeBytes (line 45) | bool ConsumeBytes(uint8_t **current, size_t how_many, size_t *remainin...
    function T (line 57) | T ReadFromBytes(uint8_t **current, size_t *remaining) {
    function ReadVarInt (line 63) | uint64_t ReadVarInt(uint8_t **current, size_t *remaining) {
    function ReadWireTypeAndFieldNumber (line 76) | void ReadWireTypeAndFieldNumber(uint8_t **current, size_t *remaining, ...
    function FieldTypeDebugString (line 84) | std::string FieldTypeDebugString(enum FieldType type) {
    function Field (line 259) | Field *Message::AddField(int32_t number, enum FieldType type) {
    function Field (line 269) | Field *Message::GetField(int32_t number) {
    function Field (line 275) | Field *Message::GetFieldAndCheckType(int32_t number, enum FieldType ty...
    function Message (line 356) | Message *Message::GetMessage(int32_t number) {

FILE: 3rdparty/qv2ray/v3/components/GeositeReader/picoproto.hpp
  type picoproto (line 77) | namespace picoproto {
    type FieldType (line 84) | enum FieldType {
    type FieldType (line 92) | enum FieldType
    class Message (line 95) | class Message
      type FieldType (line 195) | enum FieldType
      type FieldType (line 197) | enum FieldType
    class Field (line 101) | class Field {
      type FieldType (line 112) | enum FieldType
    class Message (line 137) | class Message {
      type FieldType (line 195) | enum FieldType
      type FieldType (line 197) | enum FieldType

FILE: 3rdparty/qv2ray/wrapper.hpp
  type Qv2ray (line 10) | namespace Qv2ray {
    type base (line 11) | namespace base {
      function log_internal (line 13) | inline void log_internal(T... v) {}
  function QString (line 21) | inline QString VerifyJsonString(const QString &source) {

FILE: db/ConfigBuilder.cpp
  type NekoGui (line 12) | namespace NekoGui {
    function QStringList (line 14) | QStringList getAutoBypassExternalProcessPaths(const std::shared_ptr<Bu...
    function QString (line 24) | QString genTunName() {
    function MergeJson (line 32) | void MergeJson(QJsonObject &dst, const QJsonObject &src) {
    function BuildConfig (line 73) | std::shared_ptr<BuildConfigResult> BuildConfig(const std::shared_ptr<P...
    function QString (line 94) | QString BuildChain(int chainId, const std::shared_ptr<BuildConfigStatu...
    function QString (line 174) | QString BuildChainInternal(int chainId, const QList<std::shared_ptr<Pr...
    function BuildConfigSingBox (line 389) | void BuildConfigSingBox(const std::shared_ptr<BuildConfigStatus> &stat...
    function QString (line 745) | QString WriteVPNSingBoxConfig() {
    function QString (line 799) | QString WriteVPNLinuxScript(const QString &configPath) {

FILE: db/ConfigBuilder.hpp
  type NekoGui (line 6) | namespace NekoGui {
    class BuildConfigResult (line 7) | class BuildConfigResult {
    class BuildConfigStatus (line 19) | class BuildConfigStatus {

FILE: db/Database.cpp
  type NekoGui (line 9) | namespace NekoGui {
    function filterIntJsonFile (line 17) | QList<int> filterIntJsonFile(const QString &path) {
    function QString (line 226) | QString ProxyEntity::DisplayLatency() const {
    function QColor (line 236) | QColor ProxyEntity::DisplayLatencyColor() const {

FILE: db/Database.hpp
  type NekoGui (line 7) | namespace NekoGui {
    class ProfileManager (line 8) | class ProfileManager : private JsonStore {

FILE: db/Group.hpp
  type NekoGui (line 6) | namespace NekoGui {
    class Group (line 7) | class Group : public JsonStore {

FILE: db/ProfileFilter.cpp
  type NekoGui (line 3) | namespace NekoGui {
    function QString (line 5) | QString ProfileFilter_ent_key(const std::shared_ptr<NekoGui::ProxyEnti...

FILE: db/ProfileFilter.hpp
  type NekoGui (line 5) | namespace NekoGui {
    class ProfileFilter (line 6) | class ProfileFilter {

FILE: db/ProxyEntity.hpp
  type NekoGui_fmt (line 7) | namespace NekoGui_fmt {
    class SocksHttpBean (line 8) | class SocksHttpBean
    class ShadowSocksBean (line 10) | class ShadowSocksBean
    class VMessBean (line 12) | class VMessBean
    class TrojanVLESSBean (line 14) | class TrojanVLESSBean
    class NaiveBean (line 16) | class NaiveBean
    class QUICBean (line 18) | class QUICBean
    class CustomBean (line 20) | class CustomBean
    class ChainBean (line 22) | class ChainBean
  type NekoGui (line 25) | namespace NekoGui {
    class ProxyEntity (line 26) | class ProxyEntity : public JsonStore {

FILE: db/traffic/TrafficData.hpp
  type NekoGui_traffic (line 5) | namespace NekoGui_traffic {
    class TrafficData (line 6) | class TrafficData : public JsonStore {
      method TrafficData (line 18) | explicit TrafficData(std::string tag) {
      method Reset (line 24) | void Reset() {
      method QString (line 31) | [[nodiscard]] QString DisplaySpeed() const {
      method QString (line 35) | [[nodiscard]] QString DisplayTraffic() const {

FILE: db/traffic/TrafficLooper.cpp
  type NekoGui_traffic (line 12) | namespace NekoGui_traffic {
    function TrafficData (line 17) | TrafficData *TrafficLooper::update_stats(TrafficData *item) {
    function QJsonArray (line 46) | QJsonArray TrafficLooper::get_connection_list() {

FILE: db/traffic/TrafficLooper.hpp
  type NekoGui_traffic (line 9) | namespace NekoGui_traffic {
    class TrafficLooper (line 10) | class TrafficLooper {

FILE: fmt/AbstractBean.cpp
  type NekoGui_fmt (line 7) | namespace NekoGui_fmt {
    function QString (line 18) | QString AbstractBean::ToNekorayShareLink(const QString &type) {
    function QString (line 29) | QString AbstractBean::DisplayAddress() {
    function QString (line 33) | QString AbstractBean::DisplayName() {
    function QString (line 40) | QString AbstractBean::DisplayTypeAndName() {

FILE: fmt/AbstractBean.hpp
  type NekoGui_fmt (line 8) | namespace NekoGui_fmt {
    type CoreObjOutboundBuildResult (line 9) | struct CoreObjOutboundBuildResult {
    type ExternalBuildResult (line 15) | struct ExternalBuildResult {
    class AbstractBean (line 27) | class AbstractBean : public JsonStore {
      method QString (line 52) | virtual QString DisplayCoreType() { return software_core_name; }
      method QString (line 54) | virtual QString DisplayType() { return {}; }
      method NeedExternal (line 60) | virtual int NeedExternal(bool isFirstProfile) { return 0; }
      method CoreObjOutboundBuildResult (line 62) | virtual CoreObjOutboundBuildResult BuildCoreObjSingBox() { return {}; }
      method ExternalBuildResult (line 64) | virtual ExternalBuildResult BuildExternal(int mapping_port, int sock...
      method QString (line 66) | virtual QString ToShareLink() { return {}; }

FILE: fmt/Bean2CoreObj_box.cpp
  type NekoGui_fmt (line 4) | namespace NekoGui_fmt {
    function CoreObjOutboundBuildResult (line 81) | CoreObjOutboundBuildResult SocksHttpBean::BuildCoreObjSingBox() {
    function CoreObjOutboundBuildResult (line 100) | CoreObjOutboundBuildResult ShadowSocksBean::BuildCoreObjSingBox() {
    function CoreObjOutboundBuildResult (line 129) | CoreObjOutboundBuildResult VMessBean::BuildCoreObjSingBox() {
    function CoreObjOutboundBuildResult (line 146) | CoreObjOutboundBuildResult TrojanVLESSBean::BuildCoreObjSingBox() {
    function CoreObjOutboundBuildResult (line 175) | CoreObjOutboundBuildResult QUICBean::BuildCoreObjSingBox() {
    function CoreObjOutboundBuildResult (line 228) | CoreObjOutboundBuildResult CustomBean::BuildCoreObjSingBox() {

FILE: fmt/Bean2External.cpp
  type NekoGui_fmt (line 22) | namespace NekoGui_fmt {
    function ExternalBuildResult (line 67) | ExternalBuildResult NaiveBean::BuildExternal(int mapping_port, int soc...
    function ExternalBuildResult (line 103) | ExternalBuildResult QUICBean::BuildExternal(int mapping_port, int sock...
    function ExternalBuildResult (line 223) | ExternalBuildResult CustomBean::BuildExternal(int mapping_port, int so...

FILE: fmt/Bean2Link.cpp
  type NekoGui_fmt (line 6) | namespace NekoGui_fmt {
    function QString (line 7) | QString SocksHttpBean::ToShareLink() {
    function QString (line 26) | QString TrojanVLESSBean::ToShareLink() {
    function QString (line 81) | QString ShadowSocksBean::ToShareLink() {
    function QString (line 102) | QString VMessBean::ToShareLink() {
    function QString (line 172) | QString NaiveBean::ToShareLink() {
    function QString (line 183) | QString QUICBean::ToShareLink() {

FILE: fmt/ChainBean.hpp
  type NekoGui_fmt (line 5) | namespace NekoGui_fmt {
    class ChainBean (line 6) | class ChainBean : public AbstractBean {
      method ChainBean (line 10) | ChainBean() : AbstractBean(0) {
      method QString (line 14) | QString DisplayType() override { return QObject::tr("Chain Proxy"); }
      method QString (line 16) | QString DisplayAddress() override { return ""; }

FILE: fmt/CustomBean.hpp
  type NekoGui_fmt (line 5) | namespace NekoGui_fmt {
    class CustomBean (line 6) | class CustomBean : public AbstractBean {
      method CustomBean (line 15) | CustomBean() : AbstractBean(0) {
      method QString (line 24) | QString DisplayType() override {
      method QString (line 34) | QString DisplayCoreType() override { return NeedExternal(true) == 0 ...
      method QString (line 36) | QString DisplayAddress() override {

FILE: fmt/Link2Bean.cpp
  type NekoGui_fmt (line 6) | namespace NekoGui_fmt {

FILE: fmt/NaiveBean.hpp
  type NekoGui_fmt (line 5) | namespace NekoGui_fmt {
    class NaiveBean (line 6) | class NaiveBean : public AbstractBean {
      method NaiveBean (line 18) | NaiveBean() : AbstractBean(0) {
      method QString (line 29) | QString DisplayCoreType() override { return "Naive"; }
      method QString (line 31) | QString DisplayType() override { return "Naive"; }

FILE: fmt/Preset.hpp
  type Preset (line 3) | namespace Preset {
    type SingBox (line 4) | namespace SingBox {
    type Windows (line 12) | namespace Windows {

FILE: fmt/QUICBean.hpp
  type NekoGui_fmt (line 5) | namespace NekoGui_fmt {
    class QUICBean (line 6) | class QUICBean : public AbstractBean {
      method QUICBean (line 50) | explicit QUICBean(int _proxy_type) : AbstractBean(0) {
      method QString (line 80) | QString DisplayAddress() override {
      method QString (line 85) | QString DisplayCoreType() override {
      method QString (line 95) | QString DisplayType() override {

FILE: fmt/ShadowSocksBean.hpp
  type NekoGui_fmt (line 6) | namespace NekoGui_fmt {
    class ShadowSocksBean (line 7) | class ShadowSocksBean : public AbstractBean {
      method ShadowSocksBean (line 16) | ShadowSocksBean() : AbstractBean(0) {
      method QString (line 24) | QString DisplayType() override { return "Shadowsocks"; }

FILE: fmt/SocksHttpBean.hpp
  type NekoGui_fmt (line 6) | namespace NekoGui_fmt {
    class SocksHttpBean (line 7) | class SocksHttpBean : public AbstractBean {
      method SocksHttpBean (line 19) | explicit SocksHttpBean(int _socks_http_type) : AbstractBean(0) {
      method QString (line 27) | QString DisplayType() override { return socks_http_type == type_HTTP...

FILE: fmt/TrojanVLESSBean.hpp
  type NekoGui_fmt (line 6) | namespace NekoGui_fmt {
    class TrojanVLESSBean (line 7) | class TrojanVLESSBean : public AbstractBean {
      method TrojanVLESSBean (line 18) | explicit TrojanVLESSBean(int _proxy_type) : AbstractBean(0) {
      method QString (line 25) | QString DisplayType() override { return proxy_type == proxy_VLESS ? ...

FILE: fmt/V2RayStreamSettings.hpp
  type NekoGui_fmt (line 5) | namespace NekoGui_fmt {
    class V2rayStreamSettings (line 6) | class V2rayStreamSettings : public JsonStore {
      method V2rayStreamSettings (line 32) | V2rayStreamSettings() : JsonStore() {
    function V2rayStreamSettings (line 55) | inline V2rayStreamSettings *GetStreamSettings(AbstractBean *bean) {
      method V2rayStreamSettings (line 32) | V2rayStreamSettings() : JsonStore() {

FILE: fmt/VMessBean.hpp
  type NekoGui_fmt (line 6) | namespace NekoGui_fmt {
    class VMessBean (line 7) | class VMessBean : public AbstractBean {
      method VMessBean (line 15) | VMessBean() : AbstractBean(0) {
      method QString (line 22) | QString DisplayType() override { return "VMess"; }

FILE: go/cmd/nekobox_core/core_box.go
  function setupCore (line 18) | func setupCore() {

FILE: go/cmd/nekobox_core/grpc_box.go
  type server (line 23) | type server struct
    method Start (line 27) | func (s *server) Start(ctx context.Context, in *gen.LoadConfigReq) (ou...
    method Stop (line 64) | func (s *server) Stop(ctx context.Context, in *gen.EmptyReq) (out *gen...
    method Test (line 86) | func (s *server) Test(ctx context.Context, in *gen.TestReq) (out *gen....
    method QueryStats (line 135) | func (s *server) QueryStats(ctx context.Context, in *gen.QueryStatsReq...
    method ListConnections (line 147) | func (s *server) ListConnections(ctx context.Context, in *gen.EmptyReq...

FILE: go/cmd/nekobox_core/main.go
  function main (line 15) | func main() {

FILE: go/cmd/updater/launcher.go
  function Launcher (line 10) | func Launcher() {

FILE: go/cmd/updater/launcher_linux.go
  function Launcher (line 13) | func Launcher() {

FILE: go/cmd/updater/main.go
  function main (line 14) | func main() {
  function Copy (line 57) | func Copy(src string, dst string) {

FILE: go/cmd/updater/msgbox.go
  function MessageBoxPlain (line 5) | func MessageBoxPlain(title, caption string) int {

FILE: go/cmd/updater/msgbox_windows.go
  function MessageBoxPlain (line 9) | func MessageBoxPlain(title, caption string) int {
  function MessageBox (line 18) | func MessageBox(hwnd uintptr, caption, title string, flags uint) int {

FILE: go/cmd/updater/updater.go
  function Updater (line 14) | func Updater() {
  function Exist (line 81) | func Exist(path string) bool {
  function FindExist (line 86) | func FindExist(paths []string) string {
  function Mv (line 95) | func Mv(src, dst string) error {
  function removeAll (line 124) | func removeAll(glob string) {

FILE: go/grpc_server/auth/auth.go
  type Authenticator (line 12) | type Authenticator struct
    method Authenticate (line 18) | func (a Authenticator) Authenticate(ctx context.Context) (newCtx conte...
  function extractHeader (line 31) | func extractHeader(ctx context.Context, header string) (string, error) {
  function purgeHeader (line 49) | func purgeHeader(ctx context.Context, header string) context.Context {

FILE: go/grpc_server/fulltest.go
  constant KiB (line 21) | KiB = 1024
  constant MiB (line 22) | MiB = 1024 * KiB
  function getBetweenStr (line 25) | func getBetweenStr(str, start, end string) string {
  function DoFullTest (line 39) | func DoFullTest(ctx context.Context, in *gen.TestReq, instance interface...

FILE: go/grpc_server/gen/libcore.pb.go
  constant _ (line 18) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 20) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type TestMode (line 23) | type TestMode
    method Enum (line 45) | func (x TestMode) Enum() *TestMode {
    method String (line 51) | func (x TestMode) String() string {
    method Descriptor (line 55) | func (TestMode) Descriptor() protoreflect.EnumDescriptor {
    method Type (line 59) | func (TestMode) Type() protoreflect.EnumType {
    method Number (line 63) | func (x TestMode) Number() protoreflect.EnumNumber {
    method EnumDescriptor (line 68) | func (TestMode) EnumDescriptor() ([]byte, []int) {
  constant TestMode_TcpPing (line 26) | TestMode_TcpPing  TestMode = 0
  constant TestMode_UrlTest (line 27) | TestMode_UrlTest  TestMode = 1
  constant TestMode_FullTest (line 28) | TestMode_FullTest TestMode = 2
  type UpdateAction (line 72) | type UpdateAction
    method Enum (line 91) | func (x UpdateAction) Enum() *UpdateAction {
    method String (line 97) | func (x UpdateAction) String() string {
    method Descriptor (line 101) | func (UpdateAction) Descriptor() protoreflect.EnumDescriptor {
    method Type (line 105) | func (UpdateAction) Type() protoreflect.EnumType {
    method Number (line 109) | func (x UpdateAction) Number() protoreflect.EnumNumber {
    method EnumDescriptor (line 114) | func (UpdateAction) EnumDescriptor() ([]byte, []int) {
  constant UpdateAction_Check (line 75) | UpdateAction_Check    UpdateAction = 0
  constant UpdateAction_Download (line 76) | UpdateAction_Download UpdateAction = 1
  type EmptyReq (line 118) | type EmptyReq struct
    method Reset (line 124) | func (x *EmptyReq) Reset() {
    method String (line 133) | func (x *EmptyReq) String() string {
    method ProtoMessage (line 137) | func (*EmptyReq) ProtoMessage() {}
    method ProtoReflect (line 139) | func (x *EmptyReq) ProtoReflect() protoreflect.Message {
    method Descriptor (line 152) | func (*EmptyReq) Descriptor() ([]byte, []int) {
  type EmptyResp (line 156) | type EmptyResp struct
    method Reset (line 162) | func (x *EmptyResp) Reset() {
    method String (line 171) | func (x *EmptyResp) String() string {
    method ProtoMessage (line 175) | func (*EmptyResp) ProtoMessage() {}
    method ProtoReflect (line 177) | func (x *EmptyResp) ProtoReflect() protoreflect.Message {
    method Descriptor (line 190) | func (*EmptyResp) Descriptor() ([]byte, []int) {
  type ErrorResp (line 194) | type ErrorResp struct
    method Reset (line 202) | func (x *ErrorResp) Reset() {
    method String (line 211) | func (x *ErrorResp) String() string {
    method ProtoMessage (line 215) | func (*ErrorResp) ProtoMessage() {}
    method ProtoReflect (line 217) | func (x *ErrorResp) ProtoReflect() protoreflect.Message {
    method Descriptor (line 230) | func (*ErrorResp) Descriptor() ([]byte, []int) {
    method GetError (line 234) | func (x *ErrorResp) GetError() string {
  type LoadConfigReq (line 241) | type LoadConfigReq struct
    method Reset (line 251) | func (x *LoadConfigReq) Reset() {
    method String (line 260) | func (x *LoadConfigReq) String() string {
    method ProtoMessage (line 264) | func (*LoadConfigReq) ProtoMessage() {}
    method ProtoReflect (line 266) | func (x *LoadConfigReq) ProtoReflect() protoreflect.Message {
    method Descriptor (line 279) | func (*LoadConfigReq) Descriptor() ([]byte, []int) {
    method GetCoreConfig (line 283) | func (x *LoadConfigReq) GetCoreConfig() string {
    method GetEnableNekorayConnections (line 290) | func (x *LoadConfigReq) GetEnableNekorayConnections() bool {
    method GetStatsOutbounds (line 297) | func (x *LoadConfigReq) GetStatsOutbounds() []string {
  type TestReq (line 304) | type TestReq struct
    method Reset (line 329) | func (x *TestReq) Reset() {
    method String (line 338) | func (x *TestReq) String() string {
    method ProtoMessage (line 342) | func (*TestReq) ProtoMessage() {}
    method ProtoReflect (line 344) | func (x *TestReq) ProtoReflect() protoreflect.Message {
    method Descriptor (line 357) | func (*TestReq) Descriptor() ([]byte, []int) {
    method GetMode (line 361) | func (x *TestReq) GetMode() TestMode {
    method GetTimeout (line 368) | func (x *TestReq) GetTimeout() int32 {
    method GetAddress (line 375) | func (x *TestReq) GetAddress() string {
    method GetConfig (line 382) | func (x *TestReq) GetConfig() *LoadConfigReq {
    method GetInbound (line 389) | func (x *TestReq) GetInbound() string {
    method GetUrl (line 396) | func (x *TestReq) GetUrl() string {
    method GetInAddress (line 403) | func (x *TestReq) GetInAddress() string {
    method GetFullLatency (line 410) | func (x *TestReq) GetFullLatency() bool {
    method GetFullSpeed (line 417) | func (x *TestReq) GetFullSpeed() bool {
    method GetFullSpeedUrl (line 424) | func (x *TestReq) GetFullSpeedUrl() string {
    method GetFullSpeedTimeout (line 431) | func (x *TestReq) GetFullSpeedTimeout() int32 {
    method GetFullInOut (line 438) | func (x *TestReq) GetFullInOut() bool {
    method GetFullUdpLatency (line 445) | func (x *TestReq) GetFullUdpLatency() bool {
    method GetFullNat (line 453) | func (x *TestReq) GetFullNat() bool {
  type TestResp (line 460) | type TestResp struct
    method Reset (line 470) | func (x *TestResp) Reset() {
    method String (line 479) | func (x *TestResp) String() string {
    method ProtoMessage (line 483) | func (*TestResp) ProtoMessage() {}
    method ProtoReflect (line 485) | func (x *TestResp) ProtoReflect() protoreflect.Message {
    method Descriptor (line 498) | func (*TestResp) Descriptor() ([]byte, []int) {
    method GetError (line 502) | func (x *TestResp) GetError() string {
    method GetMs (line 509) | func (x *TestResp) GetMs() int32 {
    method GetFullReport (line 516) | func (x *TestResp) GetFullReport() string {
  type QueryStatsReq (line 523) | type QueryStatsReq struct
    method Reset (line 532) | func (x *QueryStatsReq) Reset() {
    method String (line 541) | func (x *QueryStatsReq) String() string {
    method ProtoMessage (line 545) | func (*QueryStatsReq) ProtoMessage() {}
    method ProtoReflect (line 547) | func (x *QueryStatsReq) ProtoReflect() protoreflect.Message {
    method Descriptor (line 560) | func (*QueryStatsReq) Descriptor() ([]byte, []int) {
    method GetTag (line 564) | func (x *QueryStatsReq) GetTag() string {
    method GetDirect (line 571) | func (x *QueryStatsReq) GetDirect() string {
  type QueryStatsResp (line 578) | type QueryStatsResp struct
    method Reset (line 586) | func (x *QueryStatsResp) Reset() {
    method String (line 595) | func (x *QueryStatsResp) String() string {
    method ProtoMessage (line 599) | func (*QueryStatsResp) ProtoMessage() {}
    method ProtoReflect (line 601) | func (x *QueryStatsResp) ProtoReflect() protoreflect.Message {
    method Descriptor (line 614) | func (*QueryStatsResp) Descriptor() ([]byte, []int) {
    method GetTraffic (line 618) | func (x *QueryStatsResp) GetTraffic() int64 {
  type UpdateReq (line 625) | type UpdateReq struct
    method Reset (line 634) | func (x *UpdateReq) Reset() {
    method String (line 643) | func (x *UpdateReq) String() string {
    method ProtoMessage (line 647) | func (*UpdateReq) ProtoMessage() {}
    method ProtoReflect (line 649) | func (x *UpdateReq) ProtoReflect() protoreflect.Message {
    method Descriptor (line 662) | func (*UpdateReq) Descriptor() ([]byte, []int) {
    method GetAction (line 666) | func (x *UpdateReq) GetAction() UpdateAction {
    method GetCheckPreRelease (line 673) | func (x *UpdateReq) GetCheckPreRelease() bool {
  type UpdateResp (line 680) | type UpdateResp struct
    method Reset (line 693) | func (x *UpdateResp) Reset() {
    method String (line 702) | func (x *UpdateResp) String() string {
    method ProtoMessage (line 706) | func (*UpdateResp) ProtoMessage() {}
    method ProtoReflect (line 708) | func (x *UpdateResp) ProtoReflect() protoreflect.Message {
    method Descriptor (line 721) | func (*UpdateResp) Descriptor() ([]byte, []int) {
    method GetError (line 725) | func (x *UpdateResp) GetError() string {
    method GetAssetsName (line 732) | func (x *UpdateResp) GetAssetsName() string {
    method GetDownloadUrl (line 739) | func (x *UpdateResp) GetDownloadUrl() string {
    method GetReleaseUrl (line 746) | func (x *UpdateResp) GetReleaseUrl() string {
    method GetReleaseNote (line 753) | func (x *UpdateResp) GetReleaseNote() string {
    method GetIsPreRelease (line 760) | func (x *UpdateResp) GetIsPreRelease() bool {
  type ListConnectionsResp (line 767) | type ListConnectionsResp struct
    method Reset (line 775) | func (x *ListConnectionsResp) Reset() {
    method String (line 784) | func (x *ListConnectionsResp) String() string {
    method ProtoMessage (line 788) | func (*ListConnectionsResp) ProtoMessage() {}
    method ProtoReflect (line 790) | func (x *ListConnectionsResp) ProtoReflect() protoreflect.Message {
    method Descriptor (line 803) | func (*ListConnectionsResp) Descriptor() ([]byte, []int) {
    method GetNekorayConnectionsJson (line 807) | func (x *ListConnectionsResp) GetNekorayConnectionsJson() string {
  function file_libcore_proto_rawDescGZIP (line 939) | func file_libcore_proto_rawDescGZIP() []byte {
  function init (line 988) | func init() { file_libcore_proto_init() }
  function file_libcore_proto_init (line 989) | func file_libcore_proto_init() {

FILE: go/grpc_server/gen/libcore_grpc.pb.go
  constant _ (line 19) | _ = grpc.SupportPackageIsVersion7
  type LibcoreServiceClient (line 24) | type LibcoreServiceClient interface
  type libcoreServiceClient (line 34) | type libcoreServiceClient struct
    method Exit (line 42) | func (c *libcoreServiceClient) Exit(ctx context.Context, in *EmptyReq,...
    method Update (line 51) | func (c *libcoreServiceClient) Update(ctx context.Context, in *UpdateR...
    method Start (line 60) | func (c *libcoreServiceClient) Start(ctx context.Context, in *LoadConf...
    method Stop (line 69) | func (c *libcoreServiceClient) Stop(ctx context.Context, in *EmptyReq,...
    method Test (line 78) | func (c *libcoreServiceClient) Test(ctx context.Context, in *TestReq, ...
    method QueryStats (line 87) | func (c *libcoreServiceClient) QueryStats(ctx context.Context, in *Que...
    method ListConnections (line 96) | func (c *libcoreServiceClient) ListConnections(ctx context.Context, in...
  function NewLibcoreServiceClient (line 38) | func NewLibcoreServiceClient(cc grpc.ClientConnInterface) LibcoreService...
  type LibcoreServiceServer (line 108) | type LibcoreServiceServer interface
  type UnimplementedLibcoreServiceServer (line 120) | type UnimplementedLibcoreServiceServer struct
    method Exit (line 123) | func (UnimplementedLibcoreServiceServer) Exit(context.Context, *EmptyR...
    method Update (line 126) | func (UnimplementedLibcoreServiceServer) Update(context.Context, *Upda...
    method Start (line 129) | func (UnimplementedLibcoreServiceServer) Start(context.Context, *LoadC...
    method Stop (line 132) | func (UnimplementedLibcoreServiceServer) Stop(context.Context, *EmptyR...
    method Test (line 135) | func (UnimplementedLibcoreServiceServer) Test(context.Context, *TestRe...
    method QueryStats (line 138) | func (UnimplementedLibcoreServiceServer) QueryStats(context.Context, *...
    method ListConnections (line 141) | func (UnimplementedLibcoreServiceServer) ListConnections(context.Conte...
    method mustEmbedUnimplementedLibcoreServiceServer (line 144) | func (UnimplementedLibcoreServiceServer) mustEmbedUnimplementedLibcore...
  type UnsafeLibcoreServiceServer (line 149) | type UnsafeLibcoreServiceServer interface
  function RegisterLibcoreServiceServer (line 153) | func RegisterLibcoreServiceServer(s grpc.ServiceRegistrar, srv LibcoreSe...
  function _LibcoreService_Exit_Handler (line 157) | func _LibcoreService_Exit_Handler(srv interface{}, ctx context.Context, ...
  function _LibcoreService_Update_Handler (line 175) | func _LibcoreService_Update_Handler(srv interface{}, ctx context.Context...
  function _LibcoreService_Start_Handler (line 193) | func _LibcoreService_Start_Handler(srv interface{}, ctx context.Context,...
  function _LibcoreService_Stop_Handler (line 211) | func _LibcoreService_Stop_Handler(srv interface{}, ctx context.Context, ...
  function _LibcoreService_Test_Handler (line 229) | func _LibcoreService_Test_Handler(srv interface{}, ctx context.Context, ...
  function _LibcoreService_QueryStats_Handler (line 247) | func _LibcoreService_QueryStats_Handler(srv interface{}, ctx context.Con...
  function _LibcoreService_ListConnections_Handler (line 265) | func _LibcoreService_ListConnections_Handler(srv interface{}, ctx contex...

FILE: go/grpc_server/grpc.go
  type BaseServer (line 25) | type BaseServer struct
    method Exit (line 29) | func (s *BaseServer) Exit(ctx context.Context, in *gen.EmptyReq) (out ...
  function RunCore (line 37) | func RunCore(setupCore func(), server gen.LibcoreServiceServer) {

FILE: go/grpc_server/update.go
  method Update (line 19) | func (s *BaseServer) Update(ctx context.Context, in *gen.UpdateReq) (*ge...

FILE: main/Const.hpp
  type NekoGui (line 3) | namespace NekoGui {
    type DomainMatcher (line 4) | namespace DomainMatcher {
      type DomainMatcher (line 5) | enum DomainMatcher {
    type SniffingMode (line 11) | namespace SniffingMode {
      type SniffingMode (line 12) | enum SniffingMode {
    type CoreType (line 19) | namespace CoreType {
      type CoreType (line 20) | enum CoreType {

FILE: main/HTTPRequestHelper.cpp
  type NekoGui_network (line 11) | namespace NekoGui_network {
    function NekoHTTPResponse (line 13) | NekoHTTPResponse NetworkRequestHelper::HttpGet(const QUrl &url) {
    function QString (line 78) | QString NetworkRequestHelper::GetHeader(const QList<QPair<QByteArray, ...

FILE: main/HTTPRequestHelper.hpp
  type NekoGui_network (line 9) | namespace NekoGui_network {
    type NekoHTTPResponse (line 10) | struct NekoHTTPResponse {
    class NetworkRequestHelper (line 16) | class NetworkRequestHelper : QObject {
      method NetworkRequestHelper (line 19) | NetworkRequestHelper(QObject *parent) : QObject(parent){}

FILE: main/NekoGui.cpp
  type NekoGui_ConfigItem (line 21) | namespace NekoGui_ConfigItem {
    function QString (line 28) | QString JsonStore::_name(void *p) {
    function QJsonObject (line 68) | QJsonObject JsonStore::ToJson(const QStringList &without) {
    function QByteArray (line 104) | QByteArray JsonStore::ToJsonBytes() {
  type NekoGui (line 223) | namespace NekoGui {
    function QString (line 299) | QString DataStore::GetUserAgent(bool isDefault) const {
    function QString (line 351) | QString Routing::DisplayRouting() const {
    function QStringList (line 363) | QStringList Routing::List() {
    function QString (line 386) | QString ExtraCore::Get(const QString &id) const {
    function QString (line 417) | QString FindCoreAsset(const QString &name) {
    function QString (line 435) | QString FindNekoBoxCoreRealPath() {
    function IsAdmin (line 445) | bool IsAdmin() {

FILE: main/NekoGui.hpp
  type NekoGui (line 10) | namespace NekoGui {

FILE: main/NekoGui_ConfigItem.hpp
  type NekoGui_ConfigItem (line 3) | namespace NekoGui_ConfigItem {
    type itemType (line 5) | enum itemType {
    class configItem (line 15) | class configItem {
      method configItem (line 21) | configItem(QString n, void *p, itemType t) {
    class JsonStore (line 29) | class JsonStore {
      method JsonStore (line 42) | JsonStore() = default;
      method JsonStore (line 44) | explicit JsonStore(QString fileName) {

FILE: main/NekoGui_DataStore.hpp
  type NekoGui (line 3) | namespace NekoGui {
    class Routing (line 5) | class Routing : public JsonStore {
    class ExtraCore (line 40) | class ExtraCore : public JsonStore {
    class InboundAuthorization (line 53) | class InboundAuthorization : public JsonStore {
    class DataStore (line 63) | class DataStore : public JsonStore {

FILE: main/NekoGui_Utils.cpp
  function QStringList (line 25) | QStringList SplitLines(const QString &_string) {
  function QStringList (line 33) | QStringList SplitLinesSkipSharp(const QString &_string, int maxLine) {
  function QByteArray (line 45) | QByteArray DecodeB64IfValid(const QString &input, QByteArray::Base64Opti...
  function QString (line 56) | QString QStringList2Command(const QStringList &list) {
  function QString (line 65) | QString GetQueryValue(const QUrlQuery &q, const QString &key, const QStr...
  function QString (line 73) | QString GetRandomString(int randomStringLength) {
  function quint64 (line 89) | quint64 GetRandomUint64() {
  function QJsonObject (line 97) | QJsonObject QString2QJsonObject(const QString &jsonString) {
  function QString (line 104) | QString QJsonObject2QString(const QJsonObject &jsonObject, bool compact) {
  function QJsonArray (line 109) | QJsonArray QList2QJsonArray(const QList<T> &list) {
  function QJsonArray2QListInt (line 119) | QList<int> QJsonArray2QListInt(const QJsonArray &arr) {
  function QJsonArray2QListString (line 126) | QList<QString> QJsonArray2QListString(const QJsonArray &arr) {
  function QByteArray (line 133) | QByteArray ReadFile(const QString &path) {
  function QString (line 139) | QString ReadFileText(const QString &path) {
  function MkPort (line 146) | int MkPort() {
  function QString (line 154) | QString ReadableSize(const qint64 &size) {
  function IsIpAddress (line 176) | bool IsIpAddress(const QString &str) {
  function IsIpAddressV4 (line 183) | bool IsIpAddressV4(const QString &str) {
  function IsIpAddressV6 (line 190) | bool IsIpAddressV6(const QString &str) {
  function QString (line 197) | QString DisplayTime(long long time, int formatType) {
  function QWidget (line 203) | QWidget *GetMessageBoxParent() {
  function MessageBoxWarning (line 212) | int MessageBoxWarning(const QString &title, const QString &text) {
  function MessageBoxInfo (line 216) | int MessageBoxInfo(const QString &title, const QString &text) {
  function ActivateWindow (line 220) | void ActivateWindow(QWidget *w) {
  function runOnUiThread (line 230) | void runOnUiThread(const std::function<void()> &callback, QObject *paren...
  function runOnNewThread (line 248) | void runOnNewThread(const std::function<void()> &callback) {
  function setTimeout (line 252) | void setTimeout(const std::function<void()> &callback, QObject *obj, int...

FILE: main/NekoGui_Utils.hpp
  class QWidget (line 19) | class QWidget
  class QThread (line 28) | class QThread
  class QTimer (line 33) | class QTimer
  function QString (line 45) | inline QString SubStrBefore(QString str, const QString &sub) {
  function QString (line 50) | inline QString SubStrAfter(QString str, const QString &sub) {
  class QUrlQuery (line 67) | class QUrlQuery
  class QJsonObject (line 79) | class QJsonObject
  class QJsonArray (line 80) | class QJsonArray
  function QString (line 117) | inline QString UnwrapIPV6Host(QString &str) {
  function QString (line 122) | inline QString WrapIPV6Host(QString &str) {
  function QString (line 127) | inline QString DisplayAddress(QString serverAddress, int serverPort) {
  function InRange (line 140) | inline bool InRange(unsigned x, unsigned low, unsigned high) {
  function IsValidPort (line 144) | inline bool IsValidPort(int port) {
  function connectOnce (line 165) | inline void connectOnce(EMITTER *emitter, SIGNAL signal, RECEIVER *recei...

FILE: main/main.cpp
  function signal_handler (line 21) | void signal_handler(int signum) {
  function loadTranslate (line 31) | void loadTranslate(const QString& locale) {
  function main (line 53) | int main(int argc, char* argv[]) {

FILE: rpc/gRPC.cpp
  type QtGrpc (line 19) | namespace QtGrpc {
    class NoCache (line 27) | class NoCache : public QAbstractNetworkCache {
      method QNetworkCacheMetaData (line 29) | QNetworkCacheMetaData metaData(const QUrl &url) override {
      method updateMetaData (line 32) | void updateMetaData(const QNetworkCacheMetaData &metaData) override {
      method QIODevice (line 34) | QIODevice *data(const QUrl &url) override {
      method remove (line 37) | bool remove(const QUrl &url) override {
      method qint64 (line 40) | [[nodiscard]] qint64 cacheSize() const override {
      method QIODevice (line 43) | QIODevice *prepare(const QNetworkCacheMetaData &metaData) override {
      method insert (line 46) | void insert(QIODevice *device) override {
      method clear (line 48) | void clear() override {
    class Http2GrpcChannelPrivate (line 52) | class Http2GrpcChannelPrivate {
      method QNetworkReply (line 62) | QNetworkReply *post(const QString &method, const QString &service, c...
      method QByteArray (line 88) | static QByteArray processReply(QNetworkReply *networkReply, QNetwork...
      method call (line 109) | QNetworkReply::NetworkError call(const QString &method, const QStrin...
      method Http2GrpcChannelPrivate (line 142) | Http2GrpcChannelPrivate(const QString &url_, const QString &nekoray_...
      method Call (line 161) | QNetworkReply::NetworkError Call(const QString &methodName,
  type NekoGui_rpc (line 198) | namespace NekoGui_rpc {
    function QString (line 216) | QString Client::Start(bool *rpcOK, const libcore::LoadConfigReq &reque...
    function QString (line 229) | QString Client::Stop(bool *rpcOK) {

FILE: rpc/gRPC.h
  function namespace (line 8) | namespace QtGrpc {
  function namespace (line 12) | namespace NekoGui_rpc {

FILE: sub/GroupUpdater.cpp
  type NekoGui_sub (line 17) | namespace NekoGui_sub {
    function RawUpdater_FixEnt (line 21) | void RawUpdater_FixEnt(const std::shared_ptr<NekoGui::ProxyEntity> &en...
    function QString (line 153) | QString Node2QString(const YAML::Node &n, const QString &def = "") {
    function QStringList (line 162) | QStringList Node2QStringList(const YAML::Node &n) {
    function Node2Int (line 179) | int Node2Int(const YAML::Node &n, const int &def = 0) {
    function Node2Bool (line 188) | bool Node2Bool(const YAML::Node &n, const bool &def = false) {
    function NodeChild (line 203) | YAML::Node NodeChild(const YAML::Node &n, const std::list<std::string>...
  function serialUpdateSubscription (line 627) | void serialUpdateSubscription(const QList<int> &groupsTabOrder, int _ord...
  function UI_update_all_groups (line 657) | void UI_update_all_groups(bool onlyAllowed) {

FILE: sub/GroupUpdater.hpp
  type NekoGui_sub (line 5) | namespace NekoGui_sub {
    class RawUpdater (line 6) | class RawUpdater {
    class GroupUpdater (line 17) | class GroupUpdater : public QObject {

FILE: sys/AutoRun.cpp
  function QString (line 19) | QString Windows_GenAutoRunString() {
  function AutoRun_SetEnabled (line 26) | void AutoRun_SetEnabled(bool enable) {
  function AutoRun_IsEnabled (line 42) | bool AutoRun_IsEnabled() {
  function AutoRun_SetEnabled (line 58) | void AutoRun_SetEnabled(bool enable) {
  function AutoRun_IsEnabled (line 103) | bool AutoRun_IsEnabled() {
  function QString (line 160) | QString getUserAutostartDir_private() {
  function AutoRun_SetEnabled (line 166) | void AutoRun_SetEnabled(bool enable) {
  function AutoRun_IsEnabled (line 225) | bool AutoRun_IsEnabled() {

FILE: sys/ExternalProcess.cpp
  type NekoGui_sys (line 9) | namespace NekoGui_sys {

FILE: sys/ExternalProcess.hpp
  type NekoGui_sys (line 6) | namespace NekoGui_sys {
    class ExternalProcess (line 7) | class ExternalProcess : public QProcess {
    class CoreProcess (line 31) | class CoreProcess : public ExternalProcess {

FILE: sys/linux/LinuxCap.cpp
  function QString (line 9) | QString Linux_GetCapString(const QString &path) {
  function Linux_Pkexec_SetCapString (line 18) | int Linux_Pkexec_SetCapString(const QString &path, const QString &cap) {
  function Linux_HavePkexec (line 27) | bool Linux_HavePkexec() {
  function QString (line 37) | QString Linux_FindCapProgsExec(const QString &name) {

FILE: sys/windows/MiniDump.cpp
  function LONG (line 24) | LONG __stdcall CreateCrashHandler(EXCEPTION_POINTERS *pException) {
  function Windows_SetCrashHandler (line 72) | void Windows_SetCrashHandler() {

FILE: sys/windows/guihelper.cpp
  function Windows_QWidget_SetForegroundWindow (line 9) | void Windows_QWidget_SetForegroundWindow(QWidget *w) {
  function Windows_IsInAdmin (line 20) | bool Windows_IsInAdmin() {

FILE: ui/GroupSort.hpp
  type GroupSortMethod (line 4) | namespace GroupSortMethod {
    type GroupSortMethod (line 5) | enum GroupSortMethod {
  type GroupSortAction (line 15) | struct GroupSortAction {

FILE: ui/Icon.cpp
  function QPixmap (line 7) | QPixmap Icon::GetTrayIcon(Icon::TrayIconStatus status) {
  function QPixmap (line 50) | QPixmap Icon::GetMaterialIcon(const QString &name) {

FILE: ui/Icon.hpp
  type Icon (line 5) | namespace Icon {
    type TrayIconStatus (line 7) | enum TrayIconStatus {

FILE: ui/ThemeManager.hpp
  class ThemeManager (line 3) | class ThemeManager {

FILE: ui/dialog_basic_settings.cpp
  class ExtraCoreWidget (line 17) | class ExtraCoreWidget : public QWidget {
    method ExtraCoreWidget (line 25) | explicit ExtraCoreWidget(QJsonObject *extraCore, const QString &coreNa...

FILE: ui/dialog_basic_settings.h
  function namespace (line 7) | namespace Ui {
  function class (line 11) | class DialogBasicSettings : public QDialog {

FILE: ui/dialog_hotkey.h
  function QT_BEGIN_NAMESPACE (line 6) | QT_BEGIN_NAMESPACE

FILE: ui/dialog_manage_groups.h
  function QT_BEGIN_NAMESPACE (line 10) | QT_BEGIN_NAMESPACE

FILE: ui/dialog_manage_routes.cpp
  function QAction (line 120) | QAction *DialogManageRoutes::schemeToAction(const QString &name, const N...

FILE: ui/dialog_manage_routes.h
  function QT_BEGIN_NAMESPACE (line 9) | QT_BEGIN_NAMESPACE

FILE: ui/dialog_vpn_settings.h
  function QT_BEGIN_NAMESPACE (line 6) | QT_BEGIN_NAMESPACE

FILE: ui/edit/dialog_edit_group.cpp
  function ADJUST_SIZE (line 66) | ADJUST_SIZE

FILE: ui/edit/dialog_edit_group.h
  function QT_BEGIN_NAMESPACE (line 6) | QT_BEGIN_NAMESPACE

FILE: ui/edit/dialog_edit_profile.cpp
  function ADJUST_SIZE (line 323) | ADJUST_SIZE

FILE: ui/edit/dialog_edit_profile.h
  function namespace (line 10) | namespace Ui {
  function class (line 14) | class DialogEditProfile : public QDialog {

FILE: ui/edit/edit_chain.h
  function QT_BEGIN_NAMESPACE (line 6) | QT_BEGIN_NAMESPACE

FILE: ui/edit/edit_custom.h
  function QT_BEGIN_NAMESPACE (line 6) | QT_BEGIN_NAMESPACE

FILE: ui/edit/edit_naive.h
  function QT_BEGIN_NAMESPACE (line 6) | QT_BEGIN_NAMESPACE

FILE: ui/edit/edit_quic.h
  function QT_BEGIN_NAMESPACE (line 8) | QT_BEGIN_NAMESPACE

FILE: ui/edit/edit_shadowsocks.h
  function namespace (line 7) | namespace Ui {

FILE: ui/edit/edit_socks_http.h
  function namespace (line 6) | namespace Ui {

FILE: ui/edit/edit_trojan_vless.h
  function QT_BEGIN_NAMESPACE (line 6) | QT_BEGIN_NAMESPACE

FILE: ui/edit/edit_vmess.h
  function QT_BEGIN_NAMESPACE (line 6) | QT_BEGIN_NAMESPACE

FILE: ui/edit/profile_editor.h
  function class (line 8) | class ProfileEditor {

FILE: ui/mainwindow.cpp
  function UI_InitMainWindow (line 51) | void UI_InitMainWindow() {
  function tabIndex2GroupId (line 457) | inline int tabIndex2GroupId(int index) {
  function groupId2TabIndex (line 462) | inline int groupId2TabIndex(int gid) {
  class W (line 1236) | class W : public QDialog {
    method show_qr (line 1247) | void show_qr(const QSize &size) const {
    method refresh (line 1254) | void refresh(bool is_nk) {
    method W (line 1276) | W(const QString &link_, const QString &link_nk_) {
    method resizeEvent (line 1303) | void resizeEvent(QResizeEvent *resizeEvent) override {
  function FastAppendTextDocument (line 1490) | inline void FastAppendTextDocument(const QString &message, QTextDocument...

FILE: ui/mainwindow.h
  function namespace (line 26) | namespace NekoGui_sys {
  function QT_BEGIN_NAMESPACE (line 30) | QT_BEGIN_NAMESPACE
  function MainWindow (line 202) | inline MainWindow *GetMainWindow() {

FILE: ui/mainwindow_grpc.cpp
  function CreateExtCFromExtR (line 20) | std::list<std::shared_ptr<NekoGui_sys::ExternalProcess>> CreateExtCFromE...

FILE: ui/widget/FloatCheckBox.h
  function class (line 6) | class FloatCheckBox : public QCheckBox {

FILE: ui/widget/GroupItem.cpp
  function QString (line 10) | QString ParseSubInfo(const QString &info) {

FILE: ui/widget/GroupItem.h
  function QT_BEGIN_NAMESPACE (line 8) | QT_BEGIN_NAMESPACE

FILE: ui/widget/MessageBoxTimer.h
  function class (line 6) | class MessageBoxTimer : public QTimer {

FILE: ui/widget/MyLineEdit.h
  function class (line 5) | class MyLineEdit : public QLineEdit {

FILE: ui/widget/MyTableWidget.h
  function class (line 10) | class MyTableWidget : public QTableWidget {
  function _save_order (line 26) | void _save_order(bool saveToFile) {
  function update_order (line 38) | void update_order(bool saveToFile) {

FILE: ui/widget/ProxyItem.cpp
  function QPushButton (line 46) | QPushButton *ProxyItem::get_change_button() {

FILE: ui/widget/ProxyItem.h
  function QT_BEGIN_NAMESPACE (line 8) | QT_BEGIN_NAMESPACE
  function class (line 16) | class ProxyItem : public QWidget {
Condensed preview — 230 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,239K chars).
[
  {
    "path": ".clang-format",
    "chars": 255,
    "preview": "BasedOnStyle: Google\nColumnLimit: 0\nIndentWidth: 4\nSortIncludes: Never\nSpacesBeforeTrailingComments: 1\nNamespaceIndentat"
  },
  {
    "path": ".clang-tidy",
    "chars": 4608,
    "preview": "# Generated from CLion Inspection settings\n---\nChecks: '-*,\nbugprone-argument-comment,\nbugprone-assert-side-effect,\nbugp"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report-en.md",
    "chars": 459,
    "preview": "---\nname: 'Bug Report'\nabout: 'Please troubleshoot server-side issues and upgrade to the latest client before raising a "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report-zh_cn.md",
    "chars": 193,
    "preview": "---\nname: '问题反馈'\nabout: '在提出问题前请先自行排除服务器端问题和升级到最新客户端。'\ntitle: 'BUG: '\nlabels: ''\nassignees: ''\n\n---\n\n## 描述问题\n\n预期行为:\n\n实际行"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request-en.md",
    "chars": 188,
    "preview": "---\nname: 'Feature Request'\nabout: 'Make suggestions for new features of the software'\ntitle: ''\nlabels: ''\nassignees: '"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request-zh_cn.md",
    "chars": 99,
    "preview": "---\nname: '功能请求'\nabout: '对软件的新功能提出建议。'\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n## 描述建议\n\n## 建议的必要性\n"
  },
  {
    "path": ".github/workflows/build-nekoray-cmake.yml",
    "chars": 7875,
    "preview": "name: Nekoray build matrix - cmake\n\non:\n  workflow_dispatch:\n    inputs:\n      tag:\n        description: \"Release Tag\"\n "
  },
  {
    "path": ".github/workflows/update-pkgbuild.yml",
    "chars": 341,
    "preview": "name: AUR CI\non:\n  push:\n    branches:\n      - main\n    paths-ignore:\n      - '**.md'\n      - 'LICENSE'\n      - '!.githu"
  },
  {
    "path": ".gitignore",
    "chars": 863,
    "preview": "# This file is used to ignore files which are generated\n# --------------------------------------------------------------"
  },
  {
    "path": ".gitmodules",
    "chars": 105,
    "preview": "[submodule \"3rdparty/QHotkey\"]\n\tpath = 3rdparty/QHotkey\n\turl = https://github.com/Skycoder42/QHotkey.git\n"
  },
  {
    "path": "3rdparty/QThreadCreateThread.hpp",
    "chars": 1160,
    "preview": "#pragma once\n\n#include <future>\n#include <QThread>\n\n// FOR OLD QT\n\nclass QThreadCreateThread : public QThread {\npublic:\n"
  },
  {
    "path": "3rdparty/QtExtKeySequenceEdit.cpp",
    "chars": 524,
    "preview": "#include \"QtExtKeySequenceEdit.h\"\n\nQtExtKeySequenceEdit::QtExtKeySequenceEdit(QWidget *parent)\n        : QKeySequenceEdi"
  },
  {
    "path": "3rdparty/QtExtKeySequenceEdit.h",
    "chars": 231,
    "preview": "#include <QKeySequenceEdit>\n\nclass QtExtKeySequenceEdit : public QKeySequenceEdit {\npublic:\n    QtExtKeySequenceEdit(QWi"
  },
  {
    "path": "3rdparty/RunGuard.hpp",
    "chars": 2098,
    "preview": "#ifndef RUNGUARD_H\n#define RUNGUARD_H\n\n#include <QObject>\n#include <QSharedMemory>\n#include <QSystemSemaphore>\n#include "
  },
  {
    "path": "3rdparty/VT100Parser.hpp",
    "chars": 418,
    "preview": "#pragma once\n\n#include <QString>\n\ninline QString cleanVT100String(const QString &in) {\n    QString out;\n    bool in_033 "
  },
  {
    "path": "3rdparty/WinCommander.cpp",
    "chars": 3111,
    "preview": "/****************************************************************************\n**\n** Copyright (C) 2014 UpdateNode UG (ha"
  },
  {
    "path": "3rdparty/WinCommander.hpp",
    "chars": 1472,
    "preview": "/****************************************************************************\n**\n** Copyright (C) 2014 UpdateNode UG (ha"
  },
  {
    "path": "3rdparty/ZxingQtReader.hpp",
    "chars": 12938,
    "preview": "/*\n * Copyright 2020 Axel Waggershauser\n */\n// SPDX-License-Identifier: Apache-2.0\n\n#pragma once\n\n#include \"ZXing/ReadBa"
  },
  {
    "path": "3rdparty/base64.cpp",
    "chars": 3811,
    "preview": "#include \"base64.h\"\n\n#ifndef qsizetype\n#define qsizetype size_t\n#endif\n\nnamespace Qt515Base64 {\n    namespace {\n        "
  },
  {
    "path": "3rdparty/base64.h",
    "chars": 1456,
    "preview": "#include <QByteArray>\n\nnamespace Qt515Base64 {\n    enum Base64Option {\n        Base64Encoding = 0,\n        Base64UrlEnco"
  },
  {
    "path": "3rdparty/fix_old_qt.h",
    "chars": 177,
    "preview": "#pragma once\n\n#include <QString>\n\n#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)\n\ninline QString qEnvironmentVariable(const"
  },
  {
    "path": "3rdparty/qrcodegen.cpp",
    "chars": 27322,
    "preview": "/* \n * QR Code generator library (C++)\n * \n * Copyright (c) Project Nayuki. (MIT License)\n * https://www.nayuki.io/page/"
  },
  {
    "path": "3rdparty/qrcodegen.hpp",
    "chars": 20431,
    "preview": "/* \n * QR Code generator library (C++)\n * \n * Copyright (c) Project Nayuki. (MIT License)\n * https://www.nayuki.io/page/"
  },
  {
    "path": "3rdparty/qscopeguard.h",
    "chars": 2938,
    "preview": "/****************************************************************************\n**\n** Copyright (C) 2018 Klarälvdalens Dat"
  },
  {
    "path": "3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp",
    "chars": 16987,
    "preview": "#include \"QvProxyConfigurator.hpp\"\n\n#ifdef Q_OS_WIN\n//\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#i"
  },
  {
    "path": "3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.hpp",
    "chars": 322,
    "preview": "#pragma once\n#include <QHostAddress>\n#include <QObject>\n#include <QString>\n//\nnamespace Qv2ray::components::proxy {\n    "
  },
  {
    "path": "3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.cpp",
    "chars": 6599,
    "preview": "/****************************************************************************\n**\n** Copyright (C) 2016 The Qt Company Lt"
  },
  {
    "path": "3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.hpp",
    "chars": 3481,
    "preview": "/****************************************************************************\n**\n** Copyright (C) 2016 The Qt Company Lt"
  },
  {
    "path": "3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.cpp",
    "chars": 9104,
    "preview": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2011 SCHUTZ Sacha\n *\n * Permission is hereby granted, free of charge, to"
  },
  {
    "path": "3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.hpp",
    "chars": 3438,
    "preview": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2011 SCHUTZ Sacha\n *\n * Permission is hereby granted, free of charge, to"
  },
  {
    "path": "3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.cpp",
    "chars": 3101,
    "preview": "#include \"w_JsonEditor.hpp\"\n\n#include \"main/NekoGui.hpp\"\n\nJsonEditor::JsonEditor(const QJsonObject& rootObject, QWidget*"
  },
  {
    "path": "3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp",
    "chars": 608,
    "preview": "#pragma once\n\n#include \"3rdparty/qv2ray/wrapper.hpp\"\n#include \"3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.hpp\"\n#inc"
  },
  {
    "path": "3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.ui",
    "chars": 4733,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>JsonEditor</class>\n <widget class=\"QDialog\" name=\"Json"
  },
  {
    "path": "3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.cpp",
    "chars": 1323,
    "preview": "#include \"GeositeReader.hpp\"\n\n#include \"3rdparty/qv2ray/wrapper.hpp\"\n#include \"picoproto.hpp\"\n\n#include <QFile>\n#include"
  },
  {
    "path": "3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.hpp",
    "chars": 215,
    "preview": "#pragma once\n\n#include <QString>\n\nnamespace Qv2ray::components::GeositeReader {\n    QStringList ReadGeoSiteFromFile(cons"
  },
  {
    "path": "3rdparty/qv2ray/v3/components/GeositeReader/picoproto.cpp",
    "chars": 21835,
    "preview": "/* Copyright 2016 Pete Warden. All Rights Reserved.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n y"
  },
  {
    "path": "3rdparty/qv2ray/v3/components/GeositeReader/picoproto.hpp",
    "chars": 9559,
    "preview": "/* Copyright 2016 Pete Warden. All Rights Reserved.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n y"
  },
  {
    "path": "3rdparty/qv2ray/wrapper.hpp",
    "chars": 1214,
    "preview": "#pragma once\n\n// Qv2ray wrapper\n\n#include <QJsonDocument>\n#include <QDebug>\n\n#define LOG(...) Qv2ray::base::log_internal"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 8248,
    "preview": "cmake_minimum_required(VERSION 3.5)\n\nproject(nekobox VERSION 0.1 LANGUAGES CXX)\n\nset(CMAKE_INCLUDE_CURRENT_DIR ON)\n\nset("
  },
  {
    "path": "LICENSE",
    "chars": 35149,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "README.md",
    "chars": 3211,
    "preview": "# NekoBox For PC\n\nQt based cross-platform GUI proxy configuration manager (backend: sing-box)\n\nSupport Windows / Linux o"
  },
  {
    "path": "cmake/linux/linux.cmake",
    "chars": 72,
    "preview": "set(PLATFORM_SOURCES sys/linux/LinuxCap.cpp)\nset(PLATFORM_LIBRARIES dl)\n"
  },
  {
    "path": "cmake/myproto.cmake",
    "chars": 355,
    "preview": "find_package(Protobuf CONFIG REQUIRED)\n\nset(PROTO_FILES\n        go/grpc_server/gen/libcore.proto\n        )\n\nadd_library("
  },
  {
    "path": "cmake/nkr.cmake",
    "chars": 341,
    "preview": "# Release\nfile(STRINGS nekoray_version.txt NKR_VERSION)\nadd_compile_definitions(NKR_VERSION=\\\"${NKR_VERSION}\\\")\n\n# Debug"
  },
  {
    "path": "cmake/print.cmake",
    "chars": 1695,
    "preview": "macro(print_all_variables)\n    message(STATUS \"print_all_variables------------------------------------------{\")\n    get_"
  },
  {
    "path": "cmake/windows/VersionInfo.in",
    "chars": 2770,
    "preview": "#pragma once\n\n#ifndef PRODUCT_VERSION_MAJOR\n    #define PRODUCT_VERSION_MAJOR @PRODUCT_VERSION_MAJOR@\n#endif\n\n#ifndef PR"
  },
  {
    "path": "cmake/windows/VersionResource.rc",
    "chars": 1353,
    "preview": "#include \"VersionInfo.h\"\n\n#if defined(__MINGW64__) || defined(__MINGW32__)\n\t// MinGW-w64, MinGW\n\t#if defined(__has_inclu"
  },
  {
    "path": "cmake/windows/generate_product_version.cmake",
    "chars": 4400,
    "preview": "include (CMakeParseArguments)\n\nset (GenerateProductVersionCurrentDir ${CMAKE_CURRENT_LIST_DIR})\n\n# generate_product_vers"
  },
  {
    "path": "cmake/windows/windows.cmake",
    "chars": 825,
    "preview": "set(PLATFORM_SOURCES 3rdparty/WinCommander.cpp sys/windows/guihelper.cpp sys/windows/MiniDump.cpp)\nset(PLATFORM_LIBRARIE"
  },
  {
    "path": "db/ConfigBuilder.cpp",
    "chars": 33205,
    "preview": "#include \"db/ConfigBuilder.hpp\"\n#include \"db/Database.hpp\"\n#include \"fmt/includes.h\"\n#include \"fmt/Preset.hpp\"\n\n#include"
  },
  {
    "path": "db/ConfigBuilder.hpp",
    "chars": 1811,
    "preview": "#pragma once\n\n#include \"ProxyEntity.hpp\"\n#include \"sys/ExternalProcess.hpp\"\n\nnamespace NekoGui {\n    class BuildConfigRe"
  },
  {
    "path": "db/Database.cpp",
    "chars": 13509,
    "preview": "#include \"Database.hpp\"\n\n#include \"fmt/includes.h\"\n\n#include <QFile>\n#include <QDir>\n#include <QColor>\n\nnamespace NekoGu"
  },
  {
    "path": "db/Database.hpp",
    "chars": 1574,
    "preview": "#pragma once\n\n#include \"main/NekoGui.hpp\"\n#include \"ProxyEntity.hpp\"\n#include \"Group.hpp\"\n\nnamespace NekoGui {\n    class"
  },
  {
    "path": "db/Group.hpp",
    "chars": 750,
    "preview": "#pragma once\n\n#include \"main/NekoGui.hpp\"\n#include \"ProxyEntity.hpp\"\n\nnamespace NekoGui {\n    class Group : public JsonS"
  },
  {
    "path": "db/ProfileFilter.cpp",
    "chars": 2974,
    "preview": "#include \"ProfileFilter.hpp\"\n\nnamespace NekoGui {\n\n    QString ProfileFilter_ent_key(const std::shared_ptr<NekoGui::Prox"
  },
  {
    "path": "db/ProfileFilter.hpp",
    "chars": 1197,
    "preview": "#pragma once\n\n#include \"ProxyEntity.hpp\"\n\nnamespace NekoGui {\n    class ProfileFilter {\n    public:\n        static void "
  },
  {
    "path": "db/ProxyEntity.hpp",
    "chars": 2092,
    "preview": "#pragma once\n\n#include \"main/NekoGui.hpp\"\n#include \"db/traffic/TrafficData.hpp\"\n#include \"fmt/AbstractBean.hpp\"\n\nnamespa"
  },
  {
    "path": "db/traffic/TrafficData.hpp",
    "chars": 1184,
    "preview": "#pragma once\n\n#include \"main/NekoGui.hpp\"\n\nnamespace NekoGui_traffic {\n    class TrafficData : public JsonStore {\n    pu"
  },
  {
    "path": "db/traffic/TrafficLooper.cpp",
    "chars": 4220,
    "preview": "#include \"TrafficLooper.hpp\"\n\n#include \"rpc/gRPC.h\"\n#include \"ui/mainwindow_interface.h\"\n\n#include <QThread>\n#include <Q"
  },
  {
    "path": "db/traffic/TrafficLooper.hpp",
    "chars": 685,
    "preview": "#pragma once\n\n#include <QString>\n#include <QList>\n#include <QMutex>\n\n#include \"TrafficData.hpp\"\n\nnamespace NekoGui_traff"
  },
  {
    "path": "docs/Build_Core.md",
    "chars": 359,
    "preview": "## 构建 nekobox_core\n\n### 目录结构\n\n```\n  | nekoray\n  |   go/cmd/*\n  | sing-box-extra\n  | sing-box\n  | ......\n```\n\n### 常规构建\n\n1"
  },
  {
    "path": "docs/Build_Linux.md",
    "chars": 1677,
    "preview": "在 Linux 下编译 Nekoray\n\n## git clone 源码\n\n```\ngit clone https://github.com/MatsuriDayo/nekoray.git --recursive\n```\n\n## 简单编译法"
  },
  {
    "path": "docs/Build_Windows.md",
    "chars": 1221,
    "preview": "在 Windows 下编译 Nekoray\n\n### git clone 源码\n\n```\ngit clone https://github.com/MatsuriDayo/nekoray.git --recursive\n```\n\n### 安"
  },
  {
    "path": "docs/RunFlags.md",
    "chars": 136,
    "preview": "# 运行参数\n\n- `-many` 无视同目录正在运行的实例,强行开启新的实例。\n- `-appdata` 开启后配置文件会指定目录,未指定目录则使用共享目录,无法多开和自动升级。\n- `-flag_reorder` 进行重新整理配置文件的"
  },
  {
    "path": "docs/Run_Linux.md",
    "chars": 1175,
    "preview": "## Linux 安装\n\n### Debian 系发行版\n\n使用 Debian 系发行版时,推荐使用 .deb 包安装:\n\n```shell\nsudo apt install ./nekoray-*-debian-x64.deb\n```\n\n"
  },
  {
    "path": "docs/readme.md",
    "chars": 93,
    "preview": "# 技术文档\n\n# Technical documentation\n\n1. Build GUI: `Build_*.md`\n2. Build Core: `Build_Core.md`\n"
  },
  {
    "path": "fmt/AbstractBean.cpp",
    "chars": 2779,
    "preview": "#include \"includes.h\"\n\n#include <QApplication>\n#include <QHostInfo>\n#include <QUrl>\n\nnamespace NekoGui_fmt {\n    Abstrac"
  },
  {
    "path": "fmt/AbstractBean.hpp",
    "chars": 1576,
    "preview": "#pragma once\n\n#include <QJsonObject>\n#include <QJsonArray>\n\n#include \"main/NekoGui.hpp\"\n\nnamespace NekoGui_fmt {\n    str"
  },
  {
    "path": "fmt/Bean2CoreObj_box.cpp",
    "chars": 8566,
    "preview": "#include \"db/ProxyEntity.hpp\"\n#include \"fmt/includes.h\"\n\nnamespace NekoGui_fmt {\n    void V2rayStreamSettings::BuildStre"
  },
  {
    "path": "fmt/Bean2External.cpp",
    "chars": 10346,
    "preview": "#include \"db/ProxyEntity.hpp\"\n#include \"fmt/includes.h\"\n\n#include <QFile>\n#include <QDir>\n#include <QFileInfo>\n#include "
  },
  {
    "path": "fmt/Bean2Link.cpp",
    "chars": 9167,
    "preview": "#include \"db/ProxyEntity.hpp\"\n#include \"fmt/includes.h\"\n\n#include <QUrlQuery>\n\nnamespace NekoGui_fmt {\n    QString Socks"
  },
  {
    "path": "fmt/ChainBean.hpp",
    "chars": 458,
    "preview": "#pragma once\n\n#include \"main/NekoGui.hpp\"\n\nnamespace NekoGui_fmt {\n    class ChainBean : public AbstractBean {\n    publi"
  },
  {
    "path": "fmt/CustomBean.hpp",
    "chars": 1926,
    "preview": "#pragma once\n\n#include \"fmt/AbstractBean.hpp\"\n\nnamespace NekoGui_fmt {\n    class CustomBean : public AbstractBean {\n    "
  },
  {
    "path": "fmt/Link2Bean.cpp",
    "chars": 12249,
    "preview": "#include \"db/ProxyEntity.hpp\"\n#include \"fmt/includes.h\"\n\n#include <QUrlQuery>\n\nnamespace NekoGui_fmt {\n\n#define DECODE_V"
  },
  {
    "path": "fmt/NaiveBean.hpp",
    "chars": 1496,
    "preview": "#pragma once\n\n#include \"fmt/AbstractBean.hpp\"\n\nnamespace NekoGui_fmt {\n    class NaiveBean : public AbstractBean {\n    p"
  },
  {
    "path": "fmt/Preset.hpp",
    "chars": 1309,
    "preview": "#pragma once\n\nnamespace Preset {\n    namespace SingBox {\n        inline QStringList VpnImplementation = {\"gvisor\", \"syst"
  },
  {
    "path": "fmt/QUICBean.hpp",
    "chars": 4274,
    "preview": "#pragma once\n\n#include \"fmt/AbstractBean.hpp\"\n\nnamespace NekoGui_fmt {\n    class QUICBean : public AbstractBean {\n    pu"
  },
  {
    "path": "fmt/ShadowSocksBean.hpp",
    "chars": 1091,
    "preview": "#pragma once\n\n#include \"fmt/AbstractBean.hpp\"\n#include \"fmt/V2RayStreamSettings.hpp\"\n\nnamespace NekoGui_fmt {\n    class "
  },
  {
    "path": "fmt/SocksHttpBean.hpp",
    "chars": 1274,
    "preview": "#pragma once\n\n#include \"fmt/AbstractBean.hpp\"\n#include \"fmt/V2RayStreamSettings.hpp\"\n\nnamespace NekoGui_fmt {\n    class "
  },
  {
    "path": "fmt/TrojanVLESSBean.hpp",
    "chars": 1114,
    "preview": "#pragma once\n\n#include \"fmt/AbstractBean.hpp\"\n#include \"fmt/V2RayStreamSettings.hpp\"\n\nnamespace NekoGui_fmt {\n    class "
  },
  {
    "path": "fmt/V2RayStreamSettings.hpp",
    "chars": 2686,
    "preview": "#pragma once\n\n#include \"AbstractBean.hpp\"\n\nnamespace NekoGui_fmt {\n    class V2rayStreamSettings : public JsonStore {\n  "
  },
  {
    "path": "fmt/VMessBean.hpp",
    "chars": 957,
    "preview": "#pragma once\n\n#include \"fmt/AbstractBean.hpp\"\n#include \"fmt/V2RayStreamSettings.hpp\"\n\nnamespace NekoGui_fmt {\n    class "
  },
  {
    "path": "fmt/includes.h",
    "chars": 230,
    "preview": "#pragma once\n\n#include \"SocksHttpBean.hpp\"\n#include \"ShadowSocksBean.hpp\"\n#include \"ChainBean.hpp\"\n#include \"VMessBean.h"
  },
  {
    "path": "go/.gitignore",
    "chars": 98,
    "preview": "*.log\n*.pem\n*.json\n*.exe\n*.dat\n/cmd/nekoray_core/nekoray_core\n/cmd/nekobox_core/nekobox_core\n*.db\n"
  },
  {
    "path": "go/cmd/nekobox_core/core_box.go",
    "chars": 1429,
    "preview": "package main\n\nimport (\n\t\"context\"\n\t\"net\"\n\t\"net/http\"\n\n\t\"github.com/matsuridayo/libneko/neko_common\"\n\t\"github.com/matsuri"
  },
  {
    "path": "go/cmd/nekobox_core/go.mod",
    "chars": 4886,
    "preview": "module nekobox_core\n\ngo 1.19\n\nrequire (\n\tgithub.com/matsuridayo/libneko v1.0.0 // replaced\n\tgithub.com/sagernet/sing-box"
  },
  {
    "path": "go/cmd/nekobox_core/go.sum",
    "chars": 28073,
    "preview": "berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw=\nberty.tech/go-libtor v1.0.385/go.mod h1:9s"
  },
  {
    "path": "go/cmd/nekobox_core/grpc_box.go",
    "chars": 3130,
    "preview": "package main\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\n\t\"grpc_server\"\n\t\"grpc_server/gen\"\n\n\t\"github.com/matsuridayo/libneko/"
  },
  {
    "path": "go/cmd/nekobox_core/main.go",
    "chars": 532,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t_ \"unsafe\"\n\n\t\"grpc_server\"\n\n\t\"github.com/matsuridayo/libneko/neko_common\"\n\tboxmain "
  },
  {
    "path": "go/cmd/updater/.gitignore",
    "chars": 19,
    "preview": "/updater\n/launcher\n"
  },
  {
    "path": "go/cmd/updater/go.mod",
    "chars": 260,
    "preview": "module updater\n\ngo 1.18\n\nrequire github.com/codeclysm/extract v2.2.0+incompatible\n\nrequire (\n\tgithub.com/h2non/filetype "
  },
  {
    "path": "go/cmd/updater/go.sum",
    "chars": 1763,
    "preview": "github.com/codeclysm/extract v2.2.0+incompatible h1:q3wyckoA30bhUSiwdQezMqVhwd8+WGE64/GL//LtUhI=\ngithub.com/codeclysm/ex"
  },
  {
    "path": "go/cmd/updater/launcher.go",
    "chars": 147,
    "preview": "//go:build !linux\n\npackage main\n\nimport (\n\t\"log\"\n\t\"runtime\"\n)\n\nfunc Launcher() {\n\tlog.Fatalln(\"launcher is not for your "
  },
  {
    "path": "go/cmd/updater/launcher_linux.go",
    "chars": 879,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n)\n\nvar local_qt_theme bool\n\nfunc Launcher() {\n\tl"
  },
  {
    "path": "go/cmd/updater/main.go",
    "chars": 1260,
    "preview": "package main\n\nimport (\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"time\"\n)\n\nfunc main("
  },
  {
    "path": "go/cmd/updater/msgbox.go",
    "chars": 97,
    "preview": "//go:build !windows\n\npackage main\n\nfunc MessageBoxPlain(title, caption string) int {\n\treturn 0\n}\n"
  },
  {
    "path": "go/cmd/updater/msgbox_windows.go",
    "chars": 569,
    "preview": "package main\n\nimport (\n\t\"syscall\"\n\t\"unsafe\"\n)\n\n// MessageBoxPlain of Win32 API.\nfunc MessageBoxPlain(title, caption stri"
  },
  {
    "path": "go/cmd/updater/updater.go",
    "chars": 2573,
    "preview": "package main\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\n\t\"github.com/codeclysm/extract\"\n)"
  },
  {
    "path": "go/grpc_server/auth/auth.go",
    "chars": 1403,
    "preview": "package auth\n\nimport (\n\t\"context\"\n\n\t\"google.golang.org/grpc/codes\"\n\t\"google.golang.org/grpc/metadata\"\n\t\"google.golang.or"
  },
  {
    "path": "go/grpc_server/fulltest.go",
    "chars": 3794,
    "preview": "package grpc_server\n\nimport (\n\t\"context\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"grpc_server/gen\"\n\t\"io\"\n\t\"log\"\n\t\"math\"\n\t\"net\"\n\t\"net/htt"
  },
  {
    "path": "go/grpc_server/gen/libcore.pb.go",
    "chars": 37703,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.28.1\n// \tprotoc        v4.23.3\n// sou"
  },
  {
    "path": "go/grpc_server/gen/libcore.proto",
    "chars": 1753,
    "preview": "syntax = \"proto3\";\n\npackage libcore;\noption go_package = \"grpc_server/gen\";\n\nservice LibcoreService {\n  rpc Exit(EmptyRe"
  },
  {
    "path": "go/grpc_server/gen/libcore_grpc.pb.go",
    "chars": 11685,
    "preview": "// Code generated by protoc-gen-go-grpc. DO NOT EDIT.\n// versions:\n// - protoc-gen-go-grpc v1.2.0\n// - protoc           "
  },
  {
    "path": "go/grpc_server/gen/update_proto.sh",
    "chars": 223,
    "preview": "protoc -I . --go_out=. --go_opt paths=source_relative --go-grpc_out=. --go-grpc_opt paths=source_relative libcore.proto\n"
  },
  {
    "path": "go/grpc_server/go.mod",
    "chars": 628,
    "preview": "module grpc_server\n\ngo 1.19\n\nrequire (\n\tgithub.com/grpc-ecosystem/go-grpc-middleware v1.3.0\n\tgithub.com/matsuridayo/libn"
  },
  {
    "path": "go/grpc_server/go.sum",
    "chars": 17504,
    "preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0 h1:eOI3/c"
  },
  {
    "path": "go/grpc_server/grpc.go",
    "chars": 2110,
    "preview": "package grpc_server\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"grpc_server/auth\"\n\t\"grpc_server/gen\"\n\t\"log\"\n\t\"net\"\n\t\""
  },
  {
    "path": "go/grpc_server/update.go",
    "chars": 2850,
    "preview": "package grpc_server\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"grpc_server/gen\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"runtime\"\n\t\"string"
  },
  {
    "path": "libs/.gitignore",
    "chars": 17,
    "preview": "/deps*\ndownloaded"
  },
  {
    "path": "libs/build_deps_all.sh",
    "chars": 1510,
    "preview": "#!/bin/bash\nset -e\n\ncd libs\n\n# 参数\nif [ -z $cmake ]; then\n  cmake=\"cmake\"\nfi\nif [ -z $deps ]; then\n  deps=\"deps\"\nfi\n\n# li"
  },
  {
    "path": "libs/build_go.sh",
    "chars": 978,
    "preview": "#!/bin/bash\nset -e\n\nsource libs/env_deploy.sh\n[ \"$GOOS\" == \"windows\" ] && [ \"$GOARCH\" == \"amd64\" ] && DEST=$DEPLOYMENT/w"
  },
  {
    "path": "libs/build_public_res.sh",
    "chars": 610,
    "preview": "#!/bin/bash\nset -e\n\nsource libs/env_deploy.sh\nDEST=$DEPLOYMENT/public_res\nrm -rf $DEST\nmkdir -p $DEST\n\n#### Download geo"
  },
  {
    "path": "libs/deploy_linux64.sh",
    "chars": 1208,
    "preview": "#!/bin/bash\nset -e\n\nsource libs/env_deploy.sh\nDEST=$DEPLOYMENT/linux64\nrm -rf $DEST\nmkdir -p $DEST\n\n#### copy binary ###"
  },
  {
    "path": "libs/deploy_windows64.sh",
    "chars": 558,
    "preview": "#!/bin/bash\nset -e\n\nsource libs/env_deploy.sh\nDEST=$DEPLOYMENT/windows64\nrm -rf $DEST\nmkdir -p $DEST\n\n#### copy exe ####"
  },
  {
    "path": "libs/download_qtsdk_win.sh",
    "chars": 373,
    "preview": "mkdir qtsdk\ncd qtsdk\nif [ \"$DL_QT_VER\" == \"5.15\" ]; then\n  curl -LSO https://github.com/MatsuriDayo/nekoray_qt_runtime/r"
  },
  {
    "path": "libs/env_deploy.sh",
    "chars": 136,
    "preview": "SRC_ROOT=\"$PWD\"\nDEPLOYMENT=\"$SRC_ROOT/deployment\"\nBUILD=\"$SRC_ROOT/build\"\nversion_standalone=\"nekoray-\"$(cat nekoray_ver"
  },
  {
    "path": "libs/env_qtsdk.sh",
    "chars": 271,
    "preview": "echo \"Setting Qt Sdk Dir to\" \"$1\"\nexport Qt5_DIR=\"$1\"\nexport Qt6_DIR=$Qt5_DIR\nexport PATH=$PATH:$Qt5_DIR/bin\nexport LD_L"
  },
  {
    "path": "libs/format_cpp.sh",
    "chars": 94,
    "preview": "#!/bin/sh\ngit ls-files | grep -E \"\\.cpp|\\.h\" | grep -v \"3rdparty\" | xargs -n1 clang-format -i\n"
  },
  {
    "path": "libs/get_source.sh",
    "chars": 597,
    "preview": "#!/bin/bash\nset -e\n\nsource libs/env_deploy.sh\nENV_NEKORAY=1\nsource libs/get_source_env.sh\npushd ..\n\n####\n\nif [ ! -d \"sin"
  },
  {
    "path": "libs/get_source_env.sh",
    "chars": 198,
    "preview": "export COMMIT_SING_BOX=\"06557f6cef23160668122a17a818b378b5a216b5\"\nexport COMMIT_SING_QUIC=\"b49ce60d9b3622d5238fee96bfd3c"
  },
  {
    "path": "libs/package_appimage.sh",
    "chars": 789,
    "preview": "#!/bin/bash\n\nsudo apt-get install fuse -y\n\ncp -r linux64 nekobox.AppDir\n\n# The file for Appimage\n\nrm nekobox.AppDir/laun"
  },
  {
    "path": "libs/package_debian.sh",
    "chars": 1201,
    "preview": "#!/bin/bash\n\nversion=\"$1\"\n\nmkdir -p nekoray/DEBIAN\nmkdir -p nekoray/opt\ncp -r linux64 nekoray/opt/\nmv nekoray/opt/linux6"
  },
  {
    "path": "main/Const.hpp",
    "chars": 443,
    "preview": "#pragma once\n\nnamespace NekoGui {\n    namespace DomainMatcher {\n        enum DomainMatcher {\n            DEFAULT,\n      "
  },
  {
    "path": "main/GuiUtils.hpp",
    "chars": 4263,
    "preview": "#pragma once\n\n// Dialogs\n\n#define Dialog_DialogBasicSettings \"DialogBasicSettings\"\n#define Dialog_DialogEditProfile \"Dia"
  },
  {
    "path": "main/HTTPRequestHelper.cpp",
    "chars": 3464,
    "preview": "#include \"HTTPRequestHelper.hpp\"\n\n#include <QByteArray>\n#include <QNetworkProxy>\n#include <QEventLoop>\n#include <QMetaEn"
  },
  {
    "path": "main/HTTPRequestHelper.hpp",
    "chars": 759,
    "preview": "#pragma once\n\n#include <QNetworkAccessManager>\n#include <QNetworkReply>\n#include <QNetworkRequest>\n#include <QObject>\n#i"
  },
  {
    "path": "main/NekoGui.cpp",
    "chars": 18498,
    "preview": "#include \"NekoGui.hpp\"\n#include \"fmt/Preset.hpp\"\n\n#include <QFile>\n#include <QDir>\n#include <QApplication>\n#include <QFi"
  },
  {
    "path": "main/NekoGui.hpp",
    "chars": 468,
    "preview": "#pragma once\n\n#include \"Const.hpp\"\n#include \"NekoGui_Utils.hpp\"\n#include \"NekoGui_ConfigItem.hpp\"\n#include \"NekoGui_Data"
  },
  {
    "path": "main/NekoGui_ConfigItem.hpp",
    "chars": 1547,
    "preview": "// DO NOT INCLUDE THIS\n\nnamespace NekoGui_ConfigItem {\n    // config 工具\n    enum itemType {\n        string,\n        inte"
  },
  {
    "path": "main/NekoGui_DataStore.hpp",
    "chars": 5131,
    "preview": "// DO NOT INCLUDE THIS\n\nnamespace NekoGui {\n\n    class Routing : public JsonStore {\n    public:\n        QString direct_i"
  },
  {
    "path": "main/NekoGui_Utils.cpp",
    "chars": 7473,
    "preview": "#include \"NekoGui_Utils.hpp\"\n\n#include \"3rdparty/base64.h\"\n#include \"3rdparty/QThreadCreateThread.hpp\"\n\n#include <random"
  },
  {
    "path": "main/NekoGui_Utils.hpp",
    "chars": 4729,
    "preview": "// DO NOT INCLUDE THIS\n\n#include <functional>\n#include <memory>\n#include <QObject>\n#include <QString>\n#include <QDebug>\n"
  },
  {
    "path": "main/main.cpp",
    "chars": 7551,
    "preview": "#include <csignal>\n\n#include <QApplication>\n#include <QDir>\n#include <QTranslator>\n#include <QMessageBox>\n#include <QSta"
  },
  {
    "path": "nekoray_version.txt",
    "chars": 17,
    "preview": "4.0.1-2024-12-12\n"
  },
  {
    "path": "res/dashboard-notice.html",
    "chars": 436,
    "preview": "<html>\n\n<head></head>\n\n<body>\n    <h3>\n        <p>Please put your clash dashboard files to \"./config/dashboard\" dir.</p>"
  },
  {
    "path": "res/neko.css",
    "chars": 58,
    "preview": "QMessageBox {\n    messagebox-text-interaction-flags: 5;\n}\n"
  },
  {
    "path": "res/neko.qrc",
    "chars": 1168,
    "preview": "<RCC>\n    <qresource prefix=\"/\">\n        <file alias=\"icon/b-internet-web-browser.svg\">icon/internet-web-browser.svg</fi"
  },
  {
    "path": "res/theme/feiyangqingyun/qss/blacksoft.css",
    "chars": 15577,
    "preview": "QPalette{background:#444444;}*{outline:0px;color:#DCDCDC;}\n\nQGraphicsView{\nborder:1px solid #242424;\nqproperty-backgroun"
  },
  {
    "path": "res/theme/feiyangqingyun/qss/flatgray.css",
    "chars": 15558,
    "preview": "QPalette{background:#FFFFFF;}*{outline:0px;color:#57595B;}\n\nQGraphicsView{\nborder:1px solid #B6B6B6;\nqproperty-backgroun"
  },
  {
    "path": "res/theme/feiyangqingyun/qss/lightblue.css",
    "chars": 15591,
    "preview": "QPalette{background:#EAF7FF;}*{outline:0px;color:#386487;}\n\nQGraphicsView{\nborder:1px solid #C0DCF2;\nqproperty-backgroun"
  },
  {
    "path": "res/theme/feiyangqingyun/qss.qrc",
    "chars": 4032,
    "preview": "<RCC>\n    <qresource prefix=\"/themes/feiyangqingyun\">\n        <file>qss/flatgray.css</file>\n        <file>qss/lightblue."
  },
  {
    "path": "res/vpn/sing-box-vpn.json",
    "chars": 3785,
    "preview": "{\n    \"log\": {\n        \"level\": \"info\"\n    },\n    \"dns\": {\n        \"fakeip\": {\n            \"enabled\": true,\n            "
  },
  {
    "path": "res/vpn/vpn-run-root.sh",
    "chars": 690,
    "preview": "#!/bin/sh\nset -e\nset -x\n\nif [ \"$EUID\" -ne 0 ]; then\n  echo \"[Warning] Tun script not running as root\"\nfi\n\ncommand -v pki"
  },
  {
    "path": "rpc/gRPC.cpp",
    "chars": 10412,
    "preview": "#include \"gRPC.h\"\n\n#include <utility>\n#include <QStringList>\n\n#ifndef NKR_NO_GRPC\n\n#include \"main/NekoGui.hpp\"\n\n#include"
  },
  {
    "path": "rpc/gRPC.h",
    "chars": 1133,
    "preview": "#pragma once\n\n#ifndef NKR_NO_GRPC\n\n#include \"go/grpc_server/gen/libcore.pb.h\"\n#include <QString>\n\nnamespace QtGrpc {\n   "
  },
  {
    "path": "sub/GroupUpdater.cpp",
    "chars": 28105,
    "preview": "#include \"db/ProfileFilter.hpp\"\n#include \"fmt/includes.h\"\n#include \"fmt/Preset.hpp\"\n#include \"main/HTTPRequestHelper.hpp"
  },
  {
    "path": "sub/GroupUpdater.hpp",
    "chars": 827,
    "preview": "#pragma once\n\n#include \"db/Database.hpp\"\n\nnamespace NekoGui_sub {\n    class RawUpdater {\n    public:\n        void update"
  },
  {
    "path": "sys/AutoRun.cpp",
    "chars": 7914,
    "preview": "#include \"AutoRun.hpp\"\n\n#include <QApplication>\n#include <QDir>\n\n#include \"3rdparty/fix_old_qt.h\"\n#include \"main/NekoGui"
  },
  {
    "path": "sys/AutoRun.hpp",
    "chars": 79,
    "preview": "#pragma once\n\nvoid AutoRun_SetEnabled(bool enable);\n\nbool AutoRun_IsEnabled();\n"
  },
  {
    "path": "sys/ExternalProcess.cpp",
    "chars": 6017,
    "preview": "#include \"ExternalProcess.hpp\"\n#include \"main/NekoGui.hpp\"\n\n#include <QTimer>\n#include <QDir>\n#include <QApplication>\n#i"
  },
  {
    "path": "sys/ExternalProcess.hpp",
    "chars": 1055,
    "preview": "#pragma once\n\n#include <memory>\n#include <QProcess>\n\nnamespace NekoGui_sys {\n    class ExternalProcess : public QProcess"
  },
  {
    "path": "sys/linux/LinuxCap.cpp",
    "chars": 1307,
    "preview": "#include \"LinuxCap.h\"\n\n#include <QDebug>\n#include <QProcess>\n#include <QStandardPaths>\n\n#define EXIT_CODE(p) (p.exitStat"
  },
  {
    "path": "sys/linux/LinuxCap.h",
    "chars": 236,
    "preview": "#pragma once\n\n#include <QString>\n\nQString Linux_GetCapString(const QString &path);\n\nint Linux_Pkexec_SetCapString(const "
  },
  {
    "path": "sys/windows/MiniDump.cpp",
    "chars": 3022,
    "preview": "#include \"MiniDump.h\"\n\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#include <windows.h>\n#include <tch"
  },
  {
    "path": "sys/windows/MiniDump.h",
    "chars": 46,
    "preview": "#pragma once\n\nvoid Windows_SetCrashHandler();\n"
  },
  {
    "path": "sys/windows/guihelper.cpp",
    "chars": 621,
    "preview": "\n#include \"guihelper.h\"\n\n#include <QWidget>\n\n#include <windows.h>\n#include <shlobj.h>\n\nvoid Windows_QWidget_SetForegroun"
  },
  {
    "path": "sys/windows/guihelper.h",
    "chars": 111,
    "preview": "#pragma once\n\nclass QWidget;\n\nvoid Windows_QWidget_SetForegroundWindow(QWidget* w);\n\nbool Windows_IsInAdmin();\n"
  },
  {
    "path": "test/test-qt512-sdk-build.sh",
    "chars": 138,
    "preview": "QT=$PWD/qtsdk/5.12.12/gcc_64\nBUILD=build-sdk-qt512\nrm -rf $BUILD\nmkdir -p $BUILD\ncd $BUILD\ncmake -GNinja -DCMAKE_PREFIX_"
  },
  {
    "path": "test/test-qt6-build.sh",
    "chars": 93,
    "preview": "rm -rf build-qt6\nmkdir -p build-qt6\ncd build-qt6\ncmake -GNinja -DQT_VERSION_MAJOR=6 ..\nninja\n"
  },
  {
    "path": "translations/fa_IR.ts",
    "chars": 52614,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"fa_IR\" sourcelanguage=\"en\">\n<context>\n "
  },
  {
    "path": "translations/ru_RU.ts",
    "chars": 53366,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"ru_RU\">\n<context>\n    <name>DialogBasic"
  },
  {
    "path": "translations/translations.qrc",
    "chars": 159,
    "preview": "<RCC>\n    <qresource prefix=\"/translations\">\n        <file>zh_CN.qm</file>\n        <file>fa_IR.qm</file>\n        <file>r"
  },
  {
    "path": "translations/zh_CN.ts",
    "chars": 47417,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n<TS version=\"2.1\" language=\"zh_CN\">\n<context>\n    <name>DialogBasic"
  },
  {
    "path": "ui/GroupSort.hpp",
    "chars": 418,
    "preview": "#pragma once\n\n// implement in mainwindow\nnamespace GroupSortMethod {\n    enum GroupSortMethod {\n        Raw,\n        ByT"
  },
  {
    "path": "ui/Icon.cpp",
    "chars": 1404,
    "preview": "#include \"Icon.hpp\"\n\n#include \"main/NekoGui.hpp\"\n\n#include <QPainter>\n\nQPixmap Icon::GetTrayIcon(Icon::TrayIconStatus st"
  },
  {
    "path": "ui/Icon.hpp",
    "chars": 272,
    "preview": "#pragma once\n\n#include <QPixmap>\n\nnamespace Icon {\n\n    enum TrayIconStatus {\n        NONE,\n        RUNNING,\n        SYS"
  },
  {
    "path": "ui/ThemeManager.cpp",
    "chars": 2907,
    "preview": "#include <QStyle>\n#include <QApplication>\n#include <QStyleFactory>\n\n#include \"ThemeManager.hpp\"\n\nThemeManager *themeMana"
  },
  {
    "path": "ui/ThemeManager.hpp",
    "chars": 245,
    "preview": "#pragma once\n\nclass ThemeManager {\npublic:\n    QString system_style_name = \"\";\n    QString current_theme = \"0\"; // int: "
  },
  {
    "path": "ui/dialog_basic_settings.cpp",
    "chars": 15490,
    "preview": "#include \"dialog_basic_settings.h\"\n#include \"ui_dialog_basic_settings.h\"\n\n#include \"3rdparty/qv2ray/v2/ui/widgets/editor"
  },
  {
    "path": "ui/dialog_basic_settings.h",
    "chars": 711,
    "preview": "#ifndef DIALOG_BASIC_SETTINGS_H\n#define DIALOG_BASIC_SETTINGS_H\n\n#include <QDialog>\n#include <QJsonObject>\n\nnamespace Ui"
  },
  {
    "path": "ui/dialog_basic_settings.ui",
    "chars": 25296,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>DialogBasicSettings</class>\n <widget class=\"QDialog\" n"
  },
  {
    "path": "ui/dialog_hotkey.cpp",
    "chars": 1103,
    "preview": "#include \"dialog_hotkey.h\"\n#include \"ui_dialog_hotkey.h\"\n\n#include \"ui/mainwindow_interface.h\"\n\nDialogHotkey::DialogHotk"
  },
  {
    "path": "ui/dialog_hotkey.h",
    "chars": 324,
    "preview": "#pragma once\n\n#include <QDialog>\n#include \"main/NekoGui.hpp\"\n\nQT_BEGIN_NAMESPACE\nnamespace Ui {\n    class DialogHotkey;\n"
  },
  {
    "path": "ui/dialog_hotkey.ui",
    "chars": 2963,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>DialogHotkey</class>\n <widget class=\"QDialog\" name=\"Di"
  },
  {
    "path": "ui/dialog_manage_groups.cpp",
    "chars": 1919,
    "preview": "#include \"dialog_manage_groups.h\"\n#include \"ui_dialog_manage_groups.h\"\n\n#include \"db/Database.hpp\"\n#include \"sub/GroupUp"
  },
  {
    "path": "ui/dialog_manage_groups.h",
    "chars": 494,
    "preview": "#pragma once\n\n#include <QWidget>\n#include <QDialog>\n#include <QMenu>\n#include <QTableWidgetItem>\n\n#include \"db/Group.hpp"
  },
  {
    "path": "ui/dialog_manage_groups.ui",
    "chars": 1346,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>DialogManageGroups</class>\n <widget class=\"QDialog\" na"
  },
  {
    "path": "ui/dialog_manage_routes.cpp",
    "chars": 10759,
    "preview": "#include \"dialog_manage_routes.h\"\n#include \"ui_dialog_manage_routes.h\"\n\n#include \"3rdparty/qv2ray/v2/ui/widgets/editors/"
  },
  {
    "path": "ui/dialog_manage_routes.h",
    "chars": 1440,
    "preview": "#pragma once\n\n#include <QDialog>\n#include <QMenu>\n\n#include \"3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.hpp\"\n#include "
  },
  {
    "path": "ui/dialog_manage_routes.ui",
    "chars": 23125,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>DialogManageRoutes</class>\n <widget class=\"QDialog\" na"
  },
  {
    "path": "ui/dialog_vpn_settings.cpp",
    "chars": 3265,
    "preview": "#include \"dialog_vpn_settings.h\"\n#include \"ui_dialog_vpn_settings.h\"\n\n#include \"main/GuiUtils.hpp\"\n#include \"main/NekoGu"
  },
  {
    "path": "ui/dialog_vpn_settings.h",
    "chars": 509,
    "preview": "#ifndef NEKORAY_DIALOG_VPN_SETTINGS_H\n#define NEKORAY_DIALOG_VPN_SETTINGS_H\n\n#include <QDialog>\n\nQT_BEGIN_NAMESPACE\nname"
  },
  {
    "path": "ui/dialog_vpn_settings.ui",
    "chars": 7211,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>DialogVPNSettings</class>\n <widget class=\"QDialog\" nam"
  },
  {
    "path": "ui/edit/dialog_edit_group.cpp",
    "chars": 3556,
    "preview": "#include \"dialog_edit_group.h\"\n#include \"ui_dialog_edit_group.h\"\n\n#include \"db/Database.hpp\"\n#include \"ui/mainwindow_int"
  },
  {
    "path": "ui/edit/dialog_edit_group.h",
    "chars": 587,
    "preview": "#pragma once\n\n#include <QDialog>\n#include \"db/Group.hpp\"\n\nQT_BEGIN_NAMESPACE\nnamespace Ui {\n    class DialogEditGroup;\n}"
  },
  {
    "path": "ui/edit/dialog_edit_group.ui",
    "chars": 6101,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>DialogEditGroup</class>\n <widget class=\"QDialog\" name="
  },
  {
    "path": "ui/edit/dialog_edit_profile.cpp",
    "chars": 18920,
    "preview": "#include \"dialog_edit_profile.h\"\n#include \"ui_dialog_edit_profile.h\"\n\n#include \"ui/edit/edit_socks_http.h\"\n#include \"ui/"
  },
  {
    "path": "ui/edit/dialog_edit_profile.h",
    "chars": 1310,
    "preview": "#ifndef DIALOG_EDIT_PROFILE_H\n#define DIALOG_EDIT_PROFILE_H\n\n#include <QDialog>\n#include \"db/Database.hpp\"\n#include \"pro"
  },
  {
    "path": "ui/edit/dialog_edit_profile.ui",
    "chars": 23018,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>DialogEditProfile</class>\n <widget class=\"QDialog\" nam"
  },
  {
    "path": "ui/edit/edit_chain.cpp",
    "chars": 2157,
    "preview": "#include \"edit_chain.h\"\n#include \"ui_edit_chain.h\"\n\n#include \"ui/mainwindow_interface.h\"\n#include \"ui/widget/ProxyItem.h"
  },
  {
    "path": "ui/edit/edit_chain.h",
    "chars": 663,
    "preview": "#pragma once\n\n#include <QWidget>\n#include \"profile_editor.h\"\n\nQT_BEGIN_NAMESPACE\nnamespace Ui {\n    class EditChain;\n}\nQ"
  },
  {
    "path": "ui/edit/edit_chain.ui",
    "chars": 1415,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>EditChain</class>\n <widget class=\"QWidget\" name=\"EditC"
  },
  {
    "path": "ui/edit/edit_custom.cpp",
    "chars": 5353,
    "preview": "#include \"edit_custom.h\"\n#include \"ui_edit_custom.h\"\n\n#include \"3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp\"\n"
  },
  {
    "path": "ui/edit/edit_custom.h",
    "chars": 612,
    "preview": "#pragma once\n\n#include <QWidget>\n#include \"profile_editor.h\"\n\nQT_BEGIN_NAMESPACE\nnamespace Ui {\n    class EditCustom;\n}\n"
  },
  {
    "path": "ui/edit/edit_custom.ui",
    "chars": 5548,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>EditCustom</class>\n <widget class=\"QWidget\" name=\"Edit"
  },
  {
    "path": "ui/edit/edit_naive.cpp",
    "chars": 1676,
    "preview": "#include \"edit_naive.h\"\n#include \"ui_edit_naive.h\"\n\n#include \"fmt/NaiveBean.hpp\"\n\n#include <QInputDialog>\n\nEditNaive::Ed"
  },
  {
    "path": "ui/edit/edit_naive.h",
    "chars": 727,
    "preview": "#pragma once\n\n#include <QWidget>\n#include \"profile_editor.h\"\n\nQT_BEGIN_NAMESPACE\nnamespace Ui {\n    class EditNaive;\n}\nQ"
  },
  {
    "path": "ui/edit/edit_naive.ui",
    "chars": 3364,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>EditNaive</class>\n <widget class=\"QWidget\" name=\"EditN"
  },
  {
    "path": "ui/edit/edit_quic.cpp",
    "chars": 3763,
    "preview": "#include \"edit_quic.h\"\n#include \"ui_edit_quic.h\"\n\n#include \"fmt/QUICBean.hpp\"\n\n#include <QInputDialog>\n#include <QUuid>\n"
  },
  {
    "path": "ui/edit/edit_quic.h",
    "chars": 694,
    "preview": "#pragma once\n\n#include <QWidget>\n#include <QGridLayout>\n#include <QHBoxLayout>\n#include \"profile_editor.h\"\n\nQT_BEGIN_NAM"
  }
]

// ... and 30 more files (download for full content)

About this extraction

This page contains the full source code of the MatsuriDayo/nekoray GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 230 files (1.1 MB), approximately 322.4k tokens, and a symbol index with 621 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!