Merge pull request #415 from Qv2ray/dev

[WIP] Qv2ray v2.2 testing
This commit is contained in:
Qv2ray-dev 2020-03-13 20:36:28 +08:00 committed by GitHub
commit 0638060ed0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
186 changed files with 20333 additions and 10563 deletions

View File

@ -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 * * *"

View File

@ -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

View File

@ -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
View File

@ -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
View File

@ -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/

View File

@ -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

@ -1 +1 @@
Subproject commit 0f368335943cc8b84a8b52c5ad7cfd9c25ebb6d6
Subproject commit c93f1c1826d46d5d60f118688cd830b39af8b9c6

@ -1 +1 @@
Subproject commit 0f6695e2a9d8fdaa336e7ad941855c46c61f218a
Subproject commit 4abe20afbfa5695ac7a9bce1298943b645aeffe9

1
3rdparty/cpp-httplib vendored Submodule

@ -0,0 +1 @@
Subproject commit 26deffe0c6a1e177e393416b94cdc0f340ca79bd

@ -1 +0,0 @@
Subproject commit 02a6e7174b5be76e2c0e74a109817e39a141b9fd

2
3rdparty/qzxing vendored

@ -1 +1 @@
Subproject commit ee50acba1f10e70ef23c593971621ed7a9f4c5a1
Subproject commit dac9480a652d591c41ec9ef6f6c966c59a252142

382
CMakeLists.txt Normal file
View 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()

View File

@ -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 padparen,
# padparenout, padparenin, and padheader 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 padparenin to retain the inside padding. Using only
# padparenin 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

View File

@ -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
View 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
...

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View 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

View 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

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View 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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

26
assets/info.plist Normal file
View 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
View 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
View 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
View File

@ -0,0 +1 @@
set(cpp-httplib_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/3rdparty/cpp-httplib)

23
cmake/deployment.cmake Normal file
View 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
View 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
View 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
View 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()

View 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
View 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

View File

@ -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/

View File

@ -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)
}

View File

@ -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.")
}

View File

@ -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

View File

@ -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")
}
}

View File

@ -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

View File

@ -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

View File

@ -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_}\\\"\"

View File

@ -1 +1 @@
3861
4685

294
qv2ray-config-models.qmodel Normal file
View 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&lt;ConnectionId&gt;</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

File diff suppressed because it is too large Load Diff

2187
qv2ray.qmodel Normal file

File diff suppressed because it is too large Load Diff

View 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
View 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

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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";

View File

@ -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

View File

@ -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;

View File

@ -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))
};
}
}

View File

@ -5,8 +5,9 @@
namespace Qv2ray::base
{
struct Qv2rayRuntimeConfig {
//
struct Qv2rayRuntimeConfig
{
bool screenShotHideQv2ray = false;
};
}
inline base::Qv2rayRuntimeConfig RuntimeConfig = base::Qv2rayRuntimeConfig();
} // namespace Qv2ray::base

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View 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

View 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;

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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

View File

@ -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;

View 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

View File

@ -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

View File

@ -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

View File

@ -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;

View 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

View File

@ -0,0 +1,6 @@
#pragma once
namespace Qv2ray::components::darkmode
{
bool isDarkMode();
}

View File

@ -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

View 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

View 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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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)
{
}

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More