10
.github/workflows/aur.yml
vendored
@ -1,7 +1,13 @@
|
||||
name: AUR Test Build
|
||||
name: Build Qv2ray AUR
|
||||
on:
|
||||
push:
|
||||
paths-ignore: [README.md]
|
||||
paths-ignore:
|
||||
- '.github'
|
||||
branches:
|
||||
- master
|
||||
- dev
|
||||
tags:
|
||||
- 'v**'
|
||||
schedule:
|
||||
- cron: "0 19 * * *"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
name: Qv2ray build matrix
|
||||
name: Qv2ray build matrix - cmake
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -9,17 +9,31 @@ jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
qt_version: [5.12.6, 5.13.2, 5.14.1]
|
||||
qt_version: [5.11.3, 5.12.7, 5.13.2, 5.14.2]
|
||||
platform: [ubuntu-16.04, macos-latest, windows-latest]
|
||||
arch: [x86, x64]
|
||||
include:
|
||||
- platform: windows-latest
|
||||
arch: x86
|
||||
qtarch: win32_msvc2017
|
||||
- platform: windows-latest
|
||||
arch: x64
|
||||
qtarch: win64_msvc2017_64
|
||||
exclude:
|
||||
- platform: ubuntu-16.04
|
||||
arch: x86
|
||||
- platform: macos-latest
|
||||
arch: x86
|
||||
- platform: windows-latest
|
||||
qt_version: 5.11.3
|
||||
- platform: windows-latest
|
||||
qt_version: 5.12.7
|
||||
fail-fast: false
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
env:
|
||||
_QV2RAY_BUILD_INFO_: "Qv2ray built from Github Action"
|
||||
_QV2RAY_BUILD_EXTRA_INFO_: "qt${{ matrix.qt_version }}-${{ github.sha }}-ci.${{ matrix.platform }}"
|
||||
|
||||
steps:
|
||||
- name: Get the version
|
||||
@ -28,9 +42,14 @@ jobs:
|
||||
run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)
|
||||
- name: Checking out sources
|
||||
uses: actions/checkout@master
|
||||
- name: Install Python 3.7 version
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: '3.7'
|
||||
architecture: ${{ matrix.arch }}
|
||||
- name: Restoring submodules
|
||||
run: git submodule update --init
|
||||
# --------------------------------------------------------
|
||||
# =========================================================================================================
|
||||
- name: Install MSVC compiler
|
||||
if: matrix.platform == 'windows-latest'
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
@ -38,58 +57,85 @@ jobs:
|
||||
# 14.1 is for vs2017, 14.2 is vs2019, following the upstream vcpkg build from Qv2ray-deps repo
|
||||
toolset: 14.2
|
||||
arch: ${{ matrix.arch }}
|
||||
- name: Cache Qt
|
||||
id: cache-qt
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ../Qt
|
||||
key: QtCache-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.qt_version }}
|
||||
- name: Installing Qt - ${{ matrix.arch }}
|
||||
uses: Qv2ray/install-qt-action@master
|
||||
uses: jurplel/install-qt-action@v2.5.0
|
||||
with:
|
||||
version: ${{ matrix.qt_version }}
|
||||
arch: ${{ matrix.arch }}
|
||||
# --------------------------------------------------------
|
||||
- name: Linux - Install Packages
|
||||
arch: ${{ matrix.qtarch }}
|
||||
mirror: 'http://mirrors.ocf.berkeley.edu/qt/'
|
||||
cached: ${{ steps.cache-qt.outputs.cache-hit }}
|
||||
# =========================================================================================================
|
||||
- name: Linux - ${{ matrix.qt_version }} - Build preparation - Install Packages
|
||||
if: matrix.platform == 'ubuntu-16.04'
|
||||
run: |
|
||||
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
sudo add-apt-repository ppa:webispy/grpc
|
||||
sudo add-apt-repository ppa:carsten-uppenbrink-net/openssl
|
||||
sudo apt update
|
||||
sudo apt install -y gcc-7 libgl-dev openssl libx11-dev libxkbcommon-x11-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler
|
||||
|
||||
- name: macOS - Install Packages
|
||||
if: matrix.platform == 'macos-latest'
|
||||
run: brew install protobuf
|
||||
sudo apt install -y libgl-dev libx11-dev libxkbcommon-x11-dev libssl-dev libprotobuf-dev protobuf-compiler protobuf-c-compiler libgrpc++-dev protobuf-compiler-grpc tree ninja-build
|
||||
# --------------------------------------------------------
|
||||
- name: Cross-platform - Download libraries
|
||||
shell: bash
|
||||
- name: macOS - ${{ matrix.qt_version }} - Build preparation - Install Packages
|
||||
if: matrix.platform == 'macos-latest'
|
||||
run: |
|
||||
curl -o ./libs/libqvb-linux64.a -L https://github.com/Qv2ray/QvRPCBridge/releases/download/v1.1/libqvb-linux64.a
|
||||
curl -o ./libs/libqvb-darwin.a -L https://github.com/Qv2ray/QvRPCBridge/releases/download/v1.1/libqvb-darwin.a
|
||||
curl -o ./libs/Qv2ray-deps-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-${{ matrix.arch }}-windows.7z
|
||||
- name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Extract Windows Dependencies
|
||||
brew install protobuf
|
||||
brew install grpc
|
||||
brew install ninja
|
||||
# --------------------------------------------------------
|
||||
- name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Build preparation - Download Dependencies
|
||||
shell: bash
|
||||
if: matrix.platform == 'windows-latest'
|
||||
run: |
|
||||
choco install -y ninja
|
||||
curl -o ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z -L https://github.com/Qv2ray/Qv2ray-deps/releases/download/release/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z
|
||||
- name: Win-${{ matrix.arch }} - Build preparation - Extract Dependencies
|
||||
if: matrix.platform == 'windows-latest'
|
||||
uses: DuckSoft/extract-7z-action@v1.0
|
||||
with:
|
||||
pathSource: ./libs/Qv2ray-deps-${{ matrix.arch }}-windows.7z
|
||||
pathSource: ./libs/Qv2ray-deps-grpc-${{ matrix.arch }}-windows.7z
|
||||
pathTarget: ./libs
|
||||
# -------------------------------------------------------- Generate MakeFile
|
||||
- name: Cross-platform - ${{ matrix.qt_version }} - Generate Dependencies and Makefile
|
||||
# ========================================================================================================= Generate MakeFile and Build
|
||||
- name: macOS - ${{ matrix.qt_version }} - Generate Dependencies and Build
|
||||
shell: bash
|
||||
if: matrix.platform == 'macos-latest'
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
export _QV2RAY_BUILD_INFO_="Qv2ray built from Github Action"
|
||||
export _QV2RAY_BUILD_EXTRA_INFO_="qt${{ matrix.qt_version }}-${{ github.sha }}"
|
||||
qmake .. CONFIG+="debug_and_release no_increase_build_number" PREFIX=/usr
|
||||
# -------------------------------------------------------- Build
|
||||
- name: Unix - ${{ matrix.qt_version }} - Build Qv2ray
|
||||
if: matrix.platform != 'windows-latest'
|
||||
run: |
|
||||
cd build
|
||||
make -j2 release $([ "${{ matrix.platform }}" == "ubuntu-16.04" ] && echo "CC=gcc-7 CXX=g++-7" LINK="g++-7" || echo "")
|
||||
- name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Build Qv2ray
|
||||
cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build . --parallel $(sysctl -n hw.logicalcpu)
|
||||
sudo cmake --install .
|
||||
sudo chmod -Rv a+rw ./
|
||||
# --------------------------------------------------------
|
||||
- name: Windows - ${{ matrix.qt_version }} - Generate Dependencies and Build
|
||||
shell: bash
|
||||
if: matrix.platform == 'windows-latest'
|
||||
env:
|
||||
CC: cl.exe
|
||||
CXX: cl.exe
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
nmake release
|
||||
# -------------------------------------------------------- Deployments
|
||||
cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./deployment -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build . --parallel $(nproc)
|
||||
cmake --install .
|
||||
# --------------------------------------------------------
|
||||
- name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Build
|
||||
if: matrix.platform == 'ubuntu-16.04'
|
||||
shell: bash
|
||||
env:
|
||||
CC: /usr/bin/gcc-9
|
||||
CXX: /usr/bin/g++-9
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=./AppDir/usr -DCMAKE_BUILD_TYPE=Release -DQV2RAY_TRANSLATION_PATH=QApplication::applicationDirPath\(\)+"/../share/qv2ray/lang"
|
||||
cmake --build . --parallel $(nproc)
|
||||
cmake --install .
|
||||
# ========================================================================================================= Deployments
|
||||
- name: Linux - ${{ matrix.qt_version }} - Generating AppImage
|
||||
if: matrix.platform == 'ubuntu-16.04'
|
||||
run: |
|
||||
@ -97,7 +143,6 @@ jobs:
|
||||
wget https://github.com/probonopd/linuxdeployqt/releases/download/6/linuxdeployqt-6-x86_64.AppImage
|
||||
chmod +x ./linuxdeployqt-6-x86_64.AppImage
|
||||
./linuxdeployqt-6-x86_64.AppImage --appimage-extract
|
||||
make install INSTALL_ROOT=AppDir
|
||||
cd AppDir
|
||||
wget -c https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/AppRun-patched-x86_64 -O AppRun
|
||||
chmod a+x AppRun
|
||||
@ -118,22 +163,19 @@ jobs:
|
||||
path: build/AppDir/Qv2ray.AppImage
|
||||
- name: Linux - ${{ matrix.qt_version }} - Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v1-release
|
||||
if: github.event_name == 'release' && matrix.platform == 'ubuntu-16.04'
|
||||
if: github.event_name == 'release' && matrix.platform == 'ubuntu-16.04' && matrix.qt_version == '5.14.2'
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: build/AppDir/Qv2ray.AppImage
|
||||
asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.linux-${{ matrix.arch }}.qt${{ matrix.qt_version }}.AppImage
|
||||
asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.linux-${{ matrix.arch }}.AppImage
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
# ==
|
||||
# --------------------------------------------------------
|
||||
- name: macOS - ${{ matrix.qt_version }} - Making release tarball
|
||||
if: matrix.platform == 'macos-latest'
|
||||
run: |
|
||||
cd build
|
||||
cd qv2ray.app
|
||||
macdeployqt ./
|
||||
cd ..
|
||||
tar czf Qv2ray.app.tar.gz qv2ray.app
|
||||
tar czvf Qv2ray.app.tar.gz qv2ray.app
|
||||
- name: macOS - ${{ matrix.qt_version }} - Uploading Artifact
|
||||
if: matrix.platform == 'macos-latest'
|
||||
uses: actions/upload-artifact@master
|
||||
@ -142,31 +184,19 @@ jobs:
|
||||
path: build/Qv2ray.app.tar.gz
|
||||
- name: macOS - ${{ matrix.qt_version }} - Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v1-release
|
||||
if: github.event_name == 'release' && matrix.platform == 'macos-latest'
|
||||
if: github.event_name == 'release' && matrix.platform == 'macos-latest' && matrix.qt_version == '5.14.2'
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: build/Qv2ray.app.tar.gz
|
||||
asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.macOS-${{ matrix.arch }}.qt${{ matrix.qt_version }}.tar.gz
|
||||
asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.macOS-${{ matrix.arch }}.tar.gz
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
# ==
|
||||
- name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Copying DLLs to build output folders
|
||||
if: matrix.platform == 'windows-latest'
|
||||
run: .\.github\workflows\copy_DLLs.bat
|
||||
- name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Running windeployqt
|
||||
if: matrix.platform == 'windows-latest'
|
||||
shell: cmd
|
||||
run: |
|
||||
cd build
|
||||
cd release
|
||||
del *.cpp *.h *.o *.qrc *.qm *.hpp *.obj
|
||||
set VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\
|
||||
windeployqt ./qv2ray.exe --compiler-runtime --verbose 2
|
||||
# --------------------------------------------------------
|
||||
- name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Create 7z Release
|
||||
if: matrix.platform == 'windows-latest'
|
||||
uses: DuckSoft/create-7z-action@v1.0
|
||||
with:
|
||||
pathSource: ./build/release/
|
||||
pathSource: ./build/deployment/
|
||||
pathTarget: ./release.7z
|
||||
- name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Uploading artifact
|
||||
if: matrix.platform == 'windows-latest'
|
||||
@ -176,10 +206,10 @@ jobs:
|
||||
path: release.7z
|
||||
- name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v1-release
|
||||
if: github.event_name == 'release' && matrix.platform == 'windows-latest'
|
||||
if: github.event_name == 'release' && matrix.platform == 'windows-latest' && matrix.qt_version == '5.14.2'
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: release.7z
|
||||
asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.Windows-${{ matrix.arch }}.qt${{ matrix.qt_version }}.7z
|
||||
asset_name: Qv2ray.${{ steps.get_version.outputs.VERSION }}.Windows-${{ matrix.arch }}.7z
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
5
.github/workflows/copy_DLLs.bat
vendored
@ -1,5 +0,0 @@
|
||||
@echo off
|
||||
echo Copying DLLs for Windows
|
||||
forfiles /s /p %GITHUB_WORKSPACE%\libs\x86-windows\bin\ /m "*.dll" /c "cmd.exe /c copy @file %GITHUB_WORKSPACE%\build\release\"
|
||||
forfiles /s /p %GITHUB_WORKSPACE%\libs\x64-windows\bin\ /m "*.dll" /c "cmd.exe /c copy @file %GITHUB_WORKSPACE%\build\release\"
|
||||
exit 0
|
4
.gitignore
vendored
@ -1,6 +1,8 @@
|
||||
# Some files
|
||||
.DS_Store
|
||||
*.pro.user
|
||||
*.user
|
||||
.vs/
|
||||
*.qm
|
||||
./.vscode
|
||||
|
||||
@ -11,4 +13,4 @@ libs/x64-windows/
|
||||
libs/x86-windows/
|
||||
libs/libqvb-*
|
||||
|
||||
build/
|
||||
build**/
|
||||
|
9
.gitmodules
vendored
@ -1,9 +1,6 @@
|
||||
[submodule "3rdparty/x2struct"]
|
||||
path = 3rdparty/x2struct
|
||||
url = https://github.com/xyz347/x2struct
|
||||
[submodule "3rdparty/qhttpserver"]
|
||||
path = 3rdparty/qhttpserver
|
||||
url = https://github.com/nikhilm/qhttpserver
|
||||
[submodule "3rdparty/SingleApplication"]
|
||||
path = 3rdparty/SingleApplication
|
||||
url = https://github.com/itay-grudev/SingleApplication
|
||||
@ -16,3 +13,9 @@
|
||||
[submodule "libs/libqvb"]
|
||||
path = libs/libqvb
|
||||
url = https://github.com/Qv2ray/QvRPCBridge
|
||||
[submodule "3rdparty/cpp-httplib"]
|
||||
path = 3rdparty/cpp-httplib
|
||||
url = https://github.com/yhirose/cpp-httplib
|
||||
[submodule "libs/puresource"]
|
||||
path = libs/puresource
|
||||
url = https://github.com/Qv2ray/PureSource/
|
||||
|
14
.travis.yml
@ -1,4 +1,5 @@
|
||||
language: bash
|
||||
language: shell
|
||||
os: linux
|
||||
dist: bionic
|
||||
|
||||
git:
|
||||
@ -15,14 +16,15 @@ env:
|
||||
|
||||
addons:
|
||||
snaps:
|
||||
- name: snapcraft
|
||||
channel: stable
|
||||
confinement: classic
|
||||
- name: lxd
|
||||
channel: stable
|
||||
- name: snapcraft
|
||||
channel: stable
|
||||
confinement: classic
|
||||
- name: lxd
|
||||
channel: stable
|
||||
|
||||
script:
|
||||
- sudo apt autoremove lxd --purge
|
||||
- sudo /snap/bin/lxd waitready
|
||||
- sudo /snap/bin/lxd init --auto
|
||||
- sudo snapcraft --use-lxd
|
||||
|
||||
|
2
3rdparty/QNodeEditor
vendored
@ -1 +1 @@
|
||||
Subproject commit 0f368335943cc8b84a8b52c5ad7cfd9c25ebb6d6
|
||||
Subproject commit c93f1c1826d46d5d60f118688cd830b39af8b9c6
|
2
3rdparty/SingleApplication
vendored
@ -1 +1 @@
|
||||
Subproject commit 0f6695e2a9d8fdaa336e7ad941855c46c61f218a
|
||||
Subproject commit 4abe20afbfa5695ac7a9bce1298943b645aeffe9
|
1
3rdparty/cpp-httplib
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 26deffe0c6a1e177e393416b94cdc0f340ca79bd
|
1
3rdparty/qhttpserver
vendored
@ -1 +0,0 @@
|
||||
Subproject commit 02a6e7174b5be76e2c0e74a109817e39a141b9fd
|
2
3rdparty/qzxing
vendored
@ -1 +1 @@
|
||||
Subproject commit ee50acba1f10e70ef23c593971621ed7a9f4c5a1
|
||||
Subproject commit dac9480a652d591c41ec9ef6f6c966c59a252142
|
382
CMakeLists.txt
Normal file
@ -0,0 +1,382 @@
|
||||
cmake_minimum_required(VERSION 3.10.1)
|
||||
|
||||
file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/VERSION" QV2RAY_VERSION)
|
||||
file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" QV2RAY_BUILD_VERSION)
|
||||
|
||||
if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Release")
|
||||
math(EXPR QV2RAY_BUILD_VERSION "1 + ${QV2RAY_BUILD_VERSION}")
|
||||
message("Increasing BUILDVERSION")
|
||||
file(WRITE "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" ${QV2RAY_BUILD_VERSION})
|
||||
endif()
|
||||
|
||||
set(PACKAGE_VERSION "${QV2RAY_VERSION}.${QV2RAY_BUILD_VERSION}")
|
||||
project(qv2ray)
|
||||
|
||||
set(VERSION_LIST ${PACKAGE_VERSION})
|
||||
string(REPLACE "." ";" VERSION_LIST ${VERSION_LIST})
|
||||
separate_arguments(VERSION_LIST)
|
||||
|
||||
list(GET VERSION_LIST 0 QV2RAY_VERSION_MAJOR)
|
||||
list(GET VERSION_LIST 1 QV2RAY_VERSION_MINOR)
|
||||
list(GET VERSION_LIST 2 QV2RAY_VERSION_BUGFIX)
|
||||
list(GET VERSION_LIST 3 QV2RAY_VERSION_BUILD)
|
||||
|
||||
add_definitions(-DQV2RAY_VERSION_MAJOR=${QV2RAY_VERSION_MAJOR})
|
||||
add_definitions(-DQV2RAY_VERSION_MINOR=${QV2RAY_VERSION_MINOR})
|
||||
add_definitions(-DQV2RAY_VERSION_BUGFIX=${QV2RAY_VERSION_BUGFIX})
|
||||
add_definitions(-DQV2RAY_VERSION_BUILD=${QV2RAY_VERSION_BUILD})
|
||||
|
||||
add_definitions(-DQV2RAY_VERSION_STRING="v${PACKAGE_VERSION}")
|
||||
add_definitions(-DXTOSTRUCT_QT)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt5 COMPONENTS Core Gui Widgets Network REQUIRED)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
cmake_policy(SET CMP0071 NEW)
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS "3.7.0")
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
endif()
|
||||
|
||||
message(" ")
|
||||
message("Qv2ray Version: v${PACKAGE_VERSION}")
|
||||
message("|-------------------------------------------------|")
|
||||
message("| Qv2ray, A Cross Platform v2ray Qt GUI Client. |")
|
||||
message("| Licenced under GPLv3 |")
|
||||
message("| |")
|
||||
message("| You may only use this program to the extent |")
|
||||
message("| permitted by local law. |")
|
||||
message("| |")
|
||||
message("| See: https://www.gnu.org/licenses/gpl-3.0.html |")
|
||||
message("|-------------------------------------------------|")
|
||||
message("| Project Homepage: https://github.com/Qv2ray |")
|
||||
message("| Welcome to contribute! |")
|
||||
message("|-------------------------------------------------|")
|
||||
message(" ")
|
||||
|
||||
if(WIN32)
|
||||
add_compile_options("/std:c++17")
|
||||
add_definitions(-DUNICODE -D_UNICODE)
|
||||
add_definitions(-D_HAS_STD_BYTE=0 -D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS)
|
||||
set(GUI_TYPE WIN32)
|
||||
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
if(CMAKE_CL_64)
|
||||
include(${CMAKE_SOURCE_DIR}/libs/x64-windows/scripts/buildsystems/vcpkg.cmake)
|
||||
else()
|
||||
include(${CMAKE_SOURCE_DIR}/libs/x86-windows/scripts/buildsystems/vcpkg.cmake)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||
endif()
|
||||
|
||||
include(cmake/translations.cmake)
|
||||
include(cmake/qnodeeditor.cmake)
|
||||
include(cmake/singleapplication.cmake)
|
||||
include(cmake/qzxing.cmake)
|
||||
include(cmake/protobuf.cmake)
|
||||
include(cmake/cpp-httplib.cmake)
|
||||
include(cmake/backend.cmake)
|
||||
|
||||
if(QV2RAY_BUILD_INFO)
|
||||
set(_QV2RAY_BUILD_INFO_STR_ "${QV2RAY_BUILD_INFO}")
|
||||
elseif(DEFINED ENV{_QV2RAY_BUILD_INFO_})
|
||||
set(_QV2RAY_BUILD_INFO_STR_ "$ENV{_QV2RAY_BUILD_INFO_}")
|
||||
else()
|
||||
set(_QV2RAY_BUILD_INFO_STR_ "Qv2ray from manual build")
|
||||
endif()
|
||||
|
||||
if(QV2RAY_BUILD_EXTRA_INFO)
|
||||
set(_QV2RAY_BUILD_EXTRA_INFO_STR_ "${QV2RAY_BUILD_EXTRA_INFO}")
|
||||
elseif(DEFINED ENV{_QV2RAY_BUILD_EXTRA_INFO_})
|
||||
set(_QV2RAY_BUILD_EXTRA_INFO_STR_ "$ENV{_QV2RAY_BUILD_EXTRA_INFO_}")
|
||||
else()
|
||||
set(_QV2RAY_BUILD_EXTRA_INFO_STR_ "Qv2ray v${PACKAGE_VERSION}")
|
||||
endif()
|
||||
|
||||
set(QV2RAY_BUILD_INFO ${_QV2RAY_BUILD_INFO_STR_} CACHE STRING "Qv2ray build info")
|
||||
set(QV2RAY_BUILD_EXTRA_INFO ${_QV2RAY_BUILD_EXTRA_INFO_STR_} CACHE STRING "Qv2ray build extra info")
|
||||
|
||||
add_definitions(-D_QV2RAY_BUILD_INFO_STR_="${_QV2RAY_BUILD_INFO_STR_}")
|
||||
add_definitions(-D_QV2RAY_BUILD_EXTRA_INFO_STR_="${_QV2RAY_BUILD_EXTRA_INFO_STR_}")
|
||||
message("Qv2ray build info: ${_QV2RAY_BUILD_INFO_STR_}")
|
||||
message("Qv2ray build info ex: ${_QV2RAY_BUILD_EXTRA_INFO_STR_}")
|
||||
|
||||
set(QV2RAY_DEFAULT_VASSETS_PATH "unset" CACHE STRING "v2ray assets path")
|
||||
set(QV2RAY_DEFAULT_VCORE_PATH "unset" CACHE STRING "v2ray core path")
|
||||
set(QV2RAY_TRANSLATION_PATH "unset" CACHE STRING "Qv2ray translations path")
|
||||
set(QV2RAY_DISABLE_AUTO_UPDATE OFF CACHE BOOL "Disable update checker")
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(QV2RAY_USE_BUILTIN_DARKTHEME OFF CACHE BOOL "Use built-in dark theme instead of followed by the system settings")
|
||||
else()
|
||||
set(QV2RAY_USE_BUILTIN_DARKTHEME ON CACHE BOOL "Use built-in dark theme instead of followed by the system settings")
|
||||
endif()
|
||||
set(EMBED_TRANSLATIONS OFF CACHE BOOL "Embed translations")
|
||||
|
||||
if(QV2RAY_DEFAULT_VASSETS_PATH AND NOT STREQUAL "unset")
|
||||
add_definitions(-DQV2RAY_DEFAULT_VASSETS_PATH="${QV2RAY_DEFAULT_VASSETS_PATH}")
|
||||
endif()
|
||||
|
||||
if(QV2RAY_DEFAULT_VCORE_PATH AND NOT STREQUAL "unset")
|
||||
add_definitions(-DQV2RAY_DEFAULT_VCORE_PATH="${QV2RAY_DEFAULT_VCORE_PATH}")
|
||||
endif()
|
||||
|
||||
if(QV2RAY_TRANSLATION_PATH AND NOT STREQUAL "unset")
|
||||
add_definitions(-DQV2RAY_TRANSLATION_PATH="${QV2RAY_TRANSLATION_PATH}")
|
||||
endif()
|
||||
|
||||
if(QV2RAY_USE_BUILTIN_DARKTHEME)
|
||||
add_definitions(-DQV2RAY_USE_BUILTIN_DARKTHEME=true)
|
||||
endif()
|
||||
|
||||
if(QV2RAY_DISABLE_AUTO_UPDATE)
|
||||
add_definitions(-DDISABLE_AUTO_UPDATE)
|
||||
endif()
|
||||
|
||||
set(QV2RAY_SOURCES
|
||||
src/base/Qv2rayLog.cpp
|
||||
src/common/CommandArgs.cpp
|
||||
src/common/HTTPRequestHelper.cpp
|
||||
src/common/LogHighlighter.cpp
|
||||
src/common/JsonHighlighter.cpp
|
||||
src/common/QJsonModel.cpp
|
||||
src/common/QvHelpers.cpp
|
||||
src/common/QvTranslator.cpp
|
||||
src/components/autolaunch/QvAutoLaunch.cpp
|
||||
src/components/geosite/QvGeositeReader.cpp
|
||||
src/components/icmping/win/ICMPPinger.cpp
|
||||
src/components/pac/QvGFWPACConverter.cpp
|
||||
src/components/pac/QvPACHandler.cpp
|
||||
src/components/plugins/toolbar/QvToolbar.cpp
|
||||
src/components/plugins/toolbar/QvToolbar_linux.cpp
|
||||
src/components/plugins/toolbar/QvToolbar_win.cpp
|
||||
src/components/proxy/QvProxyConfigurator.cpp
|
||||
src/components/speedchart/speedplotview.cpp
|
||||
src/components/speedchart/speedwidget.cpp
|
||||
src/components/darkmode/DarkmodeDetector.cpp
|
||||
src/core/connection/ConnectionIO.cpp
|
||||
src/core/connection/Generation.cpp
|
||||
src/core/connection/Serialization.cpp
|
||||
src/core/connection/Serialization_ss.cpp
|
||||
src/core/connection/Serialization_ssd.cpp
|
||||
src/core/connection/Serialization_vmess.cpp
|
||||
src/core/CoreUtils.cpp
|
||||
src/core/handler/ConfigHandler.cpp
|
||||
src/core/handler/V2rayInstanceHandler.cpp
|
||||
src/core/kernel/APIBackend.cpp
|
||||
src/core/kernel/KernelInteractions.cpp
|
||||
src/core/settings/SettingsBackend.cpp
|
||||
src/core/settings/SettingsUpgrade.cpp
|
||||
src/core/tcping/QvTCPing.cpp
|
||||
src/main.cpp
|
||||
src/ui/editors/w_InboundEditor.cpp
|
||||
src/ui/editors/w_JsonEditor.cpp
|
||||
src/ui/editors/w_OutboundEditor.cpp
|
||||
src/ui/editors/w_RoutesEditor.cpp
|
||||
src/ui/editors/w_RoutesEditor_extra.cpp
|
||||
src/ui/messaging/QvMessageBus.cpp
|
||||
src/ui/models/InboundNodeModel.cpp
|
||||
src/ui/models/OutboundNodeModel.cpp
|
||||
src/ui/models/RuleNodeModel.cpp
|
||||
src/ui/widgets/ConnectionInfoWidget.cpp
|
||||
src/ui/widgets/ConnectionItemWidget.cpp
|
||||
src/ui/widgets/QvAutoCompleteTextEdit.cpp
|
||||
src/ui/widgets/StreamSettingsWidget.cpp
|
||||
src/ui/w_ImportConfig.cpp
|
||||
src/ui/w_MainWindow.cpp
|
||||
src/ui/w_MainWindow_extra.cpp
|
||||
src/ui/w_PreferencesWindow.cpp
|
||||
src/ui/w_ScreenShot_Core.cpp
|
||||
src/ui/w_SubscriptionManager.cpp
|
||||
# ui files
|
||||
src/ui/w_SubscriptionManager.ui
|
||||
src/ui/editors/w_OutboundEditor.ui
|
||||
src/ui/editors/w_InboundEditor.ui
|
||||
src/ui/editors/w_JsonEditor.ui
|
||||
src/ui/editors/w_RoutesEditor.ui
|
||||
src/ui/w_ImportConfig.ui
|
||||
src/ui/widgets/StreamSettingsWidget.ui
|
||||
src/ui/widgets/ConnectionInfoWidget.ui
|
||||
src/ui/widgets/ConnectionItemWidget.ui
|
||||
src/ui/w_MainWindow.ui
|
||||
src/ui/w_PreferencesWindow.ui
|
||||
src/ui/w_ScreenShot_Core.ui
|
||||
# headers
|
||||
src/base/JsonHelpers.hpp
|
||||
src/base/models/CoreObjectModels.hpp
|
||||
src/base/models/QvConfigIdentifier.hpp
|
||||
src/base/models/QvRuntimeConfig.hpp
|
||||
src/base/models/QvSafeType.hpp
|
||||
src/base/models/QvSettingsObject.hpp
|
||||
src/base/models/QvStartupConfig.hpp
|
||||
src/base/Qv2rayBase.hpp
|
||||
src/base/Qv2rayFeatures.hpp
|
||||
src/base/Qv2rayLog.hpp
|
||||
src/common/CommandArgs.hpp
|
||||
src/common/HTTPRequestHelper.hpp
|
||||
src/common/JsonHighlighter.hpp
|
||||
src/common/LogHighlighter.hpp
|
||||
src/common/QJsonModel.hpp
|
||||
src/common/QvHelpers.hpp
|
||||
src/common/QvTranslator.hpp
|
||||
src/components/autolaunch/QvAutoLaunch.hpp
|
||||
src/components/darkmode/DarkmodeDetector.hpp
|
||||
src/components/geosite/QvGeositeReader.hpp
|
||||
src/components/icmping/win/ICMPPinger.hpp
|
||||
src/components/pac/QvPACHandler.hpp
|
||||
src/components/plugins/toolbar/QvToolbar.hpp
|
||||
src/components/proxy/QvProxyConfigurator.hpp
|
||||
src/components/speedchart/speedplotview.hpp
|
||||
src/components/speedchart/speedwidget.hpp
|
||||
src/core/connection/ConnectionIO.hpp
|
||||
src/core/connection/Generation.hpp
|
||||
src/core/connection/Serialization.hpp
|
||||
src/core/CoreSafeTypes.hpp
|
||||
src/core/CoreUtils.hpp
|
||||
src/core/handler/ConfigHandler.hpp
|
||||
src/core/kernel/APIBackend.hpp
|
||||
src/core/kernel/KernelInteractions.hpp
|
||||
src/core/settings/SettingsBackend.hpp
|
||||
src/core/tcping/QvTCPing.hpp
|
||||
src/ui/editors/w_InboundEditor.hpp
|
||||
src/ui/editors/w_JsonEditor.hpp
|
||||
src/ui/editors/w_OutboundEditor.hpp
|
||||
src/ui/editors/w_RoutesEditor.hpp
|
||||
src/ui/messaging/QvMessageBus.hpp
|
||||
src/ui/models/InboundNodeModel.hpp
|
||||
src/ui/models/NodeModelsBase.hpp
|
||||
src/ui/models/OutboundNodeModel.hpp
|
||||
src/ui/models/RuleNodeModel.hpp
|
||||
src/ui/widgets/ConnectionInfoWidget.hpp
|
||||
src/ui/widgets/ConnectionItemWidget.hpp
|
||||
src/ui/widgets/StreamSettingsWidget.hpp
|
||||
src/ui/w_ImportConfig.hpp
|
||||
src/ui/w_MainWindow.hpp
|
||||
src/ui/w_PreferencesWindow.hpp
|
||||
src/ui/w_ScreenShot_Core.hpp
|
||||
src/ui/w_SubscriptionManager.hpp
|
||||
assets/qv2ray.rc
|
||||
)
|
||||
|
||||
if(EMBED_TRANSLATIONS)
|
||||
add_definitions(-DEMBED_TRANSLATIONS)
|
||||
configure_file(translations/translations.qrc ${CMAKE_BINARY_DIR} COPYONLY)
|
||||
list(APPEND QV2RAY_SOURCES ${CMAKE_BINARY_DIR}/translations.qrc)
|
||||
endif()
|
||||
|
||||
add_custom_target(lupdate
|
||||
COMMAND lupdate ${QV2RAY_SOURCES} -ts ${TRANSLATIONS_TS} -no-ui-lines
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
|
||||
set_target_properties(lupdate PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
||||
|
||||
set(QRC_RESOURCES ${CMAKE_SOURCE_DIR}/resources.qrc)
|
||||
|
||||
set(QT_LIBRARY
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
Qt5::Widgets
|
||||
Qt5::Network
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
${GUI_TYPE}
|
||||
${QV2RAY_SOURCES}
|
||||
${QNODEEDITOR_SOURCES}
|
||||
${QNODEEDITOR_QRC_RESOURCES}
|
||||
${SINGLEAPPLICATION_SOURCES}
|
||||
${QZXING_SOURCES}
|
||||
${PROTO_SRCS}
|
||||
${PROTO_HDRS}
|
||||
${API_GRPC_SRCS}
|
||||
${API_PROTO_SRCS}
|
||||
${QRC_RESOURCES}
|
||||
${QM_FILES}
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
${QT_LIBRARY}
|
||||
${QV2RAY_PROTOBUF_LIBRARY}
|
||||
${QV2RAY_BACKEND_LIBRARIES}
|
||||
)
|
||||
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_BINARY_DIR}
|
||||
${QHTTPSERVER_DIR}
|
||||
${QNODEEDITOR_INCLUDE_PATH}
|
||||
${QZXING_INCLUDE_PATH}
|
||||
${SINGLEAPPLICATION_DIR}
|
||||
${Protobuf_INCLUDE_DIRS}
|
||||
${cpp-httplib_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
find_package(Iconv REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
Iconv::Iconv
|
||||
"-framework Carbon"
|
||||
"-framework Cocoa"
|
||||
"-framework Security"
|
||||
)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${Iconv_INCLUDE_DIR}
|
||||
)
|
||||
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR})
|
||||
set(prefix "${PROJECT_NAME}.app/Contents")
|
||||
set(INSTALL_RUNTIME_DIR "${prefix}/MacOS")
|
||||
set(INSTALL_CMAKE_DIR "${prefix}/Resources")
|
||||
|
||||
# Destination paths below are relative to ${CMAKE_INSTALL_PREFIX}
|
||||
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} )
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/assets/Info.plist DESTINATION "${prefix}" )
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/assets/icons/qv2ray.icns DESTINATION "${INSTALL_CMAKE_DIR}" )
|
||||
if(NOT EMBED_TRANSLATIONS)
|
||||
install(FILES ${QM_FILES} DESTINATION ${INSTALL_CMAKE_DIR}/lang)
|
||||
endif()
|
||||
|
||||
# Call macdeployqt
|
||||
install(CODE "execute_process(COMMAND macdeployqt ${PROJECT_NAME}.app)")
|
||||
set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.app")
|
||||
include(cmake/deployment.cmake)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE AND NOT WIN32)
|
||||
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
|
||||
install(FILES assets/qv2ray.metainfo.xml DESTINATION share/metainfo)
|
||||
install(FILES assets/qv2ray.desktop DESTINATION share/applications)
|
||||
install(FILES assets/icons/qv2ray.png DESTINATION share/icons/hicolor/256x256/apps)
|
||||
if(NOT EMBED_TRANSLATIONS)
|
||||
install(FILES ${QM_FILES} DESTINATION share/qv2ray/lang)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(${PROJECT_NAME} wininet wsock32 ws2_32 user32)
|
||||
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION .)
|
||||
if(NOT EMBED_TRANSLATIONS)
|
||||
install(FILES ${QM_FILES} DESTINATION lang)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CL_64)
|
||||
install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libssl-1_1-x64.dll DESTINATION .)
|
||||
install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libcrypto-1_1-x64.dll DESTINATION .)
|
||||
else()
|
||||
install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libssl-1_1.dll DESTINATION .)
|
||||
install(FILES ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libcrypto-1_1.dll DESTINATION .)
|
||||
endif()
|
||||
|
||||
install(CODE "execute_process(COMMAND windeployqt ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe --compiler-runtime --verbose 2)")
|
||||
set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe")
|
||||
include(cmake/deployment.cmake)
|
||||
endif()
|
306
Qv2ray.astylerc
@ -1,306 +0,0 @@
|
||||
# ~/.astylerc
|
||||
#
|
||||
# Courtesy of HN's super_mario: http://news.ycombinator.com/item?id=5348401
|
||||
#
|
||||
|
||||
# Use K&R formatting style
|
||||
style=kr
|
||||
|
||||
# Indent class and struct blocks so that the blocks 'public', 'private' and
|
||||
# 'protected' are indented. This option is effective in C++ files only
|
||||
indent-classes
|
||||
|
||||
# Indent 'switch' blocks so that the 'case X:' statements are indented with
|
||||
# the switch block. The entire case block is indented.
|
||||
#
|
||||
# For example:
|
||||
# switch (foo)
|
||||
# {
|
||||
# case 1:
|
||||
# a += 1;
|
||||
# break;
|
||||
#
|
||||
# case 2:
|
||||
# {
|
||||
# a += 2;
|
||||
# break;
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# becomes
|
||||
#
|
||||
# switch (foo)
|
||||
# {
|
||||
# case 1:
|
||||
# a += 1;
|
||||
# break;
|
||||
#
|
||||
# case 2:
|
||||
# {
|
||||
# a += 2;
|
||||
# break;
|
||||
# }
|
||||
# }
|
||||
indent-switches
|
||||
|
||||
# Indent C++ namespaces (this option has no effect on other file types)
|
||||
# Add extra indentation to namespace blocks.
|
||||
# For example:
|
||||
# namespace foospace
|
||||
# {
|
||||
# class Foo
|
||||
# {
|
||||
# public:
|
||||
# Foo();
|
||||
# virtual ~Foo();
|
||||
# };
|
||||
# }
|
||||
#
|
||||
# becomes
|
||||
#
|
||||
# namespace foospace
|
||||
# {
|
||||
# class Foo
|
||||
# {
|
||||
# public:
|
||||
# Foo();
|
||||
# virtual ~Foo();
|
||||
# };
|
||||
# }
|
||||
indent-namespaces
|
||||
|
||||
# Indent multi line preprocessor definitions ending with a backslash
|
||||
# For example:
|
||||
#
|
||||
# #define Is_Bar(arg,a,b) \
|
||||
# (Is_Foo((arg), (a)) \
|
||||
# || Is_Foo((arg), (b)))
|
||||
#
|
||||
# becomes:
|
||||
#
|
||||
# #define Is_Bar(arg,a,b) \
|
||||
# (Is_Foo((arg), (a)) \
|
||||
# || Is_Foo((arg), (b)))
|
||||
#
|
||||
indent-preprocessor
|
||||
|
||||
# Indent C++ comments beginning in column one.
|
||||
# For example
|
||||
#
|
||||
# void Foo()\n"
|
||||
# {
|
||||
# // comment
|
||||
# if (isFoo)
|
||||
# bar();
|
||||
# }
|
||||
#
|
||||
# becomes:
|
||||
#
|
||||
# void Foo()\n"
|
||||
# {
|
||||
# // comment
|
||||
# if (isFoo)
|
||||
# bar();
|
||||
# }
|
||||
#
|
||||
indent-col1-comments
|
||||
|
||||
# Pad empty lines around header blocks (e.g. 'if', 'for', 'while'...).
|
||||
#
|
||||
# isFoo = true;
|
||||
# if (isFoo) {
|
||||
# bar();
|
||||
# } else {
|
||||
# anotherBar();
|
||||
# }
|
||||
# isBar = false;
|
||||
#
|
||||
# becomes:
|
||||
#
|
||||
# isFoo = true;
|
||||
#
|
||||
# if (isFoo) {
|
||||
# bar();
|
||||
# } else {
|
||||
# anotherBar();
|
||||
# }
|
||||
#
|
||||
# isBar = false;
|
||||
#
|
||||
break-blocks
|
||||
|
||||
# Insert space padding around operators. Any end of line comments will remain
|
||||
# in the original column, if possible. Note that there is no option to unpad.
|
||||
# Once padded, they stay padded.
|
||||
#
|
||||
# if (foo==2)
|
||||
# a=bar((b-c)*a,d--);
|
||||
#
|
||||
# becomes:
|
||||
#
|
||||
# if (foo == 2)
|
||||
# a = bar((b - c) * a, d--);
|
||||
#
|
||||
pad-oper
|
||||
|
||||
|
||||
# Insert space padding after paren headers only (e.g. 'if', 'for', 'while'...).
|
||||
# Any end of line comments will remain in the original column, if possible.
|
||||
# This can be used with unpad-paren to remove unwanted spaces.
|
||||
#
|
||||
# if(isFoo(a, b))
|
||||
# bar(a, b);
|
||||
#
|
||||
# becomes:
|
||||
#
|
||||
# if (isFoo(a, b))
|
||||
# bar(a, b);
|
||||
#
|
||||
pad-header
|
||||
|
||||
# Remove extra space padding around parenthesis on the inside and outside. Any
|
||||
# end of line comments will remain in the original column, if possible. This
|
||||
# option can be used in combination with the paren padding options pad‑paren,
|
||||
# pad‑paren‑out, pad‑paren‑in, and pad‑header above. Only padding that has not
|
||||
# been requested by other options will be removed.
|
||||
#
|
||||
# For example, if a source has parens padded on both the inside and outside,
|
||||
# and you want inside only. You need to use unpad-paren to remove the outside
|
||||
# padding, and pad‑paren‑in to retain the inside padding. Using only
|
||||
# pad‑paren‑in would not remove the outside padding.
|
||||
#
|
||||
# if ( isFoo( a, b ) )
|
||||
# bar ( a, b );
|
||||
#
|
||||
# becomes (with no padding option requested):
|
||||
#
|
||||
# if(isFoo(a, b))
|
||||
# bar(a, b);
|
||||
#
|
||||
unpad-paren
|
||||
|
||||
# Delete empty lines within a function or method. Empty lines outside of
|
||||
# functions or methods are NOT deleted. If used with break-blocks or
|
||||
# break-blocks=all it will delete all lines EXCEPT the lines added by the
|
||||
# break-blocks options.
|
||||
#
|
||||
# void Foo()
|
||||
# {
|
||||
#
|
||||
# foo1 = 1;
|
||||
#
|
||||
# foo2 = 2;
|
||||
#
|
||||
# }
|
||||
#
|
||||
# becomes:
|
||||
#
|
||||
# void Foo()
|
||||
# {
|
||||
# foo1 = 1;
|
||||
# foo2 = 2;
|
||||
# }
|
||||
#
|
||||
delete-empty-lines
|
||||
|
||||
# Attach a pointer or reference operator (* or &) to either the variable type
|
||||
# (left) or variable name (right), or place it between the type and name
|
||||
# (middle). The spacing between the type and name will be preserved, if
|
||||
# possible. To format references separately use the following align-reference
|
||||
# option.
|
||||
#
|
||||
# char *foo1;
|
||||
# char &foo2;
|
||||
#
|
||||
# becomes (with align-pointer=type):
|
||||
#
|
||||
# char* foo1;
|
||||
# char& foo2;
|
||||
#
|
||||
# char* foo1;
|
||||
# char& foo2;
|
||||
#
|
||||
# becomes (with align-pointer=middle):
|
||||
#
|
||||
# char * foo1;
|
||||
# char & foo2;
|
||||
#
|
||||
# char* foo1;
|
||||
# char& foo2;
|
||||
#
|
||||
# becomes (with align-pointer=name):
|
||||
#
|
||||
# char *foo1;
|
||||
# char &foo2;
|
||||
#
|
||||
align-pointer=name
|
||||
|
||||
# Set the minimal indent that is added when a header is built of multiple
|
||||
# lines. This indent helps to easily separate the header from the command
|
||||
# statements that follow. The value for # indicates a number of indents and is
|
||||
# a minimum value. The indent may be greater to align with the data on the
|
||||
# previous line.
|
||||
# The valid values are:
|
||||
# 0 - no minimal indent. The lines will be aligned with the paren on the
|
||||
# preceding line.
|
||||
# 1 - indent at least one additional indent.
|
||||
# 2 - indent at least two additional indents.
|
||||
# 3 - indent at least one-half an additional indent. This is intended for large
|
||||
# indents (e.g. 8).
|
||||
#
|
||||
# The default value is 2, two additional indents.
|
||||
#
|
||||
# // default setting makes this non-bracketed code clear
|
||||
# if (a < b
|
||||
# || c > d)
|
||||
# foo++;
|
||||
#
|
||||
# // but creates an exaggerated indent in this bracketed code
|
||||
# if (a < b
|
||||
# || c > d)
|
||||
# {
|
||||
# foo++;
|
||||
# }
|
||||
#
|
||||
# becomes (when setting --min-conditional-indent=0):
|
||||
#
|
||||
# // setting makes this non-bracketed code less clear
|
||||
# if (a < b
|
||||
# || c > d)
|
||||
# foo++;
|
||||
#
|
||||
# // but makes this bracketed code clearer
|
||||
# if (a < b
|
||||
# || c > d)
|
||||
# {
|
||||
# foo++;
|
||||
# }
|
||||
#
|
||||
min-conditional-indent=0
|
||||
|
||||
# Set the maximum of # spaces to indent a continuation line. The # indicates
|
||||
# a number of columns and must not be greater than 120. If no # is set, the
|
||||
# default value of 40 will be used. A maximum of less than two indent lengths
|
||||
# will be ignored. This option will prevent continuation lines from extending
|
||||
# too far to the right. Setting a larger value will allow the code to be
|
||||
# extended further to the right.
|
||||
#
|
||||
# fooArray[] = { red,
|
||||
# green,
|
||||
# blue };
|
||||
#
|
||||
# fooFunction(barArg1,
|
||||
# barArg2,
|
||||
# barArg3);
|
||||
#
|
||||
# becomes (with larger value):
|
||||
#
|
||||
# fooArray[] = { red,
|
||||
# green,
|
||||
# blue };
|
||||
#
|
||||
# fooFunction(barArg1,
|
||||
# barArg2,
|
||||
# barArg3);
|
||||
#
|
||||
#max-instatement-indent=9
|
168
Qv2ray.pro
@ -1,168 +0,0 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2019-03-28T08:45:32
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui widgets network
|
||||
|
||||
TARGET = qv2ray
|
||||
TEMPLATE = app
|
||||
|
||||
# Now read build number file.
|
||||
QV2RAY_VERSION=$$cat($$PWD/makespec/VERSION)
|
||||
QV2RAY_BUILD_VERSION=$$cat($$PWD/makespec/BUILDVERSION)
|
||||
|
||||
VERSION = $${QV2RAY_VERSION}.$${QV2RAY_BUILD_VERSION}
|
||||
|
||||
message(" ")
|
||||
message("Qv2ray Version: $${VERSION}")
|
||||
message("|-------------------------------------------------|")
|
||||
message("| Qv2ray, A Cross Platform v2ray Qt GUI Client. |")
|
||||
message("| Licenced under GPLv3 |")
|
||||
message("| |")
|
||||
message("| You may only use this program to the extent |")
|
||||
message("| permitted by local law. |")
|
||||
message("| |")
|
||||
message("| See: https://www.gnu.org/licenses/gpl-3.0.html |")
|
||||
message("|-------------------------------------------------|")
|
||||
message("| Project Homepage: https://github.com/Qv2ray |")
|
||||
message("| Welcome to contribute! |")
|
||||
message("|-------------------------------------------------|")
|
||||
message(" ")
|
||||
|
||||
# Distinguish debug and release builds.
|
||||
CONFIG(release, debug|release) {
|
||||
CONFIG+=Qv2ray_release no_increase_build_number
|
||||
}
|
||||
CONFIG(debug, debug|release) {
|
||||
CONFIG+=Qv2ray_debug
|
||||
}
|
||||
|
||||
# Qv2ray basic configuration
|
||||
CONFIG += qt c++17 openssl-linked
|
||||
include($$PWD/makespec/00-deps.pri)
|
||||
|
||||
# lrelease will not work when adding BEFORE 00-deps.pri
|
||||
CONFIG += lrelease embed_translations
|
||||
DEFINES += QT_DEPRECATED_WARNINGS QV2RAY_VERSION_STRING=\"\\\"v$${VERSION}\\\"\" QAPPLICATION_CLASS=QApplication
|
||||
|
||||
# Source file parser
|
||||
include($$PWD/makespec/01-sourcesparser.pri)
|
||||
|
||||
# Main config
|
||||
Qv2rayAddSource(base, _, GlobalInstances, hpp)
|
||||
Qv2rayAddSource(base, _, JsonHelpers, hpp)
|
||||
Qv2rayAddSource(base, _, Qv2rayBase, hpp)
|
||||
Qv2rayAddSource(base, _, Qv2rayFeatures, hpp)
|
||||
Qv2rayAddSource(base, _, Qv2rayLog, cpp, hpp)
|
||||
Qv2rayAddSource(base, models, CoreObjectModels, hpp)
|
||||
Qv2rayAddSource(base, models, QvConfigModel, hpp)
|
||||
Qv2rayAddSource(base, models, QvConfigIdentifier, hpp)
|
||||
Qv2rayAddSource(base, models, QvSafeType, hpp)
|
||||
Qv2rayAddSource(base, models, QvRuntimeConfig, hpp)
|
||||
Qv2rayAddSource(base, models, QvStartupConfig, hpp)
|
||||
Qv2rayAddSource(common, _, CommandArgs, cpp, hpp)
|
||||
Qv2rayAddSource(common, _, HTTPRequestHelper, cpp, hpp)
|
||||
Qv2rayAddSource(common, _, LogHighlighter, cpp, hpp)
|
||||
Qv2rayAddSource(common, _, QJsonModel, cpp, hpp)
|
||||
Qv2rayAddSource(common, _, QvHelpers, cpp, hpp)
|
||||
Qv2rayAddSource(common, _, QvTranslator, hpp)
|
||||
Qv2rayAddSource(components, autolaunch, QvAutoLaunch, cpp, hpp)
|
||||
Qv2rayAddSource(components, pac, QvGFWPACConverter, cpp)
|
||||
Qv2rayAddSource(components, pac, QvPACHandler, cpp, hpp)
|
||||
Qv2rayAddSource(components, plugins/toolbar, QvToolbar, cpp, hpp)
|
||||
Qv2rayAddSource(components, plugins/toolbar, QvToolbar_linux, cpp)
|
||||
Qv2rayAddSource(components, plugins/toolbar, QvToolbar_win, cpp)
|
||||
Qv2rayAddSource(components, proxy, QvProxyConfigurator, cpp, hpp)
|
||||
Qv2rayAddSource(components, tcping, QvTCPing, cpp, hpp)
|
||||
Qv2rayAddSource(components, speedchart, speedwidget, cpp, hpp)
|
||||
Qv2rayAddSource(components, speedchart, speedplotview, cpp, hpp)
|
||||
Qv2rayAddSource(components, geosite, QvGeositeReader, cpp, hpp)
|
||||
Qv2rayAddSource(core, config, ConfigBackend, cpp, hpp)
|
||||
Qv2rayAddSource(core, config, ConfigUpgrade, cpp)
|
||||
Qv2rayAddSource(core, connection, ConnectionIO, cpp, hpp)
|
||||
Qv2rayAddSource(core, connection, Generation, cpp, hpp)
|
||||
Qv2rayAddSource(core, connection, Serialization, cpp, hpp)
|
||||
Qv2rayAddSource(core, _, CoreUtils, cpp, hpp)
|
||||
Qv2rayAddSource(core, kernel, KernelInteractions, cpp, hpp)
|
||||
Qv2rayAddSource(core, kernel, APIBackend, cpp, hpp)
|
||||
Qv2rayAddSource(ui, editors, w_InboundEditor, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, editors, w_JsonEditor, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, editors, w_OutboundEditor, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, editors, w_RoutesEditor, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, editors, w_RoutesEditor_extra, cpp)
|
||||
Qv2rayAddSource(ui, nodemodels, InboundNodeModel, cpp, hpp)
|
||||
Qv2rayAddSource(ui, nodemodels, OutboundNodeModel, cpp, hpp)
|
||||
Qv2rayAddSource(ui, nodemodels, RuleNodeModel, cpp, hpp)
|
||||
Qv2rayAddSource(ui, nodemodels, NodeModelsBase, hpp)
|
||||
Qv2rayAddSource(ui, messaging, QvMessageBus, cpp, hpp)
|
||||
Qv2rayAddSource(ui, _, w_ExportConfig, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, _, w_ImportConfig, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, _, w_MainWindow, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, _, w_MainWindow_extra, cpp)
|
||||
Qv2rayAddSource(ui, _, w_PreferencesWindow, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, _, w_ScreenShot_Core, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, _, w_SubscriptionManager, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, widgets, StreamSettingsWidget, cpp, hpp, ui)
|
||||
|
||||
SOURCES += $$PWD/src/main.cpp
|
||||
HEADERS +=
|
||||
FORMS +=
|
||||
INCLUDEPATH += $$PWD/src
|
||||
RESOURCES += $$PWD/resources.qrc
|
||||
ICON = $$PWD/assets/icons/qv2ray.icns
|
||||
RC_ICONS += $$PWD/assets/icons/qv2ray.ico
|
||||
|
||||
include($$PWD/makespec/02-translations.pri)
|
||||
|
||||
unix {
|
||||
include($$PWD/makespec/03-unix.pri)
|
||||
# Sub-process of Qv2ray per-OS build
|
||||
!macx: include($$PWD/makespec/04-unix-linux.pri)
|
||||
macx: include($$PWD/makespec/04-unix-macOS.pri)
|
||||
} else {
|
||||
include($$PWD/makespec/03-Windows.pri)
|
||||
}
|
||||
|
||||
# ------------------------------------------ Begin checking protobuf domain list headers.
|
||||
!exists($$PWD/libs/gen/v2ray_geosite.pb.cc) || !exists($$PWD/libs/gen/v2ray_geosite.pb.cc) {
|
||||
Qv2rayQMakeError("Protobuf headers for v2ray geosite is missing.")
|
||||
}
|
||||
|
||||
SOURCES += $$PWD/libs/gen/v2ray_geosite.pb.cc
|
||||
HEADERS += $$PWD/libs/gen/v2ray_geosite.pb.h
|
||||
|
||||
# General header and source files for gRPC and libQvb
|
||||
message(" ")
|
||||
use_grpc {
|
||||
DEFINES += WITH_LIB_GRPCPP
|
||||
message("Qv2ray will use gRPC as API backend")
|
||||
|
||||
!exists($$PWD/libs/gen/v2ray_api.grpc.pb.h) || !exists($$PWD/libs/gen/v2ray_api.grpc.pb.cc) || !exists($$PWD/libs/gen/v2ray_api.pb.h) || !exists($$PWD/libs/gen/v2ray_api.pb.cc) {
|
||||
Qv2rayQMakeError("gRPC and protobuf headers for v2ray API is missing.")
|
||||
}
|
||||
|
||||
SOURCES += $$PWD/libs/gen/v2ray_api.pb.cc $$PWD/libs/gen/v2ray_api.grpc.pb.cc
|
||||
HEADERS += $$PWD/libs/gen/v2ray_api.pb.h $$PWD/libs/gen/v2ray_api.grpc.pb.h
|
||||
} else {
|
||||
message("Qv2ray will use libqvb as API backend")
|
||||
!exists($$PWD/libs/libqvb/build/libqvb.h) {
|
||||
Qv2rayQMakeError("libs/libqvb/build/libqvb.h is missing.")
|
||||
}
|
||||
HEADERS += $$PWD/libs/libqvb/build/libqvb.h
|
||||
}
|
||||
|
||||
# Misc steps to build Qv2ray.
|
||||
include($$PWD/makespec/99-others.pri)
|
||||
|
||||
message(" ")
|
||||
message("This Qv2ray build contains: ")
|
||||
message(" --> $${size(SOURCES)} source files")
|
||||
message(" --> $${size(HEADERS)} header files")
|
||||
message(" --> $${size(FORMS)} ui files")
|
||||
message(" --> $${size(TRANSLATIONS)} translation files")
|
||||
message(" --> $${size(EXTRA_TRANSLATIONS)} extra translation files")
|
||||
message(" ")
|
||||
message("Finished configuring Qv2ray project. Build output will be at:" $$OUT_PWD)
|
||||
message("Type 'make' or 'nmake' to start building Qv2ray")
|
50
_clang-format
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
BasedOnStyle: Microsoft
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: Inline
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BreakBeforeBraces: Allman
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakInheritanceList: BeforeComma
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 145
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
Cpp11BracedListStyle: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
IncludeBlocks: Regroup
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: BeforeHash
|
||||
IndentWidth: 4
|
||||
Language: Cpp
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: All
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpacesInParentheses: false
|
||||
Standard: Cpp11
|
||||
StatementMacros: [ Q_UNUSED LOG DEBUG ]
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
|
||||
...
|
BIN
assets/icons/ui_dark/connect.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
1
assets/icons/ui_dark/design/locate.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg t="1583066988697" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7967" width="128" height="128"><path d="M524.474182 1024l-24.901818 0-6.958545-10.053818C481.652364 998.097455 223.837091 624.407273 187.485091 540.974545c-37.026909-84.968727-43.52-110.917818-43.52-173.428364C143.965091 164.864 308.852364 0 511.511273 0c203.682909 0 368.546909 164.864 368.546909 367.546182 0 62.533818-6.493091 88.459636-43.52 173.428364-36.375273 83.432727-294.144 457.099636-305.082182 472.971636L524.474182 1024zM512.512 46.545455C334.498909 46.545455 190.510545 190.557091 190.510545 367.546182c0 56.064 4.817455 74.891636 39.656727 154.833455 29.090909 66.792727 220.485818 348.020364 281.856 437.620364C573.416727 870.4 764.741818 589.172364 793.832727 522.379636c34.839273-79.965091 39.656727-98.769455 39.656727-154.833455C833.489455 190.557091 689.501091 46.545455 512.512 46.545455z" p-id="7968" fill="#e6e6e6"></path><path d="M512 565.364364c-93.835636 0-170.193455-76.334545-170.193455-170.193455S418.164364 225.000727 512 225.000727s170.193455 76.334545 170.193455 170.193455S605.835636 565.364364 512 565.364364zM512 271.546182c-68.189091 0-123.648 55.458909-123.648 123.648S443.810909 518.818909 512 518.818909s123.648-55.458909 123.648-123.648S580.189091 271.546182 512 271.546182z" p-id="7969" fill="#e6e6e6"></path></svg>
|
After Width: | Height: | Size: 1.3 KiB |
1
assets/icons/ui_dark/design/sort.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1583165428350" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2286" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M128 553.984l0-84.010667 512 0 0 84.010667-512 0zM128 256l768 0 0 86.016-768 0 0-86.016zM128 768l0-86.016 256 0 0 86.016-256 0z" p-id="2287" fill="#e6e6e6"></path></svg>
|
After Width: | Height: | Size: 546 B |
@ -17,8 +17,8 @@
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14"
|
||||
sodipodi:docname="Qv2ray_System_Tray_Light.svg"
|
||||
inkscape:export-filename="/home/axionl/Desktop/Qv2ray_Design/qv2ray.png"
|
||||
sodipodi:docname="tray.svg"
|
||||
inkscape:export-filename=""
|
||||
inkscape:export-xdpi="558.54999"
|
||||
inkscape:export-ydpi="558.54999">
|
||||
<defs
|
||||
@ -171,17 +171,17 @@
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="22.627417"
|
||||
inkscape:cx="5.9585184"
|
||||
inkscape:cx="-1.0241611"
|
||||
inkscape:cy="11.144438"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1874"
|
||||
inkscape:window-height="1050"
|
||||
inkscape:window-x="46"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-width="1316"
|
||||
inkscape:window-height="814"
|
||||
inkscape:window-x="270"
|
||||
inkscape:window-y="90"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
@ -271,7 +271,7 @@
|
||||
<path
|
||||
id="path1962"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,1.9173392,290.74464)"
|
||||
style="fill:#f2f2f2;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
style="fill:#e6e6e6;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 7,11 6.2929688,11.707031 8.5859375,14 H 18 V 13 H 9 Z M 6.2929688,11.707031 5,13 H 4 v 1 H 5.4140625 L 7,12.414062 Z M 3,3 V 18.999988 H 19 V 3 Z M 3.9999999,3.9999875 H 18 V 18 H 3.9999999 Z" />
|
||||
<rect
|
||||
style="opacity:0.5;fill:none;fill-opacity:1;stroke:none;stroke-width:0.04583338;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
@ -283,7 +283,7 @@
|
||||
inkscape:export-xdpi="64"
|
||||
inkscape:export-ydpi="64" />
|
||||
<path
|
||||
style="fill:#f2f2f2;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
style="fill:#ececec;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 4.5631726,292.06756 -0.2645834,0.26459 v 0.52916 l 0.2645834,-0.26458 v 0.26458 0.52917 l 0.5291666,0.79375 0.5291667,1.32291 v -0.79374 l 0.2645833,-0.26459 -0.2645833,-0.52916 v -0.79375 l -0.2645833,-0.52917 z"
|
||||
id="path1934"
|
||||
inkscape:connector-curvature="0"
|
||||
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
BIN
assets/icons/ui_dark/locate.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
assets/icons/ui_dark/sort.png
Normal file
After Width: | Height: | Size: 304 B |
BIN
assets/icons/ui_dark/stop.png
Normal file
After Width: | Height: | Size: 508 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
assets/icons/ui_light/connect.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
1
assets/icons/ui_light/design/locate.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg t="1583066988697" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7967" width="128" height="128"><path d="M524.474182 1024l-24.901818 0-6.958545-10.053818C481.652364 998.097455 223.837091 624.407273 187.485091 540.974545c-37.026909-84.968727-43.52-110.917818-43.52-173.428364C143.965091 164.864 308.852364 0 511.511273 0c203.682909 0 368.546909 164.864 368.546909 367.546182 0 62.533818-6.493091 88.459636-43.52 173.428364-36.375273 83.432727-294.144 457.099636-305.082182 472.971636L524.474182 1024zM512.512 46.545455C334.498909 46.545455 190.510545 190.557091 190.510545 367.546182c0 56.064 4.817455 74.891636 39.656727 154.833455 29.090909 66.792727 220.485818 348.020364 281.856 437.620364C573.416727 870.4 764.741818 589.172364 793.832727 522.379636c34.839273-79.965091 39.656727-98.769455 39.656727-154.833455C833.489455 190.557091 689.501091 46.545455 512.512 46.545455z" p-id="7968" fill="#515151"></path><path d="M512 565.364364c-93.835636 0-170.193455-76.334545-170.193455-170.193455S418.164364 225.000727 512 225.000727s170.193455 76.334545 170.193455 170.193455S605.835636 565.364364 512 565.364364zM512 271.546182c-68.189091 0-123.648 55.458909-123.648 123.648S443.810909 518.818909 512 518.818909s123.648-55.458909 123.648-123.648S580.189091 271.546182 512 271.546182z" p-id="7969" fill="#515151"></path></svg>
|
After Width: | Height: | Size: 1.3 KiB |
1
assets/icons/ui_light/design/sort.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1583165428350" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2286" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M128 553.984l0-84.010667 512 0 0 84.010667-512 0zM128 256l768 0 0 86.016-768 0 0-86.016zM128 768l0-86.016 256 0 0 86.016-256 0z" p-id="2287" fill="#2c2c2c"></path></svg>
|
After Width: | Height: | Size: 546 B |
BIN
assets/icons/ui_light/locate.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
assets/icons/ui_light/sort.png
Normal file
After Width: | Height: | Size: 303 B |
BIN
assets/icons/ui_light/stop.png
Normal file
After Width: | Height: | Size: 511 B |
26
assets/info.plist
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>qv2ray</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>Created by Qv2ray development team</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>qv2ray.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.qv2ray.qv2ray</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.12</string>
|
||||
<key>NOTE</key>
|
||||
<string>Qv2ray</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
48
assets/qv2ray.rc
Normal file
@ -0,0 +1,48 @@
|
||||
#ifdef _WIN32
|
||||
#include <WINDOWS.H>
|
||||
#include <WINGDI.H>
|
||||
#include <WINUSER.H>
|
||||
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
|
||||
#define VER_FILEVERSION QV2RAY_VERSION_MAJOR,QV2RAY_VERSION_MINOR,QV2RAY_VERSION_BUGFIX,QV2RAY_VERSION_BUILD
|
||||
#define VER_FILEVERSION_STR xstr(VER_FILEVERSION)
|
||||
#define VER_PRODUCTVERSION VER_FILEVERSION
|
||||
#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR
|
||||
|
||||
IDI_ICON1 ICON DISCARDABLE "assets\\icons\\qv2ray.ico"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VER_FILEVERSION
|
||||
PRODUCTVERSION VER_PRODUCTVERSION
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Qv2ray Workgroup\0"
|
||||
VALUE "FileDescription", "Qv2ray, a cross-platform v2ray GUI client.\0"
|
||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||
VALUE "LegalCopyright", "Qv2ray is being distributed under GPLv3\0"
|
||||
VALUE "OriginalFilename", "qv2ray.exe\0"
|
||||
VALUE "ProductName", "Qv2ray\0"
|
||||
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409, 1200
|
||||
END
|
||||
END
|
||||
/* End of Version info */
|
||||
#endif
|
50
cmake/backend.cmake
Normal file
@ -0,0 +1,50 @@
|
||||
if(NOT USE_LIBQVB)
|
||||
find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin)
|
||||
|
||||
find_library(GRPC_LIBRARY NAMES grpc)
|
||||
find_library(GRPCPP_LIBRARY NAMES grpc++)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(QV2RAY_BACKEND_LIBRARIES ${GRPCPP_LIBRARY} ${GRPC_LIBRARY})
|
||||
elseif(APPLE)
|
||||
find_library(UPB_LIBRARY NAMES upb)
|
||||
set(QV2RAY_BACKEND_LIBRARIES ${GRPCPP_LIBRARY} ${GRPC_LIBRARY} ${UPB_LIBRARY})
|
||||
elseif(WIN32)
|
||||
find_library(ADDRESS_SORTING NAMES address_sorting)
|
||||
find_library(ABSL_BASE NAMES absl_base)
|
||||
find_library(ABSL_STR NAMES absl_strings)
|
||||
find_library(ABSL_THROW_DELEGATE NAMES absl_throw_delegate)
|
||||
find_library(GPR_LIBRARY NAMES gpr)
|
||||
find_library(ZLIB_LIBRARY NAMES zlib)
|
||||
find_library(UPB_LIBRARY NAMES upb)
|
||||
find_library(CARES_LIBRARY NAMES cares)
|
||||
find_library(GRPC_INSECURE_LIBRARY NAMES grpc_unsecure)
|
||||
find_library(GRPCPP_INSECURE_LIBRARY NAMES grpc++_unsecure)
|
||||
set(QV2RAY_BACKEND_LIBRARIES ${GRPC_INSECURE_LIBRARY} ${GRPCPP_INSECURE_LIBRARY} ${ABSL_BASE} ${ABSL_STR} ${ADDRESS_SORTING}
|
||||
${ABSL_THROW_DELEGATE} ${GPR_LIBRARY} ${ZLIB_LIBRARY} ${UPB_LIBRARY} ${CARES_LIBRARY})
|
||||
endif()
|
||||
|
||||
set(API_PROTO "${CMAKE_SOURCE_DIR}/tools/v2ray_api.proto")
|
||||
set(API_PROTO_PATH "${CMAKE_SOURCE_DIR}/tools")
|
||||
set(API_PROTO_SRCS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.pb.cc")
|
||||
set(API_PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.pb.h")
|
||||
set(API_GRPC_SRCS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.grpc.pb.cc")
|
||||
set(API_GRPC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/v2ray_api.grpc.pb.h")
|
||||
add_custom_command(
|
||||
OUTPUT "${API_GRPC_SRCS}" "${API_GRPC_HDRS}" "${API_PROTO_HDRS}" "${API_PROTO_SRCS}"
|
||||
COMMAND ${Protobuf_PROTOC_EXECUTABLE}
|
||||
ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
--cpp_out "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
-I "${API_PROTO_PATH}"
|
||||
--plugin=protoc-gen-grpc="${GRPC_CPP_PLUGIN}"
|
||||
"${API_PROTO}"
|
||||
DEPENDS "${API_PROTO}"
|
||||
)
|
||||
else()
|
||||
add_definitions(-DBACKEND_LIBQVB)
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(QV2RAY_BACKEND_LIBRARIES ${CMAKE_SOURCE_DIR}/libs/libqvb-linux64.a)
|
||||
elseif(APPLE)
|
||||
set(QV2RAY_BACKEND_LIBRARIES ${CMAKE_SOURCE_DIR}/libs/libqvb-darwin.a)
|
||||
endif()
|
||||
endif()
|
1
cmake/cpp-httplib.cmake
Normal file
@ -0,0 +1 @@
|
||||
set(cpp-httplib_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/3rdparty/cpp-httplib)
|
23
cmake/deployment.cmake
Normal file
@ -0,0 +1,23 @@
|
||||
# Directories to look for dependencies
|
||||
set(DIRS "${CMAKE_BINARY_DIR}")
|
||||
|
||||
# Path used for searching by FIND_XXX(), with appropriate suffixes added
|
||||
if(CMAKE_PREFIX_PATH)
|
||||
foreach(dir ${CMAKE_PREFIX_PATH})
|
||||
list(APPEND DIRS "${dir}/bin" "${dir}/lib")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Append Qt's lib folder which is two levels above Qt5Widgets_DIR
|
||||
list(APPEND DIRS "${Qt5Widgets_DIR}/../..")
|
||||
list(APPEND DIRS "/usr/local/lib")
|
||||
list(APPEND DIRS "/usr/lib")
|
||||
|
||||
include(InstallRequiredSystemLibraries)
|
||||
|
||||
message(STATUS "APPS: ${APPS}")
|
||||
message(STATUS "QT_PLUGINS: ${QT_PLUGINS}")
|
||||
message(STATUS "DIRS: ${DIRS}")
|
||||
|
||||
install(CODE "include(BundleUtilities)
|
||||
fixup_bundle(\"${APPS}\" \"${QT_PLUGINS}\" \"${DIRS}\")")
|
5
cmake/protobuf.cmake
Normal file
@ -0,0 +1,5 @@
|
||||
find_package(Protobuf REQUIRED)
|
||||
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${CMAKE_SOURCE_DIR}/tools/v2ray_geosite.proto)
|
||||
set(QV2RAY_PROTOBUF_LIBRARY
|
||||
protobuf::libprotobuf
|
||||
)
|
69
cmake/qnodeeditor.cmake
Normal file
@ -0,0 +1,69 @@
|
||||
set(QNODEEDITOR_DIR ${CMAKE_SOURCE_DIR}/3rdparty/QNodeEditor)
|
||||
add_definitions(-DNODE_EDITOR_SHARED -DNODE_EDITOR_EXPORTS)
|
||||
set(QNODEEDITOR_SOURCES
|
||||
${QNODEEDITOR_DIR}/src/Connection.cpp
|
||||
${QNODEEDITOR_DIR}/src/ConnectionBlurEffect.cpp
|
||||
${QNODEEDITOR_DIR}/src/ConnectionGeometry.cpp
|
||||
${QNODEEDITOR_DIR}/src/ConnectionGraphicsObject.cpp
|
||||
${QNODEEDITOR_DIR}/src/ConnectionPainter.cpp
|
||||
${QNODEEDITOR_DIR}/src/ConnectionState.cpp
|
||||
${QNODEEDITOR_DIR}/src/ConnectionStyle.cpp
|
||||
${QNODEEDITOR_DIR}/src/DataModelRegistry.cpp
|
||||
${QNODEEDITOR_DIR}/src/FlowScene.cpp
|
||||
${QNODEEDITOR_DIR}/src/FlowView.cpp
|
||||
${QNODEEDITOR_DIR}/src/FlowViewStyle.cpp
|
||||
${QNODEEDITOR_DIR}/src/Node.cpp
|
||||
${QNODEEDITOR_DIR}/src/NodeConnectionInteraction.cpp
|
||||
${QNODEEDITOR_DIR}/src/NodeDataModel.cpp
|
||||
${QNODEEDITOR_DIR}/src/NodeGeometry.cpp
|
||||
${QNODEEDITOR_DIR}/src/NodeGraphicsObject.cpp
|
||||
${QNODEEDITOR_DIR}/src/NodePainter.cpp
|
||||
${QNODEEDITOR_DIR}/src/NodeState.cpp
|
||||
${QNODEEDITOR_DIR}/src/NodeStyle.cpp
|
||||
${QNODEEDITOR_DIR}/src/Properties.cpp
|
||||
${QNODEEDITOR_DIR}/src/StyleCollection.cpp
|
||||
)
|
||||
set(QNODEEDITOR_INCLUDE_PATH
|
||||
${QNODEEDITOR_DIR}/src/
|
||||
${QNODEEDITOR_DIR}/include/
|
||||
${QNODEEDITOR_DIR}/include/nodes/
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal
|
||||
)
|
||||
|
||||
set(HEADERS_TO_MOC
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/Compiler.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/Connection.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/ConnectionGeometry.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/ConnectionGraphicsObject.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/ConnectionState.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/ConnectionStyle.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/DataModelRegistry.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/Export.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/FlowScene.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/FlowView.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/FlowViewStyle.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/memory.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/Node.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/NodeData.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/NodeDataModel.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/NodeGeometry.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/NodeGraphicsObject.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/NodePainterDelegate.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/NodeState.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/NodeStyle.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/OperatingSystem.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/PortType.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/QStringStdHash.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/QUuidStdHash.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/Serializable.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/Style.hpp
|
||||
${QNODEEDITOR_DIR}/include/nodes/internal/TypeConverter.hpp
|
||||
)
|
||||
|
||||
qt5_wrap_cpp(QNODEEDITOR_SOURCES
|
||||
${HEADERS_TO_MOC}
|
||||
TARGET qv2ray
|
||||
OPTIONS --no-notes # Don't display a note for the headers which don't produce a moc_*.cpp
|
||||
)
|
||||
|
||||
set(QNODEEDITOR_QRC_RESOURCES ${QNODEEDITOR_DIR}/resources/QNodeEditor_resources.qrc)
|
97
cmake/qzxing.cmake
Normal file
@ -0,0 +1,97 @@
|
||||
add_definitions(-DQZXING_LIBRARY -DZXING_ICONV_CONST -DDISABLE_LIBRARY_FEATURES -DENABLE_DECODER_QR_CODE -DENABLE_ENCODER_QR_CODE -DENABLE_ENCODER_GENERIC)
|
||||
set(QZXING_DIR ${CMAKE_SOURCE_DIR}/3rdparty/qzxing/src)
|
||||
set(QZXING_SOURCES
|
||||
${QZXING_DIR}/CameraImageWrapper.cpp
|
||||
${QZXING_DIR}/QZXing.cpp
|
||||
${QZXING_DIR}/ImageHandler.cpp
|
||||
${QZXING_DIR}/zxing/zxing/ResultIO.cpp
|
||||
${QZXING_DIR}/zxing/zxing/InvertedLuminanceSource.cpp
|
||||
${QZXING_DIR}/zxing/zxing/ChecksumException.cpp
|
||||
${QZXING_DIR}/zxing/zxing/ResultPointCallback.cpp
|
||||
${QZXING_DIR}/zxing/zxing/ResultPoint.cpp
|
||||
${QZXING_DIR}/zxing/zxing/Result.cpp
|
||||
${QZXING_DIR}/zxing/zxing/ResultMetadata.cpp
|
||||
${QZXING_DIR}/zxing/zxing/Reader.cpp
|
||||
${QZXING_DIR}/zxing/zxing/MultiFormatReader.cpp
|
||||
${QZXING_DIR}/zxing/zxing/LuminanceSource.cpp
|
||||
${QZXING_DIR}/zxing/zxing/FormatException.cpp
|
||||
${QZXING_DIR}/zxing/zxing/Exception.cpp
|
||||
${QZXING_DIR}/zxing/zxing/DecodeHints.cpp
|
||||
${QZXING_DIR}/zxing/zxing/BinaryBitmap.cpp
|
||||
${QZXING_DIR}/zxing/zxing/Binarizer.cpp
|
||||
${QZXING_DIR}/zxing/zxing/BarcodeFormat.cpp
|
||||
${QZXING_DIR}/zxing/zxing/ReaderException.cpp
|
||||
${QZXING_DIR}/zxing/zxing/IllegalStateException.cpp
|
||||
${QZXING_DIR}/zxing/zxing/NotFoundException.cpp
|
||||
${QZXING_DIR}/zxing/zxing/WriterException.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/Counted.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/StringUtils.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/Str.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/PerspectiveTransform.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/IllegalArgumentException.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/HybridBinarizer.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/GridSampler.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/GreyscaleRotatedLuminanceSource.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/GreyscaleLuminanceSource.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/GlobalHistogramBinarizer.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/DetectorResult.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/DecoderResult.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/CharacterSetECI.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/BitSource.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/BitMatrix.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/BitArray.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/BitArrayIO.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/detector/WhiteRectangleDetector.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/detector/MonochromeRectangleDetector.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/reedsolomon/ReedSolomonException.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/reedsolomon/ReedSolomonDecoder.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/reedsolomon/GenericGFPoly.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/reedsolomon/GenericGF.cpp
|
||||
${QZXING_DIR}/zxing/zxing/multi/MultipleBarcodeReader.cpp
|
||||
${QZXING_DIR}/zxing/zxing/multi/GenericMultipleBarcodeReader.cpp
|
||||
${QZXING_DIR}/zxing/zxing/multi/ByQuadrantReader.cpp
|
||||
${QZXING_DIR}/zxing/bigint/BigUnsignedInABase.cc
|
||||
${QZXING_DIR}/zxing/bigint/BigUnsigned.cc
|
||||
${QZXING_DIR}/zxing/bigint/BigIntegerUtils.cc
|
||||
${QZXING_DIR}/zxing/bigint/BigIntegerAlgorithms.cc
|
||||
${QZXING_DIR}/zxing/bigint/BigInteger.cc
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/decoder/QRBitMatrixParser.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/decoder/QRDataBlock.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/decoder/QRDataMask.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/decoder/QRDecodedBitStreamParser.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/decoder/QRDecoder.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/detector/QRAlignmentPattern.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/detector/QRAlignmentPatternFinder.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/detector/QRDetector.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/detector/QRFinderPattern.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/detector/QRFinderPatternFinder.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/detector/QRFinderPatternInfo.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/QRCodeReader.cpp
|
||||
${QZXING_DIR}/zxing/zxing/multi/qrcode/QRCodeMultiReader.cpp
|
||||
${QZXING_DIR}/zxing/zxing/multi/qrcode/detector/MultiFinderPatternFinder.cpp
|
||||
${QZXING_DIR}/zxing/zxing/multi/qrcode/detector/MultiDetector.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/encoder/ByteMatrix.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/encoder/QREncoder.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/encoder/MaskUtil.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/encoder/MatrixUtil.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/encoder/QRCode.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/QRVersion.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/QRFormatInformation.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/QRErrorCorrectionLevel.cpp
|
||||
${QZXING_DIR}/zxing/zxing/qrcode/decoder/QRMode.cpp
|
||||
${QZXING_DIR}/zxing/zxing/EncodeHint.cpp
|
||||
${QZXING_DIR}/zxing/zxing/UnsupportedEncodingException.cpp
|
||||
${QZXING_DIR}/zxing/zxing/common/reedsolomon/ReedSolomonEncoder.cpp
|
||||
)
|
||||
set(QZXING_INCLUDE_PATH
|
||||
${QZXING_DIR}
|
||||
${QZXING_DIR}/zxing
|
||||
)
|
||||
if(MSVC)
|
||||
add_definitions(-D__STDC_LIMIT_MACROS)
|
||||
list(APPEND QZXING_SOURCES ${QZXING_DIR}/zxing/win32/zxing/win_iconv.c)
|
||||
list(APPEND QZXING_INCLUDE_PATH
|
||||
${QZXING_DIR}/zxing/win32/zxing
|
||||
${QZXING_DIR}/zxing/win32/zxing/msvc
|
||||
)
|
||||
endif()
|
6
cmake/singleapplication.cmake
Normal file
@ -0,0 +1,6 @@
|
||||
add_definitions(-DQAPPLICATION_CLASS=QApplication)
|
||||
set(SINGLEAPPLICATION_DIR ${CMAKE_SOURCE_DIR}/3rdparty/SingleApplication)
|
||||
set(SINGLEAPPLICATION_SOURCES
|
||||
${SINGLEAPPLICATION_DIR}/singleapplication.cpp
|
||||
${SINGLEAPPLICATION_DIR}/singleapplication_p.cpp
|
||||
)
|
4
cmake/translations.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
find_package(Qt5 COMPONENTS LinguistTools)
|
||||
set(TRANSLATIONS_DIR ${CMAKE_SOURCE_DIR}/translations)
|
||||
file(GLOB TRANSLATIONS_TS ${TRANSLATIONS_DIR}/**.ts)
|
||||
qt5_add_translation(QM_FILES ${TRANSLATIONS_TS})
|
1
libs/puresource
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit bd4f9335bb89e7b1199282c685d49dd5ae4ce1fa
|
@ -1,48 +0,0 @@
|
||||
message(" ")
|
||||
message("Configuring Qv2ray Dependencies...")
|
||||
|
||||
defineTest(Qv2rayQMakeError) {
|
||||
message(" ")
|
||||
message("-----------------------------------------------")
|
||||
message("Cannot continue: ")
|
||||
message(" --> Qv2ray is not properly configured yet: ")
|
||||
message(" $$ARGS")
|
||||
message(" --> Please read the build wiki: https://github.com/Qv2ray/Qv2ray/wiki/Manually-Build-Qv2ray")
|
||||
message("-----------------------------------------------")
|
||||
message(" ")
|
||||
warning("IF YOU THINK IT'S A MISTAKE, PLEASE OPEN AN ISSUE")
|
||||
error("! ABORTING THE BUILD !")
|
||||
message(" ")
|
||||
}
|
||||
|
||||
CONFIG += enable_decoder_qr_code enable_encoder_qr_code
|
||||
include($$PWD/../3rdparty/qzxing/src/QZXing-components.pri)
|
||||
include($$PWD/../3rdparty/SingleApplication/singleapplication.pri)
|
||||
include($$PWD/../3rdparty/QNodeEditor/QNodeEditor.pri)
|
||||
|
||||
#include(3rdparty/x2struct/x2struct.pri)
|
||||
|
||||
message("Adding QHttpServer Support")
|
||||
message(" --> Adding qhttpserver")
|
||||
HEADERS += \
|
||||
$$PWD/../3rdparty/qhttpserver/src/qhttpconnection.h \
|
||||
$$PWD/../3rdparty/qhttpserver/src/qhttprequest.h \
|
||||
$$PWD/../3rdparty/qhttpserver/src/qhttpresponse.h \
|
||||
$$PWD/../3rdparty/qhttpserver/src/qhttpserver.h \
|
||||
$$PWD/../3rdparty/qhttpserver/src/qhttpserverapi.h \
|
||||
$$PWD/../3rdparty/qhttpserver/src/qhttpserverfwd.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/../3rdparty/qhttpserver/src/qhttpconnection.cpp \
|
||||
$$PWD/../3rdparty/qhttpserver/src/qhttprequest.cpp \
|
||||
$$PWD/../3rdparty/qhttpserver/src/qhttpresponse.cpp \
|
||||
$$PWD/../3rdparty/qhttpserver/src/qhttpserver.cpp
|
||||
|
||||
INCLUDEPATH += 3rdparty/qhttpserver/src/
|
||||
|
||||
message(" --> Adding http parser")
|
||||
HEADERS += $$PWD/../3rdparty/qhttpserver/http-parser/http_parser.h
|
||||
SOURCES += $$PWD/../3rdparty/qhttpserver/http-parser/http_parser.c
|
||||
INCLUDEPATH += $$PWD/../3rdparty/qhttpserver/http-parser/
|
||||
|
||||
|
@ -1,50 +0,0 @@
|
||||
message(" ")
|
||||
defineTest(Qv2rayAddFile) {
|
||||
ext = $$take_last(ARGS)
|
||||
filename = $${take_first(ARGS)}.$${ext}
|
||||
qmake_debug: message("Qv2rayAddFile: filename: $$filename")
|
||||
!exists($$filename) {
|
||||
error("File: \"$$filename\" is not found, Qv2ray build preparation cannot continue")
|
||||
}
|
||||
equals(ext, "cpp") {
|
||||
SOURCES += $$filename
|
||||
} else {
|
||||
equals(ext, "hpp") {
|
||||
HEADERS += $$filename
|
||||
} else {
|
||||
equals(ext, "ui") {
|
||||
FORMS += $$filename
|
||||
} else {
|
||||
error("Unknown extension: $${ext}")
|
||||
}
|
||||
}
|
||||
}
|
||||
export(SOURCES)
|
||||
export(HEADERS)
|
||||
export(FORMS)
|
||||
}
|
||||
|
||||
defineTest(Qv2rayAddSource) {
|
||||
# Module Compnent Filename extlist
|
||||
module = $$take_first(ARGS)
|
||||
component = $$take_first(ARGS)
|
||||
filename = $$take_first(ARGS)
|
||||
extlist = $$ARGS
|
||||
FILEPATH = "$$PWD/src/$${module}"
|
||||
qmake_debug: message(Qv2rayAddSource: Adding \"$${filename}\" of module \"$${module}\", component \"$${component}\" to the project)
|
||||
equals(component, "_") {
|
||||
qmake_debug: message("Qv2rayAddSource: Component is empty, ignore")
|
||||
FILEPATH += "/$${filename}"
|
||||
FILEPATH=$$join(FILEPATH)
|
||||
} else {
|
||||
FILEPATH += "/$${component}/$${filename}"
|
||||
FILEPATH=$$join(FILEPATH)
|
||||
}
|
||||
qmake_debug: message("Qv2rayAddSource: filepath: $${FILEPATH}, extlist: $${extlist}")
|
||||
for(iterate, extlist) {
|
||||
Qv2rayAddFile($$FILEPATH, $$iterate)
|
||||
}
|
||||
export(SOURCES)
|
||||
export(HEADERS)
|
||||
export(FORMS)
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
message(" ")
|
||||
message("Looking for language support.")
|
||||
QM_FILES_RESOURCE_PREFIX = "translations"
|
||||
for(var, $$list($$files("$$PWD/../translations/*.ts", true))) {
|
||||
LOCALE_FILENAME = $$basename(var)
|
||||
message(" --> Found:" $$LOCALE_FILENAME)
|
||||
!equals(LOCALE_FILENAME, "en_US.ts") {
|
||||
# ONLY USED IN LRELEASE CONTEXT
|
||||
# en_US is not EXTRA...
|
||||
EXTRA_TRANSLATIONS += $$PWD/../translations/$$LOCALE_FILENAME
|
||||
}
|
||||
}
|
||||
|
||||
TRANSLATIONS += $$PWD/../translations/en_US.ts
|
||||
message("Qv2ray will build with" $${replace(EXTRA_TRANSLATIONS, "$$PWD/../translations/", "")} and $${replace(TRANSLATIONS, "$$PWD/../translations/", "")})
|
||||
|
||||
qmake_lupdate {
|
||||
message(" ")
|
||||
message("Running lupdate...")
|
||||
message("TRANSLATIONS: $$TRANSLATIONS")
|
||||
lupdate_output = $$system(lupdate -no-ui-lines $$SOURCES $$HEADERS $$FORMS -ts $$TRANSLATIONS)
|
||||
message(" $$lupdate_output")
|
||||
message("lupdate finished.")
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
message(" ")
|
||||
message("Configuring for Windows environment")
|
||||
QMAKE_CXXFLAGS += /MP /wo4251
|
||||
DEFINES += QHTTPSERVER_EXPORT
|
||||
|
||||
CONFIG += Qv2ray_Windows use_grpc
|
||||
!contains(QMAKE_TARGET.arch, x86_64) {
|
||||
CONFIG+=Qv2ray_win32
|
||||
GRPC_DEPS_PATH=$$PWD/../libs/x86-windows
|
||||
#
|
||||
!no_generate_headers: message(" --> Generating gRPC and protobuf headers for Windows x86")
|
||||
!no_generate_headers: system("$$PWD/../tools/win32-generate-pb.bat")
|
||||
} else {
|
||||
CONFIG+=Qv2ray_win64
|
||||
GRPC_DEPS_PATH=$$PWD/../libs/x64-windows
|
||||
#
|
||||
!no_generate_headers: message(" --> Generating gRPC and protobuf headers for Windows x64")
|
||||
!no_generate_headers: system("$$PWD/../tools/win64-generate-pb.bat")
|
||||
}
|
||||
|
||||
message(" --> Applying a hack for protobuf header")
|
||||
DEFINES += _WIN32_WINNT=0x600
|
||||
|
||||
DEPENDPATH += $$GRPC_DEPS_PATH/include
|
||||
INCLUDEPATH += $$GRPC_DEPS_PATH/include
|
||||
|
||||
message(" --> Setting up target descriptions")
|
||||
QMAKE_TARGET_DESCRIPTION = "Qv2ray, a cross-platform v2ray GUI client."
|
||||
QMAKE_TARGET_PRODUCT = "Qv2ray"
|
||||
|
||||
Qv2ray_debug: GRPC_LIB_PATH=$$GRPC_DEPS_PATH/debug
|
||||
Qv2ray_release: GRPC_LIB_PATH=$$GRPC_DEPS_PATH
|
||||
|
||||
message(" --> WIN32: Linking against gRPC library: $$GRPC_LIB_PATH")
|
||||
Qv2ray_debug: LIBS += -L$$GRPC_LIB_PATH/lib/ -laddress_sorting -lcares -lgrpc++_unsecure -lupb -lzlibd -lgrpc_unsecure -lgpr -labsl_base -labsl_strings -labsl_throw_delegate
|
||||
Qv2ray_release: LIBS += -L$$GRPC_LIB_PATH/lib/ -laddress_sorting -lcares -lgrpc++_unsecure -lupb -lzlib -lgrpc_unsecure -lgpr -labsl_base -labsl_strings -labsl_throw_delegate
|
||||
|
||||
message(" --> WIN32: Linking against protobuf library: $$GRPC_LIB_PATH")
|
||||
Qv2ray_release: LIBS += -lmsvcrt -L$$GRPC_LIB_PATH/lib/ -llibprotobuf
|
||||
Qv2ray_debug: LIBS += -lmsvcrtd -L$$GRPC_LIB_PATH/lib/ -llibprotobufd
|
||||
|
||||
message(" --> Linking against winHTTP and winSock2.")
|
||||
LIBS += -lwinhttp -lwininet -lws2_32 -luser32
|
@ -1,28 +0,0 @@
|
||||
message(" ")
|
||||
win32: Qv2rayQMakeError("Do not include this file in Windows platform.")
|
||||
|
||||
# For Linux and macOS
|
||||
message("Configuring for unix-like environment")
|
||||
|
||||
message(" --> Setting up QMAKE_CXXFLAGS")
|
||||
QMAKE_CXXFLAGS += -Wno-missing-field-initializers -Wno-unused-parameter -Wno-unused-variable
|
||||
|
||||
# macOS homebrew include path
|
||||
message(" --> Adding local include folder to search path")
|
||||
INCLUDEPATH += /usr/local/include/
|
||||
|
||||
# For protobuf in linux and macOS
|
||||
message(" --> Linking against protobuf library.")
|
||||
LIBS += -L/usr/local/lib -lprotobuf
|
||||
|
||||
message(" --> Generating geosite headers for Unix")
|
||||
system("$$PWD/../tools/unix-generate-geosite.sh $$PWD")
|
||||
|
||||
use_grpc {
|
||||
no_generate_headers {
|
||||
message(" --> Skipped generation of protobuf and/or gRPC header files")
|
||||
} else {
|
||||
message(" --> Generating gRPC and protobuf headers for Unix")
|
||||
system("$$PWD/../tools/unix-generate-api.sh $$PWD")
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
message(" ")
|
||||
message("Configuring Qv2ray build for Linux")
|
||||
isEmpty(PREFIX) {
|
||||
PREFIX=/usr/local
|
||||
}
|
||||
|
||||
use_grpc {
|
||||
# For gRPC and protobuf in linux
|
||||
message(" --> Linking against gRPC and protobuf library.")
|
||||
LIBS += -L/usr/local/lib -lgrpc++ -lgrpc
|
||||
} else {
|
||||
message(" --> Linking libqvb static library, for Linux platform.")
|
||||
LIBS += -L$$PWD/../libs/ -lqvb-linux64
|
||||
}
|
||||
|
||||
message(" --> Generating desktop dependency.")
|
||||
desktop.files += $$PWD/../assets/qv2ray.desktop
|
||||
desktop.path = $$PREFIX/share/applications/
|
||||
|
||||
message(" --> Generating icons dependency.")
|
||||
icon.files += $$PWD/../assets/icons/qv2ray.png
|
||||
icon.path = $$PREFIX/share/icons/hicolor/256x256/apps/
|
||||
|
||||
target.path = $$PREFIX/bin/
|
||||
INSTALLS += target desktop icon
|
||||
|
@ -1,11 +0,0 @@
|
||||
message(" ")
|
||||
|
||||
# For Linux and macOS
|
||||
message("Configuring for macOS specific environment")
|
||||
LIBS += -framework Carbon -framework Cocoa
|
||||
|
||||
use_grpc: error("The use of gRPC backend is not supported on macOS platform.")
|
||||
|
||||
message(" --> Linking libqvb static library and Security framework, for macOS platform.")
|
||||
LIBS += -L$$PWD/../libs/ -lqvb-darwin
|
||||
LIBS += -framework Security
|
@ -1,39 +0,0 @@
|
||||
message(" ")
|
||||
with_metainfo {
|
||||
message(" --> Generating metainfo dependency.")
|
||||
appdataXml.files += ./assets/qv2ray.metainfo.xml
|
||||
appdataXml.path = $$PREFIX/share/metainfo/
|
||||
INSTALLS += appdataXml
|
||||
DEFINES += WITH_FLATHUB_CONFIG_PATH
|
||||
}
|
||||
|
||||
# Automatically increase build number.
|
||||
no_increase_build_number | qmake_lupdate {
|
||||
message("QV2RAY_BUILD_VERSION will not be increased")
|
||||
} else {
|
||||
QV2RAY_BUILD_VERSION = $$num_add($$QV2RAY_BUILD_VERSION, 1)
|
||||
write_file($$PWD/BUILDVERSION, QV2RAY_BUILD_VERSION)
|
||||
}
|
||||
|
||||
# Qv2ray manual build info
|
||||
!no_build_info {
|
||||
_QV2RAY_BUILD_INFO_STR_=$$getenv(_QV2RAY_BUILD_INFO_)
|
||||
_QV2RAY_BUILD_EXTRA_INFO_STR_=$$getenv(_QV2RAY_BUILD_EXTRA_INFO_)
|
||||
|
||||
isEmpty(_QV2RAY_BUILD_INFO_STR_) {
|
||||
_QV2RAY_BUILD_INFO_STR_ = "Qv2ray from manual build"
|
||||
}
|
||||
|
||||
isEmpty(_QV2RAY_BUILD_EXTRA_INFO_STR_) {
|
||||
_QV2RAY_BUILD_EXTRA_INFO_STR_ = "Qv2ray $$VERSION"
|
||||
}
|
||||
} else {
|
||||
_QV2RAY_BUILD_INFO_STR_ = "No Info"
|
||||
_QV2RAY_BUILD_EXTRA_INFO_STR_ = "No Extra Info"
|
||||
}
|
||||
|
||||
message("Qv2ray build info:")
|
||||
message(" --> $$_QV2RAY_BUILD_INFO_STR_")
|
||||
message(" --> $$_QV2RAY_BUILD_EXTRA_INFO_STR_")
|
||||
|
||||
DEFINES += _QV2RAY_BUILD_INFO_STR_=\"\\\"$${_QV2RAY_BUILD_INFO_STR_}\\\"\" _QV2RAY_BUILD_EXTRA_INFO_STR_=\"\\\"$${_QV2RAY_BUILD_EXTRA_INFO_STR_}\\\"\"
|
@ -1 +1 @@
|
||||
3861
|
||||
4685
|
||||
|
294
qv2ray-config-models.qmodel
Normal file
@ -0,0 +1,294 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<qmt>
|
||||
<project>
|
||||
<uid>{e33c4c89-9b5b-44c4-9790-17cef05732d8}</uid>
|
||||
<root-package>
|
||||
<instance>
|
||||
<MPackage>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{6035e8ea-cf65-4a95-b11b-59d640802d5e}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>Qv2ray-config-models</name>
|
||||
<children>
|
||||
<handles>
|
||||
<handles>
|
||||
<qlist>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{0a303cb9-6681-4f79-9779-e61a34ac44ea}</uid>
|
||||
<target>
|
||||
<instance type="MCanvasDiagram">
|
||||
<MCanvasDiagram>
|
||||
<base-MDiagram>
|
||||
<MDiagram>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{0a303cb9-6681-4f79-9779-e61a34ac44ea}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>Qv2ray-config-models</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
<elements>
|
||||
<qlist>
|
||||
<item>
|
||||
<instance type="DItem">
|
||||
<DItem>
|
||||
<base-DObject>
|
||||
<DObject>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{89aa1d96-388b-49c0-a4e6-bf55bb570889}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<object>{314756b5-bc93-49b8-ae97-957fe8b30d44}</object>
|
||||
<name>BaseGroupObject</name>
|
||||
<pos>x:410;y:235</pos>
|
||||
<rect>x:-75;y:-50;w:150;h:100</rect>
|
||||
<auto-sized>false</auto-sized>
|
||||
<visual-role>0</visual-role>
|
||||
</DObject>
|
||||
</base-DObject>
|
||||
<shape-editable>false</shape-editable>
|
||||
</DItem>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DAnnotation">
|
||||
<DAnnotation>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{7dd68311-11eb-43d0-9e64-91daeae12d97}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<text>Display Name</text>
|
||||
<pos>x:350;y:215</pos>
|
||||
<rect>x:0;y:0;w:84.2031;h:30</rect>
|
||||
</DAnnotation>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DBoundary">
|
||||
<DBoundary>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{e51a8692-6ecb-4052-8e09-f1b1ee3a2b92}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<text>Connection Groups</text>
|
||||
<pos>x:260;y:230</pos>
|
||||
<rect>x:-235;y:-75;w:470;h:150</rect>
|
||||
</DBoundary>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DAnnotation">
|
||||
<DAnnotation>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{b4dc36e8-31f6-4637-9f8f-c27ee155e301}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<text>List<ConnectionId></text>
|
||||
<pos>x:350;y:235</pos>
|
||||
<rect>x:0;y:0;w:111.391;h:30</rect>
|
||||
</DAnnotation>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DBoundary">
|
||||
<DBoundary>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{ffc9dfd5-2441-4b3b-b814-3ac76fb03c7e}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<text>Subscriptions</text>
|
||||
<pos>x:565;y:230</pos>
|
||||
<rect>x:-240;y:-75;w:480;h:150</rect>
|
||||
</DBoundary>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DAnnotation">
|
||||
<DAnnotation>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{3634dcd7-fac8-4993-b3e7-c10450dae1de}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<text>Nothing here since the base group
|
||||
is enough</text>
|
||||
<pos>x:85;y:215</pos>
|
||||
<rect>x:0;y:0;w:186.047;h:44</rect>
|
||||
</DAnnotation>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DAnnotation">
|
||||
<DAnnotation>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{41e1ca4e-8395-472f-8470-912cf2c7b9d1}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<text>Some other metadata of subscription</text>
|
||||
<pos>x:535;y:220</pos>
|
||||
<rect>x:0;y:0;w:199.766;h:30</rect>
|
||||
</DAnnotation>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DItem">
|
||||
<DItem>
|
||||
<base-DObject>
|
||||
<DObject>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{d27ab510-0eda-4d06-ac71-cd8b1d68571f}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<object>{48b1692c-e2da-49cb-b1da-dd1030084013}</object>
|
||||
<name>Address, last-renewed......</name>
|
||||
<pos>x:610;y:205</pos>
|
||||
<rect>x:-75;y:-15;w:150;h:30</rect>
|
||||
<visual-role>0</visual-role>
|
||||
</DObject>
|
||||
</base-DObject>
|
||||
<shape-editable>false</shape-editable>
|
||||
</DItem>
|
||||
</instance>
|
||||
</item>
|
||||
</qlist>
|
||||
</elements>
|
||||
<last-modified>1581683831371</last-modified>
|
||||
<toolbarid>General</toolbarid>
|
||||
</MDiagram>
|
||||
</base-MDiagram>
|
||||
</MCanvasDiagram>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{314756b5-bc93-49b8-ae97-957fe8b30d44}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{314756b5-bc93-49b8-ae97-957fe8b30d44}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>BaseGroupObject</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{e2922977-d357-43f0-822a-624245d6b470}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{e2922977-d357-43f0-822a-624245d6b470}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>New Item</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{8a788e13-b40c-4a33-8121-f0a4817428b1}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{8a788e13-b40c-4a33-8121-f0a4817428b1}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>Address</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{ec54fd48-400e-4e7d-9e74-b6333d2101c1}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{ec54fd48-400e-4e7d-9e74-b6333d2101c1}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>Some other metadata of subscription</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{48b1692c-e2da-49cb-b1da-dd1030084013}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{48b1692c-e2da-49cb-b1da-dd1030084013}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>Address, last-renewed......</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
</qlist>
|
||||
</handles>
|
||||
</handles>
|
||||
</children>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MPackage>
|
||||
</instance>
|
||||
</root-package>
|
||||
</project>
|
||||
</qmt>
|
2321
qv2ray-new.qmodel
Normal file
2187
qv2ray.qmodel
Normal file
@ -24,5 +24,13 @@
|
||||
<file>assets/icons/qv2ray.ico</file>
|
||||
<file>assets/icons/qv2ray.png</file>
|
||||
<file>assets/credit.html</file>
|
||||
<file>assets/icons/ui_dark/connect.png</file>
|
||||
<file>assets/icons/ui_light/connect.png</file>
|
||||
<file>assets/icons/ui_dark/stop.png</file>
|
||||
<file>assets/icons/ui_light/stop.png</file>
|
||||
<file>assets/icons/ui_dark/locate.png</file>
|
||||
<file>assets/icons/ui_light/locate.png</file>
|
||||
<file>assets/icons/ui_dark/sort.png</file>
|
||||
<file>assets/icons/ui_light/sort.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
174
snap/plugins/x_cmake.py
Normal file
@ -0,0 +1,174 @@
|
||||
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
|
||||
#
|
||||
# Copyright (C) 2015-2016 Canonical Ltd
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 3 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""The cmake plugin is useful for building cmake based parts.
|
||||
|
||||
These are projects that have a CMakeLists.txt that drives the build.
|
||||
The plugin requires a CMakeLists.txt in the root of the source tree.
|
||||
|
||||
If the part has a list of build-snaps listed, the part will be set up in
|
||||
such a way that the paths to those snaps are used as paths for find_package
|
||||
and find_library by use of `CMAKE_FIND_ROOT_PATH``.
|
||||
This plugin uses the common plugin keywords as well as those for "sources".
|
||||
For more information check the 'plugins' topic for the former and the
|
||||
'sources' topic for the latter.
|
||||
|
||||
Additionally, this plugin uses the following plugin-specific keywords:
|
||||
|
||||
- configflags:
|
||||
(list of strings)
|
||||
configure flags to pass to the build using the common cmake semantics.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
from typing import List, Optional
|
||||
import subprocess
|
||||
|
||||
import snapcraft
|
||||
from snapcraft.internal import errors
|
||||
|
||||
|
||||
logger = logging.getLogger(name=__name__)
|
||||
|
||||
|
||||
class _Flag:
|
||||
def __str__(self) -> str:
|
||||
if self.value is None:
|
||||
flag = self.name
|
||||
else:
|
||||
flag = "{}={}".format(self.name, self.value)
|
||||
return flag
|
||||
|
||||
def __init__(self, flag: str) -> None:
|
||||
parts = flag.split("=")
|
||||
self.name = parts[0]
|
||||
try:
|
||||
self.value: Optional[str] = parts[1]
|
||||
except IndexError:
|
||||
self.value = None
|
||||
|
||||
|
||||
class CMakePlugin(snapcraft.BasePlugin):
|
||||
@classmethod
|
||||
def schema(cls):
|
||||
schema = super().schema()
|
||||
schema["properties"]["configflags"] = {
|
||||
"type": "array",
|
||||
"minitems": 1,
|
||||
"uniqueItems": True,
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
}
|
||||
# For backwards compatibility
|
||||
schema["properties"]["make-parameters"] = {
|
||||
"type": "array",
|
||||
"minitems": 1,
|
||||
"uniqueItems": True,
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
}
|
||||
schema["required"] = ["source"]
|
||||
|
||||
return schema
|
||||
|
||||
@classmethod
|
||||
def get_build_properties(cls):
|
||||
# Inform Snapcraft of the properties associated with building. If these
|
||||
# change in the YAML Snapcraft will consider the build step dirty.
|
||||
return super().get_build_properties() + ["configflags"]
|
||||
|
||||
def __init__(self, name, options, project):
|
||||
super().__init__(name, options, project)
|
||||
self.build_packages.append("cmake")
|
||||
self.build_packages.append("ninja-build")
|
||||
self.out_of_source_build = True
|
||||
|
||||
cmd = '''
|
||||
echo 'deb http://archive.neon.kde.org/unstable bionic main' > /etc/apt/sources.list.d/neon.list
|
||||
echo 'deb http://ppa.launchpad.net/ymshenyu/grpc-1/ubuntu bionic main' > /etc/apt/sources.list.d/grpc.list
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E6D4736255751E5D
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 281f24e574404629aa3bda1a4f10c386c55cdb04
|
||||
sudo apt update -qq
|
||||
'''
|
||||
|
||||
subprocess.call(cmd, shell=True)
|
||||
|
||||
if project.info.get_build_base() not in ("core", "core16", "core18"):
|
||||
raise errors.PluginBaseError(
|
||||
part_name=self.name, base=project.info.get_build_base()
|
||||
)
|
||||
|
||||
if options.make_parameters:
|
||||
logger.warning("make-paramaters is deprecated, ignoring.")
|
||||
|
||||
def build(self):
|
||||
source_subdir = getattr(self.options, "source_subdir", None)
|
||||
if source_subdir:
|
||||
sourcedir = os.path.join(self.sourcedir, source_subdir)
|
||||
else:
|
||||
sourcedir = self.sourcedir
|
||||
|
||||
env = self._build_environment()
|
||||
configflags = self._get_processed_flags()
|
||||
|
||||
self.run(["cmake", sourcedir, "-DCMAKE_INSTALL_PREFIX="] + configflags, env=env)
|
||||
|
||||
# TODO: there is a better way to specify the job count on newer versions of cmake
|
||||
# https://github.com/Kitware/CMake/commit/1ab3881ec9e809ac5f6cad5cd84048310b8683e2
|
||||
self.run(
|
||||
["cmake", "--build", ".", "--", "-j{}".format(self.parallel_build_count)],
|
||||
env=env,
|
||||
)
|
||||
|
||||
self.run(["cmake", "--build", ".", "--target", "install"], env=env)
|
||||
|
||||
def _get_processed_flags(self) -> List[str]:
|
||||
# Return the original if no build_snaps are in options.
|
||||
if not self.options.build_snaps:
|
||||
return self.options.configflags
|
||||
|
||||
build_snap_paths = [
|
||||
os.path.join(os.path.sep, "snap", snap_name.split("/")[0], "current")
|
||||
for snap_name in self.options.build_snaps
|
||||
]
|
||||
|
||||
flags = [_Flag(f) for f in self.options.configflags]
|
||||
for flag in flags:
|
||||
if flag.name == "-DCMAKE_FIND_ROOT_PATH":
|
||||
flag.value = "{};{}".format(flag.value, ";".join(build_snap_paths))
|
||||
break
|
||||
else:
|
||||
flags.append(
|
||||
_Flag("-DCMAKE_FIND_ROOT_PATH={}".format(";".join(build_snap_paths)))
|
||||
)
|
||||
|
||||
return [str(f) for f in flags]
|
||||
|
||||
def _build_environment(self):
|
||||
env = os.environ.copy()
|
||||
env["DESTDIR"] = self.installdir
|
||||
env["CMAKE_PREFIX_PATH"] = "$CMAKE_PREFIX_PATH:{}".format(
|
||||
self.project.stage_dir
|
||||
)
|
||||
env["CMAKE_INCLUDE_PATH"] = "$CMAKE_INCLUDE_PATH:" + ":".join(
|
||||
["{0}/include", "{0}/usr/include", "{0}/include/{1}", "{0}/usr/include/{1}"]
|
||||
).format(self.project.stage_dir, self.project.arch_triplet)
|
||||
env["CMAKE_LIBRARY_PATH"] = "$CMAKE_LIBRARY_PATH:" + ":".join(
|
||||
["{0}/lib", "{0}/usr/lib", "{0}/lib/{1}", "{0}/usr/lib/{1}"]
|
||||
).format(self.project.stage_dir, self.project.arch_triplet)
|
||||
|
||||
return env
|
@ -3,8 +3,8 @@ base: core18
|
||||
adopt-info: qv2ray
|
||||
icon: assets/icons/qv2ray.png
|
||||
|
||||
grade: devel
|
||||
confinement: devmode
|
||||
grade: stable
|
||||
confinement: strict
|
||||
|
||||
plugs:
|
||||
gsettings:
|
||||
@ -26,18 +26,33 @@ apps:
|
||||
command: bin/desktop-launch qv2ray
|
||||
environment:
|
||||
QT_QPA_PLATFORMTHEME: gtk3
|
||||
plugs:
|
||||
- home
|
||||
- x11
|
||||
- wayland
|
||||
- opengl
|
||||
- network
|
||||
- network-bind
|
||||
- unity7
|
||||
- pulseaudio
|
||||
- desktop
|
||||
- desktop-legacy
|
||||
- gsettings
|
||||
- network-control
|
||||
- network-manager
|
||||
common-id: com.github.Qv2ray
|
||||
desktop: "usr/share/applications/qv2ray.desktop"
|
||||
|
||||
parts:
|
||||
qv2ray:
|
||||
plugin: qmake
|
||||
plugin: x-cmake
|
||||
source-type: git
|
||||
source: .
|
||||
parse-info: [usr/share/metainfo/qv2ray.metainfo.xml]
|
||||
build-packages:
|
||||
- build-essential
|
||||
- qttools5-dev-tools
|
||||
- qttools5-dev
|
||||
- qt5-default
|
||||
- libgrpc++-dev
|
||||
- libprotobuf-dev
|
||||
@ -52,12 +67,12 @@ parts:
|
||||
- libqt5gui5
|
||||
- libqt5network5
|
||||
- libqt5widgets5
|
||||
- fonts-noto-cjk
|
||||
- libglib2.0-bin
|
||||
options:
|
||||
- PREFIX=/usr
|
||||
- CONFIG+=with_metainfo
|
||||
- CONFIG+=use_grpc
|
||||
configflags:
|
||||
- -DCMAKE_INSTALL_PREFIX=/usr
|
||||
- -DCMAKE_BUILD_TYPE=Release
|
||||
- -GNinja
|
||||
- -DEMBED_TRANSLATIONS=ON
|
||||
override-pull: |
|
||||
snapcraftctl pull
|
||||
build_number=$(cat makespec/BUILDVERSION)
|
||||
@ -66,7 +81,6 @@ parts:
|
||||
snapcraftctl set-version "$version"
|
||||
sed -i 's|^Icon=.*|Icon=/usr/share/icons/hicolor/256x256/apps/qv2ray.png|g' assets/qv2ray.desktop
|
||||
after:
|
||||
- mytools
|
||||
- desktop-qt5
|
||||
|
||||
desktop-qt5:
|
||||
@ -93,28 +107,8 @@ parts:
|
||||
- locales-all
|
||||
- xdg-user-dirs
|
||||
- fcitx-frontend-qt5
|
||||
after:
|
||||
- mytools
|
||||
|
||||
qt5-gtk-platform:
|
||||
plugin: nil
|
||||
stage-packages:
|
||||
- qt5-gtk-platformtheme
|
||||
after:
|
||||
- mytools
|
||||
|
||||
mytools:
|
||||
plugin: nil
|
||||
build-packages:
|
||||
- dirmngr
|
||||
override-pull: |
|
||||
echo 'deb http://archive.neon.kde.org/unstable bionic main' > /etc/apt/sources.list.d/neon.list
|
||||
echo 'deb http://ppa.launchpad.net/ymshenyu/grpc-1/ubuntu bionic main' >> /etc/apt/sources.list.d/tools.list
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E6D4736255751E5D
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 281f24e574404629aa3bda1a4f10c386c55cdb04
|
||||
sudo apt-get update
|
||||
snapcraftctl pull
|
||||
override-build: |
|
||||
snapcraftctl build
|
||||
sudo apt upgrade -y
|
||||
sudo apt dist-upgrade -y
|
@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "base/models/QvRuntimeConfig.hpp"
|
||||
#include "base/models/QvStartupConfig.hpp"
|
||||
#include "base/models/QvConfigModel.hpp"
|
||||
|
||||
#include <QTranslator>
|
||||
|
||||
// Instantiation for Qv2ray global objects.
|
||||
#ifdef QT_DEBUG
|
||||
const bool isDebugBuild = true;
|
||||
#else
|
||||
const bool isDebugBuild = false;
|
||||
#endif
|
||||
|
||||
namespace Qv2ray
|
||||
{
|
||||
// Qv2ray runtime config
|
||||
inline bool isExiting = false;
|
||||
inline QString Qv2rayConfigPath = "/";
|
||||
inline base::Qv2rayRuntimeConfig RuntimeConfig = base::Qv2rayRuntimeConfig();
|
||||
inline base::config::Qv2rayConfig GlobalConfig = base::config::Qv2rayConfig();
|
||||
inline base::QvStartupOptions StartupOption = base::QvStartupOptions();
|
||||
//
|
||||
inline std::unique_ptr<QTranslator> Qv2rayTranslator;
|
||||
}
|
@ -1,42 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#define STRINGIZE(arg) STRINGIZE1(arg)
|
||||
#define STRINGIZE(arg) STRINGIZE1(arg)
|
||||
#define STRINGIZE1(arg) STRINGIZE2(arg)
|
||||
#define STRINGIZE2(arg) #arg
|
||||
|
||||
#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2)
|
||||
#define CONCATENATE2(arg1, arg2) arg1##arg2
|
||||
#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2)
|
||||
#define CONCATENATE2(arg1, arg2) arg1##arg2
|
||||
|
||||
#define EXPAND(x) x
|
||||
#define FOR_EACH_1(what, x, ...) what(x)
|
||||
|
||||
#define FOR_EACH_2(what, x, ...)\
|
||||
what(x);\
|
||||
EXPAND(FOR_EACH_1(what, __VA_ARGS__))
|
||||
#define FOR_EACH_3(what, x, ...)\
|
||||
what(x);\
|
||||
#define FOR_EACH_2(what, x, ...) \
|
||||
what(x); \
|
||||
EXPAND(FOR_EACH_1(what, __VA_ARGS__))
|
||||
#define FOR_EACH_3(what, x, ...) \
|
||||
what(x); \
|
||||
EXPAND(FOR_EACH_2(what, __VA_ARGS__))
|
||||
#define FOR_EACH_4(what, x, ...)\
|
||||
what(x);\
|
||||
EXPAND(FOR_EACH_3(what, __VA_ARGS__))
|
||||
#define FOR_EACH_5(what, x, ...)\
|
||||
what(x);\
|
||||
EXPAND(FOR_EACH_4(what, __VA_ARGS__))
|
||||
#define FOR_EACH_6(what, x, ...)\
|
||||
what(x);\
|
||||
EXPAND(FOR_EACH_5(what, __VA_ARGS__))
|
||||
#define FOR_EACH_7(what, x, ...)\
|
||||
what(x);\
|
||||
EXPAND(FOR_EACH_6(what, __VA_ARGS__))
|
||||
#define FOR_EACH_8(what, x, ...)\
|
||||
what(x);\
|
||||
EXPAND(FOR_EACH_7(what, __VA_ARGS__))
|
||||
#define FOR_EACH_4(what, x, ...) \
|
||||
what(x); \
|
||||
EXPAND(FOR_EACH_3(what, __VA_ARGS__))
|
||||
#define FOR_EACH_5(what, x, ...) \
|
||||
what(x); \
|
||||
EXPAND(FOR_EACH_4(what, __VA_ARGS__))
|
||||
#define FOR_EACH_6(what, x, ...) \
|
||||
what(x); \
|
||||
EXPAND(FOR_EACH_5(what, __VA_ARGS__))
|
||||
#define FOR_EACH_7(what, x, ...) \
|
||||
what(x); \
|
||||
EXPAND(FOR_EACH_6(what, __VA_ARGS__))
|
||||
#define FOR_EACH_8(what, x, ...) \
|
||||
what(x); \
|
||||
EXPAND(FOR_EACH_7(what, __VA_ARGS__))
|
||||
|
||||
#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
|
||||
#define FOR_EACH_NARG_(...) EXPAND(FOR_EACH_ARG_N(__VA_ARGS__))
|
||||
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
|
||||
#define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||
#define CONCATENATE(x,y) x##y
|
||||
#define CONCATENATE(x, y) x##y
|
||||
#define FOR_EACH_(N, what, ...) EXPAND(CONCATENATE(FOR_EACH_, N)(what, __VA_ARGS__))
|
||||
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)
|
||||
#define JADDEx_(jsonObj, field) jsonObj.insert(#field, field);
|
||||
|
@ -1,28 +1,25 @@
|
||||
#pragma once
|
||||
//
|
||||
#ifndef XTOSTRUCT_QT
|
||||
# define XTOSTRUCT_QT
|
||||
#endif
|
||||
//
|
||||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
#include <QApplication>
|
||||
#include <QMap>
|
||||
#include <vector>
|
||||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
// Base support.
|
||||
#include "base/Qv2rayLog.hpp"
|
||||
#include "base/Qv2rayFeatures.hpp"
|
||||
#include "base/JsonHelpers.hpp"
|
||||
#include "base/GlobalInstances.hpp"
|
||||
#include "base/Qv2rayFeatures.hpp"
|
||||
#include "base/Qv2rayLog.hpp"
|
||||
// Code Models
|
||||
#include "base/models/QvSafeType.hpp"
|
||||
#include "base/models/CoreObjectModels.hpp"
|
||||
#include "base/models/QvConfigModel.hpp"
|
||||
#include "base/models/QvConfigIdentifier.hpp"
|
||||
#include "base/models/QvStartupConfig.hpp"
|
||||
#include "base/models/QvRuntimeConfig.hpp"
|
||||
#include "base/models/QvSafeType.hpp"
|
||||
#include "base/models/QvSettingsObject.hpp"
|
||||
#include "base/models/QvStartupConfig.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
@ -34,27 +31,20 @@ using namespace Qv2ray::base::objects;
|
||||
using namespace Qv2ray::base::objects::protocol;
|
||||
using namespace Qv2ray::base::objects::transfer;
|
||||
|
||||
// Linux users and DEs should handle the darkMode UI themselves.
|
||||
#ifndef QV2RAY_USE_BUILTIN_DARKTHEME
|
||||
# ifndef Q_OS_LINUX
|
||||
# define QV2RAY_USE_BUILTIN_DARKTHEME
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define QV2RAY_BUILD_INFO QString(_QV2RAY_BUILD_INFO_STR_)
|
||||
#define QV2RAY_BUILD_EXTRA_INFO QString(_QV2RAY_BUILD_EXTRA_INFO_STR_)
|
||||
|
||||
extern const bool isDebugBuild;
|
||||
// Base folder suffix.
|
||||
#ifdef QT_DEBUG
|
||||
# define QV2RAY_CONFIG_DIR_SUFFIX "_debug/"
|
||||
#define QV2RAY_CONFIG_DIR_SUFFIX "_debug/"
|
||||
#else
|
||||
# define QV2RAY_CONFIG_DIR_SUFFIX "/"
|
||||
#define QV2RAY_CONFIG_DIR_SUFFIX "/"
|
||||
#endif
|
||||
|
||||
// Get Configured Config Dir Path
|
||||
#define QV2RAY_CONFIG_DIR (Qv2ray::Qv2rayConfigPath)
|
||||
#define QV2RAY_CONFIG_FILE (QV2RAY_CONFIG_DIR + "Qv2ray.conf")
|
||||
#define QV2RAY_CONNECTIONS_DIR (QV2RAY_CONFIG_DIR + "connections/")
|
||||
#define QV2RAY_SUBSCRIPTION_DIR (QV2RAY_CONFIG_DIR + "subscriptions/")
|
||||
|
||||
// Get GFWList and PAC file path.
|
||||
@ -66,17 +56,17 @@ extern const bool isDebugBuild;
|
||||
#define QV2RAY_GENERATED_DIR (QV2RAY_CONFIG_DIR + "generated/")
|
||||
#define QV2RAY_GENERATED_FILE_PATH (QV2RAY_GENERATED_DIR + "config.gen.json")
|
||||
|
||||
#if ! defined (QV2RAY_DEFAULT_VCORE_PATH) && ! defined (QV2RAY_DEFAULT_VASSETS_PATH)
|
||||
# define QV2RAY_DEFAULT_VASSETS_PATH (QV2RAY_CONFIG_DIR + "vcore/")
|
||||
# ifdef Q_OS_WIN
|
||||
# define QV2RAY_DEFAULT_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray.exe")
|
||||
# else
|
||||
# define QV2RAY_DEFAULT_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray")
|
||||
# endif
|
||||
#elif defined (QV2RAY_DEFAULT_VCORE_PATH) && defined (QV2RAY_DEFAULT_VASSETS_PATH)
|
||||
#if !defined(QV2RAY_DEFAULT_VCORE_PATH) && !defined(QV2RAY_DEFAULT_VASSETS_PATH)
|
||||
#define QV2RAY_DEFAULT_VASSETS_PATH (QV2RAY_CONFIG_DIR + "vcore/")
|
||||
#ifdef Q_OS_WIN
|
||||
#define QV2RAY_DEFAULT_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray.exe")
|
||||
#else
|
||||
#define QV2RAY_DEFAULT_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray")
|
||||
#endif
|
||||
#elif defined(QV2RAY_DEFAULT_VCORE_PATH) && defined(QV2RAY_DEFAULT_VASSETS_PATH)
|
||||
// ---- Using user-specified VCore and VAssets path
|
||||
#else
|
||||
# error Both QV2RAY_DEFAULT_VCORE_PATH and QV2RAY_DEFAULT_VASSETS_PATH need to present when specifying the paths.
|
||||
#error Both QV2RAY_DEFAULT_VCORE_PATH and QV2RAY_DEFAULT_VASSETS_PATH need to be presented when using manually specify the paths.
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
@ -84,8 +74,8 @@ extern const bool isDebugBuild;
|
||||
//# define QV2RAY_TPROXY_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray.exe")
|
||||
//# define QV2RAY_TPROXY_VCTL_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ctl.exe")
|
||||
#else
|
||||
# define QV2RAY_TPROXY_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray")
|
||||
# define QV2RAY_TPROXY_VCTL_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ctl")
|
||||
#define QV2RAY_TPROXY_VCORE_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ray")
|
||||
#define QV2RAY_TPROXY_VCTL_PATH (QV2RAY_CONFIG_DIR + "vcore/v2ctl")
|
||||
#endif
|
||||
|
||||
#define QV2RAY_VCORE_LOG_DIRNAME "logs/"
|
||||
@ -93,20 +83,19 @@ extern const bool isDebugBuild;
|
||||
#define QV2RAY_VCORE_ERROR_LOG_FILENAME "error.log"
|
||||
|
||||
// GUI TOOLS
|
||||
#define RED(obj) \
|
||||
auto _temp = obj->palette(); \
|
||||
_temp.setColor(QPalette::Text, Qt::red); \
|
||||
#define RED(obj) \
|
||||
auto _temp = obj->palette(); \
|
||||
_temp.setColor(QPalette::Text, Qt::red); \
|
||||
obj->setPalette(_temp);
|
||||
|
||||
#define BLACK(obj) \
|
||||
obj->setPalette(this->palette());
|
||||
#define BLACK(obj) obj->setPalette(QWidget::palette());
|
||||
|
||||
#define QV2RAY_UI_RESOURCES_ROOT ((GlobalConfig.uiConfig.useDarkTheme) ? QStringLiteral(":/assets/icons/ui_dark/") : QStringLiteral(":/assets/icons/ui_light/"))
|
||||
#define QICON_R(file) QIcon(QV2RAY_UI_RESOURCES_ROOT + file)
|
||||
#define QV2RAY_UI_COLORSCHEME_ROOT \
|
||||
((GlobalConfig.uiConfig.useDarkTheme) ? QStringLiteral(":/assets/icons/ui_dark/") : QStringLiteral(":/assets/icons/ui_light/"))
|
||||
#define QICON_R(file) QIcon(QV2RAY_UI_COLORSCHEME_ROOT + file)
|
||||
|
||||
#define QSTRN(num) QString::number(num)
|
||||
|
||||
|
||||
#define OUTBOUND_TAG_DIRECT "outBound_DIRECT"
|
||||
#define OUTBOUND_TAG_PROXY "outBound_PROXY"
|
||||
#define OUTBOUND_TAG_FORWARD_PROXY "_QV2RAY_FORWARD_PROXY_"
|
||||
@ -116,16 +105,25 @@ extern const bool isDebugBuild;
|
||||
|
||||
#define QV2RAY_USE_FPROXY_KEY "_QV2RAY_USE_GLOBAL_FORWARD_PROXY_"
|
||||
|
||||
#define JSON_ROOT_TRY_REMOVE(obj) if (root.contains(obj)) { root.remove(obj); }
|
||||
#define JSON_ROOT_TRY_REMOVE(obj) \
|
||||
if (root.contains(obj)) \
|
||||
{ \
|
||||
root.remove(obj); \
|
||||
}
|
||||
|
||||
namespace Qv2ray
|
||||
{
|
||||
// Extra header for QvConfigUpgrade.cpp
|
||||
QJsonObject UpgradeConfig(int fromVersion, int toVersion, QJsonObject root);
|
||||
QJsonObject UpgradeSettingsVersion(int fromVersion, int toVersion, QJsonObject root);
|
||||
|
||||
// Qv2ray runtime config
|
||||
inline bool isExiting = false;
|
||||
inline QString Qv2rayConfigPath = "";
|
||||
inline base::config::Qv2rayConfig GlobalConfig = base::config::Qv2rayConfig();
|
||||
//
|
||||
inline void ExitQv2ray()
|
||||
{
|
||||
isExiting = true;
|
||||
QApplication::quit();
|
||||
}
|
||||
}
|
||||
} // namespace Qv2ray
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Qv2ray build features.
|
||||
//
|
||||
// Always use libgRPC++ on windows platform.
|
||||
#ifndef WITH_LIB_GRPCPP
|
||||
# ifdef _WIN32
|
||||
# define WITH_LIB_GRPCPP
|
||||
# endif
|
||||
#ifdef BACKEND_LIBQVB
|
||||
#ifdef _WIN32
|
||||
#error "libQvb is not supported on Windows Platform"
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,5 +1,8 @@
|
||||
#include "Qv2rayLog.hpp"
|
||||
#include "GlobalInstances.hpp"
|
||||
|
||||
#include "Qv2rayBase.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace Qv2ray::base
|
||||
{
|
||||
@ -11,42 +14,48 @@ namespace Qv2ray::base
|
||||
|
||||
void __QV2RAY_LOG_FUNC__(int type, const std::string &func, int line, const QString &module, const QString &log)
|
||||
{
|
||||
auto logString = "[" + module + "]: " + log;
|
||||
auto logString = QString("[" % module % "]: " % log);
|
||||
auto funcPrepend = QString::fromStdString(func + ":" + to_string(line) + " ");
|
||||
|
||||
if (isDebugBuild) {
|
||||
// Debug build version, we only print info for DEBUG logs and print ALL info when debugLog presents,
|
||||
if (type == QV2RAY_LOG_DEBUG || StartupOption.debugLog) {
|
||||
logString = logString.prepend(funcPrepend);
|
||||
#ifdef QT_DEBUG
|
||||
// Debug build version, we only print info for DEBUG logs and print
|
||||
// ALL info when debugLog presents,
|
||||
if (type == QV2RAY_LOG_DEBUG || StartupOption.debugLog)
|
||||
{
|
||||
logString.prepend(funcPrepend);
|
||||
}
|
||||
#else
|
||||
// We only process DEBUG log in Release mode
|
||||
if (type == QV2RAY_LOG_DEBUG)
|
||||
{
|
||||
if (StartupOption.debugLog)
|
||||
{
|
||||
logString.prepend(funcPrepend);
|
||||
}
|
||||
} else {
|
||||
// We only process DEBUG log in Release mode
|
||||
if (type == QV2RAY_LOG_DEBUG) {
|
||||
if (StartupOption.debugLog) {
|
||||
logString = logString.prepend(funcPrepend);
|
||||
} else {
|
||||
// Discard debug log in non-debug Qv2ray version with no-debugLog mode.
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Discard debug log in non-debug Qv2ray version with
|
||||
// no-debugLog mode.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
cout << logString.toStdString() << endl;
|
||||
{
|
||||
QMutexLocker _(&__loggerMutex);
|
||||
__loggerBuffer->append(logString + NEWLINE);
|
||||
}
|
||||
}
|
||||
} // namespace Qv2ray::base
|
||||
|
||||
const QString readLastLog()
|
||||
QString readLastLog()
|
||||
{
|
||||
QMutexLocker _(&__purgerMutex);
|
||||
{
|
||||
QMutexLocker _(&__loggerMutex);
|
||||
QMutexLocker locker(&__loggerMutex);
|
||||
__loggerBuffer.swap(__purgerBuffer);
|
||||
}
|
||||
auto result = __purgerBuffer->join("");
|
||||
__purgerBuffer->clear();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} // namespace Qv2ray::base
|
||||
|
@ -1,28 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <QtDebug>
|
||||
#include <QBuffer>
|
||||
#include <QString>
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* Tiny log module.
|
||||
*/
|
||||
|
||||
namespace Qv2ray::base
|
||||
{
|
||||
void __QV2RAY_LOG_FUNC__(int type, const std::string &func, int line, const QString &module, const QString &log);
|
||||
const QString readLastLog();
|
||||
}
|
||||
QString readLastLog();
|
||||
} // namespace Qv2ray::base
|
||||
|
||||
#define NEWLINE "\r\n"
|
||||
|
||||
#define QV2RAY_LOG_NORMAL 0
|
||||
#define QV2RAY_LOG_DEBUG 1
|
||||
#define QV2RAY_LOG_DEBUG 1
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
#define Qv2ray_PRETTY_FUNCTION __PRETTY_FUNCTION__
|
||||
#define Qv2ray_PRETTY_FUNCTION __PRETTY_FUNCTION__
|
||||
#else
|
||||
#define Qv2ray_PRETTY_FUNCTION __FUNCSIG__
|
||||
#define Qv2ray_PRETTY_FUNCTION __FUNCSIG__
|
||||
#endif
|
||||
|
||||
#define __LOG_IMPL(LEVEL, MODULE, MSG) __QV2RAY_LOG_FUNC__(LEVEL, Qv2ray_PRETTY_FUNCTION, __LINE__, MODULE, MSG);
|
||||
@ -31,21 +30,23 @@ namespace Qv2ray::base
|
||||
#define DEBUG(MODULE, MSG) __LOG_IMPL(QV2RAY_LOG_DEBUG, (MODULE), (MSG));
|
||||
|
||||
// Log modules used by Qv2ray
|
||||
const inline QString INIT = "INIT" ;
|
||||
const inline QString MESSAGING = "BASE-MESSAGING" ;
|
||||
const inline QString UI = "CORE-UI" ;
|
||||
const inline QString GRAPH = "CORE-UI-GRAPH" ;
|
||||
const inline QString SETTINGS = "CORE-SETTINGS" ;
|
||||
const inline QString VCORE = "CORE-VCORE" ;
|
||||
const inline QString MODULE_INIT = "INIT";
|
||||
const inline QString MODULE_MESSAGING = "BASE-MESSAGING";
|
||||
const inline QString MODULE_UI = "CORE-UI";
|
||||
const inline QString MODULE_GRAPH = "CORE-UI-GRAPH";
|
||||
const inline QString MODULE_SETTINGS = "CORE-SETTINGS";
|
||||
const inline QString MODULE_VCORE = "CORE-VCORE";
|
||||
//
|
||||
const inline QString CONNECTION = "CORE-CONNECTION" ;
|
||||
const inline QString SUBSCRIPTION = "CORE-SUBSCRIPTION" ;
|
||||
const inline QString IMPORT = "CORE-IMPORT" ;
|
||||
const inline QString EXPORT = "CORE-EXPORT" ;
|
||||
const inline QString MODULE_CONNECTION = "CORE-CONNECTION";
|
||||
const inline QString MODULE_SUBSCRIPTION = "CORE-SUBSCRIPTION";
|
||||
const inline QString MODULE_IMPORT = "CORE-IMPORT";
|
||||
const inline QString MODULE_EXPORT = "CORE-EXPORT";
|
||||
//
|
||||
const inline QString NETWORK = "COMMON-NETWORK" ;
|
||||
const inline QString FILEIO = "COMMON-FILEIO" ;
|
||||
const inline QString MODULE_NETWORK = "COMMON-NETWORK";
|
||||
const inline QString MODULE_FILEIO = "COMMON-FILEIO";
|
||||
//
|
||||
const inline QString PROXY = "COMPONENT-PROXY" ;
|
||||
const inline QString UPDATE = "COMPONENT-UPDATE" ;
|
||||
const inline QString PLUGIN = "COMPONENT-PLUGIN" ;
|
||||
const inline QString MODULE_PROXY = "COMPONENT-PROXY";
|
||||
const inline QString MODULE_UPDATE = "COMPONENT-UPDATE";
|
||||
const inline QString MODULE_PLUGIN = "COMPONENT-PLUGIN";
|
||||
// ================================================================
|
||||
const inline QString MODULE_CORE_HANDLER = "QV2RAY-CORE";
|
||||
|
@ -1,37 +1,46 @@
|
||||
#pragma once
|
||||
#include <QString>
|
||||
#include "3rdparty/x2struct/x2struct.hpp"
|
||||
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include "3rdparty/x2struct/x2struct.hpp"
|
||||
#include <QString>
|
||||
|
||||
namespace Qv2ray::base::objects
|
||||
{
|
||||
//
|
||||
// Used in config generation
|
||||
struct AccountObject {
|
||||
struct AccountObject
|
||||
{
|
||||
QString user;
|
||||
QString pass;
|
||||
XTOSTRUCT(O(user, pass))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct ApiObject {
|
||||
struct ApiObject
|
||||
{
|
||||
QString tag;
|
||||
QList<QString> services;
|
||||
ApiObject() : tag("api"), services() {}
|
||||
ApiObject() : tag("api"), services()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(tag, services))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct SystemPolicyObject {
|
||||
struct SystemPolicyObject
|
||||
{
|
||||
bool statsInboundUplink;
|
||||
bool statsInboundDownlink;
|
||||
SystemPolicyObject() : statsInboundUplink(), statsInboundDownlink() {}
|
||||
SystemPolicyObject() : statsInboundUplink(), statsInboundDownlink()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(statsInboundUplink, statsInboundDownlink))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct LevelPolicyObject {
|
||||
struct LevelPolicyObject
|
||||
{
|
||||
int handshake;
|
||||
int connIdle;
|
||||
int uplinkOnly;
|
||||
@ -39,20 +48,26 @@ namespace Qv2ray::base::objects
|
||||
bool statsUserUplink;
|
||||
bool statsUserDownlink;
|
||||
int bufferSize;
|
||||
LevelPolicyObject(): handshake(), connIdle(), uplinkOnly(), downlinkOnly(), statsUserUplink(), statsUserDownlink(), bufferSize() {}
|
||||
LevelPolicyObject() : handshake(), connIdle(), uplinkOnly(), downlinkOnly(), statsUserUplink(), statsUserDownlink(), bufferSize()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(handshake, connIdle, uplinkOnly, downlinkOnly, statsUserUplink, statsUserDownlink, bufferSize))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct PolicyObject {
|
||||
struct PolicyObject
|
||||
{
|
||||
QMap<QString, LevelPolicyObject> level;
|
||||
QList<SystemPolicyObject> system;
|
||||
PolicyObject(): level(), system() {}
|
||||
PolicyObject() : level(), system()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(level, system))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct RuleObject {
|
||||
struct RuleObject
|
||||
{
|
||||
// Added due to the request of @aliyuchang33
|
||||
bool QV2RAY_RULE_ENABLED;
|
||||
bool QV2RAY_RULE_USE_BALANCER;
|
||||
@ -70,65 +85,89 @@ namespace Qv2ray::base::objects
|
||||
QString attrs;
|
||||
QString outboundTag;
|
||||
QString balancerTag;
|
||||
RuleObject() : QV2RAY_RULE_ENABLED(true), QV2RAY_RULE_USE_BALANCER(false), QV2RAY_RULE_TAG("new rule"), type("field"), domain(), ip(), port("1-65535"), network(""), source(), user(), inboundTag(), protocol(), attrs(), outboundTag(""), balancerTag("") {}
|
||||
XTOSTRUCT(O(QV2RAY_RULE_ENABLED, QV2RAY_RULE_USE_BALANCER, QV2RAY_RULE_TAG, type, domain, ip, port, network, source, user, inboundTag, protocol, attrs, outboundTag, balancerTag))
|
||||
RuleObject()
|
||||
: QV2RAY_RULE_ENABLED(true), QV2RAY_RULE_USE_BALANCER(false), QV2RAY_RULE_TAG("new rule"), type("field"), domain(), ip(),
|
||||
port("1-65535"), network(""), source(), user(), inboundTag(), protocol(), attrs(), outboundTag(""), balancerTag("")
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(QV2RAY_RULE_ENABLED, QV2RAY_RULE_USE_BALANCER, QV2RAY_RULE_TAG, type, domain, ip, port, network, source, user, inboundTag,
|
||||
protocol, attrs, outboundTag, balancerTag))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct BalancerObject {
|
||||
QString tag ;
|
||||
struct BalancerObject
|
||||
{
|
||||
QString tag;
|
||||
QList<QString> selector;
|
||||
BalancerObject() : tag(), selector() {}
|
||||
BalancerObject() : tag(), selector()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(tag, selector))
|
||||
};
|
||||
//
|
||||
//
|
||||
namespace transfer
|
||||
{
|
||||
struct HTTPRequestObject {
|
||||
struct HTTPRequestObject
|
||||
{
|
||||
QString version;
|
||||
QString method;
|
||||
QList<QString> path;
|
||||
QMap<QString, QList<QString>> headers;
|
||||
HTTPRequestObject(): version("1.1"), method("GET"), path(), headers() {}
|
||||
HTTPRequestObject() : version("1.1"), method("GET"), path(), headers()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(version, method, path, headers))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct HTTPResponseObject {
|
||||
struct HTTPResponseObject
|
||||
{
|
||||
QString version;
|
||||
QString status;
|
||||
QString reason;
|
||||
QMap<QString, QList<QString>> headers;
|
||||
HTTPResponseObject(): version("1.1"), status("200"), reason("OK"), headers() {}
|
||||
HTTPResponseObject() : version("1.1"), status("200"), reason("OK"), headers()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(version, status, reason, headers))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct TCPHeader_M_Object {
|
||||
struct TCPHeader_M_Object
|
||||
{
|
||||
QString type;
|
||||
HTTPRequestObject request;
|
||||
HTTPResponseObject response;
|
||||
TCPHeader_M_Object(): type("none"), request(), response() {}
|
||||
TCPHeader_M_Object() : type("none"), request(), response()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(type, request, response))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct HeaderObject {
|
||||
struct HeaderObject
|
||||
{
|
||||
QString type;
|
||||
HeaderObject(): type("none") {}
|
||||
HeaderObject() : type("none")
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(type))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct TCPObject {
|
||||
struct TCPObject
|
||||
{
|
||||
TCPHeader_M_Object header;
|
||||
TCPObject(): header() {}
|
||||
TCPObject() : header()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(header))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct KCPObject {
|
||||
struct KCPObject
|
||||
{
|
||||
int mtu = 1350;
|
||||
int tti = 20;
|
||||
int uplinkCapacity = 5;
|
||||
@ -137,84 +176,111 @@ namespace Qv2ray::base::objects
|
||||
int readBufferSize = 1;
|
||||
int writeBufferSize = 1;
|
||||
HeaderObject header;
|
||||
KCPObject(): header() {}
|
||||
KCPObject() : header()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(mtu, tti, uplinkCapacity, downlinkCapacity, congestion, readBufferSize, writeBufferSize, header))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct WebSocketObject {
|
||||
struct WebSocketObject
|
||||
{
|
||||
QString path;
|
||||
QMap<QString, QString> headers;
|
||||
WebSocketObject(): path("/"), headers() {}
|
||||
WebSocketObject() : path("/"), headers()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(path, headers))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct HttpObject {
|
||||
struct HttpObject
|
||||
{
|
||||
QList<QString> host;
|
||||
QString path;
|
||||
HttpObject() : host(), path("/") {}
|
||||
HttpObject() : host(), path("/")
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(host, path))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct DomainSocketObject {
|
||||
struct DomainSocketObject
|
||||
{
|
||||
QString path;
|
||||
DomainSocketObject(): path("/") {}
|
||||
DomainSocketObject() : path("/")
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(path))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct QuicObject {
|
||||
struct QuicObject
|
||||
{
|
||||
QString security;
|
||||
QString key;
|
||||
HeaderObject header;
|
||||
QuicObject(): security(""), key(""), header() {}
|
||||
QuicObject() : security(""), key(""), header()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(security, key, header))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct SockoptObject {
|
||||
struct SockoptObject
|
||||
{
|
||||
int mark;
|
||||
bool tcpFastOpen;
|
||||
QString tproxy;
|
||||
SockoptObject(): mark(0), tcpFastOpen(false), tproxy("off") {}
|
||||
SockoptObject() : mark(0), tcpFastOpen(false), tproxy("off")
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(mark, tcpFastOpen, tproxy))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct CertificateObject {
|
||||
struct CertificateObject
|
||||
{
|
||||
QString usage;
|
||||
QString certificateFile;
|
||||
QString keyFile;
|
||||
QList<QString> certificate;
|
||||
QList<QString> key;
|
||||
CertificateObject(): usage(), certificateFile(), keyFile(), certificate(), key() {}
|
||||
CertificateObject() : usage(), certificateFile(), keyFile(), certificate(), key()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(usage, certificateFile, keyFile, certificate, key))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct TLSObject {
|
||||
struct TLSObject
|
||||
{
|
||||
QString serverName;
|
||||
bool allowInsecure;
|
||||
QList<QString> alpn;
|
||||
QList<CertificateObject> certificates;
|
||||
bool disableSystemRoot;
|
||||
TLSObject(): serverName(), allowInsecure(), certificates(), disableSystemRoot() {}
|
||||
TLSObject() : serverName(), allowInsecure(), certificates(), disableSystemRoot()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(serverName, allowInsecure, alpn, certificates, disableSystemRoot))
|
||||
};
|
||||
}
|
||||
} // namespace transfer
|
||||
//
|
||||
//
|
||||
struct SniffingObject {
|
||||
struct SniffingObject
|
||||
{
|
||||
bool enabled = false;
|
||||
QList<QString> destOverride;
|
||||
SniffingObject(): enabled(), destOverride() {}
|
||||
SniffingObject() : enabled(), destOverride()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(enabled, destOverride))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct StreamSettingsObject {
|
||||
struct StreamSettingsObject
|
||||
{
|
||||
QString network;
|
||||
QString security;
|
||||
transfer::SockoptObject sockopt;
|
||||
@ -225,15 +291,22 @@ namespace Qv2ray::base::objects
|
||||
transfer::HttpObject httpSettings;
|
||||
transfer::DomainSocketObject dsSettings;
|
||||
transfer::QuicObject quicSettings;
|
||||
StreamSettingsObject(): network("tcp"), security("none"), sockopt(), tlsSettings(), tcpSettings(), kcpSettings(), wsSettings(), httpSettings(), dsSettings(), quicSettings() {}
|
||||
StreamSettingsObject()
|
||||
: network("tcp"), security("none"), sockopt(), tlsSettings(), tcpSettings(), kcpSettings(), wsSettings(), httpSettings(),
|
||||
dsSettings(), quicSettings()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(network, security, sockopt, tcpSettings, tlsSettings, kcpSettings, wsSettings, httpSettings, dsSettings, quicSettings))
|
||||
};
|
||||
//
|
||||
//
|
||||
struct MuxObject {
|
||||
struct MuxObject
|
||||
{
|
||||
bool enabled;
|
||||
int concurrency;
|
||||
MuxObject(): enabled(), concurrency() {}
|
||||
MuxObject() : enabled(), concurrency()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(enabled, concurrency))
|
||||
};
|
||||
//
|
||||
@ -241,21 +314,28 @@ namespace Qv2ray::base::objects
|
||||
namespace protocol
|
||||
{
|
||||
// DNS, OutBound
|
||||
struct DNSOut {
|
||||
struct DNSOut
|
||||
{
|
||||
QString network;
|
||||
QString address;
|
||||
int port;
|
||||
DNSOut(): network(""), address("0.0.0.0"), port(0) {}
|
||||
DNSOut() : network(""), address("0.0.0.0"), port(0)
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(network, address, port))
|
||||
};
|
||||
//
|
||||
// MTProto, InBound || OutBound
|
||||
struct MTProtoIn {
|
||||
struct UserObject {
|
||||
struct MTProtoIn
|
||||
{
|
||||
struct UserObject
|
||||
{
|
||||
QString email;
|
||||
int level;
|
||||
QString secret;
|
||||
UserObject() : email("user@domain.com"), level(0), secret("") {}
|
||||
UserObject() : email("user@domain.com"), level(0), secret("")
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(email, level, secret))
|
||||
};
|
||||
QList<UserObject> users;
|
||||
@ -263,42 +343,55 @@ namespace Qv2ray::base::objects
|
||||
};
|
||||
//
|
||||
// Socks, OutBound
|
||||
struct SocksServerObject {
|
||||
struct UserObject {
|
||||
struct SocksServerObject
|
||||
{
|
||||
struct UserObject
|
||||
{
|
||||
QString user;
|
||||
QString pass;
|
||||
int level;
|
||||
UserObject(): user("username"), pass("password"), level(0) {}
|
||||
UserObject() : user("username"), pass("password"), level(0)
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(user, pass, level))
|
||||
};
|
||||
|
||||
QString address;
|
||||
int port;
|
||||
QList<UserObject> users;
|
||||
SocksServerObject(): address("0.0.0.0"), port(0), users() {}
|
||||
SocksServerObject() : address("0.0.0.0"), port(0), users()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(address, port, users))
|
||||
};
|
||||
//
|
||||
// VMess Server
|
||||
struct VMessServerObject {
|
||||
struct UserObject {
|
||||
struct VMessServerObject
|
||||
{
|
||||
struct UserObject
|
||||
{
|
||||
QString id;
|
||||
int alterId;
|
||||
QString security;
|
||||
int level;
|
||||
UserObject() : id(""), alterId(64), security("auto"), level(0) {}
|
||||
UserObject() : id(""), alterId(64), security("auto"), level(0)
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(id, alterId, security, level))
|
||||
};
|
||||
|
||||
QString address;
|
||||
int port;
|
||||
QList<UserObject> users;
|
||||
VMessServerObject(): address(""), port(0), users() {}
|
||||
VMessServerObject() : address(""), port(0), users()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(address, port, users))
|
||||
};
|
||||
//
|
||||
// ShadowSocks Server
|
||||
struct ShadowSocksServerObject {
|
||||
struct ShadowSocksServerObject
|
||||
{
|
||||
QString email;
|
||||
QString address;
|
||||
QString method;
|
||||
@ -306,8 +399,11 @@ namespace Qv2ray::base::objects
|
||||
bool ota;
|
||||
int level;
|
||||
int port;
|
||||
ShadowSocksServerObject(): email("user@domain.com"), address("0.0.0.0"), method("aes-256-cfb"), password(""), ota(false), level(0), port(0) {}
|
||||
ShadowSocksServerObject()
|
||||
: email("user@domain.com"), address("0.0.0.0"), method("aes-256-cfb"), password(""), ota(false), level(0), port(0)
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(email, address, port, method, password, ota, level))
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace protocol
|
||||
} // namespace Qv2ray::base::objects
|
||||
|
@ -1,56 +1,50 @@
|
||||
#pragma once
|
||||
#include "3rdparty/x2struct/x2struct.hpp"
|
||||
|
||||
#include <QString>
|
||||
#include <QtCore>
|
||||
#include "3rdparty/x2struct/x2struct.hpp"
|
||||
namespace Qv2ray::base
|
||||
{
|
||||
struct ConnectionIdentifier {
|
||||
QString subscriptionName;
|
||||
QString connectionName;
|
||||
ConnectionIdentifier() { };
|
||||
bool isEmpty()
|
||||
using namespace std::chrono;
|
||||
// Common struct for Groups and Subscriptions
|
||||
struct GroupObject_Config
|
||||
{
|
||||
QString displayName;
|
||||
QList<QString> connections;
|
||||
int64_t importDate;
|
||||
GroupObject_Config() : displayName(), connections(), importDate()
|
||||
{
|
||||
return connectionName.isEmpty();
|
||||
}
|
||||
ConnectionIdentifier(QString connectionName)
|
||||
{
|
||||
this->connectionName = connectionName;
|
||||
}
|
||||
ConnectionIdentifier(QString connectionName, QString subscriptionName)
|
||||
{
|
||||
this->connectionName = connectionName;
|
||||
this->subscriptionName = subscriptionName;
|
||||
}
|
||||
const QString IdentifierString() const
|
||||
{
|
||||
return connectionName + (subscriptionName.isEmpty() ? "" : " (" + subscriptionName + ")");
|
||||
}
|
||||
friend bool operator==(ConnectionIdentifier &left, ConnectionIdentifier &right)
|
||||
{
|
||||
return left.subscriptionName == right.subscriptionName && left.connectionName == right.connectionName;
|
||||
}
|
||||
friend bool operator!=(ConnectionIdentifier &left, ConnectionIdentifier &right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
friend bool operator==(ConnectionIdentifier &left, QString &right)
|
||||
{
|
||||
return left.IdentifierString() == right;
|
||||
}
|
||||
friend bool operator!=(ConnectionIdentifier &left, QString &right)
|
||||
{
|
||||
return !(left.IdentifierString() == right);
|
||||
}
|
||||
// To make QMap happy
|
||||
friend bool operator<(const ConnectionIdentifier left, const ConnectionIdentifier right)
|
||||
{
|
||||
return left.IdentifierString() < right.IdentifierString();
|
||||
}
|
||||
friend bool operator>(const ConnectionIdentifier left, const ConnectionIdentifier right)
|
||||
{
|
||||
return left.IdentifierString() > right.IdentifierString();
|
||||
}
|
||||
XTOSTRUCT(O(subscriptionName, connectionName))
|
||||
XTOSTRUCT(O(displayName, connections, importDate))
|
||||
};
|
||||
}
|
||||
Q_DECLARE_METATYPE(Qv2ray::base::ConnectionIdentifier);
|
||||
|
||||
struct SubscriptionObject_Config : GroupObject_Config
|
||||
{
|
||||
//
|
||||
QString address;
|
||||
int64_t lastUpdated;
|
||||
float updateInterval;
|
||||
SubscriptionObject_Config() : address(""), lastUpdated(system_clock::to_time_t(system_clock::now())), updateInterval(10)
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(lastUpdated, updateInterval, address, connections, displayName, importDate))
|
||||
};
|
||||
|
||||
struct ConnectionObject_Config
|
||||
{
|
||||
QString displayName;
|
||||
int64_t importDate;
|
||||
int64_t lastConnected;
|
||||
int64_t latency;
|
||||
int64_t upLinkData;
|
||||
int64_t downLinkData;
|
||||
ConnectionObject_Config()
|
||||
: displayName(), importDate(system_clock::to_time_t(system_clock::now())), lastConnected(), latency(0), upLinkData(0),
|
||||
downLinkData(0)
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(displayName, importDate, lastConnected, latency, upLinkData, downLinkData))
|
||||
};
|
||||
} // namespace Qv2ray::base
|
||||
|
||||
using namespace Qv2ray::base;
|
||||
|
@ -1,184 +0,0 @@
|
||||
#pragma once
|
||||
#include "3rdparty/x2struct/x2struct.hpp"
|
||||
#include "base/models/CoreObjectModels.hpp"
|
||||
#include "base/models/QvConfigIdentifier.hpp"
|
||||
#include <chrono>
|
||||
|
||||
const int QV2RAY_CONFIG_VERSION = 8;
|
||||
|
||||
namespace Qv2ray::base
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
|
||||
|
||||
struct QvBarLine {
|
||||
QString Family;
|
||||
bool Bold;
|
||||
bool Italic;
|
||||
int ColorA;
|
||||
int ColorR;
|
||||
int ColorG;
|
||||
int ColorB;
|
||||
int ContentType;
|
||||
double Size;
|
||||
QString Message;
|
||||
QvBarLine()
|
||||
: Family("Consolas")
|
||||
, Bold(true)
|
||||
, Italic(false)
|
||||
, ColorA(255), ColorR(255), ColorG(255), ColorB(255)
|
||||
, ContentType(0)
|
||||
, Size(9),
|
||||
Message("") { }
|
||||
XTOSTRUCT(O(Bold, Italic, ColorA, ColorR, ColorG, ColorB, Size, Family, Message, ContentType))
|
||||
};
|
||||
|
||||
struct QvBarPage {
|
||||
int OffsetYpx;
|
||||
QList<QvBarLine> Lines;
|
||||
QvBarPage() : OffsetYpx(5) { }
|
||||
XTOSTRUCT(O(OffsetYpx, Lines))
|
||||
};
|
||||
|
||||
struct Qv2rayToolBarConfig {
|
||||
QList<QvBarPage> Pages;
|
||||
XTOSTRUCT(O(Pages))
|
||||
};
|
||||
|
||||
struct Qv2raySubscriptionConfig {
|
||||
time_t lastUpdated;
|
||||
float updateInterval;
|
||||
QString address;
|
||||
Qv2raySubscriptionConfig() : lastUpdated(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())), updateInterval(5), address("") { }
|
||||
XTOSTRUCT(O(lastUpdated, updateInterval, address))
|
||||
};
|
||||
|
||||
struct Qv2rayPACConfig {
|
||||
bool enablePAC;
|
||||
int port;
|
||||
QString localIP;
|
||||
bool useSocksProxy;
|
||||
Qv2rayPACConfig() : enablePAC(false), port(8989), useSocksProxy(false) { }
|
||||
XTOSTRUCT(O(enablePAC, port, localIP, useSocksProxy))
|
||||
};
|
||||
|
||||
struct Qv2rayForwardProxyConfig {
|
||||
bool enableForwardProxy;
|
||||
QString type;
|
||||
QString serverAddress;
|
||||
int port;
|
||||
bool useAuth;
|
||||
QString username;
|
||||
QString password;
|
||||
|
||||
Qv2rayForwardProxyConfig() :
|
||||
enableForwardProxy(false),
|
||||
type("http"), serverAddress("127.0.0.1"), port(8008), useAuth(false),
|
||||
username("username"), password("password")
|
||||
{ }
|
||||
|
||||
XTOSTRUCT(O(enableForwardProxy, type, serverAddress, port, useAuth, username, password))
|
||||
};
|
||||
|
||||
struct Qv2rayInboundsConfig {
|
||||
QString listenip;
|
||||
bool setSystemProxy;
|
||||
Qv2rayPACConfig pacConfig;
|
||||
|
||||
// SOCKS
|
||||
bool useSocks;
|
||||
int socks_port;
|
||||
bool socks_useAuth;
|
||||
bool socksUDP;
|
||||
QString socksLocalIP;
|
||||
objects::AccountObject socksAccount;
|
||||
// HTTP
|
||||
bool useHTTP;
|
||||
int http_port;
|
||||
bool http_useAuth;
|
||||
objects::AccountObject httpAccount;
|
||||
|
||||
Qv2rayInboundsConfig():
|
||||
listenip("127.0.0.1"), setSystemProxy(false), pacConfig(),
|
||||
useSocks(true), socks_port(1088), socks_useAuth(false), socksUDP(true), socksLocalIP("127.0.0.1"), socksAccount(),
|
||||
useHTTP(true), http_port(8888), http_useAuth(false), httpAccount() {}
|
||||
|
||||
XTOSTRUCT(O(setSystemProxy, pacConfig, listenip, useSocks, useHTTP, socks_port, socks_useAuth, socksAccount, socksUDP, socksLocalIP, http_port, http_useAuth, httpAccount))
|
||||
};
|
||||
|
||||
struct Qv2rayUIConfig {
|
||||
QString theme;
|
||||
QString language;
|
||||
bool useDarkTheme;
|
||||
bool useDarkTrayIcon;
|
||||
int maximumLogLines;
|
||||
Qv2rayUIConfig() : theme("Fusion"), language("en_US"), useDarkTheme(false), useDarkTrayIcon(true), maximumLogLines(500) { }
|
||||
XTOSTRUCT(O(theme, language, useDarkTheme, useDarkTrayIcon, maximumLogLines))
|
||||
};
|
||||
|
||||
struct Qv2rayConnectionConfig {
|
||||
bool bypassCN;
|
||||
bool enableProxy;
|
||||
bool withLocalDNS;
|
||||
QList<QString> dnsList;
|
||||
Qv2rayForwardProxyConfig forwardProxyConfig;
|
||||
|
||||
Qv2rayConnectionConfig() : bypassCN(true), enableProxy(true), withLocalDNS(false), dnsList(QStringList() << "8.8.4.4" << "1.1.1.1") { }
|
||||
XTOSTRUCT(O(bypassCN, enableProxy, withLocalDNS, dnsList, forwardProxyConfig))
|
||||
};
|
||||
|
||||
struct Qv2rayAPIConfig {
|
||||
bool enableAPI;
|
||||
int statsPort;
|
||||
Qv2rayAPIConfig(): enableAPI(true), statsPort(15490) { }
|
||||
XTOSTRUCT(O(enableAPI, statsPort))
|
||||
};
|
||||
|
||||
struct Qv2rayConfig {
|
||||
int config_version;
|
||||
bool tProxySupport;
|
||||
int logLevel;
|
||||
//
|
||||
QString v2CorePath;
|
||||
QString v2AssetsPath;
|
||||
ConnectionIdentifier autoStartConfig;
|
||||
QString ignoredVersion;
|
||||
//
|
||||
QList<QString> configs;
|
||||
QMap<QString, Qv2raySubscriptionConfig> subscriptions;
|
||||
//
|
||||
Qv2rayUIConfig uiConfig;
|
||||
Qv2rayAPIConfig apiConfig;
|
||||
Qv2rayInboundsConfig inboundConfig;
|
||||
Qv2rayConnectionConfig connectionConfig;
|
||||
Qv2rayToolBarConfig toolBarConfig;
|
||||
|
||||
Qv2rayConfig():
|
||||
config_version(QV2RAY_CONFIG_VERSION),
|
||||
tProxySupport(false),
|
||||
logLevel(),
|
||||
v2CorePath(),
|
||||
v2AssetsPath(),
|
||||
autoStartConfig(),
|
||||
ignoredVersion(),
|
||||
configs(),
|
||||
subscriptions(),
|
||||
uiConfig(),
|
||||
apiConfig(),
|
||||
inboundConfig(),
|
||||
connectionConfig(),
|
||||
toolBarConfig() { }
|
||||
|
||||
XTOSTRUCT(O(config_version,
|
||||
ignoredVersion,
|
||||
tProxySupport,
|
||||
logLevel,
|
||||
autoStartConfig,
|
||||
v2CorePath, v2AssetsPath,
|
||||
configs,
|
||||
uiConfig,
|
||||
subscriptions, inboundConfig, connectionConfig, toolBarConfig, apiConfig))
|
||||
};
|
||||
}
|
||||
}
|
@ -5,8 +5,9 @@
|
||||
|
||||
namespace Qv2ray::base
|
||||
{
|
||||
struct Qv2rayRuntimeConfig {
|
||||
//
|
||||
struct Qv2rayRuntimeConfig
|
||||
{
|
||||
bool screenShotHideQv2ray = false;
|
||||
};
|
||||
}
|
||||
inline base::Qv2rayRuntimeConfig RuntimeConfig = base::Qv2rayRuntimeConfig();
|
||||
} // namespace Qv2ray::base
|
||||
|
@ -1,17 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#define SAFE_TYPEDEF(Base, name) \
|
||||
class name : public Base { \
|
||||
public: \
|
||||
template <class... Args> \
|
||||
explicit name (Args... args) : Base(args...) {} \
|
||||
const Base& raw() const { return *this; } \
|
||||
#define SAFE_TYPEDEF_EXTRA(Base, name, extra) \
|
||||
class name : public Base \
|
||||
{ \
|
||||
public: \
|
||||
template<class... Args> \
|
||||
explicit name(Args... args) : Base(args...) \
|
||||
{ \
|
||||
} \
|
||||
const Base &raw() const \
|
||||
{ \
|
||||
return *this; \
|
||||
} \
|
||||
extra \
|
||||
};
|
||||
|
||||
#define nothing
|
||||
#define SAFE_TYPEDEF(Base, name) SAFE_TYPEDEF_EXTRA(Base, name, nothing)
|
||||
|
||||
using namespace std;
|
||||
namespace Qv2ray::base::safetype
|
||||
{
|
||||
// To prevent anonying QJsonObject misuse
|
||||
@ -22,10 +32,10 @@ namespace Qv2ray::base::safetype
|
||||
SAFE_TYPEDEF(QJsonObject, CONFIGROOT)
|
||||
SAFE_TYPEDEF(QJsonObject, PROXYSETTING)
|
||||
//
|
||||
SAFE_TYPEDEF(QJsonArray, ROUTERULELIST)
|
||||
SAFE_TYPEDEF(QJsonArray, INOUTLIST)
|
||||
SAFE_TYPEDEF(INOUTLIST, OUTBOUNDS)
|
||||
SAFE_TYPEDEF(INOUTLIST, INBOUNDS)
|
||||
SAFE_TYPEDEF(QJsonObject, ROUTING)
|
||||
SAFE_TYPEDEF(QJsonObject, ROUTERULE)
|
||||
SAFE_TYPEDEF(QJsonArray, ROUTERULELIST)
|
||||
}
|
||||
SAFE_TYPEDEF(INOUTLIST, OUTBOUNDS)
|
||||
SAFE_TYPEDEF(INOUTLIST, INBOUNDS)
|
||||
} // namespace Qv2ray::base::safetype
|
||||
|
209
src/base/models/QvSettingsObject.hpp
Normal file
@ -0,0 +1,209 @@
|
||||
#pragma once
|
||||
#include "3rdparty/x2struct/x2struct.hpp"
|
||||
#include "base/models/CoreObjectModels.hpp"
|
||||
#include "base/models/QvConfigIdentifier.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
const int QV2RAY_CONFIG_VERSION = 10;
|
||||
|
||||
namespace Qv2ray::base::config
|
||||
{
|
||||
struct QvBarLine
|
||||
{
|
||||
QString Family;
|
||||
bool Bold, Italic;
|
||||
int ColorA, ColorR, ColorG, ColorB;
|
||||
int ContentType;
|
||||
double Size;
|
||||
QString Message;
|
||||
QvBarLine()
|
||||
: Family("Consolas"), Bold(true), Italic(false), ColorA(255), ColorR(255), ColorG(255), ColorB(255), ContentType(0), Size(9),
|
||||
Message("")
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(Bold, Italic, ColorA, ColorR, ColorG, ColorB, Size, Family, Message, ContentType))
|
||||
};
|
||||
|
||||
struct QvBarPage
|
||||
{
|
||||
int OffsetYpx;
|
||||
QList<QvBarLine> Lines;
|
||||
QvBarPage() : OffsetYpx(5)
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(OffsetYpx, Lines))
|
||||
};
|
||||
|
||||
struct Qv2rayToolBarConfig
|
||||
{
|
||||
QList<QvBarPage> Pages;
|
||||
XTOSTRUCT(O(Pages))
|
||||
};
|
||||
|
||||
struct Qv2rayPACConfig
|
||||
{
|
||||
bool enablePAC;
|
||||
int port;
|
||||
QString localIP;
|
||||
bool useSocksProxy;
|
||||
Qv2rayPACConfig() : enablePAC(false), port(8989), useSocksProxy(false)
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(enablePAC, port, localIP, useSocksProxy))
|
||||
};
|
||||
|
||||
struct Qv2rayForwardProxyConfig
|
||||
{
|
||||
bool enableForwardProxy;
|
||||
QString type;
|
||||
QString serverAddress;
|
||||
int port;
|
||||
bool useAuth;
|
||||
QString username;
|
||||
QString password;
|
||||
Qv2rayForwardProxyConfig()
|
||||
: enableForwardProxy(false), type("http"), serverAddress("127.0.0.1"), port(8008), useAuth(false), username(), password()
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(enableForwardProxy, type, serverAddress, port, useAuth, username, password))
|
||||
};
|
||||
|
||||
struct Qv2rayInboundsConfig
|
||||
{
|
||||
QString listenip;
|
||||
bool setSystemProxy;
|
||||
Qv2rayPACConfig pacConfig;
|
||||
|
||||
// SOCKS
|
||||
bool useSocks;
|
||||
int socks_port;
|
||||
bool socks_useAuth;
|
||||
bool socksUDP;
|
||||
QString socksLocalIP;
|
||||
objects::AccountObject socksAccount;
|
||||
// HTTP
|
||||
bool useHTTP;
|
||||
int http_port;
|
||||
bool http_useAuth;
|
||||
objects::AccountObject httpAccount;
|
||||
|
||||
Qv2rayInboundsConfig()
|
||||
: listenip("127.0.0.1"), setSystemProxy(true), pacConfig(), useSocks(true), socks_port(1088), socks_useAuth(false), socksUDP(true),
|
||||
socksLocalIP("127.0.0.1"), socksAccount(), useHTTP(true), http_port(8888), http_useAuth(false), httpAccount()
|
||||
{
|
||||
}
|
||||
|
||||
XTOSTRUCT(O(setSystemProxy, pacConfig, listenip, useSocks, useHTTP, socks_port, socks_useAuth, socksAccount, socksUDP, socksLocalIP,
|
||||
http_port, http_useAuth, httpAccount))
|
||||
};
|
||||
|
||||
struct Qv2rayUIConfig
|
||||
{
|
||||
QString theme;
|
||||
QString language;
|
||||
bool useDarkTheme;
|
||||
bool useDarkTrayIcon;
|
||||
int maximumLogLines;
|
||||
Qv2rayUIConfig() : theme("Fusion"), language("en_US"), useDarkTheme(false), useDarkTrayIcon(true), maximumLogLines(500)
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(theme, language, useDarkTheme, useDarkTrayIcon, maximumLogLines))
|
||||
};
|
||||
|
||||
struct Qv2rayConnectionConfig
|
||||
{
|
||||
bool bypassCN;
|
||||
bool enableProxy;
|
||||
bool withLocalDNS;
|
||||
QList<QString> dnsList;
|
||||
Qv2rayForwardProxyConfig forwardProxyConfig;
|
||||
Qv2rayConnectionConfig() : bypassCN(true), enableProxy(true), withLocalDNS(false), dnsList(QStringList{ "8.8.4.4", "1.1.1.1" })
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(bypassCN, enableProxy, withLocalDNS, dnsList, forwardProxyConfig))
|
||||
};
|
||||
|
||||
struct Qv2rayAPIConfig
|
||||
{
|
||||
bool enableAPI;
|
||||
int statsPort;
|
||||
Qv2rayAPIConfig() : enableAPI(true), statsPort(15490)
|
||||
{
|
||||
}
|
||||
XTOSTRUCT(O(enableAPI, statsPort))
|
||||
};
|
||||
|
||||
struct Qv2rayKernelConfig
|
||||
{
|
||||
QString v2CorePath_linux;
|
||||
QString v2AssetsPath_linux;
|
||||
QString v2CorePath_macx;
|
||||
QString v2AssetsPath_macx;
|
||||
QString v2CorePath_win;
|
||||
QString v2AssetsPath_win; //
|
||||
Qv2rayKernelConfig()
|
||||
: v2CorePath_linux(), v2AssetsPath_linux(), //
|
||||
v2CorePath_macx(), v2AssetsPath_macx(), //
|
||||
v2CorePath_win(), v2AssetsPath_win() //
|
||||
{
|
||||
}
|
||||
//
|
||||
#ifdef Q_OS_LINUX
|
||||
#define _VARNAME_VCOREPATH_ v2CorePath_linux
|
||||
#define _VARNAME_VASSETSPATH_ v2AssetsPath_linux
|
||||
#elif defined(Q_OS_MACOS)
|
||||
#define _VARNAME_VCOREPATH_ v2CorePath_macx
|
||||
#define _VARNAME_VASSETSPATH_ v2AssetsPath_macx
|
||||
#elif defined(Q_OS_WIN)
|
||||
#define _VARNAME_VCOREPATH_ v2CorePath_win
|
||||
#define _VARNAME_VASSETSPATH_ v2AssetsPath_win
|
||||
#endif
|
||||
|
||||
inline const QString KernelPath(const QString &path = "")
|
||||
{
|
||||
return path.isEmpty() ? _VARNAME_VCOREPATH_ : _VARNAME_VCOREPATH_ = path;
|
||||
}
|
||||
inline const QString AssetsPath(const QString &path = "")
|
||||
{
|
||||
return path.isEmpty() ? _VARNAME_VASSETSPATH_ : _VARNAME_VASSETSPATH_ = path;
|
||||
}
|
||||
|
||||
#undef _VARNAME_VCOREPATH_
|
||||
#undef _VARNAME_VASSETSPATH_
|
||||
|
||||
XTOSTRUCT(O(v2CorePath_linux, v2AssetsPath_linux, v2CorePath_macx, v2AssetsPath_macx, v2CorePath_win, v2AssetsPath_win))
|
||||
};
|
||||
|
||||
struct Qv2rayConfig
|
||||
{
|
||||
int config_version;
|
||||
bool tProxySupport;
|
||||
int logLevel;
|
||||
//
|
||||
QString ignoredVersion;
|
||||
QString autoStartId;
|
||||
//
|
||||
// Key = groupId, connectionId
|
||||
QMap<QString, GroupObject_Config> groups;
|
||||
QMap<QString, SubscriptionObject_Config> subscriptions;
|
||||
/// Connections are used privately.
|
||||
QMap<QString, ConnectionObject_Config> connections;
|
||||
//
|
||||
Qv2rayUIConfig uiConfig;
|
||||
Qv2rayAPIConfig apiConfig;
|
||||
Qv2rayKernelConfig kernelConfig;
|
||||
Qv2rayToolBarConfig toolBarConfig;
|
||||
Qv2rayInboundsConfig inboundConfig;
|
||||
Qv2rayConnectionConfig connectionConfig;
|
||||
|
||||
Qv2rayConfig()
|
||||
: config_version(QV2RAY_CONFIG_VERSION), tProxySupport(false), logLevel(), ignoredVersion(), autoStartId("null"), groups(),
|
||||
subscriptions(), connections(), uiConfig(), apiConfig(), kernelConfig(), toolBarConfig(), inboundConfig(), connectionConfig()
|
||||
{
|
||||
}
|
||||
|
||||
XTOSTRUCT(O(config_version, ignoredVersion, tProxySupport, logLevel, uiConfig, kernelConfig, groups, connections, subscriptions,
|
||||
autoStartId, inboundConfig, connectionConfig, toolBarConfig, apiConfig))
|
||||
};
|
||||
} // namespace Qv2ray::base::config
|
@ -4,7 +4,8 @@ namespace Qv2ray
|
||||
{
|
||||
namespace base
|
||||
{
|
||||
struct QvStartupOptions {
|
||||
struct QvStartupOptions
|
||||
{
|
||||
/// No API subsystem
|
||||
bool noAPI;
|
||||
/// Explicitly run as root user.
|
||||
@ -14,5 +15,6 @@ namespace Qv2ray
|
||||
/// Enable Network toolbar plugin.
|
||||
bool enableToolbarPlguin;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace base
|
||||
inline base::QvStartupOptions StartupOption = base::QvStartupOptions();
|
||||
} // namespace Qv2ray
|
||||
|
@ -1,15 +1,16 @@
|
||||
#include "CommandArgs.hpp"
|
||||
|
||||
#include "base/Qv2rayBase.hpp"
|
||||
|
||||
namespace Qv2ray::common
|
||||
{
|
||||
QvCommandArgParser::QvCommandArgParser() : QObject(),
|
||||
noAPIOption("noAPI", QObject::tr("Disable gRPC API subsystems.")),
|
||||
runAsRootOption("I-just-wanna-run-with-root", QObject::tr("Explicitly run Qv2ray as root.")),
|
||||
debugOption("debug", QObject::tr("Enable Debug Output")),
|
||||
withToolbarOption("withToolbarPlugin", QObject::tr("Enable Qv2ray network toolbar plugin")),
|
||||
//
|
||||
helpOption("FAKE"), versionOption("FAKE")
|
||||
QvCommandArgParser::QvCommandArgParser()
|
||||
: QObject(), noAPIOption("noAPI", QObject::tr("Disable gRPC API subsystems.")),
|
||||
runAsRootOption("I-just-wanna-run-with-root", QObject::tr("Explicitly run Qv2ray as root.")),
|
||||
debugOption("debug", QObject::tr("Enable Debug Output")),
|
||||
withToolbarOption("withToolbarPlugin", QObject::tr("Enable Qv2ray network toolbar plugin")),
|
||||
//
|
||||
helpOption("FAKE"), versionOption("FAKE")
|
||||
{
|
||||
parser.setApplicationDescription(QObject::tr("Qv2ray - A cross-platform Qt frontend for V2ray."));
|
||||
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
|
||||
@ -24,7 +25,8 @@ namespace Qv2ray::common
|
||||
|
||||
CommandLineParseResult QvCommandArgParser::ParseCommandLine(QString *errorMessage)
|
||||
{
|
||||
if (!parser.parse(QCoreApplication::arguments())) {
|
||||
if (!parser.parse(QCoreApplication::arguments()))
|
||||
{
|
||||
*errorMessage = parser.errorText();
|
||||
return CommandLineError;
|
||||
}
|
||||
@ -35,27 +37,31 @@ namespace Qv2ray::common
|
||||
if (parser.isSet(helpOption))
|
||||
return CommandLineHelpRequested;
|
||||
|
||||
if (parser.isSet(noAPIOption)) {
|
||||
DEBUG(INIT, "noAPIOption is set.")
|
||||
if (parser.isSet(noAPIOption))
|
||||
{
|
||||
DEBUG(MODULE_INIT, "noAPIOption is set.")
|
||||
StartupOption.noAPI = true;
|
||||
}
|
||||
|
||||
if (parser.isSet(runAsRootOption)) {
|
||||
DEBUG(INIT, "runAsRootOption is set.")
|
||||
if (parser.isSet(runAsRootOption))
|
||||
{
|
||||
DEBUG(MODULE_INIT, "runAsRootOption is set.")
|
||||
StartupOption.forceRunAsRootUser = true;
|
||||
}
|
||||
|
||||
if (parser.isSet(debugOption)) {
|
||||
DEBUG(INIT, "debugOption is set.")
|
||||
if (parser.isSet(debugOption))
|
||||
{
|
||||
DEBUG(MODULE_INIT, "debugOption is set.")
|
||||
StartupOption.debugLog = true;
|
||||
}
|
||||
|
||||
if (parser.isSet(withToolbarOption)) {
|
||||
DEBUG(INIT, "withToolbarOption is set.")
|
||||
if (parser.isSet(withToolbarOption))
|
||||
{
|
||||
DEBUG(MODULE_INIT, "withToolbarOption is set.")
|
||||
StartupOption.enableToolbarPlguin = true;
|
||||
}
|
||||
|
||||
return CommandLineOk;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Qv2ray::common
|
||||
|
@ -4,7 +4,8 @@
|
||||
|
||||
namespace Qv2ray::common
|
||||
{
|
||||
enum CommandLineParseResult {
|
||||
enum CommandLineParseResult
|
||||
{
|
||||
CommandLineOk,
|
||||
CommandLineError,
|
||||
CommandLineVersionRequested,
|
||||
@ -12,24 +13,24 @@ namespace Qv2ray::common
|
||||
};
|
||||
class QvCommandArgParser : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QvCommandArgParser();
|
||||
CommandLineParseResult ParseCommandLine(QString *errorMessage);
|
||||
const QCommandLineParser *Parser()
|
||||
{
|
||||
return &parser;
|
||||
}
|
||||
Q_OBJECT
|
||||
public:
|
||||
QvCommandArgParser();
|
||||
CommandLineParseResult ParseCommandLine(QString *errorMessage);
|
||||
const QCommandLineParser *Parser()
|
||||
{
|
||||
return &parser;
|
||||
}
|
||||
|
||||
private:
|
||||
QCommandLineParser parser;
|
||||
QCommandLineOption noAPIOption;
|
||||
QCommandLineOption runAsRootOption;
|
||||
QCommandLineOption debugOption;
|
||||
QCommandLineOption withToolbarOption;
|
||||
QCommandLineOption helpOption;
|
||||
QCommandLineOption versionOption;
|
||||
private:
|
||||
QCommandLineParser parser;
|
||||
QCommandLineOption noAPIOption;
|
||||
QCommandLineOption runAsRootOption;
|
||||
QCommandLineOption debugOption;
|
||||
QCommandLineOption withToolbarOption;
|
||||
QCommandLineOption helpOption;
|
||||
QCommandLineOption versionOption;
|
||||
};
|
||||
}
|
||||
} // namespace Qv2ray::common
|
||||
|
||||
using namespace Qv2ray::common;
|
||||
|
@ -1,11 +1,13 @@
|
||||
#include "HTTPRequestHelper.hpp"
|
||||
|
||||
#include "base/Qv2rayBase.hpp"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QNetworkProxy>
|
||||
#include "base/Qv2rayBase.hpp"
|
||||
|
||||
namespace Qv2ray::common
|
||||
{
|
||||
QvHttpRequestHelper::QvHttpRequestHelper() : reply()
|
||||
QvHttpRequestHelper::QvHttpRequestHelper(QObject *parent) : QObject(parent), reply()
|
||||
{
|
||||
}
|
||||
|
||||
@ -18,8 +20,9 @@ namespace Qv2ray::common
|
||||
{
|
||||
QUrl qUrl = QUrl(url);
|
||||
|
||||
if (!qUrl.isValid()) {
|
||||
LOG(NETWORK, "Provided URL is invalid: " + url)
|
||||
if (!qUrl.isValid())
|
||||
{
|
||||
LOG(MODULE_NETWORK, "Provided URL is invalid: " + url)
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -29,7 +32,7 @@ namespace Qv2ray::common
|
||||
|
||||
void QvHttpRequestHelper::setHeader(const QByteArray &key, const QByteArray &value)
|
||||
{
|
||||
DEBUG(NETWORK, "Adding HTTP request header: " + key + ":" + value)
|
||||
DEBUG(MODULE_NETWORK, "Adding HTTP request header: " + key + ":" + value)
|
||||
request.setRawHeader(key, value);
|
||||
}
|
||||
|
||||
@ -37,17 +40,22 @@ namespace Qv2ray::common
|
||||
{
|
||||
this->setUrl(url);
|
||||
|
||||
if (useProxy) {
|
||||
if (useProxy)
|
||||
{
|
||||
auto proxy = QNetworkProxyFactory::systemProxyForQuery();
|
||||
accessManager.setProxy(proxy.first());
|
||||
} else {
|
||||
LOG(MODULE_NETWORK, "Sync get is using system proxy settings")
|
||||
}
|
||||
else
|
||||
{
|
||||
accessManager.setProxy(QNetworkProxy(QNetworkProxy::ProxyType::NoProxy));
|
||||
}
|
||||
|
||||
LOG(NETWORK, "Sync get is using system proxy settings")
|
||||
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true);
|
||||
request.setHeader(QNetworkRequest::KnownHeaders::UserAgentHeader, "Mozilla/5.0 (rv:71.0) Gecko/20100101 Firefox/71.0");
|
||||
reply = accessManager.get(request);
|
||||
connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished);
|
||||
connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished_p);
|
||||
//
|
||||
QEventLoop loop;
|
||||
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||
@ -60,28 +68,34 @@ namespace Qv2ray::common
|
||||
void QvHttpRequestHelper::get(const QString &url)
|
||||
{
|
||||
this->setUrl(url);
|
||||
// request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
// request.setRawHeader("Content-Type",
|
||||
// "application/x-www-form-urlencoded");
|
||||
reply = accessManager.get(request);
|
||||
connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished);
|
||||
connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished_p);
|
||||
connect(reply, &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead);
|
||||
}
|
||||
|
||||
//void QvHttpRequestHelper::post(const QString &url, const QByteArray &data)
|
||||
// void QvHttpRequestHelper::post(const QString &url, const QByteArray
|
||||
// &data)
|
||||
//{
|
||||
// this->setUrl(url);
|
||||
// request.setRawHeader("Content-Type", "application/json");
|
||||
// reply = accessManager.post(request, data);
|
||||
// connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished);
|
||||
// connect(reply, &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead);
|
||||
// connect(reply, &QNetworkReply::finished, this,
|
||||
// &QvHttpRequestHelper::onRequestFinished); connect(reply,
|
||||
// &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead);
|
||||
//}
|
||||
|
||||
// void QvHttpRequestHelper::put(const QString &url, const QByteArray &data)
|
||||
// void QvHttpRequestHelper::put(const QString &url, const QByteArray
|
||||
// &data)
|
||||
// {
|
||||
// this->setUrl(url);
|
||||
// request.setRawHeader("Content-Type", "application/json");
|
||||
// reply = accessManager.put(request, data);
|
||||
// connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished);
|
||||
// connect(reply, &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead);
|
||||
// connect(reply, &QNetworkReply::finished, this,
|
||||
// &QvHttpRequestHelper::onRequestFinished); connect(reply,
|
||||
// &QNetworkReply::readyRead, this,
|
||||
// &QvHttpRequestHelper::onReadyRead);
|
||||
// }
|
||||
|
||||
// void QvHttpRequestHelper::del(const QString &url)
|
||||
@ -89,28 +103,46 @@ namespace Qv2ray::common
|
||||
// this->setUrl(url);
|
||||
// request.setRawHeader("Content-Type", "application/json");
|
||||
// reply = accessManager.deleteResource(request);
|
||||
// connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished);
|
||||
// connect(reply, &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead);
|
||||
// connect(reply, &QNetworkReply::finished, this,
|
||||
// &QvHttpRequestHelper::onRequestFinished); connect(reply,
|
||||
// &QNetworkReply::readyRead, this,
|
||||
// &QvHttpRequestHelper::onReadyRead);
|
||||
// }
|
||||
|
||||
// void QvHttpRequestHelper::login(const QString &url, const QByteArray &data)
|
||||
// void QvHttpRequestHelper::login(const QString &url, const QByteArray
|
||||
// &data)
|
||||
// {
|
||||
// this->setUrl(url);
|
||||
// request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
// reply = accessManager.post(request, data);
|
||||
// connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished);
|
||||
// connect(reply, &QNetworkReply::readyRead, this, &QvHttpRequestHelper::onReadyRead);
|
||||
// request.setRawHeader("Content-Type",
|
||||
// "application/x-www-form-urlencoded"); reply =
|
||||
// accessManager.post(request, data); connect(reply,
|
||||
// &QNetworkReply::finished, this,
|
||||
// &QvHttpRequestHelper::onRequestFinished); connect(reply,
|
||||
// &QNetworkReply::readyRead, this,
|
||||
// &QvHttpRequestHelper::onReadyRead);
|
||||
// }
|
||||
|
||||
void QvHttpRequestHelper::onRequestFinished()
|
||||
void QvHttpRequestHelper::onRequestFinished_p()
|
||||
{
|
||||
LOG(NETWORK, "Network request errcode: " + QSTRN(reply->error()))
|
||||
if (reply->attribute(QNetworkRequest::HTTP2WasUsedAttribute).toBool())
|
||||
{
|
||||
DEBUG(MODULE_NETWORK, "HTTP/2 was used.")
|
||||
}
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
QString error = QMetaEnum::fromType<QNetworkReply::NetworkError>().key(reply->error());
|
||||
LOG(MODULE_NETWORK, "Network request error string: " + error)
|
||||
QByteArray empty;
|
||||
emit httpRequestFinished(empty);
|
||||
}
|
||||
|
||||
emit httpRequestFinished(this->data);
|
||||
}
|
||||
|
||||
void QvHttpRequestHelper::onReadyRead()
|
||||
{
|
||||
DEBUG(NETWORK, "A request is now ready read")
|
||||
DEBUG(MODULE_NETWORK, "A request is now ready read")
|
||||
this->data += reply->readAll();
|
||||
}
|
||||
}
|
||||
} // namespace Qv2ray::common
|
||||
|
@ -18,45 +18,46 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QObject>
|
||||
|
||||
namespace Qv2ray::common
|
||||
{
|
||||
class QvHttpRequestHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QvHttpRequestHelper();
|
||||
~QvHttpRequestHelper();
|
||||
bool setUrl(const QString &url);
|
||||
void setHeader(const QByteArray &key, const QByteArray &value);
|
||||
// get
|
||||
QByteArray syncget(const QString &url, bool useProxy);
|
||||
void get(const QString &url);
|
||||
//// insert
|
||||
//void post(const QString &url, const QByteArray &data);
|
||||
//// update
|
||||
//void put(const QString &url, const QByteArray &data);
|
||||
//// delete
|
||||
//void del(const QString &url);
|
||||
//void login(const QString &url, const QByteArray &data);
|
||||
signals:
|
||||
void httpRequestFinished(QByteArray &data);
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QvHttpRequestHelper(QObject *parent = nullptr);
|
||||
~QvHttpRequestHelper();
|
||||
bool setUrl(const QString &url);
|
||||
void setHeader(const QByteArray &key, const QByteArray &value);
|
||||
// get
|
||||
QByteArray syncget(const QString &url, bool useProxy);
|
||||
void get(const QString &url);
|
||||
//// insert
|
||||
// void post(const QString &url, const QByteArray &data);
|
||||
//// update
|
||||
// void put(const QString &url, const QByteArray &data);
|
||||
//// delete
|
||||
// void del(const QString &url);
|
||||
// void login(const QString &url, const QByteArray &data);
|
||||
signals:
|
||||
void httpRequestFinished(QByteArray &data);
|
||||
|
||||
public slots:
|
||||
void onRequestFinished();
|
||||
private slots:
|
||||
void onReadyRead();
|
||||
private:
|
||||
QByteArray data;
|
||||
QUrl url;
|
||||
QNetworkReply *reply;
|
||||
QNetworkRequest request;
|
||||
QNetworkAccessManager accessManager;
|
||||
public slots:
|
||||
void onRequestFinished_p();
|
||||
private slots:
|
||||
void onReadyRead();
|
||||
|
||||
private:
|
||||
QByteArray data;
|
||||
QUrl url;
|
||||
QNetworkReply *reply;
|
||||
QNetworkRequest request;
|
||||
QNetworkAccessManager accessManager;
|
||||
};
|
||||
}
|
||||
} // namespace Qv2ray::common
|
||||
|
||||
using namespace Qv2ray::common;
|
||||
|
111
src/common/JsonHighlighter.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
#include "JsonHighlighter.hpp"
|
||||
|
||||
#include "core/settings/SettingsBackend.hpp"
|
||||
|
||||
namespace Qv2ray::common
|
||||
{
|
||||
vCoreConfigJsonHighlighter::vCoreConfigJsonHighlighter(QTextDocument *parent) : QSyntaxHighlighter(parent)
|
||||
{
|
||||
QTextCharFormat keywordFormat;
|
||||
keywordFormat.setForeground(GlobalConfig.uiConfig.useDarkTheme ? Qt::GlobalColor::magenta : Qt::darkMagenta);
|
||||
keywordFormat.setFontWeight(QFont::Bold);
|
||||
// It's holy a dirty hack here, we'll fully ultilize the vCoreConfig models.
|
||||
auto keywordPatterns = { "inbounds",
|
||||
"outbounds",
|
||||
"routing",
|
||||
"settings",
|
||||
"transport",
|
||||
"request",
|
||||
"headers",
|
||||
"ip",
|
||||
"tag",
|
||||
"protocol",
|
||||
"listen",
|
||||
"rules",
|
||||
"port",
|
||||
"reverse",
|
||||
"dsSettings",
|
||||
"httpSettings",
|
||||
"kcpSettings",
|
||||
"network",
|
||||
"quicSettings",
|
||||
"security",
|
||||
"sockopt",
|
||||
"tcpSettings",
|
||||
"tlsSettings",
|
||||
"wsSettings",
|
||||
"streamSettings",
|
||||
"mux",
|
||||
"sendThrough",
|
||||
"vnext",
|
||||
"address",
|
||||
"users",
|
||||
"alterId",
|
||||
"id",
|
||||
"level",
|
||||
"path",
|
||||
"host",
|
||||
"congestion",
|
||||
"downlinkCapacity",
|
||||
"header",
|
||||
"type",
|
||||
"mtu",
|
||||
"readBufferSize",
|
||||
"tti",
|
||||
"uplinkCapacity",
|
||||
"writeBufferSize",
|
||||
"key",
|
||||
"mark",
|
||||
"tcpFastOpen",
|
||||
"tproxy",
|
||||
"allowInsecure",
|
||||
"alpn",
|
||||
"disableSystemRoot",
|
||||
"certificates",
|
||||
"serverName",
|
||||
"QV2RAY_RULE_ENABLED",
|
||||
"QV2RAY_RULE_TAG",
|
||||
"QV2RAY_RULE_USE_BALANCER" };
|
||||
int i = 0;
|
||||
for (const QString &pattern : keywordPatterns)
|
||||
{
|
||||
SetRule(QString("00_KeyWord_%1").arg(i), "\"" + pattern + "\"", keywordFormat);
|
||||
++i;
|
||||
}
|
||||
//
|
||||
// Values
|
||||
QTextCharFormat valueFormat, classFormat;
|
||||
valueFormat.setForeground(Qt::blue);
|
||||
SetRule("03_Values", "\\btrue\\b|\\bfalse\\b|\\b[0-9]+\\b", valueFormat);
|
||||
//
|
||||
// Single Line Comments
|
||||
QTextCharFormat singleLineCommentFormat;
|
||||
singleLineCommentFormat.setForeground(Qt::darkGreen);
|
||||
SetRule("z2_SingleLineComments", "//[^\n]*", singleLineCommentFormat);
|
||||
}
|
||||
void vCoreConfigJsonHighlighter::SetRule(const QString &kind, const QString &pattern, QTextCharFormat format)
|
||||
{
|
||||
JsonHighlightingRule rule;
|
||||
rule.name = kind;
|
||||
rule.pattern = QRegularExpression(pattern);
|
||||
rule.format = format;
|
||||
highlightingRules.append(rule);
|
||||
}
|
||||
|
||||
void vCoreConfigJsonHighlighter::highlightBlock(const QString &text)
|
||||
{
|
||||
for (const auto &rule : std::as_const(highlightingRules))
|
||||
{
|
||||
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
|
||||
|
||||
while (matchIterator.hasNext())
|
||||
{
|
||||
QRegularExpressionMatch match = matchIterator.next();
|
||||
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentBlockState(0);
|
||||
}
|
||||
|
||||
} // namespace Qv2ray::common
|
29
src/common/JsonHighlighter.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QRegularExpression>
|
||||
#include <QStringList>
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QVector>
|
||||
|
||||
namespace Qv2ray::common
|
||||
{
|
||||
struct JsonHighlightingRule
|
||||
{
|
||||
QString name;
|
||||
QRegularExpression pattern;
|
||||
QTextCharFormat format;
|
||||
};
|
||||
class vCoreConfigJsonHighlighter : public QSyntaxHighlighter
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
vCoreConfigJsonHighlighter(QTextDocument *parent = nullptr);
|
||||
|
||||
private:
|
||||
QVector<JsonHighlightingRule> highlightingRules;
|
||||
void SetRule(const QString &kind, const QString &pattern, QTextCharFormat format);
|
||||
void highlightBlock(const QString &text) override;
|
||||
};
|
||||
} // namespace Qv2ray::common
|
||||
using namespace Qv2ray::common;
|
@ -1,30 +1,32 @@
|
||||
#include "LogHighlighter.hpp"
|
||||
|
||||
#include "common/QvHelpers.hpp"
|
||||
|
||||
#define TO_EOL "(([\\s\\S]*)|([\\d\\D]*)|([\\w\\W]*))$"
|
||||
|
||||
namespace Qv2ray::common
|
||||
{
|
||||
SyntaxHighlighter::SyntaxHighlighter(bool darkMode, QTextDocument *parent)
|
||||
: QSyntaxHighlighter(parent)
|
||||
SyntaxHighlighter::SyntaxHighlighter(bool darkMode, QTextDocument *parent) : QSyntaxHighlighter(parent)
|
||||
{
|
||||
HighlightingRule rule;
|
||||
keywordFormat.setForeground(darkMode ? Qt::darkMagenta : Qt::magenta);
|
||||
keywordFormat.setFontWeight(QFont::Bold);
|
||||
const QString keywordPatterns[] = {
|
||||
"tcp", "udp"
|
||||
};
|
||||
const QString keywordPatterns[] = { "tcp", "udp" };
|
||||
|
||||
for (const QString &pattern : keywordPatterns) {
|
||||
for (const QString &pattern : keywordPatterns)
|
||||
{
|
||||
rule.pattern = QRegularExpression(pattern);
|
||||
rule.format = keywordFormat;
|
||||
highlightingRules.append(rule);
|
||||
}
|
||||
|
||||
if (darkMode) {
|
||||
if (darkMode)
|
||||
{
|
||||
ipHostFormat.setForeground(Qt::yellow);
|
||||
warningFormat.setForeground(QColor(230, 180, 0));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ipHostFormat.setForeground(Qt::black);
|
||||
ipHostFormat.setFontWeight(QFont::Bold);
|
||||
warningFormat.setForeground(Qt::white);
|
||||
@ -49,7 +51,7 @@ namespace Qv2ray::common
|
||||
rule.format = debugFormat;
|
||||
highlightingRules.append(rule);
|
||||
//
|
||||
infoFormat.setForeground(darkMode ? Qt::lightGray : Qt::darkCyan);
|
||||
infoFormat.setForeground(darkMode ? Qt::lightGray : Qt::darkCyan);
|
||||
rule.pattern = QRegularExpression("\\[[Ii]nfo\\]" TO_EOL);
|
||||
rule.format = infoFormat;
|
||||
highlightingRules.append(rule);
|
||||
@ -119,10 +121,12 @@ namespace Qv2ray::common
|
||||
|
||||
void SyntaxHighlighter::highlightBlock(const QString &text)
|
||||
{
|
||||
for (const HighlightingRule &rule : qAsConst(highlightingRules)) {
|
||||
for (const HighlightingRule &rule : qAsConst(highlightingRules))
|
||||
{
|
||||
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
|
||||
|
||||
while (matchIterator.hasNext()) {
|
||||
while (matchIterator.hasNext())
|
||||
{
|
||||
QRegularExpressionMatch match = matchIterator.next();
|
||||
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
|
||||
}
|
||||
@ -130,4 +134,4 @@ namespace Qv2ray::common
|
||||
|
||||
setCurrentBlockState(0);
|
||||
}
|
||||
}
|
||||
} // namespace Qv2ray::common
|
||||
|
@ -49,45 +49,46 @@
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <QRegularExpression>
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QTextCharFormat>
|
||||
#include <QRegularExpression>
|
||||
#include <QTextDocument>
|
||||
|
||||
namespace Qv2ray::common
|
||||
{
|
||||
class SyntaxHighlighter : public QSyntaxHighlighter
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SyntaxHighlighter(bool darkMode, QTextDocument *parent = nullptr);
|
||||
public:
|
||||
explicit SyntaxHighlighter(bool darkMode, QTextDocument *parent = nullptr);
|
||||
|
||||
protected:
|
||||
void highlightBlock(const QString &text) override;
|
||||
protected:
|
||||
void highlightBlock(const QString &text) override;
|
||||
|
||||
private:
|
||||
struct HighlightingRule {
|
||||
QRegularExpression pattern;
|
||||
QTextCharFormat format;
|
||||
};
|
||||
QVector<HighlightingRule> highlightingRules;
|
||||
private:
|
||||
struct HighlightingRule
|
||||
{
|
||||
QRegularExpression pattern;
|
||||
QTextCharFormat format;
|
||||
};
|
||||
QVector<HighlightingRule> highlightingRules;
|
||||
|
||||
QTextCharFormat keywordFormat;
|
||||
QTextCharFormat dateFormat;
|
||||
QTextCharFormat acceptedFormat;
|
||||
QTextCharFormat rejectedFormat;
|
||||
QTextCharFormat failedFormat;
|
||||
QTextCharFormat warningFormat;
|
||||
QTextCharFormat infoFormat;
|
||||
QTextCharFormat debugFormat;
|
||||
QTextCharFormat timeFormat;
|
||||
QTextCharFormat ipHostFormat;
|
||||
QTextCharFormat v2rayComponentFormat;
|
||||
//
|
||||
QTextCharFormat qvAppLogFormat;
|
||||
QTextCharFormat qvAppDebugLogFormat;
|
||||
QTextCharFormat keywordFormat;
|
||||
QTextCharFormat dateFormat;
|
||||
QTextCharFormat acceptedFormat;
|
||||
QTextCharFormat rejectedFormat;
|
||||
QTextCharFormat failedFormat;
|
||||
QTextCharFormat warningFormat;
|
||||
QTextCharFormat infoFormat;
|
||||
QTextCharFormat debugFormat;
|
||||
QTextCharFormat timeFormat;
|
||||
QTextCharFormat ipHostFormat;
|
||||
QTextCharFormat v2rayComponentFormat;
|
||||
//
|
||||
QTextCharFormat qvAppLogFormat;
|
||||
QTextCharFormat qvAppDebugLogFormat;
|
||||
};
|
||||
}
|
||||
} // namespace Qv2ray::common
|
||||
|
||||
using namespace Qv2ray::common;
|
||||
|
@ -10,8 +10,8 @@
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
@ -23,10 +23,10 @@
|
||||
*/
|
||||
|
||||
#include "QJsonModel.hpp"
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
#include <QFont>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QFont>
|
||||
|
||||
QJsonTreeItem::QJsonTreeItem(QJsonTreeItem *parent)
|
||||
{
|
||||
@ -101,27 +101,34 @@ QJsonTreeItem *QJsonTreeItem::load(const QJsonValue &value, QJsonTreeItem *paren
|
||||
QJsonTreeItem *rootItem = new QJsonTreeItem(parent);
|
||||
rootItem->setKey("root");
|
||||
|
||||
if (value.isObject()) {
|
||||
//Get all QJsonValue childs
|
||||
for (QString key : value.toObject().keys()) {
|
||||
if (value.isObject())
|
||||
{
|
||||
// Get all QJsonValue childs
|
||||
for (QString key : value.toObject().keys())
|
||||
{
|
||||
QJsonValue v = value.toObject().value(key);
|
||||
QJsonTreeItem *child = load(v, rootItem);
|
||||
child->setKey(key);
|
||||
child->setType(v.type());
|
||||
rootItem->appendChild(child);
|
||||
}
|
||||
} else if (value.isArray()) {
|
||||
//Get all QJsonValue childs
|
||||
}
|
||||
else if (value.isArray())
|
||||
{
|
||||
// Get all QJsonValue childs
|
||||
int index = 0;
|
||||
|
||||
for (QJsonValue v : value.toArray()) {
|
||||
for (QJsonValue v : value.toArray())
|
||||
{
|
||||
QJsonTreeItem *child = load(v, rootItem);
|
||||
child->setKey(QString::number(index));
|
||||
child->setType(v.type());
|
||||
rootItem->appendChild(child);
|
||||
++index;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
rootItem->setValue(value.toVariant().toString());
|
||||
rootItem->setType(value.type());
|
||||
}
|
||||
@ -131,35 +138,27 @@ QJsonTreeItem *QJsonTreeItem::load(const QJsonValue &value, QJsonTreeItem *paren
|
||||
|
||||
//=========================================================================
|
||||
|
||||
QJsonModel::QJsonModel(QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
, mRootItem{new QJsonTreeItem}
|
||||
QJsonModel::QJsonModel(QObject *parent) : QAbstractItemModel(parent), mRootItem{ new QJsonTreeItem }
|
||||
{
|
||||
mHeaders.append("key");
|
||||
mHeaders.append("value");
|
||||
}
|
||||
|
||||
QJsonModel::QJsonModel(const QString &fileName, QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
, mRootItem{new QJsonTreeItem}
|
||||
QJsonModel::QJsonModel(const QString &fileName, QObject *parent) : QAbstractItemModel(parent), mRootItem{ new QJsonTreeItem }
|
||||
{
|
||||
mHeaders.append("key");
|
||||
mHeaders.append("value");
|
||||
load(fileName);
|
||||
}
|
||||
|
||||
QJsonModel::QJsonModel(QIODevice *device, QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
, mRootItem{new QJsonTreeItem}
|
||||
QJsonModel::QJsonModel(QIODevice *device, QObject *parent) : QAbstractItemModel(parent), mRootItem{ new QJsonTreeItem }
|
||||
{
|
||||
mHeaders.append("key");
|
||||
mHeaders.append("value");
|
||||
load(device);
|
||||
}
|
||||
|
||||
QJsonModel::QJsonModel(const QByteArray &json, QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
, mRootItem{new QJsonTreeItem}
|
||||
QJsonModel::QJsonModel(const QByteArray &json, QObject *parent) : QAbstractItemModel(parent), mRootItem{ new QJsonTreeItem }
|
||||
{
|
||||
mHeaders.append("key");
|
||||
mHeaders.append("value");
|
||||
@ -176,10 +175,13 @@ bool QJsonModel::load(const QString &fileName)
|
||||
QFile file(fileName);
|
||||
bool success = false;
|
||||
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
if (file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
success = load(&file);
|
||||
file.close();
|
||||
} else success = false;
|
||||
}
|
||||
else
|
||||
success = false;
|
||||
|
||||
return success;
|
||||
}
|
||||
@ -193,14 +195,18 @@ bool QJsonModel::loadJson(const QByteArray &json)
|
||||
{
|
||||
auto const &jdoc = QJsonDocument::fromJson(json);
|
||||
|
||||
if (!jdoc.isNull()) {
|
||||
if (!jdoc.isNull())
|
||||
{
|
||||
beginResetModel();
|
||||
delete mRootItem;
|
||||
|
||||
if (jdoc.isArray()) {
|
||||
if (jdoc.isArray())
|
||||
{
|
||||
mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.array()));
|
||||
mRootItem->setType(QJsonValue::Array);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.object()));
|
||||
mRootItem->setType(QJsonValue::Object);
|
||||
}
|
||||
@ -213,7 +219,6 @@ bool QJsonModel::loadJson(const QByteArray &json)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QVariant QJsonModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
@ -221,14 +226,18 @@ QVariant QJsonModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
QJsonTreeItem *item = static_cast<QJsonTreeItem *>(index.internalPointer());
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (index.column() == 0)
|
||||
return QString("%1").arg(item->key());
|
||||
|
||||
if (index.column() == 1)
|
||||
return QString("%1").arg(item->value());
|
||||
} else if (Qt::EditRole == role) {
|
||||
if (index.column() == 1) {
|
||||
}
|
||||
else if (Qt::EditRole == role)
|
||||
{
|
||||
if (index.column() == 1)
|
||||
{
|
||||
return QString("%1").arg(item->value());
|
||||
}
|
||||
}
|
||||
@ -240,11 +249,13 @@ bool QJsonModel::setData(const QModelIndex &index, const QVariant &value, int ro
|
||||
{
|
||||
int col = index.column();
|
||||
|
||||
if (Qt::EditRole == role) {
|
||||
if (col == 1) {
|
||||
if (Qt::EditRole == role)
|
||||
{
|
||||
if (col == 1)
|
||||
{
|
||||
QJsonTreeItem *item = static_cast<QJsonTreeItem *>(index.internalPointer());
|
||||
item->setValue(value.toString());
|
||||
emit dataChanged(index, index, {Qt::EditRole});
|
||||
emit dataChanged(index, index, { Qt::EditRole });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -252,16 +263,16 @@ bool QJsonModel::setData(const QModelIndex &index, const QVariant &value, int ro
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QVariant QJsonModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
if (orientation == Qt::Horizontal) {
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
return mHeaders.value(section);
|
||||
} else
|
||||
}
|
||||
else
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
@ -322,14 +333,17 @@ int QJsonModel::columnCount(const QModelIndex &parent) const
|
||||
|
||||
Qt::ItemFlags QJsonModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
int col = index.column();
|
||||
int col = index.column();
|
||||
auto item = static_cast<QJsonTreeItem *>(index.internalPointer());
|
||||
auto isArray = QJsonValue::Array == item->type();
|
||||
auto isObject = QJsonValue::Object == item->type();
|
||||
|
||||
if ((col == 1) && !(isArray || isObject)) {
|
||||
if ((col == 1) && !(isArray || isObject))
|
||||
{
|
||||
return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return QAbstractItemModel::flags(index);
|
||||
}
|
||||
}
|
||||
@ -339,40 +353,50 @@ QJsonDocument QJsonModel::json() const
|
||||
auto v = genJson(mRootItem);
|
||||
QJsonDocument doc;
|
||||
|
||||
if (v.isObject()) {
|
||||
if (v.isObject())
|
||||
{
|
||||
doc = QJsonDocument(v.toObject());
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
doc = QJsonDocument(v.toArray());
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
QJsonValue QJsonModel::genJson(QJsonTreeItem *item) const
|
||||
QJsonValue QJsonModel::genJson(QJsonTreeItem *item) const
|
||||
{
|
||||
auto type = item->type();
|
||||
int nchild = item->childCount();
|
||||
auto type = item->type();
|
||||
int nchild = item->childCount();
|
||||
|
||||
if (QJsonValue::Object == type) {
|
||||
if (QJsonValue::Object == type)
|
||||
{
|
||||
QJsonObject jo;
|
||||
|
||||
for (int i = 0; i < nchild; ++i) {
|
||||
for (int i = 0; i < nchild; ++i)
|
||||
{
|
||||
auto ch = item->child(i);
|
||||
auto key = ch->key();
|
||||
jo.insert(key, genJson(ch));
|
||||
}
|
||||
|
||||
return jo;
|
||||
} else if (QJsonValue::Array == type) {
|
||||
return jo;
|
||||
}
|
||||
else if (QJsonValue::Array == type)
|
||||
{
|
||||
QJsonArray arr;
|
||||
|
||||
for (int i = 0; i < nchild; ++i) {
|
||||
for (int i = 0; i < nchild; ++i)
|
||||
{
|
||||
auto ch = item->child(i);
|
||||
arr.append(genJson(ch));
|
||||
}
|
||||
|
||||
return arr;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
QJsonValue va(item->value());
|
||||
return va;
|
||||
}
|
||||
|
@ -1,101 +1,94 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2011 SCHUTZ Sacha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2011 SCHUTZ Sacha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonValue>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QIcon>
|
||||
#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;
|
||||
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;
|
||||
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;
|
||||
};
|
||||
|
@ -1,4 +1,11 @@
|
||||
#include "common/QvHelpers.hpp"
|
||||
|
||||
#include "libs/puresource/src/PureJson.hpp"
|
||||
|
||||
#include <QGraphicsEffect>
|
||||
#include <QGraphicsProxyWidget>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsView>
|
||||
#include <QQueue>
|
||||
|
||||
namespace Qv2ray::common
|
||||
@ -8,7 +15,8 @@ namespace Qv2ray::common
|
||||
const QString possibleCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
|
||||
QString randomString;
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
uint rand = QRandomGenerator::system()->generate();
|
||||
uint max = static_cast<uint>(possibleCharacters.length());
|
||||
QChar nextChar = possibleCharacters[rand % max];
|
||||
@ -26,21 +34,43 @@ namespace Qv2ray::common
|
||||
|
||||
QString StringFromFile(QFile *source)
|
||||
{
|
||||
source->open(QFile::ReadOnly);
|
||||
QTextStream stream(source);
|
||||
QString str = stream.readAll();
|
||||
source->close();
|
||||
return str;
|
||||
bool wasOpened = source->isOpen();
|
||||
if (!wasOpened)
|
||||
source->open(QFile::ReadOnly);
|
||||
auto byteArray = source->readAll();
|
||||
if (!wasOpened)
|
||||
source->close();
|
||||
//
|
||||
QTextCodec::ConverterState state;
|
||||
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
|
||||
const QString text = codec->toUnicode(byteArray.constData(), byteArray.size(), &state);
|
||||
if (state.invalidChars > 0)
|
||||
{
|
||||
LOG(MODULE_FILEIO, "Not a valid UTF-8 sequence: " + source->fileName())
|
||||
return source->readAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
bool StringToFile(const QString *text, QFile *targetFile)
|
||||
bool StringToFile(const QString &text, const QString &targetpath)
|
||||
{
|
||||
bool override = targetFile->exists();
|
||||
targetFile->open(QFile::WriteOnly);
|
||||
QTextStream stream(targetFile);
|
||||
stream << *text << endl;
|
||||
stream.flush();
|
||||
targetFile->close();
|
||||
auto file = QFile(targetpath);
|
||||
return StringToFile(text, file);
|
||||
}
|
||||
bool StringToFile(const QString &text, QFile &targetFile)
|
||||
{
|
||||
QFileInfo info(targetFile);
|
||||
if (!info.dir().exists())
|
||||
{
|
||||
info.dir().mkpath(info.dir().path());
|
||||
}
|
||||
bool override = targetFile.exists();
|
||||
targetFile.open(QFile::WriteOnly);
|
||||
targetFile.write(text.toUtf8());
|
||||
targetFile.close();
|
||||
return override;
|
||||
}
|
||||
|
||||
@ -50,14 +80,14 @@ namespace Qv2ray::common
|
||||
return JsonFromString(json);
|
||||
}
|
||||
|
||||
QString JsonToString(QJsonObject json, QJsonDocument::JsonFormat format)
|
||||
QString JsonToString(const QJsonObject &json, QJsonDocument::JsonFormat format)
|
||||
{
|
||||
QJsonDocument doc;
|
||||
doc.setObject(json);
|
||||
return doc.toJson(format);
|
||||
}
|
||||
|
||||
QString JsonToString(QJsonArray array, QJsonDocument::JsonFormat format)
|
||||
QString JsonToString(const QJsonArray &array, QJsonDocument::JsonFormat format)
|
||||
{
|
||||
QJsonDocument doc;
|
||||
doc.setArray(array);
|
||||
@ -70,27 +100,35 @@ namespace Qv2ray::common
|
||||
QJsonDocument doc = QJsonDocument::fromJson(source.toUtf8(), &error);
|
||||
Q_UNUSED(doc)
|
||||
|
||||
if (error.error == QJsonParseError::NoError) {
|
||||
if (error.error == QJsonParseError::NoError)
|
||||
{
|
||||
return "";
|
||||
} else {
|
||||
LOG(UI, "WARNING: Json parse returns: " + error.errorString())
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(MODULE_UI, "WARNING: Json parse returns: " + error.errorString())
|
||||
return error.errorString();
|
||||
}
|
||||
}
|
||||
|
||||
QJsonObject JsonFromString(QString string)
|
||||
QJsonObject JsonFromString(const QString &string)
|
||||
{
|
||||
QJsonDocument doc = QJsonDocument::fromJson(string.toUtf8());
|
||||
auto removeComment = RemoveComment(string.trimmed()).trimmed();
|
||||
if (removeComment != string.trimmed())
|
||||
{
|
||||
LOG(MODULE_FILEIO, "Some comments have been removed from the json.")
|
||||
}
|
||||
QJsonDocument doc = QJsonDocument::fromJson(removeComment.toUtf8());
|
||||
return doc.object();
|
||||
}
|
||||
|
||||
QString Base64Encode(QString string)
|
||||
QString Base64Encode(const QString &string)
|
||||
{
|
||||
QByteArray ba = string.toUtf8();
|
||||
return ba.toBase64();
|
||||
}
|
||||
|
||||
QString Base64Decode(QString string)
|
||||
QString Base64Decode(const QString &string)
|
||||
{
|
||||
QByteArray ba = string.toUtf8();
|
||||
return QString(QByteArray::fromBase64(ba));
|
||||
@ -105,50 +143,52 @@ namespace Qv2ray::common
|
||||
{
|
||||
list<string> list;
|
||||
|
||||
for (auto line : _string.split(QRegExp("[\r\n]"), QString::SkipEmptyParts)) {
|
||||
for (auto line : _string.split(QRegExp("[\r\n]"), QString::SkipEmptyParts))
|
||||
{
|
||||
list.push_back(line.toStdString());
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
QStringList GetFileList(QDir dir)
|
||||
QStringList GetFileList(const QDir &dir)
|
||||
{
|
||||
return dir.entryList(QStringList() << "*" << "*.*", QDir::Hidden | QDir::Files);
|
||||
return dir.entryList(QStringList{ "*", "*.*" }, QDir::Hidden | QDir::Files);
|
||||
}
|
||||
|
||||
bool FileExistsIn(QDir dir, QString fileName)
|
||||
bool FileExistsIn(const QDir &dir, const QString &fileName)
|
||||
{
|
||||
return GetFileList(dir).contains(fileName);
|
||||
}
|
||||
|
||||
void QvMessageBoxWarn(QWidget *parent, QString title, QString text)
|
||||
void QvMessageBoxWarn(QWidget *parent, const QString &title, const QString &text)
|
||||
{
|
||||
QMessageBox::warning(parent, title, text, QMessageBox::Ok | QMessageBox::Default, 0);
|
||||
}
|
||||
|
||||
void QvMessageBoxInfo(QWidget *parent, QString title, QString text)
|
||||
void QvMessageBoxInfo(QWidget *parent, const QString &title, const QString &text)
|
||||
{
|
||||
QMessageBox::information(parent, title, text, QMessageBox::Ok | QMessageBox::Default, 0);
|
||||
}
|
||||
|
||||
QMessageBox::StandardButton QvMessageBoxAsk(QWidget *parent, QString title, QString text, QMessageBox::StandardButton extraButtons)
|
||||
QMessageBox::StandardButton QvMessageBoxAsk(QWidget *parent, const QString &title, const QString &text,
|
||||
QMessageBox::StandardButton extraButtons)
|
||||
{
|
||||
return QMessageBox::question(parent, title, text, QMessageBox::Yes | QMessageBox::No | extraButtons);
|
||||
}
|
||||
|
||||
QString FormatBytes(long long bytes)
|
||||
QString FormatBytes(const int64_t b)
|
||||
{
|
||||
auto _bytes = b;
|
||||
char str[64];
|
||||
const char *sizes[5] = { "B", "KB", "MB", "GB", "TB" };
|
||||
int i;
|
||||
double dblByte = bytes;
|
||||
double dblByte = _bytes;
|
||||
|
||||
for (i = 0; i < 5 && bytes >= 1024; i++, bytes /= 1024)
|
||||
dblByte = bytes / 1024.0;
|
||||
for (i = 0; i < 5 && _bytes >= 1024; i++, _bytes /= 1024) dblByte = _bytes / 1024.0;
|
||||
|
||||
sprintf(str, "%.2f", dblByte);
|
||||
return strcat(strcat(str, " "), sizes[i]);
|
||||
return QString(str) + " " + QString(sizes[i]);
|
||||
}
|
||||
|
||||
bool IsValidFileName(const QString &fileName)
|
||||
@ -160,9 +200,8 @@ namespace Qv2ray::common
|
||||
QString RemoveInvalidFileName(const QString &fileName)
|
||||
{
|
||||
std::string _name = fileName.toStdString();
|
||||
std::replace_if(_name.begin(), _name.end(), [](char c) {
|
||||
return std::string::npos != string(R"("/\?%&^*;:|><)").find(c);
|
||||
}, '_');
|
||||
std::replace_if(
|
||||
_name.begin(), _name.end(), [](char c) { return std::string::npos != string(R"("/\?%&^*;:|><)").find(c); }, '_');
|
||||
return QString::fromStdString(_name);
|
||||
}
|
||||
|
||||
@ -171,42 +210,54 @@ namespace Qv2ray::common
|
||||
{
|
||||
int i = 1;
|
||||
|
||||
if (!QDir(baseDir).exists()) {
|
||||
if (!QDir(baseDir).exists())
|
||||
{
|
||||
QDir(baseDir).mkpath(baseDir);
|
||||
LOG(FILEIO, "Making path: " + baseDir)
|
||||
LOG(MODULE_FILEIO, "Making path: " + baseDir)
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (!QFile(baseDir + "/" + fileName + "_" + QSTRN(i) + extension).exists()) {
|
||||
while (true)
|
||||
{
|
||||
if (!QFile(baseDir + "/" + fileName + "_" + QSTRN(i) + extension).exists())
|
||||
{
|
||||
*fileName = *fileName + "_" + QSTRN(i);
|
||||
return;
|
||||
} else {
|
||||
DEBUG(FILEIO, "File with name: " + *fileName + "_" + QSTRN(i) + extension + " already exists")
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG(MODULE_FILEIO, "File with name: " + *fileName + "_" + QSTRN(i) + extension + " already exists")
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
QStringList ConvertQStringList(const QList<string> &stdListString)
|
||||
QPixmap BlurImage(const QPixmap &pixmap, const double rad)
|
||||
{
|
||||
QStringList listQt;
|
||||
listQt.reserve(stdListString.size());
|
||||
|
||||
for (const std::string &s : stdListString) {
|
||||
listQt.append(QString::fromStdString(s));
|
||||
}
|
||||
|
||||
return listQt;
|
||||
QGraphicsView view;
|
||||
QGraphicsScene scene;
|
||||
QGraphicsBlurEffect pBlur;
|
||||
//
|
||||
view.setScene(&scene);
|
||||
scene.setSceneRect(pixmap.rect());
|
||||
pBlur.setBlurRadius(rad);
|
||||
QGraphicsPixmapItem *p = view.scene()->addPixmap(pixmap);
|
||||
p->setGraphicsEffect(&pBlur);
|
||||
return view.grab();
|
||||
}
|
||||
std::list<string> ConvertStdStringList(const QStringList &qStringList)
|
||||
|
||||
QPixmap ColorizeImage(const QPixmap &pixmap, const QColor &color, const qreal factor)
|
||||
{
|
||||
std::list<string> stdList;
|
||||
|
||||
for (auto &s : qStringList) {
|
||||
stdList.push_back(s.toStdString());
|
||||
}
|
||||
|
||||
return stdList;
|
||||
QGraphicsView view;
|
||||
QGraphicsScene scene;
|
||||
QGraphicsColorizeEffect pColor;
|
||||
pColor.setColor(color);
|
||||
pColor.setStrength(factor);
|
||||
//
|
||||
view.setScene(&scene);
|
||||
scene.setSceneRect(pixmap.rect());
|
||||
QGraphicsPixmapItem *p = view.scene()->addPixmap(pixmap);
|
||||
p->setGraphicsEffect(&pColor);
|
||||
return view.grab();
|
||||
}
|
||||
}
|
||||
} // namespace Qv2ray::common
|
||||
|
@ -1,50 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include "base/Qv2rayBase.hpp"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
#define REGEX_IPV6_ADDR R"(\[\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*\])"
|
||||
#define REGEX_IPV4_ADDR R"((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]))"
|
||||
#define REGEX_IPV6_ADDR \
|
||||
R"(\[\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*\])"
|
||||
#define REGEX_IPV4_ADDR \
|
||||
R"((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]))"
|
||||
#define REGEX_PORT_NUMBER R"(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])*)"
|
||||
|
||||
namespace Qv2ray::common
|
||||
{
|
||||
QStringList GetFileList(QDir dir);
|
||||
QString Base64Encode(QString string);
|
||||
QString Base64Decode(QString string);
|
||||
QStringList GetFileList(const QDir &dir);
|
||||
QString Base64Encode(const QString &string);
|
||||
QString Base64Decode(const QString &string);
|
||||
QStringList SplitLines(const QString &str);
|
||||
list<string> SplitLines_std(const QString &_string);
|
||||
bool FileExistsIn(QDir dir, QString fileName);
|
||||
bool FileExistsIn(const QDir &dir, const QString &fileName);
|
||||
const QString GenerateRandomString(int len = 12);
|
||||
//
|
||||
void QvMessageBoxWarn(QWidget *parent, QString title, QString text);
|
||||
void QvMessageBoxInfo(QWidget *parent, QString title, QString text);
|
||||
QMessageBox::StandardButton QvMessageBoxAsk(QWidget *parent, QString title, QString text, QMessageBox::StandardButton extraButtons = QMessageBox::NoButton);
|
||||
void QvMessageBoxWarn(QWidget *parent, const QString &title, const QString &text);
|
||||
void QvMessageBoxInfo(QWidget *parent, const QString &title, const QString &text);
|
||||
QMessageBox::StandardButton QvMessageBoxAsk(QWidget *parent, const QString &title, const QString &text,
|
||||
QMessageBox::StandardButton extraButtons = QMessageBox::NoButton);
|
||||
//
|
||||
QString StringFromFile(const QString &filePath);
|
||||
QString StringFromFile(QFile *source);
|
||||
bool StringToFile(const QString *text, QFile *target);
|
||||
bool StringToFile(const QString &text, QFile &target);
|
||||
bool StringToFile(const QString &text, const QString &targetpath);
|
||||
//
|
||||
QJsonObject JsonFromString(QString string);
|
||||
QString JsonToString(QJsonObject json, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented);
|
||||
QString JsonToString(QJsonArray array, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented);
|
||||
QJsonObject JsonFromString(const QString &string);
|
||||
QString JsonToString(const QJsonObject &json, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented);
|
||||
QString JsonToString(const QJsonArray &array, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented);
|
||||
QString VerifyJsonString(const QString &source);
|
||||
//
|
||||
QString FormatBytes(long long bytes);
|
||||
QString FormatBytes(const int64_t bytes);
|
||||
void DeducePossibleFileName(const QString &baseDir, QString *fileName, const QString &extension);
|
||||
QStringList ConvertQStringList(const QList<string> &stdListString);
|
||||
std::list<string> ConvertStdStringList(const QStringList &qStringList);
|
||||
//
|
||||
QPixmap BlurImage(const QPixmap &pixmap, const double rad = 50);
|
||||
QPixmap ColorizeImage(const QPixmap &pixmap, const QColor &color, const qreal factor);
|
||||
// This function cannot be marked as inline.
|
||||
QString RemoveInvalidFileName(const QString &fileName);
|
||||
bool IsValidFileName(const QString &fileName);
|
||||
inline QString GenerateUuid()
|
||||
{
|
||||
return GenerateRandomString().toLower();
|
||||
// return QUuid::createUuid().toString(QUuid::WithoutBraces);
|
||||
}
|
||||
//
|
||||
template <typename TYPE>
|
||||
template<typename TYPE>
|
||||
QString StructToJsonString(const TYPE t)
|
||||
{
|
||||
return QString::fromStdString(x2struct::X::tojson(t, "", 4, ' '));
|
||||
}
|
||||
//
|
||||
template <typename TYPE>
|
||||
template<typename TYPE>
|
||||
TYPE StructFromJsonString(const QString &str)
|
||||
{
|
||||
TYPE v;
|
||||
@ -59,68 +70,43 @@ namespace Qv2ray::common
|
||||
return JsonFromString(json);
|
||||
}
|
||||
|
||||
inline bool IsIPv4Address(const QString &addr)
|
||||
inline QString TruncateString(const QString &str, int limit = -1, const QString &suffix = "...")
|
||||
{
|
||||
return QRegularExpression(REGEX_IPV4_ADDR "$").match(addr).hasMatch();
|
||||
QString t = str;
|
||||
t.truncate(limit);
|
||||
return (limit == -1 || str.length() < limit) ? str : (t + suffix);
|
||||
}
|
||||
|
||||
inline bool IsIPv6Address(const QString &addr)
|
||||
namespace validation
|
||||
{
|
||||
return QRegularExpression(REGEX_IPV6_ADDR "$").match(addr).hasMatch();
|
||||
}
|
||||
const inline QRegularExpression __regex_ipv4_full(REGEX_IPV4_ADDR "$");
|
||||
const inline QRegularExpression __regex_ipv6_full(REGEX_IPV6_ADDR "$");
|
||||
|
||||
inline bool IsValidIPAddress(const QString &addr)
|
||||
{
|
||||
return IsIPv4Address(addr) || IsIPv6Address(addr);
|
||||
}
|
||||
inline bool IsIPv4Address(const QString &addr)
|
||||
{
|
||||
return __regex_ipv4_full.match(addr).hasMatch();
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic function to find if an element of any type exists in list
|
||||
*/
|
||||
template<typename T>
|
||||
bool contains(std::list<T> &listOfElements, const T &element)
|
||||
{
|
||||
// Find the iterator if element in list
|
||||
auto it = std::find(listOfElements.begin(), listOfElements.end(), element);
|
||||
//return if iterator points to end or not. It points to end then it means element
|
||||
// does not exists in list
|
||||
return it != listOfElements.end();
|
||||
}
|
||||
inline bool IsIPv6Address(const QString &addr)
|
||||
{
|
||||
return __regex_ipv6_full.match(addr).hasMatch();
|
||||
}
|
||||
|
||||
inline bool IsValidIPAddress(const QString &addr)
|
||||
{
|
||||
return IsIPv4Address(addr) || IsIPv6Address(addr);
|
||||
}
|
||||
} // namespace validation
|
||||
|
||||
inline QString timeToString(const time_t &t)
|
||||
{
|
||||
auto _tm = std::localtime(&t);
|
||||
char MY_TIME[128];
|
||||
setlocale(1, "3");
|
||||
// using strftime to display time
|
||||
strftime(MY_TIME, sizeof(MY_TIME), "%x - %I:%M%p", _tm);
|
||||
return QString(MY_TIME);
|
||||
}
|
||||
|
||||
template<typename myMap>
|
||||
std::vector<typename myMap::key_type> Keys(const myMap &m)
|
||||
{
|
||||
std::vector<typename myMap::key_type> r;
|
||||
r.reserve(m.size());
|
||||
|
||||
for (const auto &kvp : m) {
|
||||
r.push_back(kvp.first);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename myMap>
|
||||
std::vector<typename myMap::mapped_type> Values(const myMap &m)
|
||||
{
|
||||
std::vector<typename myMap::mapped_type> r;
|
||||
r.reserve(m.size());
|
||||
|
||||
for (const auto &kvp : m) {
|
||||
r.push_back(kvp.second);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
} // namespace Qv2ray::common
|
||||
|
||||
using namespace Qv2ray::common;
|
||||
|
93
src/common/QvTranslator.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include "QvTranslator.hpp"
|
||||
|
||||
#include "base/Qv2rayLog.hpp"
|
||||
#include "common/QvHelpers.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
#include <QString>
|
||||
#include <QStringBuilder>
|
||||
#include <QTranslator>
|
||||
#include <memory>
|
||||
|
||||
using namespace Qv2ray::base;
|
||||
|
||||
// path searching list.
|
||||
QStringList getLanguageSearchPaths()
|
||||
{
|
||||
// Configuration Path
|
||||
QStringList list;
|
||||
list << QV2RAY_CONFIG_DIR + "lang";
|
||||
//
|
||||
#ifdef EMBED_TRANSLATIONS
|
||||
// If the translations have been embedded.
|
||||
list << QString(":/translations/");
|
||||
#endif
|
||||
//
|
||||
//
|
||||
#ifdef QV2RAY_TRANSLATION_PATH
|
||||
// Platform-specific dir, if specified.
|
||||
list << QString(QV2RAY_TRANSLATION_PATH);
|
||||
#endif
|
||||
//
|
||||
//
|
||||
#ifdef Q_OS_LINUX
|
||||
// Linux platform directories.
|
||||
list << QString("/usr/share/qv2ray/lang/");
|
||||
list << QString("/usr/local/share/qv2ray/lang/");
|
||||
list << QStandardPaths::locateAll(QStandardPaths::AppDataLocation, "lang", QStandardPaths::LocateDirectory);
|
||||
list << QStandardPaths::locateAll(QStandardPaths::AppConfigLocation, "lang", QStandardPaths::LocateDirectory);
|
||||
#elif defined(Q_OS_MAC)
|
||||
// macOS platform directories.
|
||||
list << QDir(QApplication::applicationDirPath() + "/../Resources/lang").absolutePath();
|
||||
#else
|
||||
// This is the default behavior on Windows
|
||||
list << QApplication::applicationDirPath() + "/lang";
|
||||
#endif
|
||||
return list;
|
||||
};
|
||||
|
||||
namespace Qv2ray::common
|
||||
{
|
||||
QvTranslator::QvTranslator()
|
||||
{
|
||||
DEBUG(MODULE_UI, "QvTranslator constructor.")
|
||||
GetAvailableLanguages();
|
||||
}
|
||||
|
||||
QStringList QvTranslator::GetAvailableLanguages()
|
||||
{
|
||||
languages.clear();
|
||||
for (auto path : getLanguageSearchPaths())
|
||||
{
|
||||
languages << QDir(path).entryList(QStringList{ "*.qm" }, QDir::Hidden | QDir::Files);
|
||||
}
|
||||
std::transform(languages.begin(), languages.end(), languages.begin(), [](QString &fileName) { return fileName.replace(".qm", ""); });
|
||||
languages.removeDuplicates();
|
||||
DEBUG(MODULE_UI, "Found translations: " + languages.join(" "))
|
||||
return languages;
|
||||
}
|
||||
|
||||
bool QvTranslator::InstallTranslation(const QString &code)
|
||||
{
|
||||
for (auto path : getLanguageSearchPaths())
|
||||
{
|
||||
if (FileExistsIn(QDir(path), code + ".qm"))
|
||||
{
|
||||
LOG(MODULE_UI, "Found " + code + " in folder: " + path)
|
||||
QTranslator *translatorNew = new QTranslator();
|
||||
translatorNew->load(code + ".qm", path);
|
||||
if (pTranslator)
|
||||
{
|
||||
LOG(MODULE_INIT, "Removed translations")
|
||||
qApp->removeTranslator(pTranslator.get());
|
||||
}
|
||||
this->pTranslator.reset(translatorNew);
|
||||
qApp->installTranslator(pTranslator.get());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace Qv2ray::common
|
@ -2,20 +2,30 @@
|
||||
#include <QString>
|
||||
#include <QTranslator>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace Qv2ray::common
|
||||
{
|
||||
class QvTranslator
|
||||
{
|
||||
public:
|
||||
QvTranslator(const QString &lang)
|
||||
{
|
||||
QTranslator *translator = new QTranslator();
|
||||
translator->load(lang + ".qm", ":/translations/");
|
||||
this->pTranslator.reset(translator);
|
||||
}
|
||||
public:
|
||||
explicit QvTranslator();
|
||||
|
||||
public:
|
||||
std::unique_ptr<QTranslator> pTranslator;
|
||||
public:
|
||||
/**
|
||||
* @brief get the available languages.
|
||||
* @return (if available) languages (zh_CN, en_US, ...)
|
||||
*/
|
||||
QStringList GetAvailableLanguages();
|
||||
/**
|
||||
* @brief reload the translation from file
|
||||
* @param code eg: en_US, zh_CN, ...
|
||||
*/
|
||||
bool InstallTranslation(const QString &);
|
||||
|
||||
private:
|
||||
QStringList languages;
|
||||
std::unique_ptr<QTranslator> pTranslator;
|
||||
};
|
||||
inline std::unique_ptr<common::QvTranslator> Qv2rayTranslator;
|
||||
} // namespace Qv2ray::common
|
||||
|
@ -1,13 +1,14 @@
|
||||
#include "QvAutoLaunch.hpp"
|
||||
#include <QSettings>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
#include <QStandardPaths>
|
||||
#include <QTextStream>
|
||||
// macOS headers (possibly OBJ-c)
|
||||
#if defined(Q_OS_MAC)
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
namespace Qv2ray::components::autolaunch
|
||||
{
|
||||
@ -34,8 +35,10 @@ namespace Qv2ray::components::autolaunch
|
||||
}
|
||||
|
||||
#elif defined Q_OS_MAC
|
||||
// From https://github.com/nextcloud/desktop/blob/master/src/common/utility_mac.cpp
|
||||
// this is quite some duplicate code with setLaunchOnStartup, at some point we should fix this FIXME.
|
||||
// From
|
||||
// https://github.com/nextcloud/desktop/blob/master/src/common/utility_mac.cpp
|
||||
// this is quite some duplicate code with setLaunchOnStartup, at some
|
||||
// point we should fix this FIXME.
|
||||
bool returnValue = false;
|
||||
QString filePath = QDir(QCoreApplication::applicationDirPath() + QLatin1String("/../..")).absolutePath();
|
||||
CFStringRef folderCFStr = CFStringCreateWithCString(0, filePath.toUtf8().data(), kCFStringEncodingUTF8);
|
||||
@ -49,14 +52,17 @@ namespace Qv2ray::components::autolaunch
|
||||
CFArrayRef itemsArray = LSSharedFileListCopySnapshot(loginItems, &seedValue);
|
||||
CFStringRef appUrlRefString = CFURLGetString(urlRef); // no need for release
|
||||
|
||||
for (int i = 0; i < CFArrayGetCount(itemsArray); i++) {
|
||||
LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(itemsArray, i);
|
||||
for (int i = 0; i < CFArrayGetCount(itemsArray); i++)
|
||||
{
|
||||
LSSharedFileListItemRef item = (LSSharedFileListItemRef) CFArrayGetValueAtIndex(itemsArray, i);
|
||||
CFURLRef itemUrlRef = NULL;
|
||||
|
||||
if (LSSharedFileListItemResolve(item, 0, &itemUrlRef, NULL) == noErr && itemUrlRef) {
|
||||
if (LSSharedFileListItemResolve(item, 0, &itemUrlRef, NULL) == noErr && itemUrlRef)
|
||||
{
|
||||
CFStringRef itemUrlString = CFURLGetString(itemUrlRef);
|
||||
|
||||
if (CFStringCompare(itemUrlString, appUrlRefString, 0) == kCFCompareEqualTo) {
|
||||
if (CFStringCompare(itemUrlString, appUrlRefString, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
returnValue = true;
|
||||
}
|
||||
|
||||
@ -86,16 +92,20 @@ namespace Qv2ray::components::autolaunch
|
||||
QString appName = QApplication::applicationName();
|
||||
QSettings reg("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
|
||||
|
||||
if (enable) {
|
||||
if (enable)
|
||||
{
|
||||
QString strAppPath = QDir::toNativeSeparators(QCoreApplication::applicationFilePath());
|
||||
reg.setValue(appName, strAppPath);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
reg.remove(appName);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined Q_OS_MAC
|
||||
// From https://github.com/nextcloud/desktop/blob/master/src/common/utility_mac.cpp
|
||||
// From
|
||||
// https://github.com/nextcloud/desktop/blob/master/src/common/utility_mac.cpp
|
||||
QString filePath = QDir(QCoreApplication::applicationDirPath() + QLatin1String("/../..")).absolutePath();
|
||||
CFStringRef folderCFStr = CFStringCreateWithCString(0, filePath.toUtf8().data(), kCFStringEncodingUTF8);
|
||||
CFURLRef urlRef = CFURLCreateWithFileSystemPath(0, folderCFStr, kCFURLPOSIXPathStyle, true);
|
||||
@ -103,30 +113,32 @@ namespace Qv2ray::components::autolaunch
|
||||
|
||||
if (loginItems && enable)
|
||||
{
|
||||
//Insert an item to the list.
|
||||
LSSharedFileListItemRef item = LSSharedFileListInsertItemURL(loginItems,
|
||||
kLSSharedFileListItemLast, 0, 0,
|
||||
urlRef, 0, 0);
|
||||
// Insert an item to the list.
|
||||
LSSharedFileListItemRef item = LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemLast, 0, 0, urlRef, 0, 0);
|
||||
|
||||
if (item)
|
||||
CFRelease(item);
|
||||
|
||||
CFRelease(loginItems);
|
||||
} else if (loginItems && !enable)
|
||||
}
|
||||
else if (loginItems && !enable)
|
||||
{
|
||||
// We need to iterate over the items and check which one is "ours".
|
||||
UInt32 seedValue;
|
||||
CFArrayRef itemsArray = LSSharedFileListCopySnapshot(loginItems, &seedValue);
|
||||
CFStringRef appUrlRefString = CFURLGetString(urlRef);
|
||||
|
||||
for (int i = 0; i < CFArrayGetCount(itemsArray); i++) {
|
||||
LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(itemsArray, i);
|
||||
for (int i = 0; i < CFArrayGetCount(itemsArray); i++)
|
||||
{
|
||||
LSSharedFileListItemRef item = (LSSharedFileListItemRef) CFArrayGetValueAtIndex(itemsArray, i);
|
||||
CFURLRef itemUrlRef = NULL;
|
||||
|
||||
if (LSSharedFileListItemResolve(item, 0, &itemUrlRef, NULL) == noErr && itemUrlRef) {
|
||||
if (LSSharedFileListItemResolve(item, 0, &itemUrlRef, NULL) == noErr && itemUrlRef)
|
||||
{
|
||||
CFStringRef itemUrlString = CFURLGetString(itemUrlRef);
|
||||
|
||||
if (CFStringCompare(itemUrlString, appUrlRefString, 0) == kCFCompareEqualTo) {
|
||||
if (CFStringCompare(itemUrlString, appUrlRefString, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
LSSharedFileListItemRemove(loginItems, item); // remove it!
|
||||
}
|
||||
|
||||
@ -143,6 +155,10 @@ namespace Qv2ray::components::autolaunch
|
||||
}
|
||||
|
||||
#elif defined Q_OS_LINUX
|
||||
//
|
||||
// For AppImage packaging.
|
||||
auto binPath = qEnvironmentVariableIsSet("APPIMAGE") ? qEnvironmentVariable("APPIMAGE") : QCoreApplication::applicationFilePath();
|
||||
//
|
||||
// From https://github.com/nextcloud/desktop/blob/master/src/common/utility_unix.cpp
|
||||
QString appName = QApplication::applicationName();
|
||||
QString userAutoStartPath = getUserAutostartDir_private();
|
||||
@ -150,15 +166,19 @@ namespace Qv2ray::components::autolaunch
|
||||
|
||||
if (enable)
|
||||
{
|
||||
if (!QDir().exists(userAutoStartPath) && !QDir().mkpath(userAutoStartPath)) {
|
||||
// qCWarning(lcUtility) << "Could not create autostart folder" << userAutoStartPath;
|
||||
if (!QDir().exists(userAutoStartPath) && !QDir().mkpath(userAutoStartPath))
|
||||
{
|
||||
// qCWarning(lcUtility) << "Could not create autostart folder"
|
||||
// << userAutoStartPath;
|
||||
return;
|
||||
}
|
||||
|
||||
QFile iniFile(desktopFileLocation);
|
||||
|
||||
if (!iniFile.open(QIODevice::WriteOnly)) {
|
||||
// qCWarning(lcUtility) << "Could not write auto start entry" << desktopFileLocation;
|
||||
if (!iniFile.open(QIODevice::WriteOnly))
|
||||
{
|
||||
// qCWarning(lcUtility) << "Could not write auto start entry" <<
|
||||
// desktopFileLocation;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -167,20 +187,22 @@ namespace Qv2ray::components::autolaunch
|
||||
ts << QLatin1String("[Desktop Entry]") << endl
|
||||
<< QLatin1String("Name=") << QApplication::applicationName() << endl
|
||||
<< QLatin1String("GenericName=") << QLatin1String("V2ray Frontend") << endl
|
||||
<< QLatin1String("Exec=") << QCoreApplication::applicationFilePath() << endl
|
||||
<< QLatin1String("Exec=") << binPath << endl
|
||||
<< QLatin1String("Terminal=") << "false" << endl
|
||||
<< QLatin1String("Icon=") << "qv2ray" << endl // always use lowercase for icons
|
||||
<< QLatin1String("Categories=") << "Network" << endl
|
||||
<< QLatin1String("Type=") << "Application" << endl
|
||||
<< QLatin1String("StartupNotify=") << "false" << endl
|
||||
<< QLatin1String("X-GNOME-Autostart-enabled=") << "true" << endl;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!QFile::remove(desktopFileLocation)) {
|
||||
// qCWarning(lcUtility) << "Could not remove autostart desktop file";
|
||||
if (!QFile::remove(desktopFileLocation))
|
||||
{
|
||||
// qCWarning(lcUtility) << "Could not remove autostart desktop
|
||||
// file";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Qv2ray::components::autolaunch
|
||||
|
@ -4,7 +4,7 @@ namespace Qv2ray::components::autolaunch
|
||||
{
|
||||
bool GetLaunchAtLoginStatus();
|
||||
void SetLaunchAtLoginStatus(bool enable);
|
||||
}
|
||||
} // namespace Qv2ray::components::autolaunch
|
||||
|
||||
using namespace Qv2ray::components;
|
||||
using namespace Qv2ray::components::autolaunch;
|
||||
|
34
src/components/darkmode/DarkmodeDetector.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "DarkmodeDetector.hpp"
|
||||
|
||||
#include <QtGlobal>
|
||||
#ifdef Q_OS_LINUX
|
||||
#include <QApplication>
|
||||
#include <QStyle>
|
||||
#elif defined(Q_OS_WIN32)
|
||||
#include <QSettings>
|
||||
#else
|
||||
// TODO: macOS headers.
|
||||
#endif
|
||||
|
||||
namespace Qv2ray::components::darkmode
|
||||
{
|
||||
// Referenced from github.com/keepassxreboot/keepassxc. Licensed under GPL2/3.
|
||||
// Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
|
||||
bool isDarkMode()
|
||||
{
|
||||
#if defined(Q_OS_LINUX)
|
||||
if (!qApp || !qApp->style())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return qApp->style()->standardPalette().color(QPalette::Window).toHsl().lightness() < 110;
|
||||
#elif defined(Q_OS_WIN32)
|
||||
QSettings settings(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)", QSettings::NativeFormat);
|
||||
return settings.value("AppsUseLightTheme", 1).toInt() == 0;
|
||||
#elif defined(Q_OS_DARWIN)
|
||||
// TODO: expand this stub
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Qv2ray::components::darkmode
|
6
src/components/darkmode/DarkmodeDetector.hpp
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace Qv2ray::components::darkmode
|
||||
{
|
||||
bool isDarkMode();
|
||||
}
|
@ -1,20 +1,22 @@
|
||||
#include "QvGeositeReader.hpp"
|
||||
#include "libs/gen/v2ray_geosite.pb.h"
|
||||
|
||||
#include "v2ray_geosite.pb.h"
|
||||
|
||||
namespace Qv2ray::components::geosite
|
||||
{
|
||||
QStringList ReadGeoSiteFromFile(QString filepath)
|
||||
{
|
||||
QStringList list;
|
||||
LOG(FILEIO, "Reading geosites from: " + filepath)
|
||||
LOG(MODULE_FILEIO, "Reading geosites from: " + filepath)
|
||||
//
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
//
|
||||
QFile f(filepath);
|
||||
bool opened = f.open(QFile::OpenModeFlag::ReadOnly);
|
||||
|
||||
if (!opened) {
|
||||
LOG(FILEIO, "File cannot be opened: " + filepath)
|
||||
if (!opened)
|
||||
{
|
||||
LOG(MODULE_FILEIO, "File cannot be opened: " + filepath)
|
||||
return list;
|
||||
}
|
||||
|
||||
@ -24,14 +26,15 @@ namespace Qv2ray::components::geosite
|
||||
GeoSiteList sites;
|
||||
sites.ParseFromArray(content.data(), content.size());
|
||||
|
||||
for (auto e : sites.entry()) {
|
||||
for (auto e : sites.entry())
|
||||
{
|
||||
// We want to use lower string.
|
||||
list << QString::fromStdString(e.country_code()).toLower();
|
||||
}
|
||||
|
||||
LOG(FILEIO, "Loaded " + QSTRN(list.count()) + " geosite entries from data file.")
|
||||
LOG(MODULE_FILEIO, "Loaded " + QSTRN(list.count()) + " geosite entries from data file.")
|
||||
// Optional: Delete all global objects allocated by libprotobuf.
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
return list;
|
||||
}
|
||||
}
|
||||
} // namespace Qv2ray::components::geosite
|
||||
|
52
src/components/icmping/win/ICMPPinger.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "ICMPPinger.hpp"
|
||||
#if 0
|
||||
|
||||
ICMPPinger::ICMPPinger(UINT64 timeout = DEFAULT_TIMEOUT)
|
||||
{
|
||||
// create icmp handle
|
||||
if ((this->hIcmpFile = IcmpCreateFile()) == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
throw "IcmpCreateFile failed";
|
||||
}
|
||||
|
||||
// remember the timeout
|
||||
this->timeout = timeout;
|
||||
}
|
||||
|
||||
ICMPPinger::~ICMPPinger()
|
||||
{
|
||||
// release the handle on destruction
|
||||
IcmpCloseHandle(this->hIcmpFile);
|
||||
}
|
||||
|
||||
std::pair<std::optional<UINT64>, std::optional<std::string>> ICMPPinger::ping(const std::string &ipAddr)
|
||||
{
|
||||
// convert network address
|
||||
const auto addr = inet_addr(ipAddr.c_str());
|
||||
if (addr == INADDR_NONE)
|
||||
{
|
||||
return std::pair(std::nullopt, "invalid ip address: " + ipAddr);
|
||||
}
|
||||
|
||||
// request buffer
|
||||
const static char bufRequest[] = "echo test";
|
||||
|
||||
// response buffer
|
||||
const auto responseSize = sizeof(ICMP_ECHO_REPLY) + sizeof(bufRequest);
|
||||
const std::unique_ptr<char> bufRecv(new (char[responseSize]));
|
||||
|
||||
// send echo
|
||||
auto ret = IcmpSendEcho(this->hIcmpFile, addr, (LPVOID) bufRequest, sizeof(bufRequest), NULL, bufRecv.get(), responseSize, this->timeout);
|
||||
|
||||
// ret == 0: failed
|
||||
if (ret == 0)
|
||||
{
|
||||
return std::pair(std::nullopt, "IcmpSendEcho returned error");
|
||||
}
|
||||
|
||||
// read round-trip time
|
||||
PICMP_ECHO_REPLY pReply = (PICMP_ECHO_REPLY) bufRecv.get();
|
||||
return std::pair(pReply->RoundTripTime, std::nullopt);
|
||||
}
|
||||
|
||||
#endif
|
34
src/components/icmping/win/ICMPPinger.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include <QtGlobal>
|
||||
#include <optional>
|
||||
#if 0
|
||||
/**
|
||||
* ICMPPinger - An Implementation of ICMPPing on Windows Platform
|
||||
* Required Windows Version: 2000 / XP / 7 / Vista+
|
||||
* License: WTFPL
|
||||
*/
|
||||
|
||||
#include <icmpapi.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <winsock2.h>
|
||||
|
||||
class ICMPPinger
|
||||
{
|
||||
public:
|
||||
ICMPPinger(UINT64 timeout = DEFAULT_TIMEOUT);
|
||||
~ICMPPinger();
|
||||
|
||||
public:
|
||||
static const UINT64 DEFAULT_TIMEOUT = 10000U;
|
||||
|
||||
public:
|
||||
std::pair<std::optional<UINT64>, std::optional<std::string>> ping(const std::string &ipAddr);
|
||||
|
||||
private:
|
||||
HANDLE hIcmpFile;
|
||||
UINT64 timeout = DEFAULT_TIMEOUT;
|
||||
};
|
||||
#endif
|
@ -21,27 +21,37 @@ namespace Qv2ray::components::pac
|
||||
bool passRule1 = originLine.find("|") != string::npos; // Proxy Lines
|
||||
bool passRule2 = originLine.find(".") != string::npos; // Link-Contained Lines
|
||||
|
||||
if (originLine[endPosition] == '\n') {
|
||||
if (originLine[endPosition] == '\n')
|
||||
{
|
||||
endPosition -= 1;
|
||||
}
|
||||
|
||||
if (originLine.find("http://") != string::npos) {
|
||||
if (originLine.find("http://") != string::npos)
|
||||
{
|
||||
startPosition += 8;
|
||||
} else if (originLine.find("https://") != string::npos) {
|
||||
}
|
||||
else if (originLine.find("https://") != string::npos)
|
||||
{
|
||||
startPosition += 9;
|
||||
}
|
||||
|
||||
// Skip unrelated lines
|
||||
if (skipRule1 || skipRule2 || skipRule3 || skipRule4) {
|
||||
if (skipRule1 || skipRule2 || skipRule3 || skipRule4)
|
||||
{
|
||||
return "";
|
||||
} else if (passRule2) {
|
||||
if (passRule1) {
|
||||
}
|
||||
else if (passRule2)
|
||||
{
|
||||
if (passRule1)
|
||||
{
|
||||
startPosition += originLine.find_last_of("|") + 1;
|
||||
}
|
||||
|
||||
if (originLine[startPosition] == '\n') startPosition += 1;
|
||||
if (originLine[startPosition] == '\n')
|
||||
startPosition += 1;
|
||||
|
||||
for (size_t i = startPosition; i < endPosition; ++i) {
|
||||
for (size_t i = startPosition; i < endPosition; ++i)
|
||||
{
|
||||
returnBuffer += originLine[i];
|
||||
}
|
||||
}
|
||||
@ -52,17 +62,20 @@ namespace Qv2ray::components::pac
|
||||
QString ConvertGFWToPAC(const QString &rawContent, const QString &customProxyString)
|
||||
{
|
||||
auto rawFileContent = Base64Decode(rawContent).toStdString();
|
||||
string readBuffer = ""; //cleanup
|
||||
string readBuffer = ""; // cleanup
|
||||
string writeBuffer;
|
||||
string domainListCache = "";
|
||||
|
||||
for (size_t i = 0; i < rawFileContent.size(); ++i) {
|
||||
for (size_t i = 0; i < rawFileContent.size(); ++i)
|
||||
{
|
||||
readBuffer += rawFileContent[i];
|
||||
|
||||
if (rawFileContent[i + 1] == '\n') {
|
||||
if (rawFileContent[i + 1] == '\n')
|
||||
{
|
||||
writeBuffer = getRawDomain(readBuffer);
|
||||
|
||||
if (writeBuffer != "") {
|
||||
if (writeBuffer != "")
|
||||
{
|
||||
domainListCache += writeBuffer + "\n";
|
||||
}
|
||||
|
||||
@ -72,19 +85,22 @@ namespace Qv2ray::components::pac
|
||||
}
|
||||
|
||||
size_t rotatorTwo = 0;
|
||||
string readDomainBuffer = "";
|
||||
string readDomainBuffer = "";
|
||||
bool isFirstLine = true;
|
||||
string outputContent = "";
|
||||
//Header
|
||||
// Header
|
||||
outputContent += "var domains = {\n";
|
||||
|
||||
//Read and process output content line by line
|
||||
while (rotatorTwo < domainListCache.size()) {
|
||||
while (true) {
|
||||
//Get Domain
|
||||
// Read and process output content line by line
|
||||
while (rotatorTwo < domainListCache.size())
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
// Get Domain
|
||||
readDomainBuffer += domainListCache[rotatorTwo];
|
||||
|
||||
if (domainListCache[rotatorTwo + 1] == '\n') {
|
||||
if (domainListCache[rotatorTwo + 1] == '\n')
|
||||
{
|
||||
rotatorTwo += 2;
|
||||
break;
|
||||
}
|
||||
@ -92,9 +108,11 @@ namespace Qv2ray::components::pac
|
||||
rotatorTwo++;
|
||||
}
|
||||
|
||||
//Format
|
||||
if (!isFirstLine) outputContent += ",\n";
|
||||
else isFirstLine = false;
|
||||
// Format
|
||||
if (!isFirstLine)
|
||||
outputContent += ",\n";
|
||||
else
|
||||
isFirstLine = false;
|
||||
|
||||
outputContent += "\t\"";
|
||||
outputContent += readDomainBuffer;
|
||||
@ -102,32 +120,18 @@ namespace Qv2ray::components::pac
|
||||
readDomainBuffer = "";
|
||||
}
|
||||
|
||||
//End Message
|
||||
outputContent +=
|
||||
NEWLINE "};"
|
||||
NEWLINE ""
|
||||
NEWLINE " var proxy = \"" + customProxyString.toStdString() + ";\";" +
|
||||
NEWLINE " var direct = 'DIRECT;';"
|
||||
NEWLINE " function FindProxyForURL(url, host) {"
|
||||
NEWLINE " var suffix;"
|
||||
NEWLINE " var pos = host.lastIndexOf('.');"
|
||||
NEWLINE " pos = host.lastIndexOf('.', pos - 1);"
|
||||
NEWLINE " //"
|
||||
NEWLINE " while (1) {"
|
||||
NEWLINE " if (domains[host] != undefined) {"
|
||||
NEWLINE " return proxy;"
|
||||
NEWLINE " }"
|
||||
NEWLINE " else if (pos <= 0) {"
|
||||
NEWLINE " return domains['.' + host] != undefined ? proxy : direct;"
|
||||
NEWLINE " }"
|
||||
NEWLINE " suffix = host.substring(pos);"
|
||||
NEWLINE " if (domains[suffix] != undefined) {"
|
||||
NEWLINE " return proxy;"
|
||||
NEWLINE " }"
|
||||
NEWLINE " pos = host.lastIndexOf('.', pos - 1);"
|
||||
NEWLINE " }"
|
||||
NEWLINE " }";
|
||||
// End Message
|
||||
outputContent += NEWLINE "};" NEWLINE "" NEWLINE " var proxy = \"" + customProxyString.toStdString() + ";\";" +
|
||||
NEWLINE " var direct = 'DIRECT;';" NEWLINE " function FindProxyForURL(url, host) {" NEWLINE
|
||||
" var suffix;" NEWLINE " var pos = host.lastIndexOf('.');" NEWLINE
|
||||
" pos = host.lastIndexOf('.', pos - 1);" NEWLINE " //" NEWLINE " while (1) {" NEWLINE
|
||||
" if (domains[host] != undefined) {" NEWLINE " return proxy;" NEWLINE
|
||||
" }" NEWLINE " else if (pos <= 0) {" NEWLINE
|
||||
" return domains['.' + host] != undefined ? proxy : direct;" NEWLINE " }" NEWLINE
|
||||
" suffix = host.substring(pos);" NEWLINE " if (domains[suffix] != undefined) {" NEWLINE
|
||||
" return proxy;" NEWLINE " }" NEWLINE
|
||||
" pos = host.lastIndexOf('.', pos - 1);" NEWLINE " }" NEWLINE " }";
|
||||
//
|
||||
return QString::fromStdString(outputContent);
|
||||
}
|
||||
}
|
||||
} // namespace Qv2ray::components::pac
|
||||
|
@ -1,79 +1,82 @@
|
||||
#include "QvPACHandler.hpp"
|
||||
#include "qhttprequest.h"
|
||||
#include "qhttpresponse.h"
|
||||
#include "core/CoreUtils.hpp"
|
||||
|
||||
#include "3rdparty/cpp-httplib/httplib.h"
|
||||
#include "common/QvHelpers.hpp"
|
||||
#include "core/CoreUtils.hpp"
|
||||
|
||||
namespace Qv2ray::components::pac
|
||||
{
|
||||
|
||||
PACServer::PACServer() : QObject(), pacServer(this)
|
||||
PACServer::PACServer() : QThread()
|
||||
{
|
||||
connect(&pacServer, &QHttpServer::newRequest, this, &PACServer::onNewRequest);
|
||||
pacServer = new httplib::Server();
|
||||
}
|
||||
PACServer::~PACServer()
|
||||
{
|
||||
if (isStarted) {
|
||||
pacServer.close();
|
||||
}
|
||||
StopServer();
|
||||
delete pacServer;
|
||||
}
|
||||
void PACServer::SetProxyString(const QString &proxyString)
|
||||
{
|
||||
DEBUG(PROXY, "Setting new PAC proxy string: " + proxyString)
|
||||
DEBUG(MODULE_PROXY, "Setting new PAC proxy string: " + proxyString)
|
||||
this->proxyString = proxyString;
|
||||
}
|
||||
void PACServer::StartListen()
|
||||
void PACServer::run()
|
||||
{
|
||||
LOG(PROXY, "Starting PAC listener")
|
||||
LOG(MODULE_PROXY, "Starting PAC listener")
|
||||
//
|
||||
auto address = GlobalConfig.inboundConfig.listenip;
|
||||
auto port = GlobalConfig.inboundConfig.pacConfig.port;
|
||||
//
|
||||
DEBUG(PROXY, "PAC Listening local endpoint: " + address + ":" + QSTRN(port))
|
||||
DEBUG(MODULE_PROXY, "PAC Listening local endpoint: " + address + ":" + QSTRN(port))
|
||||
//
|
||||
QString gfwContent = StringFromFile(QV2RAY_RULES_GFWLIST_PATH);
|
||||
pacContent = ConvertGFWToPAC(gfwContent, proxyString);
|
||||
//
|
||||
auto result = pacServer.listen(QHostAddress(address), static_cast<ushort>(port));
|
||||
|
||||
if (result) {
|
||||
isStarted = true;
|
||||
DEBUG(PROXY, "Started PAC handler")
|
||||
} else {
|
||||
LOG(PROXY, "Failed to listen on port " + QSTRN(port) + ", possible permission denied.")
|
||||
pacServer->Get("/pac", onNewRequest);
|
||||
auto result = pacServer->listen(address.toStdString().c_str(), static_cast<ushort>(port));
|
||||
if (result)
|
||||
{
|
||||
DEBUG(MODULE_PROXY, "PAC handler stopped.")
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(MODULE_PROXY, "Failed to listen on port " + QSTRN(port) + ", possible permission denied.")
|
||||
QvMessageBoxWarn(nullptr, tr("PAC Handler"), tr("Failed to listen PAC request on this port, please verify the permissions"));
|
||||
}
|
||||
}
|
||||
|
||||
void PACServer::StopServer()
|
||||
{
|
||||
if (isStarted) {
|
||||
pacServer.close();
|
||||
DEBUG(PROXY, "PAC Handler stopped.")
|
||||
isStarted = false;
|
||||
if (pacServer->is_running())
|
||||
{
|
||||
pacServer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void PACServer::onNewRequest(QHttpRequest *req, QHttpResponse *rsp)
|
||||
void PACServer::onNewRequest(const httplib::Request &req, httplib::Response &rsp)
|
||||
{
|
||||
rsp->setHeader("Server", "Qv2ray/" QV2RAY_VERSION_STRING " PAC_Handler");
|
||||
|
||||
if (req->method() == QHttpRequest::HTTP_GET) {
|
||||
//
|
||||
if (req->path() == "/pac") {
|
||||
DEBUG(PROXY, "Serving PAC file request.")
|
||||
rsp.set_header("Server", "Qv2ray/" QV2RAY_VERSION_STRING " PAC_Handler");
|
||||
if (req.method == "GET")
|
||||
{
|
||||
if (req.path == "/pac")
|
||||
{
|
||||
DEBUG(MODULE_PROXY, "Serving PAC file request.")
|
||||
//
|
||||
rsp->setHeader("Content-Type", "application/javascript; charset=utf-8");
|
||||
rsp->writeHead(QHttpResponse::StatusCode::STATUS_OK);
|
||||
rsp->end(pacContent.toUtf8());
|
||||
DEBUG(PROXY, "Serving a pac file...")
|
||||
} else {
|
||||
rsp->writeHead(QHttpResponse::StatusCode::STATUS_NOT_FOUND);
|
||||
rsp->end("NOT FOUND");
|
||||
rsp.status = 200;
|
||||
rsp.set_content(pacContent.toStdString(), "application/javascript; charset=utf-8");
|
||||
DEBUG(MODULE_PROXY, "Serving a pac file...")
|
||||
}
|
||||
} else {
|
||||
rsp->writeHead(QHttpResponse::StatusCode::STATUS_METHOD_NOT_ALLOWED);
|
||||
rsp->end("PAC ONLY SUPPORT GET");
|
||||
else
|
||||
{
|
||||
rsp.status = 404;
|
||||
rsp.set_content("NOT FOUND", "text/plain; charset=utf-8");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rsp.status = 405;
|
||||
rsp.set_content("PAC ONLY SUPPORT GET", "text/plain; charset=utf-8");
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Qv2ray::components::pac
|
||||
|
@ -1,33 +1,44 @@
|
||||
#pragma once
|
||||
#include "qhttpserver.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <memory>
|
||||
|
||||
namespace httplib
|
||||
{
|
||||
class Server;
|
||||
struct Request;
|
||||
struct Response;
|
||||
} // namespace httplib
|
||||
|
||||
namespace Qv2ray::components::pac
|
||||
{
|
||||
QString ConvertGFWToPAC(const QString &rawContent, const QString &customProxyString);
|
||||
class PACServer : public QObject
|
||||
class PACServer : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PACServer();
|
||||
~PACServer();
|
||||
void SetProxyString(const QString &proxyString);
|
||||
void StartListen();
|
||||
void StopServer();
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PACServer();
|
||||
~PACServer();
|
||||
void SetProxyString(const QString &proxyString);
|
||||
void StartListen()
|
||||
{
|
||||
start();
|
||||
}
|
||||
void StopServer();
|
||||
|
||||
QString gfwFilePath;
|
||||
QString gfwFilePath;
|
||||
|
||||
public slots:
|
||||
void onNewRequest(QHttpRequest *request, QHttpResponse *response);
|
||||
private:
|
||||
void run() override;
|
||||
httplib::Server *pacServer;
|
||||
QString proxyString;
|
||||
|
||||
private:
|
||||
bool isStarted;
|
||||
QHttpServer pacServer;
|
||||
QString pacContent;
|
||||
QString proxyString;
|
||||
private:
|
||||
static void onNewRequest(const httplib::Request &req, httplib::Response &rsp);
|
||||
static inline QString pacContent;
|
||||
};
|
||||
}
|
||||
} // namespace Qv2ray::components::pac
|
||||
|
||||
using namespace Qv2ray::components;
|
||||
using namespace Qv2ray::components::pac;
|
||||
|
@ -1,7 +1,9 @@
|
||||
#include <QThread>
|
||||
#include "ui/w_MainWindow.hpp"
|
||||
#include "components/plugins/toolbar/QvToolbar.hpp"
|
||||
#include "components/plugins/toolbar/QvToolbar.hpp"
|
||||
|
||||
#include "common/QvHelpers.hpp"
|
||||
#include "core/handler/ConfigHandler.hpp"
|
||||
|
||||
#include <QThread>
|
||||
|
||||
namespace Qv2ray::components::plugins
|
||||
{
|
||||
@ -30,129 +32,148 @@ namespace Qv2ray::components::plugins
|
||||
}
|
||||
QString GetAnswerToRequest(const QString &pchRequest)
|
||||
{
|
||||
auto instance = MainWindow::mwInstance;
|
||||
|
||||
if (instance == nullptr || instance->vinstance == nullptr) {
|
||||
LOG(PLUGIN, "MainWindow != nullptr Assertion failed!")
|
||||
return "{}";
|
||||
}
|
||||
|
||||
auto vinstance = instance->vinstance;
|
||||
//
|
||||
auto req = pchRequest.trimmed();
|
||||
QString reply = "{}";
|
||||
|
||||
if (req == "START") {
|
||||
emit instance->Connect();
|
||||
} else if (req == "STOP") {
|
||||
emit instance->DisConnect();
|
||||
} else if (req == "RESTART") {
|
||||
emit instance->ReConnect();
|
||||
if (req == "START")
|
||||
{
|
||||
emit ConnectionManager->RestartConnection();
|
||||
}
|
||||
else if (req == "STOP")
|
||||
{
|
||||
emit ConnectionManager->StopConnection();
|
||||
}
|
||||
else if (req == "RESTART")
|
||||
{
|
||||
emit ConnectionManager->RestartConnection();
|
||||
}
|
||||
|
||||
auto BarConfig = GlobalConfig.toolBarConfig;
|
||||
|
||||
for (auto i = 0; i < BarConfig.Pages.size(); i++) {
|
||||
for (auto j = 0; j < BarConfig.Pages[i].Lines.size(); j++) {
|
||||
for (auto i = 0; i < BarConfig.Pages.size(); i++)
|
||||
{
|
||||
for (auto j = 0; j < BarConfig.Pages[i].Lines.size(); j++)
|
||||
{
|
||||
#define CL BarConfig.Pages[i].Lines[j]
|
||||
|
||||
switch (CL.ContentType) {
|
||||
case 0: {
|
||||
switch (CL.ContentType)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
// Custom Text
|
||||
// We do nothing...
|
||||
break;
|
||||
}
|
||||
|
||||
case 101: {
|
||||
case 101:
|
||||
{
|
||||
// Current Time
|
||||
CL.Message = QTime().currentTime().toString("hh:mm:ss");
|
||||
break;
|
||||
}
|
||||
|
||||
case 102: {
|
||||
case 102:
|
||||
{
|
||||
// Current Date
|
||||
CL.Message = QDate().currentDate().toString("yyyy-MM-dd");
|
||||
break;
|
||||
}
|
||||
|
||||
case 103: {
|
||||
case 103:
|
||||
{
|
||||
// Current Qv2ray Version
|
||||
CL.Message = QV2RAY_VERSION_STRING;
|
||||
break;
|
||||
}
|
||||
|
||||
case 104: {
|
||||
case 104:
|
||||
{
|
||||
// Current Connection Name
|
||||
CL.Message = instance->GetCurrentConnectedConfigName();
|
||||
CL.Message = GetDisplayName(ConnectionManager->CurrentConnection());
|
||||
break;
|
||||
}
|
||||
|
||||
case 105: {
|
||||
case 105:
|
||||
{
|
||||
// Current Connection Status
|
||||
CL.Message = instance->vinstance->KernelStarted
|
||||
? QObject::tr("Connected")
|
||||
: QObject::tr("Disconnected");
|
||||
CL.Message = ConnectionManager->CurrentConnection() == NullConnectionId ? QObject::tr("Not connected") :
|
||||
QObject::tr("Connected");
|
||||
break;
|
||||
}
|
||||
|
||||
case 201: {
|
||||
// Total upload speed;
|
||||
CL.Message = FormatBytes(vinstance->getAllSpeedUp()) + "/s";
|
||||
break;
|
||||
}
|
||||
// case 201:
|
||||
//{
|
||||
// // Total upload speed;
|
||||
// CL.Message = FormatBytes(get<0>(GetConnectionUsageAmount())) + "/s";
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
// case 202:
|
||||
//{
|
||||
// // Total download speed;
|
||||
// CL.Message = FormatBytes(vinstance->getAllSpeedDown()) + "/s";
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
// case 203:
|
||||
//{
|
||||
// // Upload speed for tag
|
||||
// CL.Message = FormatBytes(vinstance->getTagSpeedUp(CL.Message)) + "/s";
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
// case 204:
|
||||
//{
|
||||
// // Download speed for tag
|
||||
// CL.Message = FormatBytes(vinstance->getTagSpeedDown(CL.Message)) + "/s";
|
||||
// break;
|
||||
//}
|
||||
|
||||
case 202: {
|
||||
// Total download speed;
|
||||
CL.Message = FormatBytes(vinstance->getAllSpeedDown()) + "/s";
|
||||
break;
|
||||
}
|
||||
|
||||
case 203: {
|
||||
// Upload speed for tag
|
||||
CL.Message = FormatBytes(vinstance->getTagSpeedUp(CL.Message)) + "/s";
|
||||
break;
|
||||
}
|
||||
|
||||
case 204: {
|
||||
// Download speed for tag
|
||||
CL.Message = FormatBytes(vinstance->getTagSpeedDown(CL.Message)) + "/s";
|
||||
break;
|
||||
}
|
||||
|
||||
case 301: {
|
||||
case 301:
|
||||
{
|
||||
// Total Upload
|
||||
CL.Message = FormatBytes(vinstance->getAllDataUp());
|
||||
CL.Message = FormatBytes(get<0>(GetConnectionUsageAmount(ConnectionManager->CurrentConnection())));
|
||||
break;
|
||||
}
|
||||
|
||||
case 302: {
|
||||
case 302:
|
||||
{
|
||||
// Total download
|
||||
CL.Message = FormatBytes(vinstance->getAllDataDown());
|
||||
CL.Message = FormatBytes(get<1>(GetConnectionUsageAmount(ConnectionManager->CurrentConnection())));
|
||||
break;
|
||||
}
|
||||
|
||||
case 303: {
|
||||
// Upload for tag
|
||||
CL.Message = FormatBytes(vinstance->getTagDataUp(CL.Message));
|
||||
// case 303:
|
||||
//{
|
||||
// // Upload for tag
|
||||
// CL.Message = FormatBytes(vinstance->getTagDataUp(CL.Message));
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
// case 304:
|
||||
//{
|
||||
// // Download for tag
|
||||
// CL.Message = FormatBytes(vinstance->getTagDataDown(CL.Message));
|
||||
// break;
|
||||
//}
|
||||
|
||||
case 305:
|
||||
{
|
||||
// Connection latency
|
||||
CL.Message = QSTRN(GetConnectionLatency(ConnectionManager->CurrentConnection())) + " ms";
|
||||
break;
|
||||
}
|
||||
|
||||
case 304: {
|
||||
// Download for tag
|
||||
CL.Message = FormatBytes(vinstance->getTagDataDown(CL.Message));
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
CL.Message = "Not Supported?";
|
||||
default:
|
||||
{
|
||||
CL.Message = "Not Implemented";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef CL
|
||||
reply = StructToJsonString(BarConfig);
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Toolbar
|
||||
} // namespace Qv2ray::components::plugins
|
||||
|
@ -9,8 +9,8 @@ namespace Qv2ray::components::plugins
|
||||
namespace Toolbar
|
||||
{
|
||||
/// NO NOT CHANGE THE ORDER
|
||||
static const QMap<int, QString> NetSpeedPluginMessages {
|
||||
{ 0, QObject::tr("Custom Text")},
|
||||
static const QMap<int, QString> NetSpeedPluginMessages{
|
||||
{ 0, QObject::tr("Custom Text") },
|
||||
// Current Status
|
||||
{ 101, QObject::tr("Current Time") },
|
||||
{ 102, QObject::tr("Current Date") },
|
||||
@ -20,13 +20,14 @@ namespace Qv2ray::components::plugins
|
||||
// Speeds
|
||||
{ 201, QObject::tr("Total Upload Speed") },
|
||||
{ 202, QObject::tr("Total Download Speed") },
|
||||
{ 203, QObject::tr("Upload Speed for Specific Tag") },
|
||||
{ 204, QObject::tr("Download Speed for Specific Tag") },
|
||||
//{ 203, QObject::tr("Upload Speed for Specific Tag") },
|
||||
//{ 204, QObject::tr("Download Speed for Specific Tag") },
|
||||
// Datas
|
||||
{ 301, QObject::tr("Total Uploaded Data") },
|
||||
{ 302, QObject::tr("Total Downloaded Data") },
|
||||
{ 303, QObject::tr("Uploaded Data for Specific Tag") },
|
||||
{ 304, QObject::tr("Downloaded Data for Specific Tag") }
|
||||
//{ 303, QObject::tr("Uploaded Data for Specific Tag") },
|
||||
//{ 304, QObject::tr("Downloaded Data for Specific Tag") }
|
||||
{ 305, QObject::tr("Current Connection Latency") } //
|
||||
};
|
||||
void StartProcessingPlugins();
|
||||
void StopProcessingPlugins();
|
||||
@ -35,7 +36,7 @@ namespace Qv2ray::components::plugins
|
||||
{
|
||||
void StartNamedPipeThread();
|
||||
void KillNamedPipeThread();
|
||||
}
|
||||
} // namespace _win
|
||||
#endif
|
||||
#ifdef Q_OS_LINUX
|
||||
namespace _linux
|
||||
@ -45,13 +46,12 @@ namespace Qv2ray::components::plugins
|
||||
void StartMessageQThread();
|
||||
void StopMessageQThread();
|
||||
|
||||
}
|
||||
} // namespace _linux
|
||||
#endif
|
||||
|
||||
QString GetAnswerToRequest(const QString &pchRequest);
|
||||
}
|
||||
}
|
||||
} // namespace Toolbar
|
||||
} // namespace Qv2ray::components::plugins
|
||||
|
||||
using namespace Qv2ray::components;
|
||||
using namespace Qv2ray::components::plugins::Toolbar;
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
#include <QtCore>
|
||||
#ifdef Q_OS_LINUX
|
||||
#include "components/plugins/toolbar/QvToolbar.hpp"
|
||||
#include "common/QvHelpers.hpp"
|
||||
#include <QLocalSocket>
|
||||
#include <QLocalServer>
|
||||
#include "common/QvHelpers.hpp"
|
||||
#include "components/plugins/toolbar/QvToolbar.hpp"
|
||||
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
namespace Qv2ray::components::plugins::Toolbar
|
||||
{
|
||||
namespace _linux
|
||||
@ -19,32 +20,41 @@ namespace Qv2ray::components::plugins::Toolbar
|
||||
if (!socket->waitForConnected() || !socket->waitForReadyRead())
|
||||
return;
|
||||
|
||||
try {
|
||||
while (!isExiting && socket->isOpen() && socket->isValid() && socket->waitForReadyRead()) {
|
||||
try
|
||||
{
|
||||
while (!isExiting && socket->isOpen() && socket->isValid() && socket->waitForReadyRead())
|
||||
{
|
||||
// CANNOT PROPERLY READ...
|
||||
// Temp-ly fixed (but why and how?)
|
||||
auto in = QString(socket->readAll());
|
||||
|
||||
if (!isExiting && !in.isEmpty()) {
|
||||
if (!isExiting && !in.isEmpty())
|
||||
{
|
||||
auto out = GetAnswerToRequest(in);
|
||||
//
|
||||
socket->write(out.toUtf8());
|
||||
socket->flush();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
QThread::msleep(200);
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
LOG(PLUGIN, "Closing a broken socket.")
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG(MODULE_PLUGIN, "Closing a broken socket.")
|
||||
}
|
||||
}
|
||||
void DataMessageQThread()
|
||||
{
|
||||
server = new QLocalServer();
|
||||
// BUG Sometimes failed to listen due to improper close of last session.
|
||||
// BUG Sometimes failed to listen due to improper close of last
|
||||
// session.
|
||||
bool listening = server->listen(QV2RAY_NETSPEED_PLUGIN_PIPE_NAME_LINUX);
|
||||
|
||||
while (!isExiting && !listening) {
|
||||
while (!isExiting && !listening)
|
||||
{
|
||||
QThread::msleep(500);
|
||||
listening = server->listen(QV2RAY_NETSPEED_PLUGIN_PIPE_NAME_LINUX);
|
||||
}
|
||||
@ -53,10 +63,11 @@ namespace Qv2ray::components::plugins::Toolbar
|
||||
server->setSocketOptions(QLocalServer::WorldAccessOption);
|
||||
QObject::connect(server, &QLocalServer::newConnection, &qobject_proxy);
|
||||
|
||||
while (!isExiting) {
|
||||
while (!isExiting)
|
||||
{
|
||||
bool result = server->waitForNewConnection(5000, &timeOut);
|
||||
DEBUG(PLUGIN, "Plugin thread listening failed: " + server->errorString())
|
||||
DEBUG(PLUGIN, "waitForNewConnection: " + QString(result ? "true" : "false") + ", " + QString(timeOut ? "true" : "false"))
|
||||
DEBUG(MODULE_PLUGIN, "Plugin thread listening failed: " + server->errorString())
|
||||
DEBUG(MODULE_PLUGIN, "waitForNewConnection: " + QString(result ? "true" : "false") + ", " + QString(timeOut ? "true" : "false"))
|
||||
}
|
||||
|
||||
server->close();
|
||||
@ -72,13 +83,14 @@ namespace Qv2ray::components::plugins::Toolbar
|
||||
{
|
||||
isExiting = true;
|
||||
|
||||
if (linuxWorkerThread->isRunning()) {
|
||||
LOG(PLUGIN, "Waiting for linuxWorkerThread to stop.")
|
||||
if (linuxWorkerThread->isRunning())
|
||||
{
|
||||
LOG(MODULE_PLUGIN, "Waiting for linuxWorkerThread to stop.")
|
||||
linuxWorkerThread->wait();
|
||||
}
|
||||
|
||||
delete _linux::linuxWorkerThread;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace _linux
|
||||
} // namespace Qv2ray::components::plugins::Toolbar
|
||||
#endif
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include <QtCore>
|
||||
#ifdef Q_OS_WIN
|
||||
#include "components/plugins/toolbar/QvToolbar.hpp"
|
||||
#include "common/QvHelpers.hpp"
|
||||
#include <windows.h>
|
||||
#include "common/QvHelpers.hpp"
|
||||
#include "components/plugins/toolbar/QvToolbar.hpp"
|
||||
|
||||
#include <windows.h>
|
||||
namespace Qv2ray::components::plugins::Toolbar
|
||||
{
|
||||
namespace _win
|
||||
@ -25,40 +26,53 @@ namespace Qv2ray::components::plugins::Toolbar
|
||||
{
|
||||
auto hThread = CreateThread(nullptr, 0, NamedPipeMasterThread, nullptr, 0, nullptr);
|
||||
|
||||
if (hThread == nullptr) {
|
||||
LOG(PLUGIN, "CreateThread failed, GLE=" + QSTRN(GetLastError()))
|
||||
if (hThread == nullptr)
|
||||
{
|
||||
LOG(MODULE_PLUGIN, "CreateThread failed, GLE=" + QSTRN(GetLastError()))
|
||||
return;
|
||||
} else CloseHandle(hThread);
|
||||
}
|
||||
else
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
|
||||
DWORD WINAPI NamedPipeMasterThread(LPVOID lpvParam)
|
||||
{
|
||||
Q_UNUSED(lpvParam)
|
||||
BOOL fConnected = FALSE;
|
||||
DWORD dwThreadId = 0;
|
||||
BOOL fConnected = FALSE;
|
||||
DWORD dwThreadId = 0;
|
||||
HANDLE hPipe = INVALID_HANDLE_VALUE;
|
||||
auto lpszPipename = QString(QV2RAY_NETSPEED_PLUGIN_PIPE_NAME_WIN).toStdWString();
|
||||
|
||||
while (!isExiting) {
|
||||
//printf("Pipe Server: Main thread awaiting client connection on %s\n", lpszPipename.c_str());
|
||||
hPipe = CreateNamedPipe(lpszPipename.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, 0, nullptr);
|
||||
while (!isExiting)
|
||||
{
|
||||
// printf("Pipe Server: Main thread awaiting client connection
|
||||
// on %s\n", lpszPipename.c_str());
|
||||
hPipe = CreateNamedPipe(lpszPipename.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
||||
PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, 0, nullptr);
|
||||
|
||||
if (hPipe == INVALID_HANDLE_VALUE) {
|
||||
LOG(PLUGIN, "CreateNamedPipe failed, GLE=" + QSTRN(GetLastError()))
|
||||
if (hPipe == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
LOG(MODULE_PLUGIN, "CreateNamedPipe failed, GLE=" + QSTRN(GetLastError()))
|
||||
return static_cast<DWORD>(-1);
|
||||
}
|
||||
|
||||
fConnected = ConnectNamedPipe(hPipe, nullptr) ? true : (GetLastError() == ERROR_PIPE_CONNECTED);
|
||||
|
||||
if (fConnected) {
|
||||
LOG(PLUGIN, "Client connected, creating a processing thread")
|
||||
if (fConnected)
|
||||
{
|
||||
LOG(MODULE_PLUGIN, "Client connected, creating a processing thread")
|
||||
ThreadHandle = CreateThread(nullptr, 0, InstanceThread, hPipe, 0, &dwThreadId);
|
||||
|
||||
if (ThreadHandle == nullptr) {
|
||||
LOG(PLUGIN, "CreateThread failed, GLE=" + QSTRN(GetLastError()))
|
||||
if (ThreadHandle == nullptr)
|
||||
{
|
||||
LOG(MODULE_PLUGIN, "CreateThread failed, GLE=" + QSTRN(GetLastError()))
|
||||
return static_cast<DWORD>(-1);
|
||||
} else CloseHandle(ThreadHandle);
|
||||
} else CloseHandle(hPipe);
|
||||
}
|
||||
else
|
||||
CloseHandle(ThreadHandle);
|
||||
}
|
||||
else
|
||||
CloseHandle(hPipe);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -71,14 +85,19 @@ namespace Qv2ray::components::plugins::Toolbar
|
||||
HANDLE hPipe = static_cast<HANDLE>(lpvParam);
|
||||
TCHAR pchRequest[BUFSIZE] = { 0 };
|
||||
|
||||
while (!isExiting) {
|
||||
while (!isExiting)
|
||||
{
|
||||
fSuccess = ReadFile(hPipe, pchRequest, BUFSIZE * sizeof(TCHAR), &cbBytesRead, nullptr);
|
||||
|
||||
if (!fSuccess || cbBytesRead == 0) {
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE) {
|
||||
LOG(PLUGIN, "InstanceThread: client disconnected, GLE=" + QSTRN(GetLastError()))
|
||||
} else {
|
||||
LOG(PLUGIN, "InstanceThread ReadFile failed, GLE=" + QSTRN(GetLastError()))
|
||||
if (!fSuccess || cbBytesRead == 0)
|
||||
{
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE)
|
||||
{
|
||||
LOG(MODULE_PLUGIN, "InstanceThread: client disconnected, GLE=" + QSTRN(GetLastError()))
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(MODULE_PLUGIN, "InstanceThread ReadFile failed, GLE=" + QSTRN(GetLastError()))
|
||||
}
|
||||
|
||||
break;
|
||||
@ -87,18 +106,21 @@ namespace Qv2ray::components::plugins::Toolbar
|
||||
auto req = QString::fromStdWString(pchRequest);
|
||||
QString replyQString = "{}";
|
||||
|
||||
if (!isExiting) {
|
||||
if (!isExiting)
|
||||
{
|
||||
replyQString = GetAnswerToRequest(req);
|
||||
//
|
||||
// REPLY as std::string
|
||||
std::string pchReply = replyQString.toUtf8().constData();
|
||||
cbReplyBytes = static_cast<DWORD>(pchReply.length() + 1) * sizeof(CHAR);
|
||||
//cbReplyBytes = static_cast<DWORD>(replyQString.length() + 1) * sizeof(TCHAR);
|
||||
// cbReplyBytes = static_cast<DWORD>(replyQString.length() +
|
||||
// 1) * sizeof(TCHAR);
|
||||
//
|
||||
fSuccess = WriteFile(hPipe, pchReply.c_str(), cbReplyBytes, &cbWritten, nullptr);
|
||||
|
||||
if (!fSuccess || cbReplyBytes != cbWritten) {
|
||||
LOG(PLUGIN, "InstanceThread WriteFile failed, GLE=" + QSTRN(GetLastError()))
|
||||
if (!fSuccess || cbReplyBytes != cbWritten)
|
||||
{
|
||||
LOG(MODULE_PLUGIN, "InstanceThread WriteFile failed, GLE=" + QSTRN(GetLastError()))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -109,6 +131,6 @@ namespace Qv2ray::components::plugins::Toolbar
|
||||
CloseHandle(hPipe);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace _win
|
||||
} // namespace Qv2ray::components::plugins::Toolbar
|
||||
#endif
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include "QvProxyConfigurator.hpp"
|
||||
|
||||
#include "common/QvHelpers.hpp"
|
||||
#ifdef Q_OS_WIN
|
||||
#include "wininet.h"
|
||||
#include <windows.h>
|
||||
#include <WinInet.h>
|
||||
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
namespace Qv2ray::components::proxy
|
||||
@ -13,30 +15,33 @@ namespace Qv2ray::components::proxy
|
||||
{
|
||||
QProcess p;
|
||||
p.setProgram("/usr/sbin/networksetup");
|
||||
p.setArguments(QStringList() << "-listallnetworkservices");
|
||||
p.setArguments(QStringList{ "-listallnetworkservices" });
|
||||
p.start();
|
||||
p.waitForStarted();
|
||||
p.waitForFinished();
|
||||
LOG(PROXY, p.errorString())
|
||||
LOG(MODULE_PROXY, p.errorString())
|
||||
auto str = p.readAllStandardOutput();
|
||||
auto lines = SplitLines(str);
|
||||
QStringList result;
|
||||
|
||||
// Start from 1 since first line is unneeded.
|
||||
for (auto i = 1; i < lines.count(); i++) {
|
||||
for (auto i = 1; i < lines.count(); i++)
|
||||
{
|
||||
// * means disabled.
|
||||
if (!lines[i].contains("*")) {
|
||||
result << (lines[i].contains(" ") ? "\"" + lines[i] + "\"" : lines[i]);
|
||||
if (!lines[i].contains("*"))
|
||||
{
|
||||
result << (lines[i].contains(" ") ? "\"" + lines[i] + "\"" : lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
LOG(PROXY, "Found " + QSTRN(result.size()) + " network services: " + result.join(";"))
|
||||
LOG(MODULE_PROXY, "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");
|
||||
#define NO_CONST(expr) const_cast<wchar_t *>(expr)
|
||||
// static auto DEFAULT_CONNECTION_NAME =
|
||||
// NO_CONST(L"DefaultConnectionSettings");
|
||||
///
|
||||
/// INTERNAL FUNCTION
|
||||
bool __QueryProxyOptions()
|
||||
@ -52,58 +57,69 @@ namespace Qv2ray::components::proxy
|
||||
Option[4].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
|
||||
//
|
||||
List.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LIST);
|
||||
List.pszConnection = nullptr;// NO_CONST(DEFAULT_CONNECTION_NAME);
|
||||
List.pszConnection = nullptr; // NO_CONST(DEFAULT_CONNECTION_NAME);
|
||||
List.dwOptionCount = 5;
|
||||
List.dwOptionError = 0;
|
||||
List.pOptions = Option;
|
||||
|
||||
if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) {
|
||||
LOG(PROXY, "InternetQueryOption failed, GLE=" + QSTRN(GetLastError()))
|
||||
if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize))
|
||||
{
|
||||
LOG(MODULE_PROXY, "InternetQueryOption failed, GLE=" + QSTRN(GetLastError()))
|
||||
}
|
||||
|
||||
LOG(PROXY, "System default proxy info:")
|
||||
LOG(MODULE_PROXY, "System default proxy info:")
|
||||
|
||||
if (Option[0].Value.pszValue != nullptr) {
|
||||
LOG(PROXY, QString::fromWCharArray(Option[0].Value.pszValue))
|
||||
if (Option[0].Value.pszValue != nullptr)
|
||||
{
|
||||
LOG(MODULE_PROXY, QString::fromWCharArray(Option[0].Value.pszValue))
|
||||
}
|
||||
|
||||
if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL) == PROXY_TYPE_AUTO_PROXY_URL) {
|
||||
LOG(PROXY, "PROXY_TYPE_AUTO_PROXY_URL")
|
||||
if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL) == PROXY_TYPE_AUTO_PROXY_URL)
|
||||
{
|
||||
LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_PROXY_URL")
|
||||
}
|
||||
|
||||
if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_DETECT) == PROXY_TYPE_AUTO_DETECT) {
|
||||
LOG(PROXY, "PROXY_TYPE_AUTO_DETECT")
|
||||
if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_DETECT) == PROXY_TYPE_AUTO_DETECT)
|
||||
{
|
||||
LOG(MODULE_PROXY, "PROXY_TYPE_AUTO_DETECT")
|
||||
}
|
||||
|
||||
if ((Option[2].Value.dwValue & PROXY_TYPE_DIRECT) == PROXY_TYPE_DIRECT) {
|
||||
LOG(PROXY, "PROXY_TYPE_DIRECT")
|
||||
if ((Option[2].Value.dwValue & PROXY_TYPE_DIRECT) == PROXY_TYPE_DIRECT)
|
||||
{
|
||||
LOG(MODULE_PROXY, "PROXY_TYPE_DIRECT")
|
||||
}
|
||||
|
||||
if ((Option[2].Value.dwValue & PROXY_TYPE_PROXY) == PROXY_TYPE_PROXY) {
|
||||
LOG(PROXY, "PROXY_TYPE_PROXY")
|
||||
if ((Option[2].Value.dwValue & PROXY_TYPE_PROXY) == PROXY_TYPE_PROXY)
|
||||
{
|
||||
LOG(MODULE_PROXY, "PROXY_TYPE_PROXY")
|
||||
}
|
||||
|
||||
if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) {
|
||||
LOG(PROXY, "InternetQueryOption failed,GLE=" + QSTRN(GetLastError()))
|
||||
if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize))
|
||||
{
|
||||
LOG(MODULE_PROXY, "InternetQueryOption failed,GLE=" + QSTRN(GetLastError()))
|
||||
}
|
||||
|
||||
if (Option[4].Value.pszValue != nullptr) {
|
||||
LOG(PROXY, QString::fromStdWString(Option[4].Value.pszValue))
|
||||
if (Option[4].Value.pszValue != nullptr)
|
||||
{
|
||||
LOG(MODULE_PROXY, QString::fromStdWString(Option[4].Value.pszValue))
|
||||
}
|
||||
|
||||
INTERNET_VERSION_INFO Version;
|
||||
nSize = sizeof(INTERNET_VERSION_INFO);
|
||||
InternetQueryOption(nullptr, INTERNET_OPTION_VERSION, &Version, &nSize);
|
||||
|
||||
if (Option[0].Value.pszValue != nullptr) {
|
||||
if (Option[0].Value.pszValue != nullptr)
|
||||
{
|
||||
GlobalFree(Option[0].Value.pszValue);
|
||||
}
|
||||
|
||||
if (Option[3].Value.pszValue != nullptr) {
|
||||
if (Option[3].Value.pszValue != nullptr)
|
||||
{
|
||||
GlobalFree(Option[3].Value.pszValue);
|
||||
}
|
||||
|
||||
if (Option[4].Value.pszValue != nullptr) {
|
||||
if (Option[4].Value.pszValue != nullptr)
|
||||
{
|
||||
GlobalFree(Option[4].Value.pszValue);
|
||||
}
|
||||
|
||||
@ -112,21 +128,23 @@ namespace Qv2ray::components::proxy
|
||||
bool __SetProxyOptions(LPWSTR proxy_full_addr, bool isPAC)
|
||||
{
|
||||
INTERNET_PER_CONN_OPTION_LIST list;
|
||||
BOOL bReturn;
|
||||
DWORD dwBufSize = sizeof(list);
|
||||
BOOL bReturn;
|
||||
DWORD dwBufSize = sizeof(list);
|
||||
// Fill the list structure.
|
||||
list.dwSize = sizeof(list);
|
||||
// NULL == LAN, otherwise connectoid name.
|
||||
list.pszConnection = nullptr;
|
||||
|
||||
if (isPAC) {
|
||||
LOG(PROXY, "Setting system proxy for PAC")
|
||||
if (isPAC)
|
||||
{
|
||||
LOG(MODULE_PROXY, "Setting system proxy for PAC")
|
||||
//
|
||||
list.dwOptionCount = 2;
|
||||
list.pOptions = new INTERNET_PER_CONN_OPTION[2];
|
||||
|
||||
// Ensure that the memory was allocated.
|
||||
if (nullptr == list.pOptions) {
|
||||
if (nullptr == list.pOptions)
|
||||
{
|
||||
// Return FALSE if the memory wasn't allocated.
|
||||
return FALSE;
|
||||
}
|
||||
@ -137,13 +155,16 @@ namespace Qv2ray::components::proxy
|
||||
// Set proxy name.
|
||||
list.pOptions[1].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL;
|
||||
list.pOptions[1].Value.pszValue = proxy_full_addr;
|
||||
} else {
|
||||
LOG(PROXY, "Setting system proxy for Global Proxy")
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(MODULE_PROXY, "Setting system proxy for Global Proxy")
|
||||
//
|
||||
list.dwOptionCount = 3;
|
||||
list.pOptions = new INTERNET_PER_CONN_OPTION[3];
|
||||
|
||||
if (nullptr == list.pOptions) {
|
||||
if (nullptr == list.pOptions)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -161,7 +182,7 @@ namespace Qv2ray::components::proxy
|
||||
|
||||
// Set the options on the connection.
|
||||
bReturn = InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize);
|
||||
delete [] list.pOptions;
|
||||
delete[] list.pOptions;
|
||||
InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0);
|
||||
InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0);
|
||||
return bReturn;
|
||||
@ -170,43 +191,54 @@ namespace Qv2ray::components::proxy
|
||||
|
||||
void SetSystemProxy(const QString &address, int httpPort, int socksPort, bool usePAC)
|
||||
{
|
||||
LOG(MODULE_PROXY, "Setting up System Proxy")
|
||||
bool hasHTTP = (httpPort != 0);
|
||||
bool hasSOCKS = (socksPort != 0);
|
||||
|
||||
if (!(hasHTTP || hasSOCKS || usePAC)) {
|
||||
LOG(PROXY, "Nothing?")
|
||||
if (!(hasHTTP || hasSOCKS || usePAC))
|
||||
{
|
||||
LOG(MODULE_PROXY, "Nothing?")
|
||||
return;
|
||||
}
|
||||
|
||||
if (usePAC) {
|
||||
LOG(PROXY, "Qv2ray will set system proxy to use PAC file")
|
||||
} else {
|
||||
if (hasHTTP) {
|
||||
LOG(PROXY, "Qv2ray will set system proxy to use HTTP")
|
||||
if (usePAC)
|
||||
{
|
||||
LOG(MODULE_PROXY, "Qv2ray will set system proxy to use PAC file")
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hasHTTP)
|
||||
{
|
||||
LOG(MODULE_PROXY, "Qv2ray will set system proxy to use HTTP")
|
||||
}
|
||||
|
||||
if (hasSOCKS) {
|
||||
LOG(PROXY, "Qv2ray will set system proxy to use SOCKS")
|
||||
if (hasSOCKS)
|
||||
{
|
||||
LOG(MODULE_PROXY, "Qv2ray will set system proxy to use SOCKS")
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
QString __a;
|
||||
|
||||
if (usePAC) {
|
||||
if (usePAC)
|
||||
{
|
||||
__a = address;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
__a = (hasHTTP ? "http://" : "socks5://") + address + ":" + QSTRN(httpPort);
|
||||
}
|
||||
|
||||
LOG(PROXY, "Windows proxy string: " + __a)
|
||||
LOG(MODULE_PROXY, "Windows proxy string: " + __a)
|
||||
auto proxyStrW = new WCHAR[__a.length() + 1];
|
||||
wcscpy(proxyStrW, __a.toStdWString().c_str());
|
||||
//
|
||||
__QueryProxyOptions();
|
||||
|
||||
if (!__SetProxyOptions(proxyStrW, usePAC)) {
|
||||
LOG(PROXY, "Failed to set proxy.")
|
||||
if (!__SetProxyOptions(proxyStrW, usePAC))
|
||||
{
|
||||
LOG(MODULE_PROXY, "Failed to set proxy.")
|
||||
}
|
||||
|
||||
__QueryProxyOptions();
|
||||
@ -214,54 +246,104 @@ namespace Qv2ray::components::proxy
|
||||
QStringList actions;
|
||||
auto proxyMode = usePAC ? "auto" : "manual";
|
||||
actions << QString("gsettings set org.gnome.system.proxy mode '%1'").arg(proxyMode);
|
||||
|
||||
if (usePAC) {
|
||||
bool isKDE = qEnvironmentVariable("XDG_SESSION_DESKTOP") == "KDE";
|
||||
if (isKDE)
|
||||
{
|
||||
LOG(MODULE_PROXY, "KDE detected")
|
||||
}
|
||||
//
|
||||
if (usePAC)
|
||||
{
|
||||
actions << QString("gsettings set org.gnome.system.proxy autoconfig-url '%1'").arg(address);
|
||||
} else {
|
||||
if (hasHTTP) {
|
||||
if (isKDE)
|
||||
{
|
||||
actions << QString("kwriteconfig5 --file " + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) +
|
||||
"/kioslaverc --group \"Proxy Settings\" --key ProxyType 2");
|
||||
|
||||
actions << QString("kwriteconfig5 --file " + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) +
|
||||
"/kioslaverc --group \"Proxy Settings\" --key \"Proxy Config Script\" " + address);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isKDE)
|
||||
{
|
||||
actions << QString("kwriteconfig5 --file " + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) +
|
||||
"/kioslaverc --group \"Proxy Settings\" --key ProxyType 1");
|
||||
}
|
||||
if (hasHTTP)
|
||||
{
|
||||
actions << QString("gsettings set org.gnome.system.proxy.http host '%1'").arg(address);
|
||||
actions << QString("gsettings set org.gnome.system.proxy.http port %1").arg(httpPort);
|
||||
//
|
||||
actions << QString("gsettings set org.gnome.system.proxy.https host '%1'").arg(address);
|
||||
actions << QString("gsettings set org.gnome.system.proxy.https port %1").arg(httpPort);;
|
||||
actions << QString("gsettings set org.gnome.system.proxy.https port %1").arg(httpPort);
|
||||
if (isKDE)
|
||||
{
|
||||
// FTP here should be scheme: ftp://
|
||||
for (auto protocol : { "http", "ftp", "https" })
|
||||
{
|
||||
auto str = QString("kwriteconfig5 --file " + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) +
|
||||
"/kioslaverc --group \"Proxy Settings\" --key %1Proxy \"http://%2 %3\"")
|
||||
.arg(protocol)
|
||||
.arg(address)
|
||||
.arg(QSTRN(httpPort));
|
||||
actions << str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasSOCKS) {
|
||||
if (hasSOCKS)
|
||||
{
|
||||
actions << QString("gsettings set org.gnome.system.proxy.socks host '%1'").arg(address);
|
||||
actions << QString("gsettings set org.gnome.system.proxy.socks port %1").arg(socksPort);
|
||||
if (isKDE)
|
||||
{
|
||||
actions << QString("kwriteconfig5 --file " + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) +
|
||||
"/kioslaverc --group \"Proxy Settings\" --key socksProxy \"socks://%1 %2\"")
|
||||
.arg(address)
|
||||
.arg(QSTRN(socksPort));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// note: do not use std::all_of / any_of / none_of,
|
||||
// because those are short-circuit and cannot guarantee atomicity.
|
||||
auto result = std::count_if(actions.cbegin(), actions.cend(), [](const QString & action) {
|
||||
DEBUG(PROXY, action)
|
||||
return QProcess::execute(action) == QProcess::NormalExit;
|
||||
}) == actions.size();
|
||||
auto result = std::count_if(actions.cbegin(), actions.cend(), [](const QString &action) {
|
||||
DEBUG(MODULE_PROXY, action)
|
||||
return QProcess::execute(action) == QProcess::NormalExit;
|
||||
}) == actions.size();
|
||||
|
||||
if (!result) {
|
||||
LOG(PROXY, "Something wrong happens when setting system proxy -> Gnome ONLY.")
|
||||
LOG(PROXY, "If you are using KDE Plasma and receiving this message, just simply ignore this.")
|
||||
if (!result)
|
||||
{
|
||||
LOG(MODULE_PROXY, "There was something wrong when setting proxies.")
|
||||
LOG(MODULE_PROXY, "It may happen if you are using KDE with no gsettings support.")
|
||||
}
|
||||
|
||||
Q_UNUSED(result);
|
||||
#else
|
||||
|
||||
for (auto service : macOSgetNetworkServices()) {
|
||||
LOG(PROXY, "Setting proxy for interface: " + service)
|
||||
for (auto service : macOSgetNetworkServices())
|
||||
{
|
||||
LOG(MODULE_PROXY, "Setting proxy for interface: " + service)
|
||||
|
||||
if (usePAC) {
|
||||
if (usePAC)
|
||||
{
|
||||
QProcess::execute("/usr/sbin/networksetup -setautoproxystate " + service + " on");
|
||||
QProcess::execute("/usr/sbin/networksetup -setautoproxyurl " + service + " " + address);
|
||||
} else {
|
||||
if (hasHTTP) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hasHTTP)
|
||||
{
|
||||
QProcess::execute("/usr/sbin/networksetup -setwebproxystate " + service + " on");
|
||||
QProcess::execute("/usr/sbin/networksetup -setsecurewebproxystate " + service + " on");
|
||||
QProcess::execute("/usr/sbin/networksetup -setwebproxy " + service + " " + address + " " + QSTRN(httpPort));
|
||||
QProcess::execute("/usr/sbin/networksetup -setsecurewebproxy " + service + " " + address + " " + QSTRN(httpPort));
|
||||
}
|
||||
|
||||
if (hasSOCKS) {
|
||||
if (hasSOCKS)
|
||||
{
|
||||
QProcess::execute("/usr/sbin/networksetup -setsocksfirewallproxystate " + service + " on");
|
||||
QProcess::execute("/usr/sbin/networksetup -setsocksfirewallproxy " + service + " " + address + " " + QSTRN(socksPort));
|
||||
}
|
||||
@ -273,8 +355,9 @@ namespace Qv2ray::components::proxy
|
||||
|
||||
void ClearSystemProxy()
|
||||
{
|
||||
LOG(MODULE_PROXY, "Clearing System Proxy")
|
||||
#ifdef Q_OS_WIN
|
||||
LOG(PROXY, "Cleaning system proxy settings.")
|
||||
LOG(MODULE_PROXY, "Cleaning system proxy settings.")
|
||||
INTERNET_PER_CONN_OPTION_LIST list;
|
||||
BOOL bReturn;
|
||||
DWORD dwBufSize = sizeof(list);
|
||||
@ -287,9 +370,10 @@ namespace Qv2ray::components::proxy
|
||||
list.pOptions = new INTERNET_PER_CONN_OPTION[list.dwOptionCount];
|
||||
|
||||
// Make sure the memory was allocated.
|
||||
if (nullptr == list.pOptions) {
|
||||
if (nullptr == list.pOptions)
|
||||
{
|
||||
// Return FALSE if the memory wasn't allocated.
|
||||
LOG(PROXY, "Failed to allocat memory in DisableConnectionProxy()")
|
||||
LOG(MODULE_PROXY, "Failed to allocat memory in DisableConnectionProxy()")
|
||||
}
|
||||
|
||||
// Set flags.
|
||||
@ -298,15 +382,21 @@ namespace Qv2ray::components::proxy
|
||||
//
|
||||
// Set the options on the connection.
|
||||
bReturn = InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize);
|
||||
delete [] list.pOptions;
|
||||
delete[] list.pOptions;
|
||||
InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0);
|
||||
InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0);
|
||||
#elif defined(Q_OS_LINUX)
|
||||
if (qEnvironmentVariable("XDG_SESSION_DESKTOP") == "KDE")
|
||||
{
|
||||
QProcess::execute("kwriteconfig5 --file " + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) +
|
||||
"/kioslaverc --group \"Proxy Settings\" --key ProxyType 0");
|
||||
}
|
||||
QProcess::execute("gsettings set org.gnome.system.proxy mode 'none'");
|
||||
#else
|
||||
|
||||
for (auto service : macOSgetNetworkServices()) {
|
||||
LOG(PROXY, "Clearing proxy for interface: " + service)
|
||||
for (auto service : macOSgetNetworkServices())
|
||||
{
|
||||
LOG(MODULE_PROXY, "Clearing proxy for interface: " + service)
|
||||
QProcess::execute("/usr/sbin/networksetup -setautoproxystate " + service + " off");
|
||||
QProcess::execute("/usr/sbin/networksetup -setwebproxystate " + service + " off");
|
||||
QProcess::execute("/usr/sbin/networksetup -setsecurewebproxystate " + service + " off");
|
||||
@ -315,4 +405,4 @@ namespace Qv2ray::components::proxy
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // namespace Qv2ray::components::proxy
|
||||
|
@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
//
|
||||
namespace Qv2ray::components::proxy
|
||||
{
|
||||
void ClearSystemProxy();
|
||||
void SetSystemProxy(const QString &address, int http_port, int socks_port, bool usePAC);
|
||||
}
|
||||
} // namespace Qv2ray::components::proxy
|
||||
|
||||
using namespace Qv2ray::components;
|
||||
using namespace Qv2ray::components::proxy;
|
||||
|
@ -14,39 +14,40 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
* License in all respects for all of the code used other than "OpenSSL". If
|
||||
* you modify file(s), you may extend this exception to your version of the
|
||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
||||
* delete this exception statement from your version.
|
||||
*/
|
||||
|
||||
#include "speedplotview.hpp"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QLocale>
|
||||
#include <QPainter>
|
||||
#include <QPen>
|
||||
#include <list>
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
#define VIEWABLE 60
|
||||
#define VIEWABLE 120
|
||||
|
||||
// use binary prefix standards from IEC 60027-2
|
||||
// see http://en.wikipedia.org/wiki/Kilobyte
|
||||
enum class SizeUnit {
|
||||
Byte, // 1024^0,
|
||||
KibiByte, // 1024^1,
|
||||
MebiByte, // 1024^2,
|
||||
GibiByte, // 1024^3,
|
||||
TebiByte, // 1024^4,
|
||||
PebiByte, // 1024^5,
|
||||
ExbiByte // 1024^6,
|
||||
enum class SizeUnit
|
||||
{
|
||||
Byte, // 1024^0,
|
||||
KibiByte, // 1024^1,
|
||||
MebiByte, // 1024^2,
|
||||
GibiByte, // 1024^3,
|
||||
TebiByte, // 1024^4,
|
||||
PebiByte, // 1024^5,
|
||||
ExbiByte // 1024^6,
|
||||
// int64 is used for sizes and thus the next units can not be handled
|
||||
// ZebiByte, // 1024^7,
|
||||
// YobiByte, // 1024^8
|
||||
@ -54,19 +55,18 @@ enum class SizeUnit {
|
||||
|
||||
namespace
|
||||
{
|
||||
const struct {
|
||||
const struct
|
||||
{
|
||||
const char *source;
|
||||
const char *comment;
|
||||
} units[] = {
|
||||
QT_TRANSLATE_NOOP3("misc", "B", "bytes"),
|
||||
QT_TRANSLATE_NOOP3("misc", "KiB", "kibibytes (1024 bytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "MiB", "mebibytes (1024 kibibytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "GiB", "gibibytes (1024 mibibytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "TiB", "tebibytes (1024 gibibytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "PiB", "pebibytes (1024 tebibytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "EiB", "exbibytes (1024 pebibytes)")
|
||||
};
|
||||
}
|
||||
} units[] = { QT_TRANSLATE_NOOP3("misc", "B", "bytes"),
|
||||
QT_TRANSLATE_NOOP3("misc", "KiB", "kibibytes (1024 bytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "MiB", "mebibytes (1024 kibibytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "GiB", "gibibytes (1024 mibibytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "TiB", "tebibytes (1024 gibibytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "PiB", "pebibytes (1024 tebibytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "EiB", "exbibytes (1024 pebibytes)") };
|
||||
} // namespace
|
||||
|
||||
QString unitString(const SizeUnit unit, const bool isSpeed)
|
||||
{
|
||||
@ -82,53 +82,34 @@ QString unitString(const SizeUnit unit, const bool isSpeed)
|
||||
int friendlyUnitPrecision(const SizeUnit unit)
|
||||
{
|
||||
// friendlyUnit's number of digits after the decimal point
|
||||
switch (unit) {
|
||||
case SizeUnit::Byte:
|
||||
return 0;
|
||||
switch (unit)
|
||||
{
|
||||
case SizeUnit::Byte: return 0;
|
||||
|
||||
case SizeUnit::KibiByte:
|
||||
case SizeUnit::MebiByte:
|
||||
return 1;
|
||||
case SizeUnit::MebiByte: return 1;
|
||||
|
||||
case SizeUnit::GibiByte:
|
||||
return 2;
|
||||
case SizeUnit::GibiByte: return 2;
|
||||
|
||||
default:
|
||||
return 3;
|
||||
default: return 3;
|
||||
}
|
||||
}
|
||||
|
||||
qlonglong sizeInBytes(qreal size, const SizeUnit unit)
|
||||
{
|
||||
for (int i = 0; i < static_cast<int>(unit); ++i)
|
||||
size *= 1024;
|
||||
for (int i = 0; i < static_cast<int>(unit); ++i) size *= 1024;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr typename std::add_const<T>::type &asConst(T &t) noexcept
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
// Forward rvalue as const
|
||||
template <typename T>
|
||||
constexpr typename std::add_const<T>::type asConst(T &&t) noexcept
|
||||
{
|
||||
return std::move(t);
|
||||
}
|
||||
|
||||
// Prevent const rvalue arguments
|
||||
template <typename T>
|
||||
void asConst(const T &&) = delete;
|
||||
|
||||
namespace
|
||||
{
|
||||
// table of supposed nice steps for grid marks to get nice looking quarters of scale
|
||||
const double roundingTable[] = {1.2, 1.6, 2, 2.4, 2.8, 3.2, 4, 6, 8};
|
||||
// table of supposed nice steps for grid marks to get nice looking quarters
|
||||
// of scale
|
||||
const double roundingTable[] = { 1.2, 1.6, 2, 2.4, 2.8, 3.2, 4, 6, 8 };
|
||||
|
||||
struct SplittedValue {
|
||||
struct SplittedValue
|
||||
{
|
||||
double arg;
|
||||
SizeUnit unit;
|
||||
qint64 sizeInBytes() const
|
||||
@ -139,56 +120,56 @@ namespace
|
||||
|
||||
SplittedValue getRoundedYScale(double value)
|
||||
{
|
||||
if (value == 0.0) return {0, SizeUnit::Byte};
|
||||
if (value == 0.0)
|
||||
return { 0, SizeUnit::Byte };
|
||||
|
||||
if (value <= 12.0) return {12, SizeUnit::Byte};
|
||||
if (value <= 12.0)
|
||||
return { 12, SizeUnit::Byte };
|
||||
|
||||
SizeUnit calculatedUnit = SizeUnit::Byte;
|
||||
|
||||
while (value > 1024) {
|
||||
while (value > 1024)
|
||||
{
|
||||
value /= 1024;
|
||||
calculatedUnit = static_cast<SizeUnit>(static_cast<int>(calculatedUnit) + 1);
|
||||
}
|
||||
|
||||
if (value > 100.0) {
|
||||
if (value > 100.0)
|
||||
{
|
||||
int roundedValue = static_cast<int>(value / 40) * 40;
|
||||
|
||||
while (roundedValue < value)
|
||||
roundedValue += 40;
|
||||
while (roundedValue < value) roundedValue += 40;
|
||||
|
||||
return {static_cast<double>(roundedValue), calculatedUnit};
|
||||
return { static_cast<double>(roundedValue), calculatedUnit };
|
||||
}
|
||||
|
||||
if (value > 10.0) {
|
||||
if (value > 10.0)
|
||||
{
|
||||
int roundedValue = static_cast<int>(value / 4) * 4;
|
||||
|
||||
while (roundedValue < value)
|
||||
roundedValue += 4;
|
||||
while (roundedValue < value) roundedValue += 4;
|
||||
|
||||
return {static_cast<double>(roundedValue), calculatedUnit};
|
||||
return { static_cast<double>(roundedValue), calculatedUnit };
|
||||
}
|
||||
|
||||
for (const auto &roundedValue : roundingTable) {
|
||||
for (const auto &roundedValue : roundingTable)
|
||||
{
|
||||
if (value <= roundedValue)
|
||||
return {roundedValue, calculatedUnit};
|
||||
return { roundedValue, calculatedUnit };
|
||||
}
|
||||
|
||||
return {10.0, calculatedUnit};
|
||||
return { 10.0, calculatedUnit };
|
||||
}
|
||||
|
||||
QString formatLabel(const double argValue, const SizeUnit unit)
|
||||
{
|
||||
// check is there need for digits after decimal separator
|
||||
const int precision = (argValue < 10) ? friendlyUnitPrecision(unit) : 0;
|
||||
return QLocale::system().toString(argValue, 'f', precision)
|
||||
+ QString::fromUtf8(" ")
|
||||
+ unitString(unit, true);
|
||||
return QLocale::system().toString(argValue, 'f', precision) + QString::fromUtf8(" ") + unitString(unit, true);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SpeedPlotView::SpeedPlotView(QWidget *parent)
|
||||
: QGraphicsView(parent)
|
||||
, m_currentData(&m_datahalfMin)
|
||||
SpeedPlotView::SpeedPlotView(QWidget *parent) : QGraphicsView(parent), m_currentData(&m_datahalfMin)
|
||||
{
|
||||
QPen greenPen;
|
||||
greenPen.setWidthF(1.5);
|
||||
@ -210,7 +191,8 @@ void SpeedPlotView::pushPoint(const SpeedPlotView::PointData &point)
|
||||
{
|
||||
m_datahalfMin.push_back(point);
|
||||
|
||||
while (m_datahalfMin.length() > VIEWABLE) {
|
||||
while (m_datahalfMin.length() > VIEWABLE)
|
||||
{
|
||||
m_datahalfMin.removeFirst();
|
||||
}
|
||||
}
|
||||
@ -230,9 +212,11 @@ quint64 SpeedPlotView::maxYValue()
|
||||
auto &queue = getCurrentData();
|
||||
quint64 maxYValue = 0;
|
||||
|
||||
for (int id = UP; id < NB_GRAPHS; ++id) {
|
||||
for (int id = UP; id < NB_GRAPHS; ++id)
|
||||
{
|
||||
// 30 is half min
|
||||
for (int i = queue.size() - 1, j = 0; (i >= 0) && (j <= VIEWABLE); --i, ++j) {
|
||||
for (int i = queue.size() - 1, j = 0; (i >= 0) && (j <= VIEWABLE); --i, ++j)
|
||||
{
|
||||
if (queue[i].y[id] > maxYValue)
|
||||
maxYValue = queue[i].y[id];
|
||||
}
|
||||
@ -266,7 +250,8 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (const QString &label : speedLabels) {
|
||||
for (const QString &label : speedLabels)
|
||||
{
|
||||
QRectF labelRect(rect.topLeft() + QPointF(-yAxisWidth, (i++) * 0.25 * rect.height() - fontMetrics.height()),
|
||||
QSizeF(2 * yAxisWidth, fontMetrics.height()));
|
||||
painter.drawText(labelRect, label, Qt::AlignRight | Qt::AlignTop);
|
||||
@ -286,7 +271,8 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
|
||||
painter.drawLine(fullRect.left(), rect.bottom(), rect.right(), rect.bottom());
|
||||
const int TIME_AXIS_DIVISIONS = 6;
|
||||
|
||||
for (int i = 0; i < TIME_AXIS_DIVISIONS; ++i) {
|
||||
for (int i = 0; i < TIME_AXIS_DIVISIONS; ++i)
|
||||
{
|
||||
const int x = rect.left() + (i * rect.width()) / TIME_AXIS_DIVISIONS;
|
||||
painter.drawLine(x, fullRect.top(), x, fullRect.bottom());
|
||||
}
|
||||
@ -299,10 +285,12 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
|
||||
const double xTickSize = static_cast<double>(rect.width()) / VIEWABLE;
|
||||
auto &queue = getCurrentData();
|
||||
|
||||
for (int id = UP; id < NB_GRAPHS; ++id) {
|
||||
for (int id = UP; id < NB_GRAPHS; ++id)
|
||||
{
|
||||
QVector<QPoint> points;
|
||||
|
||||
for (int i = static_cast<int>(queue.size()) - 1, j = 0; (i >= 0) && (j <= VIEWABLE); --i, ++j) {
|
||||
for (int i = static_cast<int>(queue.size()) - 1, j = 0; (i >= 0) && (j <= VIEWABLE); --i, ++j)
|
||||
{
|
||||
int newX = rect.right() - j * xTickSize;
|
||||
int newY = rect.bottom() - queue[i].y[id] * yMultiplier;
|
||||
points.push_back(QPoint(newX, newY));
|
||||
@ -317,7 +305,8 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
|
||||
double legendHeight = 0;
|
||||
int legendWidth = 0;
|
||||
|
||||
for (const auto &property : asConst(m_properties)) {
|
||||
for (const auto &property : m_properties)
|
||||
{
|
||||
if (fontMetrics.horizontalAdvance(property.name) > legendWidth)
|
||||
legendWidth = fontMetrics.horizontalAdvance(property.name);
|
||||
|
||||
@ -326,18 +315,19 @@ void SpeedPlotView::paintEvent(QPaintEvent *)
|
||||
|
||||
QRectF legendBackgroundRect(QPoint(legendTopLeft.x() - 4, legendTopLeft.y() - 4), QSizeF(legendWidth + 8, legendHeight + 8));
|
||||
QColor legendBackgroundColor = QWidget::palette().color(QWidget::backgroundRole());
|
||||
legendBackgroundColor.setAlpha(128); // 50% transparent
|
||||
legendBackgroundColor.setAlpha(128); // 50% transparent
|
||||
painter.fillRect(legendBackgroundRect, legendBackgroundColor);
|
||||
i = 0;
|
||||
|
||||
for (const auto &property : asConst(m_properties)) {
|
||||
for (const auto &property : m_properties)
|
||||
{
|
||||
int nameSize = fontMetrics.horizontalAdvance(property.name);
|
||||
double indent = 1.5 * (i++) * fontMetrics.height();
|
||||
painter.setPen(property.pen);
|
||||
painter.drawLine(legendTopLeft + QPointF(0, indent + fontMetrics.height()),
|
||||
legendTopLeft + QPointF(nameSize, indent + fontMetrics.height()));
|
||||
painter.drawText(QRectF(legendTopLeft + QPointF(0, indent), QSizeF(2 * nameSize, fontMetrics.height())),
|
||||
property.name, QTextOption(Qt::AlignVCenter));
|
||||
painter.drawText(QRectF(legendTopLeft + QPointF(0, indent), QSizeF(2 * nameSize, fontMetrics.height())), property.name,
|
||||
QTextOption(Qt::AlignVCenter));
|
||||
}
|
||||
}
|
||||
|
||||
@ -345,8 +335,6 @@ SpeedPlotView::GraphProperties::GraphProperties()
|
||||
{
|
||||
}
|
||||
|
||||
SpeedPlotView::GraphProperties::GraphProperties(const QString &name, const QPen &pen)
|
||||
: name(name)
|
||||
, pen(pen)
|
||||
SpeedPlotView::GraphProperties::GraphProperties(const QString &name, const QPen &pen) : name(name), pen(pen)
|
||||
{
|
||||
}
|
||||
|
@ -36,43 +36,46 @@ class QPen;
|
||||
|
||||
class SpeedPlotView : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum GraphID {
|
||||
UP = 0,
|
||||
DOWN,
|
||||
NB_GRAPHS
|
||||
};
|
||||
public:
|
||||
enum GraphID
|
||||
{
|
||||
UP = 0,
|
||||
DOWN,
|
||||
NB_GRAPHS
|
||||
};
|
||||
|
||||
struct PointData {
|
||||
qint64 x;
|
||||
quint64 y[NB_GRAPHS];
|
||||
};
|
||||
struct PointData
|
||||
{
|
||||
qint64 x;
|
||||
quint64 y[NB_GRAPHS];
|
||||
};
|
||||
|
||||
explicit SpeedPlotView(QWidget *parent = nullptr);
|
||||
void pushPoint(const PointData &point);
|
||||
void Clear();
|
||||
void replot();
|
||||
explicit SpeedPlotView(QWidget *parent = nullptr);
|
||||
void pushPoint(const PointData &point);
|
||||
void Clear();
|
||||
void replot();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
struct GraphProperties {
|
||||
GraphProperties();
|
||||
GraphProperties(const QString &name, const QPen &pen);
|
||||
private:
|
||||
struct GraphProperties
|
||||
{
|
||||
GraphProperties();
|
||||
GraphProperties(const QString &name, const QPen &pen);
|
||||
|
||||
QString name;
|
||||
QPen pen;
|
||||
};
|
||||
QString name;
|
||||
QPen pen;
|
||||
};
|
||||
|
||||
quint64 maxYValue();
|
||||
QList<PointData> &getCurrentData();
|
||||
QList<PointData> m_datahalfMin;
|
||||
QList<PointData> *m_currentData;
|
||||
quint64 maxYValue();
|
||||
QList<PointData> &getCurrentData();
|
||||
QList<PointData> m_datahalfMin;
|
||||
QList<PointData> *m_currentData;
|
||||
|
||||
QMap<GraphID, GraphProperties> m_properties;
|
||||
QMap<GraphID, GraphProperties> m_properties;
|
||||
};
|
||||
|
||||
#endif // SPEEDPLOTVIEW_H
|
||||
|