mirror of
https://github.com/zhuzichu520/FluentUI.git
synced 2025-07-04 09:05:30 +08:00
Compare commits
47 Commits
1.7.4
...
74f265dd41
Author | SHA1 | Date | |
---|---|---|---|
74f265dd41 | |||
c36515f19c | |||
2d4e61445e | |||
cc79854191 | |||
500efa6298 | |||
355332da96 | |||
a0d662a8a5 | |||
aecc3fe3b4 | |||
3554fb99cd | |||
24fdff7e35 | |||
d2fdd08604 | |||
1f5d6ce1aa | |||
5fd7c7d10e | |||
83507a6ed5 | |||
789d9164a1 | |||
cb44759978 | |||
04c52b1b25 | |||
b8ef9169b9 | |||
c7de653ba2 | |||
2ddb7e3290 | |||
e8d79e3c7b | |||
bc4510077f | |||
179bc8b21f | |||
8fe4e3b047 | |||
a443f3a9ba | |||
1a0f2afee0 | |||
c9c737f2fc | |||
f0f00b9eba | |||
956f2e0ad0 | |||
ecd13a9cca | |||
17bfff2346 | |||
295dcf02c4 | |||
f701f97756 | |||
2c4cf82f63 | |||
e8c47e0fd8 | |||
9296b18606 | |||
481e19c8cc | |||
44f7948df3 | |||
0ab315e258 | |||
44acdbcf7f | |||
3997daaa11 | |||
531f659e59 | |||
3f6ef13cd0 | |||
96fef84c2d | |||
a3f375c9ef | |||
6a31e86505 | |||
6ebd659e13 |
4
.github/workflows/windows-mingw.yml
vendored
4
.github/workflows/windows-mingw.yml
vendored
@ -91,14 +91,14 @@ jobs:
|
||||
if: startsWith(github.event.ref, 'refs/tags/')
|
||||
uses: zhuzichu520/inno-setup-action@v1.0.1
|
||||
with:
|
||||
filepath: ./action-cli/InstallerScript.iss
|
||||
filepath: ./package/InstallerScript.iss
|
||||
|
||||
- name: uploadRelease
|
||||
if: startsWith(github.event.ref, 'refs/tags/')
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ./action-cli/installer.exe
|
||||
file: ./package/installer.exe
|
||||
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.exe
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
4
.github/workflows/windows-qt5.yml
vendored
4
.github/workflows/windows-qt5.yml
vendored
@ -78,14 +78,14 @@ jobs:
|
||||
if: startsWith(github.event.ref, 'refs/tags/')
|
||||
uses: zhuzichu520/inno-setup-action@v1.0.1
|
||||
with:
|
||||
filepath: ./action-cli/InstallerScript.iss
|
||||
filepath: ./package/InstallerScript.iss
|
||||
|
||||
- name: uploadRelease
|
||||
if: startsWith(github.event.ref, 'refs/tags/')
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ./action-cli/installer.exe
|
||||
file: ./package/installer.exe
|
||||
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.exe
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
4
.github/workflows/windows.yml
vendored
4
.github/workflows/windows.yml
vendored
@ -85,14 +85,14 @@ jobs:
|
||||
if: startsWith(github.event.ref, 'refs/tags/')
|
||||
uses: zhuzichu520/inno-setup-action@v1.0.1
|
||||
with:
|
||||
filepath: ./action-cli/InstallerScript.iss
|
||||
filepath: ./package/InstallerScript.iss
|
||||
|
||||
- name: uploadRelease
|
||||
if: startsWith(github.event.ref, 'refs/tags/')
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ./action-cli/installer.exe
|
||||
file: ./package/installer.exe
|
||||
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.exe
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -36,10 +36,8 @@ bin
|
||||
build
|
||||
cmake-build-*
|
||||
.idea
|
||||
|
||||
package
|
||||
example/Version.h
|
||||
|
||||
action-cli
|
||||
dist
|
||||
|
||||
*.qm
|
@ -2,13 +2,13 @@ cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
project(FluentUI VERSION 1.0)
|
||||
|
||||
if(MSVC)
|
||||
if (MSVC)
|
||||
#让Release也生成pdb文件
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/.cmake/)
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/.cmake/)
|
||||
|
||||
include(GetGitRevisionDescription)
|
||||
|
||||
@ -22,8 +22,8 @@ add_subdirectory(src)
|
||||
|
||||
#Release也支持日志打印代码位置
|
||||
target_compile_definitions(fluentuiplugin
|
||||
PRIVATE
|
||||
QT_MESSAGELOGCONTEXT
|
||||
PRIVATE
|
||||
QT_MESSAGELOGCONTEXT
|
||||
)
|
||||
|
||||
if (FLUENTUI_BUILD_EXAMPLES)
|
||||
|
@ -10,68 +10,68 @@ set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
#判断FluentUI库类型
|
||||
if(FLUENTUI_BUILD_STATIC_LIB)
|
||||
if (FLUENTUI_BUILD_STATIC_LIB)
|
||||
add_definitions(-DFLUENTUI_BUILD_STATIC_LIB)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
#设置可执行文件输出目录
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE})
|
||||
|
||||
if(APPLE)
|
||||
if (APPLE)
|
||||
set(APPLICATION_DIR_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.app/Contents/MacOS)
|
||||
else()
|
||||
else ()
|
||||
set(APPLICATION_DIR_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
#导入Qt相关依赖包
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Quick Svg Network)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Quick Svg Network)
|
||||
|
||||
#添加国际化脚本
|
||||
find_program(QT_LUPDATE NAMES lupdate)
|
||||
find_program(QT_LRELEASE NAMES lrelease)
|
||||
find_program(QT_LUPDATE NAMES lupdate lupdate-qt6)
|
||||
find_program(QT_LRELEASE NAMES lrelease lrelease-qt6)
|
||||
file(GLOB TS_FILE_PATHS ${CMAKE_CURRENT_LIST_DIR}/ *.ts)
|
||||
add_custom_target(Script-UpdateTranslations
|
||||
COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts ${PROJECT_NAME}_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts ${PROJECT_NAME}_zh_CN.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
COMMAND ${QT_LRELEASE} ${PROJECT_NAME}_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
COMMAND ${QT_LRELEASE} ${PROJECT_NAME}_zh_CN.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${APPLICATION_DIR_PATH}/i18n
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_NAME}_en_US.qm ${PROJECT_NAME}_zh_CN.qm ${APPLICATION_DIR_PATH}/i18n
|
||||
SOURCES ${TS_FILE_PATHS}
|
||||
COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts ${PROJECT_NAME}_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts ${PROJECT_NAME}_zh_CN.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
COMMAND ${QT_LRELEASE} ${PROJECT_NAME}_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
COMMAND ${QT_LRELEASE} ${PROJECT_NAME}_zh_CN.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${APPLICATION_DIR_PATH}/i18n
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_NAME}_en_US.qm ${PROJECT_NAME}_zh_CN.qm ${APPLICATION_DIR_PATH}/i18n
|
||||
SOURCES ${TS_FILE_PATHS}
|
||||
)
|
||||
|
||||
##生成版本信息头文件
|
||||
set(HEADER_FILE_VERSION_PATH ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/Version.h)
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/.cmake/Version.h.in
|
||||
${HEADER_FILE_VERSION_PATH}
|
||||
${CMAKE_SOURCE_DIR}/.cmake/Version.h.in
|
||||
${HEADER_FILE_VERSION_PATH}
|
||||
)
|
||||
|
||||
#遍历所有Cpp文件
|
||||
file(GLOB_RECURSE CPP_FILES *.cpp *.h)
|
||||
foreach(filepath ${CPP_FILES})
|
||||
foreach (filepath ${CPP_FILES})
|
||||
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
|
||||
list(APPEND sources_files ${filename})
|
||||
endforeach(filepath)
|
||||
endforeach (filepath)
|
||||
|
||||
if(WIN32)
|
||||
if (WIN32)
|
||||
list(APPEND sources_files "src/app_dmp.h")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
#如果是Windows平台,则生成rc文件,还有inno setup脚本文件
|
||||
set(EXAMPLE_VERSION_RC_PATH "")
|
||||
if(WIN32)
|
||||
if (WIN32)
|
||||
set(EXAMPLE_VERSION_RC_PATH ${CMAKE_CURRENT_BINARY_DIR}/version_${PROJECT_NAME}.rc)
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/.cmake/version_exe.rc.in
|
||||
${EXAMPLE_VERSION_RC_PATH}
|
||||
${CMAKE_SOURCE_DIR}/.cmake/version_exe.rc.in
|
||||
${EXAMPLE_VERSION_RC_PATH}
|
||||
)
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/.cmake/InstallerScript.iss.in
|
||||
${CMAKE_SOURCE_DIR}/action-cli/InstallerScript.iss
|
||||
)
|
||||
endif()
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/.cmake/InstallerScript.iss.in
|
||||
${CMAKE_SOURCE_DIR}/package/InstallerScript.iss
|
||||
)
|
||||
endif ()
|
||||
|
||||
#加快qrc编译
|
||||
qt_add_big_resources(QRC_RESOURCES ${PROJECT_NAME}.qrc)
|
||||
@ -80,34 +80,34 @@ set_property(SOURCE ${PROJECT_NAME}.qrc PROPERTY SKIP_AUTORCC ON)
|
||||
list(APPEND sources_files ${QRC_RESOURCES})
|
||||
|
||||
#添加可执行文件
|
||||
if(WIN32)
|
||||
if (WIN32)
|
||||
list(APPEND sources_files ${EXAMPLE_VERSION_RC_PATH})
|
||||
endif()
|
||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
endif ()
|
||||
if (${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
qt_add_executable(${PROJECT_NAME}
|
||||
MANUAL_FINALIZATION
|
||||
${sources_files}
|
||||
MANUAL_FINALIZATION
|
||||
${sources_files}
|
||||
)
|
||||
else()
|
||||
else ()
|
||||
add_executable(${PROJECT_NAME}
|
||||
${sources_files}
|
||||
${sources_files}
|
||||
)
|
||||
endif()
|
||||
endif ()
|
||||
add_dependencies(${PROJECT_NAME} Script-UpdateTranslations)
|
||||
|
||||
#复制程序运行所需要的动态库
|
||||
if(WIN32)
|
||||
if(MSVC)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
if (WIN32)
|
||||
if (MSVC)
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
file(GLOB_RECURSE 3RDPARTY_DLL_DIR ${CMAKE_SOURCE_DIR}/3rdparty/msvc/x86/*.dll)
|
||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
file(GLOB_RECURSE 3RDPARTY_DLL_DIR ${CMAKE_SOURCE_DIR}/3rdparty/msvc/x64/*.dll)
|
||||
endif()
|
||||
elseif(MINGW)
|
||||
endif ()
|
||||
elseif (MINGW)
|
||||
file(GLOB_RECURSE 3RDPARTY_DLL_DIR ${CMAKE_SOURCE_DIR}/3rdparty/mingw/*.dll)
|
||||
endif()
|
||||
endif ()
|
||||
file(COPY ${3RDPARTY_DLL_DIR} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
#复制FluentUI源码到运行目录下,用于脚手架生成
|
||||
file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/source/)
|
||||
@ -115,37 +115,37 @@ file(COPY ${CMAKE_SOURCE_DIR}/src/ DESTINATION ${APPLICATION_DIR_PATH}/source/)
|
||||
|
||||
#导入component头文件,不然通过QML_NAMED_ELEMENT生成的c++类会找不到头文件报错
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/component
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/component
|
||||
)
|
||||
|
||||
#如果是静态库则需要手动注册插件,导入FluentUI.h头文件
|
||||
if(FLUENTUI_BUILD_STATIC_LIB)
|
||||
if (FLUENTUI_BUILD_STATIC_LIB)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
#设置属性
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.${PROJECT_NAME}.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.${PROJECT_NAME}.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
#Release也支持日志打印代码位置
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
QT_MESSAGELOGCONTEXT
|
||||
PRIVATE
|
||||
QT_MESSAGELOGCONTEXT
|
||||
)
|
||||
|
||||
#目标文件链接库
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Quick
|
||||
Qt${QT_VERSION_MAJOR}::Svg
|
||||
Qt${QT_VERSION_MAJOR}::Network
|
||||
fluentuiplugin
|
||||
Qt${QT_VERSION_MAJOR}::Quick
|
||||
Qt${QT_VERSION_MAJOR}::Svg
|
||||
Qt${QT_VERSION_MAJOR}::Network
|
||||
fluentuiplugin
|
||||
)
|
||||
|
||||
#添加部署脚本
|
||||
@ -153,23 +153,23 @@ if (CMAKE_BUILD_TYPE MATCHES "Release")
|
||||
if (APPLE)
|
||||
find_program(QT_DEPLOY_QT NAMES macdeployqt)
|
||||
add_custom_target(Script-DeployRelease
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/dist
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/dist
|
||||
COMMAND ${QT_DEPLOY_QT} ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME}.app -qmldir=${CMAKE_CURRENT_LIST_DIR}
|
||||
COMMENT "MacOs Deploying Qt Dependencies After Build........."
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/dist
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/dist
|
||||
COMMAND ${QT_DEPLOY_QT} ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME}.app -qmldir=${CMAKE_CURRENT_LIST_DIR}
|
||||
COMMENT "MacOs Deploying Qt Dependencies After Build........."
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
endif()
|
||||
if(WIN32)
|
||||
endif ()
|
||||
if (WIN32)
|
||||
find_program(QT_DEPLOY_QT NAMES windeployqt)
|
||||
add_custom_target(Script-DeployRelease
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/dist
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/dist
|
||||
COMMAND ${QT_DEPLOY_QT} --qmldir=${CMAKE_CURRENT_LIST_DIR} --plugindir ${CMAKE_SOURCE_DIR}/dist/plugins --no-translations --compiler-runtime ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME}.exe
|
||||
COMMENT "Windows Deploying Qt Dependencies After Build........."
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/dist
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/dist
|
||||
COMMAND ${QT_DEPLOY_QT} --qmldir=${CMAKE_CURRENT_LIST_DIR} --plugindir ${CMAKE_SOURCE_DIR}/dist/plugins --no-translations --compiler-runtime ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME}.exe
|
||||
COMMENT "Windows Deploying Qt Dependencies After Build........."
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif ()
|
||||
endif ()
|
||||
|
@ -127,7 +127,6 @@
|
||||
<file>qml/global/ItemsOriginal.qml</file>
|
||||
<file>qml/global/qmldir</file>
|
||||
<file>qml/page/T_Acrylic.qml</file>
|
||||
<file>qml/page/T_Awesome.qml</file>
|
||||
<file>qml/page/T_Badge.qml</file>
|
||||
<file>qml/page/T_BreadcrumbBar.qml</file>
|
||||
<file>qml/page/T_Buttons.qml</file>
|
||||
@ -181,7 +180,6 @@
|
||||
<file>qml/window/PageWindow.qml</file>
|
||||
<file>qml/page/T_StaggeredLayout.qml</file>
|
||||
<file>qml/page/T_Clip.qml</file>
|
||||
<file>qml/page/T_3D.qml</file>
|
||||
<file>qml/page/T_Network.qml</file>
|
||||
<file>qml/page/T_ShortcutPicker.qml</file>
|
||||
<file>qml/chart/T_BarChart.qml</file>
|
||||
@ -209,5 +207,8 @@
|
||||
<file>qml/page/T_GroupBox.qml</file>
|
||||
<file>res/image/bg_scenic.jpg</file>
|
||||
<file>qml/window/FluentInitializrWindow.qml</file>
|
||||
<file>qml/page/T_OpenGL.qml</file>
|
||||
<file>qml/page/T_Icons.qml</file>
|
||||
</qresource>
|
||||
<qresource prefix="/"/>
|
||||
</RCC>
|
||||
|
@ -87,22 +87,22 @@
|
||||
<context>
|
||||
<name>InitializrHelper</name>
|
||||
<message>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="77"/>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="69"/>
|
||||
<source>The name cannot be empty</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="81"/>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="73"/>
|
||||
<source>The creation path cannot be empty</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="86"/>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="78"/>
|
||||
<source>The path does not exist</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="92"/>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="84"/>
|
||||
<source>%1 folder already exists</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -425,7 +425,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="367"/>
|
||||
<source>Awesome</source>
|
||||
<source>Icons</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
@ -475,42 +475,42 @@
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="430"/>
|
||||
<source>QRCode</source>
|
||||
<source>OpenGL</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="436"/>
|
||||
<source>Tour</source>
|
||||
<source>QRCode</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="442"/>
|
||||
<source>Timeline</source>
|
||||
<source>Tour</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="448"/>
|
||||
<source>Captcha</source>
|
||||
<source>Timeline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="454"/>
|
||||
<source>Captcha</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="460"/>
|
||||
<source>Network</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="461"/>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="467"/>
|
||||
<source>Remote Loader</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="475"/>
|
||||
<source>Hot Loader</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="481"/>
|
||||
<source>3D</source>
|
||||
<source>Hot Loader</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
@ -546,104 +546,104 @@
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="307"/>
|
||||
<source>Dark Mode</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="83"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="91"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="87"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="95"/>
|
||||
<source>Quit</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="84"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="88"/>
|
||||
<source>Are you sure you want to exit the program?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="85"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="89"/>
|
||||
<source>Minimize</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="88"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="92"/>
|
||||
<source>Friendly Reminder</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="88"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="92"/>
|
||||
<source>FluentUI is hidden from the tray, click on the tray to activate the window again</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="92"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="336"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="96"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="340"/>
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="103"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="107"/>
|
||||
<source>Open in Separate Window</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="200"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="204"/>
|
||||
<source>Click Time</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="210"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="214"/>
|
||||
<source>Search</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="301"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="305"/>
|
||||
<source>Finish</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="302"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="306"/>
|
||||
<source>Next</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="303"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="307"/>
|
||||
<source>Previous</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="307"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="311"/>
|
||||
<source>Dark Mode</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="311"/>
|
||||
<source>Here you can switch to night mode.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="309"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="313"/>
|
||||
<source>Hide Easter eggs</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="309"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="313"/>
|
||||
<source>Try a few more clicks!!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="333"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="337"/>
|
||||
<source>Upgrade Tips</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="334"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="338"/>
|
||||
<source>FluentUI is currently up to date </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="334"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="338"/>
|
||||
<source> -- The current app version</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="334"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="338"/>
|
||||
<source>
|
||||
Now go and download the new version?
|
||||
|
||||
@ -652,17 +652,17 @@ Updated content:
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="337"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="341"/>
|
||||
<source>OK</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="364"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="368"/>
|
||||
<source>The current version is already the latest</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="371"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="375"/>
|
||||
<source>The network is abnormal</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -769,29 +769,6 @@ Updated content:
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_Awesome</name>
|
||||
<message>
|
||||
<location filename="qml/page/T_Awesome.qml" line="9"/>
|
||||
<source>Awesome</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Awesome.qml" line="13"/>
|
||||
<source>Please enter a keyword</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Awesome.qml" line="20"/>
|
||||
<source>Search</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Awesome.qml" line="55"/>
|
||||
<source>You Copied </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_Badge</name>
|
||||
<message>
|
||||
@ -1107,46 +1084,6 @@ Updated content:
|
||||
<source>Click to Select a Color - ></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="22"/>
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="23"/>
|
||||
<source>OK</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="24"/>
|
||||
<source>Color Picker</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="25"/>
|
||||
<source>Edit Color</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="26"/>
|
||||
<source>Red</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="27"/>
|
||||
<source>Green</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="28"/>
|
||||
<source>Blue</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="29"/>
|
||||
<source>Opacity</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_ComboBox</name>
|
||||
@ -1361,26 +1298,49 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
|
||||
<context>
|
||||
<name>T_Home</name>
|
||||
<message>
|
||||
<location filename="qml/page/T_Home.qml" line="23"/>
|
||||
<location filename="qml/page/T_Home.qml" line="19"/>
|
||||
<source>FluentUI GitHub</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Home.qml" line="24"/>
|
||||
<location filename="qml/page/T_Home.qml" line="20"/>
|
||||
<source>The latest FluentUI controls and styles for your applications.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Home.qml" line="32"/>
|
||||
<location filename="qml/page/T_Home.qml" line="28"/>
|
||||
<source>FluentUI Initializr</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Home.qml" line="33"/>
|
||||
<location filename="qml/page/T_Home.qml" line="29"/>
|
||||
<source>FluentUI Initializr is a Tool that helps you create and customize Fluent UI projects with various options.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_Icons</name>
|
||||
<message>
|
||||
<location filename="qml/page/T_Icons.qml" line="9"/>
|
||||
<source>Icons</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Icons.qml" line="13"/>
|
||||
<source>Please enter a keyword</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Icons.qml" line="20"/>
|
||||
<source>Search</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Icons.qml" line="60"/>
|
||||
<source>You Copied </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_Image</name>
|
||||
<message>
|
||||
@ -1621,6 +1581,14 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_OpenGL</name>
|
||||
<message>
|
||||
<location filename="qml/page/T_OpenGL.qml" line="11"/>
|
||||
<source>OpenGL</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_Pagination</name>
|
||||
<message>
|
||||
@ -1957,26 +1925,6 @@ Some contents...</source>
|
||||
<source>StatusLayout</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_StatusLayout.qml" line="63"/>
|
||||
<source>Loading...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_StatusLayout.qml" line="64"/>
|
||||
<source>Empty</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_StatusLayout.qml" line="65"/>
|
||||
<source>The page went wrong...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_StatusLayout.qml" line="66"/>
|
||||
<source>Reload</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_TabView</name>
|
||||
@ -2020,7 +1968,7 @@ Some contents...</source>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="177"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="478"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="513"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -2040,57 +1988,67 @@ Some contents...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="337"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="358"/>
|
||||
<source>Age</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="412"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="433"/>
|
||||
<source>Clear All</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="473"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="470"/>
|
||||
<source>Insert a Row</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="478"/>
|
||||
<source>Focus not acquired: Please click any item in the form as the target for insertion!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="508"/>
|
||||
<source>Avatar</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="491"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="526"/>
|
||||
<source>Address</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="498"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="534"/>
|
||||
<source>Nickname</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="505"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="541"/>
|
||||
<source>Long String</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="513"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="549"/>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="532"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="568"/>
|
||||
<source><Previous</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="533"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="569"/>
|
||||
<source>Next></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="419"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="440"/>
|
||||
<source>Delete Selection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="443"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="464"/>
|
||||
<source>Add a row of Data</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -2177,6 +2135,11 @@ Some contents...</source>
|
||||
<source>Open Animation</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Theme.qml" line="123"/>
|
||||
<source>Open Blur Window</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_TimePicker</name>
|
||||
@ -2376,13 +2339,23 @@ Some contents...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TreeView.qml" line="44"/>
|
||||
<source>Total %1 data, %2 data currently displayed</source>
|
||||
<location filename="qml/page/T_TreeView.qml" line="183"/>
|
||||
<source>Title</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TreeView.qml" line="48"/>
|
||||
<source>A total of %1 data items are selected</source>
|
||||
<location filename="qml/page/T_TreeView.qml" line="187"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TreeView.qml" line="191"/>
|
||||
<source>Avatar</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TreeView.qml" line="195"/>
|
||||
<source>Address</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
|
@ -87,22 +87,22 @@
|
||||
<context>
|
||||
<name>InitializrHelper</name>
|
||||
<message>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="77"/>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="69"/>
|
||||
<source>The name cannot be empty</source>
|
||||
<translation type="unfinished">名称不能为空</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="81"/>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="73"/>
|
||||
<source>The creation path cannot be empty</source>
|
||||
<translation type="unfinished">创建路径不能为空</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="86"/>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="78"/>
|
||||
<source>The path does not exist</source>
|
||||
<translation type="unfinished">路径不存在</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="92"/>
|
||||
<location filename="src/helper/InitializrHelper.cpp" line="84"/>
|
||||
<source>%1 folder already exists</source>
|
||||
<translation type="unfinished">%1 文件夹已经存在</translation>
|
||||
</message>
|
||||
@ -425,7 +425,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="367"/>
|
||||
<source>Awesome</source>
|
||||
<source>Icons</source>
|
||||
<translation type="unfinished">图标</translation>
|
||||
</message>
|
||||
<message>
|
||||
@ -475,43 +475,47 @@
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="430"/>
|
||||
<source>OpenGL</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="436"/>
|
||||
<source>QRCode</source>
|
||||
<translation type="unfinished">二维码</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="436"/>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="442"/>
|
||||
<source>Tour</source>
|
||||
<translation type="unfinished">游览</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="442"/>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="448"/>
|
||||
<source>Timeline</source>
|
||||
<translation type="unfinished">时间轴</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="448"/>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="454"/>
|
||||
<source>Captcha</source>
|
||||
<translation type="unfinished">验证码</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="454"/>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="460"/>
|
||||
<source>Network</source>
|
||||
<translation type="unfinished">网络</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="461"/>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="467"/>
|
||||
<source>Remote Loader</source>
|
||||
<translation type="unfinished">远程加载</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="475"/>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="481"/>
|
||||
<source>Hot Loader</source>
|
||||
<translation type="unfinished">热加载</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="481"/>
|
||||
<source>3D</source>
|
||||
<translation type="unfinished">3D</translation>
|
||||
<translation type="obsolete">3D</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="487"/>
|
||||
@ -546,104 +550,104 @@
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="307"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="311"/>
|
||||
<source>Dark Mode</source>
|
||||
<translation type="unfinished">夜间模式</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="83"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="91"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="87"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="95"/>
|
||||
<source>Quit</source>
|
||||
<translation type="unfinished">退出</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="84"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="88"/>
|
||||
<source>Are you sure you want to exit the program?</source>
|
||||
<translation type="unfinished">您确定要退出程序吗</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="85"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="89"/>
|
||||
<source>Minimize</source>
|
||||
<translation type="unfinished">最小化</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="88"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="92"/>
|
||||
<source>Friendly Reminder</source>
|
||||
<translation type="unfinished">友情提示</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="88"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="92"/>
|
||||
<source>FluentUI is hidden from the tray, click on the tray to activate the window again</source>
|
||||
<translation type="unfinished">FluentUI 在托盘中处于隐藏状态,单击托盘以再次激活窗口</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="92"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="336"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="96"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="340"/>
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">取消</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="103"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="107"/>
|
||||
<source>Open in Separate Window</source>
|
||||
<translation type="unfinished">在独立窗口中打开</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="200"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="204"/>
|
||||
<source>Click Time</source>
|
||||
<translation type="unfinished">点击次数</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="210"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="214"/>
|
||||
<source>Search</source>
|
||||
<translation type="unfinished">搜索</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="301"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="305"/>
|
||||
<source>Finish</source>
|
||||
<translation type="unfinished">完成</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="302"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="306"/>
|
||||
<source>Next</source>
|
||||
<translation type="unfinished">下一步</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="303"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="307"/>
|
||||
<source>Previous</source>
|
||||
<translation type="unfinished">上一步</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="307"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="311"/>
|
||||
<source>Here you can switch to night mode.</source>
|
||||
<translation type="unfinished">在这里,您可以切换到夜间模式。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="309"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="313"/>
|
||||
<source>Hide Easter eggs</source>
|
||||
<translation type="unfinished">隐藏彩蛋</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="309"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="313"/>
|
||||
<source>Try a few more clicks!!</source>
|
||||
<translation type="unfinished">再试几下!!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="333"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="337"/>
|
||||
<source>Upgrade Tips</source>
|
||||
<translation type="unfinished">升级提示</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="334"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="338"/>
|
||||
<source>FluentUI is currently up to date </source>
|
||||
<translation type="unfinished">FluentUI 目前最新版本 </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="334"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="338"/>
|
||||
<source> -- The current app version</source>
|
||||
<translation type="unfinished"> -- 当前应用版本</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="334"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="338"/>
|
||||
<source>
|
||||
Now go and download the new version?
|
||||
|
||||
@ -656,17 +660,17 @@ Updated content:
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="337"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="341"/>
|
||||
<source>OK</source>
|
||||
<translation type="unfinished">确定</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="364"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="368"/>
|
||||
<source>The current version is already the latest</source>
|
||||
<translation type="unfinished">当前版本已经是最新版本</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/window/MainWindow.qml" line="371"/>
|
||||
<location filename="qml/window/MainWindow.qml" line="375"/>
|
||||
<source>The network is abnormal</source>
|
||||
<translation type="unfinished">网络异常</translation>
|
||||
</message>
|
||||
@ -776,24 +780,20 @@ Updated content:
|
||||
<context>
|
||||
<name>T_Awesome</name>
|
||||
<message>
|
||||
<location filename="qml/page/T_Awesome.qml" line="9"/>
|
||||
<source>Awesome</source>
|
||||
<translation type="unfinished">图标</translation>
|
||||
<translation type="obsolete">图标</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Awesome.qml" line="13"/>
|
||||
<source>Please enter a keyword</source>
|
||||
<translation type="unfinished">请输入关键字</translation>
|
||||
<translation type="obsolete">请输入关键字</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Awesome.qml" line="20"/>
|
||||
<source>Search</source>
|
||||
<translation type="unfinished">搜索</translation>
|
||||
<translation type="obsolete">搜索</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Awesome.qml" line="55"/>
|
||||
<source>You Copied </source>
|
||||
<translation type="unfinished">您复制</translation>
|
||||
<translation type="obsolete">您复制</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1112,44 +1112,36 @@ Updated content:
|
||||
<translation type="unfinished">点击选中颜色 - ></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="22"/>
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">取消</translation>
|
||||
<translation type="obsolete">取消</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="23"/>
|
||||
<source>OK</source>
|
||||
<translation type="unfinished">确定</translation>
|
||||
<translation type="obsolete">确定</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="24"/>
|
||||
<source>Color Picker</source>
|
||||
<translation type="unfinished">颜色选择器</translation>
|
||||
<translation type="obsolete">颜色选择器</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="25"/>
|
||||
<source>Edit Color</source>
|
||||
<translation type="unfinished">编辑颜色</translation>
|
||||
<translation type="obsolete">编辑颜色</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="26"/>
|
||||
<source>Red</source>
|
||||
<translation type="unfinished">红色</translation>
|
||||
<translation type="obsolete">红色</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="27"/>
|
||||
<source>Green</source>
|
||||
<translation type="unfinished">绿色</translation>
|
||||
<translation type="obsolete">绿色</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="28"/>
|
||||
<source>Blue</source>
|
||||
<translation type="unfinished">蓝色</translation>
|
||||
<translation type="obsolete">蓝色</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_ColorPicker.qml" line="29"/>
|
||||
<source>Opacity</source>
|
||||
<translation type="unfinished">透明度</translation>
|
||||
<translation type="obsolete">透明度</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1392,26 +1384,49 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
|
||||
<context>
|
||||
<name>T_Home</name>
|
||||
<message>
|
||||
<location filename="qml/page/T_Home.qml" line="23"/>
|
||||
<location filename="qml/page/T_Home.qml" line="19"/>
|
||||
<source>FluentUI GitHub</source>
|
||||
<translation type="unfinished">FluentUI GitHub</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Home.qml" line="24"/>
|
||||
<location filename="qml/page/T_Home.qml" line="20"/>
|
||||
<source>The latest FluentUI controls and styles for your applications.</source>
|
||||
<translation type="unfinished">最新的 FluentUI 控件和样式</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Home.qml" line="32"/>
|
||||
<location filename="qml/page/T_Home.qml" line="28"/>
|
||||
<source>FluentUI Initializr</source>
|
||||
<translation type="unfinished">FluentUI脚手架</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Home.qml" line="33"/>
|
||||
<location filename="qml/page/T_Home.qml" line="29"/>
|
||||
<source>FluentUI Initializr is a Tool that helps you create and customize Fluent UI projects with various options.</source>
|
||||
<translation type="unfinished">FluentUI 脚手架是一个快速创建项目工具,可帮助您创建和自定义具有各种选项的 Fluent UI 项目</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_Icons</name>
|
||||
<message>
|
||||
<location filename="qml/page/T_Icons.qml" line="9"/>
|
||||
<source>Icons</source>
|
||||
<translation type="unfinished">图标</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Icons.qml" line="13"/>
|
||||
<source>Please enter a keyword</source>
|
||||
<translation type="unfinished">请输入关键字</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Icons.qml" line="20"/>
|
||||
<source>Search</source>
|
||||
<translation type="unfinished">搜索</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Icons.qml" line="60"/>
|
||||
<source>You Copied </source>
|
||||
<translation type="unfinished">您复制</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_Image</name>
|
||||
<message>
|
||||
@ -1660,6 +1675,14 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
|
||||
<translation type="unfinished">网络</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_OpenGL</name>
|
||||
<message>
|
||||
<location filename="qml/page/T_OpenGL.qml" line="11"/>
|
||||
<source>OpenGL</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_Pagination</name>
|
||||
<message>
|
||||
@ -2029,24 +2052,20 @@ Some contents...</source>
|
||||
<translation type="unfinished">状态布局</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_StatusLayout.qml" line="63"/>
|
||||
<source>Loading...</source>
|
||||
<translation type="unfinished">正在加载...</translation>
|
||||
<translation type="obsolete">正在加载...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_StatusLayout.qml" line="64"/>
|
||||
<source>Empty</source>
|
||||
<translation type="unfinished">空空如也</translation>
|
||||
<translation type="obsolete">空空如也</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_StatusLayout.qml" line="65"/>
|
||||
<source>The page went wrong...</source>
|
||||
<translation type="unfinished">页面出错了...</translation>
|
||||
<translation type="obsolete">页面出错了...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_StatusLayout.qml" line="66"/>
|
||||
<source>Reload</source>
|
||||
<translation type="unfinished">重新加载</translation>
|
||||
<translation type="obsolete">重新加载</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -2091,7 +2110,7 @@ Some contents...</source>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="177"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="478"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="513"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished">名称</translation>
|
||||
</message>
|
||||
@ -2111,57 +2130,67 @@ Some contents...</source>
|
||||
<translation type="unfinished">全选</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="337"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="358"/>
|
||||
<source>Age</source>
|
||||
<translation type="unfinished">年龄</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="412"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="433"/>
|
||||
<source>Clear All</source>
|
||||
<translation type="unfinished">清除所有</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="473"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="470"/>
|
||||
<source>Insert a Row</source>
|
||||
<translation type="unfinished">插入一行</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="478"/>
|
||||
<source>Focus not acquired: Please click any item in the form as the target for insertion!</source>
|
||||
<translation type="unfinished">焦点未获取:请点击表格中的任意一项,作为插入的靶点!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="508"/>
|
||||
<source>Avatar</source>
|
||||
<translation type="unfinished">头像</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="491"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="526"/>
|
||||
<source>Address</source>
|
||||
<translation type="unfinished">地址</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="498"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="534"/>
|
||||
<source>Nickname</source>
|
||||
<translation type="unfinished">昵称</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="505"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="541"/>
|
||||
<source>Long String</source>
|
||||
<translation type="unfinished">长字符串</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="513"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="549"/>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">操作</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="532"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="568"/>
|
||||
<source><Previous</source>
|
||||
<translation type="unfinished"><上一页</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="533"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="569"/>
|
||||
<source>Next></source>
|
||||
<translation type="unfinished">下一页></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="419"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="440"/>
|
||||
<source>Delete Selection</source>
|
||||
<translation type="unfinished">删除选中</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TableView.qml" line="443"/>
|
||||
<location filename="qml/page/T_TableView.qml" line="464"/>
|
||||
<source>Add a row of Data</source>
|
||||
<translation type="unfinished">添加一行数据</translation>
|
||||
</message>
|
||||
@ -2248,6 +2277,11 @@ Some contents...</source>
|
||||
<source>Open Animation</source>
|
||||
<translation type="unfinished">开启动画</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Theme.qml" line="123"/>
|
||||
<source>Open Blur Window</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>T_TimePicker</name>
|
||||
@ -2459,14 +2493,32 @@ Some contents...</source>
|
||||
<translation type="unfinished">树</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TreeView.qml" line="44"/>
|
||||
<source>Total %1 data, %2 data currently displayed</source>
|
||||
<translation type="unfinished">共计%1条数据,当前显示的%2条数据</translation>
|
||||
<translation type="obsolete">共计%1条数据,当前显示的%2条数据</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TreeView.qml" line="48"/>
|
||||
<source>A total of %1 data items are selected</source>
|
||||
<translation type="unfinished">共计选中%1条数据</translation>
|
||||
<translation type="obsolete">共计选中%1条数据</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TreeView.qml" line="183"/>
|
||||
<source>Title</source>
|
||||
<translation type="unfinished">标题</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TreeView.qml" line="195"/>
|
||||
<source>Address</source>
|
||||
<translation type="unfinished">地址</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TreeView.qml" line="191"/>
|
||||
<source>Avatar</source>
|
||||
<translation type="unfinished">头像</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_TreeView.qml" line="187"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished">名称</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -364,9 +364,9 @@ FluObject{
|
||||
onTap: { navigationView.push(url) }
|
||||
}
|
||||
FluPaneItem{
|
||||
title: qsTr("Awesome")
|
||||
title: qsTr("Icons")
|
||||
menuDelegate: paneItemMenu
|
||||
url: "qrc:/example/qml/page/T_Awesome.qml"
|
||||
url: "qrc:/example/qml/page/T_Icons.qml"
|
||||
onTap: { navigationView.push(url) }
|
||||
}
|
||||
}
|
||||
@ -426,6 +426,12 @@ FluObject{
|
||||
FluPaneItemExpander{
|
||||
title: qsTr("Other")
|
||||
icon: FluentIcons.Shop
|
||||
FluPaneItem{
|
||||
title: qsTr("OpenGL")
|
||||
menuDelegate: paneItemMenu
|
||||
url: "qrc:/example/qml/page/T_OpenGL.qml"
|
||||
onTap: { navigationView.push(url) }
|
||||
}
|
||||
FluPaneItem{
|
||||
title: qsTr("QRCode")
|
||||
menuDelegate: paneItemMenu
|
||||
@ -477,12 +483,6 @@ FluObject{
|
||||
FluRouter.navigate("/hotload")
|
||||
}
|
||||
}
|
||||
FluPaneItem{
|
||||
title: qsTr("3D")
|
||||
menuDelegate: paneItemMenu
|
||||
url: "qrc:/example/qml/page/T_3D.qml"
|
||||
onTap: { navigationView.push(url) }
|
||||
}
|
||||
FluPaneItem{
|
||||
title: qsTr("Test Crash")
|
||||
onTapListener: function(){
|
||||
|
@ -1,116 +0,0 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Window 2.15
|
||||
import Qt3D.Core 2.15
|
||||
import Qt3D.Render 2.15
|
||||
import Qt3D.Input 2.12
|
||||
import Qt3D.Extras 2.15
|
||||
import QtQuick.Scene3D 2.15
|
||||
import Qt.labs.platform 1.1
|
||||
import FluentUI 1.0
|
||||
import "../component"
|
||||
|
||||
FluContentPage{
|
||||
|
||||
id:root
|
||||
title:"3D"
|
||||
|
||||
Scene3D{
|
||||
id:scene_3d
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
aspects: ["input", "logic"]
|
||||
cameraAspectRatioMode: Scene3D.AutomaticAspectRatio
|
||||
Entity {
|
||||
Camera {
|
||||
id: camera
|
||||
projectionType: CameraLens.PerspectiveProjection
|
||||
fieldOfView: 22.5
|
||||
aspectRatio: scene_3d.width / scene_3d.height
|
||||
nearPlane: 1
|
||||
farPlane: 1000.0
|
||||
viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
|
||||
upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
|
||||
position: Qt.vector3d( 0.0, 0.0, 15.0 )
|
||||
}
|
||||
FirstPersonCameraController {
|
||||
linearSpeed: 100
|
||||
lookSpeed: 50
|
||||
camera: camera
|
||||
}
|
||||
components: [
|
||||
RenderSettings{
|
||||
activeFrameGraph: ForwardRenderer{
|
||||
clearColor: Qt.rgba(0,0,0,0);
|
||||
camera: camera
|
||||
}
|
||||
},
|
||||
InputSettings{}
|
||||
]
|
||||
Mesh {
|
||||
id: mesh
|
||||
source: "https://zhu-zichu.gitee.io/test.obj"
|
||||
}
|
||||
PhongMaterial {
|
||||
id: material
|
||||
ambient: color_picker.current
|
||||
}
|
||||
Transform{
|
||||
id:transform
|
||||
scale: 1.0
|
||||
translation: Qt.vector3d(0, 0, 0)
|
||||
rotation: fromEulerAngles(0, 0, 0)
|
||||
property real hAngle:0.0
|
||||
NumberAnimation on hAngle{
|
||||
from:0
|
||||
to:360.0
|
||||
duration: 5000
|
||||
loops: Animation.Infinite
|
||||
}
|
||||
matrix:{
|
||||
var m=Qt.matrix4x4();
|
||||
m.rotate(hAngle,Qt.vector3d(0,1,0));
|
||||
m.translate(Qt.vector3d(0,0,0));
|
||||
return m;
|
||||
}
|
||||
}
|
||||
Entity {
|
||||
id: entity
|
||||
components: [mesh, material,transform]
|
||||
}
|
||||
}
|
||||
}
|
||||
ColumnLayout{
|
||||
RowLayout{
|
||||
spacing: 10
|
||||
Layout.topMargin: 20
|
||||
FluText{
|
||||
text:"tintColor:"
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
FluColorPicker{
|
||||
id:color_picker
|
||||
current: "gray"
|
||||
}
|
||||
}
|
||||
|
||||
FluButton{
|
||||
text:"选择obj资源"
|
||||
onClicked: {
|
||||
file_dialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileDialog {
|
||||
id: file_dialog
|
||||
nameFilters: ["Obj files (*.obj)"]
|
||||
folder: StandardPaths.writableLocation(StandardPaths.DocumentsLocation)
|
||||
onAccepted: {
|
||||
var fileUrl = file_dialog.currentFile
|
||||
mesh.source = fileUrl
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -18,16 +18,7 @@ FluScrollablePage{
|
||||
text: qsTr("Click to Select a Color - >")
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
FluColorPicker{
|
||||
cancelText: qsTr("Cancel")
|
||||
okText: qsTr("OK")
|
||||
titleText: qsTr("Color Picker")
|
||||
editText: qsTr("Edit Color")
|
||||
redText: qsTr("Red")
|
||||
greenText: qsTr("Green")
|
||||
blueText: qsTr("Blue")
|
||||
opacityText: qsTr("Opacity")
|
||||
}
|
||||
FluColorPicker{}
|
||||
}
|
||||
}
|
||||
CodeExpander{
|
||||
|
@ -12,10 +12,6 @@ FluScrollablePage{
|
||||
animationEnabled: false
|
||||
header: Item{}
|
||||
|
||||
FluentInitializrWindow{
|
||||
id:fluent_Initializr
|
||||
}
|
||||
|
||||
ListModel{
|
||||
id: model_header
|
||||
ListElement{
|
||||
|
@ -6,13 +6,13 @@ import FluentUI 1.0
|
||||
|
||||
FluContentPage {
|
||||
|
||||
title: qsTr("Awesome")
|
||||
title: qsTr("Icons")
|
||||
|
||||
FluTextBox{
|
||||
id:text_box
|
||||
id: text_box
|
||||
placeholderText: qsTr("Please enter a keyword")
|
||||
anchors{
|
||||
top:parent.top
|
||||
top: parent.top
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,47 +24,49 @@ FluContentPage {
|
||||
leftMargin: 14
|
||||
}
|
||||
onClicked: {
|
||||
grid_view.model = FluTheme.awesomeList(text_box.text)
|
||||
grid_view.model = FluApp.iconDatas(text_box.text)
|
||||
}
|
||||
}
|
||||
GridView{
|
||||
id:grid_view
|
||||
cellWidth: 80
|
||||
cellHeight: 80
|
||||
id: grid_view
|
||||
cellWidth: 110
|
||||
cellHeight: 110
|
||||
clip: true
|
||||
boundsBehavior: GridView.StopAtBounds
|
||||
model:FluTheme.awesomeList()
|
||||
model: FluApp.iconDatas()
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
anchors{
|
||||
topMargin: 10
|
||||
top:text_box.bottom
|
||||
top: text_box.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
delegate: Item {
|
||||
width: 68
|
||||
height: 80
|
||||
width: 100
|
||||
height: 100
|
||||
FluIconButton{
|
||||
id:item_icon
|
||||
iconSource:modelData.icon
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
iconSource: modelData.icon
|
||||
iconSize: 30
|
||||
padding: 0
|
||||
verticalPadding: 0
|
||||
horizontalPadding: 0
|
||||
bottomPadding: 30
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
var text ="FluentIcons."+modelData.name;
|
||||
FluTools.clipText(text)
|
||||
showSuccess(qsTr("You Copied ")+text)
|
||||
}
|
||||
}
|
||||
FluText {
|
||||
id:item_name
|
||||
font.pixelSize: 10
|
||||
font.family: FluTextStyle.family
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: item_icon.bottom
|
||||
width:parent.width
|
||||
wrapMode: Text.WrapAnywhere
|
||||
text: modelData.name
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
FluText{
|
||||
width: parent.width
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
wrapMode: Text.WrapAnywhere
|
||||
text: modelData.name
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 60
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -9,9 +9,13 @@ FluScrollablePage{
|
||||
|
||||
title: qsTr("InfoBar")
|
||||
|
||||
property var info1
|
||||
property var info2
|
||||
property var info3
|
||||
|
||||
FluFrame{
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 270
|
||||
Layout.preferredHeight: 350
|
||||
padding: 10
|
||||
ColumnLayout{
|
||||
spacing: 14
|
||||
@ -49,6 +53,51 @@ FluScrollablePage{
|
||||
showInfo(qsTr("This is an InfoBar in the Info Style"),0,qsTr("Manual shutdown is supported"))
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: parent.width
|
||||
text: qsTr("Manually close the info message box")
|
||||
}
|
||||
Row{
|
||||
spacing: 5
|
||||
FluButton{
|
||||
text: (info1 ? qsTr("close '%1'") : qsTr("show '%1")).arg("info1")
|
||||
onClicked: {
|
||||
if(info1) {
|
||||
info1.close()
|
||||
return
|
||||
}
|
||||
info1 = showInfo(qsTr("This is an '%1'").arg("info1"), 0)
|
||||
}
|
||||
}
|
||||
FluButton{
|
||||
text: (info2 ? qsTr("close '%1'") : qsTr("show '%1")).arg("info2")
|
||||
onClicked: {
|
||||
if(info2) {
|
||||
info2.close()
|
||||
return
|
||||
}
|
||||
info2 = showInfo(qsTr("This is an '%1'").arg("info2"), 0)
|
||||
}
|
||||
}
|
||||
FluButton{
|
||||
text: (info3 ? qsTr("close '%1'") : qsTr("show '%1")).arg("info3")
|
||||
onClicked: {
|
||||
if(info3) {
|
||||
info3.close()
|
||||
return
|
||||
}
|
||||
info3 = showInfo(qsTr("This is an '%1'").arg("info3"), 0)
|
||||
}
|
||||
}
|
||||
FluButton{
|
||||
text: qsTr("clear all info")
|
||||
onClicked: {
|
||||
clearAllInfo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FluButton{
|
||||
text:"Loading"
|
||||
onClicked: {
|
||||
@ -60,12 +109,17 @@ FluScrollablePage{
|
||||
CodeExpander{
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -6
|
||||
code:'showInfo(qsTr("This is an InfoBar in the Info Style"))
|
||||
code:`
|
||||
showInfo(qsTr("This is an InfoBar in the Info Style"))
|
||||
|
||||
showWarning(qsTr("This is an InfoBar in the Warning Style"))
|
||||
|
||||
showError(qsTr("This is an InfoBar in the Error Style"))
|
||||
|
||||
showSuccess(qsTr("This is an InfoBar in the Success Style"))'
|
||||
showSuccess(qsTr("This is an InfoBar in the Success Style"))
|
||||
|
||||
var info1 = showInfo(qsTr("This is an 'Info1'"), 0)
|
||||
info1.close()
|
||||
`
|
||||
}
|
||||
}
|
||||
|
26
example/qml/page/T_OpenGL.qml
Normal file
26
example/qml/page/T_OpenGL.qml
Normal file
@ -0,0 +1,26 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Window 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import FluentUI 1.0
|
||||
import example 1.0
|
||||
import "../component"
|
||||
|
||||
FluContentPage{
|
||||
|
||||
title: qsTr("OpenGL")
|
||||
|
||||
FluFrame{
|
||||
anchors.fill: parent
|
||||
OpenGLItem{
|
||||
anchors.fill: parent
|
||||
SequentialAnimation on t {
|
||||
NumberAnimation { to: 1; duration: 2500; easing.type: Easing.InQuad }
|
||||
NumberAnimation { to: 0; duration: 2500; easing.type: Easing.OutQuad }
|
||||
loops: Animation.Infinite
|
||||
running: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -60,12 +60,8 @@ FluScrollablePage{
|
||||
FluStatusLayout{
|
||||
id:status_view
|
||||
anchors.fill: parent
|
||||
loadingText: qsTr("Loading...")
|
||||
emptyText: qsTr("Empty")
|
||||
errorText: qsTr("The page went wrong...")
|
||||
errorButtonText: qsTr("Reload")
|
||||
onErrorClicked:{
|
||||
showError("Click Reload")
|
||||
status_view.statusMode = FluStatusLayoutType.Loading
|
||||
}
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
|
@ -13,7 +13,7 @@ FluContentPage{
|
||||
|
||||
property var dataSource : []
|
||||
property int sortType: 0
|
||||
property bool seletedAll: true
|
||||
property bool selectedAll: true
|
||||
property string nameKeyword: ""
|
||||
|
||||
onNameKeywordChanged: {
|
||||
@ -32,11 +32,11 @@ FluContentPage{
|
||||
onCheckBoxChanged: {
|
||||
for(var i =0;i< table_view.rows ;i++){
|
||||
if(false === table_view.getRow(i).checkbox.options.checked){
|
||||
root.seletedAll = false
|
||||
root.selectedAll = false
|
||||
return
|
||||
}
|
||||
}
|
||||
root.seletedAll = true
|
||||
root.selectedAll = true
|
||||
}
|
||||
|
||||
onSortTypeChanged: {
|
||||
@ -238,12 +238,12 @@ FluContentPage{
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
FluCheckBox{
|
||||
checked: true === root.seletedAll
|
||||
checked: true === root.selectedAll
|
||||
animationEnabled: false
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
clickListener: function(){
|
||||
root.seletedAll = !root.seletedAll
|
||||
var checked = root.seletedAll
|
||||
root.selectedAll = !root.selectedAll
|
||||
var checked = root.selectedAll
|
||||
itemModel.display = table_view.customItem(com_column_checbox,{"checked":checked})
|
||||
for(var i =0;i< table_view.rows ;i++){
|
||||
var rowData = table_view.getRow(i)
|
||||
@ -280,6 +280,27 @@ FluContentPage{
|
||||
}
|
||||
}
|
||||
|
||||
Component{
|
||||
id:com_auto_suggestbox
|
||||
FluAutoSuggestBox {
|
||||
id: textbox
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
Component.onCompleted: {
|
||||
var data = ["傲来国界花果山水帘洞","傲来国界坎源山脏水洞","大唐国界黑风山黑风洞","大唐国界黄风岭黄风洞","大唐国界骷髅山白骨洞","宝象国界碗子山波月洞","宝象国界平顶山莲花洞","宝象国界压龙山压龙洞","乌鸡国界号山枯松涧火云洞","乌鸡国界衡阳峪黑水河河神府"]
|
||||
var result = data.map(function(item) {
|
||||
return {title: item};
|
||||
});
|
||||
items = result
|
||||
textbox.text= String(display)
|
||||
}
|
||||
onCommit: {
|
||||
editTextChaged(textbox.text)
|
||||
tableView.closeEditor()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component{
|
||||
id:com_avatar
|
||||
Item{
|
||||
@ -445,6 +466,20 @@ FluContentPage{
|
||||
table_view.appendRow(genTestObject())
|
||||
}
|
||||
}
|
||||
FluButton{
|
||||
text: qsTr("Insert a Row")
|
||||
onClicked: {
|
||||
if(typeof table_view.current !== 'undefined'){
|
||||
var newLine = genTestObject()
|
||||
var currentLine = dataSource.findIndex(obj => obj._key === table_view.current._key)
|
||||
root.dataSource.splice(currentLine, 0, newLine);
|
||||
table_view.dataSource = root.dataSource
|
||||
}else{
|
||||
showWarning(qsTr("Focus not acquired: Please click any item in the form as the target for insertion!"))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -490,6 +525,7 @@ FluContentPage{
|
||||
{
|
||||
title: qsTr("Address"),
|
||||
dataIndex: 'address',
|
||||
editDelegate: com_auto_suggestbox,
|
||||
width:200,
|
||||
minimumWidth:100,
|
||||
maximumWidth:250
|
||||
@ -566,7 +602,7 @@ FluContentPage{
|
||||
return avatars[randomIndex];
|
||||
}
|
||||
return {
|
||||
checkbox: table_view.customItem(com_checbox,{checked:root.seletedAll}),
|
||||
checkbox: table_view.customItem(com_checbox,{checked:root.selectedAll}),
|
||||
avatar:table_view.customItem(com_avatar,{avatar:getAvatar()}),
|
||||
name: getRandomName(),
|
||||
age:getRandomAge(),
|
||||
@ -579,7 +615,7 @@ FluContentPage{
|
||||
}
|
||||
}
|
||||
function loadData(page,count){
|
||||
root.seletedAll = true
|
||||
root.selectedAll = true
|
||||
const dataSource = []
|
||||
for(var i=0;i<count;i++){
|
||||
dataSource.push(genTestObject())
|
||||
|
@ -13,7 +13,7 @@ FluScrollablePage{
|
||||
|
||||
FluFrame{
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 340
|
||||
Layout.preferredHeight: 408
|
||||
padding: 10
|
||||
|
||||
ColumnLayout{
|
||||
@ -119,6 +119,17 @@ FluScrollablePage{
|
||||
FluTheme.animationEnabled = !FluTheme.animationEnabled
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
text: qsTr("Open Blur Window")
|
||||
Layout.topMargin: 20
|
||||
}
|
||||
FluToggleSwitch{
|
||||
Layout.topMargin: 5
|
||||
checked: FluTheme.blurBehindWindowEnabled
|
||||
onClicked: {
|
||||
FluTheme.blurBehindWindowEnabled = !FluTheme.blurBehindWindowEnabled
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CodeExpander{
|
||||
|
@ -9,14 +9,33 @@ FluContentPage {
|
||||
|
||||
title: qsTr("TreeView")
|
||||
|
||||
|
||||
function treeData(){
|
||||
const dig = (path = '0', level = 4) => {
|
||||
const names = ["孙悟空", "猪八戒", "沙和尚", "唐僧","白骨夫人","金角大王","熊山君","黄风怪","银角大王"]
|
||||
function getRandomName(){
|
||||
var randomIndex = Math.floor(Math.random() * names.length)
|
||||
return names[randomIndex]
|
||||
}
|
||||
const addresses = ["傲来国界花果山水帘洞","傲来国界坎源山脏水洞","大唐国界黑风山黑风洞","大唐国界黄风岭黄风洞","大唐国界骷髅山白骨洞","宝象国界碗子山波月洞","宝象国界平顶山莲花洞","宝象国界压龙山压龙洞","乌鸡国界号山枯松涧火云洞","乌鸡国界衡阳峪黑水河河神府"]
|
||||
function getRandomAddresses(){
|
||||
var randomIndex = Math.floor(Math.random() * addresses.length)
|
||||
return addresses[randomIndex]
|
||||
}
|
||||
const avatars = ["qrc:/example/res/svg/avatar_1.svg", "qrc:/example/res/svg/avatar_2.svg", "qrc:/example/res/svg/avatar_3.svg", "qrc:/example/res/svg/avatar_4.svg","qrc:/example/res/svg/avatar_5.svg","qrc:/example/res/svg/avatar_6.svg","qrc:/example/res/svg/avatar_7.svg","qrc:/example/res/svg/avatar_8.svg","qrc:/example/res/svg/avatar_9.svg","qrc:/example/res/svg/avatar_10.svg","qrc:/example/res/svg/avatar_11.svg","qrc:/example/res/svg/avatar_12.svg"]
|
||||
function getRandomAvatar(){
|
||||
var randomIndex = Math.floor(Math.random() * avatars.length);
|
||||
return avatars[randomIndex];
|
||||
}
|
||||
const dig = (path = '0', level = 5) => {
|
||||
const list = [];
|
||||
for (let i = 0; i < 6; i += 1) {
|
||||
for (let i = 0; i < 4; i += 1) {
|
||||
const key = `${path}-${i}`;
|
||||
const treeNode = {
|
||||
title: key,
|
||||
key,
|
||||
_key: key,
|
||||
name: getRandomName(),
|
||||
avatar:tree_view.customItem(com_avatar,{avatar:getRandomAvatar()}),
|
||||
address: getRandomAddresses()
|
||||
};
|
||||
if (level > 0) {
|
||||
treeNode.children = dig(key, level - 1);
|
||||
@ -28,103 +47,159 @@ FluContentPage {
|
||||
return dig();
|
||||
}
|
||||
|
||||
Column{
|
||||
id: layout_column
|
||||
spacing: 12
|
||||
width: 300
|
||||
anchors{
|
||||
top:parent.top
|
||||
left: parent.left
|
||||
leftMargin: 10
|
||||
bottom:parent.bottom
|
||||
bottomMargin: 20
|
||||
}
|
||||
|
||||
FluText{
|
||||
text: qsTr("Total %1 data, %2 data currently displayed").arg(tree_view.count()).arg(tree_view.visibleCount())
|
||||
}
|
||||
|
||||
FluText{
|
||||
text: qsTr("A total of %1 data items are selected").arg(tree_view.selectionModel().length)
|
||||
}
|
||||
|
||||
RowLayout{
|
||||
spacing: 10
|
||||
FluText{
|
||||
text: "cellHeight:"
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
FluSlider{
|
||||
id: slider_cell_height
|
||||
value: 30
|
||||
from: 30
|
||||
to:100
|
||||
}
|
||||
}
|
||||
RowLayout{
|
||||
spacing: 10
|
||||
FluText{
|
||||
text: "depthPadding:"
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
FluSlider{
|
||||
id: slider_depth_padding
|
||||
value: 30
|
||||
from: 30
|
||||
to:100
|
||||
}
|
||||
}
|
||||
FluToggleSwitch{
|
||||
id: switch_showline
|
||||
text:"showLine"
|
||||
checked: false
|
||||
}
|
||||
FluToggleSwitch{
|
||||
id: switch_draggable
|
||||
text:"draggable"
|
||||
checked: false
|
||||
}
|
||||
FluToggleSwitch{
|
||||
id: switch_checkable
|
||||
text:"checkable"
|
||||
checked: false
|
||||
}
|
||||
FluButton{
|
||||
text: "all expand"
|
||||
onClicked: {
|
||||
tree_view.allExpand()
|
||||
}
|
||||
}
|
||||
FluButton{
|
||||
text: "all collapse"
|
||||
onClicked: {
|
||||
tree_view.allCollapse()
|
||||
Component{
|
||||
id:com_avatar
|
||||
Item{
|
||||
FluClip{
|
||||
anchors.centerIn: parent
|
||||
width: height
|
||||
height: parent.height/3*2
|
||||
radius: [height/2,height/2,height/2,height/2]
|
||||
Image{
|
||||
anchors.fill: parent
|
||||
source: {
|
||||
if(options && options.avatar){
|
||||
return options.avatar
|
||||
}
|
||||
return ""
|
||||
}
|
||||
sourceSize: Qt.size(80,80)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FluFrame{
|
||||
id:layout_controls
|
||||
anchors{
|
||||
left: layout_column.right
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
rightMargin: 5
|
||||
topMargin: 5
|
||||
bottomMargin: 5
|
||||
top: parent.top
|
||||
topMargin: 10
|
||||
}
|
||||
FluShadow{}
|
||||
FluTreeView{
|
||||
id:tree_view
|
||||
anchors.fill: parent
|
||||
cellHeight: slider_cell_height.value
|
||||
draggable:switch_draggable.checked
|
||||
showLine: switch_showline.checked
|
||||
checkable:switch_checkable.checked
|
||||
depthPadding: slider_depth_padding.value
|
||||
Component.onCompleted: {
|
||||
var data = treeData()
|
||||
dataSource = data
|
||||
height: 80
|
||||
clip: true
|
||||
Row{
|
||||
spacing: 12
|
||||
anchors{
|
||||
left: parent.left
|
||||
leftMargin: 10
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Column{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
RowLayout{
|
||||
spacing: 10
|
||||
FluText{
|
||||
text: "cellHeight:"
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
FluSlider{
|
||||
id: slider_cell_height
|
||||
value: 38
|
||||
from: 38
|
||||
to:100
|
||||
}
|
||||
}
|
||||
RowLayout{
|
||||
spacing: 10
|
||||
FluText{
|
||||
text: "depthPadding:"
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
FluSlider{
|
||||
id: slider_depth_padding
|
||||
value: 15
|
||||
from: 15
|
||||
to:100
|
||||
}
|
||||
}
|
||||
}
|
||||
Column{
|
||||
spacing: 8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
FluToggleSwitch{
|
||||
id: switch_showline
|
||||
text:"showLine"
|
||||
checked: false
|
||||
}
|
||||
FluToggleSwitch{
|
||||
id: switch_checkable
|
||||
text:"checkable"
|
||||
checked: false
|
||||
}
|
||||
}
|
||||
Column{
|
||||
spacing: 8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
FluButton{
|
||||
text: "all expand"
|
||||
onClicked: {
|
||||
tree_view.allExpand()
|
||||
}
|
||||
}
|
||||
FluButton{
|
||||
text: "all collapse"
|
||||
onClicked: {
|
||||
tree_view.allCollapse()
|
||||
}
|
||||
}
|
||||
}
|
||||
FluButton{
|
||||
text: "print selection model"
|
||||
onClicked: {
|
||||
var printData = []
|
||||
var data = tree_view.selectionModel();
|
||||
console.debug(data.length)
|
||||
for(var i = 0; i <= data.length-1 ; i++){
|
||||
const newObj = Object.assign({}, data[i].data);
|
||||
delete newObj["__parent"];
|
||||
delete newObj["children"];
|
||||
printData.push(newObj)
|
||||
}
|
||||
console.debug(JSON.stringify(printData))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FluTreeView{
|
||||
id:tree_view
|
||||
anchors{
|
||||
left: parent.left
|
||||
top: layout_controls.bottom
|
||||
topMargin: 10
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
cellHeight: slider_cell_height.value
|
||||
showLine: switch_showline.checked
|
||||
checkable:switch_checkable.checked
|
||||
depthPadding: slider_depth_padding.value
|
||||
onCurrentChanged: {
|
||||
showInfo(current.data.title)
|
||||
}
|
||||
columnSource:[
|
||||
{
|
||||
title: qsTr("Title"),
|
||||
dataIndex: 'title',
|
||||
width: 300
|
||||
},{
|
||||
title: qsTr("Name"),
|
||||
dataIndex: 'name',
|
||||
width: 100
|
||||
},{
|
||||
title: qsTr("Avatar"),
|
||||
dataIndex: 'avatar',
|
||||
width: 100
|
||||
},{
|
||||
title: qsTr("Address"),
|
||||
dataIndex: 'address',
|
||||
width: 200
|
||||
},
|
||||
]
|
||||
Component.onCompleted: {
|
||||
var data = treeData()
|
||||
dataSource = data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ FluWindowDialog {
|
||||
showError(message)
|
||||
}
|
||||
function onSuccess(path){
|
||||
FluTools.showFileInFolder(path+"/CMakeLists.txt")
|
||||
FluTools.showFileInFolder(path)
|
||||
window.close()
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ FluWindow {
|
||||
title: "FluentUI"
|
||||
width: 1000
|
||||
height: 680
|
||||
minimumWidth: 520
|
||||
minimumWidth: 680
|
||||
minimumHeight: 200
|
||||
launchMode: FluWindowType.SingleTask
|
||||
fitsAppBarWindows: true
|
||||
@ -28,6 +28,10 @@ FluWindow {
|
||||
z:7
|
||||
}
|
||||
|
||||
FluentInitializrWindow{
|
||||
id:fluent_Initializr
|
||||
}
|
||||
|
||||
FluEvent{
|
||||
name: "checkUpdate"
|
||||
onTriggered: {
|
||||
|
@ -1,17 +1,15 @@
|
||||
#include "AppInfo.h"
|
||||
|
||||
#include <QQmlContext>
|
||||
#include <QDebug>
|
||||
#include <QGuiApplication>
|
||||
#include "Version.h"
|
||||
|
||||
AppInfo::AppInfo(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
: QObject{parent} {
|
||||
version(APPLICATION_VERSION);
|
||||
}
|
||||
|
||||
void AppInfo::testCrash(){
|
||||
[[maybe_unused]] void AppInfo::testCrash() {
|
||||
auto *crash = reinterpret_cast<volatile int *>(0);
|
||||
*crash = 0;
|
||||
}
|
||||
|
@ -1,20 +1,18 @@
|
||||
#ifndef APPINFO_H
|
||||
#define APPINFO_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include "stdafx.h"
|
||||
#include "singleton.h"
|
||||
|
||||
class AppInfo : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QString,version)
|
||||
class AppInfo : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QString, version)
|
||||
private:
|
||||
explicit AppInfo(QObject *parent = nullptr);
|
||||
public:
|
||||
SINGLETON(AppInfo)
|
||||
Q_INVOKABLE void testCrash();
|
||||
};
|
||||
|
||||
#endif // APPINFO_H
|
||||
public:
|
||||
SINGLETON(AppInfo)
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void testCrash();
|
||||
};
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef APP_DUMP_H
|
||||
#define APP_DUMP_H
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <DbgHelp.h>
|
||||
@ -12,71 +11,69 @@
|
||||
|
||||
#pragma comment(lib, "Dbghelp.lib")
|
||||
|
||||
static void miniDumpWriteDump(HANDLE hProcess,DWORD ProcessId,HANDLE hFile,MINIDUMP_TYPE DumpType,CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam){
|
||||
typedef HRESULT (WINAPI* MiniDumpWriteDumpPtr)(HANDLE hProcess,DWORD ProcessId,HANDLE hFile,MINIDUMP_TYPE DumpType,CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
|
||||
static void
|
||||
miniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam) {
|
||||
typedef HRESULT (WINAPI *MiniDumpWriteDumpPtr)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
||||
CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
|
||||
HMODULE module = LoadLibraryW(L"Dbghelp.dll");
|
||||
if (module)
|
||||
{
|
||||
if (module) {
|
||||
MiniDumpWriteDumpPtr mini_dump_write_dump;
|
||||
mini_dump_write_dump= reinterpret_cast<MiniDumpWriteDumpPtr>(GetProcAddress(module, "MiniDumpWriteDump"));
|
||||
if (mini_dump_write_dump)
|
||||
{
|
||||
mini_dump_write_dump(hProcess,ProcessId,hFile,DumpType,ExceptionParam,UserStreamParam,CallbackParam);
|
||||
mini_dump_write_dump = reinterpret_cast<MiniDumpWriteDumpPtr>(GetProcAddress(module, "MiniDumpWriteDump"));
|
||||
if (mini_dump_write_dump) {
|
||||
mini_dump_write_dump(hProcess, ProcessId, hFile, static_cast<MINIDUMP_TYPE>(80), ExceptionParam, nullptr, CallbackParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CALLBACK MyMiniDumpCallback(PVOID, const PMINIDUMP_CALLBACK_INPUT input, PMINIDUMP_CALLBACK_OUTPUT output) {
|
||||
if (input == NULL || output == NULL)
|
||||
if (input == nullptr || output == nullptr)
|
||||
return FALSE;
|
||||
|
||||
BOOL ret = FALSE;
|
||||
switch (input->CallbackType) {
|
||||
case IncludeModuleCallback:
|
||||
case IncludeThreadCallback:
|
||||
case ThreadCallback:
|
||||
case ThreadExCallback:
|
||||
ret = TRUE;
|
||||
break;
|
||||
case ModuleCallback: {
|
||||
if (!(output->ModuleWriteFlags & ModuleReferencedByMemory)) {
|
||||
output->ModuleWriteFlags &= ~ModuleWriteModule;
|
||||
case IncludeModuleCallback:
|
||||
case IncludeThreadCallback:
|
||||
case ThreadCallback:
|
||||
case ThreadExCallback:
|
||||
ret = TRUE;
|
||||
break;
|
||||
case ModuleCallback: {
|
||||
if (!(output->ModuleWriteFlags & ModuleReferencedByMemory)) {
|
||||
output->ModuleWriteFlags &= ~ModuleWriteModule;
|
||||
}
|
||||
ret = TRUE;
|
||||
}
|
||||
ret = TRUE;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WriteDump(EXCEPTION_POINTERS* exp, const std::wstring& path) {
|
||||
HANDLE h = ::CreateFileW(path.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
void WriteDump(EXCEPTION_POINTERS *exp, const std::wstring &path) {
|
||||
HANDLE h = ::CreateFileW(path.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
MINIDUMP_EXCEPTION_INFORMATION info;
|
||||
info.ThreadId = ::GetCurrentThreadId();
|
||||
info.ExceptionPointers = exp;
|
||||
info.ClientPointers = FALSE;
|
||||
MINIDUMP_CALLBACK_INFORMATION mci;
|
||||
mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MyMiniDumpCallback;
|
||||
mci.CallbackParam = 0;
|
||||
MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory);
|
||||
miniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), h, mdt, &info, NULL, &mci);
|
||||
mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE) MyMiniDumpCallback;
|
||||
mci.CallbackParam = nullptr;
|
||||
miniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), h, &info, &mci);
|
||||
::CloseHandle(h);
|
||||
}
|
||||
|
||||
LONG WINAPI MyUnhandledExceptionFilter(EXCEPTION_POINTERS* exp) {
|
||||
const QString dumpFileName = QString("%1_%2.dmp").arg("crash",QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss"));
|
||||
const QString dumpDirPath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)+"/dmp";
|
||||
LONG WINAPI MyUnhandledExceptionFilter(EXCEPTION_POINTERS *exp) {
|
||||
const QString dumpFileName = QString("%1_%2.dmp").arg("crash", QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss"));
|
||||
const QString dumpDirPath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/dmp";
|
||||
const QDir dumpDir(dumpDirPath);
|
||||
if(!dumpDir.exists()){
|
||||
if (!dumpDir.exists()) {
|
||||
dumpDir.mkpath(dumpDirPath);
|
||||
}
|
||||
QString dumpFilePath = dumpDir.filePath(dumpFileName);
|
||||
WriteDump(exp, dumpFilePath.toStdWString());
|
||||
QStringList arguments;
|
||||
arguments << "-crashed=" + dumpFilePath;
|
||||
QProcess::startDetached(qApp->applicationFilePath(), arguments);
|
||||
QProcess::startDetached(QGuiApplication::applicationFilePath(), arguments);
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
#endif // APP_DUMP_H
|
||||
}
|
@ -3,43 +3,43 @@
|
||||
#include <QQuickItemGrabResult>
|
||||
#include <QPainterPath>
|
||||
|
||||
CircularReveal::CircularReveal(QQuickItem* parent) : QQuickPaintedItem(parent)
|
||||
{
|
||||
CircularReveal::CircularReveal(QQuickItem *parent) : QQuickPaintedItem(parent) {
|
||||
_target = nullptr;
|
||||
_radius = 0;
|
||||
_anim = new QPropertyAnimation(this, "radius", this);
|
||||
setVisible(false);
|
||||
_anim->setDuration(333);
|
||||
_anim->setEasingCurve(QEasingCurve::OutCubic);
|
||||
connect(_anim, &QPropertyAnimation::finished,this,[=](){
|
||||
setVisible(false);
|
||||
connect(_anim, &QPropertyAnimation::finished, this, [=]() {
|
||||
update();
|
||||
setVisible(false);
|
||||
Q_EMIT animationFinished();
|
||||
});
|
||||
connect(this,&CircularReveal::radiusChanged,this,[=](){
|
||||
connect(this, &CircularReveal::radiusChanged, this, [=]() {
|
||||
update();
|
||||
});
|
||||
}
|
||||
|
||||
void CircularReveal::paint(QPainter* painter)
|
||||
{
|
||||
void CircularReveal::paint(QPainter *painter) {
|
||||
painter->save();
|
||||
painter->drawImage(QRect(0, 0, static_cast<int>(width()), static_cast<int>(height())), _source);
|
||||
QPainterPath path;
|
||||
path.moveTo(_center.x(),_center.y());
|
||||
path.addEllipse(QPointF(_center.x(),_center.y()), _radius, _radius);
|
||||
path.moveTo(_center.x(), _center.y());
|
||||
path.addEllipse(QPointF(_center.x(), _center.y()), _radius, _radius);
|
||||
painter->setCompositionMode(QPainter::CompositionMode_Clear);
|
||||
painter->fillPath(path, Qt::black);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void CircularReveal::start(int w,int h,const QPoint& center,int radius){
|
||||
[[maybe_unused]] void CircularReveal::start(int w, int h, const QPoint ¢er, int radius) {
|
||||
_anim->setStartValue(0);
|
||||
_anim->setEndValue(radius);
|
||||
_center = center;
|
||||
_grabResult = _target->grabToImage(QSize(w,h));
|
||||
_grabResult = _target->grabToImage(QSize(w, h));
|
||||
connect(_grabResult.data(), &QQuickItemGrabResult::ready, this, &CircularReveal::handleGrabResult);
|
||||
}
|
||||
|
||||
void CircularReveal::handleGrabResult(){
|
||||
void CircularReveal::handleGrabResult() {
|
||||
_grabResult.data()->image().swap(_source);
|
||||
update();
|
||||
setVisible(true);
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef CIRCULARREVEAL_H
|
||||
#define CIRCULARREVEAL_H
|
||||
#pragma once
|
||||
|
||||
#include <QQuickItem>
|
||||
#include <QQuickPaintedItem>
|
||||
@ -7,23 +6,26 @@
|
||||
#include <QPropertyAnimation>
|
||||
#include "src/stdafx.h"
|
||||
|
||||
class CircularReveal : public QQuickPaintedItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QQuickItem*,target)
|
||||
Q_PROPERTY_AUTO(int,radius)
|
||||
class CircularReveal : public QQuickPaintedItem {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO_P(QQuickItem*, target)
|
||||
Q_PROPERTY_AUTO(int, radius)
|
||||
public:
|
||||
CircularReveal(QQuickItem* parent = nullptr);
|
||||
void paint(QPainter* painter) override;
|
||||
Q_INVOKABLE void start(int w,int h,const QPoint& center,int radius);
|
||||
explicit CircularReveal(QQuickItem *parent = nullptr);
|
||||
|
||||
void paint(QPainter *painter) override;
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void start(int w, int h, const QPoint ¢er, int radius);
|
||||
|
||||
Q_SIGNAL void imageChanged();
|
||||
|
||||
Q_SIGNAL void animationFinished();
|
||||
|
||||
Q_SLOT void handleGrabResult();
|
||||
|
||||
private:
|
||||
QPropertyAnimation* _anim = nullptr;
|
||||
QPropertyAnimation *_anim = nullptr;
|
||||
QImage _source;
|
||||
QPoint _center;
|
||||
QSharedPointer<QQuickItemGrabResult> _grabResult;
|
||||
QSharedPointer<QQuickItemGrabResult> _grabResult;
|
||||
};
|
||||
|
||||
#endif // CIRCULARREVEAL_H
|
||||
|
@ -1,24 +1,23 @@
|
||||
#include "FileWatcher.h"
|
||||
|
||||
FileWatcher::FileWatcher(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
connect(&_watcher, &QFileSystemWatcher::fileChanged, this, [=](const QString &path){
|
||||
FileWatcher::FileWatcher(QObject *parent) : QObject{parent} {
|
||||
connect(&_watcher, &QFileSystemWatcher::fileChanged, this, [=](const QString &path) {
|
||||
Q_EMIT fileChanged();
|
||||
clean();
|
||||
_watcher.addPath(_path);
|
||||
});
|
||||
connect(this,&FileWatcher::pathChanged,this,[=](){
|
||||
connect(this, &FileWatcher::pathChanged, this, [=]() {
|
||||
clean();
|
||||
_watcher.addPath(_path.replace("file:///",""));
|
||||
_watcher.addPath(_path.replace("file:///", ""));
|
||||
});
|
||||
if(!_path.isEmpty()){
|
||||
if (!_path.isEmpty()) {
|
||||
_watcher.addPath(_path);
|
||||
}
|
||||
}
|
||||
|
||||
void FileWatcher::clean(){
|
||||
foreach (const QString &item, _watcher.files()) {
|
||||
void FileWatcher::clean() {
|
||||
for (int i = 0; i <= _watcher.files().size() - 1; ++i) {
|
||||
auto item = _watcher.files().at(i);
|
||||
_watcher.removePath(item);
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,21 @@
|
||||
#ifndef FILEWATCHER_H
|
||||
#define FILEWATCHER_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QtQml/qqml.h>
|
||||
#include "src/stdafx.h"
|
||||
|
||||
class FileWatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QString,path);
|
||||
class FileWatcher : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QString, path);
|
||||
public:
|
||||
explicit FileWatcher(QObject *parent = nullptr);
|
||||
|
||||
Q_SIGNAL void fileChanged();
|
||||
|
||||
private:
|
||||
void clean();
|
||||
|
||||
private:
|
||||
QFileSystemWatcher _watcher;
|
||||
};
|
||||
|
||||
#endif // FILEWATCHER_H
|
||||
|
@ -3,16 +3,16 @@
|
||||
#include <QTimer>
|
||||
#include <QQuickWindow>
|
||||
|
||||
FpsItem::FpsItem()
|
||||
{
|
||||
QTimer *timer = new QTimer(this);
|
||||
connect(timer, &QTimer::timeout, this, [this]{
|
||||
FpsItem::FpsItem() {
|
||||
_fps = 0;
|
||||
auto *timer = new QTimer(this);
|
||||
connect(timer, &QTimer::timeout, this, [this] {
|
||||
fps(_frameCount);
|
||||
_frameCount = 0;
|
||||
});
|
||||
connect(this, &QQuickItem::windowChanged, this, [this]{
|
||||
if (window()){
|
||||
connect(window(), &QQuickWindow::afterRendering, this, [this]{ _frameCount++; }, Qt::DirectConnection);
|
||||
connect(this, &QQuickItem::windowChanged, this, [this] {
|
||||
if (window()) {
|
||||
connect(window(), &QQuickWindow::afterRendering, this, [this] { _frameCount++; }, Qt::DirectConnection);
|
||||
}
|
||||
});
|
||||
timer->start(1000);
|
||||
|
@ -1,19 +1,15 @@
|
||||
#ifndef FPSITEM_H
|
||||
#define FPSITEM_H
|
||||
#pragma once
|
||||
|
||||
#include <QQuickItem>
|
||||
#include "src/stdafx.h"
|
||||
|
||||
class FpsItem : public QQuickItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(int,fps)
|
||||
class FpsItem : public QQuickItem {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(int, fps)
|
||||
public:
|
||||
FpsItem();
|
||||
|
||||
private:
|
||||
int _frameCount = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif // FPSITEM_H
|
||||
};
|
93
example/src/component/OpenGLItem.cpp
Normal file
93
example/src/component/OpenGLItem.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include "OpenGLItem.h"
|
||||
|
||||
#include <QOpenGLFramebufferObjectFormat>
|
||||
#include <QOpenGLShaderProgram>
|
||||
|
||||
class FBORenderer : public QQuickFramebufferObject::Renderer, protected QOpenGLFunctions {
|
||||
public:
|
||||
explicit FBORenderer(const OpenGLItem *item);
|
||||
|
||||
void render() override;
|
||||
|
||||
QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override;
|
||||
|
||||
QOpenGLShaderProgram program;
|
||||
const OpenGLItem *item = nullptr;
|
||||
};
|
||||
|
||||
FBORenderer::FBORenderer(const OpenGLItem *item) {
|
||||
this->item = item;
|
||||
initializeOpenGLFunctions();
|
||||
program.addCacheableShaderFromSourceCode(QOpenGLShader::Vertex,
|
||||
"attribute highp vec4 vertices;"
|
||||
"varying highp vec2 coords;"
|
||||
"void main() {"
|
||||
" gl_Position = vertices;"
|
||||
" coords = vertices.xy;"
|
||||
"}");
|
||||
program.addCacheableShaderFromSourceCode(QOpenGLShader::Fragment,
|
||||
"uniform lowp float t;"
|
||||
"varying highp vec2 coords;"
|
||||
"void main() {"
|
||||
" lowp float i = 1. - (pow(abs(coords.x), 4.) + pow(abs(coords.y), 4.));"
|
||||
" i = smoothstep(t - 0.8, t + 0.8, i);"
|
||||
" i = floor(i * 20.) / 20.;"
|
||||
" gl_FragColor = vec4(coords * .5 + .5, i, i);"
|
||||
"}");
|
||||
|
||||
program.bindAttributeLocation("vertices", 0);
|
||||
program.link();
|
||||
}
|
||||
|
||||
QOpenGLFramebufferObject *FBORenderer::createFramebufferObject(const QSize &size) {
|
||||
QOpenGLFramebufferObjectFormat format;
|
||||
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
|
||||
format.setSamples(4);
|
||||
return new QOpenGLFramebufferObject(size, format);
|
||||
}
|
||||
|
||||
void FBORenderer::render() {
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
program.bind();
|
||||
program.enableAttributeArray(0);
|
||||
float values[] = {
|
||||
-1, -1,
|
||||
1, -1,
|
||||
-1, 1,
|
||||
1, 1
|
||||
};
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
program.setAttributeArray(0, GL_FLOAT, values, 2);
|
||||
program.setUniformValue("t", (float) item->t());
|
||||
glViewport(0, 0, qRound(item->width()), qRound(item->height()));
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
program.disableAttributeArray(0);
|
||||
program.release();
|
||||
}
|
||||
|
||||
|
||||
OpenGLItem::OpenGLItem(QQuickItem *parent) : QQuickFramebufferObject(parent) {
|
||||
setMirrorVertically(true);
|
||||
startTimer(1);
|
||||
}
|
||||
|
||||
void OpenGLItem::timerEvent(QTimerEvent *) {
|
||||
update();
|
||||
}
|
||||
|
||||
void OpenGLItem::setT(qreal t) {
|
||||
if (t == m_t)
|
||||
return;
|
||||
m_t = t;
|
||||
emit tChanged();
|
||||
}
|
||||
|
||||
|
||||
QQuickFramebufferObject::Renderer *OpenGLItem::createRenderer() const {
|
||||
return new FBORenderer(this);
|
||||
}
|
29
example/src/component/OpenGLItem.h
Normal file
29
example/src/component/OpenGLItem.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtQuick/QQuickItem>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QQuickFramebufferObject>
|
||||
|
||||
class FBORenderer;
|
||||
|
||||
class OpenGLItem : public QQuickFramebufferObject, protected QOpenGLFunctions {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged)
|
||||
public:
|
||||
explicit OpenGLItem(QQuickItem *parent = nullptr);
|
||||
|
||||
[[nodiscard]] QQuickFramebufferObject::Renderer *createRenderer() const override;
|
||||
|
||||
void timerEvent(QTimerEvent *) override;
|
||||
|
||||
[[nodiscard]] qreal t() const { return m_t; }
|
||||
|
||||
void setT(qreal t);
|
||||
|
||||
signals:
|
||||
|
||||
void tChanged();
|
||||
|
||||
private:
|
||||
qreal m_t{};
|
||||
};
|
@ -3,55 +3,47 @@
|
||||
#include <QDir>
|
||||
#include <QGuiApplication>
|
||||
|
||||
InitializrHelper::InitializrHelper(QObject *parent) : QObject(parent)
|
||||
{
|
||||
[[maybe_unused]] InitializrHelper::InitializrHelper(QObject *parent) : QObject(parent) {
|
||||
|
||||
}
|
||||
|
||||
InitializrHelper::~InitializrHelper() = default;
|
||||
|
||||
bool InitializrHelper::copyDir(const QDir& fromDir, const QDir& toDir, bool coverIfFileExists){
|
||||
QDir _formDir = fromDir;
|
||||
bool InitializrHelper::copyDir(const QDir &fromDir, const QDir &toDir, bool coverIfFileExists) {
|
||||
const QDir &_formDir = fromDir;
|
||||
QDir _toDir = toDir;
|
||||
if(!_toDir.exists())
|
||||
{
|
||||
if(!_toDir.mkdir(toDir.absolutePath()))
|
||||
if (!_toDir.exists()) {
|
||||
if (!_toDir.mkdir(toDir.absolutePath()))
|
||||
return false;
|
||||
}
|
||||
QFileInfoList fileInfoList = _formDir.entryInfoList();
|
||||
foreach(QFileInfo fileInfo, fileInfoList)
|
||||
{
|
||||
if(fileInfo.fileName() == "." || fileInfo.fileName() == "..")
|
||||
continue;
|
||||
if(fileInfo.isDir())
|
||||
{
|
||||
if(!copyDir(fileInfo.filePath(), _toDir.filePath(fileInfo.fileName()),true))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(coverIfFileExists && _toDir.exists(fileInfo.fileName()))
|
||||
{
|
||||
_toDir.remove(fileInfo.fileName());
|
||||
}
|
||||
if(!QFile::copy(fileInfo.filePath(), _toDir.filePath(fileInfo.fileName())))
|
||||
{
|
||||
return false;
|
||||
foreach(QFileInfo fileInfo, fileInfoList) {
|
||||
if (fileInfo.fileName() == "." || fileInfo.fileName() == "..")
|
||||
continue;
|
||||
if (fileInfo.isDir()) {
|
||||
if (!copyDir(fileInfo.filePath(), _toDir.filePath(fileInfo.fileName()), true))
|
||||
return false;
|
||||
} else {
|
||||
if (coverIfFileExists && _toDir.exists(fileInfo.fileName())) {
|
||||
_toDir.remove(fileInfo.fileName());
|
||||
}
|
||||
if (!QFile::copy(fileInfo.filePath(), _toDir.filePath(fileInfo.fileName()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename...Args>
|
||||
void InitializrHelper::templateToFile(const QString& source,const QString& dest,Args &&...args){
|
||||
template<typename...Args>
|
||||
void InitializrHelper::templateToFile(const QString &source, const QString &dest, Args &&...args) {
|
||||
QFile file(source);
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QTextStream in(&file);
|
||||
QString content = in.readAll().arg(std::forward<Args>(args)...);
|
||||
file.close();
|
||||
QDir outputDir = QFileInfo(dest).absoluteDir();
|
||||
if(!outputDir.exists()){
|
||||
if (!outputDir.exists()) {
|
||||
outputDir.mkpath(outputDir.absolutePath());
|
||||
}
|
||||
QFile outputFile(dest);
|
||||
@ -67,43 +59,43 @@ void InitializrHelper::templateToFile(const QString& source,const QString& dest,
|
||||
}
|
||||
}
|
||||
|
||||
void InitializrHelper::copyFile(const QString& source,const QString& dest){
|
||||
QFile::copy(source,dest);
|
||||
void InitializrHelper::copyFile(const QString &source, const QString &dest) {
|
||||
QFile::copy(source, dest);
|
||||
QFile::setPermissions(dest, QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther);
|
||||
}
|
||||
|
||||
void InitializrHelper::generate(const QString& name,const QString& path){
|
||||
if(name.isEmpty()){
|
||||
[[maybe_unused]] void InitializrHelper::generate(const QString &name, const QString &path) {
|
||||
if (name.isEmpty()) {
|
||||
error(tr("The name cannot be empty"));
|
||||
return;
|
||||
}
|
||||
if(path.isEmpty()){
|
||||
if (path.isEmpty()) {
|
||||
error(tr("The creation path cannot be empty"));
|
||||
return;
|
||||
}
|
||||
QDir projectRootDir(path);
|
||||
if(!projectRootDir.exists()){
|
||||
if (!projectRootDir.exists()) {
|
||||
error(tr("The path does not exist"));
|
||||
return;
|
||||
}
|
||||
QString projectPath = projectRootDir.filePath(name);
|
||||
QDir projectDir(projectPath);
|
||||
if(projectDir.exists()){
|
||||
if (projectDir.exists()) {
|
||||
error(tr("%1 folder already exists").arg(name));
|
||||
return;
|
||||
}
|
||||
projectDir.mkpath(projectPath);
|
||||
QDir fluentDir(projectDir.filePath("FluentUI"));
|
||||
copyDir(QDir(QGuiApplication::applicationDirPath()+"/source"),fluentDir);
|
||||
templateToFile(":/example/res/template/CMakeLists.txt.in",projectDir.filePath("CMakeLists.txt"),name);
|
||||
templateToFile(":/example/res/template/src/CMakeLists.txt.in",projectDir.filePath("src/CMakeLists.txt"),name);
|
||||
templateToFile(":/example/res/template/src/main.cpp.in",projectDir.filePath("src/main.cpp"),name);
|
||||
templateToFile(":/example/res/template/src/main.qml.in",projectDir.filePath("src/main.qml"),name);
|
||||
templateToFile(":/example/res/template/src/en_US.ts.in",projectDir.filePath("src/"+name+"_en_US.ts"),name);
|
||||
templateToFile(":/example/res/template/src/zh_CN.ts.in",projectDir.filePath("src/"+name+"_zh_CN.ts"),name);
|
||||
copyFile(":/example/res/template/src/App.qml.in",projectDir.filePath("src/App.qml"));
|
||||
copyFile(":/example/res/template/src/qml.qrc.in",projectDir.filePath("src/qml.qrc"));
|
||||
copyFile(":/example/res/template/src/logo.ico.in",projectDir.filePath("src/logo.ico"));
|
||||
copyFile(":/example/res/template/src/README.md.in",projectDir.filePath("src/README.md"));
|
||||
return this->success(projectPath);
|
||||
copyDir(QDir(QGuiApplication::applicationDirPath() + "/source"), fluentDir);
|
||||
templateToFile(":/example/res/template/CMakeLists.txt.in", projectDir.filePath("CMakeLists.txt"), name);
|
||||
templateToFile(":/example/res/template/src/CMakeLists.txt.in", projectDir.filePath("src/CMakeLists.txt"), name);
|
||||
templateToFile(":/example/res/template/src/main.cpp.in", projectDir.filePath("src/main.cpp"), name);
|
||||
templateToFile(":/example/res/template/src/main.qml.in", projectDir.filePath("src/main.qml"), name);
|
||||
templateToFile(":/example/res/template/src/en_US.ts.in", projectDir.filePath("src/" + name + "_en_US.ts"), name);
|
||||
templateToFile(":/example/res/template/src/zh_CN.ts.in", projectDir.filePath("src/" + name + "_zh_CN.ts"), name);
|
||||
copyFile(":/example/res/template/src/App.qml.in", projectDir.filePath("src/App.qml"));
|
||||
copyFile(":/example/res/template/src/qml.qrc.in", projectDir.filePath("src/qml.qrc"));
|
||||
copyFile(":/example/res/template/src/logo.ico.in", projectDir.filePath("src/logo.ico"));
|
||||
copyFile(":/example/res/template/src/README.md.in", projectDir.filePath("src/README.md"));
|
||||
return this->success(projectPath+"/CMakeLists.txt");
|
||||
}
|
||||
|
@ -1,26 +1,30 @@
|
||||
#ifndef INITIALIZRHELPER_H
|
||||
#define INITIALIZRHELPER_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QtQml/qqml.h>
|
||||
#include <QDir>
|
||||
#include "src/singleton.h"
|
||||
|
||||
class InitializrHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
class InitializrHelper : public QObject {
|
||||
Q_OBJECT
|
||||
private:
|
||||
explicit InitializrHelper(QObject* parent = nullptr);
|
||||
bool copyDir(const QDir& fromDir, const QDir& toDir, bool coverIfFileExists = true);
|
||||
void copyFile(const QString& source,const QString& dest);
|
||||
template <typename...Args>
|
||||
void templateToFile(const QString& source,const QString& dest,Args &&...args);
|
||||
public:
|
||||
SINGLETON(InitializrHelper)
|
||||
~InitializrHelper() override;
|
||||
Q_INVOKABLE void generate(const QString& name,const QString& path);
|
||||
Q_SIGNAL void error(const QString& message);
|
||||
Q_SIGNAL void success(const QString& path);
|
||||
};
|
||||
[[maybe_unused]] explicit InitializrHelper(QObject *parent = nullptr);
|
||||
|
||||
#endif // INITIALIZRHELPER_H
|
||||
bool copyDir(const QDir &fromDir, const QDir &toDir, bool coverIfFileExists = true);
|
||||
|
||||
static void copyFile(const QString &source, const QString &dest);
|
||||
|
||||
template<typename...Args>
|
||||
void templateToFile(const QString &source, const QString &dest, Args &&...args);
|
||||
|
||||
public:
|
||||
SINGLETON(InitializrHelper)
|
||||
|
||||
~InitializrHelper() override;
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void generate(const QString &name, const QString &path);
|
||||
|
||||
Q_SIGNAL void error(const QString &message);
|
||||
|
||||
Q_SIGNAL void success(const QString &path);
|
||||
};
|
||||
|
@ -11,8 +11,11 @@
|
||||
#include <QSettings>
|
||||
#include <QRegularExpression>
|
||||
#include "Version.h"
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include <process.h>
|
||||
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@ -26,7 +29,7 @@
|
||||
#endif
|
||||
|
||||
static QString g_app = {};
|
||||
static QString g_file_path= {};
|
||||
static QString g_file_path = {};
|
||||
static bool g_logError = false;
|
||||
|
||||
static std::unique_ptr<QFile> g_logFile = nullptr;
|
||||
@ -35,15 +38,14 @@ static std::unique_ptr<QTextStream> g_logStream = nullptr;
|
||||
static int g_logLevel = 4;
|
||||
|
||||
std::map<QtMsgType, int> logLevelMap = {
|
||||
{QtFatalMsg,0},
|
||||
{QtCriticalMsg,1},
|
||||
{QtWarningMsg,2},
|
||||
{QtInfoMsg,3},
|
||||
{QtDebugMsg,4}
|
||||
{QtFatalMsg, 0},
|
||||
{QtCriticalMsg, 1},
|
||||
{QtWarningMsg, 2},
|
||||
{QtInfoMsg, 3},
|
||||
{QtDebugMsg, 4}
|
||||
};
|
||||
|
||||
QString Log::prettyProductInfoWrapper()
|
||||
{
|
||||
QString Log::prettyProductInfoWrapper() {
|
||||
auto productName = QSysInfo::prettyProductName();
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
|
||||
#if defined(Q_OS_MACOS)
|
||||
@ -70,20 +72,17 @@ QString Log::prettyProductInfoWrapper()
|
||||
#endif
|
||||
#endif
|
||||
#if defined(Q_OS_WIN)
|
||||
QSettings regKey {QString::fromUtf8("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), QSettings::NativeFormat};
|
||||
QSettings regKey{QString::fromUtf8(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion)"), QSettings::NativeFormat};
|
||||
if (regKey.contains(QString::fromUtf8("CurrentBuildNumber"))) {
|
||||
auto buildNumber = regKey.value(QString::fromUtf8("CurrentBuildNumber")).toInt();
|
||||
if (buildNumber > 0) {
|
||||
if (buildNumber < 9200) {
|
||||
productName = QString::fromUtf8("Windows 7 build %1").arg(buildNumber);
|
||||
}
|
||||
else if (buildNumber < 10240) {
|
||||
} else if (buildNumber < 10240) {
|
||||
productName = QString::fromUtf8("Windows 8 build %1").arg(buildNumber);
|
||||
}
|
||||
else if (buildNumber < 22000) {
|
||||
} else if (buildNumber < 22000) {
|
||||
productName = QString::fromUtf8("Windows 10 build %1").arg(buildNumber);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
productName = QString::fromUtf8("Windows 11 build %1").arg(buildNumber);
|
||||
}
|
||||
}
|
||||
@ -92,56 +91,55 @@ QString Log::prettyProductInfoWrapper()
|
||||
return productName;
|
||||
}
|
||||
|
||||
static inline void messageHandler(const QtMsgType type, const QMessageLogContext &context, const QString &message)
|
||||
{
|
||||
if(message == "Could not get the INetworkConnection instance for the adapter GUID."){
|
||||
static inline void messageHandler(const QtMsgType type, const QMessageLogContext &context, const QString &message) {
|
||||
if (message == "Could not get the INetworkConnection instance for the adapter GUID.") {
|
||||
return;
|
||||
}
|
||||
if(logLevelMap[type]>g_logLevel){
|
||||
if (logLevelMap[type] > g_logLevel) {
|
||||
return;
|
||||
}
|
||||
if (!message.isEmpty()) {
|
||||
QString levelName;
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
levelName = QStringLiteral("Debug");
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
levelName = QStringLiteral("Info");
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
levelName = QStringLiteral("Warning");
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
levelName = QStringLiteral("Critical");
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
levelName = QStringLiteral("Fatal");
|
||||
break;
|
||||
case QtDebugMsg:
|
||||
levelName = QStringLiteral("Debug");
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
levelName = QStringLiteral("Info");
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
levelName = QStringLiteral("Warning");
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
levelName = QStringLiteral("Critical");
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
levelName = QStringLiteral("Fatal");
|
||||
break;
|
||||
}
|
||||
QString fileAndLineLogStr;
|
||||
if(context.file){
|
||||
if (context.file) {
|
||||
std::string strFileTmp = context.file;
|
||||
const char* ptr = strrchr(strFileTmp.c_str(), '/');
|
||||
const char *ptr = strrchr(strFileTmp.c_str(), '/');
|
||||
if (nullptr != ptr) {
|
||||
char fn[512] = {0};
|
||||
sprintf(fn, "%s", ptr + 1);
|
||||
strFileTmp = fn;
|
||||
}
|
||||
const char* ptrTmp = strrchr(strFileTmp.c_str(), '\\');
|
||||
const char *ptrTmp = strrchr(strFileTmp.c_str(), '\\');
|
||||
if (nullptr != ptrTmp) {
|
||||
char fn[512] = {0};
|
||||
sprintf(fn, "%s", ptrTmp + 1);
|
||||
strFileTmp = fn;
|
||||
}
|
||||
fileAndLineLogStr = QString::fromStdString("[%1:%2]").arg(QString::fromStdString(strFileTmp),QString::number(context.line));
|
||||
fileAndLineLogStr = QString::fromStdString("[%1:%2]").arg(QString::fromStdString(strFileTmp), QString::number(context.line));
|
||||
}
|
||||
const QString finalMessage = QString::fromStdString("%1[%2]%3[%4]:%5").arg(
|
||||
QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss.zzz"),
|
||||
levelName,
|
||||
fileAndLineLogStr,
|
||||
QString::number(reinterpret_cast<quintptr>(QThread::currentThreadId())),
|
||||
message);
|
||||
QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss.zzz"),
|
||||
levelName,
|
||||
fileAndLineLogStr,
|
||||
QString::number(reinterpret_cast<quintptr>(QThread::currentThreadId())),
|
||||
message);
|
||||
if ((type == QtInfoMsg) || (type == QtDebugMsg)) {
|
||||
std::cout << qPrintable(finalMessage) << std::endl;
|
||||
} else {
|
||||
@ -168,8 +166,7 @@ static inline void messageHandler(const QtMsgType type, const QMessageLogContext
|
||||
}
|
||||
}
|
||||
|
||||
void Log::setup(char *argv[],const QString &app,int level)
|
||||
{
|
||||
void Log::setup(char *argv[], const QString &app, int level) {
|
||||
Q_ASSERT(!app.isEmpty());
|
||||
if (app.isEmpty()) {
|
||||
return;
|
||||
@ -182,30 +179,30 @@ void Log::setup(char *argv[],const QString &app,int level)
|
||||
QString applicationPath = QString::fromStdString(argv[0]);
|
||||
once = true;
|
||||
g_app = app;
|
||||
const QString logFileName = QString("%1_%2.log").arg(g_app,QDateTime::currentDateTime().toString("yyyyMMdd"));
|
||||
const QString logDirPath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)+"/log";
|
||||
const QString logFileName = QString("%1_%2.log").arg(g_app, QDateTime::currentDateTime().toString("yyyyMMdd"));
|
||||
const QString logDirPath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/log";
|
||||
const QDir logDir(logDirPath);
|
||||
if(!logDir.exists()){
|
||||
if (!logDir.exists()) {
|
||||
logDir.mkpath(logDirPath);
|
||||
}
|
||||
g_file_path = logDir.filePath(logFileName);
|
||||
qInstallMessageHandler(messageHandler);
|
||||
qInfo()<<"===================================================";
|
||||
qInfo()<<"[AppName]"<<g_app;
|
||||
qInfo()<<"[AppVersion]"<<APPLICATION_VERSION;
|
||||
qInfo()<<"[AppPath]"<<applicationPath;
|
||||
qInfo()<<"[QtVersion]"<<QT_VERSION_STR;
|
||||
qInfo() << "===================================================";
|
||||
qInfo() << "[AppName]" << g_app;
|
||||
qInfo() << "[AppVersion]" << APPLICATION_VERSION;
|
||||
qInfo() << "[AppPath]" << applicationPath;
|
||||
qInfo() << "[QtVersion]" << QT_VERSION_STR;
|
||||
#ifdef WIN32
|
||||
qInfo()<<"[ProcessId]"<<QString::number(_getpid());
|
||||
qInfo() << "[ProcessId]" << QString::number(_getpid());
|
||||
#else
|
||||
qInfo()<<"[ProcessId]"<<QString::number(getpid());
|
||||
#endif
|
||||
qInfo()<<"[GitHashCode]"<<COMMIT_HASH;
|
||||
qInfo()<<"[DeviceInfo]";
|
||||
qInfo()<<" [DeviceId]"<<QSysInfo::machineUniqueId();
|
||||
qInfo()<<" [Manufacturer]"<<prettyProductInfoWrapper();
|
||||
qInfo()<<" [CPU_ABI]"<<QSysInfo::currentCpuArchitecture();
|
||||
qInfo()<<"[LOG_LEVEL]"<<g_logLevel;
|
||||
qInfo()<<"[LOG_PATH]"<<g_file_path;
|
||||
qInfo()<<"===================================================";
|
||||
qInfo() << "[GitHashCode]" << COMMIT_HASH;
|
||||
qInfo() << "[DeviceInfo]";
|
||||
qInfo() << " [DeviceId]" << QSysInfo::machineUniqueId();
|
||||
qInfo() << " [Manufacturer]" << prettyProductInfoWrapper();
|
||||
qInfo() << " [CPU_ABI]" << QSysInfo::currentCpuArchitecture();
|
||||
qInfo() << "[LOG_LEVEL]" << g_logLevel;
|
||||
qInfo() << "[LOG_PATH]" << g_file_path;
|
||||
qInfo() << "===================================================";
|
||||
}
|
||||
|
@ -1,11 +1,9 @@
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qstring.h>
|
||||
|
||||
namespace Log
|
||||
{
|
||||
namespace Log {
|
||||
QString prettyProductInfoWrapper();
|
||||
void setup(char *argv[], const QString &app,int level = 4);
|
||||
}
|
||||
|
||||
#endif // LOG_H
|
||||
void setup(char *argv[], const QString &app, int level = 4);
|
||||
}
|
@ -17,175 +17,174 @@
|
||||
#include <QCryptographicHash>
|
||||
#include <QEventLoop>
|
||||
#include <QGuiApplication>
|
||||
#include <utility>
|
||||
|
||||
NetworkCallable::NetworkCallable(QObject *parent):QObject{parent}{
|
||||
|
||||
NetworkCallable::NetworkCallable(QObject *parent) : QObject{parent} {
|
||||
|
||||
}
|
||||
|
||||
QString NetworkParams::method2String(){
|
||||
QString NetworkParams::method2String() const {
|
||||
switch (_method) {
|
||||
case METHOD_GET:
|
||||
return "GET";
|
||||
case METHOD_HEAD:
|
||||
return "HEAD";
|
||||
case METHOD_POST:
|
||||
return "POST";
|
||||
case METHOD_PUT:
|
||||
return "PUT";
|
||||
case METHOD_PATCH:
|
||||
return "PATCH";
|
||||
case METHOD_DELETE:
|
||||
return "DELETE";
|
||||
default:
|
||||
return "";
|
||||
case METHOD_GET:
|
||||
return "GET";
|
||||
case METHOD_HEAD:
|
||||
return "HEAD";
|
||||
case METHOD_POST:
|
||||
return "POST";
|
||||
case METHOD_PUT:
|
||||
return "PUT";
|
||||
case METHOD_PATCH:
|
||||
return "PATCH";
|
||||
case METHOD_DELETE:
|
||||
return "DELETE";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
int NetworkParams::getTimeout(){
|
||||
if(_timeout != -1){
|
||||
int NetworkParams::getTimeout() const {
|
||||
if (_timeout != -1) {
|
||||
return _timeout;
|
||||
}
|
||||
return Network::getInstance()->timeout();
|
||||
}
|
||||
|
||||
int NetworkParams::getRetry(){
|
||||
if(_retry != -1){
|
||||
int NetworkParams::getRetry() const {
|
||||
if (_retry != -1) {
|
||||
return _retry;
|
||||
}
|
||||
return Network::getInstance()->retry();
|
||||
}
|
||||
|
||||
bool NetworkParams::getOpenLog(){
|
||||
if(!_openLog.isNull()){
|
||||
bool NetworkParams::getOpenLog() const {
|
||||
if (!_openLog.isNull()) {
|
||||
return _openLog.toBool();
|
||||
}
|
||||
return Network::getInstance()->openLog();
|
||||
}
|
||||
|
||||
FluDownloadParam::FluDownloadParam(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
: QObject{parent} {
|
||||
}
|
||||
|
||||
FluDownloadParam::FluDownloadParam(QString destPath,bool append,QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
this->_destPath = destPath;
|
||||
FluDownloadParam::FluDownloadParam(QString destPath, bool append, QObject *parent)
|
||||
: QObject{parent} {
|
||||
this->_destPath = std::move(destPath);
|
||||
this->_append = append;
|
||||
}
|
||||
|
||||
NetworkParams::NetworkParams(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
NetworkParams::NetworkParams(QObject *parent) : QObject{parent} {
|
||||
_method = NetworkParams::Method::METHOD_GET;
|
||||
_type = NetworkParams::Type::TYPE_BODY;
|
||||
}
|
||||
|
||||
NetworkParams::NetworkParams(QString url,Type type,Method method,QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
NetworkParams::NetworkParams(QString url, Type type, Method method, QObject *parent)
|
||||
: QObject{parent} {
|
||||
this->_method = method;
|
||||
this->_url = url;
|
||||
this->_url = std::move(url);
|
||||
this->_type = type;
|
||||
}
|
||||
|
||||
NetworkParams* NetworkParams::add(QString key,QVariant val){
|
||||
_paramMap.insert(key,val);
|
||||
NetworkParams *NetworkParams::add(const QString &key, const QVariant &val) {
|
||||
_paramMap.insert(key, val);
|
||||
return this;
|
||||
}
|
||||
|
||||
NetworkParams* NetworkParams::addFile(QString key,QVariant val){
|
||||
_fileMap.insert(key,val);
|
||||
NetworkParams *NetworkParams::addFile(const QString &key, const QVariant &val) {
|
||||
_fileMap.insert(key, val);
|
||||
return this;
|
||||
}
|
||||
|
||||
NetworkParams* NetworkParams::addHeader(QString key,QVariant val){
|
||||
_headerMap.insert(key,val);
|
||||
NetworkParams *NetworkParams::addHeader(const QString &key, const QVariant &val) {
|
||||
_headerMap.insert(key, val);
|
||||
return this;
|
||||
}
|
||||
|
||||
NetworkParams* NetworkParams::addQuery(QString key,QVariant val){
|
||||
_queryMap.insert(key,val);
|
||||
NetworkParams *NetworkParams::addQuery(const QString &key, const QVariant &val) {
|
||||
_queryMap.insert(key, val);
|
||||
return this;
|
||||
}
|
||||
|
||||
NetworkParams* NetworkParams::setBody(QString val){
|
||||
_body = val;
|
||||
NetworkParams *NetworkParams::setBody(QString val) {
|
||||
_body = std::move(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
NetworkParams* NetworkParams::setTimeout(int val){
|
||||
NetworkParams *NetworkParams::setTimeout(int val) {
|
||||
_timeout = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
NetworkParams* NetworkParams::setRetry(int val){
|
||||
NetworkParams *NetworkParams::setRetry(int val) {
|
||||
_retry = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
NetworkParams* NetworkParams::setCacheMode(int val){
|
||||
NetworkParams *NetworkParams::setCacheMode(int val) {
|
||||
_cacheMode = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
NetworkParams* NetworkParams::toDownload(QString destPath,bool append){
|
||||
_downloadParam = new FluDownloadParam(destPath,append,this);
|
||||
NetworkParams *NetworkParams::toDownload(QString destPath, bool append) {
|
||||
_downloadParam = new FluDownloadParam(std::move(destPath), append, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
NetworkParams* NetworkParams::bind(QObject* target){
|
||||
NetworkParams *NetworkParams::bind(QObject *target) {
|
||||
_target = target;
|
||||
return this;
|
||||
}
|
||||
|
||||
NetworkParams* NetworkParams::openLog(QVariant val){
|
||||
_openLog = val;
|
||||
NetworkParams *NetworkParams::openLog(QVariant val) {
|
||||
_openLog = std::move(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
QString NetworkParams::buildCacheKey(){
|
||||
QString NetworkParams::buildCacheKey() const {
|
||||
QJsonObject obj;
|
||||
obj.insert("url",_url);
|
||||
obj.insert("method",method2String());
|
||||
obj.insert("body",_body);
|
||||
obj.insert("query",QJsonDocument::fromVariant(_queryMap).object());
|
||||
obj.insert("param",QJsonDocument::fromVariant(_paramMap).object());
|
||||
obj.insert("header",QJsonDocument::fromVariant(_headerMap).object());
|
||||
obj.insert("file",QJsonDocument::fromVariant(_fileMap).object());
|
||||
if(_downloadParam){
|
||||
obj.insert("url", _url);
|
||||
obj.insert("method", method2String());
|
||||
obj.insert("body", _body);
|
||||
obj.insert("query", QJsonDocument::fromVariant(_queryMap).object());
|
||||
obj.insert("param", QJsonDocument::fromVariant(_paramMap).object());
|
||||
obj.insert("header", QJsonDocument::fromVariant(_headerMap).object());
|
||||
obj.insert("file", QJsonDocument::fromVariant(_fileMap).object());
|
||||
if (_downloadParam) {
|
||||
QJsonObject downObj;
|
||||
downObj.insert("destPath",_downloadParam->_destPath);
|
||||
downObj.insert("append",_downloadParam->_append);
|
||||
obj.insert("download",downObj);
|
||||
downObj.insert("destPath", _downloadParam->_destPath);
|
||||
downObj.insert("append", _downloadParam->_append);
|
||||
obj.insert("download", downObj);
|
||||
}
|
||||
QByteArray data = QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
||||
return QCryptographicHash::hash(data, QCryptographicHash::Sha256).toHex();
|
||||
}
|
||||
|
||||
void NetworkParams::go(NetworkCallable* callable){
|
||||
void NetworkParams::go(NetworkCallable *callable) {
|
||||
QJSValueList data;
|
||||
data<<qjsEngine(callable)->newQObject(this);
|
||||
data << qjsEngine(callable)->newQObject(this);
|
||||
Network::getInstance()->_interceptor.call(data);
|
||||
if(_downloadParam){
|
||||
Network::getInstance()->handleDownload(this,callable);
|
||||
}else{
|
||||
Network::getInstance()->handle(this,callable);
|
||||
if (_downloadParam) {
|
||||
Network::getInstance()->handleDownload(this, callable);
|
||||
} else {
|
||||
Network::getInstance()->handle(this, callable);
|
||||
}
|
||||
}
|
||||
|
||||
void Network::handle(NetworkParams* params,NetworkCallable* c){
|
||||
void Network::handle(NetworkParams *params, NetworkCallable *c) {
|
||||
QPointer<NetworkCallable> callable(c);
|
||||
QThreadPool::globalInstance()->start([=](){
|
||||
if(!callable.isNull()){
|
||||
QThreadPool::globalInstance()->start([=]() {
|
||||
if (!callable.isNull()) {
|
||||
callable->start();
|
||||
}
|
||||
QString cacheKey = params->buildCacheKey();
|
||||
if(params->_cacheMode == NetworkType::CacheMode::FirstCacheThenRequest && cacheExists(cacheKey)){
|
||||
if(!callable.isNull()){
|
||||
if (params->_cacheMode == NetworkType::CacheMode::FirstCacheThenRequest && cacheExists(cacheKey)) {
|
||||
if (!callable.isNull()) {
|
||||
callable->cache(readCache(cacheKey));
|
||||
}
|
||||
}
|
||||
if(params->_cacheMode == NetworkType::CacheMode::IfNoneCacheRequest && cacheExists(cacheKey)){
|
||||
if(!callable.isNull()){
|
||||
if (params->_cacheMode == NetworkType::CacheMode::IfNoneCacheRequest && cacheExists(cacheKey)) {
|
||||
if (!callable.isNull()) {
|
||||
callable->cache(readCache(cacheKey));
|
||||
callable->finish();
|
||||
params->deleteLater();
|
||||
@ -195,131 +194,130 @@ void Network::handle(NetworkParams* params,NetworkCallable* c){
|
||||
QNetworkAccessManager manager;
|
||||
manager.setTransferTimeout(params->getTimeout());
|
||||
QEventLoop loop;
|
||||
connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();});
|
||||
for (int i = 0; i < params->getRetry(); ++i) {
|
||||
connect(&manager, &QNetworkAccessManager::finished, &manager, [&loop](QNetworkReply *reply) { loop.quit(); });
|
||||
for (int i = 0; i <= params->getRetry() - 1; ++i) {
|
||||
QUrl url(params->_url);
|
||||
addQueryParam(&url,params->_queryMap);
|
||||
addQueryParam(&url, params->_queryMap);
|
||||
QNetworkRequest request(url);
|
||||
addHeaders(&request,params->_headerMap);
|
||||
QNetworkReply* reply;
|
||||
sendRequest(&manager,request,params,reply,i==0,callable);
|
||||
if(!QPointer<QGuiApplication>(qApp)){
|
||||
addHeaders(&request, params->_headerMap);
|
||||
QNetworkReply *reply;
|
||||
sendRequest(&manager, request, params, reply, i == 0, callable);
|
||||
if (!QPointer<QCoreApplication>(QGuiApplication::instance())) {
|
||||
reply->deleteLater();
|
||||
reply = nullptr;
|
||||
return;
|
||||
}
|
||||
auto abortCallable = [&loop,reply,&i,params]{
|
||||
if(reply){
|
||||
auto abortCallable = [reply, &i, params] {
|
||||
if (reply) {
|
||||
i = params->getRetry();
|
||||
reply->abort();
|
||||
}
|
||||
};
|
||||
QMetaObject::Connection conn_destroyed = {};
|
||||
QMetaObject::Connection conn_quit = {};
|
||||
if(params->_target){
|
||||
conn_destroyed = connect(params->_target,&QObject::destroyed,&manager,abortCallable);
|
||||
if (params->_target) {
|
||||
conn_destroyed = connect(params->_target, &QObject::destroyed, &manager, abortCallable);
|
||||
}
|
||||
conn_quit = connect(qApp,&QGuiApplication::aboutToQuit,&manager, abortCallable);
|
||||
conn_quit = connect(QGuiApplication::instance(), &QGuiApplication::aboutToQuit, &manager, abortCallable);
|
||||
loop.exec();
|
||||
if(conn_destroyed){
|
||||
if (conn_destroyed) {
|
||||
disconnect(conn_destroyed);
|
||||
}
|
||||
if(conn_quit){
|
||||
if (conn_quit) {
|
||||
disconnect(conn_quit);
|
||||
}
|
||||
QString response;
|
||||
if(params->_method == NetworkParams::METHOD_HEAD){
|
||||
if (params->_method == NetworkParams::METHOD_HEAD) {
|
||||
response = headerList2String(reply->rawHeaderPairs());
|
||||
}else{
|
||||
if(reply->isOpen()){
|
||||
} else {
|
||||
if (reply->isOpen()) {
|
||||
response = QString::fromUtf8(reply->readAll());
|
||||
}
|
||||
}
|
||||
int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if(httpStatus == 200){
|
||||
if(!callable.isNull()){
|
||||
if(params->_cacheMode != NetworkType::CacheMode::NoCache){
|
||||
saveResponse(cacheKey,response);
|
||||
if (httpStatus == 200) {
|
||||
if (!callable.isNull()) {
|
||||
if (params->_cacheMode != NetworkType::CacheMode::NoCache) {
|
||||
saveResponse(cacheKey, response);
|
||||
}
|
||||
callable->success(response);
|
||||
}
|
||||
printRequestEndLog(request,params,reply,response);
|
||||
printRequestEndLog(request, params, reply, response);
|
||||
break;
|
||||
}else{
|
||||
if(i == params->getRetry()-1){
|
||||
if(!callable.isNull()){
|
||||
if(params->_cacheMode == NetworkType::CacheMode::RequestFailedReadCache && cacheExists(cacheKey)){
|
||||
if(!callable.isNull()){
|
||||
} else {
|
||||
if (i == params->getRetry() - 1) {
|
||||
if (!callable.isNull()) {
|
||||
if (params->_cacheMode == NetworkType::CacheMode::RequestFailedReadCache && cacheExists(cacheKey)) {
|
||||
if (!callable.isNull()) {
|
||||
callable->cache(readCache(cacheKey));
|
||||
}
|
||||
}
|
||||
callable->error(httpStatus,reply->errorString(),response);
|
||||
callable->error(httpStatus, reply->errorString(), response);
|
||||
}
|
||||
printRequestEndLog(request,params,reply,response);
|
||||
printRequestEndLog(request, params, reply, response);
|
||||
}
|
||||
}
|
||||
reply->deleteLater();
|
||||
}
|
||||
params->deleteLater();
|
||||
if(!callable.isNull()){
|
||||
if (!callable.isNull()) {
|
||||
callable->finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Network::handleDownload(NetworkParams* params,NetworkCallable* c){
|
||||
void Network::handleDownload(NetworkParams *params, NetworkCallable *c) {
|
||||
QPointer<NetworkCallable> callable(c);
|
||||
QThreadPool::globalInstance()->start([=](){
|
||||
if(!callable.isNull()){
|
||||
QThreadPool::globalInstance()->start([=]() {
|
||||
if (!callable.isNull()) {
|
||||
callable->start();
|
||||
}
|
||||
QString cacheKey = params->buildCacheKey();
|
||||
QUrl url(params->_url);
|
||||
QNetworkAccessManager manager;
|
||||
manager.setTransferTimeout(params->getTimeout());
|
||||
addQueryParam(&url,params->_queryMap);
|
||||
addQueryParam(&url, params->_queryMap);
|
||||
QNetworkRequest request(url);
|
||||
addHeaders(&request,params->_headerMap);
|
||||
addHeaders(&request, params->_headerMap);
|
||||
QString cachePath = getCacheFilePath(cacheKey);
|
||||
QString destPath = params->_downloadParam->_destPath;
|
||||
QFile* destFile = new QFile(destPath);
|
||||
QFile* cacheFile = new QFile(cachePath);
|
||||
bool isOpen = false;
|
||||
qint64 seek = 0;
|
||||
if(cacheFile->exists() && destFile->exists() && params->_downloadParam->_append){
|
||||
auto *destFile = new QFile(destPath);
|
||||
auto *cacheFile = new QFile(cachePath);
|
||||
bool isOpen;
|
||||
qint64 seek;
|
||||
if (cacheFile->exists() && destFile->exists() && params->_downloadParam->_append) {
|
||||
QJsonObject cacheInfo = QJsonDocument::fromJson(readCache(cacheKey).toUtf8()).object();
|
||||
qint64 fileSize = cacheInfo.value("fileSize").toDouble();
|
||||
qint64 contentLength = cacheInfo.value("contentLength").toDouble();
|
||||
if(fileSize == contentLength && destFile->size() == contentLength){
|
||||
if(!callable.isNull()){
|
||||
callable->downloadProgress(fileSize,contentLength);
|
||||
qint64 fileSize = qRound(cacheInfo.value("fileSize").toDouble());
|
||||
qint64 contentLength = qRound(cacheInfo.value("contentLength").toDouble());
|
||||
if (fileSize == contentLength && destFile->size() == contentLength) {
|
||||
if (!callable.isNull()) {
|
||||
callable->downloadProgress(fileSize, contentLength);
|
||||
callable->success(destPath);
|
||||
callable->finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(fileSize==destFile->size()){
|
||||
if (fileSize == destFile->size()) {
|
||||
request.setRawHeader("Range", QString("bytes=%1-").arg(fileSize).toUtf8());
|
||||
seek = fileSize;
|
||||
isOpen = destFile->open(QIODevice::WriteOnly|QIODevice::Append);
|
||||
}else{
|
||||
isOpen = destFile->open(QIODevice::WriteOnly|QIODevice::Truncate);
|
||||
isOpen = destFile->open(QIODevice::WriteOnly | QIODevice::Append);
|
||||
} else {
|
||||
isOpen = destFile->open(QIODevice::WriteOnly | QIODevice::Truncate);
|
||||
}
|
||||
}else{
|
||||
isOpen = destFile->open(QIODevice::WriteOnly|QIODevice::Truncate);
|
||||
} else {
|
||||
isOpen = destFile->open(QIODevice::WriteOnly | QIODevice::Truncate);
|
||||
}
|
||||
if(!isOpen){
|
||||
if(!callable.isNull()){
|
||||
callable->error(-1,"device not open","");
|
||||
if (!isOpen) {
|
||||
if (!callable.isNull()) {
|
||||
callable->error(-1, "device not open", "");
|
||||
callable->finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(params->_downloadParam->_append){
|
||||
if (!cacheFile->open(QIODevice::WriteOnly|QIODevice::Truncate))
|
||||
{
|
||||
if(!callable.isNull()){
|
||||
callable->error(-1,"cache file device not open","");
|
||||
if (params->_downloadParam->_append) {
|
||||
if (!cacheFile->open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
if (!callable.isNull()) {
|
||||
callable->error(-1, "cache file device not open", "");
|
||||
callable->finish();
|
||||
}
|
||||
return;
|
||||
@ -329,73 +327,72 @@ void Network::handleDownload(NetworkParams* params,NetworkCallable* c){
|
||||
QNetworkReply *reply = manager.get(request);
|
||||
destFile->setParent(reply);
|
||||
cacheFile->setParent(reply);
|
||||
auto abortCallable = [&loop,reply,params]{
|
||||
if(reply){
|
||||
auto abortCallable = [reply] {
|
||||
if (reply) {
|
||||
reply->abort();
|
||||
}
|
||||
};
|
||||
connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();});
|
||||
connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();});
|
||||
connect(&manager, &QNetworkAccessManager::finished, &manager, [&loop](QNetworkReply *reply) { loop.quit(); });
|
||||
connect(QGuiApplication::instance(), &QGuiApplication::aboutToQuit, &manager, [&loop, reply]() { reply->abort(), loop.quit(); });
|
||||
QMetaObject::Connection conn_destroyed = {};
|
||||
QMetaObject::Connection conn_quit = {};
|
||||
if(params->_target){
|
||||
conn_destroyed = connect(params->_target,&QObject::destroyed,&manager,abortCallable);
|
||||
if (params->_target) {
|
||||
conn_destroyed = connect(params->_target, &QObject::destroyed, &manager, abortCallable);
|
||||
}
|
||||
conn_quit = connect(qApp,&QGuiApplication::aboutToQuit,&manager, abortCallable);
|
||||
connect(reply,&QNetworkReply::readyRead,reply,[reply,seek,destFile,cacheFile,callable]{
|
||||
if (!reply || !destFile || reply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
conn_quit = connect(QGuiApplication::instance(), &QGuiApplication::aboutToQuit, &manager, abortCallable);
|
||||
connect(reply, &QNetworkReply::readyRead, reply, [reply, seek, destFile, cacheFile, callable] {
|
||||
if (!reply || !destFile || reply->error() != QNetworkReply::NoError) {
|
||||
return;
|
||||
}
|
||||
QMap<QString, QVariant> downInfo;
|
||||
qint64 contentLength = reply->header(QNetworkRequest::ContentLengthHeader).toLongLong()+seek;
|
||||
downInfo.insert("contentLength",contentLength);
|
||||
qint64 contentLength = reply->header(QNetworkRequest::ContentLengthHeader).toLongLong() + seek;
|
||||
downInfo.insert("contentLength", contentLength);
|
||||
QString eTag = reply->header(QNetworkRequest::ETagHeader).toString();
|
||||
downInfo.insert("eTag",eTag);
|
||||
downInfo.insert("eTag", eTag);
|
||||
destFile->write(reply->readAll());
|
||||
destFile->flush();
|
||||
downInfo.insert("fileSize",destFile->size());
|
||||
if(cacheFile->isOpen()){
|
||||
downInfo.insert("fileSize", destFile->size());
|
||||
if (cacheFile->isOpen()) {
|
||||
cacheFile->resize(0);
|
||||
cacheFile->write(QJsonDocument::fromVariant(QVariant(downInfo)).toJson().toBase64());
|
||||
cacheFile->flush();
|
||||
}
|
||||
if(!callable.isNull()){
|
||||
callable->downloadProgress(destFile->size(),contentLength);
|
||||
if (!callable.isNull()) {
|
||||
callable->downloadProgress(destFile->size(), contentLength);
|
||||
}
|
||||
});
|
||||
loop.exec();
|
||||
int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if(httpStatus == 200){
|
||||
if(!callable.isNull()){
|
||||
if (httpStatus == 200) {
|
||||
if (!callable.isNull()) {
|
||||
callable->success(destPath);
|
||||
}
|
||||
printRequestEndLog(request,params,reply,destPath);
|
||||
}else{
|
||||
if(!callable.isNull()){
|
||||
callable->error(httpStatus,reply->errorString(),destPath);
|
||||
printRequestEndLog(request, params, reply, destPath);
|
||||
} else {
|
||||
if (!callable.isNull()) {
|
||||
callable->error(httpStatus, reply->errorString(), destPath);
|
||||
}
|
||||
printRequestEndLog(request,params,reply,destPath);
|
||||
printRequestEndLog(request, params, reply, destPath);
|
||||
}
|
||||
if(conn_destroyed){
|
||||
if (conn_destroyed) {
|
||||
disconnect(conn_destroyed);
|
||||
}
|
||||
if(conn_quit){
|
||||
if (conn_quit) {
|
||||
disconnect(conn_quit);
|
||||
}
|
||||
params->deleteLater();
|
||||
reply->deleteLater();
|
||||
if(!callable.isNull()){
|
||||
if (!callable.isNull()) {
|
||||
callable->finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QString Network::readCache(const QString& key){
|
||||
QString Network::readCache(const QString &key) {
|
||||
auto filePath = getCacheFilePath(key);
|
||||
QString result;
|
||||
QFile file(filePath);
|
||||
if(!file.exists()){
|
||||
if (!file.exists()) {
|
||||
return result;
|
||||
}
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
@ -405,27 +402,27 @@ QString Network::readCache(const QString& key){
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Network::cacheExists(const QString& key){
|
||||
bool Network::cacheExists(const QString &key) {
|
||||
return QFile(getCacheFilePath(key)).exists();
|
||||
}
|
||||
|
||||
QString Network::getCacheFilePath(const QString& key){
|
||||
QString Network::getCacheFilePath(const QString &key) {
|
||||
QDir cacheDir(_cacheDir);
|
||||
if(!cacheDir.exists()){
|
||||
if (!cacheDir.exists()) {
|
||||
cacheDir.mkpath(_cacheDir);
|
||||
}
|
||||
return cacheDir.absoluteFilePath(key);
|
||||
}
|
||||
|
||||
QString Network::headerList2String(const QList<QNetworkReply::RawHeaderPair>& data){
|
||||
QString Network::headerList2String(const QList<QNetworkReply::RawHeaderPair> &data) {
|
||||
QJsonObject object;
|
||||
for (auto it = data.constBegin(); it != data.constEnd(); ++it) {
|
||||
object.insert(QString(it->first),QString(it->second));
|
||||
object.insert(QString(it->first), QString(it->second));
|
||||
}
|
||||
return QJsonDocument(object).toJson(QJsonDocument::Compact);
|
||||
}
|
||||
|
||||
QString Network::map2String(const QMap<QString, QVariant>& map){
|
||||
QString Network::map2String(const QMap<QString, QVariant> &map) {
|
||||
QStringList parameters;
|
||||
for (auto it = map.constBegin(); it != map.constEnd(); ++it) {
|
||||
parameters << QString("%1=%2").arg(it.key(), it.value().toString());
|
||||
@ -433,244 +430,235 @@ QString Network::map2String(const QMap<QString, QVariant>& map){
|
||||
return parameters.join(" ");
|
||||
}
|
||||
|
||||
void Network::sendRequest(QNetworkAccessManager* manager,QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,bool isFirst,QPointer<NetworkCallable> callable){
|
||||
void Network::sendRequest(QNetworkAccessManager *manager, QNetworkRequest request, NetworkParams *params, QNetworkReply *&reply, bool isFirst, const QPointer<NetworkCallable> &callable) {
|
||||
QByteArray verb = params->method2String().toUtf8();
|
||||
switch (params->_type) {
|
||||
case NetworkParams::TYPE_FORM:{
|
||||
bool isFormData = !params->_fileMap.isEmpty();
|
||||
if(isFormData){
|
||||
QHttpMultiPart *multiPart = new QHttpMultiPart();
|
||||
multiPart->setContentType(QHttpMultiPart::FormDataType);
|
||||
for (const auto& each : params->_paramMap.toStdMap())
|
||||
{
|
||||
QHttpPart part;
|
||||
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"").arg(each.first));
|
||||
part.setBody(each.second.toByteArray());
|
||||
multiPart->append(part);
|
||||
}
|
||||
for (const auto& each : params->_fileMap.toStdMap())
|
||||
{
|
||||
QString filePath = each.second.toString();
|
||||
QString name = each.first;
|
||||
QFile *file = new QFile(filePath);
|
||||
QString fileName = QFileInfo(filePath).fileName();
|
||||
file->open(QIODevice::ReadOnly);
|
||||
file->setParent(multiPart);
|
||||
QHttpPart part;
|
||||
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"; filename=\"%2\"").arg(name,fileName));
|
||||
part.setBodyDevice(file);
|
||||
multiPart->append(part);
|
||||
}
|
||||
reply = manager->sendCustomRequest(request,verb,multiPart);
|
||||
multiPart->setParent(reply);
|
||||
connect(reply,&QNetworkReply::uploadProgress,reply,[callable](qint64 bytesSent, qint64 bytesTotal){
|
||||
if(!callable.isNull() && bytesSent!=0 && bytesTotal!=0){
|
||||
Q_EMIT callable->uploadProgress(bytesSent,bytesTotal);
|
||||
case NetworkParams::TYPE_FORM: {
|
||||
bool isFormData = !params->_fileMap.isEmpty();
|
||||
if (isFormData) {
|
||||
auto *multiPart = new QHttpMultiPart();
|
||||
multiPart->setContentType(QHttpMultiPart::FormDataType);
|
||||
for (const auto &each: params->_paramMap.toStdMap()) {
|
||||
QHttpPart part;
|
||||
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"").arg(each.first));
|
||||
part.setBody(each.second.toByteArray());
|
||||
multiPart->append(part);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/x-www-form-urlencoded"));
|
||||
QString value;
|
||||
for (const auto& each : params->_paramMap.toStdMap())
|
||||
{
|
||||
value += QString("%1=%2").arg(each.first,each.second.toString());
|
||||
value += "&";
|
||||
for (const auto &each: params->_fileMap.toStdMap()) {
|
||||
QString filePath = each.second.toString();
|
||||
QString name = each.first;
|
||||
auto *file = new QFile(filePath);
|
||||
QString fileName = QFileInfo(filePath).fileName();
|
||||
file->open(QIODevice::ReadOnly);
|
||||
file->setParent(multiPart);
|
||||
QHttpPart part;
|
||||
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString(R"(form-data; name="%1"; filename="%2")").arg(name, fileName));
|
||||
part.setBodyDevice(file);
|
||||
multiPart->append(part);
|
||||
}
|
||||
reply = manager->sendCustomRequest(request, verb, multiPart);
|
||||
multiPart->setParent(reply);
|
||||
connect(reply, &QNetworkReply::uploadProgress, reply, [callable](qint64 bytesSent, qint64 bytesTotal) {
|
||||
if (!callable.isNull() && bytesSent != 0 && bytesTotal != 0) {
|
||||
Q_EMIT callable->uploadProgress(bytesSent, bytesTotal);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/x-www-form-urlencoded"));
|
||||
QString value;
|
||||
for (const auto &each: params->_paramMap.toStdMap()) {
|
||||
value += QString("%1=%2").arg(each.first, each.second.toString());
|
||||
value += "&";
|
||||
}
|
||||
if (!params->_paramMap.isEmpty()) {
|
||||
value.chop(1);
|
||||
}
|
||||
QByteArray data = value.toUtf8();
|
||||
reply = manager->sendCustomRequest(request, verb, data);
|
||||
}
|
||||
if(!params->_paramMap.isEmpty()){
|
||||
value.chop(1);
|
||||
}
|
||||
QByteArray data = value.toUtf8();
|
||||
reply = manager->sendCustomRequest(request,verb,data);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NetworkParams::TYPE_JSON:{
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/json;charset=utf-8"));
|
||||
QJsonObject json;
|
||||
for (const auto& each : params->_paramMap.toStdMap())
|
||||
{
|
||||
json.insert(each.first,each.second.toJsonValue());
|
||||
}
|
||||
QByteArray data = QJsonDocument(json).toJson(QJsonDocument::Compact);
|
||||
reply = manager->sendCustomRequest(request,verb,data);
|
||||
break;
|
||||
}
|
||||
case NetworkParams::TYPE_JSONARRAY:{
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/json;charset=utf-8"));
|
||||
QJsonArray jsonArray;
|
||||
for (const auto& each : params->_paramMap.toStdMap())
|
||||
{
|
||||
case NetworkParams::TYPE_JSON: {
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/json;charset=utf-8"));
|
||||
QJsonObject json;
|
||||
json.insert(each.first,each.second.toJsonValue());
|
||||
jsonArray.append(json);
|
||||
for (const auto &each: params->_paramMap.toStdMap()) {
|
||||
json.insert(each.first, each.second.toJsonValue());
|
||||
}
|
||||
QByteArray data = QJsonDocument(json).toJson(QJsonDocument::Compact);
|
||||
reply = manager->sendCustomRequest(request, verb, data);
|
||||
break;
|
||||
}
|
||||
QByteArray data = QJsonDocument(jsonArray).toJson(QJsonDocument::Compact);
|
||||
reply = manager->sendCustomRequest(request,params->method2String().toUtf8(),data);
|
||||
break;
|
||||
case NetworkParams::TYPE_JSONARRAY: {
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/json;charset=utf-8"));
|
||||
QJsonArray jsonArray;
|
||||
for (const auto &each: params->_paramMap.toStdMap()) {
|
||||
QJsonObject json;
|
||||
json.insert(each.first, each.second.toJsonValue());
|
||||
jsonArray.append(json);
|
||||
}
|
||||
QByteArray data = QJsonDocument(jsonArray).toJson(QJsonDocument::Compact);
|
||||
reply = manager->sendCustomRequest(request, params->method2String().toUtf8(), data);
|
||||
break;
|
||||
}
|
||||
case NetworkParams::TYPE_BODY: {
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("text/plain;charset=utf-8"));
|
||||
QByteArray data = params->_body.toUtf8();
|
||||
reply = manager->sendCustomRequest(request, verb, data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
reply = manager->sendCustomRequest(request, verb);
|
||||
break;
|
||||
}
|
||||
case NetworkParams::TYPE_BODY:{
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("text/plain;charset=utf-8"));
|
||||
QByteArray data = params->_body.toUtf8();
|
||||
reply = manager->sendCustomRequest(request,verb,data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
reply = manager->sendCustomRequest(request,verb);
|
||||
break;
|
||||
}
|
||||
if(isFirst){
|
||||
printRequestStartLog(request,params);
|
||||
if (isFirst) {
|
||||
printRequestStartLog(request, params);
|
||||
}
|
||||
}
|
||||
|
||||
void Network::printRequestStartLog(QNetworkRequest request,NetworkParams* params){
|
||||
if(!params->getOpenLog()){
|
||||
void Network::printRequestStartLog(const QNetworkRequest &request, NetworkParams *params) {
|
||||
if (!params->getOpenLog()) {
|
||||
return;
|
||||
}
|
||||
qDebug()<<"<------"<<qUtf8Printable(request.header(QNetworkRequest::UserAgentHeader).toString())<<"Request Start ------>";
|
||||
qDebug()<<qUtf8Printable(QString::fromStdString("<%1>").arg(params->method2String()))<<qUtf8Printable(params->_url);
|
||||
qDebug() << "<------" << qUtf8Printable(request.header(QNetworkRequest::UserAgentHeader).toString()) << "Request Start ------>";
|
||||
qDebug() << qUtf8Printable(QString::fromStdString("<%1>").arg(params->method2String())) << qUtf8Printable(params->_url);
|
||||
auto contentType = request.header(QNetworkRequest::ContentTypeHeader).toString();
|
||||
if(!contentType.isEmpty()){
|
||||
qDebug()<<qUtf8Printable(QString::fromStdString("<Header> %1=%2").arg("Content-Type",contentType));
|
||||
if (!contentType.isEmpty()) {
|
||||
qDebug() << qUtf8Printable(QString::fromStdString("<Header> %1=%2").arg("Content-Type", contentType));
|
||||
}
|
||||
QList<QByteArray> headers = request.rawHeaderList();
|
||||
for(const QByteArray& header:headers){
|
||||
qDebug()<<qUtf8Printable(QString::fromStdString("<Header> %1=%2").arg(header,request.rawHeader(header)));
|
||||
for (const QByteArray &header: headers) {
|
||||
qDebug() << qUtf8Printable(QString::fromStdString("<Header> %1=%2").arg(header, request.rawHeader(header)));
|
||||
}
|
||||
if(!params->_queryMap.isEmpty()){
|
||||
qDebug()<<"<Query>"<<qUtf8Printable(map2String(params->_queryMap));
|
||||
if (!params->_queryMap.isEmpty()) {
|
||||
qDebug() << "<Query>" << qUtf8Printable(map2String(params->_queryMap));
|
||||
}
|
||||
if(!params->_paramMap.isEmpty()){
|
||||
qDebug()<<"<Param>"<<qUtf8Printable(map2String(params->_paramMap));
|
||||
if (!params->_paramMap.isEmpty()) {
|
||||
qDebug() << "<Param>" << qUtf8Printable(map2String(params->_paramMap));
|
||||
}
|
||||
if(!params->_fileMap.isEmpty()){
|
||||
qDebug()<<"<File>"<<qUtf8Printable(map2String(params->_fileMap));
|
||||
if (!params->_fileMap.isEmpty()) {
|
||||
qDebug() << "<File>" << qUtf8Printable(map2String(params->_fileMap));
|
||||
}
|
||||
if(!params->_body.isEmpty()){
|
||||
qDebug()<<"<Body>"<<qUtf8Printable(params->_body);
|
||||
if (!params->_body.isEmpty()) {
|
||||
qDebug() << "<Body>" << qUtf8Printable(params->_body);
|
||||
}
|
||||
}
|
||||
|
||||
void Network::printRequestEndLog(QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,const QString& response){
|
||||
if(!params->getOpenLog()){
|
||||
void Network::printRequestEndLog(const QNetworkRequest &request, NetworkParams *params, QNetworkReply *&reply, const QString &response) {
|
||||
if (!params->getOpenLog()) {
|
||||
return;
|
||||
}
|
||||
qDebug()<<"<------"<<qUtf8Printable(request.header(QNetworkRequest::UserAgentHeader).toString())<<"Request End ------>";
|
||||
qDebug()<<qUtf8Printable(QString::fromStdString("<%1>").arg(params->method2String()))<<qUtf8Printable(params->_url);
|
||||
qDebug()<<"<Result>"<<qUtf8Printable(response);
|
||||
qDebug() << "<------" << qUtf8Printable(request.header(QNetworkRequest::UserAgentHeader).toString()) << "Request End ------>";
|
||||
qDebug() << qUtf8Printable(QString::fromStdString("<%1>").arg(params->method2String())) << qUtf8Printable(params->_url);
|
||||
qDebug() << "<Result>" << qUtf8Printable(response);
|
||||
}
|
||||
|
||||
void Network::saveResponse(QString key,QString response){
|
||||
void Network::saveResponse(const QString &key, const QString &response) {
|
||||
QSharedPointer<QFile> file(new QFile(getCacheFilePath(key)));
|
||||
QIODevice::OpenMode mode = QIODevice::WriteOnly|QIODevice::Truncate;
|
||||
if (!file->open(mode))
|
||||
{
|
||||
QIODevice::OpenMode mode = QIODevice::WriteOnly | QIODevice::Truncate;
|
||||
if (!file->open(mode)) {
|
||||
return;
|
||||
}
|
||||
file->write(response.toUtf8().toBase64());
|
||||
}
|
||||
|
||||
void Network::addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& headers){
|
||||
request->setHeader(QNetworkRequest::UserAgentHeader,QString::fromStdString("Mozilla/5.0 %1/%2").arg(QGuiApplication::applicationName(),QGuiApplication::applicationVersion()));
|
||||
void Network::addHeaders(QNetworkRequest *request, const QMap<QString, QVariant> &headers) {
|
||||
request->setHeader(QNetworkRequest::UserAgentHeader, QString::fromStdString("Mozilla/5.0 %1/%2").arg(QGuiApplication::applicationName(), QGuiApplication::applicationVersion()));
|
||||
QMapIterator<QString, QVariant> iter(headers);
|
||||
while (iter.hasNext())
|
||||
{
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
request->setRawHeader(iter.key().toUtf8(), iter.value().toString().toUtf8());
|
||||
}
|
||||
}
|
||||
|
||||
void Network::addQueryParam(QUrl* url,const QMap<QString, QVariant>& params){
|
||||
void Network::addQueryParam(QUrl *url, const QMap<QString, QVariant> ¶ms) {
|
||||
QMapIterator<QString, QVariant> iter(params);
|
||||
QUrlQuery urlQuery(*url);
|
||||
while (iter.hasNext())
|
||||
{
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
urlQuery.addQueryItem(iter.key(), iter.value().toString());
|
||||
}
|
||||
url->setQuery(urlQuery);
|
||||
}
|
||||
|
||||
Network::Network(QObject *parent): QObject{parent}
|
||||
{
|
||||
timeout(5000);
|
||||
retry(3);
|
||||
openLog(false);
|
||||
cacheDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation).append(QDir::separator()).append("network"));
|
||||
Network::Network(QObject *parent) : QObject{parent} {
|
||||
_timeout = 5000;
|
||||
_retry = 3;
|
||||
_openLog = false;
|
||||
_cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation).append(QDir::separator()).append("network");
|
||||
}
|
||||
|
||||
NetworkParams* Network::get(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_NONE,NetworkParams::METHOD_GET,this);
|
||||
NetworkParams *Network::get(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_NONE, NetworkParams::METHOD_GET, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::head(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_NONE,NetworkParams::METHOD_HEAD,this);
|
||||
NetworkParams *Network::head(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_NONE, NetworkParams::METHOD_HEAD, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::postBody(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_POST,this);
|
||||
NetworkParams *Network::postBody(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_BODY, NetworkParams::METHOD_POST, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::putBody(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_PUT,this);
|
||||
NetworkParams *Network::putBody(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_BODY, NetworkParams::METHOD_PUT, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::patchBody(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_PATCH,this);
|
||||
NetworkParams *Network::patchBody(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_BODY, NetworkParams::METHOD_PATCH, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::deleteBody(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_DELETE,this);
|
||||
NetworkParams *Network::deleteBody(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_BODY, NetworkParams::METHOD_DELETE, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::postForm(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_POST,this);
|
||||
NetworkParams *Network::postForm(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_FORM, NetworkParams::METHOD_POST, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::putForm(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_PUT,this);
|
||||
NetworkParams *Network::putForm(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_FORM, NetworkParams::METHOD_PUT, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::patchForm(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_PATCH,this);
|
||||
NetworkParams *Network::patchForm(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_FORM, NetworkParams::METHOD_PATCH, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::deleteForm(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_DELETE,this);
|
||||
NetworkParams *Network::deleteForm(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_FORM, NetworkParams::METHOD_DELETE, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::postJson(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_POST,this);
|
||||
NetworkParams *Network::postJson(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_JSON, NetworkParams::METHOD_POST, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::putJson(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_PUT,this);
|
||||
NetworkParams *Network::putJson(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_JSON, NetworkParams::METHOD_PUT, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::patchJson(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_PATCH,this);
|
||||
NetworkParams *Network::patchJson(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_JSON, NetworkParams::METHOD_PATCH, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::deleteJson(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_DELETE,this);
|
||||
NetworkParams *Network::deleteJson(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_JSON, NetworkParams::METHOD_DELETE, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::postJsonArray(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_POST,this);
|
||||
NetworkParams *Network::postJsonArray(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_JSONARRAY, NetworkParams::METHOD_POST, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::putJsonArray(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_PUT,this);
|
||||
NetworkParams *Network::putJsonArray(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_JSONARRAY, NetworkParams::METHOD_PUT, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::patchJsonArray(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_PATCH,this);
|
||||
NetworkParams *Network::patchJsonArray(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_JSONARRAY, NetworkParams::METHOD_PATCH, this);
|
||||
}
|
||||
|
||||
NetworkParams* Network::deleteJsonArray(const QString& url){
|
||||
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_DELETE,this);
|
||||
NetworkParams *Network::deleteJsonArray(const QString &url) {
|
||||
return new NetworkParams(url, NetworkParams::TYPE_JSONARRAY, NetworkParams::METHOD_DELETE, this);
|
||||
}
|
||||
|
||||
void Network::setInterceptor(QJSValue interceptor){
|
||||
this->_interceptor = interceptor;
|
||||
void Network::setInterceptor(QJSValue interceptor) {
|
||||
this->_interceptor = std::move(interceptor);
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef NETWORK_H
|
||||
#define NETWORK_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QtQml/qqml.h>
|
||||
@ -12,56 +11,66 @@
|
||||
#include "src/singleton.h"
|
||||
|
||||
namespace NetworkType {
|
||||
Q_NAMESPACE
|
||||
enum CacheMode {
|
||||
NoCache = 0x0000,
|
||||
RequestFailedReadCache = 0x0001,
|
||||
IfNoneCacheRequest = 0x0002,
|
||||
FirstCacheThenRequest = 0x0004,
|
||||
};
|
||||
Q_ENUM_NS(CacheMode)
|
||||
QML_NAMED_ELEMENT(NetworkType)
|
||||
Q_NAMESPACE
|
||||
enum CacheMode {
|
||||
NoCache = 0x0000,
|
||||
RequestFailedReadCache = 0x0001,
|
||||
IfNoneCacheRequest = 0x0002,
|
||||
FirstCacheThenRequest = 0x0004,
|
||||
};
|
||||
|
||||
Q_ENUM_NS(CacheMode)
|
||||
|
||||
QML_NAMED_ELEMENT(NetworkType)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The NetworkCallable class
|
||||
*/
|
||||
class NetworkCallable : public QObject{
|
||||
Q_OBJECT
|
||||
class NetworkCallable : public QObject {
|
||||
Q_OBJECT
|
||||
QML_NAMED_ELEMENT(NetworkCallable)
|
||||
public:
|
||||
explicit NetworkCallable(QObject *parent = nullptr);
|
||||
|
||||
Q_SIGNAL void start();
|
||||
|
||||
Q_SIGNAL void finish();
|
||||
Q_SIGNAL void error(int status,QString errorString,QString result);
|
||||
|
||||
Q_SIGNAL void error(int status, QString errorString, QString result);
|
||||
|
||||
Q_SIGNAL void success(QString result);
|
||||
|
||||
Q_SIGNAL void cache(QString result);
|
||||
|
||||
Q_SIGNAL void uploadProgress(qint64 sent, qint64 total);
|
||||
|
||||
Q_SIGNAL void downloadProgress(qint64 recv, qint64 total);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The FluDownloadParam class
|
||||
*/
|
||||
class FluDownloadParam : public QObject{
|
||||
Q_OBJECT
|
||||
class FluDownloadParam : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FluDownloadParam(QObject *parent = nullptr);
|
||||
FluDownloadParam(QString destPath,bool append,QObject *parent = nullptr);
|
||||
|
||||
FluDownloadParam(QString destPath, bool append, QObject *parent = nullptr);
|
||||
|
||||
public:
|
||||
QString _destPath;
|
||||
bool _append;
|
||||
bool _append{};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The NetworkParams class
|
||||
*/
|
||||
class NetworkParams : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
class NetworkParams : public QObject {
|
||||
Q_OBJECT
|
||||
QML_NAMED_ELEMENT(NetworkParams)
|
||||
public:
|
||||
enum Method{
|
||||
enum Method {
|
||||
METHOD_GET,
|
||||
METHOD_HEAD,
|
||||
METHOD_POST,
|
||||
@ -69,35 +78,55 @@ public:
|
||||
METHOD_PATCH,
|
||||
METHOD_DELETE
|
||||
};
|
||||
enum Type{
|
||||
enum Type {
|
||||
TYPE_NONE,
|
||||
TYPE_FORM,
|
||||
TYPE_JSON,
|
||||
TYPE_JSONARRAY,
|
||||
TYPE_BODY
|
||||
};
|
||||
|
||||
explicit NetworkParams(QObject *parent = nullptr);
|
||||
NetworkParams(QString url,Type type,Method method,QObject *parent = nullptr);
|
||||
Q_INVOKABLE NetworkParams* addQuery(QString key,QVariant val);
|
||||
Q_INVOKABLE NetworkParams* addHeader(QString key,QVariant val);
|
||||
Q_INVOKABLE NetworkParams* add(QString key,QVariant val);
|
||||
Q_INVOKABLE NetworkParams* addFile(QString key,QVariant val);
|
||||
Q_INVOKABLE NetworkParams* setBody(QString val);
|
||||
Q_INVOKABLE NetworkParams* setTimeout(int val);
|
||||
Q_INVOKABLE NetworkParams* setRetry(int val);
|
||||
Q_INVOKABLE NetworkParams* setCacheMode(int val);
|
||||
Q_INVOKABLE NetworkParams* toDownload(QString destPath,bool append = false);
|
||||
Q_INVOKABLE NetworkParams* bind(QObject* target);
|
||||
Q_INVOKABLE NetworkParams* openLog(QVariant val);
|
||||
Q_INVOKABLE void go(NetworkCallable* result);
|
||||
QString buildCacheKey();
|
||||
QString method2String();
|
||||
int getTimeout();
|
||||
int getRetry();
|
||||
bool getOpenLog();
|
||||
|
||||
NetworkParams(QString url, Type type, Method method, QObject *parent = nullptr);
|
||||
|
||||
Q_INVOKABLE NetworkParams *addQuery(const QString &key, const QVariant &val);
|
||||
|
||||
Q_INVOKABLE NetworkParams *addHeader(const QString &key, const QVariant &val);
|
||||
|
||||
Q_INVOKABLE NetworkParams *add(const QString &key, const QVariant &val);
|
||||
|
||||
Q_INVOKABLE NetworkParams *addFile(const QString &key, const QVariant &val);
|
||||
|
||||
Q_INVOKABLE NetworkParams *setBody(QString val);
|
||||
|
||||
Q_INVOKABLE NetworkParams *setTimeout(int val);
|
||||
|
||||
Q_INVOKABLE NetworkParams *setRetry(int val);
|
||||
|
||||
Q_INVOKABLE NetworkParams *setCacheMode(int val);
|
||||
|
||||
Q_INVOKABLE NetworkParams *toDownload(QString destPath, bool append = false);
|
||||
|
||||
Q_INVOKABLE NetworkParams *bind(QObject *target);
|
||||
|
||||
Q_INVOKABLE NetworkParams *openLog(QVariant val);
|
||||
|
||||
Q_INVOKABLE void go(NetworkCallable *result);
|
||||
|
||||
QString buildCacheKey() const;
|
||||
|
||||
QString method2String() const;
|
||||
|
||||
int getTimeout() const;
|
||||
|
||||
int getRetry() const;
|
||||
|
||||
bool getOpenLog() const;
|
||||
|
||||
public:
|
||||
FluDownloadParam* _downloadParam = nullptr;
|
||||
QObject* _target = nullptr;
|
||||
FluDownloadParam *_downloadParam = nullptr;
|
||||
QObject *_target = nullptr;
|
||||
Method _method;
|
||||
Type _type;
|
||||
QString _url;
|
||||
@ -115,55 +144,88 @@ public:
|
||||
/**
|
||||
* @brief The Network class
|
||||
*/
|
||||
class Network : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(int,timeout)
|
||||
Q_PROPERTY_AUTO(int,retry)
|
||||
Q_PROPERTY_AUTO(QString,cacheDir)
|
||||
Q_PROPERTY_AUTO(bool,openLog)
|
||||
class Network : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(int, timeout)
|
||||
Q_PROPERTY_AUTO(int, retry)
|
||||
Q_PROPERTY_AUTO(QString, cacheDir)
|
||||
Q_PROPERTY_AUTO(bool, openLog)
|
||||
QML_NAMED_ELEMENT(Network)
|
||||
QML_SINGLETON
|
||||
|
||||
private:
|
||||
explicit Network(QObject *parent = nullptr);
|
||||
|
||||
public:
|
||||
SINGLETON(Network)
|
||||
static Network *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
|
||||
Q_INVOKABLE NetworkParams* get(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* head(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* postBody(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* putBody(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* patchBody(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* deleteBody(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* postForm(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* putForm(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* patchForm(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* deleteForm(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* postJson(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* putJson(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* patchJson(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* deleteJson(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* postJsonArray(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* putJsonArray(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* patchJsonArray(const QString& url);
|
||||
Q_INVOKABLE NetworkParams* deleteJsonArray(const QString& url);
|
||||
SINGLETON(Network)
|
||||
|
||||
static Network *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine) { return getInstance(); }
|
||||
|
||||
Q_INVOKABLE NetworkParams *get(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *head(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *postBody(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *putBody(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *patchBody(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *deleteBody(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *postForm(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *putForm(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *patchForm(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *deleteForm(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *postJson(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *putJson(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *patchJson(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *deleteJson(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *postJsonArray(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *putJsonArray(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *patchJsonArray(const QString &url);
|
||||
|
||||
Q_INVOKABLE NetworkParams *deleteJsonArray(const QString &url);
|
||||
|
||||
Q_INVOKABLE void setInterceptor(QJSValue interceptor);
|
||||
void handle(NetworkParams* params,NetworkCallable* result);
|
||||
void handleDownload(NetworkParams* params,NetworkCallable* result);
|
||||
|
||||
void handle(NetworkParams *params, NetworkCallable *result);
|
||||
|
||||
void handleDownload(NetworkParams *params, NetworkCallable *result);
|
||||
|
||||
private:
|
||||
void sendRequest(QNetworkAccessManager* manager,QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,bool isFirst,QPointer<NetworkCallable> callable);
|
||||
void addQueryParam(QUrl* url,const QMap<QString, QVariant>& params);
|
||||
void addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& headers);
|
||||
void saveResponse(QString key,QString response);
|
||||
QString readCache(const QString& key);
|
||||
bool cacheExists(const QString& key);
|
||||
QString getCacheFilePath(const QString& key);
|
||||
QString map2String(const QMap<QString, QVariant>& map);
|
||||
QString headerList2String(const QList<QNetworkReply::RawHeaderPair>& data);
|
||||
void printRequestStartLog(QNetworkRequest request,NetworkParams* params);
|
||||
void printRequestEndLog(QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,const QString& response);
|
||||
static void sendRequest(QNetworkAccessManager *manager, QNetworkRequest request, NetworkParams *params, QNetworkReply *&reply, bool isFirst, const QPointer<NetworkCallable> &callable);
|
||||
|
||||
static void addQueryParam(QUrl *url, const QMap<QString, QVariant> ¶ms);
|
||||
|
||||
static void addHeaders(QNetworkRequest *request, const QMap<QString, QVariant> &headers);
|
||||
|
||||
void saveResponse(const QString &key, const QString &response);
|
||||
|
||||
QString readCache(const QString &key);
|
||||
|
||||
bool cacheExists(const QString &key);
|
||||
|
||||
QString getCacheFilePath(const QString &key);
|
||||
|
||||
static QString headerList2String(const QList<QNetworkReply::RawHeaderPair> &data);
|
||||
|
||||
static void printRequestStartLog(const QNetworkRequest &request, NetworkParams *params);
|
||||
|
||||
static void printRequestEndLog(const QNetworkRequest &request, NetworkParams *params, QNetworkReply *&reply, const QString &response);
|
||||
|
||||
static QString map2String(const QMap<QString, QVariant> &map);
|
||||
|
||||
public:
|
||||
QJSValue _interceptor;
|
||||
};
|
||||
|
||||
#endif // Network_H
|
||||
|
@ -3,19 +3,17 @@
|
||||
#include <QDataStream>
|
||||
#include <QStandardPaths>
|
||||
|
||||
SettingsHelper::SettingsHelper(QObject *parent) : QObject(parent)
|
||||
{
|
||||
SettingsHelper::SettingsHelper(QObject *parent) : QObject(parent) {
|
||||
|
||||
}
|
||||
|
||||
SettingsHelper::~SettingsHelper() = default;
|
||||
|
||||
void SettingsHelper::save(const QString& key,QVariant val)
|
||||
{
|
||||
void SettingsHelper::save(const QString &key, QVariant val) {
|
||||
m_settings->setValue(key, val);
|
||||
}
|
||||
|
||||
QVariant SettingsHelper::get(const QString& key,QVariant def){
|
||||
QVariant SettingsHelper::get(const QString &key, QVariant def) {
|
||||
QVariant data = m_settings->value(key);
|
||||
if (!data.isNull() && data.isValid()) {
|
||||
return data;
|
||||
@ -23,7 +21,7 @@ QVariant SettingsHelper::get(const QString& key,QVariant def){
|
||||
return def;
|
||||
}
|
||||
|
||||
void SettingsHelper::init(char *argv[]){
|
||||
void SettingsHelper::init(char *argv[]) {
|
||||
QString applicationPath = QString::fromStdString(argv[0]);
|
||||
const QFileInfo fileInfo(applicationPath);
|
||||
const QString iniFileName = fileInfo.completeBaseName() + ".ini";
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef SETTINGSHELPER_H
|
||||
#define SETTINGSHELPER_H
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtQml/qqml.h>
|
||||
@ -10,26 +9,35 @@
|
||||
#include <QDir>
|
||||
#include "src/singleton.h"
|
||||
|
||||
class SettingsHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
class SettingsHelper : public QObject {
|
||||
Q_OBJECT
|
||||
private:
|
||||
explicit SettingsHelper(QObject* parent = nullptr);
|
||||
explicit SettingsHelper(QObject *parent = nullptr);
|
||||
|
||||
public:
|
||||
SINGLETON(SettingsHelper)
|
||||
SINGLETON(SettingsHelper)
|
||||
|
||||
~SettingsHelper() override;
|
||||
|
||||
void init(char *argv[]);
|
||||
Q_INVOKABLE void saveDarkMode(int darkModel){save("darkMode",darkModel);}
|
||||
Q_INVOKABLE int getDarkMode(){return get("darkMode",QVariant(0)).toInt();}
|
||||
Q_INVOKABLE void saveUseSystemAppBar(bool useSystemAppBar){save("useSystemAppBar",useSystemAppBar);}
|
||||
Q_INVOKABLE bool getUseSystemAppBar(){return get("useSystemAppBar",QVariant(false)).toBool();}
|
||||
Q_INVOKABLE void saveLanguage(QString language){save("language",language);}
|
||||
Q_INVOKABLE QString getLanguage(){return get("language",QVariant("en_US")).toString();}
|
||||
|
||||
Q_INVOKABLE void saveDarkMode(int darkModel) { save("darkMode", darkModel); }
|
||||
|
||||
Q_INVOKABLE int getDarkMode() { return get("darkMode", QVariant(0)).toInt(); }
|
||||
|
||||
Q_INVOKABLE void saveUseSystemAppBar(bool useSystemAppBar) { save("useSystemAppBar", useSystemAppBar); }
|
||||
|
||||
Q_INVOKABLE bool getUseSystemAppBar() { return get("useSystemAppBar", QVariant(false)).toBool(); }
|
||||
|
||||
Q_INVOKABLE void saveLanguage(const QString &language) { save("language", language); }
|
||||
|
||||
Q_INVOKABLE QString getLanguage() { return get("language", QVariant("en_US")).toString(); }
|
||||
|
||||
private:
|
||||
void save(const QString& key,QVariant val);
|
||||
QVariant get(const QString& key,QVariant def={});
|
||||
void save(const QString &key, QVariant val);
|
||||
|
||||
QVariant get(const QString &key, QVariant def = {});
|
||||
|
||||
private:
|
||||
QScopedPointer<QSettings> m_settings;
|
||||
};
|
||||
|
||||
#endif // SETTINGSHELPER_H
|
||||
|
@ -5,21 +5,20 @@
|
||||
|
||||
#include "SettingsHelper.h"
|
||||
|
||||
TranslateHelper::TranslateHelper(QObject *parent) : QObject(parent)
|
||||
{
|
||||
_languages<<"en_US";
|
||||
_languages<<"zh_CN";
|
||||
[[maybe_unused]] TranslateHelper::TranslateHelper(QObject *parent) : QObject(parent) {
|
||||
_languages << "en_US";
|
||||
_languages << "zh_CN";
|
||||
_current = SettingsHelper::getInstance()->getLanguage();
|
||||
}
|
||||
|
||||
TranslateHelper::~TranslateHelper() = default;
|
||||
|
||||
void TranslateHelper::init(QQmlEngine* engine){
|
||||
void TranslateHelper::init(QQmlEngine *engine) {
|
||||
_engine = engine;
|
||||
_translator = new QTranslator(this);
|
||||
qApp->installTranslator(_translator);
|
||||
QString translatorPath = QGuiApplication::applicationDirPath()+"/i18n";
|
||||
if(_translator->load(QString::fromStdString("%1/example_%2.qm").arg(translatorPath,_current))){
|
||||
QGuiApplication::installTranslator(_translator);
|
||||
QString translatorPath = QGuiApplication::applicationDirPath() + "/i18n";
|
||||
if (_translator->load(QString::fromStdString("%1/example_%2.qm").arg(translatorPath, _current))) {
|
||||
_engine->retranslate();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef TRANSLATEHELPER_H
|
||||
#define TRANSLATEHELPER_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QtQml/qqml.h>
|
||||
@ -7,20 +6,21 @@
|
||||
#include "src/singleton.h"
|
||||
#include "src/stdafx.h"
|
||||
|
||||
class TranslateHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QString,current)
|
||||
Q_PROPERTY_READONLY_AUTO(QStringList,languages)
|
||||
class TranslateHelper : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QString, current)
|
||||
Q_PROPERTY_READONLY_AUTO(QStringList, languages)
|
||||
private:
|
||||
explicit TranslateHelper(QObject* parent = nullptr);
|
||||
public:
|
||||
SINGLETON(TranslateHelper)
|
||||
~TranslateHelper() override;
|
||||
void init(QQmlEngine* engine);
|
||||
private:
|
||||
QQmlEngine* _engine = nullptr;
|
||||
QTranslator* _translator = nullptr;
|
||||
};
|
||||
[[maybe_unused]] explicit TranslateHelper(QObject *parent = nullptr);
|
||||
|
||||
#endif // TRANSLATEHELPER_H
|
||||
public:
|
||||
SINGLETON(TranslateHelper)
|
||||
|
||||
~TranslateHelper() override;
|
||||
|
||||
void init(QQmlEngine *engine);
|
||||
|
||||
private:
|
||||
QQmlEngine *_engine = nullptr;
|
||||
QTranslator *_translator = nullptr;
|
||||
};
|
@ -14,6 +14,7 @@
|
||||
#include "src/component/CircularReveal.h"
|
||||
#include "src/component/FileWatcher.h"
|
||||
#include "src/component/FpsItem.h"
|
||||
#include "src/component/OpenGLItem.h"
|
||||
#include "src/helper/SettingsHelper.h"
|
||||
#include "src/helper/InitializrHelper.h"
|
||||
#include "src/helper/TranslateHelper.h"
|
||||
@ -53,7 +54,7 @@ int main(int argc, char *argv[])
|
||||
QGuiApplication::setOrganizationName("ZhuZiChu");
|
||||
QGuiApplication::setOrganizationDomain("https://zhuzichu520.github.io");
|
||||
QGuiApplication::setApplicationName("FluentUI");
|
||||
QGuiApplication::setApplicationDisplayName("FluentUI Exmaple");
|
||||
QGuiApplication::setApplicationDisplayName("FluentUI Example");
|
||||
QGuiApplication::setApplicationVersion(APPLICATION_VERSION);
|
||||
QGuiApplication::setQuitOnLastWindowClosed(false);
|
||||
SettingsHelper::getInstance()->init(argv);
|
||||
@ -75,6 +76,9 @@ int main(int argc, char *argv[])
|
||||
qmlRegisterType<FpsItem>(uri, major, minor, "FpsItem");
|
||||
qmlRegisterType<NetworkCallable>(uri,major,minor,"NetworkCallable");
|
||||
qmlRegisterType<NetworkParams>(uri,major,minor,"NetworkParams");
|
||||
qmlRegisterType<OpenGLItem>(uri,major,minor,"OpenGLItem");
|
||||
qmlRegisterUncreatableMetaObject(NetworkType::staticMetaObject, uri, major, minor, "NetworkType", "Access to enums & flags only");
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
TranslateHelper::getInstance()->init(&engine);
|
||||
engine.rootContext()->setContextProperty("AppInfo",AppInfo::getInstance());
|
||||
|
@ -1,18 +1,17 @@
|
||||
#ifndef SINGLETON_H
|
||||
#define SINGLETON_H
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief The Singleton class
|
||||
*/
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
class Singleton {
|
||||
public:
|
||||
static T* getInstance();
|
||||
static T *getInstance();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
T* Singleton<T>::getInstance() {
|
||||
static T* instance = new T();
|
||||
template<typename T>
|
||||
T *Singleton<T>::getInstance() {
|
||||
static T *instance = new T();
|
||||
return instance;
|
||||
}
|
||||
|
||||
@ -23,5 +22,3 @@ private: \
|
||||
static Class* getInstance() { \
|
||||
return Singleton<Class>::getInstance(); \
|
||||
}
|
||||
|
||||
#endif // SINGLETON_H
|
||||
|
@ -1,37 +1,50 @@
|
||||
#ifndef STDAFX_H
|
||||
#define STDAFX_H
|
||||
#pragma once
|
||||
|
||||
#define Q_PROPERTY_AUTO(TYPE, M) \
|
||||
#define Q_PROPERTY_AUTO_P(TYPE, M) \
|
||||
Q_PROPERTY(TYPE M MEMBER _##M NOTIFY M##Changed) \
|
||||
public: \
|
||||
Q_SIGNAL void M##Changed(); \
|
||||
void M(TYPE in_##M) \
|
||||
public: \
|
||||
Q_SIGNAL void M##Changed(); \
|
||||
void M(TYPE in_##M) \
|
||||
{ \
|
||||
_##M = in_##M; \
|
||||
Q_EMIT M##Changed(); \
|
||||
_##M = in_##M; \
|
||||
Q_EMIT M##Changed(); \
|
||||
} \
|
||||
TYPE M() \
|
||||
TYPE M() \
|
||||
{ \
|
||||
return _##M; \
|
||||
return _##M; \
|
||||
} \
|
||||
private: \
|
||||
TYPE _##M; \
|
||||
private: \
|
||||
TYPE _##M;
|
||||
|
||||
#define Q_PROPERTY_AUTO(TYPE, M) \
|
||||
Q_PROPERTY(TYPE M MEMBER _##M NOTIFY M##Changed) \
|
||||
public: \
|
||||
Q_SIGNAL void M##Changed(); \
|
||||
void M(const TYPE& in_##M) \
|
||||
{ \
|
||||
_##M = in_##M; \
|
||||
Q_EMIT M##Changed(); \
|
||||
} \
|
||||
TYPE M() \
|
||||
{ \
|
||||
return _##M; \
|
||||
} \
|
||||
private: \
|
||||
TYPE _##M;
|
||||
|
||||
|
||||
#define Q_PROPERTY_READONLY_AUTO(TYPE, M) \
|
||||
#define Q_PROPERTY_READONLY_AUTO(TYPE, M) \
|
||||
Q_PROPERTY(TYPE M READ M NOTIFY M##Changed FINAL) \
|
||||
public: \
|
||||
Q_SIGNAL void M##Changed(); \
|
||||
void M(TYPE in_##M) \
|
||||
public: \
|
||||
Q_SIGNAL void M##Changed(); \
|
||||
void M(const TYPE& in_##M) \
|
||||
{ \
|
||||
_##M = in_##M; \
|
||||
Q_EMIT M##Changed(); \
|
||||
_##M = in_##M; \
|
||||
Q_EMIT M##Changed(); \
|
||||
} \
|
||||
TYPE M() \
|
||||
TYPE M() \
|
||||
{ \
|
||||
return _##M; \
|
||||
return _##M; \
|
||||
} \
|
||||
private: \
|
||||
TYPE _##M; \
|
||||
|
||||
#endif // STDAFX_H
|
||||
private: \
|
||||
TYPE _##M;
|
||||
|
@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
if (FLUENTUI_BUILD_STATIC_LIB AND (QT_VERSION VERSION_GREATER_EQUAL "6.2"))
|
||||
project(fluentui VERSION 1.0)
|
||||
else()
|
||||
else ()
|
||||
project(fluentuiplugin VERSION 1.0)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/.cmake/)
|
||||
|
||||
@ -13,35 +13,35 @@ set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
#设置版本号
|
||||
add_definitions(-DFLUENTUI_VERSION=1,7,4,0)
|
||||
add_definitions(-DFLUENTUI_VERSION=1,7,5,0)
|
||||
|
||||
if (FLUENTUI_BUILD_STATIC_LIB)
|
||||
add_definitions(-DFLUENTUI_BUILD_STATIC_LIB)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
#编译参数设置
|
||||
option(FLUENTUI_BUILD_STATIC_LIB "Build static library." OFF)
|
||||
|
||||
#导入Qt相关依赖包
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Quick Qml)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick Qml)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick)
|
||||
|
||||
set(QT_SDK_DIR "${Qt${QT_VERSION_MAJOR}_DIR}/../../..")
|
||||
cmake_path(SET QT_SDK_DIR NORMALIZE ${QT_SDK_DIR})
|
||||
|
||||
#设置QML插件输出目录,可以通过外部设置,如果外部没有设置就默认到<QT_SDK_DIR_PATH>\qml\FluentUI目录下
|
||||
set(FLUENTUI_QML_PLUGIN_DIRECTORY "" CACHE PATH "Path to FluentUI plugin")
|
||||
if(NOT FLUENTUI_QML_PLUGIN_DIRECTORY)
|
||||
if (NOT FLUENTUI_QML_PLUGIN_DIRECTORY)
|
||||
set(FLUENTUI_QML_PLUGIN_DIRECTORY ${QT_SDK_DIR}/qml/FluentUI)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if(QT_VERSION VERSION_GREATER_EQUAL "6.3")
|
||||
if (QT_VERSION VERSION_GREATER_EQUAL "6.3")
|
||||
qt_standard_project_setup()
|
||||
else()
|
||||
else ()
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
#国际化
|
||||
find_program(QT_LUPDATE NAMES lupdate)
|
||||
@ -59,129 +59,125 @@ file(GLOB QM_FILE_PATHS ${CMAKE_CURRENT_LIST_DIR}/ *.qm)
|
||||
file(COPY ${QM_FILE_PATHS} DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/Qt${QT_VERSION_MAJOR}/imports/FluentUI/i18n")
|
||||
|
||||
#遍历所有Cpp文件
|
||||
file(GLOB_RECURSE CPP_FILES *.cpp *.h)
|
||||
foreach(filepath ${CPP_FILES})
|
||||
file(GLOB_RECURSE CPP_FILES *.cpp *.h *.cxx)
|
||||
foreach (filepath ${CPP_FILES})
|
||||
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
|
||||
list(APPEND sources_files ${filename})
|
||||
endforeach(filepath)
|
||||
endforeach (filepath)
|
||||
|
||||
if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
||||
if (QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
||||
#删除fluentuiplugin.cpp与fluentuiplugin.h,这些只要Qt5使用,Qt6不需要
|
||||
list(REMOVE_ITEM sources_files fluentuiplugin.h fluentuiplugin.cpp)
|
||||
if (NOT FLUENTUI_BUILD_STATIC_LIB)
|
||||
list(REMOVE_ITEM sources_files FluentUI.h FluentUI.cpp)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
#遍历所有qml文件
|
||||
file(GLOB_RECURSE QML_PATHS *.qml qmldir)
|
||||
foreach(filepath ${QML_PATHS})
|
||||
if(${filepath} MATCHES "Qt${QT_VERSION_MAJOR}/")
|
||||
foreach (filepath ${QML_PATHS})
|
||||
if (${filepath} MATCHES "Qt${QT_VERSION_MAJOR}/")
|
||||
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
|
||||
if(${filename} MATCHES "qmldir")
|
||||
if (${filename} MATCHES "qmldir")
|
||||
list(APPEND resource_files ${filename})
|
||||
else()
|
||||
else ()
|
||||
list(APPEND qml_files ${filename})
|
||||
endif()
|
||||
endif()
|
||||
endforeach(filepath)
|
||||
endif ()
|
||||
endif ()
|
||||
endforeach (filepath)
|
||||
|
||||
#遍历所有资源文件
|
||||
file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp *.js *.qm)
|
||||
foreach(filepath ${RES_PATHS})
|
||||
if(${filepath} MATCHES "Qt${QT_VERSION_MAJOR}/")
|
||||
foreach (filepath ${RES_PATHS})
|
||||
if (${filepath} MATCHES "Qt${QT_VERSION_MAJOR}/")
|
||||
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
|
||||
list(APPEND resource_files ${filename})
|
||||
endif()
|
||||
endforeach(filepath)
|
||||
endif ()
|
||||
endforeach (filepath)
|
||||
|
||||
#修改资源文件导出路径
|
||||
foreach(filepath IN LISTS qml_files resource_files)
|
||||
foreach (filepath IN LISTS qml_files resource_files)
|
||||
string(REPLACE "Qt${QT_VERSION_MAJOR}/imports/FluentUI/" "" filename ${filepath})
|
||||
set_source_files_properties(${filepath} PROPERTIES QT_RESOURCE_ALIAS ${filename})
|
||||
endforeach()
|
||||
endif()
|
||||
endforeach ()
|
||||
endif ()
|
||||
|
||||
if (FLUENTUI_BUILD_STATIC_LIB)
|
||||
set(LIB_TYPE "STATIC")
|
||||
else()
|
||||
else ()
|
||||
set(LIB_TYPE "SHARED")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (FLUENTUI_BUILD_STATIC_LIB)
|
||||
set(PLUGIN_TARGET_NAME "")
|
||||
else()
|
||||
else ()
|
||||
#如果是动态库,则使用插件目标作为其自己的支持目标来定义 QML 模块,在这种情况下,模块必须在运行时动态加载,并且不能由其他目标直接链接到
|
||||
set(PLUGIN_TARGET_NAME ${PROJECT_NAME})
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
#如果是Windows平台,则生成rc文件
|
||||
set(FLUENTUI_VERSION_RC_PATH "")
|
||||
if(WIN32)
|
||||
if (WIN32)
|
||||
set(FLUENTUI_VERSION_RC_PATH ${CMAKE_CURRENT_BINARY_DIR}/version_${PROJECT_NAME}.rc)
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/.cmake/version_dll.rc.in
|
||||
${FLUENTUI_VERSION_RC_PATH}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/.cmake/version_dll.rc.in
|
||||
${FLUENTUI_VERSION_RC_PATH}
|
||||
)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
||||
if (QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
||||
#如果是Qt6.2版本以上,则使用qt_add_library,qt_add_qml_module函数添加资源文件
|
||||
if(FLUENTUI_BUILD_STATIC_LIB)
|
||||
if (FLUENTUI_BUILD_STATIC_LIB)
|
||||
set(FLUENTUI_QML_PLUGIN_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/FluentUI)
|
||||
endif()
|
||||
endif ()
|
||||
qt_add_library(${PROJECT_NAME} ${LIB_TYPE})
|
||||
qt_add_qml_module(${PROJECT_NAME}
|
||||
PLUGIN_TARGET ${PLUGIN_TARGET_NAME}
|
||||
OUTPUT_DIRECTORY ${FLUENTUI_QML_PLUGIN_DIRECTORY}
|
||||
VERSION 1.0
|
||||
URI "FluentUI"
|
||||
#修改qmltypes文件名称。默认fluentuiplugin.qmltypes,使用默认名称有时候import FluentUI 1.0会爆红,所以修改成plugins.qmltypes
|
||||
TYPEINFO "plugins.qmltypes"
|
||||
SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH}
|
||||
QML_FILES ${qml_files}
|
||||
RESOURCES ${resource_files}
|
||||
RESOURCE_PREFIX "/qt/qml"
|
||||
PLUGIN_TARGET ${PLUGIN_TARGET_NAME}
|
||||
OUTPUT_DIRECTORY ${FLUENTUI_QML_PLUGIN_DIRECTORY}
|
||||
VERSION 1.0
|
||||
URI "FluentUI"
|
||||
#修改qmltypes文件名称。默认fluentuiplugin.qmltypes,使用默认名称有时候import FluentUI 1.0会爆红,所以修改成plugins.qmltypes
|
||||
TYPEINFO "plugins.qmltypes"
|
||||
SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH}
|
||||
QML_FILES ${qml_files}
|
||||
RESOURCES ${resource_files}
|
||||
RESOURCE_PREFIX "/qt/qml"
|
||||
)
|
||||
else()
|
||||
#加快qrc编译
|
||||
set(QRC_FILE Qt5/imports/fluentui.qrc)
|
||||
qt_add_big_resources(QRC_RESOURCES ${QRC_FILE})
|
||||
list(APPEND QRC_RESOURCES ${QRC_FILE})
|
||||
set_property(SOURCE ${QRC_FILE} PROPERTY SKIP_AUTORCC ON)
|
||||
else ()
|
||||
qt_add_resources(QRC_RESOURCES Qt5/imports/fluentui.qrc)
|
||||
#如果是Qt6.2版本以下,则使用add_qmlplugin函数添加资源文件,这是个自定义的函数,详情见.cmake/QmlPlugin.cmake
|
||||
include(QmlPlugin)
|
||||
add_qmlplugin(${PROJECT_NAME}
|
||||
URI "FluentUI"
|
||||
VERSION 1.0
|
||||
SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH} ${QRC_RESOURCES}
|
||||
QMLFILES ${qml_files}
|
||||
QMLDIR imports/FluentUI
|
||||
BINARY_DIR ${FLUENTUI_QML_PLUGIN_DIRECTORY}
|
||||
LIBTYPE ${LIB_TYPE}
|
||||
URI "FluentUI"
|
||||
VERSION 1.0
|
||||
SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH} ${QRC_RESOURCES}
|
||||
QMLFILES ${qml_files}
|
||||
QMLDIR imports/FluentUI
|
||||
BINARY_DIR ${FLUENTUI_QML_PLUGIN_DIRECTORY}
|
||||
LIBTYPE ${LIB_TYPE}
|
||||
)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
#导入qrcode配置文件
|
||||
HAVE_CONFIG_H
|
||||
PRIVATE
|
||||
#导入qrcode配置文件
|
||||
HAVE_CONFIG_H
|
||||
)
|
||||
|
||||
#去掉mingw生成的动态库libxxx前缀lib,不去掉前缀会导致 module "FluentUI" plugin "fluentuiplugin" not found
|
||||
if(MINGW)
|
||||
if (MINGW)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
#MSVC Debug 添加后缀d,与Qt插件风格保持一致
|
||||
if(MSVC)
|
||||
if (MSVC)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "d")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
#链接库
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::Quick
|
||||
Qt${QT_VERSION_MAJOR}::Qml
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::Quick
|
||||
Qt${QT_VERSION_MAJOR}::Qml
|
||||
)
|
||||
|
||||
#安装
|
||||
|
@ -1 +0,0 @@
|
||||
#include "Def.h"
|
@ -1,4 +1,4 @@
|
||||
#include "FluAccentColor.h"
|
||||
|
||||
FluAccentColor::FluAccentColor(QObject *parent):QObject{parent}{
|
||||
FluAccentColor::FluAccentColor(QObject *parent) : QObject{parent} {
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef FLUACCENTCOLOR_H
|
||||
#define FLUACCENTCOLOR_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QtQml/qqml.h>
|
||||
@ -9,19 +8,17 @@
|
||||
/**
|
||||
* @brief The FluAccentColor class
|
||||
*/
|
||||
class FluAccentColor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QColor,darkest)
|
||||
Q_PROPERTY_AUTO(QColor,darker)
|
||||
Q_PROPERTY_AUTO(QColor,dark)
|
||||
Q_PROPERTY_AUTO(QColor,normal)
|
||||
Q_PROPERTY_AUTO(QColor,light)
|
||||
Q_PROPERTY_AUTO(QColor,lighter)
|
||||
Q_PROPERTY_AUTO(QColor,lightest)
|
||||
class FluAccentColor : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY_AUTO(QColor, darkest)
|
||||
Q_PROPERTY_AUTO(QColor, darker)
|
||||
Q_PROPERTY_AUTO(QColor, dark)
|
||||
Q_PROPERTY_AUTO(QColor, normal)
|
||||
Q_PROPERTY_AUTO(QColor, light)
|
||||
Q_PROPERTY_AUTO(QColor, lighter)
|
||||
Q_PROPERTY_AUTO(QColor, lightest)
|
||||
QML_NAMED_ELEMENT(FluAccentColor)
|
||||
public:
|
||||
explicit FluAccentColor(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
#endif // FLUACCENTCOLOR_H
|
||||
|
@ -2,32 +2,48 @@
|
||||
|
||||
#include <QQmlEngine>
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlContext>
|
||||
#include <QQuickItem>
|
||||
#include <QTimer>
|
||||
#include <QUuid>
|
||||
#include <QFontDatabase>
|
||||
#include <QClipboard>
|
||||
#include <QTranslator>
|
||||
#include <utility>
|
||||
#include "FluentIconDef.h"
|
||||
|
||||
FluApp::FluApp(QObject *parent):QObject{parent}{
|
||||
useSystemAppBar(false);
|
||||
FluApp::FluApp(QObject *parent) : QObject{parent} {
|
||||
_useSystemAppBar = false;
|
||||
}
|
||||
|
||||
FluApp::~FluApp(){
|
||||
}
|
||||
FluApp::~FluApp() = default;
|
||||
|
||||
void FluApp::init(QObject *target,QLocale locale){
|
||||
_locale = locale;
|
||||
void FluApp::init(QObject *target, QLocale locale) {
|
||||
_locale = std::move(locale);
|
||||
_engine = qmlEngine(target);
|
||||
_translator = new QTranslator(this);
|
||||
qApp->installTranslator(_translator);
|
||||
QGuiApplication::installTranslator(_translator);
|
||||
const QStringList uiLanguages = _locale.uiLanguages();
|
||||
for (const QString &name : uiLanguages) {
|
||||
for (const QString &name: uiLanguages) {
|
||||
const QString baseName = "fluentui_" + QLocale(name).name();
|
||||
if (_translator->load(":/qt/qml/FluentUI/i18n/"+ baseName)) {
|
||||
if (_translator->load(":/qt/qml/FluentUI/i18n/" + baseName)) {
|
||||
_engine->retranslate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[maybe_unused]] QJsonArray FluApp::iconDatas(const QString &keyword) {
|
||||
QJsonArray arr;
|
||||
QMetaEnum enumType = Fluent_Icons::staticMetaObject.enumerator(Fluent_Icons::staticMetaObject.indexOfEnumerator("Fluent_IconType"));
|
||||
for (int i = 0; i <= enumType.keyCount() - 1; ++i) {
|
||||
QString name = enumType.key(i);
|
||||
int icon = enumType.value(i);
|
||||
if (keyword.isEmpty() || name.contains(keyword)) {
|
||||
QJsonObject obj;
|
||||
obj.insert("name", name);
|
||||
obj.insert("icon", icon);
|
||||
arr.append(obj);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
42
src/FluApp.h
42
src/FluApp.h
@ -1,5 +1,4 @@
|
||||
#ifndef FLUAPP_H
|
||||
#define FLUAPP_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QWindow>
|
||||
@ -9,30 +8,37 @@
|
||||
#include <QQmlEngine>
|
||||
#include <QTranslator>
|
||||
#include <QQuickWindow>
|
||||
#include <QJsonArray>
|
||||
#include "stdafx.h"
|
||||
#include "singleton.h"
|
||||
|
||||
/**
|
||||
* @brief The FluApp class
|
||||
*/
|
||||
class FluApp : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(bool,useSystemAppBar);
|
||||
Q_PROPERTY_AUTO(QString,windowIcon);
|
||||
Q_PROPERTY_AUTO(QLocale,locale);
|
||||
class FluApp : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY_AUTO(bool, useSystemAppBar)
|
||||
Q_PROPERTY_AUTO(QString, windowIcon)
|
||||
Q_PROPERTY_AUTO(QLocale, locale)
|
||||
QML_NAMED_ELEMENT(FluApp)
|
||||
QML_SINGLETON
|
||||
|
||||
private:
|
||||
explicit FluApp(QObject *parent = nullptr);
|
||||
~FluApp();
|
||||
public:
|
||||
SINGLETON(FluApp)
|
||||
static FluApp *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
|
||||
Q_INVOKABLE void init(QObject *target,QLocale locale = QLocale::system());
|
||||
private:
|
||||
QQmlEngine *_engine;
|
||||
QTranslator* _translator = nullptr;
|
||||
};
|
||||
|
||||
#endif // FLUAPP_H
|
||||
~FluApp() override;
|
||||
|
||||
public:
|
||||
SINGLETON(FluApp)
|
||||
|
||||
static FluApp *create(QQmlEngine *, QJSEngine *) { return getInstance(); }
|
||||
|
||||
Q_INVOKABLE void init(QObject *target, QLocale locale = QLocale::system());
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE static QJsonArray iconDatas(const QString &keyword = "");
|
||||
|
||||
private:
|
||||
QQmlEngine *_engine{};
|
||||
QTranslator *_translator = nullptr;
|
||||
};
|
||||
|
@ -3,74 +3,67 @@
|
||||
#include <QChar>
|
||||
#include <QPainter>
|
||||
#include <QRandomGenerator>
|
||||
#include <qmath.h>
|
||||
|
||||
FluCaptcha::FluCaptcha(QQuickItem *parent):QQuickPaintedItem(parent){
|
||||
ignoreCase(true);
|
||||
QFont fontStype;
|
||||
fontStype.setPixelSize(28);
|
||||
fontStype.setBold(true);
|
||||
font(fontStype);
|
||||
int generaNumber(int number) {
|
||||
return QRandomGenerator::global()->bounded(0, number);
|
||||
}
|
||||
|
||||
FluCaptcha::FluCaptcha(QQuickItem *parent) : QQuickPaintedItem(parent) {
|
||||
_ignoreCase = false;
|
||||
QFont fontStyle;
|
||||
#ifdef Q_OS_WIN
|
||||
fontStyle.setFamily("微软雅黑");
|
||||
#endif
|
||||
fontStyle.setPixelSize(28);
|
||||
fontStyle.setBold(true);
|
||||
font(fontStyle);
|
||||
setWidth(180);
|
||||
setHeight(80);
|
||||
refresh();
|
||||
}
|
||||
|
||||
void FluCaptcha::paint(QPainter* painter){
|
||||
void FluCaptcha::paint(QPainter *painter) {
|
||||
painter->save();
|
||||
painter->fillRect(boundingRect().toRect(),QColor(255,255,255,255));
|
||||
painter->fillRect(boundingRect().toRect(), QColor(255, 255, 255, 255));
|
||||
QPen pen;
|
||||
painter->setFont(_font);
|
||||
for(int i=0;i<100;i++)
|
||||
{
|
||||
pen = QPen(QColor(_generaNumber(256),_generaNumber(256),_generaNumber(256)));
|
||||
for (int i = 0; i < 100; i++) {
|
||||
pen = QPen(QColor(generaNumber(256), generaNumber(256), generaNumber(256)));
|
||||
painter->setPen(pen);
|
||||
painter->drawPoint(_generaNumber(180),_generaNumber(80));
|
||||
painter->drawPoint(generaNumber(180), generaNumber(80));
|
||||
}
|
||||
for(int i=0;i<5;i++)
|
||||
{
|
||||
pen = QPen(QColor(_generaNumber(256),_generaNumber(256),_generaNumber(256)));
|
||||
for (int i = 0; i < 5; i++) {
|
||||
pen = QPen(QColor(generaNumber(256), generaNumber(256), generaNumber(256)));
|
||||
painter->setPen(pen);
|
||||
painter->drawLine(_generaNumber(180),_generaNumber(80),_generaNumber(180),_generaNumber(80));
|
||||
painter->drawLine(generaNumber(180), generaNumber(80), generaNumber(180), generaNumber(80));
|
||||
}
|
||||
for(int i=0;i<4;i++)
|
||||
{
|
||||
pen = QPen(QColor(_generaNumber(255),_generaNumber(255),_generaNumber(255)));
|
||||
for (int i = 0; i < 4; i++) {
|
||||
pen = QPen(QColor(generaNumber(255), generaNumber(255), generaNumber(255)));
|
||||
painter->setPen(pen);
|
||||
painter->drawText(15+35*i,10+_generaNumber(15),30,40,Qt::AlignCenter, QString(_code[i]));
|
||||
painter->drawText(15 + 35 * i, 10 + generaNumber(15), 30, 40, Qt::AlignCenter, QString(_code[i]));
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
int FluCaptcha::_generaNumber(int number){
|
||||
return QRandomGenerator::global()->bounded(0,number);
|
||||
}
|
||||
|
||||
void FluCaptcha::refresh(){
|
||||
void FluCaptcha::refresh() {
|
||||
this->_code.clear();
|
||||
for(int i = 0;i < 4;++i)
|
||||
{
|
||||
int num = _generaNumber(3);
|
||||
if(num == 0)
|
||||
{
|
||||
this->_code += QString::number(_generaNumber(10));
|
||||
}
|
||||
else if(num == 1)
|
||||
{
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
int num = generaNumber(3);
|
||||
if (num == 0) {
|
||||
this->_code += QString::number(generaNumber(10));
|
||||
} else if (num == 1) {
|
||||
int temp = 'A';
|
||||
this->_code += static_cast<QChar>(temp + _generaNumber(26));
|
||||
}
|
||||
else if(num == 2)
|
||||
{
|
||||
this->_code += static_cast<QChar>(temp + generaNumber(26));
|
||||
} else if (num == 2) {
|
||||
int temp = 'a';
|
||||
this->_code += static_cast<QChar>(temp + _generaNumber(26));
|
||||
this->_code += static_cast<QChar>(temp + generaNumber(26));
|
||||
}
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
bool FluCaptcha::verify(const QString& code){
|
||||
if(_ignoreCase){
|
||||
[[maybe_unused]] bool FluCaptcha::verify(const QString &code) {
|
||||
if (_ignoreCase) {
|
||||
return this->_code.toUpper() == code.toUpper();
|
||||
}
|
||||
return this->_code == code;
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef FLUCAPTCHA_H
|
||||
#define FLUCAPTCHA_H
|
||||
#pragma once
|
||||
|
||||
#include <QQuickItem>
|
||||
#include <QQuickPaintedItem>
|
||||
@ -9,21 +8,22 @@
|
||||
/**
|
||||
* @brief The FluCaptcha class
|
||||
*/
|
||||
class FluCaptcha : public QQuickPaintedItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QFont,font);
|
||||
Q_PROPERTY_AUTO(bool,ignoreCase);
|
||||
class FluCaptcha : public QQuickPaintedItem {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY_AUTO(QFont, font);
|
||||
Q_PROPERTY_AUTO(bool, ignoreCase);
|
||||
QML_NAMED_ELEMENT(FluCaptcha)
|
||||
private:
|
||||
int _generaNumber(int number);
|
||||
|
||||
public:
|
||||
explicit FluCaptcha(QQuickItem *parent = nullptr);
|
||||
void paint(QPainter* painter) override;
|
||||
|
||||
void paint(QPainter *painter) override;
|
||||
|
||||
Q_INVOKABLE void refresh();
|
||||
Q_INVOKABLE bool verify(const QString& code);
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE bool verify(const QString &code);
|
||||
|
||||
private:
|
||||
QString _code;
|
||||
};
|
||||
|
||||
#endif // FLUCAPTCHA_H
|
||||
|
@ -1,35 +1,34 @@
|
||||
#include "FluColors.h"
|
||||
#include "FluTools.h"
|
||||
|
||||
FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
Transparent(QColor(0, 0, 0, 0));
|
||||
Black(QColor(0, 0, 0));
|
||||
White(QColor(255, 255, 255));
|
||||
Grey10(QColor(250, 249, 248));
|
||||
Grey20(QColor(243, 242, 241));
|
||||
Grey30(QColor(237, 235, 233));
|
||||
Grey40(QColor(225, 223, 221));
|
||||
Grey50(QColor(210, 208, 206));
|
||||
Grey60(QColor(200, 198, 196));
|
||||
Grey70(QColor(190, 185, 184));
|
||||
Grey80(QColor(179, 176, 173));
|
||||
Grey90(QColor(161, 159, 157));
|
||||
Grey100(QColor(151, 149, 146));
|
||||
Grey110(QColor(138, 136, 134));
|
||||
Grey120(QColor(121, 119, 117));
|
||||
Grey130(QColor(96, 94, 92));
|
||||
Grey140(QColor(72, 70, 68));
|
||||
Grey150(QColor(59, 58, 57));
|
||||
Grey160(QColor(50, 49, 48));
|
||||
Grey170(QColor(41, 40, 39));
|
||||
Grey180(QColor(37, 36, 35));
|
||||
Grey190(QColor(32, 31, 30));
|
||||
Grey200(QColor(27, 26, 25));
|
||||
Grey210(QColor(22, 21, 20));
|
||||
Grey220(QColor(17, 16, 15));
|
||||
FluColors::FluColors(QObject *parent) : QObject{parent} {
|
||||
_Transparent = QColor(0, 0, 0, 0);
|
||||
_Black = QColor(0, 0, 0);
|
||||
_White = QColor(255, 255, 255);
|
||||
_Grey10 = QColor(250, 249, 248);
|
||||
_Grey20 = QColor(243, 242, 241);
|
||||
_Grey30 = QColor(237, 235, 233);
|
||||
_Grey40 = QColor(225, 223, 221);
|
||||
_Grey50 = QColor(210, 208, 206);
|
||||
_Grey60 = QColor(200, 198, 196);
|
||||
_Grey70 = QColor(190, 185, 184);
|
||||
_Grey80 = QColor(179, 176, 173);
|
||||
_Grey90 = QColor(161, 159, 157);
|
||||
_Grey100 = QColor(151, 149, 146);
|
||||
_Grey110 = QColor(138, 136, 134);
|
||||
_Grey120 = QColor(121, 119, 117);
|
||||
_Grey130 = QColor(96, 94, 92);
|
||||
_Grey140 = QColor(72, 70, 68);
|
||||
_Grey150 = QColor(59, 58, 57);
|
||||
_Grey160 = QColor(50, 49, 48);
|
||||
_Grey170 = QColor(41, 40, 39);
|
||||
_Grey180 = QColor(37, 36, 35);
|
||||
_Grey190 = QColor(32, 31, 30);
|
||||
_Grey200 = QColor(27, 26, 25);
|
||||
_Grey210 = QColor(22, 21, 20);
|
||||
_Grey220 = QColor(17, 16, 15);
|
||||
|
||||
|
||||
FluAccentColor *yellow = new FluAccentColor(this);
|
||||
auto yellow = new FluAccentColor(this);
|
||||
yellow->darkest(QColor(249, 168, 37));
|
||||
yellow->darker(QColor(251, 192, 45));
|
||||
yellow->dark(QColor(253, 212, 53));
|
||||
@ -37,9 +36,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
yellow->light(QColor(255, 238, 88));
|
||||
yellow->lighter(QColor(255, 241, 118));
|
||||
yellow->lightest(QColor(255, 245, 155));
|
||||
Yellow(yellow);
|
||||
_Yellow = yellow;
|
||||
|
||||
FluAccentColor *orange = new FluAccentColor(this);
|
||||
auto orange = new FluAccentColor(this);
|
||||
orange->darkest(QColor(153, 61, 7));
|
||||
orange->darker(QColor(172, 68, 8));
|
||||
orange->dark(QColor(209, 88, 10));
|
||||
@ -47,9 +46,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
orange->light(QColor(248, 122, 48));
|
||||
orange->lighter(QColor(249, 145, 84));
|
||||
orange->lightest(QColor(250, 192, 106));
|
||||
Orange(orange);
|
||||
_Orange = orange;
|
||||
|
||||
FluAccentColor *red = new FluAccentColor(this);
|
||||
auto red = new FluAccentColor(this);
|
||||
red->darkest(QColor(143, 10, 21));
|
||||
red->darker(QColor(162, 11, 24));
|
||||
red->dark(QColor(185, 13, 28));
|
||||
@ -57,9 +56,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
red->light(QColor(236, 64, 79));
|
||||
red->lighter(QColor(238, 88, 101));
|
||||
red->lightest(QColor(240, 107, 118));
|
||||
Red(red);
|
||||
_Red = red;
|
||||
|
||||
FluAccentColor *magenta = new FluAccentColor(this);
|
||||
auto magenta = new FluAccentColor(this);
|
||||
magenta->darkest(QColor(111, 0, 79));
|
||||
magenta->darker(QColor(160, 7, 108));
|
||||
magenta->dark(QColor(181, 13, 125));
|
||||
@ -67,9 +66,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
magenta->light(QColor(234, 77, 168));
|
||||
magenta->lighter(QColor(238, 110, 193));
|
||||
magenta->lightest(QColor(241, 140, 213));
|
||||
Magenta(magenta);
|
||||
_Magenta = magenta;
|
||||
|
||||
FluAccentColor *purple = new FluAccentColor(this);
|
||||
auto purple = new FluAccentColor(this);
|
||||
purple->darkest(QColor(44, 15, 118));
|
||||
purple->darker(QColor(61, 15, 153));
|
||||
purple->dark(QColor(78, 17, 174));
|
||||
@ -77,9 +76,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
purple->light(QColor(123, 76, 157));
|
||||
purple->lighter(QColor(141, 110, 189));
|
||||
purple->lightest(QColor(158, 142, 217));
|
||||
Purple(purple);
|
||||
_Purple = purple;
|
||||
|
||||
FluAccentColor *blue = new FluAccentColor(this);
|
||||
auto blue = new FluAccentColor(this);
|
||||
blue->darkest(QColor(0, 74, 131));
|
||||
blue->darker(QColor(0, 84, 148));
|
||||
blue->dark(QColor(0, 102, 180));
|
||||
@ -87,9 +86,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
blue->light(QColor(38, 140, 220));
|
||||
blue->lighter(QColor(76, 160, 224));
|
||||
blue->lightest(QColor(96, 171, 228));
|
||||
Blue(blue);
|
||||
_Blue = blue;
|
||||
|
||||
FluAccentColor *teal = new FluAccentColor(this);
|
||||
auto teal = new FluAccentColor(this);
|
||||
teal->darkest(QColor(0, 110, 91));
|
||||
teal->darker(QColor(0, 124, 103));
|
||||
teal->dark(QColor(0, 151, 125));
|
||||
@ -97,9 +96,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
teal->light(QColor(38, 189, 164));
|
||||
teal->lighter(QColor(77, 201, 180));
|
||||
teal->lightest(QColor(96, 207, 188));
|
||||
Teal(teal);
|
||||
_Teal = teal;
|
||||
|
||||
FluAccentColor *green = new FluAccentColor(this);
|
||||
auto green = new FluAccentColor(this);
|
||||
green->darkest(QColor(9, 76, 9));
|
||||
green->darker(QColor(12, 93, 12));
|
||||
green->dark(QColor(14, 111, 14));
|
||||
@ -107,17 +106,17 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
green->light(QColor(39, 137, 57));
|
||||
green->lighter(QColor(76, 156, 76));
|
||||
green->lightest(QColor(106, 173, 106));
|
||||
Green(green);
|
||||
_Green = green;
|
||||
}
|
||||
|
||||
FluAccentColor* FluColors::createAccentColor(QColor primaryColor){
|
||||
FluAccentColor *accentColor = new FluAccentColor(this);
|
||||
accentColor->darkest(FluTools::getInstance()->withOpacity(primaryColor,0.7));
|
||||
accentColor->darker(FluTools::getInstance()->withOpacity(primaryColor,0.8));
|
||||
accentColor->dark(FluTools::getInstance()->withOpacity(primaryColor,0.9));
|
||||
[[maybe_unused]] FluAccentColor *FluColors::createAccentColor(const QColor &primaryColor) {
|
||||
auto accentColor = new FluAccentColor(this);
|
||||
accentColor->normal(primaryColor);
|
||||
accentColor->light(FluTools::getInstance()->withOpacity(primaryColor,0.9));
|
||||
accentColor->lighter(FluTools::getInstance()->withOpacity(primaryColor,0.8));
|
||||
accentColor->lightest(FluTools::getInstance()->withOpacity(primaryColor,0.7));
|
||||
accentColor->dark(FluTools::getInstance()->withOpacity(primaryColor, 0.9));
|
||||
accentColor->light(FluTools::getInstance()->withOpacity(primaryColor, 0.9));
|
||||
accentColor->darker(FluTools::getInstance()->withOpacity(accentColor->dark(), 0.8));
|
||||
accentColor->lighter(FluTools::getInstance()->withOpacity(accentColor->light(), 0.8));
|
||||
accentColor->darkest(FluTools::getInstance()->withOpacity(accentColor->darker(), 0.7));
|
||||
accentColor->lightest(FluTools::getInstance()->withOpacity(accentColor->lighter(), 0.7));
|
||||
return accentColor;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef FLUCOLORS_H
|
||||
#define FLUCOLORS_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QtQml/qqml.h>
|
||||
@ -11,50 +10,52 @@
|
||||
/**
|
||||
* @brief The FluColors class
|
||||
*/
|
||||
class FluColors : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QColor,Transparent);
|
||||
Q_PROPERTY_AUTO(QColor,Black);
|
||||
Q_PROPERTY_AUTO(QColor,White);
|
||||
Q_PROPERTY_AUTO(QColor,Grey10);
|
||||
Q_PROPERTY_AUTO(QColor,Grey20);
|
||||
Q_PROPERTY_AUTO(QColor,Grey30);
|
||||
Q_PROPERTY_AUTO(QColor,Grey40);
|
||||
Q_PROPERTY_AUTO(QColor,Grey50);
|
||||
Q_PROPERTY_AUTO(QColor,Grey60);
|
||||
Q_PROPERTY_AUTO(QColor,Grey70);
|
||||
Q_PROPERTY_AUTO(QColor,Grey80);
|
||||
Q_PROPERTY_AUTO(QColor,Grey90);
|
||||
Q_PROPERTY_AUTO(QColor,Grey100);
|
||||
Q_PROPERTY_AUTO(QColor,Grey110);
|
||||
Q_PROPERTY_AUTO(QColor,Grey120);
|
||||
Q_PROPERTY_AUTO(QColor,Grey130);
|
||||
Q_PROPERTY_AUTO(QColor,Grey140);
|
||||
Q_PROPERTY_AUTO(QColor,Grey150);
|
||||
Q_PROPERTY_AUTO(QColor,Grey160);
|
||||
Q_PROPERTY_AUTO(QColor,Grey170);
|
||||
Q_PROPERTY_AUTO(QColor,Grey180);
|
||||
Q_PROPERTY_AUTO(QColor,Grey190);
|
||||
Q_PROPERTY_AUTO(QColor,Grey200);
|
||||
Q_PROPERTY_AUTO(QColor,Grey210);
|
||||
Q_PROPERTY_AUTO(QColor,Grey220);
|
||||
Q_PROPERTY_AUTO(FluAccentColor*,Yellow);
|
||||
Q_PROPERTY_AUTO(FluAccentColor*,Orange);
|
||||
Q_PROPERTY_AUTO(FluAccentColor*,Red);
|
||||
Q_PROPERTY_AUTO(FluAccentColor*,Magenta);
|
||||
Q_PROPERTY_AUTO(FluAccentColor*,Purple);
|
||||
Q_PROPERTY_AUTO(FluAccentColor*,Blue);
|
||||
Q_PROPERTY_AUTO(FluAccentColor*,Teal);
|
||||
Q_PROPERTY_AUTO(FluAccentColor*,Green);
|
||||
class FluColors : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY_AUTO(QColor, Transparent);
|
||||
Q_PROPERTY_AUTO(QColor, Black);
|
||||
Q_PROPERTY_AUTO(QColor, White);
|
||||
Q_PROPERTY_AUTO(QColor, Grey10);
|
||||
Q_PROPERTY_AUTO(QColor, Grey20);
|
||||
Q_PROPERTY_AUTO(QColor, Grey30);
|
||||
Q_PROPERTY_AUTO(QColor, Grey40);
|
||||
Q_PROPERTY_AUTO(QColor, Grey50);
|
||||
Q_PROPERTY_AUTO(QColor, Grey60);
|
||||
Q_PROPERTY_AUTO(QColor, Grey70);
|
||||
Q_PROPERTY_AUTO(QColor, Grey80);
|
||||
Q_PROPERTY_AUTO(QColor, Grey90);
|
||||
Q_PROPERTY_AUTO(QColor, Grey100);
|
||||
Q_PROPERTY_AUTO(QColor, Grey110);
|
||||
Q_PROPERTY_AUTO(QColor, Grey120);
|
||||
Q_PROPERTY_AUTO(QColor, Grey130);
|
||||
Q_PROPERTY_AUTO(QColor, Grey140);
|
||||
Q_PROPERTY_AUTO(QColor, Grey150);
|
||||
Q_PROPERTY_AUTO(QColor, Grey160);
|
||||
Q_PROPERTY_AUTO(QColor, Grey170);
|
||||
Q_PROPERTY_AUTO(QColor, Grey180);
|
||||
Q_PROPERTY_AUTO(QColor, Grey190);
|
||||
Q_PROPERTY_AUTO(QColor, Grey200);
|
||||
Q_PROPERTY_AUTO(QColor, Grey210);
|
||||
Q_PROPERTY_AUTO(QColor, Grey220);
|
||||
Q_PROPERTY_AUTO_P(FluAccentColor*, Yellow);
|
||||
Q_PROPERTY_AUTO_P(FluAccentColor*, Orange);
|
||||
Q_PROPERTY_AUTO_P(FluAccentColor*, Red);
|
||||
Q_PROPERTY_AUTO_P(FluAccentColor*, Magenta);
|
||||
Q_PROPERTY_AUTO_P(FluAccentColor*, Purple);
|
||||
Q_PROPERTY_AUTO_P(FluAccentColor*, Blue);
|
||||
Q_PROPERTY_AUTO_P(FluAccentColor*, Teal);
|
||||
Q_PROPERTY_AUTO_P(FluAccentColor*, Green);
|
||||
QML_NAMED_ELEMENT(FluColors)
|
||||
QML_SINGLETON
|
||||
|
||||
private:
|
||||
explicit FluColors(QObject *parent = nullptr);
|
||||
public:
|
||||
SINGLETON(FluColors)
|
||||
Q_INVOKABLE FluAccentColor* createAccentColor(QColor primaryColor);
|
||||
static FluColors *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
|
||||
};
|
||||
|
||||
#endif // FLUCOLORS_H
|
||||
public:
|
||||
SINGLETON(FluColors)
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE FluAccentColor *createAccentColor(const QColor &primaryColor);
|
||||
|
||||
static FluColors *create(QQmlEngine *, QJSEngine *) { return getInstance(); }
|
||||
};
|
||||
|
@ -4,132 +4,152 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
#include <QDateTime>
|
||||
#include "FluTools.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#pragma comment (lib,"user32.lib")
|
||||
#pragma comment (lib,"dwmapi.lib")
|
||||
#pragma comment (lib, "user32.lib")
|
||||
#pragma comment (lib, "dwmapi.lib")
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <dwmapi.h>
|
||||
static inline QByteArray qtNativeEventType()
|
||||
{
|
||||
|
||||
|
||||
static inline QByteArray qtNativeEventType() {
|
||||
static const auto result = "windows_generic_MSG";
|
||||
return result;
|
||||
}
|
||||
static inline bool isCompositionEnabled(){
|
||||
typedef HRESULT (WINAPI* DwmIsCompositionEnabledPtr)(BOOL *pfEnabled);
|
||||
|
||||
static inline bool isCompositionEnabled() {
|
||||
typedef HRESULT (WINAPI *DwmIsCompositionEnabledPtr)(BOOL *pfEnabled);
|
||||
HMODULE module = ::LoadLibraryW(L"dwmapi.dll");
|
||||
if (module)
|
||||
{
|
||||
if (module) {
|
||||
BOOL composition_enabled = false;
|
||||
DwmIsCompositionEnabledPtr dwm_is_composition_enabled;
|
||||
dwm_is_composition_enabled= reinterpret_cast<DwmIsCompositionEnabledPtr>(::GetProcAddress(module, "DwmIsCompositionEnabled"));
|
||||
if (dwm_is_composition_enabled)
|
||||
{
|
||||
dwm_is_composition_enabled = reinterpret_cast<DwmIsCompositionEnabledPtr>(::GetProcAddress(module, "DwmIsCompositionEnabled"));
|
||||
if (dwm_is_composition_enabled) {
|
||||
dwm_is_composition_enabled(&composition_enabled);
|
||||
}
|
||||
return composition_enabled;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
FluFrameless::FluFrameless(QQuickItem *parent)
|
||||
: QQuickItem{parent}
|
||||
{
|
||||
appbar(nullptr);
|
||||
maximizeButton(nullptr);
|
||||
minimizedButton(nullptr);
|
||||
closeButton(nullptr);
|
||||
topmost(false);
|
||||
disabled(false);
|
||||
bool containsCursorToItem(QQuickItem *item) {
|
||||
if (!item || !item->isVisible()) {
|
||||
return false;
|
||||
}
|
||||
auto point = QCursor::pos();
|
||||
auto rect = QRectF(item->mapToGlobal(QPoint(0, 0)), item->size());
|
||||
if (point.x() > rect.x() && point.x() < (rect.x() + rect.width()) && point.y() > rect.y() && point.y() < (rect.y() + rect.height())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FluFrameless::~FluFrameless(){
|
||||
FluFrameless::FluFrameless(QQuickItem *parent) : QQuickItem{parent} {
|
||||
_fixSize = false;
|
||||
_appbar = nullptr;
|
||||
_maximizeButton = nullptr;
|
||||
_minimizedButton = nullptr;
|
||||
_closeButton = nullptr;
|
||||
_topmost = false;
|
||||
_disabled = false;
|
||||
_isWindows11OrGreater = FluTools::getInstance()->isWindows11OrGreater();
|
||||
}
|
||||
|
||||
void FluFrameless::onDestruction(){
|
||||
qApp->removeNativeEventFilter(this);
|
||||
FluFrameless::~FluFrameless() = default;
|
||||
|
||||
[[maybe_unused]] void FluFrameless::onDestruction() {
|
||||
QGuiApplication::instance()->removeNativeEventFilter(this);
|
||||
}
|
||||
|
||||
void FluFrameless::componentComplete(){
|
||||
if(_disabled){
|
||||
void FluFrameless::componentComplete() {
|
||||
if (_disabled) {
|
||||
return;
|
||||
}
|
||||
int w = window()->width();
|
||||
int h = window()->height();
|
||||
_current = window()->winId();
|
||||
window()->setFlags(( window()->flags()) | Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::FramelessWindowHint);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
|
||||
if(QQuickWindow::sceneGraphBackend() == "software"){
|
||||
window()->setFlag(Qt::FramelessWindowHint,false);
|
||||
window()->setFlags((window()->flags()) | Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::FramelessWindowHint);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
if (QQuickWindow::sceneGraphBackend() == "software") {
|
||||
window()->setFlag(Qt::FramelessWindowHint, false);
|
||||
}
|
||||
#endif
|
||||
if(!_fixSize){
|
||||
if (!_fixSize) {
|
||||
window()->setFlag(Qt::WindowMaximizeButtonHint);
|
||||
}
|
||||
window()->installEventFilter(this);
|
||||
qApp->installNativeEventFilter(this);
|
||||
if(_maximizeButton){
|
||||
QGuiApplication::instance()->installNativeEventFilter(this);
|
||||
if (_maximizeButton) {
|
||||
setHitTestVisible(_maximizeButton);
|
||||
}
|
||||
if(_minimizedButton){
|
||||
if (_minimizedButton) {
|
||||
setHitTestVisible(_minimizedButton);
|
||||
}
|
||||
if(_closeButton){
|
||||
if (_closeButton) {
|
||||
setHitTestVisible(_closeButton);
|
||||
}
|
||||
#ifdef Q_OS_WIN
|
||||
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
|
||||
DWORD style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
|
||||
if(_fixSize){
|
||||
if (_fixSize) {
|
||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME);
|
||||
for (int i = 0; i < qApp->screens().count(); ++i) {
|
||||
connect( qApp->screens().at(i),&QScreen::logicalDotsPerInchChanged,this,[=]{
|
||||
SetWindowPos(hwnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_FRAMECHANGED);
|
||||
for (int i = 0; i <= QGuiApplication::screens().count() - 1; ++i) {
|
||||
connect(QGuiApplication::screens().at(i), &QScreen::logicalDotsPerInchChanged, this, [=] {
|
||||
SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_FRAMECHANGED);
|
||||
});
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME);
|
||||
}
|
||||
SetWindowPos(hwnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
|
||||
connect(window(),&QQuickWindow::screenChanged,this,[hwnd]{
|
||||
::SetWindowPos(hwnd,0,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
|
||||
::RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||||
SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
|
||||
connect(window(), &QQuickWindow::screenChanged, this, [hwnd] {
|
||||
::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
|
||||
::RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
|
||||
});
|
||||
#endif
|
||||
connect(this,&FluFrameless::topmostChanged,this,[this]{
|
||||
h = qRound(h + _appbar->height());
|
||||
if (_fixSize) {
|
||||
window()->setMaximumSize(QSize(w, h));
|
||||
window()->setMinimumSize(QSize(w, h));
|
||||
}
|
||||
window()->resize(QSize(w, h));
|
||||
connect(this, &FluFrameless::topmostChanged, this, [this] {
|
||||
_setWindowTopmost(topmost());
|
||||
});
|
||||
_setWindowTopmost(topmost());
|
||||
}
|
||||
|
||||
bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result){
|
||||
[[maybe_unused]] bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) {
|
||||
#ifdef Q_OS_WIN
|
||||
if ((eventType != qtNativeEventType()) || !message) {
|
||||
return false;
|
||||
}
|
||||
const auto msg = static_cast<const MSG *>(message);
|
||||
const HWND hwnd = msg->hwnd;
|
||||
if (!hwnd || !msg) {
|
||||
auto hwnd = msg->hwnd;
|
||||
if (!hwnd) {
|
||||
return false;
|
||||
}
|
||||
const qint64 wid = reinterpret_cast<qint64>(hwnd);
|
||||
if(wid != _current){
|
||||
const quint64 wid = reinterpret_cast<qint64>(hwnd);
|
||||
if (wid != _current) {
|
||||
return false;
|
||||
}
|
||||
const UINT uMsg = msg->message;
|
||||
const WPARAM wParam = msg->wParam;
|
||||
const LPARAM lParam = msg->lParam;
|
||||
static QPoint offsetXY;
|
||||
if(uMsg == WM_WINDOWPOSCHANGING){
|
||||
WINDOWPOS* wp = reinterpret_cast<WINDOWPOS*>(lParam);
|
||||
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0)
|
||||
{
|
||||
const auto uMsg = msg->message;
|
||||
const auto wParam = msg->wParam;
|
||||
const auto lParam = msg->lParam;
|
||||
if (uMsg == WM_WINDOWPOSCHANGING) {
|
||||
auto *wp = reinterpret_cast<WINDOWPOS *>(lParam);
|
||||
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0) {
|
||||
wp->flags |= SWP_NOCOPYBITS;
|
||||
*result = ::DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||
*result = static_cast<QT_NATIVE_EVENT_RESULT_TYPE>(::DefWindowProcW(hwnd, uMsg, wParam, lParam));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}else if(uMsg == WM_NCCALCSIZE){
|
||||
} else if (uMsg == WM_NCCALCSIZE) {
|
||||
const auto clientRect = ((wParam == FALSE) ? reinterpret_cast<LPRECT>(lParam) : &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0]);
|
||||
const LONG originalTop = clientRect->top;
|
||||
const LONG originalLeft = clientRect->left;
|
||||
@ -137,47 +157,46 @@ bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message,
|
||||
const LONG originalBottom = clientRect->bottom;
|
||||
const LRESULT hitTestResult = ::DefWindowProcW(hwnd, WM_NCCALCSIZE, wParam, lParam);
|
||||
if ((hitTestResult != HTERROR) && (hitTestResult != HTNOWHERE)) {
|
||||
*result = hitTestResult;
|
||||
*result = static_cast<QT_NATIVE_EVENT_RESULT_TYPE>(hitTestResult);
|
||||
return true;
|
||||
}
|
||||
int offsetSize = 0;
|
||||
int offsetSize;
|
||||
bool isMaximum = ::IsZoomed(hwnd);
|
||||
offsetXY = QPoint(abs(clientRect->left - originalLeft),abs(clientRect->top - originalTop));
|
||||
if(isMaximum || _isFullScreen()){
|
||||
if (isMaximum || _isFullScreen()) {
|
||||
offsetSize = 0;
|
||||
}else{
|
||||
} else {
|
||||
offsetSize = 1;
|
||||
}
|
||||
if(!isCompositionEnabled()){
|
||||
if (!isCompositionEnabled()) {
|
||||
offsetSize = 0;
|
||||
}
|
||||
if (!isMaximum || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) {
|
||||
clientRect->top = originalTop + offsetSize;
|
||||
clientRect->bottom = originalBottom - offsetSize;
|
||||
clientRect->left = originalLeft + offsetSize;
|
||||
clientRect->right = originalRight - offsetSize;
|
||||
}
|
||||
clientRect->top = originalTop + offsetSize;
|
||||
clientRect->bottom = originalBottom - offsetSize;
|
||||
clientRect->left = originalLeft + offsetSize;
|
||||
clientRect->right = originalRight - offsetSize;
|
||||
_setMaximizeHovered(false);
|
||||
*result = WVR_REDRAW;
|
||||
return true;
|
||||
}else if(uMsg == WM_NCHITTEST){
|
||||
if(_hitMaximizeButton()){
|
||||
if (*result == HTNOWHERE) {
|
||||
*result = HTZOOM;
|
||||
} else if (uMsg == WM_NCHITTEST) {
|
||||
if (_isWindows11OrGreater) {
|
||||
if (_hitMaximizeButton()) {
|
||||
if (*result == HTNOWHERE) {
|
||||
*result = HTZOOM;
|
||||
}
|
||||
_setMaximizeHovered(true);
|
||||
return true;
|
||||
}
|
||||
_setMaximizeHovered(true);
|
||||
return true;
|
||||
_setMaximizeHovered(false);
|
||||
_setMaximizePressed(false);
|
||||
}
|
||||
_setMaximizeHovered(false);
|
||||
_setMaximizePressed(false);
|
||||
*result = 0;
|
||||
POINT nativeGlobalPos{GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
|
||||
POINT nativeLocalPos = nativeGlobalPos;
|
||||
::ScreenToClient(hwnd, &nativeLocalPos);
|
||||
RECT clientRect{0, 0, 0, 0};
|
||||
::GetClientRect(hwnd, &clientRect);
|
||||
auto clientWidth = clientRect.right-clientRect.left;
|
||||
auto clientHeight = clientRect.bottom-clientRect.top;
|
||||
auto clientWidth = clientRect.right - clientRect.left;
|
||||
auto clientHeight = clientRect.bottom - clientRect.top;
|
||||
bool left = nativeLocalPos.x < _margins;
|
||||
bool right = nativeLocalPos.x > clientWidth - _margins;
|
||||
bool top = nativeLocalPos.y < _margins;
|
||||
@ -205,203 +224,202 @@ bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message,
|
||||
if (0 != *result) {
|
||||
return true;
|
||||
}
|
||||
if(_hitAppBar()){
|
||||
if (_hitAppBar()) {
|
||||
*result = HTCAPTION;
|
||||
return true;
|
||||
}
|
||||
*result = HTCLIENT;
|
||||
return true;
|
||||
}else if(uMsg == WM_NCLBUTTONDBLCLK || uMsg == WM_NCLBUTTONDOWN){
|
||||
if(_hitMaximizeButton()){
|
||||
} else if (_isWindows11OrGreater && (uMsg == WM_NCLBUTTONDBLCLK || uMsg == WM_NCLBUTTONDOWN)) {
|
||||
if (_hitMaximizeButton()) {
|
||||
QMouseEvent event = QMouseEvent(QEvent::MouseButtonPress, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
||||
QGuiApplication::sendEvent(_maximizeButton,&event);
|
||||
QGuiApplication::sendEvent(_maximizeButton, &event);
|
||||
_setMaximizePressed(true);
|
||||
return true;
|
||||
}
|
||||
}else if(uMsg == WM_NCLBUTTONUP || uMsg == WM_NCRBUTTONUP){
|
||||
if(_hitMaximizeButton()){
|
||||
} else if (_isWindows11OrGreater && (uMsg == WM_NCLBUTTONUP || uMsg == WM_NCRBUTTONUP)) {
|
||||
if (_hitMaximizeButton()) {
|
||||
QMouseEvent event = QMouseEvent(QEvent::MouseButtonRelease, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
||||
QGuiApplication::sendEvent(_maximizeButton,&event);
|
||||
QGuiApplication::sendEvent(_maximizeButton, &event);
|
||||
_setMaximizePressed(false);
|
||||
return true;
|
||||
}
|
||||
}else if(uMsg == WM_NCPAINT){
|
||||
} else if (uMsg == WM_NCPAINT) {
|
||||
*result = FALSE;
|
||||
return true;
|
||||
}else if(uMsg == WM_NCACTIVATE){
|
||||
*result = ::DefWindowProcW(hwnd, WM_NCACTIVATE, wParam, -1);
|
||||
} else if (uMsg == WM_NCACTIVATE) {
|
||||
*result = static_cast<QT_NATIVE_EVENT_RESULT_TYPE>(::DefWindowProcW(hwnd, WM_NCACTIVATE, wParam, -1));
|
||||
return true;
|
||||
}else if(uMsg == WM_GETMINMAXINFO){
|
||||
MINMAXINFO* minmaxInfo = reinterpret_cast<MINMAXINFO *>(lParam);
|
||||
} else if (uMsg == WM_GETMINMAXINFO) {
|
||||
auto *minmaxInfo = reinterpret_cast<MINMAXINFO *>(lParam);
|
||||
auto pixelRatio = window()->devicePixelRatio();
|
||||
auto geometry = window()->screen()->availableGeometry();
|
||||
RECT rect;
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
|
||||
minmaxInfo->ptMaxPosition.x = rect.left - offsetXY.x();
|
||||
minmaxInfo->ptMaxPosition.y = rect.top - offsetXY.x();
|
||||
minmaxInfo->ptMaxSize.x = geometry.width()*pixelRatio + offsetXY.x() * 2;
|
||||
minmaxInfo->ptMaxSize.y = geometry.height()*pixelRatio + offsetXY.y() * 2;
|
||||
minmaxInfo->ptMaxPosition.x = rect.left;
|
||||
minmaxInfo->ptMaxPosition.y = rect.top;
|
||||
minmaxInfo->ptMaxSize.x = qRound(geometry.width() * pixelRatio);
|
||||
minmaxInfo->ptMaxSize.y = qRound(geometry.height() * pixelRatio);
|
||||
return false;
|
||||
}else if(uMsg == WM_NCRBUTTONDOWN){
|
||||
} else if (uMsg == WM_NCRBUTTONDOWN) {
|
||||
if (wParam == HTCAPTION) {
|
||||
_showSystemMenu(QCursor::pos());
|
||||
}
|
||||
}else if(uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN){
|
||||
} else if (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN) {
|
||||
const bool altPressed = ((wParam == VK_MENU) || (::GetKeyState(VK_MENU) < 0));
|
||||
const bool spacePressed = ((wParam == VK_SPACE) || (::GetKeyState(VK_SPACE) < 0));
|
||||
if (altPressed && spacePressed) {
|
||||
auto pos = window()->position();
|
||||
_showSystemMenu(QPoint(pos.x(),pos.y()+_appbar->height()));
|
||||
_showSystemMenu(QPoint(pos.x(), qRound(pos.y() + _appbar->height())));
|
||||
}
|
||||
}else if(uMsg == WM_SYSCOMMAND){
|
||||
if(wParam == SC_MINIMIZE){
|
||||
if(window()->transientParent()){
|
||||
window()->transientParent()->showMinimized();
|
||||
}else{
|
||||
window()->showMinimized();
|
||||
} else if (uMsg == WM_SYSCOMMAND) {
|
||||
if (wParam == SC_MINIMIZE) {
|
||||
if (window()->transientParent()) {
|
||||
auto _hwnd = reinterpret_cast<HWND>(window()->transientParent()->winId());
|
||||
::ShowWindow(_hwnd, 2);
|
||||
} else {
|
||||
auto _hwnd = reinterpret_cast<HWND>(window()->winId());
|
||||
::ShowWindow(_hwnd, 2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FluFrameless::_isMaximized(){
|
||||
bool FluFrameless::_isMaximized() {
|
||||
return window()->visibility() == QWindow::Maximized;
|
||||
}
|
||||
|
||||
bool FluFrameless::_isFullScreen(){
|
||||
bool FluFrameless::_isFullScreen() {
|
||||
return window()->visibility() == QWindow::FullScreen;
|
||||
}
|
||||
|
||||
void FluFrameless::_showSystemMenu(QPoint point){
|
||||
void FluFrameless::_showSystemMenu(QPoint point) {
|
||||
#ifdef Q_OS_WIN
|
||||
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
|
||||
DWORD style = ::GetWindowLongPtr(hwnd,GWL_STYLE);
|
||||
DWORD style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
|
||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_SYSMENU);
|
||||
const HMENU hMenu = ::GetSystemMenu(hwnd, FALSE);
|
||||
if(_isMaximized() || _isFullScreen()){
|
||||
::EnableMenuItem(hMenu,SC_MOVE,MFS_DISABLED);
|
||||
::EnableMenuItem(hMenu,SC_RESTORE,MFS_ENABLED);
|
||||
}else{
|
||||
::EnableMenuItem(hMenu,SC_MOVE,MFS_ENABLED);
|
||||
::EnableMenuItem(hMenu,SC_RESTORE,MFS_DISABLED);
|
||||
auto hMenu = ::GetSystemMenu(hwnd, FALSE);
|
||||
if (_isMaximized() || _isFullScreen()) {
|
||||
::EnableMenuItem(hMenu, SC_MOVE, MFS_DISABLED);
|
||||
::EnableMenuItem(hMenu, SC_RESTORE, MFS_ENABLED);
|
||||
} else {
|
||||
::EnableMenuItem(hMenu, SC_MOVE, MFS_ENABLED);
|
||||
::EnableMenuItem(hMenu, SC_RESTORE, MFS_DISABLED);
|
||||
}
|
||||
if(!_fixSize && !_isMaximized() && !_isFullScreen()){
|
||||
::EnableMenuItem(hMenu,SC_SIZE,MFS_ENABLED);
|
||||
::EnableMenuItem(hMenu,SC_MAXIMIZE,MFS_ENABLED);
|
||||
}else{
|
||||
::EnableMenuItem(hMenu,SC_SIZE,MFS_DISABLED);
|
||||
::EnableMenuItem(hMenu,SC_MAXIMIZE,MFS_DISABLED);
|
||||
if (!_fixSize && !_isMaximized() && !_isFullScreen()) {
|
||||
::EnableMenuItem(hMenu, SC_SIZE, MFS_ENABLED);
|
||||
::EnableMenuItem(hMenu, SC_MAXIMIZE, MFS_ENABLED);
|
||||
} else {
|
||||
::EnableMenuItem(hMenu, SC_SIZE, MFS_DISABLED);
|
||||
::EnableMenuItem(hMenu, SC_MAXIMIZE, MFS_DISABLED);
|
||||
}
|
||||
const int result = ::TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), point.x()*window()->devicePixelRatio(), point.y()*window()->devicePixelRatio(), 0, hwnd, nullptr);
|
||||
const int result = ::TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), qRound(point.x() * window()->devicePixelRatio()),
|
||||
qRound(point.y() * window()->devicePixelRatio()), 0, hwnd, nullptr);
|
||||
if (result != FALSE) {
|
||||
::PostMessageW(hwnd, WM_SYSCOMMAND, result, 0);
|
||||
}
|
||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style &~ WS_SYSMENU);
|
||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style & ~WS_SYSMENU);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FluFrameless::_containsCursorToItem(QQuickItem* item){
|
||||
if(!item || !item->isVisible()){
|
||||
return false;
|
||||
}
|
||||
auto point = QCursor::pos();
|
||||
auto rect = QRectF(item->mapToGlobal(QPoint(0,0)),item->size());
|
||||
if(point.x()>rect.x() && point.x()<(rect.x()+rect.width()) && point.y()>rect.y() && point.y()<(rect.y()+rect.height())){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FluFrameless::_hitAppBar(){
|
||||
foreach (auto item, _hitTestList) {
|
||||
if(_containsCursorToItem(item)){
|
||||
bool FluFrameless::_hitAppBar() {
|
||||
for (int i = 0; i <= _hitTestList.size() - 1; ++i) {
|
||||
auto item = _hitTestList.at(i);
|
||||
if (containsCursorToItem(item)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(_containsCursorToItem(_appbar)){
|
||||
if (containsCursorToItem(_appbar)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FluFrameless::_hitMaximizeButton(){
|
||||
if(_containsCursorToItem(_maximizeButton)){
|
||||
bool FluFrameless::_hitMaximizeButton() {
|
||||
if (containsCursorToItem(_maximizeButton)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FluFrameless::_setMaximizePressed(bool val){
|
||||
_maximizeButton->setProperty("down",val);
|
||||
void FluFrameless::_setMaximizePressed(bool val) {
|
||||
_maximizeButton->setProperty("down", val);
|
||||
}
|
||||
|
||||
void FluFrameless::_setMaximizeHovered(bool val){
|
||||
_maximizeButton->setProperty("hover",val);
|
||||
void FluFrameless::_setMaximizeHovered(bool val) {
|
||||
_maximizeButton->setProperty("hover", val);
|
||||
}
|
||||
|
||||
void FluFrameless::_updateCursor(int edges){
|
||||
void FluFrameless::_updateCursor(int edges) {
|
||||
switch (edges) {
|
||||
case 0:
|
||||
window()->setCursor(Qt::ArrowCursor);
|
||||
break;
|
||||
case Qt::LeftEdge:
|
||||
case Qt::RightEdge:
|
||||
window()->setCursor(Qt::SizeHorCursor);
|
||||
break;
|
||||
case Qt::TopEdge:
|
||||
case Qt::BottomEdge:
|
||||
window()->setCursor(Qt::SizeVerCursor);
|
||||
break;
|
||||
case Qt::LeftEdge | Qt::TopEdge:
|
||||
case Qt::RightEdge | Qt::BottomEdge:
|
||||
window()->setCursor(Qt::SizeFDiagCursor);
|
||||
break;
|
||||
case Qt::RightEdge | Qt::TopEdge:
|
||||
case Qt::LeftEdge | Qt::BottomEdge:
|
||||
window()->setCursor(Qt::SizeBDiagCursor);
|
||||
break;
|
||||
case 0:
|
||||
window()->setCursor(Qt::ArrowCursor);
|
||||
break;
|
||||
case Qt::LeftEdge:
|
||||
case Qt::RightEdge:
|
||||
window()->setCursor(Qt::SizeHorCursor);
|
||||
break;
|
||||
case Qt::TopEdge:
|
||||
case Qt::BottomEdge:
|
||||
window()->setCursor(Qt::SizeVerCursor);
|
||||
break;
|
||||
case Qt::LeftEdge | Qt::TopEdge:
|
||||
case Qt::RightEdge | Qt::BottomEdge:
|
||||
window()->setCursor(Qt::SizeFDiagCursor);
|
||||
break;
|
||||
case Qt::RightEdge | Qt::TopEdge:
|
||||
case Qt::LeftEdge | Qt::BottomEdge:
|
||||
window()->setCursor(Qt::SizeBDiagCursor);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FluFrameless::showFullScreen(){
|
||||
[[maybe_unused]] void FluFrameless::showFullScreen() {
|
||||
window()->showFullScreen();
|
||||
}
|
||||
|
||||
void FluFrameless::showMaximized(){
|
||||
void FluFrameless::showMaximized() {
|
||||
#ifdef Q_OS_WIN
|
||||
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
|
||||
::ShowWindow(hwnd,3);
|
||||
::ShowWindow(hwnd, 3);
|
||||
#else
|
||||
window()->showMaximized();
|
||||
window()->setVisibility(QQuickWindow::Maximized);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FluFrameless::showMinimized(){
|
||||
window()->showMinimized();
|
||||
[[maybe_unused]] void FluFrameless::showMinimized() {
|
||||
#ifdef Q_OS_WIN
|
||||
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
|
||||
::ShowWindow(hwnd, 2);
|
||||
#else
|
||||
window()->setVisibility(QQuickWindow::Minimized);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FluFrameless::showNormal(){
|
||||
window()->showNormal();
|
||||
void FluFrameless::showNormal() {
|
||||
window()->setVisibility(QQuickWindow::Windowed);
|
||||
}
|
||||
|
||||
void FluFrameless::setHitTestVisible(QQuickItem* val){
|
||||
if(!_hitTestList.contains(val)){
|
||||
void FluFrameless::setHitTestVisible(QQuickItem *val) {
|
||||
if (!_hitTestList.contains(val)) {
|
||||
_hitTestList.append(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FluFrameless::_setWindowTopmost(bool topmost){
|
||||
void FluFrameless::_setWindowTopmost(bool topmost) {
|
||||
#ifdef Q_OS_WIN
|
||||
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
|
||||
if(topmost){
|
||||
if (topmost) {
|
||||
::SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||
}else{
|
||||
} else {
|
||||
::SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||
}
|
||||
#else
|
||||
@ -409,7 +427,7 @@ void FluFrameless::_setWindowTopmost(bool topmost){
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FluFrameless::eventFilter(QObject *obj, QEvent *ev){
|
||||
bool FluFrameless::eventFilter(QObject *obj, QEvent *ev) {
|
||||
#ifndef Q_OS_WIN
|
||||
switch (ev->type()) {
|
||||
case QEvent::MouseButtonPress:
|
||||
|
@ -1,9 +1,9 @@
|
||||
#ifndef FLUFRAMELESS_H
|
||||
#define FLUFRAMELESS_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QQuickItem>
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QQmlProperty>
|
||||
#include "stdafx.h"
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
@ -15,47 +15,64 @@ using QT_ENTER_EVENT_TYPE = QEvent;
|
||||
#endif
|
||||
|
||||
|
||||
class FluFrameless : public QQuickItem,QAbstractNativeEventFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QQuickItem*,appbar)
|
||||
Q_PROPERTY_AUTO(bool,topmost)
|
||||
Q_PROPERTY_AUTO(QQuickItem*,maximizeButton)
|
||||
Q_PROPERTY_AUTO(QQuickItem*,minimizedButton)
|
||||
Q_PROPERTY_AUTO(QQuickItem*,closeButton)
|
||||
Q_PROPERTY_AUTO(bool,disabled)
|
||||
Q_PROPERTY_AUTO(bool,fixSize)
|
||||
class FluFrameless : public QQuickItem, QAbstractNativeEventFilter {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO_P(QQuickItem*, appbar)
|
||||
Q_PROPERTY_AUTO_P(QQuickItem*, maximizeButton)
|
||||
Q_PROPERTY_AUTO_P(QQuickItem*, minimizedButton)
|
||||
Q_PROPERTY_AUTO_P(QQuickItem*, closeButton)
|
||||
Q_PROPERTY_AUTO(bool, topmost)
|
||||
Q_PROPERTY_AUTO(bool, disabled)
|
||||
Q_PROPERTY_AUTO(bool, fixSize)
|
||||
QML_NAMED_ELEMENT(FluFrameless)
|
||||
public:
|
||||
explicit FluFrameless(QQuickItem* parent = nullptr);
|
||||
~FluFrameless();
|
||||
explicit FluFrameless(QQuickItem *parent = nullptr);
|
||||
|
||||
~FluFrameless() override;
|
||||
|
||||
void componentComplete() override;
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
|
||||
Q_INVOKABLE void showFullScreen();
|
||||
|
||||
[[maybe_unused]] bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void showFullScreen();
|
||||
|
||||
Q_INVOKABLE void showMaximized();
|
||||
Q_INVOKABLE void showMinimized();
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void showMinimized();
|
||||
|
||||
Q_INVOKABLE void showNormal();
|
||||
Q_INVOKABLE void setHitTestVisible(QQuickItem*);
|
||||
Q_INVOKABLE void onDestruction();
|
||||
|
||||
Q_INVOKABLE void setHitTestVisible(QQuickItem *);
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void onDestruction();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
private:
|
||||
bool _isFullScreen();
|
||||
|
||||
bool _isMaximized();
|
||||
|
||||
void _updateCursor(int edges);
|
||||
|
||||
void _setWindowTopmost(bool topmost);
|
||||
|
||||
void _showSystemMenu(QPoint point);
|
||||
bool _containsCursorToItem(QQuickItem* item);
|
||||
|
||||
bool _hitAppBar();
|
||||
|
||||
bool _hitMaximizeButton();
|
||||
|
||||
void _setMaximizePressed(bool val);
|
||||
|
||||
void _setMaximizeHovered(bool val);
|
||||
|
||||
private:
|
||||
qint64 _current;
|
||||
quint64 _current = 0;
|
||||
int _edges = 0;
|
||||
int _margins = 8;
|
||||
qint64 _clickTimer = 0;
|
||||
quint64 _clickTimer = 0;
|
||||
bool _isWindows11OrGreater = false;
|
||||
QList<QPointer<QQuickItem>> _hitTestList;
|
||||
};
|
||||
|
||||
#endif // FLUFRAMELESS_H
|
||||
|
@ -2,51 +2,47 @@
|
||||
|
||||
#include "qrcode/qrencode.h"
|
||||
|
||||
FluQrCodeItem::FluQrCodeItem(QQuickItem* parent):QQuickPaintedItem(parent){
|
||||
color(QColor(0,0,0,255));
|
||||
bgColor(QColor(255,255,255,255));
|
||||
size(100);
|
||||
FluQrCodeItem::FluQrCodeItem(QQuickItem *parent) : QQuickPaintedItem(parent) {
|
||||
_color = QColor(0, 0, 0, 255);
|
||||
_bgColor = QColor(255, 255, 255, 255);
|
||||
_size = 100;
|
||||
setWidth(_size);
|
||||
setHeight(_size);
|
||||
connect(this,&FluQrCodeItem::textChanged,this,[=]{update();});
|
||||
connect(this,&FluQrCodeItem::colorChanged,this,[=]{update();});
|
||||
connect(this,&FluQrCodeItem::bgColorChanged,this,[=]{update();});
|
||||
connect(this,&FluQrCodeItem::sizeChanged,this,[=]{
|
||||
connect(this, &FluQrCodeItem::textChanged, this, [=] { update(); });
|
||||
connect(this, &FluQrCodeItem::colorChanged, this, [=] { update(); });
|
||||
connect(this, &FluQrCodeItem::bgColorChanged, this, [=] { update(); });
|
||||
connect(this, &FluQrCodeItem::sizeChanged, this, [=] {
|
||||
setWidth(_size);
|
||||
setHeight(_size);
|
||||
update();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void FluQrCodeItem::paint(QPainter* painter){
|
||||
if(_text.isEmpty()){
|
||||
void FluQrCodeItem::paint(QPainter *painter) {
|
||||
if (_text.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if(_text.length()>1024){
|
||||
if (_text.length() > 1024) {
|
||||
return;
|
||||
}
|
||||
painter->save();
|
||||
QRcode *qrcode = QRcode_encodeString(_text.toUtf8().constData(), 2, QR_ECLEVEL_Q, QR_MODE_8, 1);
|
||||
qint32 w = width();
|
||||
qint32 h = height();
|
||||
auto w = qint32(width());
|
||||
auto h = qint32(height());
|
||||
qint32 qrcodeW = qrcode->width > 0 ? qrcode->width : 1;
|
||||
double scaleX = (double)w / (double)qrcodeW;
|
||||
double scaleY = (double)h / (double)qrcodeW;
|
||||
double scaleX = (double) w / (double) qrcodeW;
|
||||
double scaleY = (double) h / (double) qrcodeW;
|
||||
QImage image = QImage(w, h, QImage::Format_ARGB32);
|
||||
QPainter p(&image);
|
||||
p.setBrush(_bgColor);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawRect(0, 0, w, h);
|
||||
p.setBrush(_color);
|
||||
for (qint32 y = 0; y < qrcodeW; y++)
|
||||
{
|
||||
for (qint32 x = 0; x < qrcodeW; x++)
|
||||
{
|
||||
unsigned char b = qrcode->data[y*qrcodeW + x];
|
||||
if (b & 0x01)
|
||||
{
|
||||
QRectF r(x * scaleX,y * scaleY, scaleX, scaleY);
|
||||
for (qint32 y = 0; y < qrcodeW; y++) {
|
||||
for (qint32 x = 0; x < qrcodeW; x++) {
|
||||
unsigned char b = qrcode->data[y * qrcodeW + x];
|
||||
if (b & 0x01) {
|
||||
QRectF r(x * scaleX, y * scaleY, scaleX, scaleY);
|
||||
p.drawRects(&r, 1);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef FLUQRCODEITEM_H
|
||||
#define FLUQRCODEITEM_H
|
||||
#pragma once
|
||||
|
||||
#include <QQuickItem>
|
||||
#include <QQuickPaintedItem>
|
||||
@ -9,17 +8,16 @@
|
||||
/**
|
||||
* @brief The FluQrCodeItem class
|
||||
*/
|
||||
class FluQrCodeItem : public QQuickPaintedItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QString,text)
|
||||
Q_PROPERTY_AUTO(QColor,color)
|
||||
Q_PROPERTY_AUTO(QColor,bgColor)
|
||||
Q_PROPERTY_AUTO(int,size);
|
||||
class FluQrCodeItem : public QQuickPaintedItem {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY_AUTO(QString, text)
|
||||
Q_PROPERTY_AUTO(QColor, color)
|
||||
Q_PROPERTY_AUTO(QColor, bgColor)
|
||||
Q_PROPERTY_AUTO(int, size);
|
||||
QML_NAMED_ELEMENT(FluQrCodeItem)
|
||||
public:
|
||||
explicit FluQrCodeItem(QQuickItem *parent = nullptr);
|
||||
void paint(QPainter* painter) override;
|
||||
};
|
||||
|
||||
#endif // FLUQRCODEITEM_H
|
||||
void paint(QPainter *painter) override;
|
||||
};
|
@ -1,14 +1,14 @@
|
||||
#include "FluRectangle.h"
|
||||
#include <QPainterPath>
|
||||
|
||||
FluRectangle::FluRectangle(QQuickItem* parent) : QQuickPaintedItem(parent){
|
||||
color(QColor(255,255,255,255));
|
||||
radius({0,0,0,0});
|
||||
connect(this,&FluRectangle::colorChanged,this,[=]{update();});
|
||||
connect(this,&FluRectangle::radiusChanged,this,[=]{update();});
|
||||
FluRectangle::FluRectangle(QQuickItem *parent) : QQuickPaintedItem(parent) {
|
||||
color(QColor(255, 255, 255, 255));
|
||||
radius({0, 0, 0, 0});
|
||||
connect(this, &FluRectangle::colorChanged, this, [=] { update(); });
|
||||
connect(this, &FluRectangle::radiusChanged, this, [=] { update(); });
|
||||
}
|
||||
|
||||
void FluRectangle::paint(QPainter* painter){
|
||||
void FluRectangle::paint(QPainter *painter) {
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
QPainterPath path;
|
||||
@ -22,6 +22,6 @@ void FluRectangle::paint(QPainter* painter){
|
||||
path.arcTo(QRectF(QPointF(rect.bottomLeft() - QPointF(0, _radius[3] * 2)), QSize(_radius[3] * 2, _radius[3] * 2)), 180, 90);
|
||||
path.lineTo(rect.bottomRight() - QPointF(_radius[2], 0));
|
||||
path.arcTo(QRectF(QPointF(rect.bottomRight() - QPointF(_radius[2] * 2, _radius[2] * 2)), QSize(_radius[2] * 2, _radius[2] * 2)), 270, 90);
|
||||
painter->fillPath(path,_color);
|
||||
painter->fillPath(path, _color);
|
||||
painter->restore();
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef FLURECTANGLE_H
|
||||
#define FLURECTANGLE_H
|
||||
#pragma once
|
||||
|
||||
#include <QQuickItem>
|
||||
#include <QQuickPaintedItem>
|
||||
@ -9,15 +8,13 @@
|
||||
/**
|
||||
* @brief The FluRectangle class
|
||||
*/
|
||||
class FluRectangle : public QQuickPaintedItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QColor,color)
|
||||
Q_PROPERTY_AUTO(QList<int>,radius)
|
||||
class FluRectangle : public QQuickPaintedItem {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QColor, color)
|
||||
Q_PROPERTY_AUTO(QList<int>, radius)
|
||||
QML_NAMED_ELEMENT(FluRectangle)
|
||||
public:
|
||||
explicit FluRectangle(QQuickItem *parent = nullptr);
|
||||
void paint(QPainter* painter) override;
|
||||
};
|
||||
|
||||
#endif // FLURECTANGLE_H
|
||||
void paint(QPainter *painter) override;
|
||||
};
|
@ -2,74 +2,72 @@
|
||||
|
||||
#include <QJSValueList>
|
||||
|
||||
FluTableSortProxyModel::FluTableSortProxyModel(QSortFilterProxyModel *parent)
|
||||
: QSortFilterProxyModel {parent}
|
||||
{
|
||||
FluTableSortProxyModel::FluTableSortProxyModel(QSortFilterProxyModel *parent) : QSortFilterProxyModel{parent} {
|
||||
_model = nullptr;
|
||||
connect(this,&FluTableSortProxyModel::modelChanged,this,[=]{
|
||||
connect(this, &FluTableSortProxyModel::modelChanged, this, [=] {
|
||||
setSourceModel(this->model());
|
||||
});
|
||||
}
|
||||
|
||||
bool FluTableSortProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const{
|
||||
bool FluTableSortProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const {
|
||||
QJSValue filter = _filter;
|
||||
if(filter.isUndefined()){
|
||||
if (filter.isUndefined()) {
|
||||
return true;
|
||||
}
|
||||
QJSValueList data;
|
||||
data<<source_row;
|
||||
data << source_row;
|
||||
return filter.call(data).toBool();
|
||||
}
|
||||
|
||||
bool FluTableSortProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const{
|
||||
bool FluTableSortProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FluTableSortProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const{
|
||||
bool FluTableSortProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const {
|
||||
QJSValue comparator = _comparator;
|
||||
if(comparator.isUndefined()){
|
||||
if (comparator.isUndefined()) {
|
||||
return true;
|
||||
}
|
||||
QJSValueList data;
|
||||
data<<source_left.row();
|
||||
data<<source_right.row();
|
||||
data << source_left.row();
|
||||
data << source_right.row();
|
||||
bool flag = comparator.call(data).toBool();
|
||||
if(sortOrder()==Qt::AscendingOrder){
|
||||
if (sortOrder() == Qt::AscendingOrder) {
|
||||
return !flag;
|
||||
}else{
|
||||
} else {
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
|
||||
void FluTableSortProxyModel::setComparator(QJSValue comparator){
|
||||
[[maybe_unused]] void FluTableSortProxyModel::setComparator(const QJSValue &comparator) {
|
||||
int column = 0;
|
||||
if(comparator.isUndefined()){
|
||||
if (comparator.isUndefined()) {
|
||||
column = -1;
|
||||
}
|
||||
this->_comparator = comparator;
|
||||
if(sortOrder()==Qt::AscendingOrder){
|
||||
sort(column,Qt::DescendingOrder);
|
||||
}else{
|
||||
sort(column,Qt::AscendingOrder);
|
||||
if (sortOrder() == Qt::AscendingOrder) {
|
||||
sort(column, Qt::DescendingOrder);
|
||||
} else {
|
||||
sort(column, Qt::AscendingOrder);
|
||||
}
|
||||
}
|
||||
|
||||
void FluTableSortProxyModel::setFilter(QJSValue filter){
|
||||
[[maybe_unused]] void FluTableSortProxyModel::setFilter(const QJSValue &filter) {
|
||||
this->_filter = filter;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
QVariant FluTableSortProxyModel::getRow(int rowIndex){
|
||||
[[maybe_unused]] QVariant FluTableSortProxyModel::getRow(int rowIndex) {
|
||||
QVariant result;
|
||||
QMetaObject::invokeMethod(_model, "getRow",Q_RETURN_ARG(QVariant, result),Q_ARG(int, mapToSource(index(rowIndex,0)).row()));
|
||||
QMetaObject::invokeMethod(_model, "getRow", Q_RETURN_ARG(QVariant, result), Q_ARG(int, mapToSource(index(rowIndex, 0)).row()));
|
||||
return result;
|
||||
}
|
||||
|
||||
void FluTableSortProxyModel::setRow(int rowIndex,QVariant val){
|
||||
QMetaObject::invokeMethod(_model, "setRow",Q_ARG(int, mapToSource(index(rowIndex,0)).row()),Q_ARG(QVariant,val));
|
||||
[[maybe_unused]] void FluTableSortProxyModel::setRow(int rowIndex, const QVariant &val) {
|
||||
QMetaObject::invokeMethod(_model, "setRow", Q_ARG(int, mapToSource(index(rowIndex, 0)).row()), Q_ARG(QVariant, val));
|
||||
}
|
||||
|
||||
void FluTableSortProxyModel::removeRow(int rowIndex,int rows){
|
||||
QMetaObject::invokeMethod(_model, "removeRow",Q_ARG(int, mapToSource(index(rowIndex,0)).row()),Q_ARG(int,rows));
|
||||
[[maybe_unused]] void FluTableSortProxyModel::removeRow(int rowIndex, int rows) {
|
||||
QMetaObject::invokeMethod(_model, "removeRow", Q_ARG(int, mapToSource(index(rowIndex, 0)).row()), Q_ARG(int, rows));
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef FLUTABLESORTPROXYMODEL_H
|
||||
#define FLUTABLESORTPROXYMODEL_H
|
||||
#pragma once
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QAbstractTableModel>
|
||||
@ -7,24 +6,30 @@
|
||||
#include <QJSValue>
|
||||
#include "stdafx.h"
|
||||
|
||||
class FluTableSortProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QAbstractTableModel*,model)
|
||||
class FluTableSortProxyModel : public QSortFilterProxyModel {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO_P(QAbstractTableModel*, model)
|
||||
QML_NAMED_ELEMENT(FluTableSortProxyModel)
|
||||
public:
|
||||
explicit FluTableSortProxyModel(QSortFilterProxyModel *parent = nullptr);
|
||||
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
|
||||
bool filterAcceptsColumn(int sourceColumn, const QModelIndex &sourceParent) const override;
|
||||
|
||||
bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override;
|
||||
Q_INVOKABLE QVariant getRow(int rowIndex);
|
||||
Q_INVOKABLE void setRow(int rowIndex,QVariant val);
|
||||
Q_INVOKABLE void removeRow(int rowIndex,int rows);
|
||||
Q_INVOKABLE void setComparator(QJSValue comparator);
|
||||
Q_INVOKABLE void setFilter(QJSValue filter);
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE QVariant getRow(int rowIndex);
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void setRow(int rowIndex, const QVariant &val);
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void removeRow(int rowIndex, int rows);
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void setComparator(const QJSValue &comparator);
|
||||
|
||||
[[maybe_unused]] Q_INVOKABLE void setFilter(const QJSValue &filter);
|
||||
|
||||
private:
|
||||
QJSValue _filter;
|
||||
QJSValue _comparator;
|
||||
};
|
||||
|
||||
#endif // FLUTABLESORTPROXYMODEL_H
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "FluTextStyle.h"
|
||||
|
||||
FluTextStyle::FluTextStyle(QObject *parent):QObject{parent}{
|
||||
FluTextStyle::FluTextStyle(QObject *parent) : QObject{parent} {
|
||||
_family = QFont().defaultFamily();
|
||||
#ifdef Q_OS_WIN
|
||||
_family = "微软雅黑";
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef FLUTEXTSTYLE_H
|
||||
#define FLUTEXTSTYLE_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QtQml/qqml.h>
|
||||
@ -10,25 +9,25 @@
|
||||
/**
|
||||
* @brief The FluTextStyle class
|
||||
*/
|
||||
class FluTextStyle : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
class FluTextStyle : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_PROPERTY_AUTO(QString,family)
|
||||
Q_PROPERTY_AUTO(QFont,Caption);
|
||||
Q_PROPERTY_AUTO(QFont,Body);
|
||||
Q_PROPERTY_AUTO(QFont,BodyStrong);
|
||||
Q_PROPERTY_AUTO(QFont,Subtitle);
|
||||
Q_PROPERTY_AUTO(QFont,Title);
|
||||
Q_PROPERTY_AUTO(QFont,TitleLarge);
|
||||
Q_PROPERTY_AUTO(QFont,Display);
|
||||
Q_PROPERTY_AUTO(QString, family)
|
||||
Q_PROPERTY_AUTO(QFont, Caption);
|
||||
Q_PROPERTY_AUTO(QFont, Body);
|
||||
Q_PROPERTY_AUTO(QFont, BodyStrong);
|
||||
Q_PROPERTY_AUTO(QFont, Subtitle);
|
||||
Q_PROPERTY_AUTO(QFont, Title);
|
||||
Q_PROPERTY_AUTO(QFont, TitleLarge);
|
||||
Q_PROPERTY_AUTO(QFont, Display);
|
||||
QML_NAMED_ELEMENT(FluTextStyle)
|
||||
QML_SINGLETON
|
||||
|
||||
private:
|
||||
explicit FluTextStyle(QObject *parent = nullptr);
|
||||
public:
|
||||
SINGLETON(FluTextStyle)
|
||||
static FluTextStyle *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
|
||||
};
|
||||
|
||||
#endif // FLUTEXTSTYLE_H
|
||||
public:
|
||||
SINGLETON(FluTextStyle)
|
||||
|
||||
static FluTextStyle *create(QQmlEngine *, QJSEngine *) { return getInstance(); }
|
||||
};
|
||||
|
123
src/FluTheme.cpp
123
src/FluTheme.cpp
@ -2,43 +2,60 @@
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QPalette>
|
||||
#include <QImage>
|
||||
#include <QThreadPool>
|
||||
#include "Def.h"
|
||||
#include "FluColors.h"
|
||||
#include "FluTools.h"
|
||||
|
||||
FluTheme::FluTheme(QObject *parent):QObject{parent}{
|
||||
connect(this,&FluTheme::darkModeChanged,this,[=]{
|
||||
bool systemDark() {
|
||||
QPalette palette = QGuiApplication::palette();
|
||||
QColor color = palette.color(QPalette::Window).rgb();
|
||||
return color.red() * 0.2126 + color.green() * 0.7152 + color.blue() * 0.0722 <= 255.0f / 2;
|
||||
}
|
||||
|
||||
FluTheme::FluTheme(QObject *parent) : QObject{parent} {
|
||||
_accentColor = FluColors::getInstance()->Blue();
|
||||
_darkMode = FluThemeType::DarkMode::Light;
|
||||
_nativeText = false;
|
||||
_animationEnabled = true;
|
||||
_systemDark = systemDark();
|
||||
_desktopImagePath = "";
|
||||
_blurBehindWindowEnabled = false;
|
||||
QGuiApplication::instance()->installEventFilter(this);
|
||||
refreshColors();
|
||||
connect(this, &FluTheme::darkModeChanged, this, [=] {
|
||||
Q_EMIT darkChanged();
|
||||
});
|
||||
connect(this,&FluTheme::darkChanged,this,[=]{refreshColors();});
|
||||
connect(this,&FluTheme::accentColorChanged,this,[=]{refreshColors();});
|
||||
accentColor(FluColors::getInstance()->Blue());
|
||||
darkMode(FluThemeType::DarkMode::Light);
|
||||
nativeText(false);
|
||||
animationEnabled(true);
|
||||
_systemDark = systemDark();
|
||||
qApp->installEventFilter(this);
|
||||
connect(this, &FluTheme::darkChanged, this, [=] { refreshColors(); });
|
||||
connect(this, &FluTheme::accentColorChanged, this, [=] { refreshColors(); });
|
||||
connect(&_watcher, &QFileSystemWatcher::fileChanged, this, [=](const QString &path) {
|
||||
Q_EMIT desktopImagePathChanged();
|
||||
});
|
||||
connect(this, &FluTheme::blurBehindWindowEnabledChanged, this, [=] { checkUpdateDesktopImage(); });
|
||||
startTimer(1000);
|
||||
}
|
||||
|
||||
void FluTheme::refreshColors(){
|
||||
void FluTheme::refreshColors() {
|
||||
auto isDark = dark();
|
||||
primaryColor(isDark ? _accentColor->lighter() : _accentColor->dark());
|
||||
backgroundColor(isDark ? QColor(0,0,0,255) : QColor(255,255,255,255));
|
||||
dividerColor(isDark ? QColor(80,80,80,255) : QColor(210,210,210,255));
|
||||
windowBackgroundColor(isDark ? QColor(32,32,32,255) : QColor(237,237,237,255));
|
||||
windowActiveBackgroundColor(isDark ? QColor(26,26,26,255) : QColor(243,243,243,255));
|
||||
fontPrimaryColor(isDark ? QColor(248,248,248,255) : QColor(7,7,7,255));
|
||||
fontSecondaryColor(isDark ? QColor(222,222,222,255) : QColor(102,102,102,255));
|
||||
fontTertiaryColor(isDark ? QColor(200,200,200,255) : QColor(153,153,153,255));
|
||||
itemNormalColor(isDark ? QColor(255,255,255,0) : QColor(0,0,0,0));
|
||||
itemHoverColor(isDark ? QColor(255,255,255,255*0.06) : QColor(0,0,0,255*0.03));
|
||||
itemPressColor(isDark ? QColor(255,255,255,255*0.09) : QColor(0,0,0,255*0.06));
|
||||
itemCheckColor(isDark ? QColor(255,255,255,255*0.12) : QColor(0,0,0,255*0.09));
|
||||
backgroundColor(isDark ? QColor(0, 0, 0, 255) : QColor(255, 255, 255, 255));
|
||||
dividerColor(isDark ? QColor(80, 80, 80, 255) : QColor(210, 210, 210, 255));
|
||||
windowBackgroundColor(isDark ? QColor(32, 32, 32, 255) : QColor(237, 237, 237, 255));
|
||||
windowActiveBackgroundColor(isDark ? QColor(26, 26, 26, 255) : QColor(243, 243, 243, 255));
|
||||
fontPrimaryColor(isDark ? QColor(248, 248, 248, 255) : QColor(7, 7, 7, 255));
|
||||
fontSecondaryColor(isDark ? QColor(222, 222, 222, 255) : QColor(102, 102, 102, 255));
|
||||
fontTertiaryColor(isDark ? QColor(200, 200, 200, 255) : QColor(153, 153, 153, 255));
|
||||
itemNormalColor(isDark ? QColor(255, 255, 255, 0) : QColor(0, 0, 0, 0));
|
||||
frameColor(isDark ? QColor(56, 56, 56, qRound(255 * 0.8)) : QColor(243, 243, 243, qRound(255 * 0.8)));
|
||||
frameActiveColor(isDark ? QColor(48, 48, 48, qRound(255 * 0.8)) : QColor(255, 255, 255, qRound(255 * 0.8)));
|
||||
itemHoverColor(isDark ? QColor(255, 255, 255, qRound(255 * 0.06)) : QColor(0, 0, 0, qRound(255 * 0.03)));
|
||||
itemPressColor(isDark ? QColor(255, 255, 255, qRound(255 * 0.09)) : QColor(0, 0, 0, qRound(255 * 0.06)));
|
||||
itemCheckColor(isDark ? QColor(255, 255, 255, qRound(255 * 0.12)) : QColor(0, 0, 0, qRound(255 * 0.09)));
|
||||
}
|
||||
|
||||
bool FluTheme::eventFilter(QObject *obj, QEvent *event){
|
||||
Q_UNUSED(obj);
|
||||
if (event->type() == QEvent::ApplicationPaletteChange || event->type() == QEvent::ThemeChange)
|
||||
{
|
||||
bool FluTheme::eventFilter(QObject *, QEvent *event) {
|
||||
if (event->type() == QEvent::ApplicationPaletteChange || event->type() == QEvent::ThemeChange) {
|
||||
_systemDark = systemDark();
|
||||
Q_EMIT darkChanged();
|
||||
event->accept();
|
||||
@ -47,36 +64,34 @@ bool FluTheme::eventFilter(QObject *obj, QEvent *event){
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonArray FluTheme::awesomeList(const QString& keyword){
|
||||
QJsonArray arr;
|
||||
QMetaEnum enumType = Fluent_Awesome::staticMetaObject.enumerator(Fluent_Awesome::staticMetaObject.indexOfEnumerator("Fluent_AwesomeType"));
|
||||
for(int i=0; i < enumType.keyCount(); ++i){
|
||||
QString name = enumType.key(i);
|
||||
int icon = enumType.value(i);
|
||||
if(keyword.isEmpty() || name.contains(keyword)){
|
||||
QJsonObject obj;
|
||||
obj.insert("name",name);
|
||||
obj.insert("icon",icon);
|
||||
arr.append(obj);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
bool FluTheme::systemDark(){
|
||||
QPalette palette = qApp->palette();
|
||||
QColor color = palette.color(QPalette::Window).rgb();
|
||||
return !(color.red() * 0.2126 + color.green() * 0.7152 + color.blue() * 0.0722 > 255 / 2);
|
||||
}
|
||||
|
||||
bool FluTheme::dark(){
|
||||
if(_darkMode == FluThemeType::DarkMode::Dark){
|
||||
bool FluTheme::dark() const {
|
||||
if (_darkMode == FluThemeType::DarkMode::Dark) {
|
||||
return true;
|
||||
}else if(_darkMode == FluThemeType::DarkMode::Light){
|
||||
return false;
|
||||
}else if(_darkMode == FluThemeType::DarkMode::System){
|
||||
} else if (_darkMode == FluThemeType::DarkMode::System) {
|
||||
return _systemDark;
|
||||
}else{
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void FluTheme::checkUpdateDesktopImage() {
|
||||
if (!_blurBehindWindowEnabled) {
|
||||
return;
|
||||
}
|
||||
QThreadPool::globalInstance()->start([=]() {
|
||||
_mutex.lock();
|
||||
auto path = FluTools::getInstance()->getWallpaperFilePath();
|
||||
if (_desktopImagePath != path) {
|
||||
if (!_desktopImagePath.isEmpty()) {
|
||||
_watcher.removePath(_desktopImagePath);
|
||||
}
|
||||
desktopImagePath(path);
|
||||
_watcher.addPath(path);
|
||||
}
|
||||
_mutex.unlock();
|
||||
});
|
||||
}
|
||||
|
||||
void FluTheme::timerEvent(QTimerEvent *event) {
|
||||
checkUpdateDesktopImage();
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
#ifndef FLUTHEME_H
|
||||
#define FLUTHEME_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QtQml/qqml.h>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QColor>
|
||||
#include <QTimer>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QMutex>
|
||||
#include "FluAccentColor.h"
|
||||
#include "stdafx.h"
|
||||
#include "singleton.h"
|
||||
@ -13,41 +15,56 @@
|
||||
/**
|
||||
* @brief The FluTheme class
|
||||
*/
|
||||
class FluTheme : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
class FluTheme : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool dark READ dark NOTIFY darkChanged)
|
||||
Q_PROPERTY_AUTO(FluAccentColor*,accentColor);
|
||||
Q_PROPERTY_AUTO(QColor,primaryColor);
|
||||
Q_PROPERTY_AUTO(QColor,backgroundColor);
|
||||
Q_PROPERTY_AUTO(QColor,dividerColor);
|
||||
Q_PROPERTY_AUTO(QColor,windowBackgroundColor);
|
||||
Q_PROPERTY_AUTO(QColor,windowActiveBackgroundColor);
|
||||
Q_PROPERTY_AUTO(QColor,fontPrimaryColor);
|
||||
Q_PROPERTY_AUTO(QColor,fontSecondaryColor);
|
||||
Q_PROPERTY_AUTO(QColor,fontTertiaryColor);
|
||||
Q_PROPERTY_AUTO(QColor,itemNormalColor);
|
||||
Q_PROPERTY_AUTO(QColor,itemHoverColor);
|
||||
Q_PROPERTY_AUTO(QColor,itemPressColor);
|
||||
Q_PROPERTY_AUTO(QColor,itemCheckColor);
|
||||
Q_PROPERTY_AUTO(int,darkMode);
|
||||
Q_PROPERTY_AUTO(bool,nativeText);
|
||||
Q_PROPERTY_AUTO(bool,animationEnabled);
|
||||
Q_PROPERTY_AUTO_P(FluAccentColor*, accentColor);
|
||||
Q_PROPERTY_AUTO(QColor, primaryColor);
|
||||
Q_PROPERTY_AUTO(QColor, backgroundColor);
|
||||
Q_PROPERTY_AUTO(QColor, dividerColor);
|
||||
Q_PROPERTY_AUTO(QColor, windowBackgroundColor);
|
||||
Q_PROPERTY_AUTO(QColor, windowActiveBackgroundColor);
|
||||
Q_PROPERTY_AUTO(QColor, fontPrimaryColor);
|
||||
Q_PROPERTY_AUTO(QColor, fontSecondaryColor);
|
||||
Q_PROPERTY_AUTO(QColor, fontTertiaryColor);
|
||||
Q_PROPERTY_AUTO(QColor, itemNormalColor);
|
||||
Q_PROPERTY_AUTO(QColor, frameColor);
|
||||
Q_PROPERTY_AUTO(QColor, frameActiveColor);
|
||||
Q_PROPERTY_AUTO(QColor, itemHoverColor);
|
||||
Q_PROPERTY_AUTO(QColor, itemPressColor);
|
||||
Q_PROPERTY_AUTO(QColor, itemCheckColor);
|
||||
Q_PROPERTY_AUTO(QString, desktopImagePath);
|
||||
Q_PROPERTY_AUTO(int, darkMode);
|
||||
Q_PROPERTY_AUTO(bool, nativeText);
|
||||
Q_PROPERTY_AUTO(bool, animationEnabled);
|
||||
Q_PROPERTY_AUTO(bool, blurBehindWindowEnabled);
|
||||
QML_NAMED_ELEMENT(FluTheme)
|
||||
QML_SINGLETON
|
||||
|
||||
private:
|
||||
explicit FluTheme(QObject *parent = nullptr);
|
||||
bool eventFilter(QObject *obj, QEvent *event);
|
||||
bool systemDark();
|
||||
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
void refreshColors();
|
||||
|
||||
protected:
|
||||
|
||||
void timerEvent(QTimerEvent *event) override;
|
||||
|
||||
void checkUpdateDesktopImage();
|
||||
|
||||
public:
|
||||
SINGLETON(FluTheme)
|
||||
Q_INVOKABLE QJsonArray awesomeList(const QString& keyword = "");
|
||||
SINGLETON(FluTheme)
|
||||
|
||||
Q_SIGNAL void darkChanged();
|
||||
static FluTheme *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
|
||||
bool dark();
|
||||
|
||||
static FluTheme *create(QQmlEngine *, QJSEngine *) { return getInstance(); }
|
||||
|
||||
bool dark() const;
|
||||
|
||||
private:
|
||||
bool _systemDark;
|
||||
};
|
||||
|
||||
#endif // FLUTHEME_H
|
||||
QFileSystemWatcher _watcher;
|
||||
QMutex _mutex;
|
||||
};
|
180
src/FluTools.cpp
180
src/FluTools.cpp
@ -16,19 +16,27 @@
|
||||
#include <QDateTime>
|
||||
#include <QSettings>
|
||||
|
||||
FluTools::FluTools(QObject *parent):QObject{parent}{
|
||||
#ifdef Q_OS_WIN
|
||||
#pragma comment (lib, "user32.lib")
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
#endif
|
||||
|
||||
FluTools::FluTools(QObject *parent) : QObject{parent} {
|
||||
|
||||
}
|
||||
|
||||
void FluTools::clipText(const QString& text){
|
||||
void FluTools::clipText(const QString &text) {
|
||||
QGuiApplication::clipboard()->setText(text);
|
||||
}
|
||||
|
||||
QString FluTools::uuid(){
|
||||
QString FluTools::uuid() {
|
||||
return QUuid::createUuid().toString().remove('-').remove('{').remove('}');
|
||||
}
|
||||
|
||||
QString FluTools::readFile(const QString &fileName){
|
||||
QString FluTools::readFile(const QString &fileName) {
|
||||
QString content;
|
||||
QFile file(fileName);
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
@ -38,7 +46,7 @@ QString FluTools::readFile(const QString &fileName){
|
||||
return content;
|
||||
}
|
||||
|
||||
bool FluTools::isMacos(){
|
||||
bool FluTools::isMacos() {
|
||||
#if defined(Q_OS_MACOS)
|
||||
return true;
|
||||
#else
|
||||
@ -46,7 +54,7 @@ bool FluTools::isMacos(){
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FluTools::isLinux(){
|
||||
bool FluTools::isLinux() {
|
||||
#if defined(Q_OS_LINUX)
|
||||
return true;
|
||||
#else
|
||||
@ -54,7 +62,7 @@ bool FluTools::isLinux(){
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FluTools::isWin(){
|
||||
bool FluTools::isWin() {
|
||||
#if defined(Q_OS_WIN)
|
||||
return true;
|
||||
#else
|
||||
@ -62,95 +70,94 @@ bool FluTools::isWin(){
|
||||
#endif
|
||||
}
|
||||
|
||||
int FluTools::qtMajor(){
|
||||
int FluTools::qtMajor() {
|
||||
const QString qtVersion = QString::fromLatin1(qVersion());
|
||||
const QStringList versionParts = qtVersion.split('.');
|
||||
return versionParts[0].toInt();
|
||||
}
|
||||
|
||||
int FluTools::qtMinor(){
|
||||
int FluTools::qtMinor() {
|
||||
const QString qtVersion = QString::fromLatin1(qVersion());
|
||||
const QStringList versionParts = qtVersion.split('.');
|
||||
return versionParts[1].toInt();
|
||||
}
|
||||
|
||||
void FluTools::setQuitOnLastWindowClosed(bool val){
|
||||
qApp->setQuitOnLastWindowClosed(val);
|
||||
void FluTools::setQuitOnLastWindowClosed(bool val) {
|
||||
QGuiApplication::setQuitOnLastWindowClosed(val);
|
||||
}
|
||||
|
||||
void FluTools::setOverrideCursor(Qt::CursorShape shape){
|
||||
qApp->setOverrideCursor(QCursor(shape));
|
||||
void FluTools::setOverrideCursor(Qt::CursorShape shape) {
|
||||
QGuiApplication::setOverrideCursor(QCursor(shape));
|
||||
}
|
||||
|
||||
void FluTools::restoreOverrideCursor(){
|
||||
qApp->restoreOverrideCursor();
|
||||
void FluTools::restoreOverrideCursor() {
|
||||
QGuiApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
void FluTools::deleteLater(QObject *p){
|
||||
if(p){
|
||||
void FluTools::deleteLater(QObject *p) {
|
||||
if (p) {
|
||||
p->deleteLater();
|
||||
p = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QString FluTools::toLocalPath(const QUrl& url){
|
||||
QString FluTools::toLocalPath(const QUrl &url) {
|
||||
return url.toLocalFile();
|
||||
}
|
||||
|
||||
QString FluTools::getFileNameByUrl(const QUrl& url){
|
||||
QString FluTools::getFileNameByUrl(const QUrl &url) {
|
||||
return QFileInfo(url.toLocalFile()).fileName();
|
||||
}
|
||||
|
||||
QString FluTools::html2PlantText(const QString& html){
|
||||
QString FluTools::html2PlantText(const QString &html) {
|
||||
QTextDocument textDocument;
|
||||
textDocument.setHtml(html);
|
||||
return textDocument.toPlainText();
|
||||
}
|
||||
|
||||
QRect FluTools::getVirtualGeometry(){
|
||||
return qApp->primaryScreen()->virtualGeometry();
|
||||
QRect FluTools::getVirtualGeometry() {
|
||||
return QGuiApplication::primaryScreen()->virtualGeometry();
|
||||
}
|
||||
|
||||
QString FluTools::getApplicationDirPath(){
|
||||
return qApp->applicationDirPath();
|
||||
QString FluTools::getApplicationDirPath() {
|
||||
return QGuiApplication::applicationDirPath();
|
||||
}
|
||||
|
||||
QUrl FluTools::getUrlByFilePath(const QString& path){
|
||||
QUrl FluTools::getUrlByFilePath(const QString &path) {
|
||||
return QUrl::fromLocalFile(path);
|
||||
}
|
||||
|
||||
QColor FluTools::withOpacity(const QColor& color,qreal opacity){
|
||||
QColor FluTools::withOpacity(const QColor &color, qreal opacity) {
|
||||
int alpha = qRound(opacity * 255) & 0xff;
|
||||
return QColor::fromRgba((alpha << 24) | (color.rgba() & 0xffffff));
|
||||
}
|
||||
|
||||
QString FluTools::md5(QString text){
|
||||
QString FluTools::md5(const QString &text) {
|
||||
return QCryptographicHash::hash(text.toUtf8(), QCryptographicHash::Md5).toHex();
|
||||
}
|
||||
|
||||
QString FluTools::toBase64(QString text){
|
||||
QString FluTools::toBase64(const QString &text) {
|
||||
return text.toUtf8().toBase64();
|
||||
}
|
||||
|
||||
QString FluTools::fromBase64(QString text){
|
||||
QString FluTools::fromBase64(const QString &text) {
|
||||
return QByteArray::fromBase64(text.toUtf8());
|
||||
}
|
||||
|
||||
bool FluTools::removeDir(QString dirPath){
|
||||
bool FluTools::removeDir(const QString &dirPath) {
|
||||
QDir qDir(dirPath);
|
||||
return qDir.removeRecursively();
|
||||
}
|
||||
|
||||
bool FluTools::removeFile(QString filePath){
|
||||
bool FluTools::removeFile(const QString &filePath) {
|
||||
QFile file(filePath);
|
||||
return file.remove();
|
||||
}
|
||||
|
||||
QString FluTools::sha256(QString text){
|
||||
QString FluTools::sha256(const QString &text) {
|
||||
return QCryptographicHash::hash(text.toUtf8(), QCryptographicHash::Sha256).toHex();
|
||||
}
|
||||
|
||||
void FluTools::showFileInFolder(QString path){
|
||||
void FluTools::showFileInFolder(const QString &path) {
|
||||
#if defined(Q_OS_WIN)
|
||||
QProcess::startDetached("explorer.exe", {"/select,", QDir::toNativeSeparators(path)});
|
||||
#endif
|
||||
@ -166,29 +173,29 @@ void FluTools::showFileInFolder(QString path){
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FluTools::isSoftware(){
|
||||
bool FluTools::isSoftware() {
|
||||
return QQuickWindow::sceneGraphBackend() == "software";
|
||||
}
|
||||
|
||||
QPoint FluTools::cursorPos(){
|
||||
QPoint FluTools::cursorPos() {
|
||||
return QCursor::pos();
|
||||
}
|
||||
|
||||
qint64 FluTools::currentTimestamp(){
|
||||
qint64 FluTools::currentTimestamp() {
|
||||
return QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
||||
|
||||
QIcon FluTools::windowIcon(){
|
||||
QIcon FluTools::windowIcon() {
|
||||
return QGuiApplication::windowIcon();
|
||||
}
|
||||
|
||||
int FluTools::cursorScreenIndex(){
|
||||
int FluTools::cursorScreenIndex() {
|
||||
int screenIndex = 0;
|
||||
int screenCount = qApp->screens().count();
|
||||
int screenCount = QGuiApplication::screens().count();
|
||||
if (screenCount > 1) {
|
||||
QPoint pos = QCursor::pos();
|
||||
for (int i = 0; i < screenCount; ++i) {
|
||||
if (qApp->screens().at(i)->geometry().contains(pos)) {
|
||||
for (int i = 0; i <= screenCount - 1; ++i) {
|
||||
if (QGuiApplication::screens().at(i)->geometry().contains(pos)) {
|
||||
screenIndex = i;
|
||||
break;
|
||||
}
|
||||
@ -197,9 +204,9 @@ int FluTools::cursorScreenIndex(){
|
||||
return screenIndex;
|
||||
}
|
||||
|
||||
int FluTools::windowBuildNumber(){
|
||||
int FluTools::windowBuildNumber() {
|
||||
#if defined(Q_OS_WIN)
|
||||
QSettings regKey {QString::fromUtf8("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), QSettings::NativeFormat};
|
||||
QSettings regKey{QString::fromUtf8(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion)"), QSettings::NativeFormat};
|
||||
if (regKey.contains(QString::fromUtf8("CurrentBuildNumber"))) {
|
||||
auto buildNumber = regKey.value(QString::fromUtf8("CurrentBuildNumber")).toInt();
|
||||
return buildNumber;
|
||||
@ -208,40 +215,103 @@ int FluTools::windowBuildNumber(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool FluTools::isWindows11OrGreater(){
|
||||
bool FluTools::isWindows11OrGreater() {
|
||||
static QVariant var;
|
||||
if(var.isNull()){
|
||||
if (var.isNull()) {
|
||||
#if defined(Q_OS_WIN)
|
||||
auto buildNumber = windowBuildNumber();
|
||||
if(buildNumber>=22000){
|
||||
if (buildNumber >= 22000) {
|
||||
var = QVariant::fromValue(true);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
var = QVariant::fromValue(false);
|
||||
return false;
|
||||
}else{
|
||||
return false;
|
||||
} else {
|
||||
return var.toBool();
|
||||
}
|
||||
}
|
||||
|
||||
bool FluTools::isWindows10OrGreater(){
|
||||
bool FluTools::isWindows10OrGreater() {
|
||||
static QVariant var;
|
||||
if(var.isNull()){
|
||||
if (var.isNull()) {
|
||||
#if defined(Q_OS_WIN)
|
||||
auto buildNumber = windowBuildNumber();
|
||||
if(buildNumber>=10240){
|
||||
if (buildNumber >= 10240) {
|
||||
var = QVariant::fromValue(true);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
var = QVariant::fromValue(false);
|
||||
return false;
|
||||
}else{
|
||||
return false;
|
||||
} else {
|
||||
return var.toBool();
|
||||
}
|
||||
}
|
||||
|
||||
QRect FluTools::desktopAvailableGeometry(QQuickWindow* window){
|
||||
QRect FluTools::desktopAvailableGeometry(QQuickWindow *window) {
|
||||
return window->screen()->availableGeometry();
|
||||
}
|
||||
|
||||
QString FluTools::getWallpaperFilePath() {
|
||||
#if defined(Q_OS_WIN)
|
||||
wchar_t path[MAX_PATH] = {};
|
||||
if (::SystemParametersInfoW(SPI_GETDESKWALLPAPER, MAX_PATH, path, FALSE) == FALSE) {
|
||||
return {};
|
||||
}
|
||||
return QString::fromWCharArray(path);
|
||||
#elif defined(Q_OS_LINUX)
|
||||
auto type = QSysInfo::productType();
|
||||
if (type == "uos") {
|
||||
QProcess process;
|
||||
QStringList args;
|
||||
args << "--session";
|
||||
args << "--type=method_call";
|
||||
args << "--print-reply";
|
||||
args << "--dest=com.deepin.wm";
|
||||
args << "/com/deepin/wm";
|
||||
args << "com.deepin.wm.GetCurrentWorkspaceBackgroundForMonitor";
|
||||
args << QString("string:'%1'").arg(currentTimestamp());
|
||||
process.start("dbus-send", args);
|
||||
process.waitForFinished();
|
||||
QByteArray result = process.readAllStandardOutput().trimmed();
|
||||
int startIndex = result.indexOf("file:///");
|
||||
if (startIndex != -1) {
|
||||
auto path = result.mid(startIndex + 7, result.length() - startIndex - 8);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
#elif defined(Q_OS_MACOS)
|
||||
QProcess process;
|
||||
QStringList args;
|
||||
args << "-e";
|
||||
args << R"(tell application "Finder" to get POSIX path of (desktop picture as alias))";
|
||||
process.start("osascript", args);
|
||||
process.waitForFinished();
|
||||
QByteArray result = process.readAllStandardOutput().trimmed();
|
||||
if(result.isEmpty()){
|
||||
return "/System/Library/CoreServices/DefaultDesktop.heic";
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
QColor FluTools::imageMainColor(const QImage &image, double bright) {
|
||||
int step = 20;
|
||||
int t = 0;
|
||||
int r = 0, g = 0, b = 0;
|
||||
for (int i = 0; i < image.width(); i += step) {
|
||||
for (int j = 0; j < image.height(); j += step) {
|
||||
if (image.valid(i, j)) {
|
||||
t++;
|
||||
QColor c = image.pixel(i, j);
|
||||
r += c.red();
|
||||
b += c.blue();
|
||||
g += c.green();
|
||||
}
|
||||
}
|
||||
}
|
||||
return QColor(int(bright * r / t) > 255 ? 255 : int(bright * r / t), int(bright * g / t) > 255 ? 255 : int(bright * g / t), int(bright * b / t) > 255 ? 255 : int(bright * b / t));
|
||||
}
|
||||
|
128
src/FluTools.h
128
src/FluTools.h
@ -1,5 +1,4 @@
|
||||
#ifndef FLUTOOLS_H
|
||||
#define FLUTOOLS_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QFile>
|
||||
@ -11,51 +10,90 @@
|
||||
/**
|
||||
* @brief The FluTools class
|
||||
*/
|
||||
class FluTools : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
class FluTools : public QObject {
|
||||
Q_OBJECT
|
||||
QML_NAMED_ELEMENT(FluTools)
|
||||
QML_SINGLETON
|
||||
|
||||
private:
|
||||
explicit FluTools(QObject *parent = nullptr);
|
||||
public:
|
||||
SINGLETON(FluTools)
|
||||
static FluTools *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
|
||||
Q_INVOKABLE int qtMajor();
|
||||
Q_INVOKABLE int qtMinor();
|
||||
Q_INVOKABLE bool isMacos();
|
||||
Q_INVOKABLE bool isLinux();
|
||||
Q_INVOKABLE bool isWin();
|
||||
Q_INVOKABLE void clipText(const QString& text);
|
||||
Q_INVOKABLE QString uuid();
|
||||
Q_INVOKABLE QString readFile(const QString& fileName);
|
||||
Q_INVOKABLE void setQuitOnLastWindowClosed(bool val);
|
||||
Q_INVOKABLE void setOverrideCursor(Qt::CursorShape shape);
|
||||
Q_INVOKABLE void restoreOverrideCursor();
|
||||
Q_INVOKABLE QString html2PlantText(const QString& html);
|
||||
Q_INVOKABLE QString toLocalPath(const QUrl& url);
|
||||
Q_INVOKABLE void deleteLater(QObject *p);
|
||||
Q_INVOKABLE QString getFileNameByUrl(const QUrl& url);
|
||||
Q_INVOKABLE QRect getVirtualGeometry();
|
||||
Q_INVOKABLE QString getApplicationDirPath();
|
||||
Q_INVOKABLE QUrl getUrlByFilePath(const QString& path);
|
||||
Q_INVOKABLE QColor withOpacity(const QColor&,qreal alpha);
|
||||
Q_INVOKABLE QString md5(QString text);
|
||||
Q_INVOKABLE QString sha256(QString text);
|
||||
Q_INVOKABLE QString toBase64(QString text);
|
||||
Q_INVOKABLE QString fromBase64(QString text);
|
||||
Q_INVOKABLE bool removeDir(QString dirPath);
|
||||
Q_INVOKABLE bool removeFile(QString filePath);
|
||||
Q_INVOKABLE void showFileInFolder(QString path);
|
||||
Q_INVOKABLE bool isSoftware();
|
||||
Q_INVOKABLE qint64 currentTimestamp();
|
||||
Q_INVOKABLE QPoint cursorPos();
|
||||
Q_INVOKABLE QIcon windowIcon();
|
||||
Q_INVOKABLE int cursorScreenIndex();
|
||||
Q_INVOKABLE int windowBuildNumber();
|
||||
Q_INVOKABLE bool isWindows11OrGreater();
|
||||
Q_INVOKABLE bool isWindows10OrGreater();
|
||||
Q_INVOKABLE QRect desktopAvailableGeometry(QQuickWindow* window);
|
||||
};
|
||||
|
||||
#endif // FLUTOOLS_H
|
||||
public:
|
||||
SINGLETON(FluTools)
|
||||
|
||||
static FluTools *create(QQmlEngine *, QJSEngine *) { return getInstance(); }
|
||||
|
||||
Q_INVOKABLE int qtMajor();
|
||||
|
||||
Q_INVOKABLE int qtMinor();
|
||||
|
||||
Q_INVOKABLE bool isMacos();
|
||||
|
||||
Q_INVOKABLE bool isLinux();
|
||||
|
||||
Q_INVOKABLE bool isWin();
|
||||
|
||||
Q_INVOKABLE void clipText(const QString &text);
|
||||
|
||||
Q_INVOKABLE QString uuid();
|
||||
|
||||
Q_INVOKABLE QString readFile(const QString &fileName);
|
||||
|
||||
Q_INVOKABLE void setQuitOnLastWindowClosed(bool val);
|
||||
|
||||
Q_INVOKABLE void setOverrideCursor(Qt::CursorShape shape);
|
||||
|
||||
Q_INVOKABLE void restoreOverrideCursor();
|
||||
|
||||
Q_INVOKABLE QString html2PlantText(const QString &html);
|
||||
|
||||
Q_INVOKABLE QString toLocalPath(const QUrl &url);
|
||||
|
||||
Q_INVOKABLE void deleteLater(QObject *p);
|
||||
|
||||
Q_INVOKABLE QString getFileNameByUrl(const QUrl &url);
|
||||
|
||||
Q_INVOKABLE QRect getVirtualGeometry();
|
||||
|
||||
Q_INVOKABLE QString getApplicationDirPath();
|
||||
|
||||
Q_INVOKABLE QUrl getUrlByFilePath(const QString &path);
|
||||
|
||||
Q_INVOKABLE QColor withOpacity(const QColor &, qreal alpha);
|
||||
|
||||
Q_INVOKABLE QString md5(const QString &text);
|
||||
|
||||
Q_INVOKABLE QString sha256(const QString &text);
|
||||
|
||||
Q_INVOKABLE QString toBase64(const QString &text);
|
||||
|
||||
Q_INVOKABLE QString fromBase64(const QString &text);
|
||||
|
||||
Q_INVOKABLE bool removeDir(const QString &dirPath);
|
||||
|
||||
Q_INVOKABLE bool removeFile(const QString &filePath);
|
||||
|
||||
Q_INVOKABLE void showFileInFolder(const QString &path);
|
||||
|
||||
Q_INVOKABLE bool isSoftware();
|
||||
|
||||
Q_INVOKABLE qint64 currentTimestamp();
|
||||
|
||||
Q_INVOKABLE QPoint cursorPos();
|
||||
|
||||
Q_INVOKABLE QIcon windowIcon();
|
||||
|
||||
Q_INVOKABLE int cursorScreenIndex();
|
||||
|
||||
Q_INVOKABLE int windowBuildNumber();
|
||||
|
||||
Q_INVOKABLE bool isWindows11OrGreater();
|
||||
|
||||
Q_INVOKABLE bool isWindows10OrGreater();
|
||||
|
||||
Q_INVOKABLE QRect desktopAvailableGeometry(QQuickWindow *window);
|
||||
|
||||
Q_INVOKABLE QString getWallpaperFilePath();
|
||||
|
||||
Q_INVOKABLE QColor imageMainColor(const QImage& image, double bright = 1);
|
||||
};
|
||||
|
@ -1,70 +1,76 @@
|
||||
#include "FluTreeModel.h"
|
||||
|
||||
#include <QMetaEnum>
|
||||
#include <utility>
|
||||
|
||||
FluTreeNode::FluTreeNode(QObject *parent): QObject{parent}{
|
||||
FluTreeNode::FluTreeNode(QObject *parent) : QObject{parent} {
|
||||
}
|
||||
|
||||
FluTreeModel::FluTreeModel(QObject *parent): QAbstractItemModel{parent}{
|
||||
dataSourceSize(0);
|
||||
FluTreeModel::FluTreeModel(QObject *parent) : QAbstractItemModel{parent} {
|
||||
_dataSourceSize = 0;
|
||||
}
|
||||
|
||||
QModelIndex FluTreeModel::parent(const QModelIndex &child) const{
|
||||
return QModelIndex();
|
||||
QModelIndex FluTreeModel::parent(const QModelIndex &child) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
QModelIndex FluTreeModel::index(int row, int column,const QModelIndex &parent) const{
|
||||
QModelIndex FluTreeModel::index(int row, int column, const QModelIndex &parent) const {
|
||||
if (!hasIndex(row, column, parent) || parent.isValid())
|
||||
return QModelIndex();
|
||||
return {};
|
||||
return createIndex(row, column, _rows.at(row));
|
||||
}
|
||||
|
||||
int FluTreeModel::rowCount(const QModelIndex &parent) const {
|
||||
return _rows.count();
|
||||
};
|
||||
}
|
||||
|
||||
int FluTreeModel::columnCount(const QModelIndex &parent) const {
|
||||
return 1;;
|
||||
};
|
||||
return this->_columnSource.size();
|
||||
}
|
||||
|
||||
QVariant FluTreeModel::data(const QModelIndex &index, int role) const {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return QVariant::fromValue(_rows.at(index.row()));
|
||||
default:
|
||||
break;
|
||||
case TreeModelRoles::RowModel:
|
||||
return QVariant::fromValue(_rows.at(index.row()));
|
||||
case TreeModelRoles::ColumnModel:
|
||||
return QVariant::fromValue(_columnSource.at(index.column()));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QVariant();
|
||||
};
|
||||
return {};
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> FluTreeModel::roleNames() const {
|
||||
return { {Qt::DisplayRole, "dataModel"} };
|
||||
};
|
||||
return {
|
||||
{TreeModelRoles::RowModel, "rowModel"},
|
||||
{TreeModelRoles::ColumnModel, "columnModel"}
|
||||
};
|
||||
}
|
||||
|
||||
void FluTreeModel::setData(QList<FluTreeNode*> data){
|
||||
void FluTreeModel::setData(QList<FluTreeNode *> data) {
|
||||
beginResetModel();
|
||||
_rows = data;
|
||||
_rows = std::move(data);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void FluTreeModel::removeRows(int row,int count){
|
||||
if (row < 0 || row + count > _rows.size() || count==0)
|
||||
void FluTreeModel::removeRows(int row, int count) {
|
||||
if (row < 0 || row + count > _rows.size() || count == 0)
|
||||
return;
|
||||
beginRemoveRows(QModelIndex(),row, row + count - 1);
|
||||
QList<FluTreeNode*> firstPart = _rows.mid(0,row);
|
||||
QList<FluTreeNode*> secondPart = _rows.mid(row + count);
|
||||
beginRemoveRows(QModelIndex(), row, row + count - 1);
|
||||
QList<FluTreeNode *> firstPart = _rows.mid(0, row);
|
||||
QList<FluTreeNode *> secondPart = _rows.mid(row + count);
|
||||
_rows.clear();
|
||||
_rows.append(firstPart);
|
||||
_rows.append(secondPart);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void FluTreeModel::insertRows(int row,QList<FluTreeNode*> data){
|
||||
if (row < 0 || row > _rows.size() || data.size() == 0)
|
||||
return;;
|
||||
void FluTreeModel::insertRows(int row, const QList<FluTreeNode *> &data) {
|
||||
if (row < 0 || row > _rows.size() || data.empty())
|
||||
return;
|
||||
beginInsertRows(QModelIndex(), row, row + data.size() - 1);
|
||||
QList<FluTreeNode*> firstPart = _rows.mid(0, row);
|
||||
QList<FluTreeNode*> secondPart = _rows.mid(row);
|
||||
QList<FluTreeNode *> firstPart = _rows.mid(0, row);
|
||||
QList<FluTreeNode *> secondPart = _rows.mid(row);
|
||||
_rows.clear();
|
||||
_rows.append(firstPart);
|
||||
_rows.append(data);
|
||||
@ -72,79 +78,75 @@ void FluTreeModel::insertRows(int row,QList<FluTreeNode*> data){
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
QObject* FluTreeModel::getRow(int row){
|
||||
QObject *FluTreeModel::getRow(int row) {
|
||||
return _rows.at(row);
|
||||
}
|
||||
|
||||
void FluTreeModel::checkRow(int row,bool checked){
|
||||
void FluTreeModel::setRow(int row, QVariantMap data) {
|
||||
_rows.at(row)->_data = std::move(data);
|
||||
Q_EMIT dataChanged(index(row, 0), index(row, columnCount() - 1));
|
||||
}
|
||||
|
||||
void FluTreeModel::checkRow(int row, bool checked) {
|
||||
auto itemData = _rows.at(row);
|
||||
if(itemData->hasChildren()){
|
||||
QList<FluTreeNode*> stack = itemData->_children;
|
||||
if (itemData->hasChildren()) {
|
||||
QList<FluTreeNode *> stack = itemData->_children;
|
||||
std::reverse(stack.begin(), stack.end());
|
||||
while (stack.count() > 0) {
|
||||
auto item = stack.at(stack.count()-1);
|
||||
auto item = stack.at(stack.count() - 1);
|
||||
stack.pop_back();
|
||||
if(!item->hasChildren()){
|
||||
if (!item->hasChildren()) {
|
||||
item->_checked = checked;
|
||||
}
|
||||
QList<FluTreeNode*> children = item->_children;
|
||||
if(!children.isEmpty()){
|
||||
QList<FluTreeNode *> children = item->_children;
|
||||
if (!children.isEmpty()) {
|
||||
std::reverse(children.begin(), children.end());
|
||||
foreach (auto c, children) {
|
||||
stack.append(c);
|
||||
}
|
||||
foreach (auto c, children) {
|
||||
stack.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(itemData->_checked == checked){
|
||||
} else {
|
||||
if (itemData->_checked == checked) {
|
||||
return;
|
||||
}
|
||||
itemData->_checked = checked;
|
||||
}
|
||||
Q_EMIT dataChanged(index(0,0),index(rowCount()-1,0));
|
||||
QList<FluTreeNode*> data;
|
||||
foreach (auto item, _dataSource) {
|
||||
if(!item->hasChildren()){
|
||||
if(item->_checked){
|
||||
data.append(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
selectionModel(data);
|
||||
Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, 0));
|
||||
|
||||
}
|
||||
|
||||
void FluTreeModel::setDataSource(QList<QMap<QString,QVariant>> data){
|
||||
void FluTreeModel::setDataSource(QList<QMap<QString, QVariant>> data) {
|
||||
_dataSource.clear();
|
||||
if(_root){
|
||||
if (_root) {
|
||||
delete _root;
|
||||
_root = nullptr;
|
||||
}
|
||||
_root = new FluTreeNode(this);
|
||||
std::reverse(data.begin(), data.end());
|
||||
while (data.count() > 0) {
|
||||
auto item = data.at(data.count()-1);
|
||||
auto item = data.at(data.count() - 1);
|
||||
data.pop_back();
|
||||
FluTreeNode* node = new FluTreeNode(this);
|
||||
node->_title = item.value("title").toString();
|
||||
node->_key = item.value("key").toString();
|
||||
auto *node = new FluTreeNode(this);
|
||||
node->_depth = item.value("__depth").toInt();
|
||||
node->_parent = item.value("__parent").value<FluTreeNode*>();
|
||||
node->_parent = item.value("__parent").value<FluTreeNode *>();
|
||||
node->_data = item;
|
||||
node->_isExpanded = true;
|
||||
if(node->_parent){
|
||||
if (node->_parent) {
|
||||
node->_parent->_children.append(node);
|
||||
}else{
|
||||
} else {
|
||||
node->_parent = _root;
|
||||
_root->_children.append(node);
|
||||
}
|
||||
_dataSource.append(node);
|
||||
if (item.contains("children")) {
|
||||
QList<QVariant> children = item.value("children").toList();
|
||||
if(!children.isEmpty()){
|
||||
if (!children.isEmpty()) {
|
||||
std::reverse(children.begin(), children.end());
|
||||
for (int i = 0; i < children.count(); ++i) {
|
||||
for (int i = 0; i <= children.count() - 1; ++i) {
|
||||
auto child = children.at(i).toMap();
|
||||
child.insert("__depth",item.value("__depth").toInt(0)+1);
|
||||
child.insert("__parent",QVariant::fromValue(node));
|
||||
child.insert("__depth", item.value("__depth").toInt(nullptr) + 1);
|
||||
child.insert("__parent", QVariant::fromValue(node));
|
||||
data.append(child);
|
||||
}
|
||||
}
|
||||
@ -156,212 +158,119 @@ void FluTreeModel::setDataSource(QList<QMap<QString,QVariant>> data){
|
||||
dataSourceSize(_dataSource.size());
|
||||
}
|
||||
|
||||
void FluTreeModel::collapse(int row){
|
||||
if(!_rows.at(row)->_isExpanded){
|
||||
void FluTreeModel::collapse(int row) {
|
||||
if (!_rows.at(row)->_isExpanded) {
|
||||
return;
|
||||
}
|
||||
_rows.at(row)->_isExpanded = false;
|
||||
Q_EMIT dataChanged(index(row,0),index(row,0));
|
||||
Q_EMIT dataChanged(index(row, 0), index(row, 0));
|
||||
auto modelData = _rows.at(row);
|
||||
int removeCount = 0;
|
||||
for(int i=row+1;i<_rows.count();i++){
|
||||
for (int i = row + 1; i < _rows.count(); i++) {
|
||||
auto obj = _rows[i];
|
||||
if(obj->_depth<=modelData->_depth){
|
||||
if (obj->_depth <= modelData->_depth) {
|
||||
break;
|
||||
}
|
||||
removeCount = removeCount + 1;
|
||||
}
|
||||
removeRows(row+1,removeCount);
|
||||
removeRows(row + 1, removeCount);
|
||||
}
|
||||
|
||||
void FluTreeModel::expand(int row){
|
||||
if(_rows.at(row)->_isExpanded){
|
||||
void FluTreeModel::expand(int row) {
|
||||
if (_rows.at(row)->_isExpanded) {
|
||||
return;
|
||||
}
|
||||
_rows.at(row)->_isExpanded = true;
|
||||
Q_EMIT dataChanged(index(row,0),index(row,0));
|
||||
Q_EMIT dataChanged(index(row, 0), index(row, 0));
|
||||
auto modelData = _rows.at(row);
|
||||
QList<FluTreeNode*> insertData;
|
||||
QList<FluTreeNode*> stack = modelData->_children;
|
||||
QList<FluTreeNode *> insertData;
|
||||
QList<FluTreeNode *> stack = modelData->_children;
|
||||
std::reverse(stack.begin(), stack.end());
|
||||
while (stack.count() > 0) {
|
||||
auto item = stack.at(stack.count()-1);
|
||||
auto item = stack.at(stack.count() - 1);
|
||||
stack.pop_back();
|
||||
if(item->isShown()){
|
||||
if (item->isShown()) {
|
||||
insertData.append(item);
|
||||
}
|
||||
QList<FluTreeNode*> children = item->_children;
|
||||
if(!children.isEmpty()){
|
||||
QList<FluTreeNode *> children = item->_children;
|
||||
if (!children.isEmpty()) {
|
||||
std::reverse(children.begin(), children.end());
|
||||
foreach (auto c, children) {
|
||||
stack.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
insertRows(row+1,insertData);
|
||||
}
|
||||
|
||||
void FluTreeModel::dragAndDrop(int dragIndex,int dropIndex,bool isDropTopArea){
|
||||
if(dropIndex>_rows.count() || dropIndex<0){
|
||||
return;
|
||||
}
|
||||
auto dragItem = _rows[dragIndex];
|
||||
auto dropItem = _rows[dropIndex];
|
||||
int targetIndex;
|
||||
if(dropIndex > dragIndex){
|
||||
if(isDropTopArea){
|
||||
targetIndex = dropIndex;
|
||||
}else{
|
||||
targetIndex = dropIndex+1;
|
||||
}
|
||||
}else{
|
||||
if(isDropTopArea){
|
||||
targetIndex = dropIndex;
|
||||
}else{
|
||||
targetIndex = dropIndex+1;
|
||||
}
|
||||
}
|
||||
if (!beginMoveRows(QModelIndex(), dragIndex, dragIndex, QModelIndex(), targetIndex)) {
|
||||
return;
|
||||
}
|
||||
if(dropIndex > dragIndex){
|
||||
if(isDropTopArea){
|
||||
targetIndex = dropIndex-1;
|
||||
}else{
|
||||
targetIndex = dropIndex;
|
||||
}
|
||||
}else{
|
||||
if(isDropTopArea){
|
||||
targetIndex = dropIndex;
|
||||
}else{
|
||||
targetIndex = dropIndex+1;
|
||||
}
|
||||
}
|
||||
_rows.move(dragIndex,targetIndex);
|
||||
endMoveRows();
|
||||
|
||||
Q_EMIT layoutAboutToBeChanged();
|
||||
if(dragItem->_parent == dropItem->_parent){
|
||||
QList<FluTreeNode*>* children = &(dragItem->_parent->_children);
|
||||
int srcIndex = children->indexOf(dragItem);
|
||||
int destIndex = children->indexOf(dropItem);
|
||||
if(dropIndex > dragIndex){
|
||||
if(isDropTopArea){
|
||||
targetIndex = destIndex-1;
|
||||
}else{
|
||||
targetIndex = destIndex;
|
||||
}
|
||||
}else{
|
||||
if(isDropTopArea){
|
||||
targetIndex = destIndex;
|
||||
}else{
|
||||
targetIndex = destIndex+1;
|
||||
}
|
||||
}
|
||||
children->move(srcIndex,targetIndex);
|
||||
}else{
|
||||
QList<FluTreeNode*>* srcChildren = &(dragItem->_parent->_children);
|
||||
QList<FluTreeNode*>* destChildren = &(dropItem->_parent->_children);
|
||||
int srcIndex = srcChildren->indexOf(dragItem);
|
||||
int destIndex = destChildren->indexOf(dropItem);
|
||||
dragItem->_depth = dropItem->_depth;
|
||||
dragItem->_parent = dropItem->_parent;
|
||||
if(dragItem->hasChildren()){
|
||||
QList<FluTreeNode*> stack = dragItem->_children;
|
||||
foreach (auto node, stack) {
|
||||
node->_depth = dragItem->_depth+1;
|
||||
}
|
||||
std::reverse(stack.begin(), stack.end());
|
||||
while (stack.count() > 0) {
|
||||
auto item = stack.at(stack.count()-1);
|
||||
stack.pop_back();
|
||||
QList<FluTreeNode*> children = item->_children;
|
||||
if(!children.isEmpty()){
|
||||
std::reverse(children.begin(), children.end());
|
||||
foreach (auto c, children) {
|
||||
c->_depth = item->_depth+1;
|
||||
stack.append(c);
|
||||
}
|
||||
stack.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
srcChildren->removeAt(srcIndex);
|
||||
if(dropIndex > dragIndex){
|
||||
if(isDropTopArea){
|
||||
targetIndex = destIndex;
|
||||
}else{
|
||||
targetIndex = destIndex + 1;
|
||||
}
|
||||
}else{
|
||||
if(isDropTopArea){
|
||||
targetIndex = destIndex;
|
||||
}else{
|
||||
targetIndex = destIndex + 1;
|
||||
}
|
||||
}
|
||||
destChildren->insert(targetIndex,dragItem);
|
||||
}
|
||||
changePersistentIndex(index(qMin(dragIndex,dropIndex),0),index(qMax(dragIndex,dropIndex),0));
|
||||
Q_EMIT dataChanged(index(0,0),index(rowCount()-1,0));
|
||||
insertRows(row + 1, insertData);
|
||||
}
|
||||
|
||||
bool FluTreeModel::hitHasChildrenExpanded(int row){
|
||||
bool FluTreeModel::hitHasChildrenExpanded(int row) {
|
||||
auto itemData = _rows.at(row);
|
||||
if(itemData->hasChildren() && itemData->_isExpanded){
|
||||
if (itemData->hasChildren() && itemData->_isExpanded) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FluTreeModel::refreshNode(int row){
|
||||
Q_EMIT dataChanged(index(row,0),index(row,0));
|
||||
};
|
||||
void FluTreeModel::refreshNode(int row) {
|
||||
Q_EMIT dataChanged(index(row, 0), index(row, 0));
|
||||
}
|
||||
|
||||
FluTreeNode* FluTreeModel::getNode(int row){
|
||||
FluTreeNode *FluTreeModel::getNode(int row) {
|
||||
return _rows.at(row);
|
||||
}
|
||||
|
||||
void FluTreeModel::allExpand(){
|
||||
void FluTreeModel::allExpand() {
|
||||
beginResetModel();
|
||||
QList<FluTreeNode*> data;
|
||||
QList<FluTreeNode*> stack = _root->_children;
|
||||
QList<FluTreeNode *> data;
|
||||
QList<FluTreeNode *> stack = _root->_children;
|
||||
std::reverse(stack.begin(), stack.end());
|
||||
while (stack.count() > 0) {
|
||||
auto item = stack.at(stack.count()-1);
|
||||
auto item = stack.at(stack.count() - 1);
|
||||
stack.pop_back();
|
||||
if(item->hasChildren()){
|
||||
if (item->hasChildren()) {
|
||||
item->_isExpanded = true;
|
||||
}
|
||||
data.append(item);
|
||||
QList<FluTreeNode*> children = item->_children;
|
||||
if(!children.isEmpty()){
|
||||
QList<FluTreeNode *> children = item->_children;
|
||||
if (!children.isEmpty()) {
|
||||
std::reverse(children.begin(), children.end());
|
||||
foreach (auto c, children) {
|
||||
stack.append(c);
|
||||
}
|
||||
foreach (auto c, children) {
|
||||
stack.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
_rows = data;
|
||||
endResetModel();
|
||||
}
|
||||
void FluTreeModel::allCollapse(){
|
||||
|
||||
void FluTreeModel::allCollapse() {
|
||||
beginResetModel();
|
||||
QList<FluTreeNode*> stack = _root->_children;
|
||||
QList<FluTreeNode *> stack = _root->_children;
|
||||
std::reverse(stack.begin(), stack.end());
|
||||
while (stack.count() > 0) {
|
||||
auto item = stack.at(stack.count()-1);
|
||||
auto item = stack.at(stack.count() - 1);
|
||||
stack.pop_back();
|
||||
if(item->hasChildren()){
|
||||
if (item->hasChildren()) {
|
||||
item->_isExpanded = false;
|
||||
}
|
||||
QList<FluTreeNode*> children = item->_children;
|
||||
if(!children.isEmpty()){
|
||||
QList<FluTreeNode *> children = item->_children;
|
||||
if (!children.isEmpty()) {
|
||||
std::reverse(children.begin(), children.end());
|
||||
foreach (auto c, children) {
|
||||
stack.append(c);
|
||||
}
|
||||
foreach (auto c, children) {
|
||||
stack.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
_rows = _root->_children;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QVariant FluTreeModel::selectionModel(){
|
||||
QList<FluTreeNode *> data;
|
||||
foreach (auto item, _dataSource) {
|
||||
if (item->checked()) {
|
||||
data.append(item);
|
||||
}
|
||||
}
|
||||
return QVariant::fromValue(data);
|
||||
}
|
||||
|
@ -1,118 +1,149 @@
|
||||
#ifndef FLUTREEMODEL_H
|
||||
#define FLUTREEMODEL_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QAbstractTableModel>
|
||||
#include <QJsonArray>
|
||||
#include <QVariant>
|
||||
#include <QtQml/qqml.h>
|
||||
#include "stdafx.h"
|
||||
|
||||
/**
|
||||
* @brief The FluTreeNode class
|
||||
*/
|
||||
class FluTreeNode : public QObject{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString key READ key CONSTANT)
|
||||
Q_PROPERTY(QString title READ title CONSTANT)
|
||||
class FluTreeNode : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QVariantMap data READ data CONSTANT)
|
||||
Q_PROPERTY(int depth READ depth CONSTANT)
|
||||
Q_PROPERTY(bool isExpanded READ isExpanded CONSTANT)
|
||||
Q_PROPERTY(bool checked READ checked CONSTANT)
|
||||
public:
|
||||
explicit FluTreeNode(QObject *parent = nullptr);
|
||||
Q_INVOKABLE QString key(){return _key;};
|
||||
Q_INVOKABLE QString title(){return _title;};
|
||||
Q_INVOKABLE int depth(){return _depth;};
|
||||
Q_INVOKABLE bool isExpanded(){return _isExpanded;};
|
||||
Q_INVOKABLE bool hasChildren(){ return !_children.isEmpty();};
|
||||
Q_INVOKABLE bool hasNextNodeByIndex(int index){
|
||||
FluTreeNode* p = this;
|
||||
for(int i=0;i<(_depth - index -1);i++){
|
||||
|
||||
[[nodiscard]] Q_INVOKABLE int depth() const { return _depth; };
|
||||
|
||||
[[nodiscard]] Q_INVOKABLE bool isExpanded() const { return _isExpanded; };
|
||||
|
||||
[[nodiscard]] Q_INVOKABLE QVariantMap data() const { return _data; };
|
||||
|
||||
[[nodiscard]] Q_INVOKABLE bool hasChildren() const { return !_children.isEmpty(); };
|
||||
|
||||
Q_INVOKABLE bool hasNextNodeByIndex(int index) {
|
||||
FluTreeNode *p = this;
|
||||
for (int i = 0; i <= _depth - index - 1; i++) {
|
||||
p = p->_parent;
|
||||
}
|
||||
if(p->_parent->_children.indexOf(p) == p->_parent->_children.count()-1){
|
||||
if (p->_parent->_children.indexOf(p) == p->_parent->_children.count() - 1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Q_INVOKABLE bool checked(){
|
||||
if(!hasChildren()){
|
||||
|
||||
[[nodiscard]] Q_INVOKABLE bool checked() const {
|
||||
if (!hasChildren()) {
|
||||
return _checked;
|
||||
}
|
||||
foreach (auto item, _children) {
|
||||
if(!item->checked()){
|
||||
|
||||
for (int i = 0; i <= _children.size() - 1; ++i) {
|
||||
auto item = _children.at(i);
|
||||
if (!item->checked()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
Q_INVOKABLE bool hideLineFooter(){
|
||||
if(_parent){
|
||||
auto childIndex = _parent->_children.indexOf(this);
|
||||
if(childIndex==_parent->_children.count()-1){
|
||||
|
||||
Q_INVOKABLE bool hideLineFooter() {
|
||||
if (_parent) {
|
||||
auto childIndex = _parent->_children.indexOf(this);
|
||||
if (childIndex == _parent->_children.count() - 1) {
|
||||
return true;
|
||||
}
|
||||
if(_parent->_children.at(childIndex+1)->hasChildren()){
|
||||
if (_parent->_children.at(childIndex + 1)->hasChildren()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
bool isShown(){
|
||||
|
||||
[[nodiscard]] bool isShown() const {
|
||||
auto p = _parent;
|
||||
while (p) {
|
||||
if(!p->_isExpanded){
|
||||
if (!p->_isExpanded) {
|
||||
return false;
|
||||
}
|
||||
p = p->_parent;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
QString _key="";
|
||||
QString _title="";
|
||||
int _depth=0;
|
||||
QString _title = "";
|
||||
int _depth = 0;
|
||||
bool _checked = false;
|
||||
bool _isExpanded=true;
|
||||
QList<FluTreeNode*> _children;
|
||||
FluTreeNode* _parent = nullptr;
|
||||
bool _isExpanded = true;
|
||||
QVariantMap _data;
|
||||
QList<FluTreeNode *> _children;
|
||||
FluTreeNode *_parent = nullptr;
|
||||
};
|
||||
|
||||
class FluTreeModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(int,dataSourceSize)
|
||||
Q_PROPERTY_AUTO(QList<FluTreeNode*>,selectionModel)
|
||||
class FluTreeModel : public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(int, dataSourceSize)
|
||||
Q_PROPERTY_AUTO(QList<QVariantMap>, columnSource)
|
||||
QML_NAMED_ELEMENT(FluTreeModel)
|
||||
QML_ADDED_IN_MINOR_VERSION(1)
|
||||
public:
|
||||
enum TreeModelRoles {
|
||||
RowModel = 0x0101,
|
||||
ColumnModel = 0x0102
|
||||
};
|
||||
|
||||
explicit FluTreeModel(QObject *parent = nullptr);
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
QModelIndex parent(const QModelIndex &child) const override;
|
||||
QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
Q_INVOKABLE void removeRows(int row,int count);
|
||||
Q_INVOKABLE void insertRows(int row,QList<FluTreeNode*> data);
|
||||
Q_INVOKABLE QObject* getRow(int row);
|
||||
Q_INVOKABLE void setData(QList<FluTreeNode*> data);
|
||||
Q_INVOKABLE void setDataSource(QList<QMap<QString,QVariant>> data);
|
||||
[[nodiscard]] int rowCount(const QModelIndex &parent = {}) const override;
|
||||
|
||||
[[nodiscard]] int columnCount(const QModelIndex &parent = {}) const override;
|
||||
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
[[nodiscard]] QModelIndex parent(const QModelIndex &child) const override;
|
||||
|
||||
[[nodiscard]] QModelIndex index(int row, int column, const QModelIndex &parent = {}) const override;
|
||||
|
||||
Q_INVOKABLE void removeRows(int row, int count);
|
||||
|
||||
Q_INVOKABLE void insertRows(int row, const QList<FluTreeNode *> &data);
|
||||
|
||||
Q_INVOKABLE QObject *getRow(int row);
|
||||
|
||||
Q_INVOKABLE void setRow(int row, QVariantMap data);
|
||||
|
||||
Q_INVOKABLE void setData(QList<FluTreeNode *> data);
|
||||
|
||||
Q_INVOKABLE void setDataSource(QList<QMap<QString, QVariant>> data);
|
||||
|
||||
Q_INVOKABLE void collapse(int row);
|
||||
Q_INVOKABLE void expand(int row);
|
||||
Q_INVOKABLE void dragAndDrop(int dragIndex,int dropIndex,bool isDropTopArea);
|
||||
Q_INVOKABLE FluTreeNode* getNode(int row);
|
||||
Q_INVOKABLE void refreshNode(int row);
|
||||
Q_INVOKABLE void checkRow(int row,bool checked);
|
||||
Q_INVOKABLE bool hitHasChildrenExpanded(int row);
|
||||
Q_INVOKABLE void allExpand();
|
||||
Q_INVOKABLE void allCollapse();
|
||||
private:
|
||||
QList<FluTreeNode*> _rows;
|
||||
QList<FluTreeNode*> _dataSource;
|
||||
FluTreeNode* _root = nullptr;
|
||||
};
|
||||
|
||||
#endif // FLUTREEMODEL_H
|
||||
Q_INVOKABLE void expand(int row);
|
||||
|
||||
Q_INVOKABLE FluTreeNode *getNode(int row);
|
||||
|
||||
Q_INVOKABLE void refreshNode(int row);
|
||||
|
||||
Q_INVOKABLE void checkRow(int row, bool checked);
|
||||
|
||||
Q_INVOKABLE bool hitHasChildrenExpanded(int row);
|
||||
|
||||
Q_INVOKABLE void allExpand();
|
||||
|
||||
Q_INVOKABLE void allCollapse();
|
||||
|
||||
Q_INVOKABLE QVariant selectionModel();
|
||||
|
||||
private:
|
||||
QList<FluTreeNode *> _rows;
|
||||
QList<FluTreeNode *> _dataSource;
|
||||
FluTreeNode *_root = nullptr;
|
||||
};
|
||||
|
@ -1,36 +1,37 @@
|
||||
#include "FluWatermark.h"
|
||||
|
||||
FluWatermark::FluWatermark(QQuickItem* parent) : QQuickPaintedItem(parent){
|
||||
gap(QPoint(100,100));
|
||||
offset(QPoint(_gap.x()/2,_gap.y()/2));
|
||||
rotate(22);
|
||||
#include "FluTextStyle.h"
|
||||
|
||||
FluWatermark::FluWatermark(QQuickItem *parent) : QQuickPaintedItem(parent) {
|
||||
_gap = QPoint(100, 100);
|
||||
_offset = QPoint(_gap.x() / 2, _gap.y() / 2);
|
||||
_rotate = 22;
|
||||
_textColor = QColor(222, 222, 222, 222);
|
||||
_textSize = 16;
|
||||
setZ(9999);
|
||||
textColor(QColor(222,222,222,222));
|
||||
textSize(16);
|
||||
connect(this,&FluWatermark::textColorChanged,this,[=]{update();});
|
||||
connect(this,&FluWatermark::gapChanged,this,[=]{update();});
|
||||
connect(this,&FluWatermark::offsetChanged,this,[=]{update();});
|
||||
connect(this,&FluWatermark::textChanged,this,[=]{update();});
|
||||
connect(this,&FluWatermark::rotateChanged,this,[=]{update();});
|
||||
connect(this,&FluWatermark::textSizeChanged,this,[=]{update();});
|
||||
connect(this, &FluWatermark::textColorChanged, this, [=] { update(); });
|
||||
connect(this, &FluWatermark::gapChanged, this, [=] { update(); });
|
||||
connect(this, &FluWatermark::offsetChanged, this, [=] { update(); });
|
||||
connect(this, &FluWatermark::textChanged, this, [=] { update(); });
|
||||
connect(this, &FluWatermark::rotateChanged, this, [=] { update(); });
|
||||
connect(this, &FluWatermark::textSizeChanged, this, [=] { update(); });
|
||||
}
|
||||
|
||||
void FluWatermark::paint(QPainter* painter){
|
||||
void FluWatermark::paint(QPainter *painter) {
|
||||
QFont font;
|
||||
font.setFamily(FluTextStyle::getInstance()->family());
|
||||
font.setPixelSize(_textSize);
|
||||
painter->setFont(font);
|
||||
painter->setPen(_textColor);
|
||||
QFontMetricsF fontMetrics(font);
|
||||
qreal fontWidth = fontMetrics.horizontalAdvance(_text);
|
||||
qreal fontHeight = fontMetrics.height();
|
||||
int stepX = fontWidth + _gap.x();
|
||||
int stepY = fontHeight + _gap.y();
|
||||
int rowCount = width() / stepX+1;
|
||||
int colCount = height() / stepY+1;
|
||||
for (int r = 0; r < rowCount; r++)
|
||||
{
|
||||
for (int c = 0; c < colCount; c++)
|
||||
{
|
||||
int stepX = qRound(fontWidth + _gap.x());
|
||||
int stepY = qRound(fontHeight + _gap.y());
|
||||
int rowCount = qRound(width() / stepX + 1);
|
||||
int colCount = qRound(height() / stepY + 1);
|
||||
for (int r = 0; r < rowCount; r++) {
|
||||
for (int c = 0; c < colCount; c++) {
|
||||
qreal centerX = stepX * r + _offset.x() + fontWidth / 2.0;
|
||||
qreal centerY = stepY * c + _offset.y() + fontHeight / 2.0;
|
||||
painter->save();
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef FLUWATERMARK_H
|
||||
#define FLUWATERMARK_H
|
||||
#pragma once
|
||||
|
||||
#include <QQuickItem>
|
||||
#include <QQuickPaintedItem>
|
||||
@ -9,19 +8,17 @@
|
||||
/**
|
||||
* @brief The FluWatermark class
|
||||
*/
|
||||
class FluWatermark : public QQuickPaintedItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QString,text)
|
||||
Q_PROPERTY_AUTO(QPoint,gap)
|
||||
Q_PROPERTY_AUTO(QPoint,offset);
|
||||
Q_PROPERTY_AUTO(QColor,textColor);
|
||||
Q_PROPERTY_AUTO(int,rotate);
|
||||
Q_PROPERTY_AUTO(int,textSize);
|
||||
class FluWatermark : public QQuickPaintedItem {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QString, text)
|
||||
Q_PROPERTY_AUTO(QPoint, gap)
|
||||
Q_PROPERTY_AUTO(QPoint, offset);
|
||||
Q_PROPERTY_AUTO(QColor, textColor);
|
||||
Q_PROPERTY_AUTO(int, rotate);
|
||||
Q_PROPERTY_AUTO(int, textSize);
|
||||
QML_NAMED_ELEMENT(FluWatermark)
|
||||
public:
|
||||
explicit FluWatermark(QQuickItem *parent = nullptr);
|
||||
void paint(QPainter* painter) override;
|
||||
};
|
||||
|
||||
#endif // FLUWATERMARK_H
|
||||
void paint(QPainter *painter) override;
|
||||
};
|
||||
|
1417
src/FluentIconDef.h
Normal file
1417
src/FluentIconDef.h
Normal file
File diff suppressed because it is too large
Load Diff
258
src/FluentUI.cpp
258
src/FluentUI.cpp
@ -2,6 +2,7 @@
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include "Def.h"
|
||||
#include "FluentIconDef.h"
|
||||
#include "FluApp.h"
|
||||
#include "FluColors.h"
|
||||
#include "FluTheme.h"
|
||||
@ -15,143 +16,144 @@
|
||||
#include "FluTableSortProxyModel.h"
|
||||
#include "FluFrameless.h"
|
||||
|
||||
void FluentUI::registerTypes(QQmlEngine *engine){
|
||||
initializeEngine(engine,uri);
|
||||
registerTypes(uri);
|
||||
void FluentUI::registerTypes(QQmlEngine *engine) {
|
||||
initializeEngine(engine, _uri);
|
||||
registerTypes(_uri);
|
||||
}
|
||||
|
||||
void FluentUI::registerTypes(const char *uri){
|
||||
void FluentUI::registerTypes(const char *uri) const {
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 2, 0))
|
||||
Q_INIT_RESOURCE(fluentui);
|
||||
|
||||
int major = _major;
|
||||
int minor = _minor;
|
||||
//@uri FluentUI
|
||||
qmlRegisterType<FluQrCodeItem>(uri,major,minor,"FluQrCodeItem");
|
||||
qmlRegisterType<FluCaptcha>(uri,major,minor,"FluCaptcha");
|
||||
qmlRegisterType<FluWatermark>(uri,major,minor,"FluWatermark");
|
||||
qmlRegisterType<FluAccentColor>(uri,major,minor,"FluAccentColor");
|
||||
qmlRegisterType<FluTreeModel>(uri,major,minor,"FluTreeModel");
|
||||
qmlRegisterType<FluRectangle>(uri,major,minor,"FluRectangle");
|
||||
qmlRegisterType<FluFrameless>(uri,major,minor,"FluFrameless");
|
||||
qmlRegisterType<FluTableSortProxyModel>(uri,major,minor,"FluTableSortProxyModel");
|
||||
qmlRegisterType<FluQrCodeItem>(uri, major, minor, "FluQrCodeItem");
|
||||
qmlRegisterType<FluCaptcha>(uri, major, minor, "FluCaptcha");
|
||||
qmlRegisterType<FluWatermark>(uri, major, minor, "FluWatermark");
|
||||
qmlRegisterType<FluAccentColor>(uri, major, minor, "FluAccentColor");
|
||||
qmlRegisterType<FluTreeModel>(uri, major, minor, "FluTreeModel");
|
||||
qmlRegisterType<FluRectangle>(uri, major, minor, "FluRectangle");
|
||||
qmlRegisterType<FluFrameless>(uri, major, minor, "FluFrameless");
|
||||
qmlRegisterType<FluTableSortProxyModel>(uri, major, minor, "FluTableSortProxyModel");
|
||||
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluAcrylic.qml"),uri,major,minor,"FluAcrylic");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluAppBar.qml"),uri,major,minor,"FluAppBar");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluFrame.qml"),uri,major,minor,"FluFrame");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluAutoSuggestBox.qml"),uri,major,minor,"FluAutoSuggestBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluBadge.qml"),uri,major,minor,"FluBadge");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluBreadcrumbBar.qml"),uri,major,minor,"FluBreadcrumbBar");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluButton.qml"),uri,major,minor,"FluButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluCalendarPicker.qml"),uri,major,minor,"FluCalendarPicker");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluCarousel.qml"),uri,major,minor,"FluCarousel");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluChart.qml"),uri,major,minor,"FluChart");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluCheckBox.qml"),uri,major,minor,"FluCheckBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluColorPicker.qml"),uri,major,minor,"FluColorPicker");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluComboBox.qml"),uri,major,minor,"FluComboBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluContentDialog.qml"),uri,major,minor,"FluContentDialog");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluContentPage.qml"),uri,major,minor,"FluContentPage");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluControl.qml"),uri,major,minor,"FluControl");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluCopyableText.qml"),uri,major,minor,"FluCopyableText");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluDatePicker.qml"),uri,major,minor,"FluDatePicker");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluDivider.qml"),uri,major,minor,"FluDivider");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluDropDownButton.qml"),uri,major,minor,"FluDropDownButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluExpander.qml"),uri,major,minor,"FluExpander");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluFilledButton.qml"),uri,major,minor,"FluFilledButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluFlipView.qml"),uri,major,minor,"FluFlipView");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluFocusRectangle.qml"),uri,major,minor,"FluFocusRectangle");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluIcon.qml"),uri,major,minor,"FluIcon");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluIconButton.qml"),uri,major,minor,"FluIconButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluImage.qml"),uri,major,minor,"FluImage");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluImageButton.qml"),uri,major,minor,"FluImageButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluInfoBar.qml"),uri,major,minor,"FluInfoBar");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluItemDelegate.qml"),uri,major,minor,"FluItemDelegate");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMenu.qml"),uri,major,minor,"FluMenu");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMenuBar.qml"),uri,major,minor,"FluMenuBar");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMenuBarItem.qml"),uri,major,minor,"FluMenuBarItem");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMenuItem.qml"),uri,major,minor,"FluMenuItem");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMenuSeparator.qml"),uri,major,minor,"FluMenuSeparator");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMultilineTextBox.qml"),uri,major,minor,"FluMultilineTextBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluNavigationView.qml"),uri,major,minor,"FluNavigationView");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluObject.qml"),uri,major,minor,"FluObject");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPage.qml"),uri,major,minor,"FluPage");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPagination.qml"),uri,major,minor,"FluPagination");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPaneItem.qml"),uri,major,minor,"FluPaneItem");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPaneItemEmpty.qml"),uri,major,minor,"FluPaneItemEmpty");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPaneItemExpander.qml"),uri,major,minor,"FluPaneItemExpander");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPaneItemHeader.qml"),uri,major,minor,"FluPaneItemHeader");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPaneItemSeparator.qml"),uri,major,minor,"FluPaneItemSeparator");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPasswordBox.qml"),uri,major,minor,"FluPasswordBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPivot.qml"),uri,major,minor,"FluPivot");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPivotItem.qml"),uri,major,minor,"FluPivotItem");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPopup.qml"),uri,major,minor,"FluPopup");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluProgressBar.qml"),uri,major,minor,"FluProgressBar");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluProgressRing.qml"),uri,major,minor,"FluProgressRing");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluQRCode.qml"),uri,major,minor,"FluQRCode");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRadioButton.qml"),uri,major,minor,"FluRadioButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRadioButtons.qml"),uri,major,minor,"FluRadioButtons");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRatingControl.qml"),uri,major,minor,"FluRatingControl");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRemoteLoader.qml"),uri,major,minor,"FluRemoteLoader");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluScrollBar.qml"),uri,major,minor,"FluScrollBar");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluScrollIndicator.qml"),uri,major,minor,"FluScrollIndicator");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluScrollablePage.qml"),uri,major,minor,"FluScrollablePage");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluShadow.qml"),uri,major,minor,"FluShadow");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluSlider.qml"),uri,major,minor,"FluSlider");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluSpinBox.qml"),uri,major,minor,"FluSpinBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluStatusLayout.qml"),uri,major,minor,"FluStatusLayout");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTabView.qml"),uri,major,minor,"FluTabView");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTableView.qml"),uri,major,minor,"FluTableView");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluText.qml"),uri,major,minor,"FluText");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTextBox.qml"),uri,major,minor,"FluTextBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTextBoxBackground.qml"),uri,major,minor,"FluTextBoxBackground");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTextBoxMenu.qml"),uri,major,minor,"FluTextBoxMenu");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTextButton.qml"),uri,major,minor,"FluTextButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTimePicker.qml"),uri,major,minor,"FluTimePicker");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTimeline.qml"),uri,major,minor,"FluTimeline");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluToggleButton.qml"),uri,major,minor,"FluToggleButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluToggleSwitch.qml"),uri,major,minor,"FluToggleSwitch");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTooltip.qml"),uri,major,minor,"FluTooltip");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTour.qml"),uri,major,minor,"FluTour");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTreeView.qml"),uri,major,minor,"FluTreeView");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluWindow.qml"),uri,major,minor,"FluWindow");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluWindowDialog.qml"),uri,major,minor,"FluWindowDialog");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRangeSlider.qml"),uri,major,minor,"FluRangeSlider");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluStaggeredLayout.qml"),uri,major,minor,"FluStaggeredLayout");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluProgressButton.qml"),uri,major,minor,"FluProgressButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluLoadingButton.qml"),uri,major,minor,"FluLoadingButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluClip.qml"),uri,major,minor,"FluClip");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluLoader.qml"),uri,major,minor,"FluLoader");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluShortcutPicker.qml"),uri,major,minor,"FluShortcutPicker");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluSplitLayout.qml"),uri,major,minor,"FluSplitLayout");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluWindowResultLauncher.qml"),uri,major,minor,"FluWindowResultLauncher");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluLauncher.qml"),uri,major,minor,"FluLauncher");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluEvent.qml"),uri,major,minor,"FluEvent");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluSheet.qml"),uri,major,minor,"FluSheet");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluGroupBox.qml"),uri,major,minor,"FluGroupBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluControlBackground.qml"),uri,major,minor,"FluControlBackground");
|
||||
qmlRegisterSingletonType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRouter.qml"),uri,major,minor,"FluRouter");
|
||||
qmlRegisterSingletonType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluEventBus.qml"),uri,major,minor,"FluEventBus");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluAcrylic.qml"), uri, major, minor, "FluAcrylic");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluAppBar.qml"), uri, major, minor, "FluAppBar");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluFrame.qml"), uri, major, minor, "FluFrame");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluAutoSuggestBox.qml"), uri, major, minor, "FluAutoSuggestBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluBadge.qml"), uri, major, minor, "FluBadge");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluBreadcrumbBar.qml"), uri, major, minor, "FluBreadcrumbBar");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluButton.qml"), uri, major, minor, "FluButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluCalendarPicker.qml"), uri, major, minor, "FluCalendarPicker");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluCarousel.qml"), uri, major, minor, "FluCarousel");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluChart.qml"), uri, major, minor, "FluChart");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluCheckBox.qml"), uri, major, minor, "FluCheckBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluColorPicker.qml"), uri, major, minor, "FluColorPicker");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluComboBox.qml"), uri, major, minor, "FluComboBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluContentDialog.qml"), uri, major, minor, "FluContentDialog");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluContentPage.qml"), uri, major, minor, "FluContentPage");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluControl.qml"), uri, major, minor, "FluControl");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluCopyableText.qml"), uri, major, minor, "FluCopyableText");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluDatePicker.qml"), uri, major, minor, "FluDatePicker");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluDivider.qml"), uri, major, minor, "FluDivider");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluDropDownButton.qml"), uri, major, minor, "FluDropDownButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluExpander.qml"), uri, major, minor, "FluExpander");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluFilledButton.qml"), uri, major, minor, "FluFilledButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluFlipView.qml"), uri, major, minor, "FluFlipView");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluFocusRectangle.qml"), uri, major, minor, "FluFocusRectangle");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluIcon.qml"), uri, major, minor, "FluIcon");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluIconButton.qml"), uri, major, minor, "FluIconButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluImage.qml"), uri, major, minor, "FluImage");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluImageButton.qml"), uri, major, minor, "FluImageButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluInfoBar.qml"), uri, major, minor, "FluInfoBar");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluItemDelegate.qml"), uri, major, minor, "FluItemDelegate");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMenu.qml"), uri, major, minor, "FluMenu");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMenuBar.qml"), uri, major, minor, "FluMenuBar");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMenuBarItem.qml"), uri, major, minor, "FluMenuBarItem");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMenuItem.qml"), uri, major, minor, "FluMenuItem");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMenuSeparator.qml"), uri, major, minor, "FluMenuSeparator");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMultilineTextBox.qml"), uri, major, minor, "FluMultilineTextBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluNavigationView.qml"), uri, major, minor, "FluNavigationView");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluObject.qml"), uri, major, minor, "FluObject");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPage.qml"), uri, major, minor, "FluPage");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPagination.qml"), uri, major, minor, "FluPagination");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPaneItem.qml"), uri, major, minor, "FluPaneItem");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPaneItemEmpty.qml"), uri, major, minor, "FluPaneItemEmpty");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPaneItemExpander.qml"), uri, major, minor, "FluPaneItemExpander");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPaneItemHeader.qml"), uri, major, minor, "FluPaneItemHeader");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPaneItemSeparator.qml"), uri, major, minor, "FluPaneItemSeparator");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPasswordBox.qml"), uri, major, minor, "FluPasswordBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPivot.qml"), uri, major, minor, "FluPivot");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPivotItem.qml"), uri, major, minor, "FluPivotItem");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluPopup.qml"), uri, major, minor, "FluPopup");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluProgressBar.qml"), uri, major, minor, "FluProgressBar");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluProgressRing.qml"), uri, major, minor, "FluProgressRing");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluQRCode.qml"), uri, major, minor, "FluQRCode");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRadioButton.qml"), uri, major, minor, "FluRadioButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRadioButtons.qml"), uri, major, minor, "FluRadioButtons");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRatingControl.qml"), uri, major, minor, "FluRatingControl");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRemoteLoader.qml"), uri, major, minor, "FluRemoteLoader");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluScrollBar.qml"), uri, major, minor, "FluScrollBar");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluScrollIndicator.qml"), uri, major, minor, "FluScrollIndicator");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluScrollablePage.qml"), uri, major, minor, "FluScrollablePage");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluShadow.qml"), uri, major, minor, "FluShadow");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluSlider.qml"), uri, major, minor, "FluSlider");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluSpinBox.qml"), uri, major, minor, "FluSpinBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluStatusLayout.qml"), uri, major, minor, "FluStatusLayout");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTabView.qml"), uri, major, minor, "FluTabView");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTableView.qml"), uri, major, minor, "FluTableView");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluText.qml"), uri, major, minor, "FluText");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTextBox.qml"), uri, major, minor, "FluTextBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTextBoxBackground.qml"), uri, major, minor, "FluTextBoxBackground");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTextBoxMenu.qml"), uri, major, minor, "FluTextBoxMenu");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTextButton.qml"), uri, major, minor, "FluTextButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTimePicker.qml"), uri, major, minor, "FluTimePicker");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTimeline.qml"), uri, major, minor, "FluTimeline");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluToggleButton.qml"), uri, major, minor, "FluToggleButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluToggleSwitch.qml"), uri, major, minor, "FluToggleSwitch");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTooltip.qml"), uri, major, minor, "FluTooltip");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTour.qml"), uri, major, minor, "FluTour");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTreeView.qml"), uri, major, minor, "FluTreeView");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluWindow.qml"), uri, major, minor, "FluWindow");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluWindowDialog.qml"), uri, major, minor, "FluWindowDialog");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRangeSlider.qml"), uri, major, minor, "FluRangeSlider");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluStaggeredLayout.qml"), uri, major, minor, "FluStaggeredLayout");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluProgressButton.qml"), uri, major, minor, "FluProgressButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluLoadingButton.qml"), uri, major, minor, "FluLoadingButton");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluClip.qml"), uri, major, minor, "FluClip");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluLoader.qml"), uri, major, minor, "FluLoader");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluShortcutPicker.qml"), uri, major, minor, "FluShortcutPicker");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluSplitLayout.qml"), uri, major, minor, "FluSplitLayout");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluWindowResultLauncher.qml"), uri, major, minor, "FluWindowResultLauncher");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluLauncher.qml"), uri, major, minor, "FluLauncher");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluEvent.qml"), uri, major, minor, "FluEvent");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluSheet.qml"), uri, major, minor, "FluSheet");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluGroupBox.qml"), uri, major, minor, "FluGroupBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluControlBackground.qml"), uri, major, minor, "FluControlBackground");
|
||||
qmlRegisterSingletonType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRouter.qml"), uri, major, minor, "FluRouter");
|
||||
qmlRegisterSingletonType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluEventBus.qml"), uri, major, minor, "FluEventBus");
|
||||
|
||||
qmlRegisterUncreatableMetaObject(Fluent_Awesome::staticMetaObject, uri,major,minor,"FluentIcons", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluThemeType::staticMetaObject, uri,major,minor,"FluThemeType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluPageType::staticMetaObject, uri,major,minor,"FluPageType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluWindowType::staticMetaObject, uri,major,minor,"FluWindowType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluTreeViewType::staticMetaObject, uri,major,minor,"FluTreeViewType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluStatusLayoutType::staticMetaObject, uri,major,minor,"FluStatusLayoutType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluContentDialogType::staticMetaObject, uri,major,minor,"FluContentDialogType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluTimePickerType::staticMetaObject, uri,major,minor,"FluTimePickerType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluCalendarViewType::staticMetaObject, uri,major,minor,"FluCalendarViewType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluTabViewType::staticMetaObject, uri,major,minor,"FluTabViewType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluNavigationViewType::staticMetaObject, uri,major,minor,"FluNavigationViewType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluTimelineType::staticMetaObject, uri,major,minor,"FluTimelineType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluSheetType::staticMetaObject, uri,major,minor,"FluSheetType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(Fluent_Icons::staticMetaObject, uri, major, minor, "FluentIcons", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluThemeType::staticMetaObject, uri, major, minor, "FluThemeType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluPageType::staticMetaObject, uri, major, minor, "FluPageType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluWindowType::staticMetaObject, uri, major, minor, "FluWindowType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluTreeViewType::staticMetaObject, uri, major, minor, "FluTreeViewType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluStatusLayoutType::staticMetaObject, uri, major, minor, "FluStatusLayoutType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluContentDialogType::staticMetaObject, uri, major, minor, "FluContentDialogType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluTimePickerType::staticMetaObject, uri, major, minor, "FluTimePickerType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluCalendarViewType::staticMetaObject, uri, major, minor, "FluCalendarViewType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluTabViewType::staticMetaObject, uri, major, minor, "FluTabViewType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluNavigationViewType::staticMetaObject, uri, major, minor, "FluNavigationViewType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluTimelineType::staticMetaObject, uri, major, minor, "FluTimelineType", "Access to enums & flags only");
|
||||
qmlRegisterUncreatableMetaObject(FluSheetType::staticMetaObject, uri, major, minor, "FluSheetType", "Access to enums & flags only");
|
||||
|
||||
qmlRegisterModule(uri,major,minor);
|
||||
qmlRegisterModule(uri, major, minor);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FluentUI::initializeEngine(QQmlEngine *engine, const char *uri){
|
||||
engine->rootContext()->setContextProperty("FluApp",FluApp::getInstance());
|
||||
engine->rootContext()->setContextProperty("FluColors",FluColors::getInstance());
|
||||
engine->rootContext()->setContextProperty("FluTheme",FluTheme::getInstance());
|
||||
engine->rootContext()->setContextProperty("FluTools",FluTools::getInstance());
|
||||
engine->rootContext()->setContextProperty("FluTextStyle",FluTextStyle::getInstance());
|
||||
void FluentUI::initializeEngine(QQmlEngine *engine, [[maybe_unused]] const char *uri) {
|
||||
engine->rootContext()->setContextProperty("FluApp", FluApp::getInstance());
|
||||
engine->rootContext()->setContextProperty("FluColors", FluColors::getInstance());
|
||||
engine->rootContext()->setContextProperty("FluTheme", FluTheme::getInstance());
|
||||
engine->rootContext()->setContextProperty("FluTools", FluTools::getInstance());
|
||||
engine->rootContext()->setContextProperty("FluTextStyle", FluTextStyle::getInstance());
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef FLUENTUI_H
|
||||
#define FLUENTUI_H
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlEngine>
|
||||
@ -8,18 +7,20 @@
|
||||
/**
|
||||
* @brief The FluentUI class
|
||||
*/
|
||||
class FluentUI : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SINGLETON(FluentUI)
|
||||
Q_DECL_EXPORT void registerTypes(QQmlEngine *engine);
|
||||
void registerTypes(const char *uri);
|
||||
void initializeEngine(QQmlEngine *engine, const char *uri);
|
||||
private:
|
||||
const int major = 1;
|
||||
const int minor = 0;
|
||||
const char *uri = "FluentUI";
|
||||
};
|
||||
class FluentUI : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
#endif // FLUENTUI_H
|
||||
public:
|
||||
SINGLETON(FluentUI)
|
||||
|
||||
Q_DECL_EXPORT void registerTypes(QQmlEngine *engine);
|
||||
|
||||
void registerTypes(const char *uri) const;
|
||||
|
||||
void initializeEngine(QQmlEngine *engine, [[maybe_unused]] const char *uri);
|
||||
|
||||
private:
|
||||
const int _major = 1;
|
||||
const int _minor = 0;
|
||||
const char *_uri = "FluentUI";
|
||||
};
|
@ -8,10 +8,9 @@ Item {
|
||||
property real tintOpacity: 0.65
|
||||
property real luminosity: 0.01
|
||||
property real noiseOpacity: 0.02
|
||||
property alias target: effect_source.sourceItem
|
||||
property alias target : effect_source.sourceItem
|
||||
property int blurRadius: 32
|
||||
property rect targetRect: Qt.rect(control.x, control.y, control.width,
|
||||
control.height)
|
||||
property rect targetRect: Qt.rect(control.x, control.y, control.width,control.height)
|
||||
ShaderEffectSource {
|
||||
id: effect_source
|
||||
anchors.fill: parent
|
||||
@ -34,7 +33,7 @@ Item {
|
||||
}
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: "../Image/noise.png"
|
||||
source: "qrc:/qt/qml/FluentUI/Image/noise.png"
|
||||
fillMode: Image.Tile
|
||||
opacity: control.noiseOpacity
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ Rectangle{
|
||||
property string closeText : qsTr("Close")
|
||||
property string stayTopText : qsTr("Sticky on Top")
|
||||
property string stayTopCancelText : qsTr("Sticky on Top cancelled")
|
||||
property color textColor: FluTheme.dark ? "#FFFFFF" : "#000000"
|
||||
property color textColor: FluTheme.fontPrimaryColor
|
||||
property color minimizeNormalColor: FluTheme.itemNormalColor
|
||||
property color minimizeHoverColor: FluTheme.itemHoverColor
|
||||
property color minimizePressColor: FluTheme.itemPressColor
|
||||
@ -22,7 +22,7 @@ Rectangle{
|
||||
property color maximizeHoverColor: FluTheme.itemHoverColor
|
||||
property color maximizePressColor: FluTheme.itemPressColor
|
||||
property color closeNormalColor: Qt.rgba(0,0,0,0)
|
||||
property color closeHoverColor: Qt.rgba(251/255,115/255,115/255,1)
|
||||
property color closeHoverColor: Qt.rgba(251/255,115/255,115/255,1)
|
||||
property color closePressColor: Qt.rgba(251/255,115/255,115/255,0.8)
|
||||
property bool showDark: false
|
||||
property bool showClose: true
|
||||
|
@ -7,6 +7,7 @@ FluTextBox{
|
||||
property var items:[]
|
||||
property string emptyText: qsTr("No results found")
|
||||
property int autoSuggestBoxReplacement: FluentIcons.Search
|
||||
property string textRole: "title"
|
||||
property var filter: function(item){
|
||||
if(item.title.indexOf(control.text)!==-1){
|
||||
return true
|
||||
@ -25,7 +26,7 @@ FluTextBox{
|
||||
function handleClick(modelData){
|
||||
control_popup.visible = false
|
||||
control.itemClicked(modelData)
|
||||
control.updateText(modelData.title)
|
||||
control.updateText(modelData[textRole])
|
||||
}
|
||||
function loadData(){
|
||||
var result = []
|
||||
@ -48,7 +49,6 @@ FluTextBox{
|
||||
}
|
||||
Popup{
|
||||
id:control_popup
|
||||
y:control.height
|
||||
focus: false
|
||||
padding: 0
|
||||
enter: Transition {
|
||||
@ -59,14 +59,10 @@ FluTextBox{
|
||||
duration: FluTheme.animationEnabled ? 83 : 0
|
||||
}
|
||||
}
|
||||
contentItem: FluRectangle{
|
||||
radius: [4,4,4,4]
|
||||
FluShadow{
|
||||
radius: 4
|
||||
}
|
||||
color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)
|
||||
contentItem: FluClip{
|
||||
radius: [5,5,5,5]
|
||||
ListView{
|
||||
id:list_view
|
||||
id: list_view
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
boundsBehavior: ListView.StopAtBounds
|
||||
@ -76,7 +72,7 @@ FluTextBox{
|
||||
height: visible ? 38 : 0
|
||||
visible: list_view.count === 0
|
||||
FluText{
|
||||
text:emptyText
|
||||
text: emptyText
|
||||
anchors{
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
@ -85,10 +81,10 @@ FluTextBox{
|
||||
}
|
||||
}
|
||||
delegate:FluControl{
|
||||
id:item_control
|
||||
id: item_control
|
||||
height: 38
|
||||
width: control.width
|
||||
onClicked:{
|
||||
onClicked: {
|
||||
d.handleClick(modelData)
|
||||
}
|
||||
background: Rectangle{
|
||||
@ -97,14 +93,17 @@ FluTextBox{
|
||||
radius:4
|
||||
}
|
||||
color: {
|
||||
if(hovered){
|
||||
return FluTheme.dark ? Qt.rgba(63/255,60/255,61/255,1) : Qt.rgba(237/255,237/255,242/255,1)
|
||||
if(pressed){
|
||||
return FluTheme.itemPressColor
|
||||
}
|
||||
return FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(0,0,0,0)
|
||||
if(hovered){
|
||||
return FluTheme.itemHoverColor
|
||||
}
|
||||
return FluTheme.itemNormalColor
|
||||
}
|
||||
}
|
||||
contentItem: FluText{
|
||||
text:modelData.title
|
||||
text: modelData[textRole]
|
||||
leftPadding: 10
|
||||
rightPadding: 10
|
||||
verticalAlignment : Qt.AlignVCenter
|
||||
@ -112,22 +111,28 @@ FluTextBox{
|
||||
}
|
||||
}
|
||||
}
|
||||
background: Item{
|
||||
id:container
|
||||
background:Rectangle{
|
||||
id: rect_background
|
||||
implicitWidth: control.width
|
||||
implicitHeight: 38*Math.min(Math.max(list_view.count,1),8)
|
||||
radius: 5
|
||||
color: FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(1,1,1,1)
|
||||
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
|
||||
FluShadow{
|
||||
radius: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
onTextChanged: {
|
||||
d.loadData()
|
||||
if(d.flagVisible){
|
||||
var pos = control.mapToItem(null, 0, 0)
|
||||
if(d.window.height>pos.y+control.height+container.implicitHeight){
|
||||
control_popup.y = control.height
|
||||
} else if(pos.y>container.implicitHeight){
|
||||
control_popup.y = -container.implicitHeight
|
||||
if(d.window.height>pos.y+control.height+rect_background.implicitHeight){
|
||||
control_popup.y = Qt.binding(function(){return control.height})
|
||||
} else if(pos.y>rect_background.implicitHeight){
|
||||
control_popup.y = -rect_background.implicitHeight
|
||||
} else {
|
||||
control_popup.y = d.window.height-(pos.y+container.implicitHeight)
|
||||
control_popup.y = d.window.height-(pos.y+rect_background.implicitHeight) - 1
|
||||
}
|
||||
control_popup.visible = true
|
||||
}
|
||||
|
@ -57,12 +57,12 @@ Item {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
color: {
|
||||
if(item_mouse.pressed){
|
||||
return FluTheme.dark ? Qt.rgba(150/255,150/255,150/235,1) : Qt.rgba(134/255,134/255,134/235,1)
|
||||
return FluTheme.dark ? Qt.rgba(150/255,150/255,150/255,1) : Qt.rgba(134/255,134/255,134/255,1)
|
||||
}
|
||||
if(item_mouse.containsMouse){
|
||||
return FluTheme.dark ? Qt.rgba(204/255,204/255,204/235,1) : Qt.rgba(92/255,92/255,92/235,1)
|
||||
return FluTheme.dark ? Qt.rgba(204/255,204/255,204/255,1) : Qt.rgba(92/255,92/255,92/255,1)
|
||||
}
|
||||
return FluTheme.dark ? Qt.rgba(255/255,255/255,255/235,1) : Qt.rgba(26/255,26/255,26/235,1)
|
||||
return FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(26/255,26/255,26/255,1)
|
||||
}
|
||||
MouseArea{
|
||||
id:item_mouse
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,16 +13,15 @@ Button{
|
||||
property color current : Qt.rgba(1,1,1,1)
|
||||
signal accepted()
|
||||
property int colorHandleRadius: 8
|
||||
property string cancelText: "取消"
|
||||
property string okText: "确定"
|
||||
property string titleText: "颜色选择器"
|
||||
property string editText: "编辑颜色"
|
||||
property string redText: "红色"
|
||||
property string greenText: "绿色"
|
||||
property string blueText: "蓝色"
|
||||
property string opacityText: "透明度"
|
||||
background:
|
||||
Rectangle{
|
||||
property string cancelText: qsTr("Cancel")
|
||||
property string okText: qsTr("OK")
|
||||
property string titleText: qsTr("Color Picker")
|
||||
property string editText: qsTr("Edit Color")
|
||||
property string redText: qsTr("Red")
|
||||
property string greenText: qsTr("Green")
|
||||
property string blueText: qsTr("Blue")
|
||||
property string opacityText: qsTr("Opacity")
|
||||
background: Rectangle{
|
||||
id:layout_color
|
||||
radius: 5
|
||||
color:"#00000000"
|
||||
|
@ -134,10 +134,9 @@ T.ComboBox {
|
||||
}
|
||||
}
|
||||
background:Rectangle{
|
||||
color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(249/255,249/255,249/255,1)
|
||||
border.color: FluTheme.dark ? Window.active ? Qt.rgba(55/255,55/255,55/255,1):Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
|
||||
border.width: 1
|
||||
radius: 5
|
||||
color: FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(1,1,1,1)
|
||||
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
|
||||
FluShadow{
|
||||
radius: 5
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import QtQuick.Layouts 1.15
|
||||
import QtQuick.Window 2.15
|
||||
import FluentUI 1.0
|
||||
|
||||
|
||||
FluButton {
|
||||
property bool showYear: true
|
||||
property var current
|
||||
@ -96,8 +95,6 @@ FluButton {
|
||||
Menu{
|
||||
id:popup
|
||||
modal: true
|
||||
width: container.width
|
||||
height: container.height
|
||||
Overlay.modal: Item {}
|
||||
enter: Transition {
|
||||
reversible: true
|
||||
@ -116,227 +113,220 @@ FluButton {
|
||||
duration: FluTheme.animationEnabled ? 83 : 0
|
||||
}
|
||||
}
|
||||
background:Item{
|
||||
background:Rectangle{
|
||||
radius: 5
|
||||
color: FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(1,1,1,1)
|
||||
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
|
||||
FluShadow{
|
||||
radius: 4
|
||||
radius: 5
|
||||
}
|
||||
}
|
||||
contentItem: Item{
|
||||
clip: true
|
||||
Rectangle{
|
||||
id:container
|
||||
radius: 4
|
||||
width: 300
|
||||
height: 340
|
||||
color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
}
|
||||
FluShadow{
|
||||
radius: 4
|
||||
}
|
||||
RowLayout{
|
||||
id:layout_content
|
||||
spacing: 0
|
||||
width: parent.width
|
||||
height: 300
|
||||
Component{
|
||||
id:list_delegate
|
||||
Item{
|
||||
height:38
|
||||
width:getListView().width
|
||||
function getListView(){
|
||||
if(type === 0)
|
||||
return list_view_1
|
||||
if(type === 1)
|
||||
return list_view_2
|
||||
if(type === 2)
|
||||
return list_view_3
|
||||
id:container
|
||||
implicitHeight: 340
|
||||
implicitWidth: 300
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
}
|
||||
RowLayout{
|
||||
id:layout_content
|
||||
spacing: 0
|
||||
width: parent.width
|
||||
height: 280
|
||||
Component{
|
||||
id:list_delegate
|
||||
Item{
|
||||
height: 38
|
||||
width: getListView().width
|
||||
function getListView(){
|
||||
if(type === 0)
|
||||
return list_view_1
|
||||
if(type === 1)
|
||||
return list_view_2
|
||||
if(type === 2)
|
||||
return list_view_3
|
||||
}
|
||||
Rectangle{
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 2
|
||||
anchors.bottomMargin: 2
|
||||
anchors.leftMargin: 5
|
||||
anchors.rightMargin: 5
|
||||
color: {
|
||||
if(getListView().currentIndex === position){
|
||||
return item_mouse.containsMouse ? Qt.lighter(FluTheme.primaryColor,1.1): FluTheme.primaryColor
|
||||
}
|
||||
if(item_mouse.containsMouse){
|
||||
return FluTheme.dark ? Qt.rgba(63/255,60/255,61/255,1) : Qt.rgba(237/255,237/255,242/255,1)
|
||||
}
|
||||
return Qt.rgba(0,0,0,0)
|
||||
}
|
||||
Rectangle{
|
||||
radius: 3
|
||||
MouseArea{
|
||||
id:item_mouse
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 2
|
||||
anchors.bottomMargin: 2
|
||||
anchors.leftMargin: 5
|
||||
anchors.rightMargin: 5
|
||||
color: {
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
getListView().currentIndex = position
|
||||
if(type === 0){
|
||||
text_year.text = model
|
||||
list_view_2.model = generateMonthArray(1,12)
|
||||
text_month.text = list_view_2.model[list_view_2.currentIndex]
|
||||
|
||||
list_view_3.model = generateMonthDaysArray(list_view_1.model[list_view_1.currentIndex],list_view_2.model[list_view_2.currentIndex])
|
||||
text_day.text = list_view_3.model[list_view_3.currentIndex]
|
||||
}
|
||||
if(type === 1){
|
||||
text_month.text = model
|
||||
list_view_3.model = generateMonthDaysArray(list_view_1.model[list_view_1.currentIndex],list_view_2.model[list_view_2.currentIndex])
|
||||
text_day.text = list_view_3.model[list_view_3.currentIndex]
|
||||
|
||||
}
|
||||
if(type === 2){
|
||||
text_day.text = model
|
||||
}
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
text:model
|
||||
color: {
|
||||
if(getListView().currentIndex === position){
|
||||
return item_mouse.containsMouse ? Qt.lighter(FluTheme.primaryColor,1.1): FluTheme.primaryColor
|
||||
}
|
||||
if(item_mouse.containsMouse){
|
||||
return FluTheme.dark ? Qt.rgba(63/255,60/255,61/255,1) : Qt.rgba(237/255,237/255,242/255,1)
|
||||
}
|
||||
return FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(0,0,0,0)
|
||||
}
|
||||
radius: 3
|
||||
MouseArea{
|
||||
id:item_mouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
getListView().currentIndex = position
|
||||
if(type === 0){
|
||||
text_year.text = model
|
||||
list_view_2.model = generateMonthArray(1,12)
|
||||
text_month.text = list_view_2.model[list_view_2.currentIndex]
|
||||
|
||||
list_view_3.model = generateMonthDaysArray(list_view_1.model[list_view_1.currentIndex],list_view_2.model[list_view_2.currentIndex])
|
||||
text_day.text = list_view_3.model[list_view_3.currentIndex]
|
||||
}
|
||||
if(type === 1){
|
||||
text_month.text = model
|
||||
list_view_3.model = generateMonthDaysArray(list_view_1.model[list_view_1.currentIndex],list_view_2.model[list_view_2.currentIndex])
|
||||
text_day.text = list_view_3.model[list_view_3.currentIndex]
|
||||
|
||||
}
|
||||
if(type === 2){
|
||||
text_day.text = model
|
||||
}
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
text:model
|
||||
color: {
|
||||
if(getListView().currentIndex === position){
|
||||
if(FluTheme.dark){
|
||||
return Qt.rgba(0,0,0,1)
|
||||
}else{
|
||||
return Qt.rgba(1,1,1,1)
|
||||
}
|
||||
if(FluTheme.dark){
|
||||
return Qt.rgba(0,0,0,1)
|
||||
}else{
|
||||
return FluTheme.dark ? "#FFFFFF" : "#1A1A1A"
|
||||
return Qt.rgba(1,1,1,1)
|
||||
}
|
||||
}else{
|
||||
return FluTheme.dark ? "#FFFFFF" : "#1A1A1A"
|
||||
}
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
ListView{
|
||||
id:list_view_1
|
||||
width: 100
|
||||
height: parent.height
|
||||
boundsBehavior:Flickable.StopAtBounds
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
model: generateYearArray(1924,2048)
|
||||
clip: true
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
visible: showYear
|
||||
delegate: FluLoader{
|
||||
property var model: modelData
|
||||
property int type:0
|
||||
property int position:index
|
||||
sourceComponent: list_delegate
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
width: 1
|
||||
height: parent.height
|
||||
color: control.dividerColor
|
||||
}
|
||||
ListView{
|
||||
id:list_view_2
|
||||
width: showYear ? 100 : 150
|
||||
height: parent.height
|
||||
clip: true
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
boundsBehavior:Flickable.StopAtBounds
|
||||
delegate: FluLoader{
|
||||
property var model: modelData
|
||||
property int type:1
|
||||
property int position:index
|
||||
sourceComponent: list_delegate
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
width: 1
|
||||
height: parent.height
|
||||
color: control.dividerColor
|
||||
}
|
||||
ListView{
|
||||
id:list_view_3
|
||||
width: showYear ? 100 : 150
|
||||
height: parent.height
|
||||
clip: true
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
boundsBehavior:Flickable.StopAtBounds
|
||||
delegate: FluLoader{
|
||||
property var model: modelData
|
||||
property int type:2
|
||||
property int position:index
|
||||
sourceComponent: list_delegate
|
||||
}
|
||||
}
|
||||
ListView{
|
||||
id:list_view_1
|
||||
Layout.preferredWidth: 100
|
||||
Layout.preferredHeight: parent.height - 2
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
boundsBehavior:Flickable.StopAtBounds
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
model: generateYearArray(1924,2048)
|
||||
clip: true
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
visible: showYear
|
||||
delegate: FluLoader{
|
||||
property var model: modelData
|
||||
property int type:0
|
||||
property int position:index
|
||||
sourceComponent: list_delegate
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
width: parent.width
|
||||
height: 1
|
||||
anchors.top: layout_content.bottom
|
||||
Layout.preferredWidth: 1
|
||||
Layout.preferredHeight: parent.height
|
||||
color: control.dividerColor
|
||||
visible: showYear
|
||||
}
|
||||
ListView{
|
||||
id:list_view_2
|
||||
Layout.preferredWidth: showYear ? 99 : 150
|
||||
Layout.preferredHeight: parent.height - 2
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
clip: true
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
boundsBehavior:Flickable.StopAtBounds
|
||||
delegate: FluLoader{
|
||||
property var model: modelData
|
||||
property int type:1
|
||||
property int position:index
|
||||
sourceComponent: list_delegate
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
Layout.preferredWidth: 1
|
||||
Layout.preferredHeight: parent.height
|
||||
color: control.dividerColor
|
||||
}
|
||||
Rectangle{
|
||||
id:layout_actions
|
||||
height: 40
|
||||
radius: 5
|
||||
color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
|
||||
ListView{
|
||||
id:list_view_3
|
||||
Layout.preferredWidth: showYear ? 99 : 150
|
||||
Layout.preferredHeight: parent.height - 2
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
clip: true
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
boundsBehavior:Flickable.StopAtBounds
|
||||
delegate: FluLoader{
|
||||
property var model: modelData
|
||||
property int type:2
|
||||
property int position:index
|
||||
sourceComponent: list_delegate
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
id:layout_actions
|
||||
height: 60
|
||||
color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
|
||||
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
|
||||
radius: 5
|
||||
anchors{
|
||||
bottom:parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
Item {
|
||||
id:divider
|
||||
width: 1
|
||||
height: parent.height
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
FluButton{
|
||||
anchors{
|
||||
bottom:parent.bottom
|
||||
left: parent.left
|
||||
leftMargin: 20
|
||||
rightMargin: 10
|
||||
right: divider.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
text: control.cancelText
|
||||
onClicked: {
|
||||
popup.close()
|
||||
}
|
||||
}
|
||||
FluFilledButton{
|
||||
anchors{
|
||||
right: parent.right
|
||||
left: divider.right
|
||||
rightMargin: 20
|
||||
leftMargin: 10
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Item {
|
||||
id:divider
|
||||
width: 1
|
||||
height: parent.height
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
FluButton{
|
||||
anchors{
|
||||
left: parent.left
|
||||
leftMargin: 20
|
||||
rightMargin: 10
|
||||
right: divider.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
text: control.cancelText
|
||||
onClicked: {
|
||||
popup.close()
|
||||
}
|
||||
}
|
||||
FluFilledButton{
|
||||
anchors{
|
||||
right: parent.right
|
||||
left: divider.right
|
||||
rightMargin: 20
|
||||
leftMargin: 10
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
text: control.okText
|
||||
onClicked: {
|
||||
d.changeFlag = false
|
||||
popup.close()
|
||||
const year = text_year.text
|
||||
const month = text_month.text
|
||||
const day = text_day.text
|
||||
const date = new Date()
|
||||
date.setFullYear(parseInt(year));
|
||||
date.setMonth(parseInt(month) - 1);
|
||||
date.setDate(parseInt(day));
|
||||
date.setHours(0);
|
||||
date.setMinutes(0);
|
||||
date.setSeconds(0);
|
||||
current = date
|
||||
control.accepted()
|
||||
}
|
||||
text: control.okText
|
||||
onClicked: {
|
||||
d.changeFlag = false
|
||||
popup.close()
|
||||
const year = text_year.text
|
||||
const month = text_month.text
|
||||
const day = text_day.text
|
||||
const date = new Date()
|
||||
date.setFullYear(parseInt(year));
|
||||
date.setMonth(parseInt(month) - 1);
|
||||
date.setDate(parseInt(day));
|
||||
date.setHours(0);
|
||||
date.setMinutes(0);
|
||||
date.setSeconds(0);
|
||||
current = date
|
||||
control.accepted()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -361,7 +351,7 @@ FluButton {
|
||||
text_day.text = day
|
||||
var pos = control.mapToItem(null, 0, 0)
|
||||
if(d.window.height>pos.y+control.height+container.height){
|
||||
popup.y = control.height
|
||||
popup.y = control.height-1
|
||||
} else if(pos.y>container.height){
|
||||
popup.y = -container.height
|
||||
} else {
|
||||
|
@ -19,16 +19,20 @@ FluButton {
|
||||
}
|
||||
iconColor:control.textColor
|
||||
}
|
||||
Item{
|
||||
id: d
|
||||
property var window: Window.window
|
||||
}
|
||||
onClicked: {
|
||||
if(menu.count !==0){
|
||||
var pos = control.mapToItem(null, 0, 0)
|
||||
var containerHeight = menu.count*36
|
||||
if(window.height>pos.y+control.height+containerHeight){
|
||||
if(d.window.height>pos.y+control.height+containerHeight){
|
||||
menu.y = control.height
|
||||
}else if(pos.y>containerHeight){
|
||||
menu.y = -containerHeight
|
||||
}else{
|
||||
menu.y = window.height-(pos.y+containerHeight)
|
||||
menu.y = d.window.height-(pos.y+containerHeight)
|
||||
}
|
||||
menu.open()
|
||||
}
|
||||
|
@ -27,7 +27,12 @@ Item {
|
||||
height: 45
|
||||
radius: 4
|
||||
border.color: FluTheme.dividerColor
|
||||
color: FluTheme.dark ? Window.active ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
|
||||
color: {
|
||||
if(Window.active){
|
||||
return FluTheme.frameActiveColor
|
||||
}
|
||||
return FluTheme.frameColor
|
||||
}
|
||||
MouseArea{
|
||||
id:control_mouse
|
||||
anchors.fill: parent
|
||||
@ -84,12 +89,18 @@ Item {
|
||||
height: contentHeight+container.anchors.topMargin
|
||||
width: parent.width
|
||||
z:-999
|
||||
clip: true
|
||||
Rectangle{
|
||||
id:container
|
||||
anchors.fill: parent
|
||||
radius: 4
|
||||
clip: true
|
||||
color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
|
||||
color: {
|
||||
if(Window.active){
|
||||
return FluTheme.frameActiveColor
|
||||
}
|
||||
return FluTheme.frameColor
|
||||
}
|
||||
border.color: FluTheme.dividerColor
|
||||
anchors.topMargin: -contentHeight
|
||||
states: [
|
||||
|
@ -19,6 +19,11 @@ T.Frame {
|
||||
id:d
|
||||
radius: 4
|
||||
border.color: FluTheme.dividerColor
|
||||
color: FluTheme.dark ? Window.active ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(251/255,251/255,253/255,1)
|
||||
color: {
|
||||
if(Window.active){
|
||||
return FluTheme.frameActiveColor
|
||||
}
|
||||
return FluTheme.frameColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,13 @@ import FluentUI 1.0
|
||||
T.GroupBox {
|
||||
id: control
|
||||
property int borderWidth : 1
|
||||
property color borderColor : FluTheme.dark ? Window.active ? Qt.rgba(55/255,55/255,55/255,1):Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
|
||||
property color color: FluTheme.dark ? Window.active ? Qt.rgba(38/255,44/255,54/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
|
||||
property color borderColor : FluTheme.dividerColor
|
||||
property color color: {
|
||||
if(Window.active){
|
||||
return FluTheme.frameActiveColor
|
||||
}
|
||||
return FluTheme.frameColor
|
||||
}
|
||||
property int radius: 4
|
||||
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
|
||||
contentWidth + leftPadding + rightPadding,
|
||||
|
@ -7,13 +7,15 @@ Text {
|
||||
property int iconSize: 20
|
||||
property color iconColor: FluTheme.dark ? "#FFFFFF" : "#000000"
|
||||
id:control
|
||||
font.family: "Segoe Fluent Icons"
|
||||
font.family: font_loader.name
|
||||
font.pixelSize: iconSize
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: iconColor
|
||||
text: (String.fromCharCode(iconSource).toString(16))
|
||||
opacity: iconSource>0
|
||||
FontLoader{
|
||||
source: "../Font/Segoe_Fluent_Icons.ttf"
|
||||
id: font_loader
|
||||
source: "qrc:/qt/qml/FluentUI/Font/FluentIcons.ttf"
|
||||
}
|
||||
}
|
||||
|
@ -18,22 +18,23 @@ FluObject {
|
||||
if(screenLayout){
|
||||
var last = screenLayout.getLastloader();
|
||||
if(last.type === type && last.text === text && moremsg === last.moremsg){
|
||||
last.restart();
|
||||
return;
|
||||
last.duration = duration
|
||||
if (duration > 0) last.restart();
|
||||
return last;
|
||||
}
|
||||
}
|
||||
initScreenLayout();
|
||||
contentComponent.createObject(screenLayout,{
|
||||
type:type,
|
||||
text:text,
|
||||
duration:duration,
|
||||
moremsg:moremsg,
|
||||
});
|
||||
return contentComponent.createObject(screenLayout,{
|
||||
type:type,
|
||||
text:text,
|
||||
duration:duration,
|
||||
moremsg:moremsg,
|
||||
});
|
||||
}
|
||||
function createCustom(itemcomponent,duration){
|
||||
initScreenLayout();
|
||||
if(itemcomponent){
|
||||
contentComponent.createObject(screenLayout,{itemcomponent:itemcomponent,duration:duration});
|
||||
return contentComponent.createObject(screenLayout,{itemcomponent:itemcomponent,duration:duration});
|
||||
}
|
||||
}
|
||||
function initScreenLayout(){
|
||||
@ -85,7 +86,9 @@ FluObject {
|
||||
}
|
||||
Timer {
|
||||
id:delayTimer
|
||||
interval: duration; running: duration > 0; repeat: duration > 0
|
||||
interval: duration;
|
||||
running: duration > 0;
|
||||
repeat: duration > 0
|
||||
onTriggered: content.close();
|
||||
}
|
||||
FluLoader{
|
||||
@ -235,18 +238,26 @@ FluObject {
|
||||
}
|
||||
}
|
||||
function showSuccess(text,duration=1000,moremsg){
|
||||
mcontrol.create(mcontrol.const_success,text,duration,moremsg ? moremsg : "");
|
||||
return mcontrol.create(mcontrol.const_success,text,duration,moremsg ? moremsg : "");
|
||||
}
|
||||
function showInfo(text,duration=1000,moremsg){
|
||||
mcontrol.create(mcontrol.const_info,text,duration,moremsg ? moremsg : "");
|
||||
return mcontrol.create(mcontrol.const_info,text,duration,moremsg ? moremsg : "");
|
||||
}
|
||||
function showWarning(text,duration=1000,moremsg){
|
||||
mcontrol.create(mcontrol.const_warning,text,duration,moremsg ? moremsg : "");
|
||||
return mcontrol.create(mcontrol.const_warning,text,duration,moremsg ? moremsg : "");
|
||||
}
|
||||
function showError(text,duration=1000,moremsg){
|
||||
mcontrol.create(mcontrol.const_error,text,duration,moremsg ? moremsg : "");
|
||||
return mcontrol.create(mcontrol.const_error,text,duration,moremsg ? moremsg : "");
|
||||
}
|
||||
function showCustom(itemcomponent,duration=1000){
|
||||
mcontrol.createCustom(itemcomponent,duration);
|
||||
return mcontrol.createCustom(itemcomponent,duration);
|
||||
}
|
||||
function clearAllInfo(){
|
||||
if(mcontrol.screenLayout != null) {
|
||||
mcontrol.screenLayout.destroy()
|
||||
mcontrol.screenLayout = null
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -44,8 +44,8 @@ T.Menu {
|
||||
background: Rectangle {
|
||||
implicitWidth: 150
|
||||
implicitHeight: 36
|
||||
color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(240/255,240/255,240/255,1)
|
||||
border.color: FluTheme.dark ? Window.active ? Qt.rgba(55/255,55/255,55/255,1):Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
|
||||
color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(252/255,252/255,252/255,1)
|
||||
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
|
||||
border.width: 1
|
||||
radius: 5
|
||||
FluShadow{}
|
||||
|
@ -1,100 +1,112 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import FluentUI 1.0
|
||||
|
||||
Item {
|
||||
signal requestPage(int page,int count)
|
||||
property string previousText: qsTr("<Previous")
|
||||
property string nextText: qsTr("Next>")
|
||||
property int pageCurrent: 0
|
||||
property int itemCount: 0
|
||||
property int pageButtonCount: 5
|
||||
property int pageCount: itemCount>0?Math.ceil(itemCount/__itemPerPage):0
|
||||
property int __itemPerPage: 10
|
||||
property int __pageButtonHalf: Math.floor(pageButtonCount/2)+1
|
||||
id: control
|
||||
implicitHeight: 40
|
||||
implicitWidth: content.width
|
||||
Row{
|
||||
id: content
|
||||
height: control.height
|
||||
spacing: 10
|
||||
padding: 10
|
||||
FluToggleButton{
|
||||
visible: control.pageCount>1
|
||||
disabled: control.pageCurrent<=1
|
||||
text:control.previousText
|
||||
clickListener:function() {
|
||||
control.calcNewPage(control.pageCurrent-1);
|
||||
}
|
||||
}
|
||||
Row{
|
||||
spacing: 5
|
||||
FluToggleButton{
|
||||
property int pageNumber:1
|
||||
visible: control.pageCount>0
|
||||
checked: pageNumber === control.pageCurrent
|
||||
text:String(pageNumber)
|
||||
clickListener:function() {
|
||||
control.calcNewPage(pageNumber);
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
visible: (control.pageCount>control.pageButtonCount&&
|
||||
control.pageCurrent>control.__pageButtonHalf)
|
||||
text: "..."
|
||||
}
|
||||
Repeater{
|
||||
id: button_repeator
|
||||
model: (control.pageCount<2)?0:(control.pageCount>=control.pageButtonCount)?(control.pageButtonCount-2):(control.pageCount-2)
|
||||
delegate:FluToggleButton{
|
||||
property int pageNumber: {
|
||||
return (control.pageCurrent<=control.__pageButtonHalf)
|
||||
?(2+index)
|
||||
:(control.pageCount-control.pageCurrent<=control.pageButtonCount-control.__pageButtonHalf)
|
||||
?(control.pageCount-button_repeator.count+index)
|
||||
:(control.pageCurrent+2+index-control.__pageButtonHalf)
|
||||
}
|
||||
text:String(pageNumber)
|
||||
checked: pageNumber === control.pageCurrent
|
||||
clickListener:function(){
|
||||
control.calcNewPage(pageNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
visible: (control.pageCount>control.pageButtonCount&&
|
||||
control.pageCount-control.pageCurrent>control.pageButtonCount-control.__pageButtonHalf)
|
||||
text: "..."
|
||||
}
|
||||
FluToggleButton{
|
||||
property int pageNumber:control.pageCount
|
||||
visible: control.pageCount>1
|
||||
checked: pageNumber === control.pageCurrent
|
||||
text:String(pageNumber)
|
||||
clickListener:function(){
|
||||
control.calcNewPage(pageNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
FluToggleButton{
|
||||
visible: control.pageCount>1
|
||||
disabled: control.pageCurrent>=control.pageCount
|
||||
text:control.nextText
|
||||
clickListener:function() {
|
||||
control.calcNewPage(control.pageCurrent+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
function calcNewPage(page)
|
||||
{
|
||||
if(!page)
|
||||
return
|
||||
let page_num=Number(page)
|
||||
if(page_num<1||page_num>control.pageCount||page_num===control.pageCurrent)
|
||||
return
|
||||
control.pageCurrent=page_num
|
||||
control.requestPage(page_num,control.__itemPerPage)
|
||||
}
|
||||
}
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import FluentUI 1.0
|
||||
|
||||
|
||||
Item {
|
||||
signal requestPage(int page, int count)
|
||||
|
||||
property string previousText: qsTr("<Previous")
|
||||
property string nextText: qsTr("Next>")
|
||||
property int pageCurrent: 0
|
||||
property int itemCount: 0
|
||||
property int pageButtonCount: 5
|
||||
property int pageCount: itemCount > 0 ? Math.ceil(itemCount / __itemPerPage) : 0
|
||||
property int __itemPerPage: 10
|
||||
property int __pageButtonHalf: Math.floor(pageButtonCount / 2) + 1
|
||||
property Component header: null
|
||||
property Component footer: null
|
||||
id: control
|
||||
implicitHeight: 40
|
||||
implicitWidth: content.width
|
||||
Row {
|
||||
id: content
|
||||
height: control.height
|
||||
spacing: 10
|
||||
padding: 10
|
||||
Loader {
|
||||
sourceComponent: header
|
||||
}
|
||||
FluToggleButton {
|
||||
visible: control.pageCount > 1
|
||||
disabled: control.pageCurrent <= 1
|
||||
text: control.previousText
|
||||
clickListener: function () {
|
||||
control.calcNewPage(control.pageCurrent - 1);
|
||||
}
|
||||
}
|
||||
Row {
|
||||
spacing: 5
|
||||
|
||||
FluToggleButton {
|
||||
property int pageNumber: 1
|
||||
visible: control.pageCount > 0
|
||||
checked: pageNumber === control.pageCurrent
|
||||
text: String(pageNumber)
|
||||
clickListener: function () {
|
||||
control.calcNewPage(pageNumber);
|
||||
}
|
||||
}
|
||||
FluText {
|
||||
visible: (control.pageCount > control.pageButtonCount &&
|
||||
control.pageCurrent > control.__pageButtonHalf)
|
||||
text: "..."
|
||||
}
|
||||
Repeater {
|
||||
id: button_repeator
|
||||
model: (control.pageCount < 2) ? 0 : (control.pageCount >= control.pageButtonCount) ? (control.pageButtonCount - 2) : (control.pageCount - 2)
|
||||
delegate: FluToggleButton {
|
||||
property int pageNumber: {
|
||||
return (control.pageCurrent <= control.__pageButtonHalf)
|
||||
? (2 + index)
|
||||
: (control.pageCount - control.pageCurrent <= control.pageButtonCount - control.__pageButtonHalf)
|
||||
? (control.pageCount - button_repeator.count + index)
|
||||
: (control.pageCurrent + 2 + index - control.__pageButtonHalf)
|
||||
}
|
||||
text: String(pageNumber)
|
||||
checked: pageNumber === control.pageCurrent
|
||||
clickListener: function () {
|
||||
control.calcNewPage(pageNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
FluText {
|
||||
visible: (control.pageCount > control.pageButtonCount &&
|
||||
control.pageCount - control.pageCurrent > control.pageButtonCount - control.__pageButtonHalf)
|
||||
text: "..."
|
||||
}
|
||||
FluToggleButton {
|
||||
property int pageNumber: control.pageCount
|
||||
visible: control.pageCount > 1
|
||||
checked: pageNumber === control.pageCurrent
|
||||
text: String(pageNumber)
|
||||
clickListener: function () {
|
||||
control.calcNewPage(pageNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
FluToggleButton {
|
||||
visible: control.pageCount > 1
|
||||
disabled: control.pageCurrent >= control.pageCount
|
||||
text: control.nextText
|
||||
clickListener: function () {
|
||||
control.calcNewPage(control.pageCurrent + 1);
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
sourceComponent: footer
|
||||
}
|
||||
}
|
||||
|
||||
function calcNewPage(page) {
|
||||
if (!page)
|
||||
return
|
||||
let page_num = Number(page)
|
||||
if (page_num < 1 || page_num > control.pageCount || page_num === control.pageCurrent)
|
||||
return
|
||||
control.pageCurrent = page_num
|
||||
control.requestPage(page_num, control.__itemPerPage)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ T.SpinBox {
|
||||
bottom: Math.min(control.from, control.to)
|
||||
top: Math.max(control.from, control.to)
|
||||
}
|
||||
font: FluTextStyle.Body
|
||||
|
||||
contentItem: TextInput {
|
||||
property color normalColor: FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1)
|
||||
|
@ -8,11 +8,11 @@ Item{
|
||||
id:control
|
||||
default property alias content: container.data
|
||||
property int statusMode: FluStatusLayoutType.Loading
|
||||
property string loadingText:"正在加载..."
|
||||
property string emptyText: "空空如也"
|
||||
property string errorText: "页面出错了.."
|
||||
property string errorButtonText: "重新加载"
|
||||
property color color: FluTheme.dark ? Window.active ? Qt.rgba(38/255,44/255,54/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
|
||||
property string loadingText: qsTr("Loading...")
|
||||
property string emptyText: qsTr("Empty")
|
||||
property string errorText: qsTr("Error")
|
||||
property string errorButtonText: qsTr("Reload")
|
||||
property color color: Qt.rgba(0,0,0,0)
|
||||
signal errorClicked
|
||||
property Component loadingItem : com_loading
|
||||
property Component emptyItem : com_empty
|
||||
|
@ -1,4 +1,5 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Window 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import Qt.labs.qmlmodels 1.0
|
||||
@ -17,7 +18,12 @@ Rectangle {
|
||||
property color selectedBorderColor: FluTheme.primaryColor
|
||||
property color selectedColor: FluTools.withOpacity(FluTheme.primaryColor,0.3)
|
||||
id:control
|
||||
color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
|
||||
color: {
|
||||
if(Window.active){
|
||||
return FluTheme.frameActiveColor
|
||||
}
|
||||
return FluTheme.frameColor
|
||||
}
|
||||
onColumnSourceChanged: {
|
||||
if(columnSource.length!==0){
|
||||
var columns= []
|
||||
@ -90,7 +96,7 @@ Rectangle {
|
||||
if(!readOnly){
|
||||
editTextChaged(text_box.text)
|
||||
}
|
||||
tableView.closeEditor()
|
||||
control.closeEditor()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -119,7 +125,7 @@ Rectangle {
|
||||
if(!readOnly){
|
||||
editTextChaged(text_box.text)
|
||||
}
|
||||
tableView.closeEditor()
|
||||
control.closeEditor()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -190,6 +196,11 @@ Rectangle {
|
||||
id:com_table_delegate
|
||||
MouseArea{
|
||||
id:item_table_mouse
|
||||
TableView.onPooled: {
|
||||
if(d.editPosition && d.editPosition.row === row && d.editPosition.column === column){
|
||||
control.closeEditor()
|
||||
}
|
||||
}
|
||||
property var rowObject : control.getRow(row)
|
||||
property var itemModel: model
|
||||
property bool editVisible: {
|
||||
@ -258,7 +269,7 @@ Rectangle {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onPressed:{
|
||||
closeEditor()
|
||||
control.closeEditor()
|
||||
}
|
||||
onCanceled: {
|
||||
}
|
||||
@ -268,14 +279,14 @@ Rectangle {
|
||||
if(typeof(display) == "object"){
|
||||
return
|
||||
}
|
||||
loader_edit.display = display
|
||||
d.editDelegate = d.getEditDelegate(column)
|
||||
updateEditPosition()
|
||||
loader_edit.display = display
|
||||
}
|
||||
onClicked:
|
||||
(event)=>{
|
||||
d.current = rowObject
|
||||
closeEditor()
|
||||
control.closeEditor()
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
@ -381,6 +392,7 @@ Rectangle {
|
||||
clip: true
|
||||
onRowsChanged: {
|
||||
control.closeEditor()
|
||||
table_view.flick(0,1)
|
||||
}
|
||||
delegate: com_table_delegate
|
||||
FluLoader{
|
||||
@ -771,9 +783,9 @@ Rectangle {
|
||||
timer_vertical_force_layout.restart()
|
||||
}
|
||||
Connections{
|
||||
target: table_model
|
||||
function onRowCountChanged(){
|
||||
header_row_model.rows = Array.from({length: table_model.rows.length}, (_, i) => ({rowIndex:i+1}))
|
||||
target: table_view
|
||||
function onRowsChanged(){
|
||||
header_row_model.rows = Array.from({length: table_view.rows}, (_, i) => ({rowIndex:i+1}))
|
||||
}
|
||||
}
|
||||
Timer{
|
||||
|
@ -21,19 +21,29 @@ FluControlBackground{
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: d.startColor }
|
||||
GradientStop { position: 1 - d.offsetSize/control.height; color: d.startColor }
|
||||
GradientStop { position: 1 - 1/control.height; color: d.endColor }
|
||||
GradientStop { position: 1.0; color: d.endColor }
|
||||
}
|
||||
bottomMargin: inputItem && inputItem.activeFocus ? 2 : 1
|
||||
bottomMargin: 1
|
||||
QtObject{
|
||||
id:d
|
||||
property int offsetSize : inputItem && inputItem.activeFocus ? 2 : 3
|
||||
property color startColor: FluTheme.dark ? Qt.rgba(66/255,66/255,66/255,1) : Qt.rgba(232/255,232/255,232/255,1)
|
||||
property int offsetSize : 3
|
||||
property color startColor : FluTheme.dark ? Qt.rgba(66/255,66/255,66/255,1) : Qt.rgba(232/255,232/255,232/255,1)
|
||||
property color endColor: {
|
||||
if(!control.enabled){
|
||||
return d.startColor
|
||||
}
|
||||
return inputItem && inputItem.activeFocus ? FluTheme.primaryColor : FluTheme.dark ? Qt.rgba(123/255,123/255,123/255,1) : Qt.rgba(132/255,132/255,132/255,1)
|
||||
return FluTheme.dark ? Qt.rgba(123/255,123/255,123/255,1) : Qt.rgba(132/255,132/255,132/255,1)
|
||||
}
|
||||
}
|
||||
FluClip{
|
||||
anchors.fill: parent
|
||||
radius: [control.radius,control.radius,control.radius,control.radius]
|
||||
visible: inputItem && inputItem.activeFocus
|
||||
Rectangle{
|
||||
width: parent.width
|
||||
height: 2
|
||||
anchors.bottom: parent.bottom
|
||||
color: FluTheme.primaryColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,8 +111,6 @@ FluButton {
|
||||
}
|
||||
Menu{
|
||||
id:popup
|
||||
width: container.width
|
||||
height: container.height
|
||||
modal: true
|
||||
Overlay.modal: Item {}
|
||||
enter: Transition {
|
||||
@ -132,224 +130,219 @@ FluButton {
|
||||
duration: FluTheme.animationEnabled ? 83 : 0
|
||||
}
|
||||
}
|
||||
background:Item{
|
||||
background:Rectangle{
|
||||
radius: 5
|
||||
color: FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(1,1,1,1)
|
||||
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
|
||||
FluShadow{
|
||||
radius: 4
|
||||
radius: 5
|
||||
}
|
||||
}
|
||||
contentItem: Item{
|
||||
clip: true
|
||||
Rectangle{
|
||||
id:container
|
||||
height: 340
|
||||
width: 300
|
||||
radius: 4
|
||||
color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
}
|
||||
RowLayout{
|
||||
id:layout_content
|
||||
spacing: 0
|
||||
width: parent.width
|
||||
height: 300
|
||||
Component{
|
||||
id:list_delegate
|
||||
Item{
|
||||
height:38
|
||||
width:getListView().width
|
||||
function getListView(){
|
||||
if(type === 0)
|
||||
return list_view_1
|
||||
if(type === 1)
|
||||
return list_view_2
|
||||
if(type === 2)
|
||||
return list_view_3
|
||||
id:container
|
||||
implicitHeight: 340
|
||||
implicitWidth: 300
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
}
|
||||
RowLayout{
|
||||
id:layout_content
|
||||
spacing: 0
|
||||
width: parent.width
|
||||
height: 280
|
||||
Component{
|
||||
id:list_delegate
|
||||
Item{
|
||||
height:38
|
||||
width:getListView().width
|
||||
function getListView(){
|
||||
if(type === 0)
|
||||
return list_view_1
|
||||
if(type === 1)
|
||||
return list_view_2
|
||||
if(type === 2)
|
||||
return list_view_3
|
||||
}
|
||||
Rectangle{
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 2
|
||||
anchors.bottomMargin: 2
|
||||
anchors.leftMargin: 5
|
||||
anchors.rightMargin: 5
|
||||
color: {
|
||||
if(getListView().currentIndex === position){
|
||||
return item_mouse.containsMouse ? Qt.darker(FluTheme.primaryColor,1.1) : FluTheme.primaryColor
|
||||
}
|
||||
if(item_mouse.containsMouse){
|
||||
return FluTheme.dark ? Qt.rgba(63/255,60/255,61/255,1) : Qt.rgba(237/255,237/255,242/255,1)
|
||||
}
|
||||
return Qt.rgba(0,0,0,0)
|
||||
}
|
||||
Rectangle{
|
||||
radius: 3
|
||||
MouseArea{
|
||||
id:item_mouse
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 2
|
||||
anchors.bottomMargin: 2
|
||||
anchors.leftMargin: 5
|
||||
anchors.rightMargin: 5
|
||||
color: {
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
getListView().currentIndex = position
|
||||
if(type === 0){
|
||||
text_hour.text = model
|
||||
}
|
||||
if(type === 1){
|
||||
text_minute.text = model
|
||||
}
|
||||
if(type === 2){
|
||||
text_ampm.text = model
|
||||
}
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
text:model
|
||||
color: {
|
||||
if(getListView().currentIndex === position){
|
||||
return item_mouse.containsMouse ? Qt.darker(FluTheme.primaryColor,1.1) : FluTheme.primaryColor
|
||||
}
|
||||
if(item_mouse.containsMouse){
|
||||
return FluTheme.dark ? Qt.rgba(63/255,60/255,61/255,1) : Qt.rgba(237/255,237/255,242/255,1)
|
||||
}
|
||||
return FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(0,0,0,0)
|
||||
}
|
||||
radius: 3
|
||||
MouseArea{
|
||||
id:item_mouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
getListView().currentIndex = position
|
||||
if(type === 0){
|
||||
text_hour.text = model
|
||||
}
|
||||
if(type === 1){
|
||||
text_minute.text = model
|
||||
}
|
||||
if(type === 2){
|
||||
text_ampm.text = model
|
||||
}
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
text:model
|
||||
color: {
|
||||
if(getListView().currentIndex === position){
|
||||
if(FluTheme.dark){
|
||||
return Qt.rgba(0,0,0,1)
|
||||
}else{
|
||||
return Qt.rgba(1,1,1,1)
|
||||
}
|
||||
if(FluTheme.dark){
|
||||
return Qt.rgba(0,0,0,1)
|
||||
}else{
|
||||
return FluTheme.dark ? "#FFFFFF" : "#1A1A1A"
|
||||
return Qt.rgba(1,1,1,1)
|
||||
}
|
||||
}else{
|
||||
return FluTheme.dark ? "#FFFFFF" : "#1A1A1A"
|
||||
}
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
ListView{
|
||||
id:list_view_1
|
||||
width: isH ? 100 : 150
|
||||
height: parent.height
|
||||
boundsBehavior:Flickable.StopAtBounds
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
model: isH ? generateArray(1,12) : generateArray(0,23)
|
||||
clip: true
|
||||
delegate: FluLoader{
|
||||
property var model: modelData
|
||||
property int type:0
|
||||
property int position:index
|
||||
sourceComponent: list_delegate
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
width: 1
|
||||
height: parent.height
|
||||
color: control.dividerColor
|
||||
}
|
||||
ListView{
|
||||
id:list_view_2
|
||||
width: isH ? 100 : 150
|
||||
height: parent.height
|
||||
model: generateArray(0,59)
|
||||
clip: true
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
boundsBehavior:Flickable.StopAtBounds
|
||||
delegate: FluLoader{
|
||||
property var model: modelData
|
||||
property int type:1
|
||||
property int position:index
|
||||
sourceComponent: list_delegate
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
width: 1
|
||||
height: parent.height
|
||||
color: control.dividerColor
|
||||
visible: isH
|
||||
}
|
||||
ListView{
|
||||
id:list_view_3
|
||||
width: 100
|
||||
height: 76
|
||||
model: [control.amText,control.pmText]
|
||||
clip: true
|
||||
visible: isH
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
boundsBehavior:Flickable.StopAtBounds
|
||||
delegate: FluLoader{
|
||||
property var model: modelData
|
||||
property int type:2
|
||||
property int position:index
|
||||
sourceComponent: list_delegate
|
||||
}
|
||||
}
|
||||
ListView{
|
||||
id:list_view_1
|
||||
Layout.preferredWidth: isH ? 100 : 150
|
||||
Layout.preferredHeight: parent.height-2
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
boundsBehavior:Flickable.StopAtBounds
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
model: isH ? generateArray(1,12) : generateArray(0,23)
|
||||
clip: true
|
||||
delegate: FluLoader{
|
||||
property var model: modelData
|
||||
property int type:0
|
||||
property int position:index
|
||||
sourceComponent: list_delegate
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
width: parent.width
|
||||
height: 1
|
||||
anchors.top: layout_content.bottom
|
||||
Layout.preferredWidth: 1
|
||||
Layout.preferredHeight: parent.height
|
||||
color: control.dividerColor
|
||||
}
|
||||
ListView{
|
||||
id:list_view_2
|
||||
Layout.preferredWidth: isH ? 99 : 150
|
||||
Layout.preferredHeight: parent.height-2
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
model: generateArray(0,59)
|
||||
clip: true
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
boundsBehavior:Flickable.StopAtBounds
|
||||
delegate: FluLoader{
|
||||
property var model: modelData
|
||||
property int type:1
|
||||
property int position:index
|
||||
sourceComponent: list_delegate
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
id:layout_actions
|
||||
height: 40
|
||||
radius: 5
|
||||
color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
|
||||
width: 1
|
||||
height: parent.height
|
||||
color: control.dividerColor
|
||||
visible: isH
|
||||
}
|
||||
ListView{
|
||||
id:list_view_3
|
||||
Layout.preferredWidth: 100
|
||||
Layout.preferredHeight: 76
|
||||
model: [control.amText,control.pmText]
|
||||
clip: true
|
||||
visible: isH
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
ScrollBar.vertical: FluScrollBar {}
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
boundsBehavior:Flickable.StopAtBounds
|
||||
delegate: FluLoader{
|
||||
property var model: modelData
|
||||
property int type:2
|
||||
property int position:index
|
||||
sourceComponent: list_delegate
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
id:layout_actions
|
||||
height: 60
|
||||
color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
|
||||
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
|
||||
radius: 5
|
||||
anchors{
|
||||
bottom:parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
Item {
|
||||
id:divider
|
||||
width: 1
|
||||
height: parent.height
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
FluButton{
|
||||
anchors{
|
||||
bottom:parent.bottom
|
||||
left: parent.left
|
||||
leftMargin: 20
|
||||
rightMargin: 10
|
||||
right: divider.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
text: control.cancelText
|
||||
onClicked: {
|
||||
popup.close()
|
||||
}
|
||||
}
|
||||
FluFilledButton{
|
||||
anchors{
|
||||
right: parent.right
|
||||
left: divider.right
|
||||
rightMargin: 20
|
||||
leftMargin: 10
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Item {
|
||||
id:divider
|
||||
width: 1
|
||||
height: parent.height
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
FluButton{
|
||||
anchors{
|
||||
left: parent.left
|
||||
leftMargin: 20
|
||||
rightMargin: 10
|
||||
right: divider.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
text: control.cancelText
|
||||
onClicked: {
|
||||
popup.close()
|
||||
}
|
||||
}
|
||||
FluFilledButton{
|
||||
anchors{
|
||||
right: parent.right
|
||||
left: divider.right
|
||||
rightMargin: 20
|
||||
leftMargin: 10
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
text: control.okText
|
||||
onClicked: {
|
||||
d.changeFlag = false
|
||||
popup.close()
|
||||
const hours = text_hour.text
|
||||
const minutes = text_minute.text
|
||||
const period = text_ampm.text
|
||||
const date = new Date()
|
||||
var hours24 = parseInt(hours);
|
||||
if(control.hourFormat === FluTimePickerType.H){
|
||||
if (hours === "12") {
|
||||
hours24 = (period === control.amText) ? 0 : 12;
|
||||
} else {
|
||||
hours24 = (period === control.pmText) ? hours24 : hours24 + 12;
|
||||
}
|
||||
text: control.okText
|
||||
onClicked: {
|
||||
d.changeFlag = false
|
||||
popup.close()
|
||||
const hours = text_hour.text
|
||||
const minutes = text_minute.text
|
||||
const period = text_ampm.text
|
||||
const date = new Date()
|
||||
var hours24 = parseInt(hours);
|
||||
if(control.hourFormat === FluTimePickerType.H){
|
||||
if (hours === "12") {
|
||||
hours24 = (period === control.amText) ? 0 : 12;
|
||||
} else {
|
||||
hours24 = (period === control.pmText) ? hours24 : hours24 + 12;
|
||||
}
|
||||
date.setHours(hours24);
|
||||
date.setMinutes(parseInt(minutes));
|
||||
date.setSeconds(0);
|
||||
current = date
|
||||
control.accepted()
|
||||
}
|
||||
date.setHours(hours24);
|
||||
date.setMinutes(parseInt(minutes));
|
||||
date.setSeconds(0);
|
||||
current = date
|
||||
control.accepted()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -387,7 +380,7 @@ FluButton {
|
||||
}
|
||||
var pos = control.mapToItem(null, 0, 0)
|
||||
if(d.window.height>pos.y+control.height+container.height){
|
||||
popup.y = control.height
|
||||
popup.y = control.height-1
|
||||
} else if(pos.y>container.height){
|
||||
popup.y = -container.height
|
||||
} else {
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user