Compare commits

...

116 Commits

Author SHA1 Message Date
ef65183320 Merge branch '1.7.6-dev' 2024-06-04 17:53:17 +08:00
2e379fcd7e Merge pull request #518 from ArcticLampyrid/patch-1
Make static lib available (#509)
2024-05-31 12:51:28 +05:30
0a8732c91b Merge pull request #519 from ArcticLampyrid/patch-2
remove `registerForWindowResult` which is not used (#506)
2024-05-31 12:50:24 +05:30
b98c5d327a remove registerForWindowResult which is not used (#506) 2024-05-31 14:02:33 +08:00
7163c739c2 make static lib available (#509) 2024-05-31 13:59:36 +08:00
5cfd9824a8 update 2024-05-19 13:40:36 +08:00
a27554bfb2 update 2024-05-17 21:27:41 +08:00
7a67ccc1e1 update 2024-05-17 21:19:10 +08:00
39f58278ff update 2024-05-16 01:26:59 +08:00
354f7f2e3e add hotkey 2024-05-16 00:35:04 +08:00
876b230141 update 2024-05-13 18:28:28 +08:00
2367c6978a update 2024-05-11 22:21:11 +08:00
6b941697b0 update 2024-05-11 21:45:45 +08:00
4997b991db update 2024-05-10 19:23:30 +08:00
cd3abc01e9 fix bug 2024-05-10 19:20:01 +08:00
e6c4b79298 Merge branch 'main' into 1.7.6-dev
# Conflicts:
#	src/Qt5/imports/FluentUI/Controls/FluRadioButtons.qml
#	src/Qt6/imports/FluentUI/Controls/FluRadioButtons.qml
2024-05-10 12:26:14 +08:00
f830d5a9bf Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2024-05-09 19:41:15 +08:00
ed49e3f6af Merge pull request #499 from gao-xiangyang/main
info提示语支持主动调用函数关闭,支持关闭所有info框的函数
2024-05-09 17:10:34 +05:30
9aa6615189 FluRadioButtons 组件支持 disabled、manuallyDisabled选项
disabled: true // 禁用所有FluRadioButton子组件
        manuallyDisabled: true // 是否指定每个FluRadioButton上的disabled选项
2024-05-08 21:10:00 +08:00
c36515f19c info提示语支持主动调用函数关闭,支持关闭所有info框的函数 2024-05-08 20:35:31 +08:00
402579f32a update 2024-05-08 18:58:22 +08:00
655eff4f62 update 2024-05-07 22:16:42 +08:00
b916221d9f update 2024-05-07 21:47:40 +08:00
4cca680029 update 2024-05-05 22:05:18 +08:00
fe2543ab4d fix bug 2024-05-05 22:03:41 +08:00
394a42cb94 update 2024-05-05 21:33:47 +08:00
ac253a3de5 fix bug 2024-05-05 20:32:48 +08:00
0d61e33ef1 update 2024-05-05 15:52:46 +08:00
132ab12c32 update 2024-05-05 00:06:01 +08:00
af270951da update 2024-05-04 23:56:20 +08:00
18685b17ec update 2024-05-03 16:56:40 +08:00
0eb4d9f346 update 2024-05-03 01:54:38 +08:00
8015dcc2f1 update 2024-05-02 23:52:30 +08:00
0b1755e9eb update 2024-05-01 01:11:25 +08:00
e471d5a230 update 2024-04-30 19:38:05 +08:00
f922978338 update 2024-04-30 19:27:57 +08:00
91bda2a22c update 2024-04-30 13:07:46 +08:00
6638fe2e06 update 2024-04-30 13:06:27 +08:00
bf001d99d2 update 2024-04-30 12:59:09 +08:00
30531079b5 update 2024-04-29 10:12:34 +08:00
a746bc2684 update 2024-04-28 21:05:43 +08:00
96a6d0e7fa update 2024-04-28 20:22:05 +08:00
c733f3c60e update 2024-04-28 18:38:37 +08:00
effd9f3058 update 2024-04-28 18:19:21 +08:00
d93aac3518 update 2024-04-28 15:56:37 +08:00
5f6745b630 udpate 2024-04-28 13:03:20 +08:00
4f202831b8 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2024-04-28 10:51:29 +08:00
29cee84edd update 2024-04-28 10:51:13 +08:00
2d4e61445e Merge pull request #488 from yanhuacuo/path-for-insertRow
Add the functionality to insert new rows into the table
2024-04-28 10:47:28 +08:00
cc79854191 Merge pull request #489 from w-jt/main
FluPagination.qml 添加自定义控件,通过header和footer属性添加控件
2024-04-28 10:46:47 +08:00
500efa6298 添加自定义控件,通过header和footer属性添加控件
添加自定义控件,通过header和footer属性添加控件
2024-04-27 11:54:42 +08:00
355332da96 添加自定义控件,通过header和footer属性添加控件
添加自定义控件,通过header和footer属性添加控件
2024-04-27 11:53:57 +08:00
a0d662a8a5 添加自定义控件,通过header和footer属性添加控件
添加自定义控件,通过header和footer属性添加控件
2024-04-27 11:49:29 +08:00
aecc3fe3b4 添加自定义控件,通过header和footer属性添加控件
添加自定义控件,通过header和footer属性添加控件
2024-04-27 11:48:19 +08:00
3554fb99cd Add the functionality to insert new rows into the table 2024-04-27 09:40:37 +08:00
24fdff7e35 fix bug 2024-04-25 00:08:18 +08:00
d2fdd08604 update 2024-04-24 17:24:31 +08:00
1f5d6ce1aa update 2024-04-24 17:12:00 +08:00
5fd7c7d10e update 2024-04-24 10:37:15 +08:00
83507a6ed5 update 2024-04-24 09:57:28 +08:00
789d9164a1 Merge branch '1.7.5-dev' 2024-04-24 09:53:59 +08:00
cb44759978 update 2024-04-23 22:38:39 +08:00
04c52b1b25 fix bug 2024-04-23 21:19:32 +08:00
b8ef9169b9 update 2024-04-23 19:33:05 +08:00
c7de653ba2 update 2024-04-23 13:41:26 +08:00
2ddb7e3290 update 2024-04-23 00:32:15 +08:00
e8d79e3c7b update 2024-04-23 00:31:20 +08:00
bc4510077f update 2024-04-19 01:04:13 +08:00
179bc8b21f update 2024-04-19 00:42:35 +08:00
8fe4e3b047 update 2024-04-17 22:05:49 +08:00
a443f3a9ba update 2024-04-17 21:39:55 +08:00
1a0f2afee0 update 2024-04-17 15:11:14 +08:00
c9c737f2fc update 2024-04-16 12:36:41 +08:00
f0f00b9eba Merge pull request #483 from mariuszmaximus/main
fix for msys2
2024-04-15 12:39:47 +08:00
956f2e0ad0 fix for msys2 2024-04-14 19:38:52 +02:00
ecd13a9cca update 2024-04-15 00:11:41 +08:00
17bfff2346 update 2024-04-14 23:58:15 +08:00
295dcf02c4 update 2024-04-14 23:09:41 +08:00
f701f97756 update 2024-04-14 11:43:32 +08:00
2c4cf82f63 update 2024-04-13 22:00:15 +08:00
e8c47e0fd8 update 2024-04-13 21:30:23 +08:00
9296b18606 update 2024-04-13 10:51:24 +08:00
481e19c8cc update 2024-04-13 10:50:27 +08:00
44f7948df3 update 2024-04-12 16:50:49 +08:00
0ab315e258 update 2024-04-12 16:26:32 +08:00
44acdbcf7f update 2024-04-11 20:29:59 +08:00
3997daaa11 update 2024-04-11 19:18:37 +08:00
531f659e59 update 2024-04-11 15:27:15 +08:00
3f6ef13cd0 update 2024-04-11 15:09:47 +08:00
96fef84c2d update 2024-04-11 14:56:22 +08:00
a3f375c9ef update 2024-04-11 14:51:43 +08:00
6a31e86505 update 2024-04-09 20:53:52 +08:00
6ebd659e13 update 2024-04-04 22:47:07 +08:00
bd8c80feb8 update 2024-04-04 17:43:58 +08:00
6b617d10d5 update 2024-04-04 17:08:45 +08:00
cf163f5e3b update 2024-04-04 16:53:31 +08:00
b4329fdd0a update 2024-04-04 12:11:08 +08:00
84b2045b5f update 2024-04-04 02:48:26 +08:00
18193a18be update 2024-04-04 02:01:52 +08:00
fe08b08c1f update 2024-04-04 01:10:14 +08:00
ef96618151 update 2024-04-03 21:52:26 +08:00
be34220652 update 2024-04-03 19:31:01 +08:00
5cf0812562 update 2024-04-03 19:30:15 +08:00
c2b845658d update 2024-04-03 13:24:30 +08:00
eb4ec242b1 update 2024-04-03 11:28:18 +08:00
a95916ab03 update 2024-04-03 11:19:35 +08:00
bf5bedc9ed update 2024-04-03 11:09:35 +08:00
7d1666597f update 2024-04-02 00:32:06 +08:00
da9f63eb24 update 2024-03-31 21:56:11 +08:00
68015776ab update 2024-03-31 21:52:06 +08:00
d222cb640c update 2024-03-31 11:17:05 +08:00
0ab7f811e3 update 2024-03-31 10:59:15 +08:00
6a5f9d04a9 update 2024-03-29 16:56:09 +08:00
cb33af8836 update 2024-03-29 16:23:16 +08:00
5fd934b5f5 update 2024-03-29 00:51:55 +08:00
b7fde5f79c update 2024-03-29 00:48:58 +08:00
281 changed files with 15103 additions and 9787 deletions

View File

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

View File

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

View File

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

@ -36,10 +36,8 @@ bin
build
cmake-build-*
.idea
package
example/Version.h
action-cli
dist
*.qm

View File

@ -2,18 +2,18 @@ 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)
option(FLUENTUI_BUILD_EXAMPLES "Build FluentUI demo applications." ON)
set(FLUENTUI_BUILD_STATIC_LIB OFF)
option(FLUENTUI_BUILD_STATIC_LIB "Build static library." OFF)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
@ -22,8 +22,8 @@ add_subdirectory(src)
#Release也支持日志打印代码位置
target_compile_definitions(fluentuiplugin
PRIVATE
QT_MESSAGELOGCONTEXT
PRIVATE
QT_MESSAGELOGCONTEXT
)
if (FLUENTUI_BUILD_EXAMPLES)

View File

@ -34,6 +34,38 @@ providing powerful tools and support for this project.
For more information about the Qt project,
please visit the official Qt website (https://www.qt.io/).
************************************************************************************
QHotkey
Copyright (c) 2016, Felix Barz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of QHotkey nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************************
framelesshelper

View File

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

View File

@ -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>
@ -177,12 +176,10 @@
<file>qml/window/SingleInstanceWindow.qml</file>
<file>qml/window/SingleTaskWindow.qml</file>
<file>qml/window/StandardWindow.qml</file>
<file>res/image/bg_scenic.png</file>
<file>res/image/image_1.jpg</file>
<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>
@ -195,7 +192,6 @@
<file>res/image/ic_crash.png</file>
<file>qml/window/CrashWindow.qml</file>
<file>qml/page/T_SplitLayout.qml</file>
<file>qml/window/FluentInitalizrWindow.qml</file>
<file>res/template/CMakeLists.txt.in</file>
<file>res/template/src/App.qml.in</file>
<file>res/template/src/CMakeLists.txt.in</file>
@ -207,5 +203,13 @@
<file>res/template/src/zh_CN.ts.in</file>
<file>res/template/src/README.md.in</file>
<file>qml/global/GlobalModel.qml</file>
<file>qml/page/T_Sheet.qml</file>
<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>
<file>qml/window/HotkeyWindow.qml</file>
</qresource>
<qresource prefix="/"/>
</RCC>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,7 @@ FluLauncher {
FluApp.windowIcon = "qrc:/example/res/image/favicon.ico"
FluApp.useSystemAppBar = SettingsHelper.getUseSystemAppBar()
FluTheme.darkMode = SettingsHelper.getDarkMode()
FluTheme.enableAnimation = true
FluTheme.animationEnabled = true
FluRouter.routes = {
"/":"qrc:/example/qml/window/MainWindow.qml",
"/about":"qrc:/example/qml/window/AboutWindow.qml",
@ -43,7 +43,8 @@ FluLauncher {
"/singleTaskWindow":"qrc:/example/qml/window/SingleTaskWindow.qml",
"/standardWindow":"qrc:/example/qml/window/StandardWindow.qml",
"/singleInstanceWindow":"qrc:/example/qml/window/SingleInstanceWindow.qml",
"/pageWindow":"qrc:/example/qml/window/PageWindow.qml"
"/pageWindow":"qrc:/example/qml/window/PageWindow.qml",
"/hotkey":"qrc:/example/qml/window/HotkeyWindow.qml"
}
var args = Qt.application.arguments
if(args.length>=2 && args[1].startsWith("-crashed=")){
@ -52,4 +53,73 @@ FluLauncher {
FluRouter.navigate("/")
}
}
property alias hotkeys: object_hotkey
FluObject{
id: object_hotkey
FluHotkey{
name: qsTr("Quit")
sequence: "Ctrl+Alt+Q"
onActivated: {
FluRouter.exit()
}
}
FluHotkey{
name: qsTr("Test1")
sequence: "Alt+A"
onActivated: {
FluRouter.navigate("/hotkey",{sequence:sequence})
}
}
FluHotkey{
name: qsTr("Test2")
sequence: "Alt+B"
onActivated: {
FluRouter.navigate("/hotkey",{sequence:sequence})
}
}
FluHotkey{
name: qsTr("Test3")
sequence: "Alt+C"
onActivated: {
FluRouter.navigate("/hotkey",{sequence:sequence})
}
}
FluHotkey{
name: qsTr("Test4")
sequence: "Alt+D"
onActivated: {
FluRouter.navigate("/hotkey",{sequence:sequence})
}
}
FluHotkey{
name: qsTr("Test5")
sequence: "Alt+E"
onActivated: {
FluRouter.navigate("/hotkey",{sequence:sequence})
}
}
FluHotkey{
name: qsTr("Test6")
sequence: "Alt+F"
onActivated: {
FluRouter.navigate("/hotkey",{sequence:sequence})
}
}
FluHotkey{
name: qsTr("Test7")
sequence: "Alt+G"
onActivated: {
FluRouter.navigate("/hotkey",{sequence:sequence})
}
}
FluHotkey{
name: qsTr("Test8")
sequence: "Alt+H"
onActivated: {
FluRouter.navigate("/hotkey",{sequence:sequence})
}
}
}
}

View File

@ -9,10 +9,10 @@ FluScrollablePage{
title: qsTr("Bar Chart")
FluArea{
width: 500
height: 370
paddings: 10
FluFrame{
Layout.preferredWidth: 500
Layout.preferredHeight: 370
padding: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
@ -69,10 +69,10 @@ FluScrollablePage{
}
}
FluArea{
width: 500
height: 370
paddings: 10
FluFrame{
Layout.preferredWidth: 500
Layout.preferredHeight: 370
padding: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent

View File

@ -13,10 +13,10 @@ FluScrollablePage{
return Math.random().toFixed(1);
}
FluArea{
height: 370
width: 500
paddings: 10
FluFrame{
Layout.preferredWidth: 500
Layout.preferredHeight: 370
padding: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent

View File

@ -7,21 +7,24 @@ import "../component"
FluScrollablePage{
id: root
title: qsTr("Line Chart")
property var data : []
FluArea{
width: 500
height: 370
paddings: 10
FluFrame{
Layout.preferredWidth: 500
Layout.preferredHeight: 370
padding: 10
Layout.topMargin: 20
FluChart{
id: chart
anchors.fill: parent
chartType: 'line'
chartData: { return {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'My First Dataset',
data: [65, 59, 80, 81, 56, 55, 40],
data: root.data,
fill: false,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1
@ -41,5 +44,20 @@ FluScrollablePage{
}
}
}
Timer{
id: timer
interval: 300
repeat: true
onTriggered: {
root.data.push(Math.random()*100)
if(root.data.length>7){
root.data.shift()
}
chart.animateToNewData()
}
}
Component.onCompleted: {
timer.restart()
}
}
}

View File

@ -9,10 +9,10 @@ FluScrollablePage{
title: qsTr("Pie Chart")
FluArea{
width: 500
height: 370
paddings: 10
FluFrame{
Layout.preferredWidth: 500
Layout.preferredHeight: 370
padding: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
@ -50,10 +50,10 @@ FluScrollablePage{
}
}
FluArea{
width: 500
height: 370
paddings: 10
FluFrame{
Layout.preferredWidth: 500
Layout.preferredHeight: 370
padding: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent

View File

@ -9,10 +9,10 @@ FluScrollablePage{
title: qsTr("Polar Area Chart")
FluArea{
width: 500
height: 370
paddings: 10
FluFrame{
Layout.preferredWidth: 500
Layout.preferredHeight: 370
padding: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent

View File

@ -9,10 +9,10 @@ FluScrollablePage{
title: qsTr("Radar Chart")
FluArea{
width: 500
height: 370
paddings: 10
FluFrame{
Layout.preferredWidth: 500
Layout.preferredHeight: 370
padding: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent

View File

@ -13,10 +13,10 @@ FluScrollablePage{
return Math.random().toFixed(1);
}
FluArea{
height: 370
width: 500
paddings: 10
FluFrame{
Layout.preferredWidth: 500
Layout.preferredHeight: 370
padding: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
@ -119,5 +119,4 @@ FluScrollablePage{
}
}
}
}

View File

@ -137,7 +137,9 @@ FluExpander{
"FluNetwork",
"FluShortcutPicker",
"FluWindowResultLauncher",
"FluRouter"
"FluRouter",
"FluGroupBox",
"FluSheet",
];
code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;");

View File

@ -104,6 +104,12 @@ FluObject{
url: "qrc:/example/qml/page/T_ToggleSwitch.qml"
onTap: { navigationView.push(url) }
}
FluPaneItem{
title: qsTr("GroupBox")
menuDelegate: paneItemMenu
url: "qrc:/example/qml/page/T_GroupBox.qml"
onTap: { navigationView.push(url) }
}
FluPaneItem{
title: qsTr("PaneItem Disabled")
disabled: true
@ -271,6 +277,12 @@ FluObject{
url: "qrc:/example/qml/page/T_Menu.qml"
onTap: { navigationView.push(url) }
}
FluPaneItem{
title: qsTr("Sheet")
menuDelegate: paneItemMenu
url: "qrc:/example/qml/page/T_Sheet.qml"
onTap: { navigationView.push(url) }
}
}
FluPaneItemExpander{
@ -352,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) }
}
}
@ -414,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
@ -465,18 +483,14 @@ 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")
visible: FluTools.isWin()
onTapListener: function(){
AppInfo.testCrash()
}
Component.onCompleted: {
visible = FluTools.isWin()
}
}
}

View File

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

View File

@ -11,7 +11,6 @@ FluScrollablePage{
RowLayout{
spacing: 10
Layout.topMargin: 20
FluText{
text:"tintColor:"
Layout.alignment: Qt.AlignVCenter
@ -42,10 +41,10 @@ FluScrollablePage{
value: 32
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 1200/4+20
paddings: 10
Layout.preferredHeight: 1200/4+20
padding: 10
Layout.topMargin: 10
FluClip{
width: 1920/4
@ -54,7 +53,7 @@ FluScrollablePage{
Image {
id:image
asynchronous: true
source: "qrc:/example/res/image/bg_scenic.png"
source: "qrc:/example/res/image/bg_scenic.jpg"
anchors.fill: parent
sourceSize: Qt.size(2*width,2*height)
}
@ -72,7 +71,7 @@ FluScrollablePage{
anchors.centerIn: parent
text: "Acrylic"
color: "#FFFFFF"
font.bold: true
font: FluTextStyle.Subtitle
}
MouseArea {
property point clickPos: Qt.point(0,0)
@ -95,7 +94,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'Image{
id:image
width: 800

View File

@ -1,71 +0,0 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import FluentUI 1.0
FluContentPage {
title: qsTr("Awesome")
FluTextBox{
id:text_box
placeholderText: qsTr("Please enter a keyword")
anchors{
topMargin: 20
top:parent.top
}
}
FluFilledButton{
text: qsTr("Search")
anchors{
left: text_box.right
verticalCenter: text_box.verticalCenter
leftMargin: 14
}
onClicked: {
grid_view.model = FluTheme.awesomeList(text_box.text)
}
}
GridView{
id:grid_view
cellWidth: 80
cellHeight: 80
clip: true
boundsBehavior: GridView.StopAtBounds
model:FluTheme.awesomeList()
ScrollBar.vertical: FluScrollBar {}
anchors{
topMargin: 10
top:text_box.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
delegate: Item {
width: 68
height: 80
FluIconButton{
id:item_icon
iconSource:modelData.icon
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
var text ="FluentIcons."+modelData.name;
FluTools.clipText(text)
showSuccess(qsTr("You Copied ")+text)
}
}
FluText {
id:item_name
font.pixelSize: 10
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: item_icon.bottom
width:parent.width
wrapMode: Text.WrapAnywhere
text: modelData.name
horizontalAlignment: Text.AlignHCenter
}
}
}
}

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("Badge")
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 120
paddings: 10
padding: 10
Column{
spacing: 15
@ -114,7 +113,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'Rectangle{
width: 40
height: 40

View File

@ -18,11 +18,10 @@ FluScrollablePage{
breadcrumb_2.items = items
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 68
padding: 10
FluBreadcrumbBar{
id:breadcrumb_1
@ -36,10 +35,10 @@ FluScrollablePage{
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 100
paddings: 10
Layout.preferredHeight: 100
padding: 10
Layout.topMargin: 20
ColumnLayout{
@ -77,7 +76,7 @@ FluScrollablePage{
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluBreadcrumbBar{
width:parent.width
separator:">"

View File

@ -10,15 +10,14 @@ FluScrollablePage{
title: qsTr("Buttons")
FluText{
Layout.topMargin: 20
text: qsTr("Support the Tab key to switch focus, and the Space key to perform click events")
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 68
Layout.topMargin: 10
padding: 10
FluTextButton{
disabled: text_button_switch.checked
@ -42,7 +41,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluTextButton{
text:"Text Button"
onClicked: {
@ -51,10 +50,10 @@ FluScrollablePage{
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.preferredHeight: 68
padding: 10
Layout.topMargin: 20
FluButton{
@ -79,7 +78,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluButton{
text:"Standard Button"
onClicked: {
@ -88,11 +87,11 @@ FluScrollablePage{
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
Layout.preferredHeight: 68
Layout.topMargin: 20
paddings: 10
padding: 10
FluFilledButton{
disabled: filled_button_switch.checked
@ -116,7 +115,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluFilledButton{
text:"Filled Button"
onClicked: {
@ -125,11 +124,11 @@ FluScrollablePage{
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
Layout.preferredHeight: 68
Layout.topMargin: 20
paddings: 10
padding: 10
FluToggleButton{
disabled:toggle_button_switch.checked
@ -150,7 +149,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluToggleButton{
text:"Toggle Button"
onClicked: {
@ -172,11 +171,11 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
Layout.preferredHeight: 68
Layout.topMargin: 20
paddings: 10
padding: 10
FluProgressButton{
id: btn_progress
@ -202,7 +201,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluProgressButton{
text:"Progress Button"
onClicked: {
@ -211,11 +210,11 @@ FluScrollablePage{
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
Layout.preferredHeight: 68
Layout.topMargin: 20
paddings: 10
padding: 10
FluLoadingButton{
id: btn_loading
@ -241,7 +240,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluLoadingButton{
text:"Loading Button"
onClicked: {
@ -251,10 +250,10 @@ FluScrollablePage{
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: layout_icon_button.height + 30
paddings: 10
Layout.preferredHeight: layout_icon_button.height + 30
padding: 10
Layout.topMargin: 20
Flow{
id: layout_icon_button
@ -323,7 +322,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluIconButton{
iconSource:FluentIcons.ChromeCloseContrast
onClicked: {
@ -332,10 +331,10 @@ FluScrollablePage{
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.preferredHeight: 68
padding: 10
Layout.topMargin: 20
FluDropDownButton{
disabled: drop_down_button_switch.checked
@ -371,7 +370,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluDropDownButton{
text:"DropDownButton"
FluMenuItem{
@ -389,10 +388,10 @@ FluScrollablePage{
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 100
paddings: 10
Layout.preferredHeight: 100
padding: 10
Layout.topMargin: 20
FluRadioButtons{
spacing: 8
@ -424,7 +423,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluRadioButton{
checked:true
text:"Text Button"

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("CalendarPicker")
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 80
paddings: 10
Layout.preferredHeight: 80
padding: 10
ColumnLayout{
anchors{
verticalCenter: parent.verticalCenter
@ -28,7 +27,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluCalendarPicker{
}'

View File

@ -11,7 +11,6 @@ FluScrollablePage{
FluCaptcha{
id: captcha
Layout.topMargin: 20
ignoreCase:switch_case.checked
MouseArea{
anchors.fill: parent

View File

@ -22,11 +22,10 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 370
paddings: 10
Layout.topMargin: 20
padding: 10
Column{
spacing: 15
anchors{
@ -62,10 +61,10 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 340
paddings: 10
padding: 10
Layout.topMargin: 10
Column{
spacing: 15
@ -104,7 +103,6 @@ FluScrollablePage{
horizontalAlignment: Qt.AlignHCenter
text:model.title
color: FluColors.Grey10
font.pixelSize: 15
}
}
}
@ -126,7 +124,7 @@ FluScrollablePage{
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluCarousel{
id:carousel
width: 400

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("CheckBox")
FluArea{
FluFrame{
Layout.fillWidth: true
height: 72
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 72
padding: 10
FluText{
text: qsTr("A 2-state CheckBox")
@ -49,16 +48,16 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluCheckBox{
text:"Text"
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 72
paddings: 10
Layout.preferredHeight: 72
padding: 10
Layout.topMargin: 20
FluText{
@ -104,7 +103,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluCheckBox{
text:"Text"
indeterminate:true

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("Clip")
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 380
paddings: 10
Layout.preferredHeight: 380
padding: 10
Column{
spacing: 15
@ -88,7 +87,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluClip{
radius: [25,25,25,25]
width: 50

View File

@ -9,31 +9,21 @@ FluScrollablePage{
title: qsTr("ColorPicker")
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 60
paddings: 10
Layout.preferredHeight: 60
padding: 10
RowLayout{
FluText{
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{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluColorPicker{
}'

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("ComboBox")
FluArea{
FluFrame{
Layout.fillWidth: true
height: 80
paddings: 5
Layout.topMargin: 20
Layout.preferredHeight: 80
padding: 5
Column{
spacing: 5
anchors.verticalCenter: parent.verticalCenter
@ -32,10 +31,10 @@ FluScrollablePage{
}
}
FluArea {
FluFrame {
Layout.fillWidth: true
height: 80
paddings: 5
Layout.preferredHeight: 80
padding: 5
Layout.topMargin: 20
Column{
spacing: 5
@ -56,10 +55,10 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 80
paddings: 10
padding: 10
Layout.topMargin: 20
Column{
spacing: 5
@ -85,7 +84,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluComboBox{
editable: true
model: ListModel {

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("DatePicker")
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 80
paddings: 10
Layout.preferredHeight: 80
padding: 10
ColumnLayout{
anchors{
verticalCenter: parent.verticalCenter
@ -32,17 +31,17 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluDatePicker{
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 80
paddings: 10
Layout.preferredHeight: 80
padding: 10
ColumnLayout{
anchors{
verticalCenter: parent.verticalCenter
@ -61,7 +60,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluDatePicker{
showYear:false
}'

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("Dialog")
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 68
padding: 10
FluButton{
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Show Double Button Dialog")
@ -24,7 +23,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluContentDialog{
id:dialog
title: qsTr("Friendly Reminder")
@ -57,10 +56,10 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.preferredHeight: 68
padding: 10
Layout.topMargin: 20
FluButton{
anchors.verticalCenter: parent.verticalCenter
@ -72,7 +71,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluContentDialog{
id: dialog
title: qsTr("Friendly Reminder")
@ -114,10 +113,10 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 100
paddings: 10
Layout.preferredHeight: 100
padding: 10
Layout.topMargin: 20
FluButton{
anchors.top: parent.top
@ -138,7 +137,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluContentDialog{
id: dialog
title: qsTr("Friendly Reminder")

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("Expander")
FluArea{
FluFrame{
Layout.fillWidth: true
height: layout_column.height+20
paddings: 10
Layout.topMargin: 20
padding: 10
Column{
id:layout_column
spacing: 15
@ -83,7 +82,7 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluExpander{
headerText: qsTr("Open a radio box")
Item{

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("FlipView")
FluArea{
FluFrame{
Layout.fillWidth: true
height: 340
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 340
padding: 10
ColumnLayout{
anchors.verticalCenter: parent.verticalCenter
FluText{
@ -40,7 +39,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluFlipView{
Image{
source: "qrc:/example/res/image/banner_1.jpg"
@ -61,10 +60,10 @@ FluScrollablePage{
'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 340
paddings: 10
padding: 10
Layout.topMargin: 20
ColumnLayout{
anchors.verticalCenter: parent.verticalCenter
@ -93,7 +92,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluFlipView{
vertical:true
Image{

View File

@ -0,0 +1,80 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import FluentUI 1.0
import "../component"
FluScrollablePage{
title: qsTr("GroupBox")
FluGroupBox {
title: qsTr("CheckBox Group")
ColumnLayout {
spacing: 10
anchors.fill: parent
FluCheckBox { text: qsTr("E-mail") }
FluCheckBox { text: qsTr("Calendar") }
FluCheckBox { text: qsTr("Contacts") }
}
}
FluGroupBox {
title: qsTr("RadioButton Group")
Layout.fillWidth: true
Layout.preferredHeight: 150
Layout.topMargin: 20
FluRadioButtons {
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
spacing: 10
disabled: radio_button_switch.checked
FluRadioButton { text: qsTr("E-mail") }
FluRadioButton { text: qsTr("Calendar") }
FluRadioButton { text: qsTr("Contacts") }
}
FluToggleSwitch{
id: radio_button_switch
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
}
text: qsTr("Disabled")
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: 4
code:`
FluGroupBox {
title: qsTr("CheckBox Group")
ColumnLayout {
spacing: 10
anchors.fill: parent
FluCheckBox { text: qsTr("E-mail") }
FluCheckBox { text: qsTr("Calendar") }
FluCheckBox { text: qsTr("Contacts") }
}
}
FluGroupBox {
title: qsTr("RadioButton Group")
FluRadioButtons {
spacing: 10
disabled: true // 禁用所有FluRadioButton子组件
manuallyDisabled: true // 是否指定每个FluRadioButton上的disabled选项
FluRadioButton { text: qsTr("E-mail") }
FluRadioButton { text: qsTr("Calendar") }
FluRadioButton { text: qsTr("Contacts") }
}
}
`
}
}

View File

@ -9,11 +9,8 @@ import "../global"
FluScrollablePage{
launchMode: FluPageType.SingleTask
animDisabled: true
FluentInitalizrWindow{
id:fluent_initalizr
}
animationEnabled: false
header: Item{}
ListModel{
id: model_header
@ -28,11 +25,11 @@ FluScrollablePage{
}
ListElement{
icon: "qrc:/example/res/image/favicon.ico"
title: qsTr("FluentUI Initalizr")
title: qsTr("FluentUI Initializr")
desc: qsTr("FluentUI Initializr is a Tool that helps you create and customize Fluent UI projects with various options.")
url: "https://github.com/zhuzichu520/FluentUI"
clicked: function(model){
fluent_initalizr.showDialog()
fluent_Initializr.showDialog()
}
}
}
@ -121,6 +118,7 @@ FluScrollablePage{
Layout.leftMargin: 20
color: FluColors.Grey120
font.pixelSize: 12
font.family: FluTextStyle.family
wrapMode: Text.WrapAnywhere
}
}
@ -177,7 +175,7 @@ FluScrollablePage{
property string desc: modelData.extra.desc
width: 320
height: 120
FluArea{
FluFrame{
radius: 8
width: 300
height: 100

View File

@ -0,0 +1,64 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import FluentUI 1.0
FluContentPage {
title: qsTr("Icons")
FluTextBox{
id: text_box
placeholderText: qsTr("Please enter a keyword")
anchors{
top: parent.top
}
onTextChanged: {
grid_view.model = FluApp.iconData(text_box.text)
}
}
GridView{
id: grid_view
cellWidth: 110
cellHeight: 110
clip: true
boundsBehavior: GridView.StopAtBounds
model: FluApp.iconData()
ScrollBar.vertical: FluScrollBar {}
anchors{
topMargin: 10
top: text_box.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
delegate: Item {
width: 100
height: 100
FluIconButton{
id:item_icon
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{
width: parent.width
horizontalAlignment: Qt.AlignHCenter
wrapMode: Text.WrapAnywhere
text: modelData.name
anchors.top: parent.top
anchors.topMargin: 60
}
}
}
}
}

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("Image")
FluArea{
FluFrame{
Layout.fillWidth: true
height: 260
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 260
padding: 10
Column{
spacing: 15
anchors{
@ -37,7 +36,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluImage{
width: 400
height: 300

View File

@ -9,11 +9,14 @@ FluScrollablePage{
title: qsTr("InfoBar")
FluArea{
property var info1
property var info2
property var info3
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 270
paddings: 10
Layout.preferredHeight: 350
padding: 10
ColumnLayout{
spacing: 14
anchors{
@ -50,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,13 +108,18 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'showInfo(qsTr("This is an InfoBar in the Info Style"))
Layout.topMargin: -6
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()
`
}
}

View File

@ -47,11 +47,10 @@ FluScrollablePage{
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 100
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 100
padding: 10
Column{
id: layout_column
spacing: 15
@ -78,7 +77,7 @@ FluScrollablePage{
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluMenu{
id:menu
FluMenuItem:{
@ -99,10 +98,10 @@ menu.popup()
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 100
paddings: 10
Layout.preferredHeight: 100
padding: 10
Layout.topMargin: 20
Column{
spacing: 15
@ -151,7 +150,7 @@ menu.popup()
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluMenuBar{
id:menu
FluMenu:{

View File

@ -21,11 +21,10 @@ FluScrollablePage{
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 86
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 86
padding: 10
Column{
spacing: 15
anchors{
@ -44,10 +43,10 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 86
paddings: 10
Layout.preferredHeight: 86
padding: 10
Layout.topMargin: 10
Column{
spacing: 15
@ -68,10 +67,10 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 86
paddings: 10
Layout.preferredHeight: 86
padding: 10
Layout.topMargin: 10
Column{
spacing: 15
@ -92,7 +91,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluWindow{
//launchMode: FluWindowType.Standard
//launchMode: FluWindowType.SingleTask
@ -102,10 +101,10 @@ FluScrollablePage{
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 100
paddings: 10
Layout.preferredHeight: 100
padding: 10
Layout.topMargin: 20
Column{
spacing: 15
@ -126,7 +125,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluButton{
text: qsTr("Create Window")
onClicked: {
@ -136,10 +135,10 @@ FluScrollablePage{
'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 130
paddings: 10
Layout.preferredHeight: 130
padding: 10
Layout.topMargin: 20
Column{
@ -164,7 +163,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluWindowResultLauncher{
id:loginResultLauncher
path: "/login"

View File

@ -40,7 +40,6 @@ FluContentPage{
clip: true
anchors{
top: parent.top
topMargin: 20
bottom: parent.bottom
left: parent.left
}
@ -533,7 +532,7 @@ FluContentPage{
}
}
FluArea{
FluFrame{
anchors{
top: layout_flick.top
bottom: layout_flick.bottom

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

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("Pagination")
FluArea{
FluFrame{
Layout.fillWidth: true
height: 200
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 200
padding: 10
ColumnLayout{
spacing: 20
anchors.verticalCenter: parent.verticalCenter
@ -37,7 +36,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluPagination{
pageCurrent: 1
itemCount: 1000

View File

@ -9,13 +9,10 @@ FluScrollablePage{
title: qsTr("Pivot")
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 400
paddings: 10
Layout.preferredHeight: 400
padding: 10
FluPivot{
anchors.fill: parent
@ -49,7 +46,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluPivot{
anchors.fill: parent
FluPivotItem:{

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("Progress")
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 130
paddings: 10
Layout.preferredHeight: 130
padding: 10
ColumnLayout{
spacing: 10
@ -32,7 +31,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluProgressBar{
}
@ -42,11 +41,11 @@ FluProgressRing{
'
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 286
paddings: 10
Layout.preferredHeight: 286
padding: 10
ColumnLayout{
spacing: 10
@ -88,7 +87,7 @@ FluProgressRing{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluProgressBar{
indeterminate: false
}

View File

@ -11,7 +11,6 @@ FluScrollablePage{
FluQRCode{
id:qrcode
Layout.topMargin: 20
size:slider_size.value
text:text_box.text
color:color_picker.current

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("RadioButton")
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 68
padding: 10
Row{
spacing: 30
anchors.verticalCenter: parent.verticalCenter
@ -41,34 +40,33 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluRadioButton{
text:"Text"
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 100
paddings: 10
Layout.preferredHeight: 100
padding: 10
Layout.topMargin: 20
FluRadioButtons{
spacing: 8
disabled: radio_button_switch2.checked
anchors.verticalCenter: parent.verticalCenter
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
currentIndex: 1
FluRadioButton{
disabled: radio_button_switch2.checked
text: qsTr("Radio Button_1")
}
FluRadioButton{
disabled: radio_button_switch2.checked
text: qsTr("Radio Button_2")
}
FluRadioButton{
disabled: radio_button_switch2.checked
text: qsTr("Radio Button_3")
}
}
@ -83,7 +81,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluRadioButtons{
spacing: 8
FluRadioButton{
@ -98,4 +96,106 @@ FluScrollablePage{
}'
}
FluFrame{
Layout.fillWidth: true
Layout.preferredHeight: 60
padding: 10
Layout.topMargin: 20
FluRadioButtons{
spacing: 8
anchors.verticalCenter: parent.verticalCenter
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
disabled: radio_button_switch3.checked
orientation: Qt.Horizontal
currentIndex: 1
FluRadioButton{
text: qsTr("Radio Button_1")
}
FluRadioButton{
text: qsTr("Radio Button_2")
}
FluRadioButton{
text: qsTr("Radio Button_3")
}
}
FluToggleSwitch{
id: radio_button_switch3
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
}
text: qsTr("Disabled")
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -6
code:'FluRadioButtons{
spacing: 8
orientation: Qt.Horizontal
FluRadioButton{
text:"Radio Button_1"
}
FluRadioButton{
text:"Radio Button_2"
}
FluRadioButton{
text:"Radio Button_3"
}
}'
}
FluFrame{
Layout.fillWidth: true
Layout.preferredHeight: 100
padding: 10
Layout.topMargin: 20
FluRadioButtons{
spacing: 8
anchors.verticalCenter: parent.verticalCenter
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
disabled: radio_button_switch4.checked
currentIndex: -1
FluCheckBox{
text: qsTr("Radio Button_1")
}
FluCheckBox{
text: qsTr("Radio Button_2")
}
FluCheckBox{
text: qsTr("Radio Button_3")
}
}
FluToggleSwitch{
id: radio_button_switch4
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
}
text: qsTr("Disabled")
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -6
code:'FluRadioButtons{
spacing: 8
FluCheckBox{
text:"Radio Button_1"
}
FluCheckBox{
text:"Radio Button_2"
}
FluCheckBox{
text:"Radio Button_3"
}
}'
}
}

View File

@ -9,11 +9,10 @@ FluScrollablePage {
title: qsTr("RatingControl")
FluArea {
FluFrame {
Layout.fillWidth: true
height: 100
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 100
padding: 10
Column {
spacing: 10
@ -27,7 +26,7 @@ FluScrollablePage {
CodeExpander {
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code: 'FluRatingControl{
}'

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("Rectangle")
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 80
paddings: 10
Layout.preferredHeight: 80
padding: 10
Column{
spacing: 15
@ -64,7 +63,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluRectangle{
radius: [25,25,25,25]
width: 50

View File

@ -9,6 +9,6 @@ FluPage{
launchMode: FluPageType.SingleTop
FluRemoteLoader{
anchors.fill: parent
source: "https://zhu-zichu.gitee.io/Qt5_T_RemoteLoader.qml"
source: "https://zhu-zichu.gitee.io/Qt_174_RemoteLoader.qml"
}
}

View File

@ -17,11 +17,11 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 60
paddings: 10
Layout.preferredHeight: 60
padding: 10
Row{
spacing: 20
anchors.verticalCenter: parent.verticalCenter
@ -42,11 +42,11 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 50
paddings: 10
padding: 10
FluCheckBox{
text: qsTr("Use System AppBar")
checked: FluApp.useSystemAppBar
@ -58,11 +58,11 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 50
paddings: 10
padding: 10
FluCheckBox{
text:qsTr("Fits AppBar Windows")
checked: window.fitsAppBarWindows
@ -85,11 +85,11 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 128
paddings: 10
padding: 10
ColumnLayout{
spacing: 5
@ -115,11 +115,11 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 160
paddings: 10
padding: 10
ColumnLayout{
spacing: 5
@ -155,11 +155,11 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 80
paddings: 10
padding: 10
ColumnLayout{
spacing: 10

View File

@ -0,0 +1,90 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
import FluentUI 1.0
import "../component"
FluScrollablePage{
title: qsTr("Sheet")
FluSheet{
id:sheet
title: qsTr("Title")
FluText{
text: qsTr("Some contents...\nSome contents...\nSome contents...")
anchors{
left: parent.left
leftMargin: 10
}
}
}
FluFrame{
Layout.fillWidth: true
Layout.preferredHeight: 280
padding: 10
Column{
anchors.centerIn: parent
spacing: 10
Row{
spacing: 10
FluButton{
width: 80
height: 30
text: qsTr("top")
onClicked: {
sheet.open(FluSheetType.Top)
}
}
FluButton{
width: 80
height: 30
text: qsTr("right")
onClicked: {
sheet.open(FluSheetType.Right)
}
}
}
Row{
spacing: 10
FluButton{
width: 80
height: 30
text: qsTr("bottom")
onClicked: {
sheet.open(FluSheetType.Bottom)
}
}
FluButton{
width: 80
height: 30
text: qsTr("left")
onClicked: {
sheet.open(FluSheetType.Left)
}
}
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -6
code:'FluSheet{
id:sheet
title: qsTr("Title")
FluText{
text: qsTr("Some contents...")
anchors{
left: parent.left
leftMargin: 10
}
}
}
sheet.open(FluSheetType.Bottom)
'
}
}

View File

@ -9,23 +9,34 @@ FluScrollablePage{
title: qsTr("ShortcutPicker")
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 100
paddings: 10
FluShortcutPicker{
Layout.preferredHeight: childrenRect.height
ColumnLayout{
anchors.verticalCenter: parent.verticalCenter
Item{
Layout.preferredHeight: 15
}
Repeater{
model: FluApp.launcher.hotkeys.children
delegate: FluShortcutPicker{
text: model.name
syncHotkey: FluApp.launcher.hotkeys.children[index]
Layout.leftMargin: 15
}
}
Item{
Layout.preferredHeight: 15
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluShortcutPicker{
}'
}
}

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("Slider")
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.preferredHeight: 200
Layout.topMargin: 20
paddings: 10
padding: 10
Row{
spacing: 30
@ -27,18 +26,18 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluSlider{
value:50
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.preferredHeight: 200
Layout.topMargin: 20
paddings: 10
padding: 10
Row{
spacing: 30
FluRangeSlider{
@ -51,7 +50,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluRangeSlider{
orientation: Qt.Vertical
}'

View File

@ -13,7 +13,6 @@ FluContentPage{
id:layout_dropdown
anchors{
top: parent.top
topMargin: 20
}
FluText{
text:"orientation:"

View File

@ -27,7 +27,6 @@ FluContentPage{
Flickable{
id: scroll
anchors.fill: parent
anchors.topMargin: 20
boundsBehavior:Flickable.StopAtBounds
contentHeight: staggered_view.implicitHeight
clip: true
@ -43,8 +42,7 @@ FluContentPage{
FluText{
color:"#FFFFFF"
text:model.index
font.bold: true
font.pixelSize: 18
font: FluTextStyle.Title
anchors.centerIn: parent
}
}

View File

@ -9,12 +9,11 @@ FluScrollablePage{
title: qsTr("StatusLayout")
FluArea{
FluFrame{
id:layout_actions
Layout.fillWidth: true
Layout.topMargin: 20
height: 50
paddings: 10
Layout.preferredHeight: 50
padding: 10
RowLayout{
spacing: 14
FluDropDownButton{
@ -53,20 +52,16 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 10
height: 380
paddings: 10
Layout.preferredHeight: 380
padding: 10
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
@ -76,7 +71,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluStatusLayout{
anchors.fill: parent
statusMode: FluStatusLayoutType.Loading

View File

@ -29,11 +29,10 @@ FluScrollablePage{
newTab()
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 50
paddings: 10
Layout.preferredHeight: 50
padding: 10
RowLayout{
spacing: 14
FluDropDownButton{
@ -91,11 +90,11 @@ FluScrollablePage{
}
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 15
height: 400
paddings: 10
Layout.preferredHeight: 400
padding: 10
FluTabView{
id:tab_view
onNewPressed:{
@ -105,7 +104,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluTabView{
anchors.fill: parent
Component.onCompleted: {

View File

@ -11,9 +11,8 @@ FluContentPage{
title: qsTr("TableView")
signal checkBoxChanged
property var dataSource : []
property int sortType: 0
property bool seletedAll: true
property bool selectedAll: true
property string nameKeyword: ""
onNameKeywordChanged: {
@ -32,11 +31,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: {
@ -159,7 +158,7 @@ FluContentPage{
FluCheckBox{
anchors.centerIn: parent
checked: true === options.checked
enableAnimation: false
animationEnabled: false
clickListener: function(){
var obj = table_view.getRow(row)
obj.checkbox = table_view.customItem(com_checbox,{checked:!options.checked})
@ -238,13 +237,15 @@ FluContentPage{
Layout.alignment: Qt.AlignVCenter
}
FluCheckBox{
checked: true === root.seletedAll
enableAnimation: false
checked: true === root.selectedAll
animationEnabled: false
Layout.alignment: Qt.AlignVCenter
clickListener: function(){
root.seletedAll = !root.seletedAll
var checked = root.seletedAll
itemModel.display = table_view.customItem(com_column_checbox,{"checked":checked})
root.selectedAll = !root.selectedAll
var checked = root.selectedAll
var columnModel = model.display
columnModel.title = table_view.customItem(com_column_checbox,{"checked":checked})
model.display = columnModel
for(var i =0;i< table_view.rows ;i++){
var rowData = table_view.getRow(i)
rowData.checkbox = table_view.customItem(com_checbox,{"checked":checked})
@ -271,7 +272,8 @@ FluContentPage{
}
Component.onCompleted: {
currentIndex=["100","300","500","1000"].findIndex((element) => element === display)
selectAll()
textBox.forceActiveFocus()
textBox.selectAll()
}
onCommit: {
editTextChaged(editText)
@ -280,6 +282,29 @@ 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)
forceActiveFocus()
selectAll()
}
onCommit: {
editTextChaged(textbox.text)
tableView.closeEditor()
}
}
}
Component{
id:com_avatar
Item{
@ -323,7 +348,9 @@ FluContentPage{
cursorShape: Qt.PointingHandCursor
onClicked: {
custom_update_dialog.showDialog(options.title,function(text){
itemModel.display = table_view.customItem(com_column_update_title,{"title":text})
var columnModel = model.display
columnModel.title = table_view.customItem(com_column_update_title,{"title":text})
model.display = columnModel
})
}
}
@ -390,7 +417,7 @@ FluContentPage{
}
}
FluArea{
FluFrame{
id:layout_controls
anchors{
left: parent.left
@ -421,15 +448,15 @@ FluContentPage{
var data = []
var rows = []
for (var i = 0; i < table_view.rows; i++) {
var item = table_view.getRow(i);
var item = table_view.getRow(i)
rows.push(item)
if (!item.checkbox.options.checked) {
data.push(item);
}
}
var sourceModel = table_view.sourceModel;
var sourceModel = table_view.sourceModel
for (i = 0; i < sourceModel.rowCount; i++) {
var sourceItem = sourceModel.getRow(i);
var sourceItem = sourceModel.getRow(i)
const foundItem = rows.find(item=> item._key === sourceItem._key)
if (!foundItem) {
data.push(sourceItem);
@ -438,14 +465,24 @@ FluContentPage{
table_view.dataSource = data
}
}
FluButton{
text: qsTr("Add a row of Data")
onClicked: {
table_view.appendRow(genTestObject())
}
}
FluButton{
text: qsTr("Insert a Row")
onClicked: {
var index = table_view.currentIndex()
if(index !== -1){
var testObj = genTestObject()
table_view.insertRow(index,testObj)
}else{
showWarning(qsTr("Focus not acquired: Please click any item in the form as the target for insertion!"))
}
}
}
}
}
@ -465,20 +502,19 @@ FluContentPage{
{
title: table_view.customItem(com_column_checbox,{checked:true}),
dataIndex: 'checkbox',
width:100,
minimumWidth:100,
maximumWidth:100
},
{
title: table_view.customItem(com_column_update_title,{title:qsTr("Avatar")}),
dataIndex: 'avatar',
width:100
frozen: true
},
{
title: table_view.customItem(com_column_filter_name,{title:qsTr("Name")}),
dataIndex: 'name',
readOnly:true
},
{
title: table_view.customItem(com_column_update_title,{title:qsTr("Avatar")}),
dataIndex: 'avatar',
width:100,
frozen:true
},
{
title: table_view.customItem(com_column_sort_age,{sort:0}),
dataIndex: 'age',
@ -490,6 +526,7 @@ FluContentPage{
{
title: qsTr("Address"),
dataIndex: 'address',
editDelegate: com_auto_suggestbox,
width:200,
minimumWidth:100,
maximumWidth:250
@ -513,8 +550,7 @@ FluContentPage{
title: qsTr("Options"),
dataIndex: 'action',
width:160,
minimumWidth:160,
maximumWidth:160
frozen:true
}
]
}
@ -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,12 +615,11 @@ FluContentPage{
}
}
function loadData(page,count){
root.seletedAll = true
root.selectedAll = true
const dataSource = []
for(var i=0;i<count;i++){
dataSource.push(genTestObject())
}
root.dataSource = dataSource
table_view.dataSource = root.dataSource
table_view.dataSource = dataSource
}
}

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("Text")
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 60
paddings: 10
Layout.preferredHeight: 60
padding: 10
FluCopyableText{
text: qsTr("This is a text that can be copied")
@ -23,7 +22,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluCopyableText{
text: qsTr("This is a text that can be copied")
}'

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("TextBox")
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 68
padding: 10
FluTextBox{
placeholderText: qsTr("Single-line Input Box")
@ -36,16 +35,16 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluTextBox{
placeholderText: qsTr("Single-line Input Box")
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.preferredHeight: 68
padding: 10
Layout.topMargin: 20
FluPasswordBox{
@ -67,16 +66,16 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluPasswordBox{
placeholderText: qsTr("Please enter your password")
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 36+multiine_textbox.height
paddings: 10
Layout.preferredHeight: 36+multiine_textbox.height
padding: 10
Layout.topMargin: 20
FluMultilineTextBox{
@ -100,16 +99,16 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluMultilineTextBox{
placeholderText: qsTr("Multi-line Input Box")
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.preferredHeight: 68
padding: 10
Layout.topMargin: 20
FluAutoSuggestBox{
placeholderText: qsTr("AutoSuggestBox")
@ -131,16 +130,16 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluAutoSuggestBox{
placeholderText: qsTr("AutoSuggestBox")
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.preferredHeight: 68
padding: 10
Layout.topMargin: 20
FluSpinBox{
disabled: spin_box_switch.checked
@ -160,7 +159,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluSpinBox{
}'

View File

@ -11,11 +11,10 @@ FluScrollablePage{
id: root
title: qsTr("Theme")
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
Layout.preferredHeight: 340
paddings: 10
Layout.preferredHeight: 408
padding: 10
ColumnLayout{
spacing:0
@ -115,16 +114,27 @@ FluScrollablePage{
}
FluToggleSwitch{
Layout.topMargin: 5
checked: FluTheme.enableAnimation
checked: FluTheme.animationEnabled
onClicked: {
FluTheme.enableAnimation = !FluTheme.enableAnimation
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{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluTheme.accentColor = FluColors.Orange
FluTheme.dark = true

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("TimePicker")
launchMode: FluPageType.SingleInstance
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 80
paddings: 10
Layout.preferredHeight: 80
padding: 10
ColumnLayout{
@ -43,17 +42,17 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluTimePicker{
}'
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 80
paddings: 10
Layout.preferredHeight: 80
padding: 10
ColumnLayout{
@ -83,7 +82,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluTimePicker{
hourFormat:FluTimePickerType.HH
}'

View File

@ -44,7 +44,6 @@ FluScrollablePage{
wrapMode: Text.WrapAnywhere
horizontalAlignment: isRight ? Qt.AlignRight : Qt.AlignLeft
text: modelData.text
font.bold: true
linkColor: FluTheme.dark ? FluColors.Teal.lighter : FluColors.Teal.dark
onLinkActivated:
(link)=> {
@ -106,7 +105,6 @@ FluScrollablePage{
RowLayout{
spacing: 20
Layout.topMargin: 20
FluTextBox{
id: text_box
text: "Technical testing 2015-09-01"

View File

@ -9,11 +9,10 @@ FluScrollablePage{
title: qsTr("ToggleSwitch")
FluArea{
FluFrame{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 68
padding: 10
Row{
spacing: 30
anchors.verticalCenter: parent.verticalCenter
@ -41,7 +40,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluToggleSwitch{
text:"Text"
}'

View File

@ -10,15 +10,14 @@ FluScrollablePage{
title: qsTr("Tooltip")
FluText{
Layout.topMargin: 20
text: qsTr("Hover over Tultip and it pops up")
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 68
paddings: 10
Layout.preferredHeight: 68
padding: 10
Column{
spacing: 5
@ -41,7 +40,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluIconButton{
iconSource:FluentIcons.ChromeCloseContrast
iconSize: 15
@ -53,11 +52,11 @@ FluScrollablePage{
'
}
FluArea{
FluFrame{
Layout.fillWidth: true
Layout.topMargin: 20
height: 68
paddings: 10
Layout.preferredHeight: 68
padding: 10
Column{
spacing: 5
@ -84,7 +83,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluButton{
id: button_1
text: qsTr("Delete")

View File

@ -18,11 +18,10 @@ FluScrollablePage{
]
}
FluArea{
FluFrame{
Layout.fillWidth: true
height: 130
paddings: 10
Layout.topMargin: 20
Layout.preferredHeight: 130
padding: 10
FluFilledButton{
anchors{
@ -66,7 +65,7 @@ FluScrollablePage{
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
Layout.topMargin: -6
code:'FluTour{
id:tour
steps:[

View File

@ -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,104 +47,159 @@ FluContentPage {
return dig();
}
Column{
id: layout_column
spacing: 12
width: 300
anchors{
topMargin: 20
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)
}
}
}
}
FluArea{
FluFrame{
id:layout_controls
anchors{
left: layout_column.right
left: parent.left
right: parent.right
top: parent.top
topMargin: 10
}
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
rightMargin: 5
topMargin: 5
bottomMargin: 5
}
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
}
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
}
}
}

View File

@ -10,15 +10,14 @@ FluContentPage {
title: qsTr("Typography")
rightPadding: 10
FluArea{
FluFrame{
anchors{
top:parent.top
left: parent.left
right: parent.right
bottom: parent.bottom
topMargin: 20
}
paddings: 10
padding: 10
ColumnLayout{
spacing: 0
scale: textScale

View File

@ -9,9 +9,8 @@ FluContentPage{
title: qsTr("Watermark")
FluArea{
FluFrame{
anchors.fill: parent
anchors.topMargin: 20
ColumnLayout{
anchors{

View File

@ -8,26 +8,26 @@ import "../component"
FluWindowDialog {
id:window
title:qsTr("FluentUI Initalizr")
title:qsTr("FluentUI Initializr")
width: 600
height: 400
contentDelegate:Component{
Item{
Connections{
target: InitalizrHelper
target: InitializrHelper
function onError(message){
showError(message)
}
function onSuccess(path){
FluTools.showFileInFolder(path+"/CMakeLists.txt")
FluTools.showFileInFolder(path)
window.close()
}
}
FluText{
id:text_title
text:qsTr("FluentUI Initalizr")
text:qsTr("FluentUI Initializr")
font: FluTextStyle.Title
anchors{
left: parent.left
@ -102,7 +102,7 @@ FluWindowDialog {
width: 120
anchors.verticalCenter: parent.verticalCenter
onClicked: {
InitalizrHelper.generate(text_box_name.text,text_box_path.text)
InitializrHelper.generate(text_box_name.text,text_box_path.text)
}
}
}

View File

@ -0,0 +1,26 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import FluentUI 1.0
import "../component"
FluWindow {
id: window
property string sequence: ""
title: qsTr("Hotkey")
width: 250
height: 250
fixSize: true
launchMode: FluWindowType.SingleInstance
onInitArgument:
(argument)=>{
window.sequence = argument.sequence
}
FluText{
anchors.centerIn: parent
color: FluTheme.primaryColor
font: FluTextStyle.Title
text: window.sequence
}
}

View File

@ -20,7 +20,7 @@ FluWindow {
loader.reload()
}
}
FluArea{
FluFrame{
anchors.fill: parent
FluRemoteLoader{
id:loader
@ -41,7 +41,7 @@ FluWindow {
}
FluText{
text: qsTr("Drag in a qml file")
font.pixelSize: 26
font: FluTextStyle.Title
anchors.centerIn: parent
visible: !loader.itemLodaer().item && loader.statusMode === FluStatusLayoutType.Success
}

View File

@ -14,9 +14,9 @@ FluWindow {
id:window
title: "FluentUI"
width: 1000
height: 680
minimumWidth: 520
minimumHeight: 200
height: 668
minimumWidth: 668
minimumHeight: 320
launchMode: FluWindowType.SingleTask
fitsAppBarWindows: true
appBar: FluAppBar {
@ -28,6 +28,10 @@ FluWindow {
z:7
}
FluentInitializrWindow{
id:fluent_Initializr
}
FluEvent{
name: "checkUpdate"
onTriggered: {
@ -101,7 +105,7 @@ FluWindow {
width: 186
FluMenuItem{
text: qsTr("Open in Separate Window")
font.pixelSize: 12
font: FluTextStyle.Caption
onClicked: {
FluRouter.navigate("/pageWindow",{title:modelData.title,url:modelData.url})
}
@ -253,7 +257,7 @@ FluWindow {
}
function handleDarkChanged(button){
if(!FluTheme.enableAnimation || window.fitsAppBarWindows === false){
if(!FluTheme.animationEnabled || window.fitsAppBarWindows === false){
changeDark()
}else{
if(loader_reveal.sourceComponent){
@ -344,7 +348,7 @@ FluWindow {
id:callable
property bool silent: true
onStart: {
console.debug("satrt check update...")
console.debug("start check update...")
}
onFinish: {
console.debug("check update finish")

View File

@ -16,7 +16,7 @@ FluWindow {
onInitArgument:
(arg)=>{
window.title = arg.title
loader.setSource( arg.url,{animDisabled:true})
loader.setSource(arg.url,{animationEnabled:false})
}
FluLoader{
id: loader

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 MiB

View File

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

View File

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

View File

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

View File

@ -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 &center, 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);

View File

@ -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 &center, 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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,95 @@
#include "OpenGLItem.h"
#include <QOpenGLFramebufferObjectFormat>
#include <QOpenGLShaderProgram>
#include <QQuickWindow>
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() {
auto pixelRatio = item->window()->devicePixelRatio();
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()*pixelRatio), qRound(item->height()*pixelRatio));
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);
}

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

View File

@ -1,109 +0,0 @@
#include "InitalizrHelper.h"
#include <QDir>
#include <QGuiApplication>
InitalizrHelper::InitalizrHelper(QObject *parent) : QObject(parent)
{
}
InitalizrHelper::~InitalizrHelper() = default;
bool InitalizrHelper::copyDir(const QDir& fromDir, const QDir& toDir, bool coverIfFileExists){
QDir _formDir = fromDir;
QDir _toDir = toDir;
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;
}
}
}
return true;
}
template <typename...Args>
void InitalizrHelper::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()){
outputDir.mkpath(outputDir.absolutePath());
}
QFile outputFile(dest);
if (outputFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&outputFile);
out << content;
outputFile.close();
} else {
qDebug() << "Failed to open output file.";
}
} else {
qDebug() << "Failed to open resource file.";
}
}
void InitalizrHelper::copyFile(const QString& source,const QString& dest){
QFile::copy(source,dest);
QFile::setPermissions(dest, QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther);
}
void InitalizrHelper::generate(const QString& name,const QString& path){
if(name.isEmpty()){
error(tr("The name cannot be empty"));
return;
}
if(path.isEmpty()){
error(tr("The creation path cannot be empty"));
return;
}
QDir projectRootDir(path);
if(!projectRootDir.exists()){
error(tr("The path does not exist"));
return;
}
QString projectPath = projectRootDir.filePath(name);
QDir projectDir(projectPath);
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);
}

View File

@ -1,26 +0,0 @@
#ifndef INITALIZRHELPER_H
#define INITALIZRHELPER_H
#include <QObject>
#include <QtQml/qqml.h>
#include <QDir>
#include "src/singleton.h"
class InitalizrHelper : public QObject
{
Q_OBJECT
private:
explicit InitalizrHelper(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(InitalizrHelper)
~InitalizrHelper() 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);
};
#endif // INITALIZRHELPER_H

View File

@ -0,0 +1,101 @@
#include "InitializrHelper.h"
#include <QDir>
#include <QGuiApplication>
[[maybe_unused]] InitializrHelper::InitializrHelper(QObject *parent) : QObject(parent) {
}
InitializrHelper::~InitializrHelper() = default;
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()))
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;
}
}
}
return true;
}
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()) {
outputDir.mkpath(outputDir.absolutePath());
}
QFile outputFile(dest);
if (outputFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&outputFile);
out << content;
outputFile.close();
} else {
qDebug() << "Failed to open output file.";
}
} else {
qDebug() << "Failed to open resource file.";
}
}
void InitializrHelper::copyFile(const QString &source, const QString &dest) {
QFile::copy(source, dest);
QFile::setPermissions(dest, QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther);
}
[[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()) {
error(tr("The creation path cannot be empty"));
return;
}
QDir projectRootDir(path);
if (!projectRootDir.exists()) {
error(tr("The path does not exist"));
return;
}
QString projectPath = projectRootDir.filePath(name);
QDir projectDir(projectPath);
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+"/CMakeLists.txt");
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <QObject>
#include <QtQml/qqml.h>
#include <QDir>
#include "src/singleton.h"
class InitializrHelper : public QObject {
Q_OBJECT
private:
[[maybe_unused]] explicit InitializrHelper(QObject *parent = nullptr);
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);
};

View File

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

View File

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

View File

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

View File

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

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