3
.github/workflows/build-qv2ray-cmake.yml
vendored
@ -112,14 +112,13 @@ jobs:
|
||||
- uses: actions/setup-node@v1
|
||||
if: matrix.platform == 'macos-latest'
|
||||
with:
|
||||
node-version: '10.x'
|
||||
node-version: '12.x'
|
||||
- run: npm install -g appdmg
|
||||
if: matrix.platform == 'macos-latest'
|
||||
- name: macOS - ${{ matrix.qt_version }} - Generate Dependencies and Build
|
||||
shell: bash
|
||||
if: matrix.platform == 'macos-latest'
|
||||
run: |
|
||||
sudo xcode-select -s "/Applications/Xcode_10.3.app"
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DDS_STORE_SCRIPT=ON
|
||||
|
5
.gitmodules
vendored
@ -12,10 +12,7 @@
|
||||
url = https://github.com/nu-book/zxing-cpp
|
||||
[submodule "src/plugin-interface"]
|
||||
path = src/plugin-interface
|
||||
url = https://github.com/Qv2ray/QvPlugin-Interface/
|
||||
url = https://github.com/Qv2ray/QvPlugin-Interface
|
||||
[submodule "libs/QJsonStruct"]
|
||||
path = libs/QJsonStruct
|
||||
url = https://github.com/Qv2ray/QJsonStruct
|
||||
[submodule "3rdparty/uistyles"]
|
||||
path = 3rdparty/uistyles
|
||||
url = https://github.com/Qv2ray/QvUIStyles
|
||||
|
2
3rdparty/SingleApplication
vendored
@ -1 +1 @@
|
||||
Subproject commit bae7c331ca7203a242e4533ba859c0c6016521ba
|
||||
Subproject commit e93c12ab69a25fcaa963416f0e348d3269263190
|
1
3rdparty/uistyles
vendored
@ -1 +0,0 @@
|
||||
Subproject commit ccbc5a7ec83229e18804bf6b650b181f5279ca74
|
2
3rdparty/zxing-cpp
vendored
@ -1 +1 @@
|
||||
Subproject commit 6d40262e7293666909f7325075d452637f2fca75
|
||||
Subproject commit 5351b67eac63c7e544274abf5b15b55c7716a6cf
|
@ -108,6 +108,7 @@ set(QV2RAY_DISABLE_AUTO_UPDATE OFF CACHE BOOL "Disable update checker")
|
||||
set(BUILD_TESTING OFF CACHE BOOL "Build test")
|
||||
set(EMBED_TRANSLATIONS OFF CACHE BOOL "Embed translations")
|
||||
set(QV2RAY_AUTO_DEPLOY ON CACHE BOOL "Automatically run deploy command after build")
|
||||
set(QV2RAY_HAS_BUILT_IN_THEMES ON CACHE BOOL "Build with built-in themes")
|
||||
|
||||
if(QV2RAY_DEFAULT_VASSETS_PATH AND NOT QV2RAY_DEFAULT_VASSETS_PATH STREQUAL "unset")
|
||||
add_definitions(-DQV2RAY_DEFAULT_VASSETS_PATH="${QV2RAY_DEFAULT_VASSETS_PATH}")
|
||||
@ -191,7 +192,10 @@ include(src/plugin-interface/QvPluginInterface.cmake)
|
||||
# ==================================================================================
|
||||
include(cmake/components/qv2ray-lib.cmake)
|
||||
include(cmake/components/qv2ray-ui.cmake)
|
||||
include(3rdparty/uistyles/uistyles.cmake)
|
||||
|
||||
if (QV2RAY_HAS_BUILT_IN_THEMES)
|
||||
include(libs/uistyles/uistyles.cmake)
|
||||
endif()
|
||||
|
||||
set(QRC_RESOURCES
|
||||
${UISTYLE_QRCS}
|
||||
|
@ -19,7 +19,6 @@ steps:
|
||||
inputs:
|
||||
versionSpec: '12.x'
|
||||
- script: |
|
||||
sudo xcode-select -s /Applications/Xcode_10.3.app
|
||||
brew install protobuf grpc ninja qt5 pkg-config
|
||||
npm install -g appdmg
|
||||
displayName: Prepare dependencies
|
||||
@ -47,4 +46,4 @@ steps:
|
||||
action: edit
|
||||
tag: '$(Build.SourceBranchName)'
|
||||
isPreRelease: true
|
||||
addChangeLog: false
|
||||
addChangeLog: false
|
||||
|
@ -98,8 +98,8 @@ set(QV2RAY_LIB_SOURCES
|
||||
${CMAKE_SOURCE_DIR}/src/core/kernel/PluginKernelInteractions.hpp
|
||||
${CMAKE_SOURCE_DIR}/src/core/kernel/QvKernelABIChecker.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/core/kernel/QvKernelABIChecker.hpp
|
||||
${CMAKE_SOURCE_DIR}/src/core/kernel/V2rayKernelInteractions.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/core/kernel/V2rayKernelInteractions.hpp
|
||||
${CMAKE_SOURCE_DIR}/src/core/kernel/V2RayKernelInteractions.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/core/kernel/V2RayKernelInteractions.hpp
|
||||
#
|
||||
${CMAKE_SOURCE_DIR}/src/core/settings/SettingsBackend.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/core/settings/SettingsBackend.hpp
|
||||
|
9
debian/changelog
vendored
@ -1,3 +1,12 @@
|
||||
qv2ray (2.6.1-1) unstable; urgency=medium
|
||||
|
||||
* fix: should not edit GroupManager tablewidget
|
||||
* fix: fixed connection import/export with unwanted content (Closes #771)
|
||||
* fix: fixed V2RAY_LOCATION_ASSET env name (Closes #768)
|
||||
* fix: QR code file cannot be imported
|
||||
|
||||
-- Guobang Bi <ymshenyu@gmail.com> Mon, 13 Jul 2020 09:37:27 +0800
|
||||
|
||||
qv2ray (2.6.0-1) unstable; urgency=medium
|
||||
|
||||
* New Release 2.6.0
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit bd4f9335bb89e7b1199282c685d49dd5ae4ce1fa
|
||||
Subproject commit 39d0644bd3d9348f8482d3f5375a9196a54a4348
|
121
libs/uistyles/LICENSE.mulan
Normal file
@ -0,0 +1,121 @@
|
||||
木兰宽松许可证, 第1版
|
||||
|
||||
木兰宽松许可证, 第1版
|
||||
2019年8月 http://license.coscl.org.cn/MulanPSL
|
||||
|
||||
您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第1版(“本许可证”)的如下条款的约束:
|
||||
|
||||
0. 定义
|
||||
|
||||
“软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。
|
||||
|
||||
“贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。
|
||||
|
||||
“法人实体”是指提交贡献的机构及其“关联实体”。
|
||||
|
||||
“关联实体”是指,对“本许可证”下的一方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。
|
||||
|
||||
“贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。
|
||||
|
||||
1. 授予版权许可
|
||||
|
||||
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。
|
||||
|
||||
2. 授予专利许可
|
||||
|
||||
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括仅因您或他人修改“贡献”或其他结合而将必然会侵犯到的专利权利要求。如您或您的“关联实体”直接或间接地(包括通过代理、专利被许可人或受让人),就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。
|
||||
|
||||
3. 无商标许可
|
||||
|
||||
“本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。
|
||||
|
||||
4. 分发限制
|
||||
|
||||
您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。
|
||||
|
||||
5. 免责声明与责任限制
|
||||
|
||||
“软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。
|
||||
|
||||
条款结束。
|
||||
|
||||
如何将木兰宽松许可证,第1版,应用到您的软件
|
||||
|
||||
如果您希望将木兰宽松许可证,第1版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步:
|
||||
|
||||
1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字;
|
||||
|
||||
2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中;
|
||||
|
||||
3, 请将如下声明文本放入每个源文件的头部注释中。
|
||||
|
||||
Copyright (c) [2019] [name of copyright holder]
|
||||
[Software Name] is licensed under the Mulan PSL v1.
|
||||
You can use this software according to the terms and conditions of the Mulan PSL v1.
|
||||
You may obtain a copy of Mulan PSL v1 at:
|
||||
http://license.coscl.org.cn/MulanPSL
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
|
||||
PURPOSE.
|
||||
See the Mulan PSL v1 for more details.
|
||||
|
||||
|
||||
Mulan Permissive Software License,Version 1
|
||||
|
||||
Mulan Permissive Software License,Version 1 (Mulan PSL v1)
|
||||
August 2019 http://license.coscl.org.cn/MulanPSL
|
||||
|
||||
Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v1 (this License) with following terms and conditions:
|
||||
|
||||
0. Definition
|
||||
|
||||
Software means the program and related documents which are comprised of those Contribution and licensed under this License.
|
||||
|
||||
Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License.
|
||||
|
||||
Legal Entity means the entity making a Contribution and all its Affiliates.
|
||||
|
||||
Affiliates means entities that control, or are controlled by, or are under common control with a party to this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity.
|
||||
|
||||
Contribution means the copyrightable work licensed by a particular Contributor under this License.
|
||||
|
||||
1. Grant of Copyright License
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not.
|
||||
|
||||
2. Grant of Patent License
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed, excluding of any patent claims solely be infringed by your or others’ modification or other combinations. If you or your Affiliates directly or indirectly (including through an agent, patent licensee or assignee), institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken.
|
||||
|
||||
3. No Trademark License
|
||||
|
||||
No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in section 4.
|
||||
|
||||
4. Distribution Restriction
|
||||
|
||||
You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software.
|
||||
|
||||
5. Disclaimer of Warranty and Limitation of Liability
|
||||
|
||||
The Software and Contribution in it are provided without warranties of any kind, either express or implied. In no event shall any Contributor or copyright holder be liable to you for any damages, including, but not limited to any direct, or indirect, special or consequential damages arising from your use or inability to use the Software or the Contribution in it, no matter how it’s caused or based on which legal theory, even if advised of the possibility of such damages.
|
||||
|
||||
End of the Terms and Conditions
|
||||
|
||||
How to apply the Mulan Permissive Software License,Version 1 (Mulan PSL v1) to your software
|
||||
|
||||
To apply the Mulan PSL v1 to your work, for easy identification by recipients, you are suggested to complete following three steps:
|
||||
|
||||
i. Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner;
|
||||
ii. Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package;
|
||||
iii. Attach the statement to the appropriate annotated syntax at the beginning of each source file.
|
||||
|
||||
Copyright (c) [2019] [name of copyright holder]
|
||||
[Software Name] is licensed under the Mulan PSL v1.
|
||||
You can use this software according to the terms and conditions of the Mulan PSL v1.
|
||||
You may obtain a copy of Mulan PSL v1 at:
|
||||
http://license.coscl.org.cn/MulanPSL
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
|
||||
PURPOSE.
|
||||
|
||||
See the Mulan PSL v1 for more details.
|
846
libs/uistyles/flatwhite/flatwhite.css
Normal file
@ -0,0 +1,846 @@
|
||||
QPalette,
|
||||
QWidget {
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
* {
|
||||
outline: 0px;
|
||||
color: #57595B;
|
||||
}
|
||||
|
||||
QWidget[form="true"],
|
||||
QLabel[frameShape="1"] {
|
||||
border: 1px solid #B6B6B6;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
QWidget[form="bottom"] {
|
||||
background: #E4E4E4;
|
||||
}
|
||||
|
||||
QWidget[form="bottom"] .QFrame {
|
||||
border: 1px solid #57595B;
|
||||
}
|
||||
|
||||
QWidget[form="bottom"] QLabel,
|
||||
QWidget[form="title"] QLabel {
|
||||
border-radius: 0px;
|
||||
color: #57595B;
|
||||
background: none;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
QWidget[form="title"],
|
||||
QWidget[nav="left"],
|
||||
QWidget[nav="top"] QAbstractButton {
|
||||
border-style: none;
|
||||
border-radius: 0px;
|
||||
padding: 5px;
|
||||
color: #57595B;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E4E4E4, stop: 1 #E4E4E4);
|
||||
}
|
||||
|
||||
QWidget[nav="top"] QAbstractButton:hover,
|
||||
QWidget[nav="top"] QAbstractButton:pressed,
|
||||
QWidget[nav="top"] QAbstractButton:checked {
|
||||
border-style: solid;
|
||||
border-width: 0px 0px 2px 0px;
|
||||
padding: 4px 4px 2px 4px;
|
||||
border-color: #00BB9E;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #F6F6F6, stop: 1 #F6F6F6);
|
||||
}
|
||||
|
||||
QWidget[nav="left"] QAbstractButton {
|
||||
border-radius: 0px;
|
||||
color: #57595B;
|
||||
background: none;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
QWidget[nav="left"] QAbstractButton:hover {
|
||||
color: #FFFFFF;
|
||||
background-color: #00BB9E;
|
||||
}
|
||||
|
||||
QWidget[nav="left"] QAbstractButton:checked,
|
||||
QWidget[nav="left"] QAbstractButton:pressed {
|
||||
color: #57595B;
|
||||
border-style: solid;
|
||||
border-width: 0px 0px 0px 2px;
|
||||
padding: 4px 4px 4px 2px;
|
||||
border-color: #00BB9E;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
QWidget[video="true"] QLabel {
|
||||
color: #57595B;
|
||||
border: 1px solid #B6B6B6;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E4E4E4, stop: 1 #E4E4E4);
|
||||
}
|
||||
|
||||
QWidget[video="true"] QLabel:focus {
|
||||
border: 1px solid #00BB9E;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #F6F6F6, stop: 1 #F6F6F6);
|
||||
}
|
||||
|
||||
QLineEdit,
|
||||
QTextEdit,
|
||||
QPlainTextEdit,
|
||||
QSpinBox,
|
||||
QDoubleSpinBox,
|
||||
QComboBox,
|
||||
QDateEdit,
|
||||
QTimeEdit,
|
||||
QDateTimeEdit {
|
||||
border: 1px solid #B6B6B6;
|
||||
border-radius: 3px;
|
||||
padding: 2px;
|
||||
background: none;
|
||||
selection-background-color: #00BB9E;
|
||||
selection-color: #FFFFFF;
|
||||
}
|
||||
|
||||
QLineEdit:focus,
|
||||
QTextEdit:focus,
|
||||
QPlainTextEdit:focus,
|
||||
QSpinBox:focus,
|
||||
QDoubleSpinBox:focus,
|
||||
QComboBox:focus,
|
||||
QDateEdit:focus,
|
||||
QTimeEdit:focus,
|
||||
QDateTimeEdit:focus,
|
||||
QLineEdit:hover,
|
||||
QTextEdit:hover,
|
||||
QPlainTextEdit:hover,
|
||||
QSpinBox:hover,
|
||||
QDoubleSpinBox:hover,
|
||||
QComboBox:hover,
|
||||
QDateEdit:hover,
|
||||
QTimeEdit:hover,
|
||||
QDateTimeEdit:hover {
|
||||
border: 1px solid #B6B6B6;
|
||||
}
|
||||
|
||||
QLineEdit[echoMode="2"] {
|
||||
lineedit-password-character: 9679;
|
||||
}
|
||||
|
||||
.QFrame {
|
||||
border: 1px solid #B6B6B6;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.QGroupBox {
|
||||
border: 1px solid #B6B6B6;
|
||||
border-radius: 5px;
|
||||
margin-top: 3ex;
|
||||
}
|
||||
|
||||
.QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
position: relative;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.QPushButton,
|
||||
.QToolButton {
|
||||
border-style: none;
|
||||
border: 1px solid #B6B6B6;
|
||||
color: #57595B;
|
||||
padding: 5px;
|
||||
min-height: 15px;
|
||||
border-radius: 5px;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E4E4E4, stop: 1 #E4E4E4);
|
||||
}
|
||||
|
||||
.QPushButton:hover,
|
||||
.QToolButton:hover {
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #F6F6F6, stop: 1 #F6F6F6);
|
||||
}
|
||||
|
||||
.QPushButton:pressed,
|
||||
.QToolButton:pressed {
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E4E4E4, stop: 1 #E4E4E4);
|
||||
}
|
||||
|
||||
.QToolButton::menu-indicator {
|
||||
image: None;
|
||||
}
|
||||
|
||||
QToolButton#btnMenu,
|
||||
QPushButton#btnMenu_Min,
|
||||
QPushButton#btnMenu_Max,
|
||||
QPushButton#btnMenu_Close {
|
||||
border-radius: 3px;
|
||||
color: #57595B;
|
||||
padding: 3px;
|
||||
margin: 0px;
|
||||
background: none;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
QToolButton#btnMenu:hover,
|
||||
QPushButton#btnMenu_Min:hover,
|
||||
QPushButton#btnMenu_Max:hover {
|
||||
color: #FFFFFF;
|
||||
margin: 1px 1px 2px 1px;
|
||||
background-color: rgba(51, 127, 209, 230);
|
||||
}
|
||||
|
||||
QPushButton#btnMenu_Close:hover {
|
||||
color: #FFFFFF;
|
||||
margin: 1px 1px 2px 1px;
|
||||
background-color: rgba(238, 0, 0, 128);
|
||||
}
|
||||
|
||||
QRadioButton::indicator {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
QRadioButton::indicator::unchecked {
|
||||
image: url(:/uistyles/flatwhite/radiobutton_unchecked.png);
|
||||
}
|
||||
|
||||
QRadioButton::indicator::unchecked:disabled {
|
||||
image: url(:/uistyles/flatwhite/radiobutton_unchecked_disable.png);
|
||||
}
|
||||
|
||||
QRadioButton::indicator::checked {
|
||||
image: url(:/uistyles/flatwhite/radiobutton_checked.png);
|
||||
}
|
||||
|
||||
QRadioButton::indicator::checked:disabled {
|
||||
image: url(:/uistyles/flatwhite/radiobutton_checked_disable.png);
|
||||
}
|
||||
|
||||
QGroupBox::indicator,
|
||||
QTreeWidget::indicator,
|
||||
QListWidget::indicator {
|
||||
padding: 0px -3px 0px 0px;
|
||||
}
|
||||
|
||||
QCheckBox::indicator,
|
||||
QGroupBox::indicator,
|
||||
QTreeWidget::indicator,
|
||||
QListWidget::indicator {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
QCheckBox::indicator:unchecked,
|
||||
QGroupBox::indicator:unchecked,
|
||||
QTreeWidget::indicator:unchecked,
|
||||
QListWidget::indicator:unchecked {
|
||||
image: url(:/uistyles/flatwhite/checkbox_unchecked.png);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:unchecked:disabled,
|
||||
QGroupBox::indicator:unchecked:disabled,
|
||||
QTreeWidget::indicator:unchecked:disabled,
|
||||
QListWidget::indicator:disabled {
|
||||
image: url(:/uistyles/flatwhite/checkbox_unchecked_disable.png);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:checked,
|
||||
QGroupBox::indicator:checked,
|
||||
QTreeWidget::indicator:checked,
|
||||
QListWidget::indicator:checked {
|
||||
image: url(:/uistyles/flatwhite/checkbox_checked.png);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:checked:disabled,
|
||||
QGroupBox::indicator:checked:disabled,
|
||||
QTreeWidget::indicator:checked:disabled,
|
||||
QListWidget::indicator:checked:disabled {
|
||||
image: url(:/uistyles/flatwhite/checkbox_checked_disable.png);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:indeterminate,
|
||||
QGroupBox::indicator:indeterminate,
|
||||
QTreeWidget::indicator:indeterminate,
|
||||
QListWidget::indicator:indeterminate {
|
||||
image: url(:/uistyles/flatwhite/checkbox_parcial.png);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:indeterminate:disabled,
|
||||
QGroupBox::indicator:indeterminate:disabled,
|
||||
QTreeWidget::indicator:indeterminate:disabled,
|
||||
QListWidget::indicator:indeterminate:disabled {
|
||||
image: url(:/uistyles/flatwhite/checkbox_parcial_disable.png);
|
||||
}
|
||||
|
||||
QTimeEdit::up-button,
|
||||
QDateEdit::up-button,
|
||||
QDateTimeEdit::up-button,
|
||||
QDoubleSpinBox::up-button,
|
||||
QSpinBox::up-button {
|
||||
image: url(:/uistyles/flatwhite/add_top.png);
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
padding: 2px 5px 0px 0px;
|
||||
}
|
||||
|
||||
QTimeEdit::down-button,
|
||||
QDateEdit::down-button,
|
||||
QDateTimeEdit::down-button,
|
||||
QDoubleSpinBox::down-button,
|
||||
QSpinBox::down-button {
|
||||
image: url(:/uistyles/flatwhite/add_bottom.png);
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
padding: 0px 5px 2px 0px;
|
||||
}
|
||||
|
||||
QTimeEdit::up-button:pressed,
|
||||
QDateEdit::up-button:pressed,
|
||||
QDateTimeEdit::up-button:pressed,
|
||||
QDoubleSpinBox::up-button:pressed,
|
||||
QSpinBox::up-button:pressed {
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
QTimeEdit::down-button:pressed,
|
||||
QDateEdit::down-button:pressed,
|
||||
QDateTimeEdit::down-button:pressed,
|
||||
QDoubleSpinBox::down-button:pressed,
|
||||
QSpinBox::down-button:pressed,
|
||||
QSpinBox::down-button:pressed {
|
||||
bottom: -2px;
|
||||
}
|
||||
|
||||
QComboBox::down-arrow,
|
||||
QDateEdit[calendarPopup="true"]::down-arrow,
|
||||
QTimeEdit[calendarPopup="true"]::down-arrow,
|
||||
QDateTimeEdit[calendarPopup="true"]::down-arrow {
|
||||
image: url(:/uistyles/flatwhite/add_bottom.png);
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
right: 2px;
|
||||
}
|
||||
|
||||
QComboBox::drop-down,
|
||||
QDateEdit::drop-down,
|
||||
QTimeEdit::drop-down,
|
||||
QDateTimeEdit::drop-down {
|
||||
subcontrol-origin: padding;
|
||||
subcontrol-position: top right;
|
||||
width: 15px;
|
||||
border-left-width: 0px;
|
||||
border-left-style: solid;
|
||||
border-top-right-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
border-left-color: #B6B6B6;
|
||||
}
|
||||
|
||||
QComboBox::drop-down:on {
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
QMenuBar::item {
|
||||
color: #57595B;
|
||||
background-color: #E4E4E4;
|
||||
margin: 0px;
|
||||
padding: 3px 10px;
|
||||
}
|
||||
|
||||
QMenu,
|
||||
QMenuBar,
|
||||
QMenu:disabled,
|
||||
QMenuBar:disabled {
|
||||
color: #57595B;
|
||||
background-color: #E4E4E4;
|
||||
border: 1px solid #B6B6B6;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
|
||||
QMenu::icon{
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
QMenu::item {
|
||||
padding: 3px 50px 3px 15px;
|
||||
}
|
||||
|
||||
QMenu::indicator {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
QMenu::item:selected,
|
||||
QMenuBar::item:selected {
|
||||
color: #57595B;
|
||||
border: 0px solid #B6B6B6;
|
||||
background: #F6F6F6;
|
||||
}
|
||||
|
||||
QMenu::separator {
|
||||
height: 1px;
|
||||
background: #B6B6B6;
|
||||
}
|
||||
|
||||
QProgressBar {
|
||||
min-height: 10px;
|
||||
background: #E4E4E4;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
border: 1px solid #E4E4E4;
|
||||
}
|
||||
|
||||
QProgressBar:chunk {
|
||||
border-radius: 5px;
|
||||
background-color: #B6B6B6;
|
||||
}
|
||||
|
||||
QSlider::groove:horizontal {
|
||||
background: #E4E4E4;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
QSlider::add-page:horizontal {
|
||||
background: #E4E4E4;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
QSlider::sub-page:horizontal {
|
||||
background: #B6B6B6;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
QSlider::handle:horizontal {
|
||||
width: 13px;
|
||||
margin-top: -3px;
|
||||
margin-bottom: -3px;
|
||||
border-radius: 6px;
|
||||
background: qradialgradient(spread: pad, cx: 0.5, cy: 0.5, radius: 0.5, fx: 0.5, fy: 0.5, stop: 0.6 #FFFFFF, stop: 0.8 #B6B6B6);
|
||||
}
|
||||
|
||||
QSlider::groove:vertical {
|
||||
width: 8px;
|
||||
border-radius: 4px;
|
||||
background: #E4E4E4;
|
||||
}
|
||||
|
||||
QSlider::add-page:vertical {
|
||||
width: 8px;
|
||||
border-radius: 4px;
|
||||
background: #E4E4E4;
|
||||
}
|
||||
|
||||
QSlider::sub-page:vertical {
|
||||
width: 8px;
|
||||
border-radius: 4px;
|
||||
background: #B6B6B6;
|
||||
}
|
||||
|
||||
QSlider::handle:vertical {
|
||||
height: 14px;
|
||||
margin-left: -3px;
|
||||
margin-right: -3px;
|
||||
border-radius: 6px;
|
||||
background: qradialgradient(spread: pad, cx: 0.5, cy: 0.5, radius: 0.5, fx: 0.5, fy: 0.5, stop: 0.6 #FFFFFF, stop: 0.8 #B6B6B6);
|
||||
}
|
||||
|
||||
QScrollBar:horizontal {
|
||||
background: #E4E4E4;
|
||||
padding: 0px;
|
||||
border-radius: 6px;
|
||||
max-height: 8px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:horizontal {
|
||||
background: #B6B6B6;
|
||||
min-width: 50px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:horizontal:hover {
|
||||
background: #00BB9E;
|
||||
}
|
||||
|
||||
QScrollBar::handle:horizontal:pressed {
|
||||
background: #00BB9E;
|
||||
}
|
||||
|
||||
QScrollBar::add-page:horizontal {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar::sub-page:horizontal {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:horizontal {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar::sub-line:horizontal {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar:vertical {
|
||||
background: #E4E4E4;
|
||||
padding: 0px;
|
||||
border-radius: 6px;
|
||||
max-width: 8px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical {
|
||||
background: #B6B6B6;
|
||||
min-height: 50px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical:hover {
|
||||
background: #00BB9E;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical:pressed {
|
||||
background: #00BB9E;
|
||||
}
|
||||
|
||||
QScrollBar::add-page:vertical {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar::sub-page:vertical {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:vertical {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar::sub-line:vertical {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollArea {
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
QTreeView,
|
||||
QListView,
|
||||
QTableView,
|
||||
QTabWidget::pane {
|
||||
border: 1px solid #B6B6B6;
|
||||
selection-background-color: #F6F6F6;
|
||||
selection-color: #57595B;
|
||||
alternate-background-color: #F6F6F6;
|
||||
gridline-color: #B6B6B6;
|
||||
}
|
||||
|
||||
QTreeView::branch:closed:has-children {
|
||||
margin: 4px;
|
||||
border-image: url(:/uistyles/flatwhite/branch_open.png);
|
||||
}
|
||||
|
||||
QTreeView::branch:open:has-children {
|
||||
margin: 4px;
|
||||
border-image: url(:/uistyles/flatwhite/branch_close.png);
|
||||
}
|
||||
|
||||
QTreeView,
|
||||
QListView,
|
||||
QTableView,
|
||||
QSplitter::handle,
|
||||
QTreeView::branch {
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
QTableView::item:selected,
|
||||
QListView::item:selected,
|
||||
QTreeView::item:selected {
|
||||
color: #57595B;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E4E4E4, stop: 1 #E4E4E4);
|
||||
}
|
||||
|
||||
QTableView::item:hover,
|
||||
QListView::item:hover,
|
||||
QTreeView::item:hover,
|
||||
QHeaderView {
|
||||
color: #57595B;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #F6F6F6, stop: 1 #F6F6F6);
|
||||
}
|
||||
|
||||
QTableView::item,
|
||||
QListView::item,
|
||||
QTreeView::item {
|
||||
padding: 1px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
QHeaderView::section,
|
||||
QTableCornerButton:section {
|
||||
padding: 3px;
|
||||
margin: 0px;
|
||||
color: #57595B;
|
||||
border: 1px solid #B6B6B6;
|
||||
border-left-width: 0px;
|
||||
border-right-width: 1px;
|
||||
border-top-width: 0px;
|
||||
border-bottom-width: 1px;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #F6F6F6, stop: 1 #F6F6F6);
|
||||
}
|
||||
|
||||
QTabBar::tab {
|
||||
border: 1px solid #B6B6B6;
|
||||
color: #57595B;
|
||||
margin: 0px;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #F6F6F6, stop: 1 #F6F6F6);
|
||||
}
|
||||
|
||||
QTabBar::tab:selected,
|
||||
QTabBar::tab:hover {
|
||||
border-style: solid;
|
||||
border-color: #00BB9E;
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
QTabBar::tab:top,
|
||||
QTabBar::tab:bottom {
|
||||
padding: 3px 8px 3px 8px;
|
||||
}
|
||||
|
||||
QTabBar::tab:left,
|
||||
QTabBar::tab:right {
|
||||
padding: 8px 3px 8px 3px;
|
||||
}
|
||||
|
||||
QTabBar::tab:top:selected,
|
||||
QTabBar::tab:top:hover {
|
||||
border-width: 2px 0px 0px 0px;
|
||||
}
|
||||
|
||||
QTabBar::tab:right:selected,
|
||||
QTabBar::tab:right:hover {
|
||||
border-width: 0px 0px 0px 2px;
|
||||
}
|
||||
|
||||
QTabBar::tab:bottom:selected,
|
||||
QTabBar::tab:bottom:hover {
|
||||
border-width: 0px 0px 2px 0px;
|
||||
}
|
||||
|
||||
QTabBar::tab:left:selected,
|
||||
QTabBar::tab:left:hover {
|
||||
border-width: 0px 2px 0px 0px;
|
||||
}
|
||||
|
||||
QTabBar::tab:first:top:selected,
|
||||
QTabBar::tab:first:top:hover,
|
||||
QTabBar::tab:first:bottom:selected,
|
||||
QTabBar::tab:first:bottom:hover {
|
||||
border-left-width: 1px;
|
||||
border-left-color: #B6B6B6;
|
||||
}
|
||||
|
||||
QTabBar::tab:first:left:selected,
|
||||
QTabBar::tab:first:left:hover,
|
||||
QTabBar::tab:first:right:selected,
|
||||
QTabBar::tab:first:right:hover {
|
||||
border-top-width: 1px;
|
||||
border-top-color: #B6B6B6;
|
||||
}
|
||||
|
||||
QTabBar::tab:last:top:selected,
|
||||
QTabBar::tab:last:top:hover,
|
||||
QTabBar::tab:last:bottom:selected,
|
||||
QTabBar::tab:last:bottom:hover {
|
||||
border-right-width: 1px;
|
||||
border-right-color: #B6B6B6;
|
||||
}
|
||||
|
||||
QTabBar::tab:last:left:selected,
|
||||
QTabBar::tab:last:left:hover,
|
||||
QTabBar::tab:last:right:selected,
|
||||
QTabBar::tab:last:right:hover {
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-color: #B6B6B6;
|
||||
}
|
||||
|
||||
QStatusBar::item {
|
||||
border: 0px solid #E4E4E4;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
QToolBox::tab,
|
||||
QGroupBox#gboxDevicePanel,
|
||||
QGroupBox#gboxDeviceTitle,
|
||||
QFrame#gboxDevicePanel,
|
||||
QFrame#gboxDeviceTitle {
|
||||
padding: 3px;
|
||||
border-radius: 5px;
|
||||
color: #57595B;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E4E4E4, stop: 1 #E4E4E4);
|
||||
}
|
||||
|
||||
QToolTip {
|
||||
border: 0px solid #57595B;
|
||||
padding: 1px;
|
||||
color: #57595B;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E4E4E4, stop: 1 #E4E4E4);
|
||||
}
|
||||
|
||||
QToolBox::tab:selected {
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #F6F6F6, stop: 1 #F6F6F6);
|
||||
}
|
||||
|
||||
QPrintPreviewDialog QToolButton {
|
||||
border: 0px solid #57595B;
|
||||
border-radius: 0px;
|
||||
margin: 0px;
|
||||
padding: 3px;
|
||||
background: none;
|
||||
}
|
||||
|
||||
QColorDialog QPushButton,
|
||||
QFileDialog QPushButton {
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
QToolButton#qt_calendar_prevmonth {
|
||||
icon-size: 0px;
|
||||
min-width: 20px;
|
||||
image: url(:/uistyles/flatwhite/calendar_prevmonth.png);
|
||||
}
|
||||
|
||||
QToolButton#qt_calendar_nextmonth {
|
||||
icon-size: 0px;
|
||||
min-width: 20px;
|
||||
image: url(:/uistyles/flatwhite/calendar_nextmonth.png);
|
||||
}
|
||||
|
||||
QToolButton#qt_calendar_prevmonth,
|
||||
QToolButton#qt_calendar_nextmonth,
|
||||
QToolButton#qt_calendar_monthbutton,
|
||||
QToolButton#qt_calendar_yearbutton {
|
||||
border: 0px solid #57595B;
|
||||
border-radius: 3px;
|
||||
margin: 3px 3px 3px 3px;
|
||||
padding: 3px;
|
||||
background: none;
|
||||
}
|
||||
|
||||
QToolButton#qt_calendar_prevmonth:hover,
|
||||
QToolButton#qt_calendar_nextmonth:hover,
|
||||
QToolButton#qt_calendar_monthbutton:hover,
|
||||
QToolButton#qt_calendar_yearbutton:hover,
|
||||
QToolButton#qt_calendar_prevmonth:pressed,
|
||||
QToolButton#qt_calendar_nextmonth:pressed,
|
||||
QToolButton#qt_calendar_monthbutton:pressed,
|
||||
QToolButton#qt_calendar_yearbutton:pressed {
|
||||
border: 1px solid #B6B6B6;
|
||||
}
|
||||
|
||||
QCalendarWidget QSpinBox#qt_calendar_yearedit {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
QCalendarWidget QToolButton::menu-indicator {
|
||||
image: None;
|
||||
}
|
||||
|
||||
QCalendarWidget QTableView {
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
QCalendarWidget QWidget#qt_calendar_navigationbar {
|
||||
border: 1px solid #B6B6B6;
|
||||
border-width: 1px 1px 0px 1px;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E4E4E4, stop: 1 #E4E4E4);
|
||||
}
|
||||
|
||||
QComboBox QAbstractItemView::item {
|
||||
min-height: 20px;
|
||||
min-width: 10px;
|
||||
}
|
||||
|
||||
QTableView[model="true"]::item {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
QTableView QLineEdit,
|
||||
QTableView QComboBox,
|
||||
QTableView QSpinBox,
|
||||
QTableView QDoubleSpinBox,
|
||||
QTableView QDateEdit,
|
||||
QTableView QTimeEdit,
|
||||
QTableView QDateTimeEdit {
|
||||
border-width: 0px;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
QTableView QLineEdit:focus,
|
||||
QTableView QComboBox:focus,
|
||||
QTableView QSpinBox:focus,
|
||||
QTableView QDoubleSpinBox:focus,
|
||||
QTableView QDateEdit:focus,
|
||||
QTableView QTimeEdit:focus,
|
||||
QTableView QDateTimeEdit:focus {
|
||||
border-width: 0px;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
QLineEdit,
|
||||
QTextEdit,
|
||||
QPlainTextEdit,
|
||||
QSpinBox,
|
||||
QDoubleSpinBox,
|
||||
QComboBox,
|
||||
QDateEdit,
|
||||
QTimeEdit,
|
||||
QDateTimeEdit {
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
QTabWidget::pane:top {
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
QTabWidget::pane:bottom {
|
||||
bottom: -1px;
|
||||
}
|
||||
|
||||
QTabWidget::pane:left {
|
||||
right: -1px;
|
||||
}
|
||||
|
||||
QTabWidget::pane:right {
|
||||
left: -1px;
|
||||
}
|
||||
|
||||
*:disabled {
|
||||
background: #FFFFFF;
|
||||
border-color: #E4E4E4;
|
||||
color: #B6B6B6;
|
||||
}
|
||||
|
||||
|
||||
/*TextColor:#57595B*/
|
||||
|
||||
|
||||
/*PanelColor:#FFFFFF*/
|
||||
|
||||
|
||||
/*BorderColor:#B6B6B6*/
|
||||
|
||||
|
||||
/*NormalColorStart:#E4E4E4*/
|
||||
|
||||
|
||||
/*NormalColorEnd:#E4E4E4*/
|
||||
|
||||
|
||||
/*DarkColorStart:#F6F6F6*/
|
||||
|
||||
|
||||
/*DarkColorEnd:#F6F6F6*/
|
||||
|
||||
|
||||
/*HighColor:#00BB9E*/
|
23
libs/uistyles/flatwhite/flatwhite.qrc
Normal file
@ -0,0 +1,23 @@
|
||||
<RCC>
|
||||
<qresource prefix="/uistyles">
|
||||
<file>flatwhite.css</file>
|
||||
<file>flatwhite/add_bottom.png</file>
|
||||
<file>flatwhite/add_left.png</file>
|
||||
<file>flatwhite/add_right.png</file>
|
||||
<file>flatwhite/add_top.png</file>
|
||||
<file>flatwhite/branch_close.png</file>
|
||||
<file>flatwhite/branch_open.png</file>
|
||||
<file>flatwhite/calendar_nextmonth.png</file>
|
||||
<file>flatwhite/calendar_prevmonth.png</file>
|
||||
<file>flatwhite/checkbox_checked.png</file>
|
||||
<file>flatwhite/checkbox_checked_disable.png</file>
|
||||
<file>flatwhite/checkbox_parcial.png</file>
|
||||
<file>flatwhite/checkbox_parcial_disable.png</file>
|
||||
<file>flatwhite/checkbox_unchecked.png</file>
|
||||
<file>flatwhite/checkbox_unchecked_disable.png</file>
|
||||
<file>flatwhite/radiobutton_checked.png</file>
|
||||
<file>flatwhite/radiobutton_checked_disable.png</file>
|
||||
<file>flatwhite/radiobutton_unchecked.png</file>
|
||||
<file>flatwhite/radiobutton_unchecked_disable.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
BIN
libs/uistyles/flatwhite/flatwhite/add_bottom.png
Normal file
After Width: | Height: | Size: 181 B |
BIN
libs/uistyles/flatwhite/flatwhite/add_left.png
Normal file
After Width: | Height: | Size: 219 B |
BIN
libs/uistyles/flatwhite/flatwhite/add_right.png
Normal file
After Width: | Height: | Size: 214 B |
BIN
libs/uistyles/flatwhite/flatwhite/add_top.png
Normal file
After Width: | Height: | Size: 178 B |
BIN
libs/uistyles/flatwhite/flatwhite/branch_close.png
Normal file
After Width: | Height: | Size: 167 B |
BIN
libs/uistyles/flatwhite/flatwhite/branch_open.png
Normal file
After Width: | Height: | Size: 273 B |
BIN
libs/uistyles/flatwhite/flatwhite/calendar_nextmonth.png
Normal file
After Width: | Height: | Size: 358 B |
BIN
libs/uistyles/flatwhite/flatwhite/calendar_prevmonth.png
Normal file
After Width: | Height: | Size: 341 B |
BIN
libs/uistyles/flatwhite/flatwhite/checkbox_checked.png
Normal file
After Width: | Height: | Size: 289 B |
BIN
libs/uistyles/flatwhite/flatwhite/checkbox_checked_disable.png
Normal file
After Width: | Height: | Size: 301 B |
BIN
libs/uistyles/flatwhite/flatwhite/checkbox_parcial.png
Normal file
After Width: | Height: | Size: 172 B |
BIN
libs/uistyles/flatwhite/flatwhite/checkbox_parcial_disable.png
Normal file
After Width: | Height: | Size: 237 B |
BIN
libs/uistyles/flatwhite/flatwhite/checkbox_unchecked.png
Normal file
After Width: | Height: | Size: 133 B |
BIN
libs/uistyles/flatwhite/flatwhite/checkbox_unchecked_disable.png
Normal file
After Width: | Height: | Size: 137 B |
BIN
libs/uistyles/flatwhite/flatwhite/radiobutton_checked.png
Normal file
After Width: | Height: | Size: 726 B |
After Width: | Height: | Size: 817 B |
BIN
libs/uistyles/flatwhite/flatwhite/radiobutton_unchecked.png
Normal file
After Width: | Height: | Size: 523 B |
After Width: | Height: | Size: 593 B |
845
libs/uistyles/psblack/psblack.css
Normal file
@ -0,0 +1,845 @@
|
||||
QPalette,
|
||||
QWidget {
|
||||
background: #444444;
|
||||
}
|
||||
|
||||
* {
|
||||
outline: 0px;
|
||||
color: #DCDCDC;
|
||||
}
|
||||
|
||||
QWidget[form="true"],
|
||||
QLabel[frameShape="1"] {
|
||||
border: 1px solid #242424;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
QWidget[form="bottom"] {
|
||||
background: #484848;
|
||||
}
|
||||
|
||||
QWidget[form="bottom"] .QFrame {
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
QWidget[form="bottom"] QLabel,
|
||||
QWidget[form="title"] QLabel {
|
||||
border-radius: 0px;
|
||||
color: #DCDCDC;
|
||||
background: none;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
QWidget[form="title"],
|
||||
QWidget[nav="left"],
|
||||
QWidget[nav="top"] QAbstractButton {
|
||||
border-style: none;
|
||||
border-radius: 0px;
|
||||
padding: 5px;
|
||||
color: #DCDCDC;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #484848, stop: 1 #383838);
|
||||
}
|
||||
|
||||
QWidget[nav="top"] QAbstractButton:hover,
|
||||
QWidget[nav="top"] QAbstractButton:pressed,
|
||||
QWidget[nav="top"] QAbstractButton:checked {
|
||||
border-style: solid;
|
||||
border-width: 0px 0px 2px 0px;
|
||||
padding: 4px 4px 2px 4px;
|
||||
border-color: #00BB9E;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #646464, stop: 1 #525252);
|
||||
}
|
||||
|
||||
QWidget[nav="left"] QAbstractButton {
|
||||
border-radius: 0px;
|
||||
color: #DCDCDC;
|
||||
background: none;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
QWidget[nav="left"] QAbstractButton:hover {
|
||||
color: #FFFFFF;
|
||||
background-color: #00BB9E;
|
||||
}
|
||||
|
||||
QWidget[nav="left"] QAbstractButton:checked,
|
||||
QWidget[nav="left"] QAbstractButton:pressed {
|
||||
color: #DCDCDC;
|
||||
border-style: solid;
|
||||
border-width: 0px 0px 0px 2px;
|
||||
padding: 4px 4px 4px 2px;
|
||||
border-color: #00BB9E;
|
||||
background-color: #444444;
|
||||
}
|
||||
|
||||
QWidget[video="true"] QLabel {
|
||||
color: #DCDCDC;
|
||||
border: 1px solid #242424;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #484848, stop: 1 #383838);
|
||||
}
|
||||
|
||||
QWidget[video="true"] QLabel:focus {
|
||||
border: 1px solid #00BB9E;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #646464, stop: 1 #525252);
|
||||
}
|
||||
|
||||
QLineEdit,
|
||||
QTextEdit,
|
||||
QPlainTextEdit,
|
||||
QSpinBox,
|
||||
QDoubleSpinBox,
|
||||
QComboBox,
|
||||
QDateEdit,
|
||||
QTimeEdit,
|
||||
QDateTimeEdit {
|
||||
border: 1px solid #242424;
|
||||
border-radius: 3px;
|
||||
padding: 2px;
|
||||
background: none;
|
||||
selection-background-color: #484848;
|
||||
selection-color: #DCDCDC;
|
||||
}
|
||||
|
||||
QLineEdit:focus,
|
||||
QTextEdit:focus,
|
||||
QPlainTextEdit:focus,
|
||||
QSpinBox:focus,
|
||||
QDoubleSpinBox:focus,
|
||||
QComboBox:focus,
|
||||
QDateEdit:focus,
|
||||
QTimeEdit:focus,
|
||||
QDateTimeEdit:focus,
|
||||
QLineEdit:hover,
|
||||
QTextEdit:hover,
|
||||
QPlainTextEdit:hover,
|
||||
QSpinBox:hover,
|
||||
QDoubleSpinBox:hover,
|
||||
QComboBox:hover,
|
||||
QDateEdit:hover,
|
||||
QTimeEdit:hover,
|
||||
QDateTimeEdit:hover {
|
||||
border: 1px solid #242424;
|
||||
}
|
||||
|
||||
QLineEdit[echoMode="2"] {
|
||||
lineedit-password-character: 9679;
|
||||
}
|
||||
|
||||
.QFrame {
|
||||
border: 1px solid #242424;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.QGroupBox {
|
||||
border: 1px solid #242424;
|
||||
border-radius: 5px;
|
||||
margin-top: 3ex;
|
||||
}
|
||||
|
||||
.QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
position: relative;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.QPushButton,
|
||||
.QToolButton {
|
||||
border-style: none;
|
||||
border: 1px solid #242424;
|
||||
color: #DCDCDC;
|
||||
padding: 5px;
|
||||
min-height: 15px;
|
||||
border-radius: 5px;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #484848, stop: 1 #383838);
|
||||
}
|
||||
|
||||
.QPushButton:hover,
|
||||
.QToolButton:hover {
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #646464, stop: 1 #525252);
|
||||
}
|
||||
|
||||
.QPushButton:pressed,
|
||||
.QToolButton:pressed {
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #484848, stop: 1 #383838);
|
||||
}
|
||||
|
||||
.QToolButton::menu-indicator {
|
||||
image: None;
|
||||
}
|
||||
|
||||
QToolButton#btnMenu,
|
||||
QPushButton#btnMenu_Min,
|
||||
QPushButton#btnMenu_Max,
|
||||
QPushButton#btnMenu_Close {
|
||||
border-radius: 3px;
|
||||
color: #DCDCDC;
|
||||
padding: 3px;
|
||||
margin: 0px;
|
||||
background: none;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
QToolButton#btnMenu:hover,
|
||||
QPushButton#btnMenu_Min:hover,
|
||||
QPushButton#btnMenu_Max:hover {
|
||||
color: #FFFFFF;
|
||||
margin: 1px 1px 2px 1px;
|
||||
background-color: rgba(51, 127, 209, 230);
|
||||
}
|
||||
|
||||
QPushButton#btnMenu_Close:hover {
|
||||
color: #FFFFFF;
|
||||
margin: 1px 1px 2px 1px;
|
||||
background-color: rgba(238, 0, 0, 128);
|
||||
}
|
||||
|
||||
QRadioButton::indicator {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
QRadioButton::indicator::unchecked {
|
||||
image: url(:/uistyles/psblack/radiobutton_unchecked.png);
|
||||
}
|
||||
|
||||
QRadioButton::indicator::unchecked:disabled {
|
||||
image: url(:/uistyles/psblack/radiobutton_unchecked_disable.png);
|
||||
}
|
||||
|
||||
QRadioButton::indicator::checked {
|
||||
image: url(:/uistyles/psblack/radiobutton_checked.png);
|
||||
}
|
||||
|
||||
QRadioButton::indicator::checked:disabled {
|
||||
image: url(:/uistyles/psblack/radiobutton_checked_disable.png);
|
||||
}
|
||||
|
||||
QGroupBox::indicator,
|
||||
QTreeWidget::indicator,
|
||||
QListWidget::indicator {
|
||||
padding: 0px -3px 0px 0px;
|
||||
}
|
||||
|
||||
QCheckBox::indicator,
|
||||
QGroupBox::indicator,
|
||||
QTreeWidget::indicator,
|
||||
QListWidget::indicator {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
QCheckBox::indicator:unchecked,
|
||||
QGroupBox::indicator:unchecked,
|
||||
QTreeWidget::indicator:unchecked,
|
||||
QListWidget::indicator:unchecked {
|
||||
image: url(:/uistyles/psblack/checkbox_unchecked.png);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:unchecked:disabled,
|
||||
QGroupBox::indicator:unchecked:disabled,
|
||||
QTreeWidget::indicator:unchecked:disabled,
|
||||
QListWidget::indicator:disabled {
|
||||
image: url(:/uistyles/psblack/checkbox_unchecked_disable.png);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:checked,
|
||||
QGroupBox::indicator:checked,
|
||||
QTreeWidget::indicator:checked,
|
||||
QListWidget::indicator:checked {
|
||||
image: url(:/uistyles/psblack/checkbox_checked.png);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:checked:disabled,
|
||||
QGroupBox::indicator:checked:disabled,
|
||||
QTreeWidget::indicator:checked:disabled,
|
||||
QListWidget::indicator:checked:disabled {
|
||||
image: url(:/uistyles/psblack/checkbox_checked_disable.png);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:indeterminate,
|
||||
QGroupBox::indicator:indeterminate,
|
||||
QTreeWidget::indicator:indeterminate,
|
||||
QListWidget::indicator:indeterminate {
|
||||
image: url(:/uistyles/psblack/checkbox_parcial.png);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:indeterminate:disabled,
|
||||
QGroupBox::indicator:indeterminate:disabled,
|
||||
QTreeWidget::indicator:indeterminate:disabled,
|
||||
QListWidget::indicator:indeterminate:disabled {
|
||||
image: url(:/uistyles/psblack/checkbox_parcial_disable.png);
|
||||
}
|
||||
|
||||
QTimeEdit::up-button,
|
||||
QDateEdit::up-button,
|
||||
QDateTimeEdit::up-button,
|
||||
QDoubleSpinBox::up-button,
|
||||
QSpinBox::up-button {
|
||||
image: url(:/uistyles/psblack/add_top.png);
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
padding: 2px 5px 0px 0px;
|
||||
}
|
||||
|
||||
QTimeEdit::down-button,
|
||||
QDateEdit::down-button,
|
||||
QDateTimeEdit::down-button,
|
||||
QDoubleSpinBox::down-button,
|
||||
QSpinBox::down-button {
|
||||
image: url(:/uistyles/psblack/add_bottom.png);
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
padding: 0px 5px 2px 0px;
|
||||
}
|
||||
|
||||
QTimeEdit::up-button:pressed,
|
||||
QDateEdit::up-button:pressed,
|
||||
QDateTimeEdit::up-button:pressed,
|
||||
QDoubleSpinBox::up-button:pressed,
|
||||
QSpinBox::up-button:pressed {
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
QTimeEdit::down-button:pressed,
|
||||
QDateEdit::down-button:pressed,
|
||||
QDateTimeEdit::down-button:pressed,
|
||||
QDoubleSpinBox::down-button:pressed,
|
||||
QSpinBox::down-button:pressed,
|
||||
QSpinBox::down-button:pressed {
|
||||
bottom: -2px;
|
||||
}
|
||||
|
||||
QComboBox::down-arrow,
|
||||
QDateEdit[calendarPopup="true"]::down-arrow,
|
||||
QTimeEdit[calendarPopup="true"]::down-arrow,
|
||||
QDateTimeEdit[calendarPopup="true"]::down-arrow {
|
||||
image: url(:/uistyles/psblack/add_bottom.png);
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
right: 2px;
|
||||
}
|
||||
|
||||
QComboBox::drop-down,
|
||||
QDateEdit::drop-down,
|
||||
QTimeEdit::drop-down,
|
||||
QDateTimeEdit::drop-down {
|
||||
subcontrol-origin: padding;
|
||||
subcontrol-position: top right;
|
||||
width: 15px;
|
||||
border-left-width: 0px;
|
||||
border-left-style: solid;
|
||||
border-top-right-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
border-left-color: #242424;
|
||||
}
|
||||
|
||||
QComboBox::drop-down:on {
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
QMenuBar::item {
|
||||
color: #DCDCDC;
|
||||
background-color: #484848;
|
||||
margin: 0px;
|
||||
padding: 3px 10px;
|
||||
}
|
||||
|
||||
QMenu,
|
||||
QMenuBar,
|
||||
QMenu:disabled,
|
||||
QMenuBar:disabled {
|
||||
color: #DCDCDC;
|
||||
background-color: #484848;
|
||||
border: 1px solid #242424;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
QMenu::icon{
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
QMenu::item {
|
||||
padding: 3px 50px 3px 15px;
|
||||
}
|
||||
|
||||
QMenu::indicator {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
QMenu::item:selected,
|
||||
QMenuBar::item:selected {
|
||||
color: #DCDCDC;
|
||||
border: 0px solid #242424;
|
||||
background: #646464;
|
||||
}
|
||||
|
||||
QMenu::separator {
|
||||
height: 1px;
|
||||
background: #242424;
|
||||
}
|
||||
|
||||
QProgressBar {
|
||||
min-height: 10px;
|
||||
background: #484848;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
border: 1px solid #484848;
|
||||
}
|
||||
|
||||
QProgressBar:chunk {
|
||||
border-radius: 5px;
|
||||
background-color: #242424;
|
||||
}
|
||||
|
||||
QSlider::groove:horizontal {
|
||||
background: #484848;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
QSlider::add-page:horizontal {
|
||||
background: #484848;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
QSlider::sub-page:horizontal {
|
||||
background: #242424;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
QSlider::handle:horizontal {
|
||||
width: 13px;
|
||||
margin-top: -3px;
|
||||
margin-bottom: -3px;
|
||||
border-radius: 6px;
|
||||
background: qradialgradient(spread: pad, cx: 0.5, cy: 0.5, radius: 0.5, fx: 0.5, fy: 0.5, stop: 0.6 #444444, stop: 0.8 #242424);
|
||||
}
|
||||
|
||||
QSlider::groove:vertical {
|
||||
width: 8px;
|
||||
border-radius: 4px;
|
||||
background: #484848;
|
||||
}
|
||||
|
||||
QSlider::add-page:vertical {
|
||||
width: 8px;
|
||||
border-radius: 4px;
|
||||
background: #484848;
|
||||
}
|
||||
|
||||
QSlider::sub-page:vertical {
|
||||
width: 8px;
|
||||
border-radius: 4px;
|
||||
background: #242424;
|
||||
}
|
||||
|
||||
QSlider::handle:vertical {
|
||||
height: 14px;
|
||||
margin-left: -3px;
|
||||
margin-right: -3px;
|
||||
border-radius: 6px;
|
||||
background: qradialgradient(spread: pad, cx: 0.5, cy: 0.5, radius: 0.5, fx: 0.5, fy: 0.5, stop: 0.6 #444444, stop: 0.8 #242424);
|
||||
}
|
||||
|
||||
QScrollBar:horizontal {
|
||||
background: #484848;
|
||||
padding: 0px;
|
||||
border-radius: 6px;
|
||||
max-height: 12px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:horizontal {
|
||||
background: #242424;
|
||||
min-width: 50px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:horizontal:hover {
|
||||
background: #00BB9E;
|
||||
}
|
||||
|
||||
QScrollBar::handle:horizontal:pressed {
|
||||
background: #00BB9E;
|
||||
}
|
||||
|
||||
QScrollBar::add-page:horizontal {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar::sub-page:horizontal {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:horizontal {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar::sub-line:horizontal {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar:vertical {
|
||||
background: #484848;
|
||||
padding: 0px;
|
||||
border-radius: 6px;
|
||||
max-width: 12px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical {
|
||||
background: #242424;
|
||||
min-height: 50px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical:hover {
|
||||
background: #00BB9E;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical:pressed {
|
||||
background: #00BB9E;
|
||||
}
|
||||
|
||||
QScrollBar::add-page:vertical {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar::sub-page:vertical {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:vertical {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar::sub-line:vertical {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollArea {
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
QTreeView,
|
||||
QListView,
|
||||
QTableView,
|
||||
QTabWidget::pane {
|
||||
border: 1px solid #242424;
|
||||
selection-background-color: #646464;
|
||||
selection-color: #DCDCDC;
|
||||
alternate-background-color: #525252;
|
||||
gridline-color: #242424;
|
||||
}
|
||||
|
||||
QTreeView::branch:closed:has-children {
|
||||
margin: 4px;
|
||||
border-image: url(:/uistyles/psblack/branch_open.png);
|
||||
}
|
||||
|
||||
QTreeView::branch:open:has-children {
|
||||
margin: 4px;
|
||||
border-image: url(:/uistyles/psblack/branch_close.png);
|
||||
}
|
||||
|
||||
QTreeView,
|
||||
QListView,
|
||||
QTableView,
|
||||
QSplitter::handle,
|
||||
QTreeView::branch {
|
||||
background: #444444;
|
||||
}
|
||||
|
||||
QTableView::item:selected,
|
||||
QListView::item:selected,
|
||||
QTreeView::item:selected {
|
||||
color: #DCDCDC;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #484848, stop: 1 #383838);
|
||||
}
|
||||
|
||||
QTableView::item:hover,
|
||||
QListView::item:hover,
|
||||
QTreeView::item:hover,
|
||||
QHeaderView {
|
||||
color: #DCDCDC;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #646464, stop: 1 #525252);
|
||||
}
|
||||
|
||||
QTableView::item,
|
||||
QListView::item,
|
||||
QTreeView::item {
|
||||
padding: 1px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
QHeaderView::section,
|
||||
QTableCornerButton:section {
|
||||
padding: 3px;
|
||||
margin: 0px;
|
||||
color: #DCDCDC;
|
||||
border: 1px solid #242424;
|
||||
border-left-width: 0px;
|
||||
border-right-width: 1px;
|
||||
border-top-width: 0px;
|
||||
border-bottom-width: 1px;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #646464, stop: 1 #525252);
|
||||
}
|
||||
|
||||
QTabBar::tab {
|
||||
border: 1px solid #242424;
|
||||
color: #DCDCDC;
|
||||
margin: 0px;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #646464, stop: 1 #525252);
|
||||
}
|
||||
|
||||
QTabBar::tab:selected,
|
||||
QTabBar::tab:hover {
|
||||
border-style: solid;
|
||||
border-color: #00BB9E;
|
||||
background: #444444;
|
||||
}
|
||||
|
||||
QTabBar::tab:top,
|
||||
QTabBar::tab:bottom {
|
||||
padding: 3px 8px 3px 8px;
|
||||
}
|
||||
|
||||
QTabBar::tab:left,
|
||||
QTabBar::tab:right {
|
||||
padding: 8px 3px 8px 3px;
|
||||
}
|
||||
|
||||
QTabBar::tab:top:selected,
|
||||
QTabBar::tab:top:hover {
|
||||
border-width: 2px 0px 0px 0px;
|
||||
}
|
||||
|
||||
QTabBar::tab:right:selected,
|
||||
QTabBar::tab:right:hover {
|
||||
border-width: 0px 0px 0px 2px;
|
||||
}
|
||||
|
||||
QTabBar::tab:bottom:selected,
|
||||
QTabBar::tab:bottom:hover {
|
||||
border-width: 0px 0px 2px 0px;
|
||||
}
|
||||
|
||||
QTabBar::tab:left:selected,
|
||||
QTabBar::tab:left:hover {
|
||||
border-width: 0px 2px 0px 0px;
|
||||
}
|
||||
|
||||
QTabBar::tab:first:top:selected,
|
||||
QTabBar::tab:first:top:hover,
|
||||
QTabBar::tab:first:bottom:selected,
|
||||
QTabBar::tab:first:bottom:hover {
|
||||
border-left-width: 1px;
|
||||
border-left-color: #242424;
|
||||
}
|
||||
|
||||
QTabBar::tab:first:left:selected,
|
||||
QTabBar::tab:first:left:hover,
|
||||
QTabBar::tab:first:right:selected,
|
||||
QTabBar::tab:first:right:hover {
|
||||
border-top-width: 1px;
|
||||
border-top-color: #242424;
|
||||
}
|
||||
|
||||
QTabBar::tab:last:top:selected,
|
||||
QTabBar::tab:last:top:hover,
|
||||
QTabBar::tab:last:bottom:selected,
|
||||
QTabBar::tab:last:bottom:hover {
|
||||
border-right-width: 1px;
|
||||
border-right-color: #242424;
|
||||
}
|
||||
|
||||
QTabBar::tab:last:left:selected,
|
||||
QTabBar::tab:last:left:hover,
|
||||
QTabBar::tab:last:right:selected,
|
||||
QTabBar::tab:last:right:hover {
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-color: #242424;
|
||||
}
|
||||
|
||||
QStatusBar::item {
|
||||
border: 0px solid #484848;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
QToolBox::tab,
|
||||
QGroupBox#gboxDevicePanel,
|
||||
QGroupBox#gboxDeviceTitle,
|
||||
QFrame#gboxDevicePanel,
|
||||
QFrame#gboxDeviceTitle {
|
||||
padding: 3px;
|
||||
border-radius: 5px;
|
||||
color: #DCDCDC;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #484848, stop: 1 #383838);
|
||||
}
|
||||
|
||||
QToolTip {
|
||||
border: 0px solid #DCDCDC;
|
||||
padding: 1px;
|
||||
color: #DCDCDC;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #484848, stop: 1 #383838);
|
||||
}
|
||||
|
||||
QToolBox::tab:selected {
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #646464, stop: 1 #525252);
|
||||
}
|
||||
|
||||
QPrintPreviewDialog QToolButton {
|
||||
border: 0px solid #DCDCDC;
|
||||
border-radius: 0px;
|
||||
margin: 0px;
|
||||
padding: 3px;
|
||||
background: none;
|
||||
}
|
||||
|
||||
QColorDialog QPushButton,
|
||||
QFileDialog QPushButton {
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
QToolButton#qt_calendar_prevmonth {
|
||||
icon-size: 0px;
|
||||
min-width: 20px;
|
||||
image: url(:/uistyles/psblack/calendar_prevmonth.png);
|
||||
}
|
||||
|
||||
QToolButton#qt_calendar_nextmonth {
|
||||
icon-size: 0px;
|
||||
min-width: 20px;
|
||||
image: url(:/uistyles/psblack/calendar_nextmonth.png);
|
||||
}
|
||||
|
||||
QToolButton#qt_calendar_prevmonth,
|
||||
QToolButton#qt_calendar_nextmonth,
|
||||
QToolButton#qt_calendar_monthbutton,
|
||||
QToolButton#qt_calendar_yearbutton {
|
||||
border: 0px solid #DCDCDC;
|
||||
border-radius: 3px;
|
||||
margin: 3px 3px 3px 3px;
|
||||
padding: 3px;
|
||||
background: none;
|
||||
}
|
||||
|
||||
QToolButton#qt_calendar_prevmonth:hover,
|
||||
QToolButton#qt_calendar_nextmonth:hover,
|
||||
QToolButton#qt_calendar_monthbutton:hover,
|
||||
QToolButton#qt_calendar_yearbutton:hover,
|
||||
QToolButton#qt_calendar_prevmonth:pressed,
|
||||
QToolButton#qt_calendar_nextmonth:pressed,
|
||||
QToolButton#qt_calendar_monthbutton:pressed,
|
||||
QToolButton#qt_calendar_yearbutton:pressed {
|
||||
border: 1px solid #242424;
|
||||
}
|
||||
|
||||
QCalendarWidget QSpinBox#qt_calendar_yearedit {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
QCalendarWidget QToolButton::menu-indicator {
|
||||
image: None;
|
||||
}
|
||||
|
||||
QCalendarWidget QTableView {
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
QCalendarWidget QWidget#qt_calendar_navigationbar {
|
||||
border: 1px solid #242424;
|
||||
border-width: 1px 1px 0px 1px;
|
||||
background: qlineargradient(spread: pad, x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #484848, stop: 1 #383838);
|
||||
}
|
||||
|
||||
QComboBox QAbstractItemView::item {
|
||||
min-height: 20px;
|
||||
min-width: 10px;
|
||||
}
|
||||
|
||||
QTableView[model="true"]::item {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
QTableView QLineEdit,
|
||||
QTableView QComboBox,
|
||||
QTableView QSpinBox,
|
||||
QTableView QDoubleSpinBox,
|
||||
QTableView QDateEdit,
|
||||
QTableView QTimeEdit,
|
||||
QTableView QDateTimeEdit {
|
||||
border-width: 0px;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
QTableView QLineEdit:focus,
|
||||
QTableView QComboBox:focus,
|
||||
QTableView QSpinBox:focus,
|
||||
QTableView QDoubleSpinBox:focus,
|
||||
QTableView QDateEdit:focus,
|
||||
QTableView QTimeEdit:focus,
|
||||
QTableView QDateTimeEdit:focus {
|
||||
border-width: 0px;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
QLineEdit,
|
||||
QTextEdit,
|
||||
QPlainTextEdit,
|
||||
QSpinBox,
|
||||
QDoubleSpinBox,
|
||||
QComboBox,
|
||||
QDateEdit,
|
||||
QTimeEdit,
|
||||
QDateTimeEdit {
|
||||
background: #444444;
|
||||
}
|
||||
|
||||
QTabWidget::pane:top {
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
QTabWidget::pane:bottom {
|
||||
bottom: -1px;
|
||||
}
|
||||
|
||||
QTabWidget::pane:left {
|
||||
right: -1px;
|
||||
}
|
||||
|
||||
QTabWidget::pane:right {
|
||||
left: -1px;
|
||||
}
|
||||
|
||||
*:disabled {
|
||||
background: #444444;
|
||||
border-color: #484848;
|
||||
color: #242424;
|
||||
}
|
||||
|
||||
|
||||
/*TextColor:#DCDCDC*/
|
||||
|
||||
|
||||
/*PanelColor:#444444*/
|
||||
|
||||
|
||||
/*BorderColor:#242424*/
|
||||
|
||||
|
||||
/*NormalColorStart:#484848*/
|
||||
|
||||
|
||||
/*NormalColorEnd:#383838*/
|
||||
|
||||
|
||||
/*DarkColorStart:#646464*/
|
||||
|
||||
|
||||
/*DarkColorEnd:#525252*/
|
||||
|
||||
|
||||
/*HighColor:#00BB9E*/
|
23
libs/uistyles/psblack/psblack.qrc
Normal file
@ -0,0 +1,23 @@
|
||||
<RCC>
|
||||
<qresource prefix="/uistyles">
|
||||
<file>psblack.css</file>
|
||||
<file>psblack/add_bottom.png</file>
|
||||
<file>psblack/add_left.png</file>
|
||||
<file>psblack/add_right.png</file>
|
||||
<file>psblack/add_top.png</file>
|
||||
<file>psblack/branch_close.png</file>
|
||||
<file>psblack/branch_open.png</file>
|
||||
<file>psblack/calendar_nextmonth.png</file>
|
||||
<file>psblack/calendar_prevmonth.png</file>
|
||||
<file>psblack/checkbox_checked.png</file>
|
||||
<file>psblack/checkbox_checked_disable.png</file>
|
||||
<file>psblack/checkbox_parcial.png</file>
|
||||
<file>psblack/checkbox_parcial_disable.png</file>
|
||||
<file>psblack/checkbox_unchecked.png</file>
|
||||
<file>psblack/checkbox_unchecked_disable.png</file>
|
||||
<file>psblack/radiobutton_checked.png</file>
|
||||
<file>psblack/radiobutton_checked_disable.png</file>
|
||||
<file>psblack/radiobutton_unchecked.png</file>
|
||||
<file>psblack/radiobutton_unchecked_disable.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
BIN
libs/uistyles/psblack/psblack/add_bottom.png
Normal file
After Width: | Height: | Size: 201 B |
BIN
libs/uistyles/psblack/psblack/add_left.png
Normal file
After Width: | Height: | Size: 233 B |
BIN
libs/uistyles/psblack/psblack/add_right.png
Normal file
After Width: | Height: | Size: 235 B |
BIN
libs/uistyles/psblack/psblack/add_top.png
Normal file
After Width: | Height: | Size: 197 B |
BIN
libs/uistyles/psblack/psblack/branch_close.png
Normal file
After Width: | Height: | Size: 177 B |
BIN
libs/uistyles/psblack/psblack/branch_open.png
Normal file
After Width: | Height: | Size: 275 B |
BIN
libs/uistyles/psblack/psblack/calendar_nextmonth.png
Normal file
After Width: | Height: | Size: 318 B |
BIN
libs/uistyles/psblack/psblack/calendar_prevmonth.png
Normal file
After Width: | Height: | Size: 314 B |
BIN
libs/uistyles/psblack/psblack/checkbox_checked.png
Normal file
After Width: | Height: | Size: 307 B |
BIN
libs/uistyles/psblack/psblack/checkbox_checked_disable.png
Normal file
After Width: | Height: | Size: 338 B |
BIN
libs/uistyles/psblack/psblack/checkbox_parcial.png
Normal file
After Width: | Height: | Size: 188 B |
BIN
libs/uistyles/psblack/psblack/checkbox_parcial_disable.png
Normal file
After Width: | Height: | Size: 251 B |
BIN
libs/uistyles/psblack/psblack/checkbox_unchecked.png
Normal file
After Width: | Height: | Size: 150 B |
BIN
libs/uistyles/psblack/psblack/checkbox_unchecked_disable.png
Normal file
After Width: | Height: | Size: 152 B |
BIN
libs/uistyles/psblack/psblack/radiobutton_checked.png
Normal file
After Width: | Height: | Size: 756 B |
BIN
libs/uistyles/psblack/psblack/radiobutton_checked_disable.png
Normal file
After Width: | Height: | Size: 932 B |
BIN
libs/uistyles/psblack/psblack/radiobutton_unchecked.png
Normal file
After Width: | Height: | Size: 564 B |
BIN
libs/uistyles/psblack/psblack/radiobutton_unchecked_disable.png
Normal file
After Width: | Height: | Size: 715 B |
4
libs/uistyles/uistyles.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
set(UISTYLE_QRCS
|
||||
${CMAKE_SOURCE_DIR}/libs/uistyles/flatwhite/flatwhite.qrc
|
||||
${CMAKE_SOURCE_DIR}/libs/uistyles/psblack/psblack.qrc
|
||||
)
|
@ -1 +1 @@
|
||||
5756
|
||||
5779
|
||||
|
@ -1 +1 @@
|
||||
2.6.0
|
||||
2.6.1
|
||||
|
@ -348,7 +348,7 @@ namespace Qv2ray
|
||||
|
||||
if (!QDir(QV2RAY_GENERATED_DIR).exists())
|
||||
{
|
||||
// The dir used to generate final config file, for V2ray interaction.
|
||||
// The dir used to generate final config file, for V2Ray interaction.
|
||||
QDir().mkdir(QV2RAY_GENERATED_DIR);
|
||||
LOG(MODULE_INIT, "Created config generation dir at: " + QV2RAY_GENERATED_DIR)
|
||||
}
|
||||
@ -463,8 +463,17 @@ namespace Qv2ray
|
||||
return true;
|
||||
}
|
||||
|
||||
Qv2rayApplication::commandline_status Qv2rayApplication::ParseCommandLine(QString *errorMessage, const QStringList &args)
|
||||
Qv2rayApplication::commandline_status Qv2rayApplication::ParseCommandLine(QString *errorMessage, const QStringList &_argx_)
|
||||
{
|
||||
QStringList filteredArgs;
|
||||
for (const auto &arg : _argx_)
|
||||
{
|
||||
#ifdef Q_OS_MACOS
|
||||
if (arg.contains("-psn"))
|
||||
continue;
|
||||
#endif
|
||||
filteredArgs << arg;
|
||||
}
|
||||
QCommandLineParser parser;
|
||||
//
|
||||
QCommandLineOption noAPIOption("noAPI", tr("Disable gRPC API subsystem"));
|
||||
@ -476,7 +485,7 @@ namespace Qv2ray
|
||||
QCommandLineOption reconnectOption("reconnect", tr("Reconnect last connection"));
|
||||
QCommandLineOption exitOption("exit", tr("Exit Qv2ray"));
|
||||
//
|
||||
parser.setApplicationDescription(tr("Qv2ray - A cross-platform Qt frontend for V2ray."));
|
||||
parser.setApplicationDescription(tr("Qv2ray - A cross-platform Qt frontend for V2Ray."));
|
||||
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
|
||||
//
|
||||
parser.addOption(noAPIOption);
|
||||
@ -491,7 +500,7 @@ namespace Qv2ray
|
||||
auto helpOption = parser.addHelpOption();
|
||||
auto versionOption = parser.addVersionOption();
|
||||
|
||||
if (!parser.parse(args))
|
||||
if (!parser.parse(filteredArgs))
|
||||
{
|
||||
*errorMessage = parser.errorText();
|
||||
return QV2RAY_ERROR;
|
||||
|
@ -181,6 +181,12 @@ namespace Qv2ray::base
|
||||
JSONSTRUCT_REGISTER(ConnectionStatsEntryObject, F(upLinkData, downLinkData))
|
||||
};
|
||||
|
||||
enum ConnectionImportSource
|
||||
{
|
||||
IMPORT_SOURCE_SUBSCRIPTION,
|
||||
IMPORT_SOURCE_MANUAL
|
||||
};
|
||||
|
||||
struct ConnectionStatsObject
|
||||
{
|
||||
ConnectionStatsEntryObject &operator[](StatisticsType i)
|
||||
@ -195,15 +201,6 @@ namespace Qv2ray::base
|
||||
{
|
||||
return JsonStructHelper::___json_struct_store_data(entries);
|
||||
}
|
||||
auto toMap() const
|
||||
{
|
||||
std::map<StatisticsType, QvStatsData> result;
|
||||
for (auto i = 0; i < entries.count(); i++)
|
||||
{
|
||||
result[StatisticsType(i)] = { entries[i].upLinkData, entries[i].downLinkData };
|
||||
}
|
||||
return result;
|
||||
}
|
||||
void loadJson(const QJsonValue &d)
|
||||
{
|
||||
entries.clear();
|
||||
@ -222,12 +219,19 @@ namespace Qv2ray::base
|
||||
{
|
||||
qint64 lastConnected;
|
||||
qint64 latency;
|
||||
ConnectionImportSource importSource;
|
||||
ConnectionStatsObject stats;
|
||||
//
|
||||
int __qvConnectionRefCount;
|
||||
//
|
||||
ConnectionObject() : lastConnected(), latency(LATENCY_TEST_VALUE_NODATA), stats(), __qvConnectionRefCount(0){};
|
||||
JSONSTRUCT_REGISTER(ConnectionObject, F(lastConnected, latency, stats), B(__Qv2rayConfigObjectBase))
|
||||
ConnectionObject()
|
||||
: lastConnected(), //
|
||||
latency(LATENCY_TEST_VALUE_NODATA), //
|
||||
importSource(IMPORT_SOURCE_MANUAL), //
|
||||
stats(), //
|
||||
__qvConnectionRefCount(0) //
|
||||
{};
|
||||
JSONSTRUCT_REGISTER(ConnectionObject, F(lastConnected, latency, importSource, stats), B(__Qv2rayConfigObjectBase))
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -188,7 +188,7 @@ namespace Qv2ray::components::autolaunch
|
||||
ts.setCodec("UTF-8");
|
||||
ts << QLatin1String("[Desktop Entry]") << NEWLINE //
|
||||
<< QLatin1String("Name=") << QCoreApplication::applicationName() + QCoreApplication::arguments().join(" ") << NEWLINE //
|
||||
<< QLatin1String("GenericName=") << QLatin1String("V2ray Frontend") << NEWLINE //
|
||||
<< QLatin1String("GenericName=") << QLatin1String("V2Ray Frontend") << NEWLINE //
|
||||
<< QLatin1String("Exec=") << binPath << NEWLINE //
|
||||
<< QLatin1String("Terminal=") << "false" << NEWLINE //
|
||||
<< QLatin1String("Icon=") << "qv2ray" << NEWLINE //
|
||||
|
@ -109,8 +109,15 @@ namespace Qv2ray::components::latency::icmping
|
||||
memset(&targetAddress, 0, sizeof(targetAddress));
|
||||
targetAddress.sin_family = resolvedAddress->h_addrtype;
|
||||
targetAddress.sin_port = 0;
|
||||
memcpy(&targetAddress.sin_addr, resolvedAddress->h_addr, resolvedAddress->h_length);
|
||||
|
||||
auto src = resolvedAddress->h_addr;
|
||||
if (src == nullptr)
|
||||
{
|
||||
// Buggy GCC detected
|
||||
return { 0, "GCC: COMPILER BUG. Cannot even dereference a char**" };
|
||||
}
|
||||
|
||||
memcpy(&targetAddress.sin_addr, src, resolvedAddress->h_length);
|
||||
// prepare echo request packet
|
||||
icmp _icmp_request;
|
||||
memset(&_icmp_request, 0, sizeof(_icmp_request));
|
||||
|
@ -172,9 +172,9 @@ namespace Qv2ray::core
|
||||
{
|
||||
const auto &inbound = inboundVal.toObject();
|
||||
inboundPorts[inbound["tag"].toString()] = {
|
||||
inbound["protocol"].toString(), //
|
||||
inbound["listen"].toString(), //
|
||||
inbound["port"].toInt() //
|
||||
inbound["protocol"].toString(), //
|
||||
inbound["listen"].toString(), //
|
||||
inbound["port"].toVariant().toInt() //
|
||||
};
|
||||
}
|
||||
return inboundPorts;
|
||||
|
@ -13,12 +13,12 @@ namespace Qv2ray::core::connection::connectionIO
|
||||
{
|
||||
root.remove("inbounds");
|
||||
root.remove("routing");
|
||||
root.remove("dns");
|
||||
}
|
||||
|
||||
root.remove("log");
|
||||
root.remove("api");
|
||||
root.remove("stats");
|
||||
root.remove("dns");
|
||||
return root;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "base/Qv2rayBase.hpp"
|
||||
|
||||
static const inline QStringList V2rayLogLevel = { "none", "debug", "info", "warning", "error" };
|
||||
static const inline QStringList V2RayLogLevel = { "none", "debug", "info", "warning", "error" };
|
||||
|
||||
namespace Qv2ray::core::connection::generation
|
||||
{
|
||||
|
@ -75,8 +75,8 @@ namespace Qv2ray::core::handler
|
||||
tcpingHelper = new LatencyTestHost(5, this);
|
||||
connect(tcpingHelper, &LatencyTestHost::OnLatencyTestCompleted, this, &QvConfigHandler::OnLatencyDataArrived_p);
|
||||
//
|
||||
// Save per 1 minutes.
|
||||
saveTimerId = startTimer(1 * 60 * 1000);
|
||||
// Save per 1 hour.
|
||||
saveTimerId = startTimer(1 * 60 * 60 * 1000);
|
||||
// Do not ping all...
|
||||
pingConnectionTimerId = startTimer(60 * 1000);
|
||||
}
|
||||
@ -616,7 +616,8 @@ namespace Qv2ray::core::handler
|
||||
filteredConnections.count() > 5 ||
|
||||
QvMessageBoxAsk(nullptr, tr("Update Subscription"),
|
||||
tr("%1 out of %n entrie(s) have been filtered out, do you want to continue?", "", _newConnections.count())
|
||||
.arg(filteredConnections.count())) == QMessageBox::Yes;
|
||||
.arg(filteredConnections.count()) +
|
||||
NEWLINE + GetDisplayName(id)) == QMessageBox::Yes;
|
||||
|
||||
for (const auto &config : useFilteredConnections ? filteredConnections : _newConnections)
|
||||
{
|
||||
@ -659,16 +660,27 @@ namespace Qv2ray::core::handler
|
||||
}
|
||||
|
||||
// Check if anything left behind (not being updated or changed significantly)
|
||||
LOG(MODULE_CORE_HANDLER, "Removed old connections not have been matched.")
|
||||
for (const auto &conn : originalConnectionIdList)
|
||||
if (!originalConnectionIdList.isEmpty())
|
||||
{
|
||||
LOG(MODULE_CORE_HANDLER, "Removing connections not in the new subscription: " + conn.toString())
|
||||
RemoveConnectionFromGroup(conn, id);
|
||||
bool needContinue =
|
||||
QvMessageBoxAsk(nullptr, //
|
||||
tr("Update Subscription"),
|
||||
tr("There're %n connection(s) in the group that do not belong the current subscription (any more).", "",
|
||||
originalConnectionIdList.count()) +
|
||||
NEWLINE + GetDisplayName(id) + NEWLINE + tr("Would you like to remove them?")) == QMessageBox::Yes;
|
||||
if (needContinue)
|
||||
{
|
||||
LOG(MODULE_CORE_HANDLER, "Removed old connections not have been matched.")
|
||||
for (const auto &conn : originalConnectionIdList)
|
||||
{
|
||||
LOG(MODULE_CORE_HANDLER, "Removing connections not in the new subscription: " + conn.toString())
|
||||
RemoveConnectionFromGroup(conn, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the time
|
||||
groups[id].lastUpdatedDate = system_clock::to_time_t(system_clock::now());
|
||||
|
||||
return hasErrorOccured;
|
||||
}
|
||||
|
||||
|
@ -10,10 +10,10 @@ namespace Qv2ray::core::handler
|
||||
KernelInstanceHandler::KernelInstanceHandler(QObject *parent) : QObject(parent)
|
||||
{
|
||||
KernelInstance = this;
|
||||
vCoreInstance = new V2rayKernelInstance(this);
|
||||
connect(vCoreInstance, &V2rayKernelInstance::OnNewStatsDataArrived, this, &KernelInstanceHandler::OnV2rayStatsDataRcvd_p);
|
||||
connect(vCoreInstance, &V2rayKernelInstance::OnProcessOutputReadyRead, this, &KernelInstanceHandler::OnKernelLog_p);
|
||||
connect(vCoreInstance, &V2rayKernelInstance::OnProcessErrored, this, &KernelInstanceHandler::OnKernelCrashed_p);
|
||||
vCoreInstance = new V2RayKernelInstance(this);
|
||||
connect(vCoreInstance, &V2RayKernelInstance::OnNewStatsDataArrived, this, &KernelInstanceHandler::OnV2RayStatsDataRcvd_p);
|
||||
connect(vCoreInstance, &V2RayKernelInstance::OnProcessOutputReadyRead, this, &KernelInstanceHandler::OnKernelLog_p);
|
||||
connect(vCoreInstance, &V2RayKernelInstance::OnProcessErrored, this, &KernelInstanceHandler::OnKernelCrashed_p);
|
||||
//
|
||||
auto kernelList = PluginHost->GetPluginKernels();
|
||||
for (const auto &internalName : kernelList.keys())
|
||||
@ -119,7 +119,7 @@ namespace Qv2ray::core::handler
|
||||
//
|
||||
QMap<QvPluginKernel::KernelSetting, QVariant> _inboundSettings;
|
||||
|
||||
LOG(MODULE_VCORE, "V2rayIntegration: " + QSTRN(pluginPort) + " = " + outProtocol)
|
||||
LOG(MODULE_VCORE, "V2RayIntegration: " + QSTRN(pluginPort) + " = " + outProtocol)
|
||||
_inboundSettings[_k::KERNEL_HTTP_ENABLED] = false;
|
||||
_inboundSettings[_k::KERNEL_SOCKS_ENABLED] = true;
|
||||
_inboundSettings[_k::KERNEL_SOCKS_PORT] = pluginPort;
|
||||
@ -157,7 +157,7 @@ namespace Qv2ray::core::handler
|
||||
const auto firstOutboundProtocol = firstOutbound["protocol"].toString();
|
||||
if (GlobalConfig.pluginConfig.v2rayIntegration)
|
||||
{
|
||||
LOG(MODULE_VCORE, "Starting kernels with V2rayIntegration.")
|
||||
LOG(MODULE_VCORE, "Starting kernels with V2RayIntegration.")
|
||||
bool hasAllKernelStarted = true;
|
||||
for (auto &[outboundProtocol, kernelObject] : activeKernels)
|
||||
{
|
||||
@ -181,7 +181,7 @@ namespace Qv2ray::core::handler
|
||||
}
|
||||
currentId = id;
|
||||
//
|
||||
// Also start V2ray-core.
|
||||
// Also start V2Ray-core.
|
||||
auto result = vCoreInstance->StartConnection(fullConfig);
|
||||
//
|
||||
if (result.has_value())
|
||||
@ -198,8 +198,8 @@ namespace Qv2ray::core::handler
|
||||
}
|
||||
else if (outboundKernelMap.contains(firstOutboundProtocol))
|
||||
{
|
||||
// Connections without V2ray Integration will have and ONLY have ONE kernel.
|
||||
LOG(MODULE_CONNECTION, "Starting kernel " + firstOutboundProtocol + " without V2ray Integration")
|
||||
// Connections without V2Ray Integration will have and ONLY have ONE kernel.
|
||||
LOG(MODULE_CONNECTION, "Starting kernel " + firstOutboundProtocol + " without V2Ray Integration")
|
||||
{
|
||||
auto kernel = PluginHost->CreatePluginKernel(outboundKernelMap[firstOutbound["protocol"].toString()]);
|
||||
activeKernels.push_back({ firstOutboundProtocol, std::move(kernel) });
|
||||
@ -243,7 +243,7 @@ namespace Qv2ray::core::handler
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(MODULE_CONNECTION, "Starting V2ray without plugin.")
|
||||
LOG(MODULE_CONNECTION, "Starting V2Ray without plugin.")
|
||||
currentId = id;
|
||||
auto result = vCoreInstance->StartConnection(fullConfig);
|
||||
if (result.has_value())
|
||||
@ -300,7 +300,7 @@ namespace Qv2ray::core::handler
|
||||
activeKernels.clear();
|
||||
}
|
||||
|
||||
void KernelInstanceHandler::OnV2rayStatsDataRcvd_p(const QMap<StatisticsType, QvStatsSpeed> &data)
|
||||
void KernelInstanceHandler::OnV2RayStatsDataRcvd_p(const QMap<StatisticsType, QvStatsSpeed> &data)
|
||||
{
|
||||
if (isConnected)
|
||||
{
|
||||
@ -310,6 +310,6 @@ namespace Qv2ray::core::handler
|
||||
|
||||
void KernelInstanceHandler::OnPluginStatsDataRcvd_p(const long uploadSpeed, const long downloadSpeed)
|
||||
{
|
||||
OnV2rayStatsDataRcvd_p({ { API_OUTBOUND_PROXY, { uploadSpeed, downloadSpeed } } });
|
||||
OnV2RayStatsDataRcvd_p({ { API_OUTBOUND_PROXY, { uploadSpeed, downloadSpeed } } });
|
||||
}
|
||||
} // namespace Qv2ray::core::handler
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "components/plugins/QvPluginHost.hpp"
|
||||
#include "core/CoreUtils.hpp"
|
||||
#include "core/kernel/V2rayKernelInteractions.hpp"
|
||||
#include "core/kernel/V2RayKernelInteractions.hpp"
|
||||
|
||||
#include <QObject>
|
||||
#include <optional>
|
||||
@ -40,7 +40,7 @@ namespace Qv2ray::core::handler
|
||||
private slots:
|
||||
void OnKernelCrashed_p(const QString &msg);
|
||||
void OnKernelLog_p(const QString &log);
|
||||
void OnV2rayStatsDataRcvd_p(const QMap<StatisticsType, QvStatsSpeed> &data);
|
||||
void OnV2RayStatsDataRcvd_p(const QMap<StatisticsType, QvStatsSpeed> &data);
|
||||
void OnPluginStatsDataRcvd_p(const long uploadSpeed, const long downloadSpeed);
|
||||
|
||||
private:
|
||||
@ -70,7 +70,7 @@ namespace Qv2ray::core::handler
|
||||
// Since QMap does not support std::unique_ptr, we use std::map<>
|
||||
std::list<std::pair<QString, std::unique_ptr<QvPluginKernel>>> activeKernels;
|
||||
QMap<QString, InboundInfoObject> inboundInfo;
|
||||
V2rayKernelInstance *vCoreInstance = nullptr;
|
||||
V2RayKernelInstance *vCoreInstance = nullptr;
|
||||
ConnectionGroupPair currentId = {};
|
||||
};
|
||||
inline const KernelInstanceHandler *KernelInstance;
|
||||
|
@ -111,11 +111,11 @@ namespace Qv2ray::core::handler
|
||||
//
|
||||
// BEGIN RUNTIME CONFIG GENERATION
|
||||
// We need copy construct here
|
||||
CONFIGROOT RouteHandler::GenerateFinalConfig(const ConnectionGroupPair &pair) const
|
||||
CONFIGROOT RouteHandler::GenerateFinalConfig(const ConnectionGroupPair &p, bool api) const
|
||||
{
|
||||
return GenerateFinalConfig(ConnectionManager->GetConnectionRoot(pair.connectionId), ConnectionManager->GetGroupRoutingId(pair.groupId));
|
||||
return GenerateFinalConfig(ConnectionManager->GetConnectionRoot(p.connectionId), ConnectionManager->GetGroupRoutingId(p.groupId), api);
|
||||
}
|
||||
CONFIGROOT RouteHandler::GenerateFinalConfig(CONFIGROOT root, const GroupRoutingId &routingId) const
|
||||
CONFIGROOT RouteHandler::GenerateFinalConfig(CONFIGROOT root, const GroupRoutingId &routingId, bool hasAPI) const
|
||||
{
|
||||
const auto &config = configs.contains(routingId) ? configs[routingId] : GlobalConfig.defaultRouteConfig;
|
||||
//
|
||||
@ -134,7 +134,7 @@ namespace Qv2ray::core::handler
|
||||
//
|
||||
// logObject.insert("access", QV2RAY_CONFIG_PATH + QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ACCESS_LOG_FILENAME);
|
||||
// logObject.insert("error", QV2RAY_CONFIG_PATH + QV2RAY_VCORE_LOG_DIRNAME + QV2RAY_VCORE_ERROR_LOG_FILENAME);
|
||||
QJsonIO::SetValue(root, V2rayLogLevel[GlobalConfig.logLevel], "log", "loglevel");
|
||||
QJsonIO::SetValue(root, V2RayLogLevel[GlobalConfig.logLevel], "log", "loglevel");
|
||||
//
|
||||
// Since Qv2ray does not support settings DNS manually for now.
|
||||
// These settings are being added for both complex config AND simple config.
|
||||
@ -382,7 +382,7 @@ namespace Qv2ray::core::handler
|
||||
}
|
||||
|
||||
// Let's process some api features.
|
||||
if (GlobalConfig.kernelConfig.enableAPI)
|
||||
if (hasAPI && GlobalConfig.kernelConfig.enableAPI)
|
||||
{
|
||||
//
|
||||
// Stats
|
||||
|
@ -26,8 +26,8 @@ namespace Qv2ray::core::handler
|
||||
bool SetAdvancedRouteSettings(const GroupRoutingId &id, bool overrideGlobal, const QvConfig_Route &dns);
|
||||
//
|
||||
// Final Config Generation
|
||||
CONFIGROOT GenerateFinalConfig(const ConnectionGroupPair &pair) const;
|
||||
CONFIGROOT GenerateFinalConfig(CONFIGROOT root, const GroupRoutingId &routingId) const;
|
||||
CONFIGROOT GenerateFinalConfig(const ConnectionGroupPair &pair, bool hasAPI = true) const;
|
||||
CONFIGROOT GenerateFinalConfig(CONFIGROOT root, const GroupRoutingId &routingId, bool hasAPI = true) const;
|
||||
// Route Table Generation
|
||||
ROUTING GenerateRoutes(bool enableProxy, bool bypassCN, const QString &outboundTag, const QvConfig_Route &routeConfig) const;
|
||||
|
||||
|
@ -10,7 +10,7 @@ using grpc::Status;
|
||||
|
||||
namespace Qv2ray::core::kernel
|
||||
{
|
||||
constexpr auto QV2RAY_GRPC_ERROR_RETCODE = -1;
|
||||
constexpr auto Qv2ray_GRPC_ERROR_RETCODE = -1;
|
||||
static QvAPIDataTypeConfig DefaultInboundAPIConfig{ { API_INBOUND, { "dokodemo-door", "http", "socks" } } };
|
||||
static QvAPIDataTypeConfig DefaultOutboundAPIConfig{ { API_OUTBOUND_PROXY, { "dns", "http", "mtproto", "shadowsocks", "socks", "vmess" } },
|
||||
{ API_OUTBOUND_DIRECT, { "freedom" } },
|
||||
@ -22,10 +22,10 @@ namespace Qv2ray::core::kernel
|
||||
// It's been expected that you will take hours to fully understand the tricks and hacks lying deeply in this class.
|
||||
//
|
||||
// The API Worker runs as a daemon together with Qv2ray, on a single thread.
|
||||
// They use a flag, running, to indicate if the API worker should go and fetch the statistics from V2ray Core.
|
||||
// They use a flag, running, to indicate if the API worker should go and fetch the statistics from V2Ray Core.
|
||||
//
|
||||
// The flag, running, will be set to true, immediately after the V2ray core reported that it's been started.
|
||||
// and will be set to false right before we stopping V2ray Core.
|
||||
// The flag, running, will be set to true, immediately after the V2Ray core reported that it's been started.
|
||||
// and will be set to false right before we stopping V2Ray Core.
|
||||
//
|
||||
|
||||
APIWorker::APIWorker()
|
||||
@ -101,13 +101,15 @@ namespace Qv2ray::core::kernel
|
||||
if (apiFailCounter == QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD)
|
||||
{
|
||||
LOG(MODULE_VCORE, "API call failure threshold reached, cancelling further API aclls.")
|
||||
emit OnAPIErrored(tr("Failed to get statistics data, please check if V2ray is running properly"));
|
||||
emit OnAPIErrored(tr("Failed to get statistics data, please check if V2Ray is running properly"));
|
||||
apiFailCounter++;
|
||||
QThread::msleep(1000);
|
||||
continue;
|
||||
}
|
||||
else if (apiFailCounter > QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD)
|
||||
{
|
||||
// Ignored future requests.
|
||||
QThread::msleep(1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -118,7 +120,7 @@ namespace Qv2ray::core::kernel
|
||||
const QString prefix = config.type == API_INBOUND ? "inbound" : "outbound";
|
||||
const auto value_up = CallStatsAPIByName(prefix % ">>>" % tag % ">>>traffic>>>uplink");
|
||||
const auto value_down = CallStatsAPIByName(prefix % ">>>" % tag % ">>>traffic>>>downlink");
|
||||
hasError = hasError || value_up == QV2RAY_GRPC_ERROR_RETCODE || value_down == QV2RAY_GRPC_ERROR_RETCODE;
|
||||
hasError = hasError || value_up == Qv2ray_GRPC_ERROR_RETCODE || value_down == Qv2ray_GRPC_ERROR_RETCODE;
|
||||
statsResult[config.type].first += std::max(value_up, 0LL);
|
||||
statsResult[config.type].second += std::max(value_down, 0LL);
|
||||
}
|
||||
@ -145,7 +147,7 @@ namespace Qv2ray::core::kernel
|
||||
if (!status.ok())
|
||||
{
|
||||
LOG(MODULE_VCORE, "API call returns: " + QSTRN(status.error_code()) + " (" + QString::fromStdString(status.error_message()) + ")")
|
||||
return QV2RAY_GRPC_ERROR_RETCODE;
|
||||
return Qv2ray_GRPC_ERROR_RETCODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "V2rayKernelInteractions.hpp"
|
||||
#include "V2RayKernelInteractions.hpp"
|
||||
|
||||
#include "APIBackend.hpp"
|
||||
#include "common/QvHelpers.hpp"
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
namespace Qv2ray::core::kernel
|
||||
{
|
||||
std::pair<bool, std::optional<QString>> V2rayKernelInstance::CheckAndSetCoreExecutableState(const QString &vCorePath)
|
||||
std::pair<bool, std::optional<QString>> V2RayKernelInstance::CheckAndSetCoreExecutableState(const QString &vCorePath)
|
||||
{
|
||||
#ifdef Q_OS_UNIX
|
||||
// For Linux/macOS users: if they cannot execute the core,
|
||||
@ -73,23 +73,23 @@ namespace Qv2ray::core::kernel
|
||||
return { true, tr("Check is skipped") };
|
||||
}
|
||||
|
||||
bool V2rayKernelInstance::ValidateKernel(const QString &vCorePath, const QString &vAssetsPath, QString *message)
|
||||
bool V2RayKernelInstance::ValidateKernel(const QString &vCorePath, const QString &vAssetsPath, QString *message)
|
||||
{
|
||||
QFile coreFile(vCorePath);
|
||||
|
||||
if (!coreFile.exists())
|
||||
{
|
||||
DEBUG(MODULE_VCORE, "V2ray core file cannot be found.")
|
||||
*message = tr("V2ray core executable not found.");
|
||||
DEBUG(MODULE_VCORE, "V2Ray core file cannot be found.")
|
||||
*message = tr("V2Ray core executable not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use open() here to prevent `executing` a folder, which may have the
|
||||
// same name as the V2ray core.
|
||||
// same name as the V2Ray core.
|
||||
if (!coreFile.open(QFile::ReadOnly))
|
||||
{
|
||||
DEBUG(MODULE_VCORE, "V2ray core file cannot be opened, possibly be a folder?")
|
||||
*message = tr("V2ray core file cannot be opened, please ensure there's a file instead of a folder.");
|
||||
DEBUG(MODULE_VCORE, "V2Ray core file cannot be opened, possibly be a folder?")
|
||||
*message = tr("V2Ray core file cannot be opened, please ensure there's a file instead of a folder.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -150,8 +150,8 @@ namespace Qv2ray::core::kernel
|
||||
|
||||
if (!hasGeoIP && !hasGeoSite)
|
||||
{
|
||||
DEBUG(MODULE_VCORE, "V2ray assets path contains none of those two files.")
|
||||
*message = tr("V2ray assets path is not valid.");
|
||||
DEBUG(MODULE_VCORE, "V2Ray assets path contains none of those two files.")
|
||||
*message = tr("V2Ray assets path is not valid.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@ namespace Qv2ray::core::kernel
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if V2ray core returns a version number correctly.
|
||||
// Check if V2Ray core returns a version number correctly.
|
||||
QProcess proc;
|
||||
#ifdef Q_OS_WIN32
|
||||
// nativeArguments are required for Windows platform, without a
|
||||
@ -188,16 +188,16 @@ namespace Qv2ray::core::kernel
|
||||
if (exitCode != 0)
|
||||
{
|
||||
DEBUG(MODULE_VCORE, "VCore failed with an exit code: " + QSTRN(exitCode))
|
||||
*message = tr("V2ray core failed with an exit code: ") + QSTRN(exitCode);
|
||||
*message = tr("V2Ray core failed with an exit code: ") + QSTRN(exitCode);
|
||||
return false;
|
||||
}
|
||||
|
||||
QString output = proc.readAllStandardOutput();
|
||||
LOG(MODULE_VCORE, "V2ray output: " + SplitLines(output).join(";"))
|
||||
LOG(MODULE_VCORE, "V2Ray output: " + SplitLines(output).join(";"))
|
||||
|
||||
if (SplitLines(output).isEmpty())
|
||||
{
|
||||
*message = tr("V2ray core returns empty string.");
|
||||
*message = tr("V2Ray core returns empty string.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -205,21 +205,21 @@ namespace Qv2ray::core::kernel
|
||||
return true;
|
||||
}
|
||||
|
||||
bool V2rayKernelInstance::ValidateConfig(const QString &path)
|
||||
bool V2RayKernelInstance::ValidateConfig(const QString &path)
|
||||
{
|
||||
QString v2rayCheckResult;
|
||||
QString V2RayCheckResult;
|
||||
auto kernelPath = GlobalConfig.kernelConfig.KernelPath();
|
||||
auto assetsPath = GlobalConfig.kernelConfig.AssetsPath();
|
||||
if (ValidateKernel(kernelPath, assetsPath, &v2rayCheckResult))
|
||||
if (ValidateKernel(kernelPath, assetsPath, &V2RayCheckResult))
|
||||
{
|
||||
DEBUG(MODULE_VCORE, "V2ray version: " + v2rayCheckResult)
|
||||
DEBUG(MODULE_VCORE, "V2Ray version: " + V2RayCheckResult)
|
||||
// Append assets location env.
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
env.insert("V2RAY_LOCATION_ASSET", assetsPath);
|
||||
//
|
||||
QProcess process;
|
||||
process.setProcessEnvironment(env);
|
||||
DEBUG(MODULE_VCORE, "Starting V2ray core with test options")
|
||||
DEBUG(MODULE_VCORE, "Starting V2Ray core with test options")
|
||||
process.start(kernelPath, QStringList{ "-test", "-config", path }, QIODevice::ReadWrite | QIODevice::Text);
|
||||
process.waitForFinished();
|
||||
|
||||
@ -237,42 +237,42 @@ namespace Qv2ray::core::kernel
|
||||
}
|
||||
else
|
||||
{
|
||||
QvMessageBoxWarn(nullptr, tr("Cannot start V2ray"), //
|
||||
tr("V2ray core settings is incorrect.") + NEWLINE + NEWLINE + //
|
||||
tr("The error is: ") + NEWLINE + v2rayCheckResult);
|
||||
QvMessageBoxWarn(nullptr, tr("Cannot start V2Ray"), //
|
||||
tr("V2Ray core settings is incorrect.") + NEWLINE + NEWLINE + //
|
||||
tr("The error is: ") + NEWLINE + V2RayCheckResult);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
V2rayKernelInstance::V2rayKernelInstance(QObject *parent) : QObject(parent)
|
||||
V2RayKernelInstance::V2RayKernelInstance(QObject *parent) : QObject(parent)
|
||||
{
|
||||
vProcess = new QProcess();
|
||||
connect(vProcess, &QProcess::readyReadStandardOutput, this,
|
||||
[&]() { emit OnProcessOutputReadyRead(vProcess->readAllStandardOutput().trimmed()); });
|
||||
connect(vProcess, &QProcess::stateChanged, [&](QProcess::ProcessState state) {
|
||||
DEBUG(MODULE_VCORE, "V2ray kernel process status changed: " + QVariant::fromValue(state).toString())
|
||||
DEBUG(MODULE_VCORE, "V2Ray kernel process status changed: " + QVariant::fromValue(state).toString())
|
||||
|
||||
// If V2ray crashed AFTER we start it.
|
||||
// If V2Ray crashed AFTER we start it.
|
||||
if (KernelStarted && state == QProcess::NotRunning)
|
||||
{
|
||||
LOG(MODULE_VCORE, "V2ray kernel crashed.")
|
||||
LOG(MODULE_VCORE, "V2Ray kernel crashed.")
|
||||
StopConnection();
|
||||
emit OnProcessErrored("V2ray kernel crashed.");
|
||||
emit OnProcessErrored("V2Ray kernel crashed.");
|
||||
}
|
||||
});
|
||||
apiWorker = new APIWorker();
|
||||
qRegisterMetaType<StatisticsType>();
|
||||
qRegisterMetaType<QMap<StatisticsType, QvStatsSpeed>>();
|
||||
connect(apiWorker, &APIWorker::onAPIDataReady, this, &V2rayKernelInstance::OnNewStatsDataArrived);
|
||||
connect(apiWorker, &APIWorker::onAPIDataReady, this, &V2RayKernelInstance::OnNewStatsDataArrived);
|
||||
KernelStarted = false;
|
||||
}
|
||||
|
||||
std::optional<QString> V2rayKernelInstance::StartConnection(const CONFIGROOT &root)
|
||||
std::optional<QString> V2RayKernelInstance::StartConnection(const CONFIGROOT &root)
|
||||
{
|
||||
if (KernelStarted)
|
||||
{
|
||||
LOG(MODULE_VCORE, "Status is invalid, expect STOPPED when calling StartConnection")
|
||||
return tr("Invalid V2ray Instance Status.");
|
||||
return tr("Invalid V2Ray Instance Status.");
|
||||
}
|
||||
|
||||
// Write the final configuration to the disk.
|
||||
@ -288,7 +288,7 @@ namespace Qv2ray::core::kernel
|
||||
vProcess->setProcessEnvironment(env);
|
||||
vProcess->start(GlobalConfig.kernelConfig.KernelPath(), { "-config", filePath }, QIODevice::ReadWrite | QIODevice::Text);
|
||||
vProcess->waitForStarted();
|
||||
DEBUG(MODULE_VCORE, "V2ray core started.")
|
||||
DEBUG(MODULE_VCORE, "V2Ray core started.")
|
||||
KernelStarted = true;
|
||||
|
||||
QMap<bool, QMap<QString, QString>> tagProtocolMap;
|
||||
@ -333,11 +333,11 @@ namespace Qv2ray::core::kernel
|
||||
else
|
||||
{
|
||||
KernelStarted = false;
|
||||
return tr("V2ray kernel failed to start.");
|
||||
return tr("V2Ray kernel failed to start.");
|
||||
}
|
||||
}
|
||||
|
||||
void V2rayKernelInstance::StopConnection()
|
||||
void V2RayKernelInstance::StopConnection()
|
||||
{
|
||||
if (apiEnabled)
|
||||
{
|
||||
@ -349,12 +349,12 @@ namespace Qv2ray::core::kernel
|
||||
// to capture the real kernel CRASH
|
||||
KernelStarted = false;
|
||||
vProcess->close();
|
||||
// Block until V2ray core exits
|
||||
// Block until V2Ray core exits
|
||||
// Should we use -1 instead of waiting for 30secs?
|
||||
vProcess->waitForFinished();
|
||||
}
|
||||
|
||||
V2rayKernelInstance::~V2rayKernelInstance()
|
||||
V2RayKernelInstance::~V2RayKernelInstance()
|
||||
{
|
||||
if (KernelStarted)
|
||||
{
|
@ -7,12 +7,12 @@ class QProcess;
|
||||
namespace Qv2ray::core::kernel
|
||||
{
|
||||
class APIWorker;
|
||||
class V2rayKernelInstance : public QObject
|
||||
class V2RayKernelInstance : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit V2rayKernelInstance(QObject *parent = nullptr);
|
||||
~V2rayKernelInstance() override;
|
||||
explicit V2RayKernelInstance(QObject *parent = nullptr);
|
||||
~V2RayKernelInstance() override;
|
||||
//
|
||||
std::optional<QString> StartConnection(const CONFIGROOT &root);
|
||||
void StopConnection();
|
@ -201,7 +201,7 @@ namespace Qv2ray
|
||||
nullptr, QObject::tr("Deprecated"),
|
||||
QObject::tr("PAC is now deprecated and is not encouraged to be used anymore.") + NEWLINE +
|
||||
QObject::tr("It will be removed or be provided as a plugin in the future.") + NEWLINE + NEWLINE +
|
||||
QObject::tr("PAC will still work currently, but please switch to the V2ray built-in routing as soon as possible."));
|
||||
QObject::tr("PAC will still work currently, but please switch to the V2Ray built-in routing as soon as possible."));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
30
src/main.cpp
@ -72,7 +72,7 @@ void signalHandler(int signum)
|
||||
exit(-99);
|
||||
}
|
||||
|
||||
Qv2rayExitCode RunQv2rayApplicationScoped(int argc, char *argv[])
|
||||
QPair<Qv2rayExitCode, std::optional<QString>> RunQv2rayApplicationScoped(int argc, char *argv[])
|
||||
{
|
||||
Qv2rayApplication app(argc, argv);
|
||||
|
||||
@ -80,8 +80,8 @@ Qv2rayExitCode RunQv2rayApplicationScoped(int argc, char *argv[])
|
||||
switch (setupStatus)
|
||||
{
|
||||
case Qv2rayApplication::NORMAL: break;
|
||||
case Qv2rayApplication::SINGLE_APPLICATION: return QV2RAY_SECONDARY_INSTANCE;
|
||||
case Qv2rayApplication::FAILED: return QV2RAY_EARLY_SETUP_FAIL;
|
||||
case Qv2rayApplication::SINGLE_APPLICATION: return { QV2RAY_SECONDARY_INSTANCE, std::nullopt };
|
||||
case Qv2rayApplication::FAILED: return { QV2RAY_EARLY_SETUP_FAIL, app.tr("Qv2ray early initialization failed.") };
|
||||
}
|
||||
|
||||
LOG("LICENCE", NEWLINE //
|
||||
@ -99,12 +99,12 @@ Qv2rayExitCode RunQv2rayApplicationScoped(int argc, char *argv[])
|
||||
if (!app.FindAndCreateInitialConfiguration())
|
||||
{
|
||||
LOG(MODULE_INIT, "Cannot find or create initial configuration file.")
|
||||
return QV2RAY_CONFIG_PATH_FAIL;
|
||||
return { QV2RAY_CONFIG_PATH_FAIL, app.tr("Cannot create initial config file.") };
|
||||
}
|
||||
if (!app.LoadConfiguration())
|
||||
{
|
||||
LOG(MODULE_INIT, "Cannot load existing configuration file.")
|
||||
return QV2RAY_CONFIG_FILE_FAIL;
|
||||
return { QV2RAY_CONFIG_FILE_FAIL, "Configuration file currupted" };
|
||||
}
|
||||
|
||||
// Check OpenSSL version for auto-update and subscriptions
|
||||
@ -123,7 +123,7 @@ Qv2rayExitCode RunQv2rayApplicationScoped(int argc, char *argv[])
|
||||
NEWLINE + QObject::tr("Technical Details") + NEWLINE + //
|
||||
"OSsl.Rq.V=" + osslReqVersion + NEWLINE + //
|
||||
"OSsl.Cr.V=" + osslCurVersion);
|
||||
return QV2RAY_SSL_FAIL;
|
||||
return { QV2RAY_SSL_FAIL, app.tr("Cannot start Qv2ray without OpenSSL") };
|
||||
}
|
||||
|
||||
app.InitializeGlobalVariables();
|
||||
@ -132,7 +132,7 @@ Qv2rayExitCode RunQv2rayApplicationScoped(int argc, char *argv[])
|
||||
signal(SIGUSR1, [](int) { ConnectionManager->RestartConnection(); });
|
||||
signal(SIGUSR2, [](int) { ConnectionManager->StopConnection(); });
|
||||
#endif
|
||||
return app.RunQv2ray();
|
||||
return { app.RunQv2ray(), std::nullopt };
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@ -161,12 +161,26 @@ int main(int argc, char *argv[])
|
||||
//
|
||||
// parse the command line before starting as a Qt application
|
||||
if (!Qv2rayApplication::PreInitialize(argc, argv))
|
||||
{
|
||||
QApplication errorApplication{ argc, argv };
|
||||
QvMessageBoxWarn(nullptr, "Cannot Start Qv2ray!", "Early initialization failed!");
|
||||
return QV2RAY_PRE_INITIALIZE_FAIL;
|
||||
const auto rcode = RunQv2rayApplicationScoped(argc, argv);
|
||||
}
|
||||
const auto &[rcode, str] = RunQv2rayApplicationScoped(argc, argv);
|
||||
if (rcode == QV2RAY_NEW_VERSION)
|
||||
{
|
||||
LOG(MODULE_INIT, "Starting new version of Qv2ray: " + Qv2rayProcessArgument._qvNewVersionPath)
|
||||
QProcess::startDetached(Qv2rayProcessArgument._qvNewVersionPath, {});
|
||||
}
|
||||
else if (str)
|
||||
{
|
||||
QApplication errorApplication{ argc, argv };
|
||||
QvMessageBoxWarn(nullptr, errorApplication.tr("Cannot start Qv2ray"),
|
||||
ACCESS_OPTIONAL_VALUE(str) + //
|
||||
NEWLINE + //
|
||||
NEWLINE + //
|
||||
errorApplication.tr("Qv2ray will now exit!"));
|
||||
}
|
||||
|
||||
return rcode;
|
||||
}
|
||||
|
@ -30,13 +30,6 @@
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidgetx">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Json Editor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QTextEdit" name="jsonEditor">
|
||||
<property name="font">
|
||||
@ -47,6 +40,9 @@
|
||||
<property name="lineWrapMode">
|
||||
<enum>QTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
<property name="acceptRichText">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
@ -63,6 +59,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Json Editor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "core/CoreUtils.hpp"
|
||||
#include "core/connection/ConnectionIO.hpp"
|
||||
#include "core/connection/Generation.hpp"
|
||||
#include "core/handler/ConfigHandler.hpp"
|
||||
#include "ui/common/UIBase.hpp"
|
||||
#include "ui/models/InboundNodeModel.hpp"
|
||||
#include "ui/models/OutboundNodeModel.hpp"
|
||||
@ -97,17 +98,17 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QvDialog(par
|
||||
domainStrategyCombo->setCurrentText(domainStrategy);
|
||||
|
||||
// Show connections in the node graph
|
||||
for (auto in : root["inbounds"].toArray())
|
||||
for (const auto &in : root["inbounds"].toArray())
|
||||
{
|
||||
AddInbound(INBOUND(in.toObject()));
|
||||
}
|
||||
|
||||
for (auto out : root["outbounds"].toArray())
|
||||
for (const auto &out : root["outbounds"].toArray())
|
||||
{
|
||||
AddOutbound(OUTBOUND(out.toObject()));
|
||||
}
|
||||
|
||||
for (auto item : root["routing"].toObject()["rules"].toArray())
|
||||
for (const auto &item : root["routing"].toObject()["rules"].toArray())
|
||||
{
|
||||
AddRule(RuleObject::fromJson(item.toObject()));
|
||||
}
|
||||
@ -120,13 +121,17 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QvDialog(par
|
||||
for (auto _balancer : root["routing"].toObject()["balancers"].toArray())
|
||||
{
|
||||
auto _balancerObject = _balancer.toObject();
|
||||
|
||||
if (!_balancerObject["tag"].toString().isEmpty())
|
||||
{
|
||||
balancers.insert(_balancerObject["tag"].toString(), _balancerObject["selector"].toVariant().toStringList());
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &group : ConnectionManager->AllGroups())
|
||||
{
|
||||
importGroupBtn->addItem(GetDisplayName(group), group.toString());
|
||||
}
|
||||
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
@ -1056,3 +1061,22 @@ void RouteEditor::on_defaultOutboundCombo_currentTextChanged(const QString &arg1
|
||||
LOADINGCHECK
|
||||
defaultOutbound = arg1;
|
||||
}
|
||||
|
||||
void RouteEditor::on_importExistingBtn_clicked()
|
||||
{
|
||||
const auto connId = ConnectionId{ importConnBtn->currentData(Qt::UserRole).toString() };
|
||||
const auto root = ConnectionManager->GetConnectionRoot(connId);
|
||||
auto outbound = root["outbounds"].toArray()[0].toObject();
|
||||
outbound["tag"] = GetDisplayName(connId);
|
||||
AddOutbound(OUTBOUND{ outbound });
|
||||
}
|
||||
|
||||
void RouteEditor::on_importGroupBtn_currentIndexChanged(int)
|
||||
{
|
||||
const auto group = GroupId{ importGroupBtn->currentData(Qt::UserRole).toString() };
|
||||
importConnBtn->clear();
|
||||
for (const auto &connId : ConnectionManager->Connections(group))
|
||||
{
|
||||
importConnBtn->addItem(GetDisplayName(connId), connId.toString());
|
||||
}
|
||||
}
|
||||
|
@ -96,6 +96,10 @@ class RouteEditor
|
||||
|
||||
void on_defaultOutboundCombo_currentTextChanged(const QString &arg1);
|
||||
|
||||
void on_importExistingBtn_clicked();
|
||||
|
||||
void on_importGroupBtn_currentIndexChanged(int index);
|
||||
|
||||
public slots:
|
||||
void onNodeClicked(Node &n);
|
||||
void onConnectionCreated(QtNodes::Connection const &c);
|
||||
|
@ -30,14 +30,14 @@
|
||||
<property name="title">
|
||||
<string>Inbound</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QPushButton" name="addInboundBtn">
|
||||
<property name="toolTip">
|
||||
<string>Add outbound</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add an Inbound</string>
|
||||
<string>Add Inbound</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -47,7 +47,7 @@
|
||||
<string>Add default inbound from global config</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add From Global Settings</string>
|
||||
<string>Add Global Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -59,36 +59,71 @@
|
||||
<property name="title">
|
||||
<string>Outbound</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QPushButton" name="addOutboundBtn">
|
||||
<property name="toolTip">
|
||||
<string>Add outbound</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add an Outbound</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>New Outbound</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addOutboundBtn">
|
||||
<property name="toolTip">
|
||||
<string>Add outbound</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Import</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="insertBlackBtn">
|
||||
<property name="toolTip">
|
||||
<string>Add blackhole outbound</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Blackhole</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="insertDirectBtn">
|
||||
<property name="toolTip">
|
||||
<string>Add Freedom outbound</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Direct / Freedom</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="insertBlackBtn">
|
||||
<property name="toolTip">
|
||||
<string>Add blackhole outbound</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add Black Hole</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="insertDirectBtn">
|
||||
<property name="toolTip">
|
||||
<string>Add Freedom outbound</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add Direct</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Existing Outbound</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="importGroupBtn"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="importConnBtn"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="importExistingBtn">
|
||||
<property name="text">
|
||||
<string>OK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -262,7 +297,7 @@
|
||||
<item row="1" column="1">
|
||||
<widget class="QToolBox" name="toolBox">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_2">
|
||||
<property name="geometry">
|
||||
@ -270,7 +305,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>359</width>
|
||||
<height>535</height>
|
||||
<height>505</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@ -371,8 +406,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>345</width>
|
||||
<height>615</height>
|
||||
<width>347</width>
|
||||
<height>704</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@ -673,11 +708,7 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>addInboundBtn</tabstop>
|
||||
<tabstop>addDefaultBtn</tabstop>
|
||||
<tabstop>addOutboundBtn</tabstop>
|
||||
<tabstop>insertBlackBtn</tabstop>
|
||||
<tabstop>insertDirectBtn</tabstop>
|
||||
<tabstop>editBtn</tabstop>
|
||||
<tabstop>addRouteBtn</tabstop>
|
||||
<tabstop>delBtn</tabstop>
|
||||
|
@ -100,7 +100,7 @@ void ConnectionInfoWidget::ShowDetails(const ConnectionGroupPair &_identifier)
|
||||
QStringList shareLinks;
|
||||
for (const auto &connection : ConnectionManager->Connections(groupId))
|
||||
{
|
||||
shareLinks << ConvertConfigToString({ connection, groupId }, false);
|
||||
shareLinks << ConvertConfigToString({ connection, groupId }, !GlobalConfig.uiConfig.useOldShareLinkFormat);
|
||||
}
|
||||
//
|
||||
auto complexCount = shareLinks.removeAll(QV2RAY_SERIALIZATION_COMPLEX_CONFIG_PLACEHOLDER);
|
||||
|
@ -107,6 +107,7 @@ void ConnectionItemWidget::RecalculateConnectionsCount()
|
||||
{
|
||||
auto connectionCount = ConnectionManager->Connections(groupId).count();
|
||||
latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections")));
|
||||
OnGroupItemRenamed(groupId, "", originalItemName);
|
||||
}
|
||||
|
||||
void ConnectionItemWidget::OnConnected(const ConnectionGroupPair &id)
|
||||
@ -114,7 +115,7 @@ void ConnectionItemWidget::OnConnected(const ConnectionGroupPair &id)
|
||||
if (id == ConnectionGroupPair{ connectionId, groupId })
|
||||
{
|
||||
connNameLabel->setText("• " + originalItemName);
|
||||
LOG(MODULE_UI, "OnConnected signal received for: " + id.connectionId.toString())
|
||||
DEBUG(MODULE_UI, "ConnectionItemWidgetOnConnected signal received for: " + id.connectionId.toString())
|
||||
emit RequestWidgetFocus(this);
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ void GroupManager::onRCMExportConnectionTriggered()
|
||||
auto filePath = d.getSaveFileName(this, GetDisplayName(id));
|
||||
if (filePath.isEmpty())
|
||||
return;
|
||||
auto root = RouteManager->GenerateFinalConfig({ id, currentGroupId });
|
||||
auto root = RouteManager->GenerateFinalConfig({ id, currentGroupId }, false);
|
||||
//
|
||||
// Apply export filter
|
||||
ExportConnectionFilter(root);
|
||||
@ -275,6 +275,16 @@ void GroupManager::on_addGroupButton_clicked()
|
||||
|
||||
void GroupManager::on_updateButton_clicked()
|
||||
{
|
||||
if (subAddrTxt->text().trimmed().isEmpty())
|
||||
{
|
||||
QvMessageBoxWarn(this, tr("Update Subscription"), tr("The subscription link is empty."));
|
||||
return;
|
||||
}
|
||||
if (!QUrl{ subAddrTxt->text() }.isValid())
|
||||
{
|
||||
QvMessageBoxWarn(this, tr("Update Subscription"), tr("The subscription link is invalid."));
|
||||
return;
|
||||
}
|
||||
if (QvMessageBoxAsk(this, tr("Update Subscription"), tr("Would you like to update the subscription?")) == QMessageBox::Yes)
|
||||
{
|
||||
this->setEnabled(false);
|
||||
|
@ -174,6 +174,9 @@
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
|
@ -240,7 +240,7 @@ void ImportConfigWindow::on_beginImportBtn_clicked()
|
||||
bool ImportAsComplex = keepImportedInboundCheckBox->isChecked();
|
||||
QString path = fileLineTxt->text();
|
||||
|
||||
if (!V2rayKernelInstance::ValidateConfig(path))
|
||||
if (!V2RayKernelInstance::ValidateConfig(path))
|
||||
{
|
||||
QvMessageBoxWarn(this, tr("Import config file"), tr("Failed to check the validity of the config file."));
|
||||
return;
|
||||
@ -276,7 +276,7 @@ void ImportConfigWindow::on_selectImageBtn_clicked()
|
||||
}
|
||||
else
|
||||
{
|
||||
vmessConnectionStringTxt->appendPlainText(str.trimmed() + NEWLINE);
|
||||
qrCodeLinkTxt->setText(str.trimmed());
|
||||
}
|
||||
}
|
||||
void ImportConfigWindow::on_errorsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "components/ntp/QvNTPClient.hpp"
|
||||
#include "core/connection/ConnectionIO.hpp"
|
||||
#include "core/handler/ConfigHandler.hpp"
|
||||
#include "core/kernel/V2rayKernelInteractions.hpp"
|
||||
#include "core/kernel/V2RayKernelInteractions.hpp"
|
||||
#include "core/settings/SettingsBackend.hpp"
|
||||
#include "src/plugin-interface/QvPluginInterface.hpp"
|
||||
#include "ui/styles/StyleManager.hpp"
|
||||
@ -144,11 +144,11 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QvDialog(parent), Curren
|
||||
enableAPI->setChecked(CurrentConfig.kernelConfig.enableAPI);
|
||||
statsPortBox->setValue(CurrentConfig.kernelConfig.statsPort);
|
||||
//
|
||||
v2rayOutboundStatsCB->setChecked(CurrentConfig.uiConfig.graphConfig.useOutboundStats);
|
||||
V2RayOutboundStatsCB->setChecked(CurrentConfig.uiConfig.graphConfig.useOutboundStats);
|
||||
hasDirectStatisticsCB->setEnabled(CurrentConfig.uiConfig.graphConfig.useOutboundStats);
|
||||
hasDirectStatisticsCB->setChecked(CurrentConfig.uiConfig.graphConfig.hasDirectStats);
|
||||
//
|
||||
pluginKernelV2rayIntegrationCB->setChecked(CurrentConfig.pluginConfig.v2rayIntegration);
|
||||
pluginKernelV2RayIntegrationCB->setChecked(CurrentConfig.pluginConfig.v2rayIntegration);
|
||||
pluginKernelPortAllocateCB->setValue(CurrentConfig.pluginConfig.portAllocationStart);
|
||||
pluginKernelPortAllocateCB->setEnabled(CurrentConfig.pluginConfig.v2rayIntegration);
|
||||
}
|
||||
@ -213,6 +213,11 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QvDialog(parent), Curren
|
||||
//
|
||||
SET_AUTOSTART_UI_ENABLED(CurrentConfig.autoStartBehavior == AUTO_CONNECTION_FIXED);
|
||||
//
|
||||
if (CurrentConfig.autoStartId.isEmpty())
|
||||
{
|
||||
CurrentConfig.autoStartId.groupId = DefaultGroupId;
|
||||
}
|
||||
//
|
||||
auto autoStartConnId = CurrentConfig.autoStartId.connectionId;
|
||||
auto autoStartGroupId = CurrentConfig.autoStartId.groupId;
|
||||
//
|
||||
@ -455,7 +460,7 @@ void PreferencesWindow::on_localDNSCb_stateChanged(int arg1)
|
||||
void PreferencesWindow::on_selectVAssetBtn_clicked()
|
||||
{
|
||||
NEEDRESTART
|
||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Open V2ray assets folder"), QDir::currentPath());
|
||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Open V2Ray assets folder"), QDir::currentPath());
|
||||
|
||||
if (!dir.isEmpty())
|
||||
{
|
||||
@ -466,7 +471,7 @@ void PreferencesWindow::on_selectVAssetBtn_clicked()
|
||||
|
||||
void PreferencesWindow::on_selectVCoreBtn_clicked()
|
||||
{
|
||||
QString core = QFileDialog::getOpenFileName(this, tr("Open V2ray core file"), QDir::currentPath());
|
||||
QString core = QFileDialog::getOpenFileName(this, tr("Open V2Ray core file"), QDir::currentPath());
|
||||
|
||||
if (!core.isEmpty())
|
||||
{
|
||||
@ -498,17 +503,17 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1)
|
||||
#ifdef Q_OS_LINUX
|
||||
// Setting up tProxy for linux
|
||||
// Steps:
|
||||
// --> 1. Copy V2ray core files to the QV2RAY_TPROXY_VCORE_PATH and QV2RAY_TPROXY_VCTL_PATH dir.
|
||||
// --> 1. Copy V2Ray core files to the QV2RAY_TPROXY_VCORE_PATH and QV2RAY_TPROXY_VCTL_PATH dir.
|
||||
// --> 2. Change GlobalConfig.v2CorePath.
|
||||
// --> 3. Call `pkexec setcap
|
||||
// CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip` on the V2ray core.
|
||||
// CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip` on the V2Ray core.
|
||||
auto const kernelPath = CurrentConfig.kernelConfig.KernelPath();
|
||||
if (arg1 == Qt::Checked)
|
||||
{
|
||||
// We enable it!
|
||||
if (QvMessageBoxAsk(this, tr("Enable tProxy Support"),
|
||||
tr("This will append capabilities to the V2ray executable.") + NEWLINE + NEWLINE +
|
||||
tr("Qv2ray will copy your V2ray core to this path: ") + NEWLINE + QV2RAY_TPROXY_VCORE_PATH + NEWLINE + NEWLINE +
|
||||
tr("This will append capabilities to the V2Ray executable.") + NEWLINE + NEWLINE +
|
||||
tr("Qv2ray will copy your V2Ray core to this path: ") + NEWLINE + QV2RAY_TPROXY_VCORE_PATH + NEWLINE + NEWLINE +
|
||||
tr("If anything goes wrong after enabling this, please check issue #57 or the link below:") + NEWLINE +
|
||||
" https://github.com/Qv2ray/Qv2ray/wiki/FAQ ") != QMessageBox::Yes)
|
||||
{
|
||||
@ -519,14 +524,14 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1)
|
||||
{
|
||||
|
||||
LOG(MODULE_VCORE, "ENABLING tProxy Support")
|
||||
LOG(MODULE_FILEIO, " --> Origin V2ray core file is at: " + kernelPath)
|
||||
LOG(MODULE_FILEIO, " --> Origin V2Ray core file is at: " + kernelPath)
|
||||
auto v2ctlPath = QFileInfo(kernelPath).absolutePath() + "/v2ctl";
|
||||
auto newPath = QFileInfo(QV2RAY_TPROXY_VCORE_PATH).absolutePath();
|
||||
QString mkPathResult = QDir().mkpath(newPath) ? "OK" : "FAILED";
|
||||
LOG(MODULE_FILEIO, " --> mkPath result: " + mkPathResult)
|
||||
//
|
||||
LOG(MODULE_FILEIO, " --> Origin v2ctl file is at: " + v2ctlPath)
|
||||
LOG(MODULE_FILEIO, " --> New V2ray files will be placed in: " + newPath)
|
||||
LOG(MODULE_FILEIO, " --> New V2Ray files will be placed in: " + newPath)
|
||||
//
|
||||
LOG(MODULE_FILEIO, " --> Copying files....")
|
||||
|
||||
@ -552,10 +557,10 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1)
|
||||
}
|
||||
|
||||
QString vCoreresult = QFile(kernelPath).copy(QV2RAY_TPROXY_VCORE_PATH) ? "OK" : "FAILED";
|
||||
LOG(MODULE_FILEIO, " --> V2ray Core: " + vCoreresult)
|
||||
LOG(MODULE_FILEIO, " --> V2Ray Core: " + vCoreresult)
|
||||
//
|
||||
QString vCtlresult = QFile(v2ctlPath).copy(QV2RAY_TPROXY_VCTL_PATH) ? "OK" : "FAILED";
|
||||
LOG(MODULE_FILEIO, " --> V2ray Ctl: " + vCtlresult)
|
||||
LOG(MODULE_FILEIO, " --> V2Ray Ctl: " + vCtlresult)
|
||||
//
|
||||
|
||||
if (vCoreresult == "OK" && vCtlresult == "OK")
|
||||
@ -565,16 +570,16 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1)
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(MODULE_VCORE, "FAILED to copy V2ray files. Aborting.")
|
||||
LOG(MODULE_VCORE, "FAILED to copy V2Ray files. Aborting.")
|
||||
QvMessageBoxWarn(this, tr("Enable tProxy Support"),
|
||||
tr("Qv2ray cannot copy one or both V2ray files from: ") + NEWLINE + NEWLINE + kernelPath + NEWLINE +
|
||||
tr("Qv2ray cannot copy one or both V2Ray files from: ") + NEWLINE + NEWLINE + kernelPath + NEWLINE +
|
||||
v2ctlPath + NEWLINE + NEWLINE + tr("to this path: ") + NEWLINE + newPath);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(MODULE_VCORE, "Skipped removing files since the current V2ray core is in the default path.")
|
||||
LOG(MODULE_VCORE, "Skipped removing files since the current V2Ray core is in the default path.")
|
||||
LOG(MODULE_VCORE, " --> Actually because we don't know where else to obtain the files.")
|
||||
}
|
||||
|
||||
@ -583,7 +588,7 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1)
|
||||
if (ret != 0)
|
||||
{
|
||||
LOG(MODULE_UI, "WARN: setcap exits with code: " + QSTRN(ret))
|
||||
QvMessageBoxWarn(this, tr("Preferences"), tr("Failed to setcap onto V2ray executable. You may need to run `setcap` manually."));
|
||||
QvMessageBoxWarn(this, tr("Preferences"), tr("Failed to setcap onto V2Ray executable. You may need to run `setcap` manually."));
|
||||
}
|
||||
|
||||
CurrentConfig.tProxySupport = true;
|
||||
@ -597,7 +602,7 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1)
|
||||
if (ret != 0)
|
||||
{
|
||||
LOG(MODULE_UI, "WARN: setcap exits with code: " + QSTRN(ret))
|
||||
QvMessageBoxWarn(this, tr("Preferences"), tr("Failed to setcap onto V2ray executable. You may need to run `setcap` manually."));
|
||||
QvMessageBoxWarn(this, tr("Preferences"), tr("Failed to setcap onto V2Ray executable. You may need to run `setcap` manually."));
|
||||
}
|
||||
|
||||
CurrentConfig.tProxySupport = false;
|
||||
@ -698,7 +703,8 @@ void PreferencesWindow::on_setSysProxyCB_stateChanged(int arg1)
|
||||
|
||||
void PreferencesWindow::on_autoStartSubsCombo_currentIndexChanged(const QString &arg1)
|
||||
{
|
||||
LOADINGCHECK if (arg1.isEmpty())
|
||||
LOADINGCHECK
|
||||
if (arg1.isEmpty())
|
||||
{
|
||||
CurrentConfig.autoStartId.clear();
|
||||
autoStartConnCombo->clear();
|
||||
@ -841,14 +847,14 @@ void PreferencesWindow::on_checkVCoreSettings_clicked()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!V2rayKernelInstance::ValidateKernel(vcorePath, vAssetsPath, &result))
|
||||
if (!V2RayKernelInstance::ValidateKernel(vcorePath, vAssetsPath, &result))
|
||||
{
|
||||
QvMessageBoxWarn(this, tr("V2ray Core Settings"), result);
|
||||
QvMessageBoxWarn(this, tr("V2Ray Core Settings"), result);
|
||||
}
|
||||
else
|
||||
{
|
||||
QvMessageBoxInfo(this, tr("V2ray Core Settings"),
|
||||
tr("V2ray path configuration check passed.") + NEWLINE + NEWLINE + tr("Current version of V2ray is: ") + NEWLINE +
|
||||
QvMessageBoxInfo(this, tr("V2Ray Core Settings"),
|
||||
tr("V2Ray path configuration check passed.") + NEWLINE + NEWLINE + tr("Current version of V2Ray is: ") + NEWLINE +
|
||||
result);
|
||||
}
|
||||
}
|
||||
@ -903,7 +909,7 @@ void PreferencesWindow::on_updateChannelCombo_currentIndexChanged(int index)
|
||||
CurrentConfig.updateConfig.ignoredVersion.clear();
|
||||
}
|
||||
|
||||
void PreferencesWindow::on_pluginKernelV2rayIntegrationCB_stateChanged(int arg1)
|
||||
void PreferencesWindow::on_pluginKernelV2RayIntegrationCB_stateChanged(int arg1)
|
||||
{
|
||||
LOADINGCHECK
|
||||
if (KernelInstance->ActivePluginKernelsCount() > 0)
|
||||
@ -963,7 +969,7 @@ void PreferencesWindow::on_setSessionResumptionCB_stateChanged(int arg1)
|
||||
LOADINGCHECK
|
||||
if (arg1 == Qt::Checked)
|
||||
{
|
||||
QvMessageBoxWarn(this, tr("Dangerous Operation"), tr("This will make your TLS fingerpring different from common golang programs."));
|
||||
QvMessageBoxWarn(this, tr("Dangerous Operation"), tr("This will make your TLS fingerpring different from common Golang programs."));
|
||||
}
|
||||
CurrentConfig.advancedConfig.setSessionResumption = arg1 == Qt::Checked;
|
||||
}
|
||||
@ -1100,8 +1106,14 @@ void PreferencesWindow::on_pushButton_clicked()
|
||||
{
|
||||
const auto ntpTitle = tr("NTP Checker");
|
||||
const auto ntpHint = tr("Check date and time from server:");
|
||||
const static QStringList ntpServerList = { "cn.pool.ntp.org", //
|
||||
"cn.ntp.org.cn", //
|
||||
"edu.ntp.org.cn", //
|
||||
"time.pool.aliyun.com", //
|
||||
"time1.cloud.tencent.com", //
|
||||
"ntp.neu.edu.cn" };
|
||||
bool ok = false;
|
||||
QString ntpServer = QInputDialog::getText(this, ntpTitle, ntpHint, QLineEdit::Normal, "202.118.1.46", &ok).trimmed();
|
||||
QString ntpServer = QInputDialog::getItem(this, ntpTitle, ntpHint, ntpServerList, 0, true, &ok).trimmed();
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
@ -1189,7 +1201,7 @@ void PreferencesWindow::on_qvNetworkUATxt_editTextChanged(const QString &arg1)
|
||||
CurrentConfig.networkConfig.userAgent = arg1;
|
||||
}
|
||||
|
||||
void PreferencesWindow::on_v2rayOutboundStatsCB_stateChanged(int arg1)
|
||||
void PreferencesWindow::on_V2RayOutboundStatsCB_stateChanged(int arg1)
|
||||
{
|
||||
hasDirectStatisticsCB->setEnabled(arg1 == Qt::Checked);
|
||||
LOADINGCHECK
|
||||
|
@ -90,7 +90,7 @@ class PreferencesWindow
|
||||
void on_enableAPI_stateChanged(int arg1);
|
||||
void on_startWithLoginCB_stateChanged(int arg1);
|
||||
void on_updateChannelCombo_currentIndexChanged(int index);
|
||||
void on_pluginKernelV2rayIntegrationCB_stateChanged(int arg1);
|
||||
void on_pluginKernelV2RayIntegrationCB_stateChanged(int arg1);
|
||||
void on_pluginKernelPortAllocateCB_valueChanged(int arg1);
|
||||
void on_qvProxyAddressTxt_textEdited(const QString &arg1);
|
||||
void on_qvProxyTypeCombo_currentTextChanged(const QString &arg1);
|
||||
@ -122,10 +122,8 @@ class PreferencesWindow
|
||||
void on_latencyTCPingRB_clicked();
|
||||
void on_latencyICMPingRB_clicked();
|
||||
void on_qvNetworkUATxt_editTextChanged(const QString &arg1);
|
||||
void on_v2rayOutboundStatsCB_stateChanged(int arg1);
|
||||
|
||||
void on_V2RayOutboundStatsCB_stateChanged(int arg1);
|
||||
void on_hasDirectStatisticsCB_stateChanged(int arg1);
|
||||
|
||||
void on_useOldShareLinkFormatCB_stateChanged(int arg1);
|
||||
|
||||
private:
|
||||
|
@ -51,7 +51,7 @@
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="darkThemeLabel">
|
||||
<property name="text">
|
||||
<string>Darkmode UI Icons</string>
|
||||
<string>Adapt Dark Theme</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
@ -68,7 +68,7 @@
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_36">
|
||||
<property name="text">
|
||||
<string>Darkmode Tray Icon</string>
|
||||
<string>Adapt Dark Tray Theme</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
@ -664,7 +664,7 @@ But could damage your server if improperly used.</string>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="vcoresettingsGroupBox">
|
||||
<property name="title">
|
||||
<string>V2ray Core Settings</string>
|
||||
<string>V2Ray Core Settings</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_10">
|
||||
<item row="0" column="0">
|
||||
@ -721,7 +721,7 @@ But could damage your server if improperly used.</string>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_46">
|
||||
<property name="text">
|
||||
<string>V2ray Core Executable Path</string>
|
||||
<string>V2Ray Core Executable Path</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
@ -749,7 +749,7 @@ But could damage your server if improperly used.</string>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>V2ray Assets Directory</string>
|
||||
<string>V2Ray Assets Directory</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
@ -773,7 +773,7 @@ But could damage your server if improperly used.</string>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="checkVCoreSettings">
|
||||
<property name="text">
|
||||
<string>Check V2ray Core Settings</string>
|
||||
<string>Check V2Ray Core Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -787,7 +787,7 @@ But could damage your server if improperly used.</string>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_68">
|
||||
<property name="text">
|
||||
<string>V2ray API Subsystem</string>
|
||||
<string>V2Ray API Subsystem</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
@ -804,7 +804,7 @@ But could damage your server if improperly used.</string>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>V2ray API Port</string>
|
||||
<string>V2Ray API Port</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
@ -833,12 +833,12 @@ But could damage your server if improperly used.</string>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_37">
|
||||
<property name="text">
|
||||
<string>Outbound Statistics (V2ray Core v4.26+)</string>
|
||||
<string>Outbound Statistics (V2Ray Core v4.26+)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="v2rayOutboundStatsCB">
|
||||
<widget class="QCheckBox" name="V2RayOutboundStatsCB">
|
||||
<property name="toolTip">
|
||||
<string>Currently:
|
||||
- vmess/shadowsocks/socks/http will be treated as PROXY.
|
||||
@ -876,7 +876,7 @@ But could damage your server if improperly used.</string>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_62">
|
||||
<property name="text">
|
||||
<string>Enabling V2ray Integration will allow the kernel benefit from the V2ray routing engine.</string>
|
||||
<string>Enabling V2Ray Integration will allow the kernel benefit from the V2Ray routing engine.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
@ -886,7 +886,7 @@ But could damage your server if improperly used.</string>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_57">
|
||||
<property name="text">
|
||||
<string>V2ray Integration</string>
|
||||
<string>V2Ray Integration</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
@ -894,7 +894,7 @@ But could damage your server if improperly used.</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="pluginKernelV2rayIntegrationCB">
|
||||
<widget class="QCheckBox" name="pluginKernelV2RayIntegrationCB">
|
||||
<property name="toolTip">
|
||||
<string>If not checked, these features will be disabled:
|
||||
|
||||
@ -944,7 +944,7 @@ Custom DNS Settings</string>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_64">
|
||||
<property name="text">
|
||||
<string>Only V2ray Core v4.21+ is supported.</string>
|
||||
<string>Only V2Ray Core v4.21+ is supported.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
@ -1537,7 +1537,7 @@ Custom DNS Settings</string>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_75">
|
||||
<property name="text">
|
||||
<string>Use V2ray DNS for Direct Connection</string>
|
||||
<string>Use V2Ray DNS for Direct Connection</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
|
@ -292,6 +292,14 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source>All connections will be moved to default group, do you want to continue?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The subscription link is empty.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The subscription link is invalid.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ImportConfigWindow</name>
|
||||
@ -1210,18 +1218,10 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source>Appearance</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Darkmode UI Icons</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabled</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Darkmode Tray Icon</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>UI Theme</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -1393,26 +1393,10 @@ Qv2ray will give a more accurate latency value if Enabled, but makes it easy to
|
||||
<source>Select</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray Assets Directory</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check V2ray Core Settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Plugin Kernel Settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling V2ray Integration will allow the kernel benefit from the V2ray routing engine.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray Integration</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>If not checked, these features will be disabled:
|
||||
|
||||
@ -1546,10 +1530,6 @@ Custom DNS Settings</source>
|
||||
<source>Bypass Bittorrent Protocol</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use V2ray DNS for Direct Connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use Local DNS</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -1666,42 +1646,18 @@ Custom DNS Settings</source>
|
||||
<source>Invalid tproxy listening ipv6 address.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open V2ray assets folder</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open V2ray core file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable tProxy Support</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will append capabilities to the V2ray executable.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray will copy your V2ray core to this path: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>If anything goes wrong after enabling this, please check issue #57 or the link below:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray cannot copy one or both V2ray files from: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>to this path: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to setcap onto V2ray executable. You may need to run `setcap` manually.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tProxy is not supported on macOS and Windows</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -1726,18 +1682,6 @@ Custom DNS Settings</source>
|
||||
<source>Failed to set auto start option.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray Core Settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray path configuration check passed.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Current version of V2ray is: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Disabling API Subsystem</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -1758,10 +1702,6 @@ Custom DNS Settings</source>
|
||||
<source>You will lose the advantage of TLS and make your connection under MITM attack.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will make your TLS fingerpring different from common golang programs.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will (probably) make it easy to fingerprint your connection.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -1841,32 +1781,10 @@ This won't trigger a fork bomb, however, since Qv2ray works in singleton mo
|
||||
If your V2Ray core filename happened to be 'qv2ray'-something, you are totally free to ignore this warning.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>You may be about to set V2Ray core incorrectly to V2Ray Control executable, which is absolutely not correct.<byte value="xd"/>
|
||||
The filename of V2Ray core is usually 'v2ray' or 'v2ray.exe'. Make sure to choose it wisely.<byte value="xd"/>
|
||||
If you insist to proceed, we're not providing with any support.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray Core Executable Path</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check System Date and Time from the Internet</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray API Subsystem</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray API Port</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Outbound Statistics (V2ray Core v4.26+)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Currently:
|
||||
- vmess/shadowsocks/socks/http will be treated as PROXY.
|
||||
@ -1879,11 +1797,101 @@ If you insist to proceed, we're not providing with any support.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Only V2ray Core v4.21+ is supported.</source>
|
||||
<source>Old Share Link Format</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Old Share Link Format</source>
|
||||
<source>Adapt Dark Theme</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Adapt Dark Tray Theme</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray Core Settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray Core Executable Path</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray Assets Directory</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check V2Ray Core Settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray API Subsystem</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray API Port</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Outbound Statistics (V2Ray Core v4.26+)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling V2Ray Integration will allow the kernel benefit from the V2Ray routing engine.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray Integration</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Only V2Ray Core v4.21+ is supported.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use V2Ray DNS for Direct Connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open V2Ray assets folder</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open V2Ray core file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will append capabilities to the V2Ray executable.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray will copy your V2Ray core to this path: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray cannot copy one or both V2Ray files from: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to setcap onto V2Ray executable. You may need to run `setcap` manually.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray path configuration check passed.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Current version of V2Ray is: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>You may be about to set V2Ray core incorrectly to V2Ray Control executable, which is absolutely not correct.<byte value="xd"/>
|
||||
The filename of V2Ray core is usually 'v2ray' or 'v2ray.exe'. Make sure to choose it wisely.<byte value="xd"/>
|
||||
If you insist to proceed, we're not providing with any support.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will make your TLS fingerpring different from common Golang programs.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
@ -2145,10 +2153,6 @@ If you insist to proceed, we're not providing with any support.</source>
|
||||
<source>It will be removed or be provided as a plugin in the future.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>PAC will still work currently, but please switch to the V2ray built-in routing as soon as possible.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Configuration Upgrade Failed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -2181,6 +2185,10 @@ If you insist to proceed, we're not providing with any support.</source>
|
||||
<source>Unknown state.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>PAC will still work currently, but please switch to the V2Ray built-in routing as soon as possible.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::Qv2rayApplication</name>
|
||||
@ -2293,11 +2301,11 @@ If you insist to proceed, we're not providing with any support.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray - A cross-platform Qt frontend for V2ray.</source>
|
||||
<source>Do not automatically connect</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Do not automatically connect</source>
|
||||
<source>Qv2ray - A cross-platform Qt frontend for V2Ray.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
@ -2394,74 +2402,27 @@ If you insist to proceed, we're not providing with any support.</source>
|
||||
<numerusform>%1 out of %n entries have been filtered out, do you want to continue?</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Would you like to remove them?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>There're %n connection(s) in the group that do not belong the current subscription (any more).</source>
|
||||
<translation>
|
||||
<numerusform>There is %n connection in the group that do not belong to the current subscription any more.</numerusform>
|
||||
<numerusform>There are %n connections in the group that do not belong to the current subscription any more.</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::core::kernel::APIWorker</name>
|
||||
<message>
|
||||
<source>Failed to get statistics data, please check if V2ray is running properly</source>
|
||||
<source>Failed to get statistics data, please check if V2Ray is running properly</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::core::kernel::V2rayKernelInstance</name>
|
||||
<message>
|
||||
<source>V2ray core executable not found.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray core file cannot be opened, please ensure there's a file instead of a folder.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core is incompatible with your platform.<byte value="xd"/>
|
||||
Expected core ABI is %1, but got actual %2.<byte value="xd"/>
|
||||
Maybe you have downloaded the wrong core?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray assets path is not valid.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No geoip.dat in assets path.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No geosite.dat in assets path.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray core failed with an exit code: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray core returns empty string.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Configuration Error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot start V2ray</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray core settings is incorrect.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The error is: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid V2ray Instance Status.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray kernel failed to start.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<name>Qv2ray::core::kernel::V2RayKernelInstance</name>
|
||||
<message>
|
||||
<source>Core file is lacking executable permission for the current user.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -2478,6 +2439,64 @@ Maybe you have downloaded the wrong core?</source>
|
||||
<source>Check is skipped</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core executable not found.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core file cannot be opened, please ensure there's a file instead of a folder.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core is incompatible with your platform.<byte value="xd"/>
|
||||
Expected core ABI is %1, but got actual %2.<byte value="xd"/>
|
||||
Maybe you have downloaded the wrong core?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray assets path is not valid.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No geoip.dat in assets path.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No geosite.dat in assets path.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core failed with an exit code: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core returns empty string.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Configuration Error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot start V2Ray</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core settings is incorrect.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The error is: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid V2Ray Instance Status.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray kernel failed to start.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::ui::widgets::AutoCompleteTextEdit</name>
|
||||
@ -2521,42 +2540,22 @@ Maybe you have downloaded the wrong core?</source>
|
||||
<source>Add outbound</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add an Inbound</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add default inbound from global config</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add From Global Settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Outbound</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add an Outbound</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add blackhole outbound</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add Black Hole</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add Freedom outbound</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add Direct</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Selected Inbound/Outbound Info</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -2857,6 +2856,34 @@ Maybe you have downloaded the wrong core?</source>
|
||||
<source>The new tag has been used, we appended a random string to the tag.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add Inbound</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add Global Settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>New Outbound</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Import</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Blackhole</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Direct / Freedom</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Existing Outbound</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RouteSettingsMatrix</name>
|
||||
|
@ -293,6 +293,14 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source>Would you like to update the subscription?</source>
|
||||
<translation>サブスクリプションを更新しますか?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The subscription link is empty.</source>
|
||||
<translation>このサブスクリプションリンクが空です。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The subscription link is invalid.</source>
|
||||
<translation>このサブスクリプションリンクが無効です。</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ImportConfigWindow</name>
|
||||
@ -1209,14 +1217,6 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source>Enabled</source>
|
||||
<translation>有効</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Darkmode UI Icons</source>
|
||||
<translation>ダークモードUIアイコン</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Darkmode Tray Icon</source>
|
||||
<translation>ダークモードトレイアイコン</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Language</source>
|
||||
<translation>言語</translation>
|
||||
@ -1361,14 +1361,6 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source> lines</source>
|
||||
<translation> 行</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray Assets Directory</source>
|
||||
<translation>V2rayアセットフォルダー</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check V2ray Core Settings</source>
|
||||
<translation>V2ray Core設定を確認する</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>UDP Local IP</source>
|
||||
<translation>UDP ローカル IP</translation>
|
||||
@ -1429,34 +1421,10 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source>Invalid inbound listening address.</source>
|
||||
<translation>無効なインバウンドリスニングアドレス。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open V2ray assets folder</source>
|
||||
<translation>V2rayアセットフォルダーを開く</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open V2ray core file</source>
|
||||
<translation>V2rayコアファイルを開く</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will append capabilities to the V2ray executable.</source>
|
||||
<translation>これにより、V2ray実行可能ファイルに機能が追加されます。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray will copy your V2ray core to this path: </source>
|
||||
<translation>Qv2rayは、V2rayコアを次のパスにコピーします: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>If anything goes wrong after enabling this, please check issue #57 or the link below:</source>
|
||||
<translation>これを有効にした後に何か問題が発生した場合は、問題#57または以下のリンクを確認してください:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray cannot copy one or both V2ray files from: </source>
|
||||
<translation>Qv2rayは、V2rayファイルの一つまたは二つを以下からコピーできません: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to setcap onto V2ray executable. You may need to run `setcap` manually.</source>
|
||||
<translation>V2ray実行可能ファイルへのsetcapに失敗しました。`setcap`を手動で実行する必要がある可能性があります。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tProxy is not supported on macOS and Windows</source>
|
||||
<translation>tProxyはmacOSおよびWindowsではサポートされていません</translation>
|
||||
@ -1469,10 +1437,6 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source>You will lose the advantage of TLS and make your connection under MITM attack.</source>
|
||||
<translation>TLSの保護を失い、MITMの攻撃を受ける可能性が高くなります。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will make your TLS fingerpring different from common golang programs.</source>
|
||||
<translation>これにより、TLS の指紋は一般的な Golang プログラムとは異なるものになります。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will (probably) make it easy to fingerprint your connection.</source>
|
||||
<translation>そのため、(おそらく)あなたの接続が特定しやすくなります。</translation>
|
||||
@ -1485,18 +1449,6 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source>Failed to set auto start option.</source>
|
||||
<translation>自動起動オプションの設定に失敗しました。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray Core Settings</source>
|
||||
<translation>V2ray Core設定</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray path configuration check passed.</source>
|
||||
<translation>V2rayパス構成チェックに通過しました。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Current version of V2ray is: </source>
|
||||
<translation>V2rayの現在のバージョンは次のとおりです: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Bypass CN Mainland</source>
|
||||
<translation>中国本土をバイパス</translation>
|
||||
@ -1565,14 +1517,6 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source>Plugin Kernel Settings</source>
|
||||
<translation>プラグインのカーネル設定</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling V2ray Integration will allow the kernel benefit from the V2ray routing engine.</source>
|
||||
<translation>V2Ray統合を有効にすると、カーネルはV2Rayルーティングエンジンの恩恵を受けることができます。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray Integration</source>
|
||||
<translation>V2Rayの統合</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>If not checked, these features will be disabled:
|
||||
|
||||
@ -1817,10 +1761,6 @@ For example, for updating subscriptions.</source>
|
||||
<source>DNS Settings</source>
|
||||
<translation>DNS設定</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use V2ray DNS for Direct Connection</source>
|
||||
<translation>フリーダムアウトバウンドにはV2Ray DNSを使用</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>You can configure default DNS settings for all simple connection config here.</source>
|
||||
<translation>ここでは、すべてのシンプルな接続設定のデフォルトDNS設定を行うことができます。</translation>
|
||||
@ -1851,34 +1791,10 @@ If your V2Ray core filename happened to be 'qv2ray'-something, you are
|
||||
しかし、Qv2rayはシングルトンモードで動作するため、フォークボムは発生しません。
|
||||
もしあなたのV2Rayコアのファイル名が'qv2ray'などであれば、この警告を無視して構いません。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>You may be about to set V2Ray core incorrectly to V2Ray Control executable, which is absolutely not correct.<byte value="xd"/>
|
||||
The filename of V2Ray core is usually 'v2ray' or 'v2ray.exe'. Make sure to choose it wisely.<byte value="xd"/>
|
||||
If you insist to proceed, we're not providing with any support.</source>
|
||||
<translation>V2Ray coreをV2Ray Control実行ファイルに間違って設定している可能性がありますが、これは絶対に正しくありません。
|
||||
V2Ray coreのファイル名は通常'v2ray'または'v2ray.exe'です。賢明に選択してください。
|
||||
先に進むことをお勧めする場合、サポートを提供しておりません。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray Core Executable Path</source>
|
||||
<translation>V2rayコアのパス</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check System Date and Time from the Internet</source>
|
||||
<translation>インターネットからシステムの日時を確認する</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray API Subsystem</source>
|
||||
<translation>V2ray APIサブシステム</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray API Port</source>
|
||||
<translation>V2ray APIポート</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Outbound Statistics (V2ray Core v4.26+)</source>
|
||||
<translation>アウトバウンド統計(V2ray Core v4.26以降)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Currently:
|
||||
- vmess/shadowsocks/socks/http will be treated as PROXY.
|
||||
@ -1893,14 +1809,106 @@ V2Ray coreのファイル名は通常'v2ray'または'v2ray.exe&a
|
||||
<source>Include Direct Connection</source>
|
||||
<translation>直接接続を含む</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Only V2ray Core v4.21+ is supported.</source>
|
||||
<translation>V2ray Core v4.21以降のみ対応しています。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Old Share Link Format</source>
|
||||
<translation>旧リンク形式</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Adapt Dark Theme</source>
|
||||
<translation>適応ダークテーマ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Adapt Dark Tray Theme</source>
|
||||
<translation>適応ダークトレイのテーマ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray Core Settings</source>
|
||||
<translation>V2Rayコア設定</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray Core Executable Path</source>
|
||||
<translation>V2Ray コアのパス</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray Assets Directory</source>
|
||||
<translation>V2Ray アセットフォルダー</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check V2Ray Core Settings</source>
|
||||
<translation>V2Rayコア設定を確認する</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray API Subsystem</source>
|
||||
<translation>V2Ray APIサブシステム</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray API Port</source>
|
||||
<translation>V2Ray APIポート</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Outbound Statistics (V2Ray Core v4.26+)</source>
|
||||
<translation>アウトバウンド統計(V2Rayコアv4.26以降)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling V2Ray Integration will allow the kernel benefit from the V2Ray routing engine.</source>
|
||||
<translation>V2Ray統合を有効にすると、カーネルはV2Rayルーティングエンジンの恩恵を受けることができます。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray Integration</source>
|
||||
<translation>V2Rayの統合</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Only V2Ray Core v4.21+ is supported.</source>
|
||||
<translation>V2Rayコアv4.21以降のみ対応しています。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use V2Ray DNS for Direct Connection</source>
|
||||
<translation>フリーダムアウトバウンドにはV2Ray DNSを使用</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open V2Ray assets folder</source>
|
||||
<translation>V2Rayアセットフォルダーを開く</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open V2Ray core file</source>
|
||||
<translation>V2Rayコアファイルを開く</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will append capabilities to the V2Ray executable.</source>
|
||||
<translation>これにより、V2Ray実行可能ファイルに機能が追加されます。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray will copy your V2Ray core to this path: </source>
|
||||
<translation>Qv2rayは、V2Rayコアを次のパスにコピーします: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray cannot copy one or both V2Ray files from: </source>
|
||||
<translation>Qv2rayは、V2Rayファイルの一つまたは二つを以下からコピーできません: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to setcap onto V2Ray executable. You may need to run `setcap` manually.</source>
|
||||
<translation>V2Ray実行可能ファイルへのsetcapに失敗しました。`setcap`を手動で実行する必要がある可能性があります。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray path configuration check passed.</source>
|
||||
<translation>V2Rayパス構成チェックに通過しました。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Current version of V2Ray is: </source>
|
||||
<translation>V2Rayの現在のバージョンは次のとおりです: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>You may be about to set V2Ray core incorrectly to V2Ray Control executable, which is absolutely not correct.<byte value="xd"/>
|
||||
The filename of V2Ray core is usually 'v2ray' or 'v2ray.exe'. Make sure to choose it wisely.<byte value="xd"/>
|
||||
If you insist to proceed, we're not providing with any support.</source>
|
||||
<translation>V2RayコアをV2Ray制御実行ファイルに間違って設定している可能性がありますが、これは絶対に正しくありません。
|
||||
V2Rayコアのファイル名は通常'v2ray'または'v2ray.exe'です。賢明に選択してください。
|
||||
先に進むことをお勧めする場合、サポートを提供しておりません。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will make your TLS fingerpring different from common Golang programs.</source>
|
||||
<translation>これにより、TLSのフィンガースプリングが一般的なGolangプログラムとは異なるものになります。</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
@ -2004,10 +2012,6 @@ V2Ray coreのファイル名は通常'v2ray'または'v2ray.exe&a
|
||||
<source>It will be removed or be provided as a plugin in the future.</source>
|
||||
<translation>今後削除されるか、プラグインとして提供されます。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>PAC will still work currently, but please switch to the V2ray built-in routing as soon as possible.</source>
|
||||
<translation>PACは現在も機能しますが、できるだけ早くV2Rayの組み込みルーティングに切り替えてください。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Configuration Upgrade Failed</source>
|
||||
<translation>構成のアップグレードに失敗しました</translation>
|
||||
@ -2196,6 +2200,10 @@ V2Ray coreのファイル名は通常'v2ray'または'v2ray.exe&a
|
||||
<source>Unknown state.</source>
|
||||
<translation>不明な状態。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>PAC will still work currently, but please switch to the V2Ray built-in routing as soon as possible.</source>
|
||||
<translation>PACは現在も機能しますが、できるだけ早くV2Rayの組み込みルーティングに切り替えてください。</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::Qv2rayApplication</name>
|
||||
@ -2307,14 +2315,14 @@ V2Ray coreのファイル名は通常'v2ray'または'v2ray.exe&a
|
||||
<source>Exit Qv2ray</source>
|
||||
<translation>Qv2rayを終了</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray - A cross-platform Qt frontend for V2ray.</source>
|
||||
<translation>Qv2ray - V2Ray用のクロスプラットフォームQtフロントエンド。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Do not automatically connect</source>
|
||||
<translation>自動的に接続しない</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray - A cross-platform Qt frontend for V2Ray.</source>
|
||||
<translation>Qv2ray - V2Ray用のクロスプラットフォームQtフロントエンド。</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::components::QvUpdateChecker</name>
|
||||
@ -2407,76 +2415,26 @@ V2Ray coreのファイル名は通常'v2ray'または'v2ray.exe&a
|
||||
<numerusform>%n 個のエントリのうち %1 個がフィルタリングされましたが、続けますか?</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Would you like to remove them?</source>
|
||||
<translation>撤去しますか?</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>There're %n connection(s) in the group that do not belong the current subscription (any more).</source>
|
||||
<translation>
|
||||
<numerusform>現在のサブスクリプションに属していない接続がグループ内に %n あります。</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::core::kernel::APIWorker</name>
|
||||
<message>
|
||||
<source>Failed to get statistics data, please check if V2ray is running properly</source>
|
||||
<translation>統計データの取得に失敗しました。V2rayが正常に動作しているか確認してください</translation>
|
||||
<source>Failed to get statistics data, please check if V2Ray is running properly</source>
|
||||
<translation>統計データの取得に失敗しました。V2Rayが正常に動作しているか確認してください</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::core::kernel::V2rayKernelInstance</name>
|
||||
<message>
|
||||
<source>V2ray core executable not found.</source>
|
||||
<translation>V2rayコア実行可能ファイルが見つかりません。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray core file cannot be opened, please ensure there's a file instead of a folder.</source>
|
||||
<translation>V2rayコアファイルを開けません。フォルダーの代わりにファイルがあることを確認してください。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core is incompatible with your platform.<byte value="xd"/>
|
||||
Expected core ABI is %1, but got actual %2.<byte value="xd"/>
|
||||
Maybe you have downloaded the wrong core?</source>
|
||||
<translation>V2Rayコアはプラットフォームと互換性がありません。
|
||||
予想されるコアABIは%1ですが、実際は%2でした。
|
||||
間違ったコアをダウンロードした可能性がありませんか?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray assets path is not valid.</source>
|
||||
<translation>V2rayアセットのパスが無効です。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No geoip.dat in assets path.</source>
|
||||
<translation>アセットパスにgeoip.datはありません。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No geosite.dat in assets path.</source>
|
||||
<translation>アセットパスにgeosite.datはありません。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray core failed with an exit code: </source>
|
||||
<translation>V2rayコアがエラー終了しました、終了コード: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray core returns empty string.</source>
|
||||
<translation>V2rayコアは空の文字列を返します。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Configuration Error</source>
|
||||
<translation>構成エラー</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot start V2ray</source>
|
||||
<translation>V2rayを起動できません</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray core settings is incorrect.</source>
|
||||
<translation>V2rayコアの設定が正しくありません。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The error is: </source>
|
||||
<translation>エラーは次のとおりです: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid V2ray Instance Status.</source>
|
||||
<translation>無効なV2rayインスタンスステータス。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray kernel failed to start.</source>
|
||||
<translation>V2rayカーネルの起動に失敗しました。</translation>
|
||||
</message>
|
||||
<name>Qv2ray::core::kernel::V2RayKernelInstance</name>
|
||||
<message>
|
||||
<source>Core file is lacking executable permission for the current user.</source>
|
||||
<translation>コアファイルには、現在のユーザーの実行可能なパーミッションがありません。</translation>
|
||||
@ -2493,6 +2451,66 @@ Maybe you have downloaded the wrong core?</source>
|
||||
<source>Check is skipped</source>
|
||||
<translation>チェックはスキップされます</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core executable not found.</source>
|
||||
<translation>V2Rayコア実行可能ファイルが見つかりません。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core file cannot be opened, please ensure there's a file instead of a folder.</source>
|
||||
<translation>V2Rayコアファイルを開けません。フォルダーの代わりにファイルがあることを確認してください。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core is incompatible with your platform.<byte value="xd"/>
|
||||
Expected core ABI is %1, but got actual %2.<byte value="xd"/>
|
||||
Maybe you have downloaded the wrong core?</source>
|
||||
<translation>V2Rayコアはプラットフォームと互換性がありません。
|
||||
予想されるコアABIは%1ですが、実際は%2でした。
|
||||
間違ったコアをダウンロードした可能性がありませんか?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray assets path is not valid.</source>
|
||||
<translation>V2Rayアセットのパスが無効です。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No geoip.dat in assets path.</source>
|
||||
<translation>アセットパスにgeoip.datはありません。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No geosite.dat in assets path.</source>
|
||||
<translation>アセットパスにgeosite.datはありません。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core failed with an exit code: </source>
|
||||
<translation>V2Rayコアがエラー終了しました、終了コード: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core returns empty string.</source>
|
||||
<translation>V2Rayコアは空の文字列を返します。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Configuration Error</source>
|
||||
<translation>構成エラー</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot start V2Ray</source>
|
||||
<translation>V2Rayを起動できません</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core settings is incorrect.</source>
|
||||
<translation>V2Rayコアの設定が正しくありません。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The error is: </source>
|
||||
<translation>エラーは次のとおりです: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid V2Ray Instance Status.</source>
|
||||
<translation>無効なV2Rayインスタンスステータス。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray kernel failed to start.</source>
|
||||
<translation>V2Rayカーネルの起動に失敗しました。</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::ui::widgets::AutoCompleteTextEdit</name>
|
||||
@ -2628,18 +2646,6 @@ Maybe you have downloaded the wrong core?</source>
|
||||
<source>Inbound</source>
|
||||
<translation>インバウンド</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add From Global Settings</source>
|
||||
<translation>グローバル設定から追加</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add Black Hole</source>
|
||||
<translation>ブラックホールを追加</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add Direct</source>
|
||||
<translation>直接接続を追加</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Selected Inbound/Outbound Info</source>
|
||||
<translation>選択したインバウンド/アウトバウンドの情報</translation>
|
||||
@ -2856,14 +2862,6 @@ Maybe you have downloaded the wrong core?</source>
|
||||
<source>Add Rule</source>
|
||||
<translation>ルールを追加</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add an Inbound</source>
|
||||
<translation>インバウンドを追加する</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add an Outbound</source>
|
||||
<translation>アウトバウンドを追加する</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Misc Settings</source>
|
||||
<translation>その他の設定</translation>
|
||||
@ -2872,6 +2870,34 @@ Maybe you have downloaded the wrong core?</source>
|
||||
<source>Rename</source>
|
||||
<translation>リネーム</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add Inbound</source>
|
||||
<translation>インバウンドを追加</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add Global Settings</source>
|
||||
<translation>グローバル設定を追加</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>New Outbound</source>
|
||||
<translation>アウトバウンドを追加</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Import</source>
|
||||
<translation>インポート</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Blackhole</source>
|
||||
<translation>ブラックホール</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Direct / Freedom</source>
|
||||
<translation>直接・自由</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Existing Outbound</source>
|
||||
<translation>既存のアウトバウンド</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RouteSettingsMatrix</name>
|
||||
|
@ -1,9 +1,7 @@
|
||||
<RCC>
|
||||
<qresource prefix="/translations">
|
||||
<file>en_US.qm</file>
|
||||
<file>ru_RU.qm</file>
|
||||
<file>ja_JP.qm</file>
|
||||
<file>zh_CN.qm</file>
|
||||
<file>es_ES.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -293,6 +293,14 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source>Would you like to update the subscription?</source>
|
||||
<translation>您要更新订阅吗?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The subscription link is empty.</source>
|
||||
<translation>订阅链接为空。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The subscription link is invalid.</source>
|
||||
<translation>订阅链接无效。</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ImportConfigWindow</name>
|
||||
@ -950,7 +958,7 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set as automatically connected</source>
|
||||
<translation>设置为自动链接</translation>
|
||||
<translation>设置为自动连接</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Edit</source>
|
||||
@ -1209,14 +1217,6 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source>Enabled</source>
|
||||
<translation>已启用</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Darkmode UI Icons</source>
|
||||
<translation>深色模式 UI 图标</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Darkmode Tray Icon</source>
|
||||
<translation>深色模式托盘图标</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Language</source>
|
||||
<translation>语言</translation>
|
||||
@ -1353,14 +1353,6 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source> lines</source>
|
||||
<translation> 行</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray Assets Directory</source>
|
||||
<translation>V2ray 资源目录</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check V2ray Core Settings</source>
|
||||
<translation>检查 V2ray 核心设置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>UDP Local IP</source>
|
||||
<translation>UDP 本地IP</translation>
|
||||
@ -1409,34 +1401,10 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source>Invalid inbound listening address.</source>
|
||||
<translation>入站监听地址不可用。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open V2ray assets folder</source>
|
||||
<translation>打开 V2ray 资源文件夹</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open V2ray core file</source>
|
||||
<translation>打开 V2ray 核心文件</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will append capabilities to the V2ray executable.</source>
|
||||
<translation>这会将功能附加到 V2ray 可执行文件。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray will copy your V2ray core to this path: </source>
|
||||
<translation>Qv2ray 会将您的 V2ray 核心复制到以下路径: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>If anything goes wrong after enabling this, please check issue #57 or the link below:</source>
|
||||
<translation>如果有出现任何问题,请参阅 Issue #57 或以下链接:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray cannot copy one or both V2ray files from: </source>
|
||||
<translation>Qv2ray 无法从以下位置复制一个或两个 V2ray 文件: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to setcap onto V2ray executable. You may need to run `setcap` manually.</source>
|
||||
<translation>无法将 Capcap 设置到 V2ray 可执行文件上。 您可能需要手动运行“ setcap”。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tProxy is not supported on macOS and Windows</source>
|
||||
<translation>在 macOS 和 Windows 上不支持 tProxy</translation>
|
||||
@ -1461,18 +1429,6 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source>Failed to set auto start option.</source>
|
||||
<translation>无法设置自动启动选项。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray Core Settings</source>
|
||||
<translation>V2ray 核心设置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray path configuration check passed.</source>
|
||||
<translation>V2ray 路径配置检查通过。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Current version of V2ray is: </source>
|
||||
<translation>V2ray 当前版本是: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Transparent Proxy Settings</source>
|
||||
<translation>透明代理设置</translation>
|
||||
@ -1561,14 +1517,6 @@ This entry is ignored by V2Ray core when using DoH servers.</source>
|
||||
<source>Plugin Kernel Settings</source>
|
||||
<translation>插件内核设置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling V2ray Integration will allow the kernel benefit from the V2ray routing engine.</source>
|
||||
<translation>启用 V2Ray 插件集成将允许核心受益于 V2Ray 的路由引擎。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray Integration</source>
|
||||
<translation>V2Ray 集成</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>If not checked, these features will be disabled:
|
||||
|
||||
@ -1813,10 +1761,6 @@ For example, for updating subscriptions.</source>
|
||||
<source>DNS Settings</source>
|
||||
<translation>DNS 设置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use V2ray DNS for Direct Connection</source>
|
||||
<translation>为直连使用 V2Ray DNS</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>You can configure default DNS settings for all simple connection config here.</source>
|
||||
<translation>你可在此为所有简单连接配置 DNS 设定。</translation>
|
||||
@ -1835,10 +1779,6 @@ But could damage your server if improperly used.</source>
|
||||
<translation>此处的设定可能很有用。
|
||||
但若使用不当,将会造成不良后果。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will make your TLS fingerpring different from common golang programs.</source>
|
||||
<translation>这将让你的 TLS 指纹有异于正常的 Golang 程序。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Watch Out!</source>
|
||||
<translation>小心!</translation>
|
||||
@ -1851,34 +1791,10 @@ If your V2Ray core filename happened to be 'qv2ray'-something, you are
|
||||
然而,这样做并不会触发 Fork 炸弹,因为 Qv2ray 以单例模式工作。
|
||||
若你的 V2Ray 核心文件名恰好是 'qv2ray' 什么的,你完全可以忽略这个警告。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>You may be about to set V2Ray core incorrectly to V2Ray Control executable, which is absolutely not correct.<byte value="xd"/>
|
||||
The filename of V2Ray core is usually 'v2ray' or 'v2ray.exe'. Make sure to choose it wisely.<byte value="xd"/>
|
||||
If you insist to proceed, we're not providing with any support.</source>
|
||||
<translation>您或许要将 V2Ray 核心错误地设置为 V2Ray 控制文件了,这是非常不对的。
|
||||
V2Ray 核心的文件名通常为 'v2ray' 或者 'v2ray.exe'。确保你作出了明智的选择。
|
||||
若您执意继续,请恕吾等无法提供任何保证。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray Core Executable Path</source>
|
||||
<translation>V2ray 核心可执行文件路径</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check System Date and Time from the Internet</source>
|
||||
<translation>联网对时</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray API Subsystem</source>
|
||||
<translation>V2Ray API 子系统</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray API Port</source>
|
||||
<translation>V2Ray API 端口</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Outbound Statistics (V2ray Core v4.26+)</source>
|
||||
<translation>分出站统计 (V2Ray v2.46+)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Currently:
|
||||
- vmess/shadowsocks/socks/http will be treated as PROXY.
|
||||
@ -1894,12 +1810,104 @@ V2Ray 核心的文件名通常为 'v2ray' 或者 'v2ray.exe'
|
||||
<translation>包括直连流量</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Only V2ray Core v4.21+ is supported.</source>
|
||||
<source>Old Share Link Format</source>
|
||||
<translation>旧 VMess 链接格式</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Adapt Dark Theme</source>
|
||||
<translation>适应暗色主题</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Adapt Dark Tray Theme</source>
|
||||
<translation>适应暗色托盘主题</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray Core Settings</source>
|
||||
<translation>V2Ray 核心设置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray Core Executable Path</source>
|
||||
<translation>V2Ray 核心可执行文件路径</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray Assets Directory</source>
|
||||
<translation>V2Ray 资源目录</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check V2Ray Core Settings</source>
|
||||
<translation>检查 V2Ray 核心设置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray API Subsystem</source>
|
||||
<translation>V2Ray API 子系统</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray API Port</source>
|
||||
<translation>V2Ray API 端口</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Outbound Statistics (V2Ray Core v4.26+)</source>
|
||||
<translation>分出站统计 (V2Ray v4.26+)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling V2Ray Integration will allow the kernel benefit from the V2Ray routing engine.</source>
|
||||
<translation>启用 V2Ray 插件集成将允许核心受益于 V2Ray 的路由引擎。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray Integration</source>
|
||||
<translation>V2Ray 集成</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Only V2Ray Core v4.21+ is supported.</source>
|
||||
<translation>仅支持 V2Ray v4.21+。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Old Share Link Format</source>
|
||||
<translation>旧 VMess 链接格式</translation>
|
||||
<source>Use V2Ray DNS for Direct Connection</source>
|
||||
<translation>为直连使用 V2Ray DNS</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open V2Ray assets folder</source>
|
||||
<translation>打开 V2Ray 资源文件夹</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open V2Ray core file</source>
|
||||
<translation>打开 V2Ray 核心文件</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will append capabilities to the V2Ray executable.</source>
|
||||
<translation>这会将功能附加到 V2Ray 可执行文件。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray will copy your V2Ray core to this path: </source>
|
||||
<translation>Qv2ray 会将您的 V2Ray 核心复制到以下路径: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray cannot copy one or both V2Ray files from: </source>
|
||||
<translation>Qv2ray 无法从以下位置复制一个或两个 V2Ray 文件: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to setcap onto V2Ray executable. You may need to run `setcap` manually.</source>
|
||||
<translation>无法为 V2Ray 可执行文件应用 setcap。您可能需要手动运行 setcap。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray path configuration check passed.</source>
|
||||
<translation>V2Ray 路径配置检查通过。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Current version of V2Ray is: </source>
|
||||
<translation>V2Ray 当前版本是: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>You may be about to set V2Ray core incorrectly to V2Ray Control executable, which is absolutely not correct.<byte value="xd"/>
|
||||
The filename of V2Ray core is usually 'v2ray' or 'v2ray.exe'. Make sure to choose it wisely.<byte value="xd"/>
|
||||
If you insist to proceed, we're not providing with any support.</source>
|
||||
<translation>您或许要将 V2Ray 的核心可执行文件错误地设置成 V2Ray 控制文件了,这是非常不对的。
|
||||
V2Ray 核心可执行文件的文件名通常是 'v2ray' 或者 'v2ray.exe'。确保你作出了正确的选择。
|
||||
若您执意继续,我们将不提供任何支持。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This will make your TLS fingerpring different from common Golang programs.</source>
|
||||
<translation>这将使你的 TLS 指纹有异于正常的 Golang 程序。</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1956,10 +1964,6 @@ V2Ray 核心的文件名通常为 'v2ray' 或者 'v2ray.exe'
|
||||
<source>It will be removed or be provided as a plugin in the future.</source>
|
||||
<translation>它可能会在将来某个版本被移除,或者作为单独的插件提供。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>PAC will still work currently, but please switch to the V2ray built-in routing as soon as possible.</source>
|
||||
<translation>PAC 目前将会继续工作,但是我们强烈建议您切换使用 V2ray 自带的路由功能。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Configuration Upgrade Failed</source>
|
||||
<translation>配置升级失败</translation>
|
||||
@ -2196,6 +2200,10 @@ V2Ray 核心的文件名通常为 'v2ray' 或者 'v2ray.exe'
|
||||
<source>Unknown state.</source>
|
||||
<translation>未知状态。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>PAC will still work currently, but please switch to the V2Ray built-in routing as soon as possible.</source>
|
||||
<translation>PAC 目前将会继续工作,但是我们强烈建议您切换使用 V2Ray 自带的路由功能。</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::Qv2rayApplication</name>
|
||||
@ -2307,14 +2315,14 @@ V2Ray 核心的文件名通常为 'v2ray' 或者 'v2ray.exe'
|
||||
<source>Exit Qv2ray</source>
|
||||
<translation>退出 Qv2ray</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray - A cross-platform Qt frontend for V2ray.</source>
|
||||
<translation>Qv2ray - 一个 V2Ray 的跨平台 Qt 前端。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Do not automatically connect</source>
|
||||
<translation>不要自动连接节点</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Qv2ray - A cross-platform Qt frontend for V2Ray.</source>
|
||||
<translation>Qv2ray - 一个 V2Ray 的跨平台 Qt 前端。</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::components::QvUpdateChecker</name>
|
||||
@ -2407,76 +2415,26 @@ V2Ray 核心的文件名通常为 'v2ray' 或者 'v2ray.exe'
|
||||
<numerusform>%n 条中过滤出 %1 条项目,要继续吗?</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Would you like to remove them?</source>
|
||||
<translation>要移除这些节点吗?</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>There're %n connection(s) in the group that do not belong the current subscription (any more).</source>
|
||||
<translation>
|
||||
<numerusform>分组中有 %n 条连接不包含在订阅中。</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::core::kernel::APIWorker</name>
|
||||
<message>
|
||||
<source>Failed to get statistics data, please check if V2ray is running properly</source>
|
||||
<source>Failed to get statistics data, please check if V2Ray is running properly</source>
|
||||
<translation>无法获取统计数据,请检查 V2Ray 核心是否在正常运行</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::core::kernel::V2rayKernelInstance</name>
|
||||
<message>
|
||||
<source>V2ray core executable not found.</source>
|
||||
<translation>V2ray 核心可执行文件未找到。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray core file cannot be opened, please ensure there's a file instead of a folder.</source>
|
||||
<translation>无法打开 V2ray 核心文件,请检查对应的文件存在而不是文件夹。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core is incompatible with your platform.<byte value="xd"/>
|
||||
Expected core ABI is %1, but got actual %2.<byte value="xd"/>
|
||||
Maybe you have downloaded the wrong core?</source>
|
||||
<translation>V2Ray 核心与您的平台不兼容。
|
||||
期待的核心 ABI 为 %1,但实际为 %2。
|
||||
您也许下载了错误的核心?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray assets path is not valid.</source>
|
||||
<translation>V2ray Assets 路径不可用。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No geoip.dat in assets path.</source>
|
||||
<translation>没有在 Assets 路径找到 geoip.dat。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No geosite.dat in assets path.</source>
|
||||
<translation>没有在 Assets 路径找到 geosite.dat。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray core failed with an exit code: </source>
|
||||
<translation>V2ray 核心退出代码: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray core returns empty string.</source>
|
||||
<translation>V2ray 核心返回空字符串。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Configuration Error</source>
|
||||
<translation>配置错误</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot start V2ray</source>
|
||||
<translation>无法启动 V2ray</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray core settings is incorrect.</source>
|
||||
<translation>V2ray 核心设置不正确。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The error is: </source>
|
||||
<translation>错误是: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid V2ray Instance Status.</source>
|
||||
<translation>V2ray 实例状态无效。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2ray kernel failed to start.</source>
|
||||
<translation>V2ray 核心启动失败。</translation>
|
||||
</message>
|
||||
<name>Qv2ray::core::kernel::V2RayKernelInstance</name>
|
||||
<message>
|
||||
<source>Core file is lacking executable permission for the current user.</source>
|
||||
<translation>当前用户没有 V2Ray 核心文件的执行权限。</translation>
|
||||
@ -2493,6 +2451,66 @@ Maybe you have downloaded the wrong core?</source>
|
||||
<source>Check is skipped</source>
|
||||
<translation>检查已跳过</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core executable not found.</source>
|
||||
<translation>V2Ray 核心可执行文件未找到。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core file cannot be opened, please ensure there's a file instead of a folder.</source>
|
||||
<translation>无法打开 V2Ray 核心文件,请检查对应的文件存在而不是文件夹。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core is incompatible with your platform.<byte value="xd"/>
|
||||
Expected core ABI is %1, but got actual %2.<byte value="xd"/>
|
||||
Maybe you have downloaded the wrong core?</source>
|
||||
<translation>V2Ray 核心与您的平台不兼容。
|
||||
期待的核心 ABI 为 %1,但实际为 %2。
|
||||
您也许下载了错误的核心?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray assets path is not valid.</source>
|
||||
<translation>V2Ray 资源文件路径不可用。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No geoip.dat in assets path.</source>
|
||||
<translation>没有在 V2Ray 资源文件路径找到 geoip.dat。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No geosite.dat in assets path.</source>
|
||||
<translation>没有在 V2Ray 资源文件路径找到 geosite.dat。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core failed with an exit code: </source>
|
||||
<translation>V2Ray 核心退出代码: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core returns empty string.</source>
|
||||
<translation>V2Ray 核心返回空字符串。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Configuration Error</source>
|
||||
<translation>配置错误</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot start V2Ray</source>
|
||||
<translation>无法启动 V2Ray</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray core settings is incorrect.</source>
|
||||
<translation>V2Ray 核心设置不正确。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The error is: </source>
|
||||
<translation>错误如下: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid V2Ray Instance Status.</source>
|
||||
<translation>V2Ray 实例状态无效。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>V2Ray kernel failed to start.</source>
|
||||
<translation>V2Ray 核心启动失败。</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Qv2ray::ui::widgets::AutoCompleteTextEdit</name>
|
||||
@ -2628,18 +2646,6 @@ Maybe you have downloaded the wrong core?</source>
|
||||
<source>Inbound</source>
|
||||
<translation>入站</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add From Global Settings</source>
|
||||
<translation>从全局设置添加</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add Black Hole</source>
|
||||
<translation>添加黑洞</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add Direct</source>
|
||||
<translation>添加直连</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Selected Inbound/Outbound Info</source>
|
||||
<translation>选定进出站信息</translation>
|
||||
@ -2856,14 +2862,6 @@ Maybe you have downloaded the wrong core?</source>
|
||||
<source>Add Rule</source>
|
||||
<translation>添加路由规则</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add an Inbound</source>
|
||||
<translation>添加一个入站</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add an Outbound</source>
|
||||
<translation>添加一个出站</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Misc Settings</source>
|
||||
<translation>杂项设置</translation>
|
||||
@ -2872,6 +2870,34 @@ Maybe you have downloaded the wrong core?</source>
|
||||
<source>Rename</source>
|
||||
<translation>重命名</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add Inbound</source>
|
||||
<translation>添加入站</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add Global Settings</source>
|
||||
<translation>添加全局设置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>New Outbound</source>
|
||||
<translation>新建出站</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Import</source>
|
||||
<translation>导入</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Blackhole</source>
|
||||
<translation>黑洞</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Direct / Freedom</source>
|
||||
<translation>直连 / 自由</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Existing Outbound</source>
|
||||
<translation>现有节点</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RouteSettingsMatrix</name>
|
||||
@ -3230,7 +3256,7 @@ Maybe you have downloaded the wrong core?</source>
|
||||
</message>
|
||||
<message>
|
||||
<source>This group is a subscription</source>
|
||||
<translation>此分组是是一个订阅</translation>
|
||||
<translation>此分组是一个订阅</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Name</source>
|
||||
|