mirror of
https://github.com/zhuzichu520/FluentUI.git
synced 2025-07-04 17:15:29 +08:00
Compare commits
41 Commits
Author | SHA1 | Date | |
---|---|---|---|
7a1776407f | |||
f88b330f8e | |||
67ef7f13aa | |||
23ec52ce6a | |||
5b7fdab1d9 | |||
4c1a96c03e | |||
ab4090ea9b | |||
8fb2ef723e | |||
77d9b4bde9 | |||
a96191b2af | |||
28e1799ca4 | |||
8337e278ff | |||
7ad8c969da | |||
66ae37a023 | |||
b27a88d261 | |||
257f3a7b3d | |||
4710379324 | |||
8fc74fe43b | |||
be194e7624 | |||
e6d9de34ea | |||
c47fa5ebc7 | |||
af74f35e43 | |||
3b61985cfe | |||
eb96cf5b47 | |||
d48ad16ae3 | |||
39fb4d1b1a | |||
674de3f881 | |||
0c2b3173eb | |||
b2471bcf0d | |||
79a7c97fe8 | |||
fd30819393 | |||
05040ec4a9 | |||
0297445218 | |||
3990c95489 | |||
618b21854f | |||
ef40e3b109 | |||
f2b67af58a | |||
c0f15060af | |||
24f3cb1027 | |||
4b01fcf2b4 | |||
752fe8cfba |
@ -1,5 +1,6 @@
|
|||||||
include(CMakeParseArguments)
|
include(CMakeParseArguments)
|
||||||
find_package(Qt5 REQUIRED COMPONENTS Core)
|
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
|
||||||
|
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
|
||||||
|
|
||||||
function(FindQmlPluginDump)
|
function(FindQmlPluginDump)
|
||||||
get_target_property (QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION)
|
get_target_property (QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION)
|
||||||
@ -35,7 +36,6 @@ function(add_qmlplugin TARGET)
|
|||||||
${QMLPLUGIN_SOURCES}
|
${QMLPLUGIN_SOURCES}
|
||||||
)
|
)
|
||||||
set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/lib)
|
set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/lib)
|
||||||
add_custom_target("${TARGET}-qmlfiles" SOURCES ${QMLPLUGIN_QMLFILES})
|
|
||||||
|
|
||||||
if(QMLPLUGIN_NO_AUTORCC)
|
if(QMLPLUGIN_NO_AUTORCC)
|
||||||
set_target_properties(${TARGET} PROPERTIES AUTOMOC OFF)
|
set_target_properties(${TARGET} PROPERTIES AUTOMOC OFF)
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// 应用程序版本信息
|
|
||||||
// 请勿修改此头文件,因为这个文件是自动生成的
|
|
||||||
#ifndef VERSION_H
|
#ifndef VERSION_H
|
||||||
#define VERSION_H
|
#define VERSION_H
|
||||||
|
|
||||||
|
9
.github/workflows/windows-mingw.yml
vendored
9
.github/workflows/windows-mingw.yml
vendored
@ -18,9 +18,10 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build
|
name: Build
|
||||||
runs-on: windows-2022
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
os: [windows-2022]
|
||||||
include:
|
include:
|
||||||
- qt_arch: win64_mingw
|
- qt_arch: win64_mingw
|
||||||
qt_ver: 6.5.0
|
qt_ver: 6.5.0
|
||||||
@ -35,6 +36,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Setup ninja
|
||||||
|
uses: seanmiddleditch/gha-setup-ninja@master
|
||||||
|
with:
|
||||||
|
version: 1.10.2
|
||||||
|
|
||||||
- name: Install Qt
|
- name: Install Qt
|
||||||
uses: jurplel/install-qt-action@v3
|
uses: jurplel/install-qt-action@v3
|
||||||
with:
|
with:
|
||||||
@ -62,6 +68,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
|
ninja --version
|
||||||
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\FluentUI\Qt\6.5.0\mingw_64 -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release -GNinja ..
|
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\FluentUI\Qt\6.5.0\mingw_64 -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release -GNinja ..
|
||||||
cmake --build . --target all --config Release --parallel
|
cmake --build . --target all --config Release --parallel
|
||||||
|
|
||||||
|
85
.github/workflows/windows-qt5.yml
vendored
Normal file
85
.github/workflows/windows-qt5.yml
vendored
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
name: Windows Qt5.15.2
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- '*.txt'
|
||||||
|
- 'src/**'
|
||||||
|
- 'example/**'
|
||||||
|
- 'scripts/**'
|
||||||
|
- '.github/workflows/windows_qt5.yml'
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- '*.txt'
|
||||||
|
- 'example/**'
|
||||||
|
- 'src/**'
|
||||||
|
- 'scripts/**'
|
||||||
|
- '.github/workflows/windows_qt5.yml'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [windows-2019]
|
||||||
|
include:
|
||||||
|
- qt_ver: 5.15.2
|
||||||
|
qt_arch: win32_msvc2019
|
||||||
|
msvc_arch: x86
|
||||||
|
qt_arch_install: msvc2019
|
||||||
|
env:
|
||||||
|
targetName: example.exe
|
||||||
|
fileName: example
|
||||||
|
steps:
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Install Qt
|
||||||
|
uses: jurplel/install-qt-action@v3
|
||||||
|
with:
|
||||||
|
version: ${{ matrix.qt_ver }}
|
||||||
|
arch: ${{ matrix.qt_arch }}
|
||||||
|
cache: ${{steps.cache-qt.outputs.cache-hit}}
|
||||||
|
|
||||||
|
- name: msvc-build
|
||||||
|
id: build
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.msvc_arch }}
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\FluentUI\Qt\5.15.2\msvc2019 -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=Release -GNinja ..
|
||||||
|
cmake --build . --target all --config Release --parallel
|
||||||
|
echo winSdkDir=%WindowsSdkDir% >> %GITHUB_ENV%
|
||||||
|
echo winSdkVer=%WindowsSdkVersion% >> %GITHUB_ENV%
|
||||||
|
echo vcToolsInstallDir=%VCToolsInstallDir% >> %GITHUB_ENV%
|
||||||
|
echo vcToolsRedistDir=%VCToolsRedistDir% >> %GITHUB_ENV%
|
||||||
|
|
||||||
|
- name: package
|
||||||
|
id: package
|
||||||
|
env:
|
||||||
|
archiveName: ${{ env.fileName }}-${{ matrix.qt_arch }}-${{ matrix.qt_ver }}
|
||||||
|
msvcArch: ${{ matrix.msvc_arch }}
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
& scripts\windows-publish.ps1 ${env:archiveName} ${env:targetName}
|
||||||
|
# 记录packageName给后续step
|
||||||
|
$name = ${env:archiveName}
|
||||||
|
echo "::set-output name=packageName::$name"
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: ${{ steps.package.outputs.packageName }}
|
||||||
|
path: ${{ steps.package.outputs.packageName }}
|
||||||
|
|
||||||
|
- name: uploadRelease
|
||||||
|
if: startsWith(github.event.ref, 'refs/tags/')
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: ${{ steps.package.outputs.packageName }}.zip
|
||||||
|
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.zip
|
||||||
|
tag: ${{ github.ref }}
|
||||||
|
overwrite: true
|
1
.github/workflows/windows.yml
vendored
1
.github/workflows/windows.yml
vendored
@ -49,6 +49,7 @@ jobs:
|
|||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.msvc_arch }}
|
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.msvc_arch }}
|
||||||
|
ninja --version
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\FluentUI\Qt\6.5.0\msvc2019_64 -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=Release -GNinja ..
|
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\FluentUI\Qt\6.5.0\msvc2019_64 -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=Release -GNinja ..
|
||||||
|
BIN
3rdparty/Win_x86/mingw/libcrypto-1_1.dll
vendored
Normal file
BIN
3rdparty/Win_x86/mingw/libcrypto-1_1.dll
vendored
Normal file
Binary file not shown.
BIN
3rdparty/Win_x86/mingw/libssl-1_1.dll
vendored
Normal file
BIN
3rdparty/Win_x86/mingw/libssl-1_1.dll
vendored
Normal file
Binary file not shown.
BIN
3rdparty/Win_x86/msvc/libcrypto-1_1.dll
vendored
Normal file
BIN
3rdparty/Win_x86/msvc/libcrypto-1_1.dll
vendored
Normal file
Binary file not shown.
BIN
3rdparty/Win_x86/msvc/libssl-1_1.dll
vendored
Normal file
BIN
3rdparty/Win_x86/msvc/libssl-1_1.dll
vendored
Normal file
Binary file not shown.
@ -288,3 +288,28 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
|
************************************************************************************
|
||||||
|
qml-colorpicker
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Ruslan Shestopalyuk
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
@ -53,7 +53,7 @@ endforeach(filepath)
|
|||||||
|
|
||||||
if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
||||||
#遍历所有qml文件
|
#遍历所有qml文件
|
||||||
file(GLOB_RECURSE QML_PATHS *.qml qmldir)
|
file(GLOB_RECURSE QML_PATHS *.qml)
|
||||||
foreach(filepath ${QML_PATHS})
|
foreach(filepath ${QML_PATHS})
|
||||||
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
|
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
|
||||||
if(${filepath} MATCHES "Qt${QT_VERSION_MAJOR}/")
|
if(${filepath} MATCHES "Qt${QT_VERSION_MAJOR}/")
|
||||||
@ -64,7 +64,7 @@ if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
|||||||
endforeach(filepath)
|
endforeach(filepath)
|
||||||
|
|
||||||
#遍历所有资源文件
|
#遍历所有资源文件
|
||||||
file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp)
|
file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp qmldir)
|
||||||
foreach(filepath ${RES_PATHS})
|
foreach(filepath ${RES_PATHS})
|
||||||
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
|
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
|
||||||
list(APPEND resource_files ${filename})
|
list(APPEND resource_files ${filename})
|
||||||
@ -93,12 +93,17 @@ else ()
|
|||||||
)
|
)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
#复制动态库到可执行文件同级目录下
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
#复制动态库到可执行文件同级目录下
|
||||||
|
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||||
|
set(3RDPARTY_ARCH_DIR ${CMAKE_SOURCE_DIR}/3rdparty/Win_x86)
|
||||||
|
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
set(3RDPARTY_ARCH_DIR ${CMAKE_SOURCE_DIR}/3rdparty/Win_x64)
|
||||||
|
endif()
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
set(DLLPATH ${CMAKE_SOURCE_DIR}/3rdparty/msvc/*.dll)
|
set(DLLPATH ${3RDPARTY_ARCH_DIR}/msvc/*.dll)
|
||||||
else()
|
else()
|
||||||
set(DLLPATH ${CMAKE_SOURCE_DIR}/3rdparty/mingw/*.dll)
|
set(DLLPATH ${3RDPARTY_ARCH_DIR}/mingw/*.dll)
|
||||||
endif()
|
endif()
|
||||||
string(REPLACE "/" ${PATH_SEPARATOR} DLLPATH "${DLLPATH}")
|
string(REPLACE "/" ${PATH_SEPARATOR} DLLPATH "${DLLPATH}")
|
||||||
file(GLOB DLL_FILES ${DLLPATH})
|
file(GLOB DLL_FILES ${DLLPATH})
|
||||||
@ -122,7 +127,7 @@ else()
|
|||||||
target_include_directories(example PRIVATE
|
target_include_directories(example PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
)
|
)
|
||||||
target_sources(example PRIVATE resource.qrc)
|
target_sources(example PRIVATE example.qrc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#导入component头文件,不然通过QML_NAMED_ELEMENT生成的c++类会找不到头文件报错
|
#导入component头文件,不然通过QML_NAMED_ELEMENT生成的c++类会找不到头文件报错
|
||||||
@ -130,6 +135,13 @@ target_include_directories(example PRIVATE
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/component
|
${CMAKE_CURRENT_SOURCE_DIR}/src/component
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#如何是静态库则需要手动注册插件,导入FluentUI.h头文件
|
||||||
|
if(FLUENTUI_BUILD_STATIC_LIB)
|
||||||
|
target_include_directories(example PRIVATE
|
||||||
|
${CMAKE_SOURCE_DIR}/src
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
#设置属性
|
#设置属性
|
||||||
set_target_properties(example PROPERTIES
|
set_target_properties(example PROPERTIES
|
||||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||||
@ -139,18 +151,6 @@ set_target_properties(example PROPERTIES
|
|||||||
WIN32_EXECUTABLE TRUE
|
WIN32_EXECUTABLE TRUE
|
||||||
)
|
)
|
||||||
|
|
||||||
#链接库
|
|
||||||
if (FLUENTUI_BUILD_STATIC_LIB)
|
|
||||||
target_link_libraries(example PRIVATE
|
|
||||||
Qt${QT_VERSION_MAJOR}::Quick
|
|
||||||
Qt${QT_VERSION_MAJOR}::Svg
|
|
||||||
Qt${QT_VERSION_MAJOR}::Network
|
|
||||||
fluentui
|
|
||||||
fluentuiplugin
|
|
||||||
FramelessHelper::Core
|
|
||||||
FramelessHelper::Quick
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
target_link_libraries(example PRIVATE
|
target_link_libraries(example PRIVATE
|
||||||
Qt${QT_VERSION_MAJOR}::Quick
|
Qt${QT_VERSION_MAJOR}::Quick
|
||||||
Qt${QT_VERSION_MAJOR}::Svg
|
Qt${QT_VERSION_MAJOR}::Svg
|
||||||
@ -159,7 +159,6 @@ else()
|
|||||||
FramelessHelper::Core
|
FramelessHelper::Core
|
||||||
FramelessHelper::Quick
|
FramelessHelper::Quick
|
||||||
)
|
)
|
||||||
endif()
|
|
||||||
|
|
||||||
#安装
|
#安装
|
||||||
install(TARGETS example
|
install(TARGETS example
|
||||||
|
@ -126,7 +126,6 @@
|
|||||||
<file>qml/component/CustomWindow.qml</file>
|
<file>qml/component/CustomWindow.qml</file>
|
||||||
<file>qml/global/ItemsFooter.qml</file>
|
<file>qml/global/ItemsFooter.qml</file>
|
||||||
<file>qml/global/ItemsOriginal.qml</file>
|
<file>qml/global/ItemsOriginal.qml</file>
|
||||||
<file>qml/global/MainEvent.qml</file>
|
|
||||||
<file>qml/global/qmldir</file>
|
<file>qml/global/qmldir</file>
|
||||||
<file>qml/page/T_Acrylic.qml</file>
|
<file>qml/page/T_Acrylic.qml</file>
|
||||||
<file>qml/page/T_Awesome.qml</file>
|
<file>qml/page/T_Awesome.qml</file>
|
||||||
@ -186,5 +185,7 @@
|
|||||||
<file>res/image/image_1.jpg</file>
|
<file>res/image/image_1.jpg</file>
|
||||||
<file>qml/window/PageWindow.qml</file>
|
<file>qml/window/PageWindow.qml</file>
|
||||||
<file>qml/page/T_StaggeredView.qml</file>
|
<file>qml/page/T_StaggeredView.qml</file>
|
||||||
|
<file>qml/viewmodel/SettingsViewModel.qml</file>
|
||||||
|
<file>qml/viewmodel/TextBoxViewModel.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
@ -8,6 +8,13 @@ Window {
|
|||||||
id: app
|
id: app
|
||||||
flags: Qt.SplashScreen
|
flags: Qt.SplashScreen
|
||||||
|
|
||||||
|
Connections{
|
||||||
|
target: FluTheme
|
||||||
|
function onDarkModeChanged(){
|
||||||
|
SettingsHelper.saveDarkMode(FluTheme.darkMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FluHttpInterceptor{
|
FluHttpInterceptor{
|
||||||
id:interceptor
|
id:interceptor
|
||||||
function onIntercept(request){
|
function onIntercept(request){
|
||||||
@ -26,7 +33,7 @@ Window {
|
|||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
FluApp.init(app)
|
FluApp.init(app)
|
||||||
FluTheme.darkMode = FluThemeType.System
|
FluTheme.darkMode = SettingsHelper.getDarkMode()
|
||||||
FluTheme.enableAnimation = true
|
FluTheme.enableAnimation = true
|
||||||
FluApp.routes = {
|
FluApp.routes = {
|
||||||
"/":"qrc:/example/qml/window/MainWindow.qml",
|
"/":"qrc:/example/qml/window/MainWindow.qml",
|
||||||
|
@ -80,7 +80,6 @@ FluExpander{
|
|||||||
"FluIcon",
|
"FluIcon",
|
||||||
"FluIconButton",
|
"FluIconButton",
|
||||||
"FluInfoBar",
|
"FluInfoBar",
|
||||||
"FluItem",
|
|
||||||
"FluMediaPlayer",
|
"FluMediaPlayer",
|
||||||
"FluMenu",
|
"FluMenu",
|
||||||
"FluMenuItem",
|
"FluMenuItem",
|
||||||
@ -139,7 +138,8 @@ FluExpander{
|
|||||||
"FluChart",
|
"FluChart",
|
||||||
"FluRangeSlider",
|
"FluRangeSlider",
|
||||||
"FluStaggeredView",
|
"FluStaggeredView",
|
||||||
"FluProgressButton"
|
"FluProgressButton",
|
||||||
|
"FluLoadingButton"
|
||||||
];
|
];
|
||||||
code = code.replace(/\n/g, "<br>");
|
code = code.replace(/\n/g, "<br>");
|
||||||
code = code.replace(/ /g, " ");
|
code = code.replace(/ /g, " ");
|
||||||
|
@ -477,6 +477,9 @@ FluObject{
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSearchData(){
|
function getSearchData(){
|
||||||
|
if(!navigationView){
|
||||||
|
return
|
||||||
|
}
|
||||||
var arr = []
|
var arr = []
|
||||||
var items = navigationView.getItems();
|
var items = navigationView.getItems();
|
||||||
for(var i=0;i<items.length;i++){
|
for(var i=0;i<items.length;i++){
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
pragma Singleton
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import FluentUI
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
property int displayMode : FluNavigationViewType.Auto
|
|
||||||
}
|
|
@ -1,3 +1,2 @@
|
|||||||
singleton ItemsOriginal 1.0 ItemsOriginal.qml
|
singleton ItemsOriginal 1.0 ItemsOriginal.qml
|
||||||
singleton ItemsFooter 1.0 ItemsFooter.qml
|
singleton ItemsFooter 1.0 ItemsFooter.qml
|
||||||
singleton MainEvent 1.0 MainEvent.qml
|
|
||||||
|
@ -47,10 +47,10 @@ FluScrollablePage{
|
|||||||
height: 1200/4+20
|
height: 1200/4+20
|
||||||
paddings: 10
|
paddings: 10
|
||||||
Layout.topMargin: 10
|
Layout.topMargin: 10
|
||||||
FluRectangle{
|
FluClip{
|
||||||
width: 1920/4
|
width: 1920/4
|
||||||
height: 1200/4
|
height: 1200/4
|
||||||
radius:[15,15,15,15]
|
radius:[8,8,8,8]
|
||||||
Image {
|
Image {
|
||||||
id:image
|
id:image
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
@ -213,6 +213,45 @@ FluScrollablePage{
|
|||||||
}'
|
}'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FluArea{
|
||||||
|
Layout.fillWidth: true
|
||||||
|
height: 68
|
||||||
|
Layout.topMargin: 20
|
||||||
|
paddings: 10
|
||||||
|
|
||||||
|
FluLoadingButton{
|
||||||
|
id:btn_loading
|
||||||
|
loading:loading_button_switch.checked
|
||||||
|
text:"Loading Button"
|
||||||
|
anchors{
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
left: parent.left
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FluToggleSwitch{
|
||||||
|
id:loading_button_switch
|
||||||
|
checked: true
|
||||||
|
anchors{
|
||||||
|
right: parent.right
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
text:"Loading"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CodeExpander{
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: -1
|
||||||
|
code:'FluLoadingButton{
|
||||||
|
text:"Loading Button"
|
||||||
|
onClicked: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FluArea{
|
FluArea{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
@ -9,10 +9,10 @@ FluScrollablePage{
|
|||||||
|
|
||||||
title:"Captcha"
|
title:"Captcha"
|
||||||
|
|
||||||
|
|
||||||
FluCaptcha{
|
FluCaptcha{
|
||||||
id:captcha
|
id:captcha
|
||||||
Layout.topMargin: 20
|
Layout.topMargin: 20
|
||||||
|
ignoreCase:switch_case.checked
|
||||||
MouseArea{
|
MouseArea{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
@ -30,6 +30,13 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FluToggleSwitch{
|
||||||
|
id:switch_case
|
||||||
|
text:"Ignore Case"
|
||||||
|
checked: true
|
||||||
|
Layout.topMargin: 10
|
||||||
|
}
|
||||||
|
|
||||||
RowLayout{
|
RowLayout{
|
||||||
spacing: 10
|
spacing: 10
|
||||||
Layout.topMargin: 10
|
Layout.topMargin: 10
|
||||||
@ -49,6 +56,4 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,14 @@ FluScrollablePage{
|
|||||||
FluText{
|
FluText{
|
||||||
text:"轮播图,支持无限轮播,无限滑动,用ListView实现的组件"
|
text:"轮播图,支持无限轮播,无限滑动,用ListView实现的组件"
|
||||||
}
|
}
|
||||||
|
Item{
|
||||||
|
width: 400
|
||||||
|
height: 300
|
||||||
|
FluShadow{
|
||||||
|
radius: 8
|
||||||
|
}
|
||||||
FluCarousel{
|
FluCarousel{
|
||||||
radius:[5,5,5,5]
|
anchors.fill: parent
|
||||||
delegate: Component{
|
delegate: Component{
|
||||||
Image {
|
Image {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@ -54,6 +60,7 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FluArea{
|
FluArea{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@ -66,8 +73,14 @@ FluScrollablePage{
|
|||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
left:parent.left
|
left:parent.left
|
||||||
}
|
}
|
||||||
|
Item{
|
||||||
|
width: 400
|
||||||
|
height: 300
|
||||||
|
FluShadow{
|
||||||
|
radius: 8
|
||||||
|
}
|
||||||
FluCarousel{
|
FluCarousel{
|
||||||
radius:[15,15,15,15]
|
anchors.fill: parent
|
||||||
loopTime:1500
|
loopTime:1500
|
||||||
indicatorGravity: Qt.AlignHCenter | Qt.AlignTop
|
indicatorGravity: Qt.AlignHCenter | Qt.AlignTop
|
||||||
indicatorMarginTop:15
|
indicatorMarginTop:15
|
||||||
@ -107,6 +120,8 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeExpander{
|
CodeExpander{
|
||||||
|
@ -46,7 +46,6 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
FluComboBox {
|
FluComboBox {
|
||||||
editable: true
|
editable: true
|
||||||
font:FluTextStyle.BodyStrong
|
|
||||||
model: ListModel {
|
model: ListModel {
|
||||||
id: model_2
|
id: model_2
|
||||||
ListElement { text: "Banana" }
|
ListElement { text: "Banana" }
|
||||||
|
@ -27,6 +27,7 @@ FluScrollablePage{
|
|||||||
id: bg
|
id: bg
|
||||||
fillMode:Image.PreserveAspectCrop
|
fillMode:Image.PreserveAspectCrop
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
asynchronous: true
|
||||||
verticalAlignment: Qt.AlignTop
|
verticalAlignment: Qt.AlignTop
|
||||||
sourceSize: Qt.size(960,640)
|
sourceSize: Qt.size(960,640)
|
||||||
source: "qrc:/example/res/image/bg_home_header.png"
|
source: "qrc:/example/res/image/bg_home_header.png"
|
||||||
@ -49,33 +50,19 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView{
|
Component{
|
||||||
id: list
|
id:com_grallery
|
||||||
anchors{
|
Item{
|
||||||
left: parent.left
|
|
||||||
right: parent.right
|
|
||||||
bottom: parent.bottom
|
|
||||||
}
|
|
||||||
orientation: ListView.Horizontal
|
|
||||||
height: 240
|
|
||||||
model: model_header
|
|
||||||
header: Item{height: 10;width: 10}
|
|
||||||
footer: Item{height: 10;width: 10}
|
|
||||||
ScrollBar.horizontal: FluScrollBar{
|
|
||||||
id: scrollbar_header
|
|
||||||
}
|
|
||||||
clip: false
|
|
||||||
delegate:Item{
|
|
||||||
id: control
|
id: control
|
||||||
width: 220
|
width: 220
|
||||||
height: 240
|
height: 240
|
||||||
FluShadow{
|
FluShadow{
|
||||||
radius:8
|
radius:5
|
||||||
anchors.fill: item_content
|
anchors.fill: item_content
|
||||||
}
|
}
|
||||||
FluItem{
|
FluClip{
|
||||||
id:item_content
|
id:item_content
|
||||||
radius: [8,8,8,8]
|
radius: [5,5,5,5]
|
||||||
width: 200
|
width: 200
|
||||||
height: 220
|
height: 220
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@ -89,20 +76,15 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
Rectangle{
|
Rectangle{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: 8
|
radius: 5
|
||||||
color:{
|
color:FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03)
|
||||||
if(FluTheme.dark){
|
visible: item_mouse.containsMouse
|
||||||
if(item_mouse.containsMouse){
|
|
||||||
return Qt.rgba(1,1,1,0.03)
|
|
||||||
}
|
|
||||||
return Qt.rgba(0,0,0,0.0)
|
|
||||||
}else{
|
|
||||||
if(item_mouse.containsMouse){
|
|
||||||
return Qt.rgba(0,0,0,0.03)
|
|
||||||
}
|
|
||||||
return Qt.rgba(0,0,0,0.0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Rectangle{
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: 5
|
||||||
|
color:Qt.rgba(0,0,0,0.0)
|
||||||
|
visible: !item_mouse.containsMouse
|
||||||
}
|
}
|
||||||
ColumnLayout{
|
ColumnLayout{
|
||||||
Image {
|
Image {
|
||||||
@ -154,11 +136,31 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ListView{
|
||||||
|
id: list
|
||||||
|
anchors{
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
orientation: ListView.Horizontal
|
||||||
|
height: 240
|
||||||
|
model: model_header
|
||||||
|
header: Item{height: 10;width: 10}
|
||||||
|
footer: Item{height: 10;width: 10}
|
||||||
|
ScrollBar.horizontal: FluScrollBar{
|
||||||
|
id: scrollbar_header
|
||||||
|
}
|
||||||
|
clip: false
|
||||||
|
delegate: com_grallery
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component{
|
Component{
|
||||||
id:com_item
|
id:com_item
|
||||||
Item{
|
Item{
|
||||||
|
property string desc: modelData.desc
|
||||||
width: 320
|
width: 320
|
||||||
height: 120
|
height: 120
|
||||||
FluArea{
|
FluArea{
|
||||||
@ -194,7 +196,6 @@ FluScrollablePage{
|
|||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FluText{
|
FluText{
|
||||||
id:item_title
|
id:item_title
|
||||||
text:modelData.title
|
text:modelData.title
|
||||||
@ -205,10 +206,9 @@ FluScrollablePage{
|
|||||||
top: item_icon.top
|
top: item_icon.top
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FluText{
|
FluText{
|
||||||
id:item_desc
|
id:item_desc
|
||||||
text:modelData.desc
|
text:desc
|
||||||
color:FluColors.Grey120
|
color:FluColors.Grey120
|
||||||
wrapMode: Text.WrapAnywhere
|
wrapMode: Text.WrapAnywhere
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
|
@ -11,6 +11,7 @@ FluContentPage{
|
|||||||
|
|
||||||
title:"Http"
|
title:"Http"
|
||||||
property string cacheDirPath: FluTools.getApplicationDirPath() + "/cache/http"
|
property string cacheDirPath: FluTools.getApplicationDirPath() + "/cache/http"
|
||||||
|
property bool isDownCompleted: false
|
||||||
|
|
||||||
FluHttp{
|
FluHttp{
|
||||||
id:http
|
id:http
|
||||||
@ -171,6 +172,10 @@ FluContentPage{
|
|||||||
}
|
}
|
||||||
onSuccess:
|
onSuccess:
|
||||||
(result)=>{
|
(result)=>{
|
||||||
|
if(!isDownCompleted){
|
||||||
|
tour.open()
|
||||||
|
isDownCompleted = true
|
||||||
|
}
|
||||||
showSuccess(result)
|
showSuccess(result)
|
||||||
}
|
}
|
||||||
onDownloadProgress:
|
onDownloadProgress:
|
||||||
@ -281,6 +286,13 @@ FluContentPage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FluTour{
|
||||||
|
id:tour
|
||||||
|
steps:[
|
||||||
|
{title:"友情提示",description: "下载已完成,左击这里可以打开文件所在路径,右击可以弹出菜单删除文件!",target:()=>btn_breakpoint_download}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
HttpCallable{
|
HttpCallable{
|
||||||
id:callable_upload
|
id:callable_upload
|
||||||
onStart: {
|
onStart: {
|
||||||
|
@ -12,7 +12,7 @@ FluScrollablePage{
|
|||||||
FluArea{
|
FluArea{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 20
|
Layout.topMargin: 20
|
||||||
height: 240
|
height: 270
|
||||||
paddings: 10
|
paddings: 10
|
||||||
ColumnLayout{
|
ColumnLayout{
|
||||||
spacing: 14
|
spacing: 14
|
||||||
@ -44,6 +44,12 @@ FluScrollablePage{
|
|||||||
showSuccess("这是一个Success样式的InfoBar这是一个Success样式的InfoBar")
|
showSuccess("这是一个Success样式的InfoBar这是一个Success样式的InfoBar")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
FluButton{
|
||||||
|
text:"手动关闭的InfoBar"
|
||||||
|
onClicked: {
|
||||||
|
showInfo("这是一个Info样式的InfoBar",0,"支持手动关闭")
|
||||||
|
}
|
||||||
|
}
|
||||||
FluButton{
|
FluButton{
|
||||||
text:"Loading"
|
text:"Loading"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
@ -3,7 +3,6 @@ import QtQuick.Controls
|
|||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import QtQuick.Window
|
import QtQuick.Window
|
||||||
import FluentUI
|
import FluentUI
|
||||||
import Qt5Compat.GraphicalEffects
|
|
||||||
import "qrc:///example/qml/component"
|
import "qrc:///example/qml/component"
|
||||||
|
|
||||||
FluScrollablePage{
|
FluScrollablePage{
|
||||||
|
@ -68,7 +68,7 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
RowLayout{
|
RowLayout{
|
||||||
spacing: 14
|
spacing: 14
|
||||||
FluRectangle{
|
FluClip{
|
||||||
width: 50
|
width: 50
|
||||||
height: 50
|
height: 50
|
||||||
radius:[25,0,25,25]
|
radius:[25,0,25,25]
|
||||||
@ -79,7 +79,7 @@ FluScrollablePage{
|
|||||||
sourceSize: Qt.size(width,height)
|
sourceSize: Qt.size(width,height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FluRectangle{
|
FluClip{
|
||||||
width: 50
|
width: 50
|
||||||
height: 50
|
height: 50
|
||||||
radius:[10,10,10,10]
|
radius:[10,10,10,10]
|
||||||
@ -90,7 +90,7 @@ FluScrollablePage{
|
|||||||
source: "qrc:/example/res/svg/avatar_2.svg"
|
source: "qrc:/example/res/svg/avatar_2.svg"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FluRectangle{
|
FluClip{
|
||||||
width: 50
|
width: 50
|
||||||
height: 50
|
height: 50
|
||||||
radius:[25,25,25,25]
|
radius:[25,25,25,25]
|
||||||
@ -101,7 +101,7 @@ FluScrollablePage{
|
|||||||
source: "qrc:/example/res/svg/avatar_3.svg"
|
source: "qrc:/example/res/svg/avatar_3.svg"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FluRectangle{
|
FluClip{
|
||||||
width: 50
|
width: 50
|
||||||
height: 50
|
height: 50
|
||||||
radius:[0,25,25,25]
|
radius:[0,25,25,25]
|
||||||
@ -113,10 +113,10 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FluRectangle{
|
FluClip{
|
||||||
width: 1920/5
|
width: 1920/5
|
||||||
height: 1200/5
|
height: 1200/5
|
||||||
radius:[15,15,15,15]
|
radius:[8,8,8,8]
|
||||||
Image {
|
Image {
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
source: "qrc:/example/res/image/banner_1.jpg"
|
source: "qrc:/example/res/image/banner_1.jpg"
|
||||||
|
@ -30,9 +30,10 @@ FluScrollablePage{
|
|||||||
Layout.topMargin: 10
|
Layout.topMargin: 10
|
||||||
Layout.leftMargin: 4
|
Layout.leftMargin: 4
|
||||||
Layout.bottomMargin: 4
|
Layout.bottomMargin: 4
|
||||||
|
radius: 4
|
||||||
color: FluTheme.dark ? FluColors.Black : FluColors.White
|
color: FluTheme.dark ? FluColors.Black : FluColors.White
|
||||||
FluShadow{
|
FluShadow{
|
||||||
radius: 0
|
radius: 4
|
||||||
color: FluTheme.primaryColor.dark
|
color: FluTheme.primaryColor.dark
|
||||||
}
|
}
|
||||||
Image{
|
Image{
|
||||||
|
@ -5,11 +5,90 @@ import QtQuick.Controls
|
|||||||
import FluentUI
|
import FluentUI
|
||||||
import "qrc:///example/qml/global"
|
import "qrc:///example/qml/global"
|
||||||
import "qrc:///example/qml/component"
|
import "qrc:///example/qml/component"
|
||||||
|
import "qrc:///example/qml/viewmodel"
|
||||||
|
|
||||||
FluScrollablePage{
|
FluScrollablePage{
|
||||||
|
|
||||||
title:"Settings"
|
title:"Settings"
|
||||||
|
|
||||||
|
SettingsViewModel{
|
||||||
|
id:viewmodel_settings
|
||||||
|
}
|
||||||
|
|
||||||
|
FluEvent{
|
||||||
|
id:event_checkupdate_finish
|
||||||
|
name: "checkUpdateFinish"
|
||||||
|
onTriggered: {
|
||||||
|
btn_checkupdate.loading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
FluEventBus.registerEvent(event_checkupdate_finish)
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
FluEventBus.unRegisterEvent(event_checkupdate_finish)
|
||||||
|
}
|
||||||
|
|
||||||
|
FluArea{
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 20
|
||||||
|
height: 60
|
||||||
|
paddings: 10
|
||||||
|
Row{
|
||||||
|
spacing: 20
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
FluText{
|
||||||
|
text:"当前版本 v%1".arg(AppInfo.version)
|
||||||
|
font: FluTextStyle.Body
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
FluLoadingButton{
|
||||||
|
id:btn_checkupdate
|
||||||
|
text:"检查更新"
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: {
|
||||||
|
loading = true
|
||||||
|
FluEventBus.post("checkUpdate")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FluArea{
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 20
|
||||||
|
height: 50
|
||||||
|
paddings: 10
|
||||||
|
FluCheckBox{
|
||||||
|
text:"Software Render"
|
||||||
|
checked: SettingsHelper.getReander() === "software"
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: {
|
||||||
|
if(SettingsHelper.getReander() === "software"){
|
||||||
|
SettingsHelper.saveRender("")
|
||||||
|
}else{
|
||||||
|
SettingsHelper.saveRender("software")
|
||||||
|
}
|
||||||
|
dialog_render.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FluContentDialog{
|
||||||
|
id:dialog_render
|
||||||
|
title:"友情提示"
|
||||||
|
message:"此操作需要重启才能生效,是否重新启动?"
|
||||||
|
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
|
||||||
|
negativeText: "取消"
|
||||||
|
positiveText:"确定"
|
||||||
|
onPositiveClicked:{
|
||||||
|
window.deleteWindow()
|
||||||
|
AppInfo.restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FluArea{
|
FluArea{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 20
|
Layout.topMargin: 20
|
||||||
@ -60,10 +139,10 @@ FluScrollablePage{
|
|||||||
Repeater{
|
Repeater{
|
||||||
model: [{title:"Open",mode:FluNavigationViewType.Open},{title:"Compact",mode:FluNavigationViewType.Compact},{title:"Minimal",mode:FluNavigationViewType.Minimal},{title:"Auto",mode:FluNavigationViewType.Auto}]
|
model: [{title:"Open",mode:FluNavigationViewType.Open},{title:"Compact",mode:FluNavigationViewType.Compact},{title:"Minimal",mode:FluNavigationViewType.Minimal},{title:"Auto",mode:FluNavigationViewType.Auto}]
|
||||||
delegate: FluRadioButton{
|
delegate: FluRadioButton{
|
||||||
checked : MainEvent.displayMode===modelData.mode
|
checked : viewmodel_settings.displayMode===modelData.mode
|
||||||
text:modelData.title
|
text:modelData.title
|
||||||
clickListener:function(){
|
clickListener:function(){
|
||||||
MainEvent.displayMode = modelData.mode
|
viewmodel_settings.displayMode = modelData.mode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,10 +173,10 @@ FluScrollablePage{
|
|||||||
Repeater{
|
Repeater{
|
||||||
model: ["Zh","En"]
|
model: ["Zh","En"]
|
||||||
delegate: FluRadioButton{
|
delegate: FluRadioButton{
|
||||||
checked: appInfo.lang.objectName === modelData
|
checked: AppInfo.lang.objectName === modelData
|
||||||
text:modelData
|
text:modelData
|
||||||
clickListener:function(){
|
clickListener:function(){
|
||||||
appInfo.changeLang(modelData)
|
AppInfo.changeLang(modelData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,19 @@ import QtQuick.Layouts
|
|||||||
import QtQuick.Window
|
import QtQuick.Window
|
||||||
import FluentUI
|
import FluentUI
|
||||||
import "qrc:///example/qml/component"
|
import "qrc:///example/qml/component"
|
||||||
|
import "qrc:///example/qml/viewmodel"
|
||||||
|
|
||||||
FluScrollablePage{
|
FluScrollablePage{
|
||||||
|
|
||||||
launchMode: FluPageType.SingleInstance
|
|
||||||
|
|
||||||
title:"TextBox"
|
title:"TextBox"
|
||||||
|
|
||||||
|
TextBoxViewModel{
|
||||||
|
id:viewModel
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
console.debug("T_TextBox页面销毁了")
|
||||||
|
}
|
||||||
|
|
||||||
FluArea{
|
FluArea{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
height: 68
|
height: 68
|
||||||
@ -20,6 +27,10 @@ FluScrollablePage{
|
|||||||
placeholderText: "单行输入框"
|
placeholderText: "单行输入框"
|
||||||
disabled:text_box_switch.checked
|
disabled:text_box_switch.checked
|
||||||
cleanEnabled: true
|
cleanEnabled: true
|
||||||
|
text:viewModel.text1
|
||||||
|
onTextChanged: {
|
||||||
|
viewModel.text1 = text
|
||||||
|
}
|
||||||
anchors{
|
anchors{
|
||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
left: parent.left
|
left: parent.left
|
||||||
@ -84,6 +95,10 @@ FluScrollablePage{
|
|||||||
FluMultilineTextBox{
|
FluMultilineTextBox{
|
||||||
id:multiine_textbox
|
id:multiine_textbox
|
||||||
placeholderText: "多行输入框"
|
placeholderText: "多行输入框"
|
||||||
|
text:viewModel.text2
|
||||||
|
onTextChanged: {
|
||||||
|
viewModel.text2 = text
|
||||||
|
}
|
||||||
disabled:text_box_multi_switch.checked
|
disabled:text_box_multi_switch.checked
|
||||||
anchors{
|
anchors{
|
||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
|
@ -5,152 +5,127 @@ import QtQuick.Controls
|
|||||||
import FluentUI
|
import FluentUI
|
||||||
import "qrc:///example/qml/component"
|
import "qrc:///example/qml/component"
|
||||||
|
|
||||||
FluScrollablePage {
|
FluContentPage {
|
||||||
|
|
||||||
title:"TreeView"
|
title:"TreeView"
|
||||||
|
|
||||||
function randomName() {
|
function treeData(){
|
||||||
var names = ["张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"]
|
const dig = (path = '0', level = 4) => {
|
||||||
return names[Math.floor(Math.random() * names.length)]
|
const list = [];
|
||||||
|
for (let i = 0; i < 6; i += 1) {
|
||||||
|
const key = `${path}-${i}`;
|
||||||
|
const treeNode = {
|
||||||
|
title: key,
|
||||||
|
key,
|
||||||
|
};
|
||||||
|
if (level > 0) {
|
||||||
|
treeNode.children = dig(key, level - 1);
|
||||||
|
}
|
||||||
|
list.push(treeNode);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
};
|
||||||
|
return dig();
|
||||||
}
|
}
|
||||||
|
|
||||||
function randomCompany() {
|
Column{
|
||||||
var companies = ["阿里巴巴", "腾讯", "百度", "京东", "华为", "小米", "字节跳动", "美团", "滴滴"]
|
id:layout_column
|
||||||
return companies[Math.floor(Math.random() * companies.length)]
|
spacing: 12
|
||||||
}
|
width: 300
|
||||||
|
|
||||||
function randomDepartment() {
|
|
||||||
var departments = ["技术部", "销售部", "市场部", "人事部", "财务部", "客服部", "产品部", "设计部", "运营部"]
|
|
||||||
return departments[Math.floor(Math.random() * departments.length)]
|
|
||||||
}
|
|
||||||
|
|
||||||
function createEmployee() {
|
|
||||||
var name = randomName()
|
|
||||||
return tree_view.createItem(name, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
function createSubtree(numEmployees) {
|
|
||||||
var employees = []
|
|
||||||
for (var i = 0; i < numEmployees; i++) {
|
|
||||||
employees.push(createEmployee())
|
|
||||||
}
|
|
||||||
return tree_view.createItem(randomDepartment(), true, employees)
|
|
||||||
}
|
|
||||||
|
|
||||||
function createOrg(numLevels, numSubtrees, numEmployees) {
|
|
||||||
if (numLevels === 0) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
var subtrees = []
|
|
||||||
for (var i = 0; i < numSubtrees; i++) {
|
|
||||||
subtrees.push(createSubtree(numEmployees))
|
|
||||||
}
|
|
||||||
return [tree_view.createItem(randomCompany(), true, subtrees)].concat(createOrg(numLevels - 1, numSubtrees, numEmployees))
|
|
||||||
}
|
|
||||||
|
|
||||||
FluArea{
|
|
||||||
id:layout_actions
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 20
|
|
||||||
height: 50
|
|
||||||
paddings: 10
|
|
||||||
RowLayout{
|
|
||||||
spacing: 14
|
|
||||||
FluDropDownButton{
|
|
||||||
id:btn_selection_model
|
|
||||||
Layout.preferredWidth: 140
|
|
||||||
text:"None"
|
|
||||||
FluMenuItem{
|
|
||||||
text:"None"
|
|
||||||
onClicked: {
|
|
||||||
btn_selection_model.text = text
|
|
||||||
tree_view.selectionMode = FluTabViewType.Equal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FluMenuItem{
|
|
||||||
text:"Single"
|
|
||||||
onClicked: {
|
|
||||||
btn_selection_model.text = text
|
|
||||||
tree_view.selectionMode = FluTabViewType.SizeToContent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FluMenuItem{
|
|
||||||
text:"Muiltple"
|
|
||||||
onClicked: {
|
|
||||||
btn_selection_model.text = text
|
|
||||||
tree_view.selectionMode = FluTabViewType.Compact
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FluFilledButton{
|
|
||||||
text:"获取选中的数据"
|
|
||||||
onClicked: {
|
|
||||||
if(tree_view.selectionMode === FluTreeViewType.None){
|
|
||||||
showError("当前非选择模式,没有选中的数据")
|
|
||||||
}
|
|
||||||
if(tree_view.selectionMode === FluTreeViewType.Single){
|
|
||||||
if(!tree_view.signleData()){
|
|
||||||
showError("没有选中数据")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
showSuccess(tree_view.signleData().text)
|
|
||||||
}
|
|
||||||
if(tree_view.selectionMode === FluTreeViewType.Multiple){
|
|
||||||
if(tree_view.multipData().length===0){
|
|
||||||
showError("没有选中数据")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var info = []
|
|
||||||
tree_view.multipData().map((value)=>info.push(value.text))
|
|
||||||
showSuccess(info.join(","))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FluArea{
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 10
|
|
||||||
paddings: 10
|
|
||||||
height: 400
|
|
||||||
FluTreeView{
|
|
||||||
id:tree_view
|
|
||||||
width:240
|
|
||||||
anchors{
|
anchors{
|
||||||
|
topMargin: 20
|
||||||
top:parent.top
|
top:parent.top
|
||||||
left: parent.left
|
left: parent.left
|
||||||
|
leftMargin: 10
|
||||||
bottom:parent.bottom
|
bottom:parent.bottom
|
||||||
}
|
bottomMargin: 20
|
||||||
onItemClicked:
|
|
||||||
(model)=>{
|
|
||||||
showSuccess(model.text)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
FluText{
|
||||||
var org = createOrg(3, 3, 3)
|
text:"共计%1条数据,当前显示的%2条数据".arg(tree_view.count()).arg(tree_view.visibleCount())
|
||||||
createItem()
|
|
||||||
updateData(org)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeExpander{
|
FluText{
|
||||||
Layout.fillWidth: true
|
text:"共计选中%1条数据".arg(tree_view.selectionModel().length)
|
||||||
Layout.topMargin: -1
|
}
|
||||||
code:'FluTreeView{
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FluArea{
|
||||||
|
anchors{
|
||||||
|
left: layout_column.right
|
||||||
|
top: parent.top
|
||||||
|
bottom: parent.bottom
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: 5
|
||||||
|
topMargin: 5
|
||||||
|
bottomMargin: 5
|
||||||
|
}
|
||||||
|
FluShadow{}
|
||||||
|
FluTreeView{
|
||||||
id:tree_view
|
id:tree_view
|
||||||
width:240
|
anchors.fill: parent
|
||||||
height:600
|
cellHeight: slider_cell_height.value
|
||||||
|
draggable:switch_draggable.checked
|
||||||
|
showLine: switch_showline.checked
|
||||||
|
checkable:switch_checkable.checked
|
||||||
|
depthPadding: slider_depth_padding.value
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
var datas = []
|
var data = treeData()
|
||||||
datas.push(createItem("Node1",false))
|
dataSource = data
|
||||||
datas.push(createItem("Node2",false))
|
|
||||||
datas.push(createItem("Node2",true,[createItem("Node2-1",false),createItem("Node2-2",false)]))
|
|
||||||
updateData(datas)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
13
example/qml-Qt6/viewmodel/SettingsViewModel.qml
Normal file
13
example/qml-Qt6/viewmodel/SettingsViewModel.qml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import QtQuick
|
||||||
|
import FluentUI
|
||||||
|
|
||||||
|
FluViewModel{
|
||||||
|
|
||||||
|
objectName: "SettingsViewModel"
|
||||||
|
property int displayMode
|
||||||
|
|
||||||
|
onInitData: {
|
||||||
|
displayMode = FluNavigationViewType.Auto
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
8
example/qml-Qt6/viewmodel/TextBoxViewModel.qml
Normal file
8
example/qml-Qt6/viewmodel/TextBoxViewModel.qml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import QtQuick
|
||||||
|
import FluentUI
|
||||||
|
|
||||||
|
FluViewModel {
|
||||||
|
objectName: "TextBoxView"
|
||||||
|
property string text1
|
||||||
|
property string text2
|
||||||
|
}
|
@ -35,7 +35,7 @@ CustomWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
FluText{
|
FluText{
|
||||||
text:"v%1".arg(appInfo.version)
|
text:"v%1".arg(AppInfo.version)
|
||||||
font: FluTextStyle.Body
|
font: FluTextStyle.Body
|
||||||
Layout.alignment: Qt.AlignBottom
|
Layout.alignment: Qt.AlignBottom
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import FluentUI
|
|||||||
import example
|
import example
|
||||||
import "qrc:///example/qml/component"
|
import "qrc:///example/qml/component"
|
||||||
import "qrc:///example/qml/global"
|
import "qrc:///example/qml/global"
|
||||||
|
import "qrc:///example/qml/viewmodel"
|
||||||
|
|
||||||
CustomWindow {
|
CustomWindow {
|
||||||
|
|
||||||
@ -20,15 +21,32 @@ CustomWindow {
|
|||||||
appBarVisible: false
|
appBarVisible: false
|
||||||
launchMode: FluWindowType.SingleTask
|
launchMode: FluWindowType.SingleTask
|
||||||
|
|
||||||
|
SettingsViewModel{
|
||||||
|
id:viewmodel_settings
|
||||||
|
}
|
||||||
|
|
||||||
closeFunc:function(event){
|
closeFunc:function(event){
|
||||||
dialog_close.open()
|
dialog_close.open()
|
||||||
event.accepted = false
|
event.accepted = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FluEvent{
|
||||||
|
id:event_checkupdate
|
||||||
|
name: "checkUpdate"
|
||||||
|
onTriggered: {
|
||||||
|
checkUpdate(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
FluTools.setQuitOnLastWindowClosed(false)
|
FluTools.setQuitOnLastWindowClosed(false)
|
||||||
tour.open()
|
tour.open()
|
||||||
checkUpdate()
|
checkUpdate(true)
|
||||||
|
FluEventBus.registerEvent(event_checkupdate)
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
FluEventBus.unRegisterEvent(event_checkupdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemTrayIcon {
|
SystemTrayIcon {
|
||||||
@ -164,13 +182,13 @@ CustomWindow {
|
|||||||
height: parent.height
|
height: parent.height
|
||||||
z:999
|
z:999
|
||||||
//Stack模式,每次切换都会将页面压入栈中,随着栈的页面增多,消耗的内存也越多,内存消耗多就会卡顿,这时候就需要按返回将页面pop掉,释放内存。该模式可以配合FluPage中的launchMode属性,设置页面的启动模式
|
//Stack模式,每次切换都会将页面压入栈中,随着栈的页面增多,消耗的内存也越多,内存消耗多就会卡顿,这时候就需要按返回将页面pop掉,释放内存。该模式可以配合FluPage中的launchMode属性,设置页面的启动模式
|
||||||
pageMode: FluNavigationViewType.Stack
|
// pageMode: FluNavigationViewType.Stack
|
||||||
//NoStack模式,每次切换都会销毁之前的页面然后创建一个新的页面,只需消耗少量内存(推荐)
|
//NoStack模式,每次切换都会销毁之前的页面然后创建一个新的页面,只需消耗少量内存,可以配合FluViewModel保存页面数据(推荐)
|
||||||
// pageMode: FluNavigationViewType.NoStack
|
pageMode: FluNavigationViewType.NoStack
|
||||||
items: ItemsOriginal
|
items: ItemsOriginal
|
||||||
footerItems:ItemsFooter
|
footerItems:ItemsFooter
|
||||||
topPadding:FluTools.isMacos() ? 20 : 0
|
topPadding:FluTools.isMacos() ? 20 : 0
|
||||||
displayMode:MainEvent.displayMode
|
displayMode:viewmodel_settings.displayMode
|
||||||
logo: "qrc:/example/res/image/favicon.ico"
|
logo: "qrc:/example/res/image/favicon.ico"
|
||||||
title:"FluentUI"
|
title:"FluentUI"
|
||||||
onLogoClicked:{
|
onLogoClicked:{
|
||||||
@ -300,7 +318,7 @@ CustomWindow {
|
|||||||
property string body
|
property string body
|
||||||
id:dialog_update
|
id:dialog_update
|
||||||
title:"升级提示"
|
title:"升级提示"
|
||||||
message:"FluentUI目前最新版本 "+ newVerson +" -- 当前应用版本 "+appInfo.version+" \n现在是否去下载新版本?\n\n更新内容:\n"+body
|
message:"FluentUI目前最新版本 "+ newVerson +" -- 当前应用版本 "+AppInfo.version+" \n现在是否去下载新版本?\n\n更新内容:\n"+body
|
||||||
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
|
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
|
||||||
negativeText: "取消"
|
negativeText: "取消"
|
||||||
positiveText:"确定"
|
positiveText:"确定"
|
||||||
@ -311,30 +329,40 @@ CustomWindow {
|
|||||||
|
|
||||||
HttpCallable{
|
HttpCallable{
|
||||||
id:callable
|
id:callable
|
||||||
|
property bool silent: true
|
||||||
onStart: {
|
onStart: {
|
||||||
console.debug("satrt check update...")
|
console.debug("satrt check update...")
|
||||||
}
|
}
|
||||||
onFinish: {
|
onFinish: {
|
||||||
console.debug("check update finish")
|
console.debug("check update finish")
|
||||||
|
FluEventBus.post("checkUpdateFinish");
|
||||||
}
|
}
|
||||||
onSuccess:
|
onSuccess:
|
||||||
(result)=>{
|
(result)=>{
|
||||||
var data = JSON.parse(result)
|
var data = JSON.parse(result)
|
||||||
console.debug("current version "+appInfo.version)
|
console.debug("current version "+AppInfo.version)
|
||||||
console.debug("new version "+data.tag_name)
|
console.debug("new version "+data.tag_name)
|
||||||
if(data.tag_name !== appInfo.version){
|
if(data.tag_name !== AppInfo.version){
|
||||||
dialog_update.newVerson = data.tag_name
|
dialog_update.newVerson = data.tag_name
|
||||||
dialog_update.body = data.body
|
dialog_update.body = data.body
|
||||||
dialog_update.open()
|
dialog_update.open()
|
||||||
|
}else{
|
||||||
|
if(!silent){
|
||||||
|
showInfo("当前版本已经是最新版")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onError:
|
onError:
|
||||||
(status,errorString)=>{
|
(status,errorString)=>{
|
||||||
|
if(!silent){
|
||||||
|
showError("网络异常!")
|
||||||
|
}
|
||||||
console.debug(status+";"+errorString)
|
console.debug(status+";"+errorString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkUpdate(){
|
function checkUpdate(silent){
|
||||||
|
callable.silent = silent
|
||||||
var request = http.newRequest("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
|
var request = http.newRequest("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
|
||||||
http.get(request,callable);
|
http.get(request,callable);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,13 @@ Window {
|
|||||||
id: app
|
id: app
|
||||||
flags: Qt.SplashScreen
|
flags: Qt.SplashScreen
|
||||||
|
|
||||||
|
Connections{
|
||||||
|
target: FluTheme
|
||||||
|
function onDarkModeChanged(){
|
||||||
|
SettingsHelper.saveDarkMode(FluTheme.darkMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FluHttpInterceptor{
|
FluHttpInterceptor{
|
||||||
id:interceptor
|
id:interceptor
|
||||||
function onIntercept(request){
|
function onIntercept(request){
|
||||||
@ -26,7 +33,7 @@ Window {
|
|||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
FluApp.init(app)
|
FluApp.init(app)
|
||||||
FluTheme.darkMode = FluThemeType.System
|
FluTheme.darkMode = SettingsHelper.getDarkMode()
|
||||||
FluTheme.enableAnimation = true
|
FluTheme.enableAnimation = true
|
||||||
FluApp.routes = {
|
FluApp.routes = {
|
||||||
"/":"qrc:/example/qml/window/MainWindow.qml",
|
"/":"qrc:/example/qml/window/MainWindow.qml",
|
||||||
|
@ -80,7 +80,6 @@ FluExpander{
|
|||||||
"FluIcon",
|
"FluIcon",
|
||||||
"FluIconButton",
|
"FluIconButton",
|
||||||
"FluInfoBar",
|
"FluInfoBar",
|
||||||
"FluItem",
|
|
||||||
"FluMediaPlayer",
|
"FluMediaPlayer",
|
||||||
"FluMenu",
|
"FluMenu",
|
||||||
"FluMenuItem",
|
"FluMenuItem",
|
||||||
@ -139,7 +138,8 @@ FluExpander{
|
|||||||
"FluChart",
|
"FluChart",
|
||||||
"FluRangeSlider",
|
"FluRangeSlider",
|
||||||
"FluStaggeredView",
|
"FluStaggeredView",
|
||||||
"FluProgressButton"
|
"FluProgressButton",
|
||||||
|
"FluLoadingButton"
|
||||||
];
|
];
|
||||||
code = code.replace(/\n/g, "<br>");
|
code = code.replace(/\n/g, "<br>");
|
||||||
code = code.replace(/ /g, " ");
|
code = code.replace(/ /g, " ");
|
||||||
|
@ -477,6 +477,9 @@ FluObject{
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSearchData(){
|
function getSearchData(){
|
||||||
|
if(!navigationView){
|
||||||
|
return
|
||||||
|
}
|
||||||
var arr = []
|
var arr = []
|
||||||
var items = navigationView.getItems();
|
var items = navigationView.getItems();
|
||||||
for(var i=0;i<items.length;i++){
|
for(var i=0;i<items.length;i++){
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
pragma Singleton
|
|
||||||
|
|
||||||
import QtQuick 2.15
|
|
||||||
import QtQuick.Controls 2.15
|
|
||||||
import FluentUI 1.0
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
property int displayMode : FluNavigationViewType.Auto
|
|
||||||
}
|
|
@ -1,3 +1,2 @@
|
|||||||
singleton ItemsOriginal 1.0 ItemsOriginal.qml
|
singleton ItemsOriginal 1.0 ItemsOriginal.qml
|
||||||
singleton ItemsFooter 1.0 ItemsFooter.qml
|
singleton ItemsFooter 1.0 ItemsFooter.qml
|
||||||
singleton MainEvent 1.0 MainEvent.qml
|
|
||||||
|
@ -48,10 +48,10 @@ FluScrollablePage{
|
|||||||
height: 1200/4+20
|
height: 1200/4+20
|
||||||
paddings: 10
|
paddings: 10
|
||||||
Layout.topMargin: 10
|
Layout.topMargin: 10
|
||||||
FluRectangle{
|
FluClip{
|
||||||
width: 1920/4
|
width: 1920/4
|
||||||
height: 1200/4
|
height: 1200/4
|
||||||
radius:[15,15,15,15]
|
radius:[8,8,8,8]
|
||||||
Image {
|
Image {
|
||||||
id:image
|
id:image
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
@ -213,6 +213,45 @@ FluScrollablePage{
|
|||||||
}'
|
}'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FluArea{
|
||||||
|
Layout.fillWidth: true
|
||||||
|
height: 68
|
||||||
|
Layout.topMargin: 20
|
||||||
|
paddings: 10
|
||||||
|
|
||||||
|
FluLoadingButton{
|
||||||
|
id:btn_loading
|
||||||
|
loading:loading_button_switch.checked
|
||||||
|
text:"Loading Button"
|
||||||
|
anchors{
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
left: parent.left
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FluToggleSwitch{
|
||||||
|
id:loading_button_switch
|
||||||
|
checked: true
|
||||||
|
anchors{
|
||||||
|
right: parent.right
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
text:"Loading"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CodeExpander{
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: -1
|
||||||
|
code:'FluLoadingButton{
|
||||||
|
text:"Loading Button"
|
||||||
|
onClicked: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FluArea{
|
FluArea{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
@ -10,10 +10,10 @@ FluScrollablePage{
|
|||||||
|
|
||||||
title:"Captcha"
|
title:"Captcha"
|
||||||
|
|
||||||
|
|
||||||
FluCaptcha{
|
FluCaptcha{
|
||||||
id:captcha
|
id:captcha
|
||||||
Layout.topMargin: 20
|
Layout.topMargin: 20
|
||||||
|
ignoreCase:switch_case.checked
|
||||||
MouseArea{
|
MouseArea{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
@ -31,6 +31,13 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FluToggleSwitch{
|
||||||
|
id:switch_case
|
||||||
|
text:"Ignore Case"
|
||||||
|
checked: true
|
||||||
|
Layout.topMargin: 10
|
||||||
|
}
|
||||||
|
|
||||||
RowLayout{
|
RowLayout{
|
||||||
spacing: 10
|
spacing: 10
|
||||||
Layout.topMargin: 10
|
Layout.topMargin: 10
|
||||||
@ -50,6 +57,4 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,14 @@ FluScrollablePage{
|
|||||||
FluText{
|
FluText{
|
||||||
text:"轮播图,支持无限轮播,无限滑动,用ListView实现的组件"
|
text:"轮播图,支持无限轮播,无限滑动,用ListView实现的组件"
|
||||||
}
|
}
|
||||||
|
Item{
|
||||||
|
width: 400
|
||||||
|
height: 300
|
||||||
|
FluShadow{
|
||||||
|
radius: 8
|
||||||
|
}
|
||||||
FluCarousel{
|
FluCarousel{
|
||||||
radius:[5,5,5,5]
|
anchors.fill: parent
|
||||||
delegate: Component{
|
delegate: Component{
|
||||||
Image {
|
Image {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@ -55,6 +61,7 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FluArea{
|
FluArea{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@ -67,8 +74,14 @@ FluScrollablePage{
|
|||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
left:parent.left
|
left:parent.left
|
||||||
}
|
}
|
||||||
|
Item{
|
||||||
|
width: 400
|
||||||
|
height: 300
|
||||||
|
FluShadow{
|
||||||
|
radius: 8
|
||||||
|
}
|
||||||
FluCarousel{
|
FluCarousel{
|
||||||
radius:[15,15,15,15]
|
anchors.fill: parent
|
||||||
loopTime:1500
|
loopTime:1500
|
||||||
indicatorGravity: Qt.AlignHCenter | Qt.AlignTop
|
indicatorGravity: Qt.AlignHCenter | Qt.AlignTop
|
||||||
indicatorMarginTop:15
|
indicatorMarginTop:15
|
||||||
@ -108,6 +121,8 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeExpander{
|
CodeExpander{
|
||||||
|
@ -47,7 +47,6 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
FluComboBox {
|
FluComboBox {
|
||||||
editable: true
|
editable: true
|
||||||
font:FluTextStyle.BodyStrong
|
|
||||||
model: ListModel {
|
model: ListModel {
|
||||||
id: model_2
|
id: model_2
|
||||||
ListElement { text: "Banana" }
|
ListElement { text: "Banana" }
|
||||||
|
@ -2,6 +2,7 @@ import QtQuick 2.15
|
|||||||
import QtQuick.Layouts 1.15
|
import QtQuick.Layouts 1.15
|
||||||
import QtQuick.Window 2.15
|
import QtQuick.Window 2.15
|
||||||
import QtQuick.Controls 2.15
|
import QtQuick.Controls 2.15
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
import "qrc:///example/qml/global"
|
import "qrc:///example/qml/global"
|
||||||
import FluentUI 1.0
|
import FluentUI 1.0
|
||||||
|
|
||||||
@ -50,33 +51,19 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView{
|
Component{
|
||||||
id: list
|
id:com_grallery
|
||||||
anchors{
|
Item{
|
||||||
left: parent.left
|
|
||||||
right: parent.right
|
|
||||||
bottom: parent.bottom
|
|
||||||
}
|
|
||||||
orientation: ListView.Horizontal
|
|
||||||
height: 240
|
|
||||||
model: model_header
|
|
||||||
header: Item{height: 10;width: 10}
|
|
||||||
footer: Item{height: 10;width: 10}
|
|
||||||
ScrollBar.horizontal: FluScrollBar{
|
|
||||||
id: scrollbar_header
|
|
||||||
}
|
|
||||||
clip: false
|
|
||||||
delegate:Item{
|
|
||||||
id: control
|
id: control
|
||||||
width: 220
|
width: 220
|
||||||
height: 240
|
height: 240
|
||||||
FluShadow{
|
FluShadow{
|
||||||
radius:8
|
radius:5
|
||||||
anchors.fill: item_content
|
anchors.fill: item_content
|
||||||
}
|
}
|
||||||
FluItem{
|
FluClip{
|
||||||
id:item_content
|
id:item_content
|
||||||
radius: [8,8,8,8]
|
radius: [5,5,5,5]
|
||||||
width: 200
|
width: 200
|
||||||
height: 220
|
height: 220
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@ -90,20 +77,15 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
Rectangle{
|
Rectangle{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: 8
|
radius: 5
|
||||||
color:{
|
color:FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03)
|
||||||
if(FluTheme.dark){
|
visible: item_mouse.containsMouse
|
||||||
if(item_mouse.containsMouse){
|
|
||||||
return Qt.rgba(1,1,1,0.03)
|
|
||||||
}
|
|
||||||
return Qt.rgba(0,0,0,0.0)
|
|
||||||
}else{
|
|
||||||
if(item_mouse.containsMouse){
|
|
||||||
return Qt.rgba(0,0,0,0.03)
|
|
||||||
}
|
|
||||||
return Qt.rgba(0,0,0,0.0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Rectangle{
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: 5
|
||||||
|
color:Qt.rgba(0,0,0,0.0)
|
||||||
|
visible: !item_mouse.containsMouse
|
||||||
}
|
}
|
||||||
ColumnLayout{
|
ColumnLayout{
|
||||||
Image {
|
Image {
|
||||||
@ -155,11 +137,31 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ListView{
|
||||||
|
id: list
|
||||||
|
anchors{
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
orientation: ListView.Horizontal
|
||||||
|
height: 240
|
||||||
|
model: model_header
|
||||||
|
header: Item{height: 10;width: 10}
|
||||||
|
footer: Item{height: 10;width: 10}
|
||||||
|
ScrollBar.horizontal: FluScrollBar{
|
||||||
|
id: scrollbar_header
|
||||||
|
}
|
||||||
|
clip: false
|
||||||
|
delegate: com_grallery
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component{
|
Component{
|
||||||
id:com_item
|
id:com_item
|
||||||
Item{
|
Item{
|
||||||
|
property string desc: modelData.desc
|
||||||
width: 320
|
width: 320
|
||||||
height: 120
|
height: 120
|
||||||
FluArea{
|
FluArea{
|
||||||
@ -195,7 +197,6 @@ FluScrollablePage{
|
|||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FluText{
|
FluText{
|
||||||
id:item_title
|
id:item_title
|
||||||
text:modelData.title
|
text:modelData.title
|
||||||
@ -206,10 +207,9 @@ FluScrollablePage{
|
|||||||
top: item_icon.top
|
top: item_icon.top
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FluText{
|
FluText{
|
||||||
id:item_desc
|
id:item_desc
|
||||||
text:modelData.desc
|
text:desc
|
||||||
color:FluColors.Grey120
|
color:FluColors.Grey120
|
||||||
wrapMode: Text.WrapAnywhere
|
wrapMode: Text.WrapAnywhere
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
|
@ -12,6 +12,7 @@ FluContentPage{
|
|||||||
|
|
||||||
title:"Http"
|
title:"Http"
|
||||||
property string cacheDirPath: FluTools.getApplicationDirPath() + "/cache/http"
|
property string cacheDirPath: FluTools.getApplicationDirPath() + "/cache/http"
|
||||||
|
property bool isDownCompleted: false
|
||||||
|
|
||||||
FluHttp{
|
FluHttp{
|
||||||
id:http
|
id:http
|
||||||
@ -172,6 +173,10 @@ FluContentPage{
|
|||||||
}
|
}
|
||||||
onSuccess:
|
onSuccess:
|
||||||
(result)=>{
|
(result)=>{
|
||||||
|
if(!isDownCompleted){
|
||||||
|
tour.open()
|
||||||
|
isDownCompleted = true
|
||||||
|
}
|
||||||
showSuccess(result)
|
showSuccess(result)
|
||||||
}
|
}
|
||||||
onDownloadProgress:
|
onDownloadProgress:
|
||||||
@ -282,6 +287,13 @@ FluContentPage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FluTour{
|
||||||
|
id:tour
|
||||||
|
steps:[
|
||||||
|
{title:"友情提示",description: "下载已完成,左击这里可以打开文件所在路径,右击可以弹出菜单删除文件!",target:()=>btn_breakpoint_download}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
HttpCallable{
|
HttpCallable{
|
||||||
id:callable_upload
|
id:callable_upload
|
||||||
onStart: {
|
onStart: {
|
||||||
|
@ -13,7 +13,7 @@ FluScrollablePage{
|
|||||||
FluArea{
|
FluArea{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 20
|
Layout.topMargin: 20
|
||||||
height: 240
|
height: 270
|
||||||
paddings: 10
|
paddings: 10
|
||||||
ColumnLayout{
|
ColumnLayout{
|
||||||
spacing: 14
|
spacing: 14
|
||||||
@ -45,6 +45,12 @@ FluScrollablePage{
|
|||||||
showSuccess("这是一个Success样式的InfoBar这是一个Success样式的InfoBar")
|
showSuccess("这是一个Success样式的InfoBar这是一个Success样式的InfoBar")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
FluButton{
|
||||||
|
text:"手动关闭的InfoBar"
|
||||||
|
onClicked: {
|
||||||
|
showInfo("这是一个Info样式的InfoBar",0,"支持手动关闭")
|
||||||
|
}
|
||||||
|
}
|
||||||
FluButton{
|
FluButton{
|
||||||
text:"Loading"
|
text:"Loading"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
@ -16,9 +16,12 @@ FluScrollablePage{
|
|||||||
height: 400
|
height: 400
|
||||||
paddings: 10
|
paddings: 10
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FluPivot{
|
FluPivot{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
currentIndex: 2
|
currentIndex: 2
|
||||||
|
|
||||||
FluPivotItem{
|
FluPivotItem{
|
||||||
title:"All"
|
title:"All"
|
||||||
contentItem:FluText{
|
contentItem:FluText{
|
||||||
|
@ -3,7 +3,6 @@ import QtQuick.Controls 2.15
|
|||||||
import QtQuick.Layouts 1.15
|
import QtQuick.Layouts 1.15
|
||||||
import QtQuick.Window 2.15
|
import QtQuick.Window 2.15
|
||||||
import FluentUI 1.0
|
import FluentUI 1.0
|
||||||
import QtGraphicalEffects 1.15
|
|
||||||
import "qrc:///example/qml/component"
|
import "qrc:///example/qml/component"
|
||||||
import "../component"
|
import "../component"
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
RowLayout{
|
RowLayout{
|
||||||
spacing: 14
|
spacing: 14
|
||||||
FluRectangle{
|
FluClip{
|
||||||
width: 50
|
width: 50
|
||||||
height: 50
|
height: 50
|
||||||
radius:[25,0,25,25]
|
radius:[25,0,25,25]
|
||||||
@ -80,7 +80,7 @@ FluScrollablePage{
|
|||||||
sourceSize: Qt.size(width,height)
|
sourceSize: Qt.size(width,height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FluRectangle{
|
FluClip{
|
||||||
width: 50
|
width: 50
|
||||||
height: 50
|
height: 50
|
||||||
radius:[10,10,10,10]
|
radius:[10,10,10,10]
|
||||||
@ -91,7 +91,7 @@ FluScrollablePage{
|
|||||||
source: "qrc:/example/res/svg/avatar_2.svg"
|
source: "qrc:/example/res/svg/avatar_2.svg"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FluRectangle{
|
FluClip{
|
||||||
width: 50
|
width: 50
|
||||||
height: 50
|
height: 50
|
||||||
radius:[25,25,25,25]
|
radius:[25,25,25,25]
|
||||||
@ -102,7 +102,7 @@ FluScrollablePage{
|
|||||||
source: "qrc:/example/res/svg/avatar_3.svg"
|
source: "qrc:/example/res/svg/avatar_3.svg"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FluRectangle{
|
FluClip{
|
||||||
width: 50
|
width: 50
|
||||||
height: 50
|
height: 50
|
||||||
radius:[0,25,25,25]
|
radius:[0,25,25,25]
|
||||||
@ -114,10 +114,10 @@ FluScrollablePage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FluRectangle{
|
FluClip{
|
||||||
width: 1920/5
|
width: 1920/5
|
||||||
height: 1200/5
|
height: 1200/5
|
||||||
radius:[15,15,15,15]
|
radius:[8,8,8,8]
|
||||||
Image {
|
Image {
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
source: "qrc:/example/res/image/banner_1.jpg"
|
source: "qrc:/example/res/image/banner_1.jpg"
|
||||||
|
@ -31,9 +31,10 @@ FluScrollablePage{
|
|||||||
Layout.topMargin: 10
|
Layout.topMargin: 10
|
||||||
Layout.leftMargin: 4
|
Layout.leftMargin: 4
|
||||||
Layout.bottomMargin: 4
|
Layout.bottomMargin: 4
|
||||||
|
radius: 4
|
||||||
color: FluTheme.dark ? FluColors.Black : FluColors.White
|
color: FluTheme.dark ? FluColors.Black : FluColors.White
|
||||||
FluShadow{
|
FluShadow{
|
||||||
radius: 0
|
radius: 4
|
||||||
color: FluTheme.primaryColor.dark
|
color: FluTheme.primaryColor.dark
|
||||||
}
|
}
|
||||||
Image{
|
Image{
|
||||||
|
@ -5,12 +5,93 @@ import QtQuick.Controls 2.15
|
|||||||
import FluentUI 1.0
|
import FluentUI 1.0
|
||||||
import "qrc:///example/qml/global"
|
import "qrc:///example/qml/global"
|
||||||
import "qrc:///example/qml/component"
|
import "qrc:///example/qml/component"
|
||||||
|
import "qrc:///example/qml/viewmodel"
|
||||||
import "../component"
|
import "../component"
|
||||||
|
import "../viewmodel"
|
||||||
|
import "../global"
|
||||||
|
|
||||||
FluScrollablePage{
|
FluScrollablePage{
|
||||||
|
|
||||||
title:"Settings"
|
title:"Settings"
|
||||||
|
|
||||||
|
SettingsViewModel{
|
||||||
|
id:viewmodel_settings
|
||||||
|
}
|
||||||
|
|
||||||
|
FluEvent{
|
||||||
|
id:event_checkupdate_finish
|
||||||
|
name: "checkUpdateFinish"
|
||||||
|
onTriggered: {
|
||||||
|
btn_checkupdate.loading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
FluEventBus.registerEvent(event_checkupdate_finish)
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
FluEventBus.unRegisterEvent(event_checkupdate_finish)
|
||||||
|
}
|
||||||
|
|
||||||
|
FluArea{
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 20
|
||||||
|
height: 60
|
||||||
|
paddings: 10
|
||||||
|
Row{
|
||||||
|
spacing: 20
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
FluText{
|
||||||
|
text:"当前版本 v%1".arg(AppInfo.version)
|
||||||
|
font: FluTextStyle.Body
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
FluLoadingButton{
|
||||||
|
id:btn_checkupdate
|
||||||
|
text:"检查更新"
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: {
|
||||||
|
loading = true
|
||||||
|
FluEventBus.post("checkUpdate")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FluArea{
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 20
|
||||||
|
height: 50
|
||||||
|
paddings: 10
|
||||||
|
FluCheckBox{
|
||||||
|
text:"Software Render"
|
||||||
|
checked: SettingsHelper.getReander() === "software"
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: {
|
||||||
|
if(SettingsHelper.getReander() === "software"){
|
||||||
|
SettingsHelper.saveRender("")
|
||||||
|
}else{
|
||||||
|
SettingsHelper.saveRender("software")
|
||||||
|
}
|
||||||
|
dialog_render.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FluContentDialog{
|
||||||
|
id:dialog_render
|
||||||
|
title:"友情提示"
|
||||||
|
message:"此操作需要重启才能生效,是否重新启动?"
|
||||||
|
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
|
||||||
|
negativeText: "取消"
|
||||||
|
positiveText:"确定"
|
||||||
|
onPositiveClicked:{
|
||||||
|
window.deleteWindow()
|
||||||
|
AppInfo.restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FluArea{
|
FluArea{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 20
|
Layout.topMargin: 20
|
||||||
@ -61,10 +142,10 @@ FluScrollablePage{
|
|||||||
Repeater{
|
Repeater{
|
||||||
model: [{title:"Open",mode:FluNavigationViewType.Open},{title:"Compact",mode:FluNavigationViewType.Compact},{title:"Minimal",mode:FluNavigationViewType.Minimal},{title:"Auto",mode:FluNavigationViewType.Auto}]
|
model: [{title:"Open",mode:FluNavigationViewType.Open},{title:"Compact",mode:FluNavigationViewType.Compact},{title:"Minimal",mode:FluNavigationViewType.Minimal},{title:"Auto",mode:FluNavigationViewType.Auto}]
|
||||||
delegate: FluRadioButton{
|
delegate: FluRadioButton{
|
||||||
checked : MainEvent.displayMode===modelData.mode
|
checked : viewmodel_settings.displayMode===modelData.mode
|
||||||
text:modelData.title
|
text:modelData.title
|
||||||
clickListener:function(){
|
clickListener:function(){
|
||||||
MainEvent.displayMode = modelData.mode
|
viewmodel_settings.displayMode = modelData.mode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,10 +176,10 @@ FluScrollablePage{
|
|||||||
Repeater{
|
Repeater{
|
||||||
model: ["Zh","En"]
|
model: ["Zh","En"]
|
||||||
delegate: FluRadioButton{
|
delegate: FluRadioButton{
|
||||||
checked: appInfo.lang.objectName === modelData
|
checked: AppInfo.lang.objectName === modelData
|
||||||
text:modelData
|
text:modelData
|
||||||
clickListener:function(){
|
clickListener:function(){
|
||||||
appInfo.changeLang(modelData)
|
AppInfo.changeLang(modelData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,21 @@ import QtQuick.Layouts 1.15
|
|||||||
import QtQuick.Window 2.15
|
import QtQuick.Window 2.15
|
||||||
import FluentUI 1.0
|
import FluentUI 1.0
|
||||||
import "qrc:///example/qml/component"
|
import "qrc:///example/qml/component"
|
||||||
|
import "qrc:///example/qml/viewmodel"
|
||||||
import "../component"
|
import "../component"
|
||||||
|
import "../viewmodel"
|
||||||
|
|
||||||
FluScrollablePage{
|
FluScrollablePage{
|
||||||
|
|
||||||
launchMode: FluPageType.SingleInstance
|
|
||||||
|
|
||||||
title:"TextBox"
|
title:"TextBox"
|
||||||
|
|
||||||
|
TextBoxViewModel{
|
||||||
|
id:viewModel
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
console.debug("T_TextBox页面销毁了")
|
||||||
|
}
|
||||||
|
|
||||||
FluArea{
|
FluArea{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
height: 68
|
height: 68
|
||||||
@ -21,6 +29,10 @@ FluScrollablePage{
|
|||||||
placeholderText: "单行输入框"
|
placeholderText: "单行输入框"
|
||||||
disabled:text_box_switch.checked
|
disabled:text_box_switch.checked
|
||||||
cleanEnabled: true
|
cleanEnabled: true
|
||||||
|
text:viewModel.text1
|
||||||
|
onTextChanged: {
|
||||||
|
viewModel.text1 = text
|
||||||
|
}
|
||||||
anchors{
|
anchors{
|
||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
left: parent.left
|
left: parent.left
|
||||||
@ -85,6 +97,10 @@ FluScrollablePage{
|
|||||||
FluMultilineTextBox{
|
FluMultilineTextBox{
|
||||||
id:multiine_textbox
|
id:multiine_textbox
|
||||||
placeholderText: "多行输入框"
|
placeholderText: "多行输入框"
|
||||||
|
text:viewModel.text2
|
||||||
|
onTextChanged: {
|
||||||
|
viewModel.text2 = text
|
||||||
|
}
|
||||||
disabled:text_box_multi_switch.checked
|
disabled:text_box_multi_switch.checked
|
||||||
anchors{
|
anchors{
|
||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
|
@ -6,152 +6,127 @@ import FluentUI 1.0
|
|||||||
import "qrc:///example/qml/component"
|
import "qrc:///example/qml/component"
|
||||||
import "../component"
|
import "../component"
|
||||||
|
|
||||||
FluScrollablePage {
|
FluContentPage {
|
||||||
|
|
||||||
title:"TreeView"
|
title:"TreeView"
|
||||||
|
|
||||||
function randomName() {
|
function treeData(){
|
||||||
var names = ["张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"]
|
const dig = (path = '0', level = 4) => {
|
||||||
return names[Math.floor(Math.random() * names.length)]
|
const list = [];
|
||||||
|
for (let i = 0; i < 6; i += 1) {
|
||||||
|
const key = `${path}-${i}`;
|
||||||
|
const treeNode = {
|
||||||
|
title: key,
|
||||||
|
key,
|
||||||
|
};
|
||||||
|
if (level > 0) {
|
||||||
|
treeNode.children = dig(key, level - 1);
|
||||||
|
}
|
||||||
|
list.push(treeNode);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
};
|
||||||
|
return dig();
|
||||||
}
|
}
|
||||||
|
|
||||||
function randomCompany() {
|
Column{
|
||||||
var companies = ["阿里巴巴", "腾讯", "百度", "京东", "华为", "小米", "字节跳动", "美团", "滴滴"]
|
id:layout_column
|
||||||
return companies[Math.floor(Math.random() * companies.length)]
|
spacing: 12
|
||||||
}
|
width: 300
|
||||||
|
|
||||||
function randomDepartment() {
|
|
||||||
var departments = ["技术部", "销售部", "市场部", "人事部", "财务部", "客服部", "产品部", "设计部", "运营部"]
|
|
||||||
return departments[Math.floor(Math.random() * departments.length)]
|
|
||||||
}
|
|
||||||
|
|
||||||
function createEmployee() {
|
|
||||||
var name = randomName()
|
|
||||||
return tree_view.createItem(name, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
function createSubtree(numEmployees) {
|
|
||||||
var employees = []
|
|
||||||
for (var i = 0; i < numEmployees; i++) {
|
|
||||||
employees.push(createEmployee())
|
|
||||||
}
|
|
||||||
return tree_view.createItem(randomDepartment(), true, employees)
|
|
||||||
}
|
|
||||||
|
|
||||||
function createOrg(numLevels, numSubtrees, numEmployees) {
|
|
||||||
if (numLevels === 0) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
var subtrees = []
|
|
||||||
for (var i = 0; i < numSubtrees; i++) {
|
|
||||||
subtrees.push(createSubtree(numEmployees))
|
|
||||||
}
|
|
||||||
return [tree_view.createItem(randomCompany(), true, subtrees)].concat(createOrg(numLevels - 1, numSubtrees, numEmployees))
|
|
||||||
}
|
|
||||||
|
|
||||||
FluArea{
|
|
||||||
id:layout_actions
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 20
|
|
||||||
height: 50
|
|
||||||
paddings: 10
|
|
||||||
RowLayout{
|
|
||||||
spacing: 14
|
|
||||||
FluDropDownButton{
|
|
||||||
id:btn_selection_model
|
|
||||||
Layout.preferredWidth: 140
|
|
||||||
text:"None"
|
|
||||||
FluMenuItem{
|
|
||||||
text:"None"
|
|
||||||
onClicked: {
|
|
||||||
btn_selection_model.text = text
|
|
||||||
tree_view.selectionMode = FluTabViewType.Equal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FluMenuItem{
|
|
||||||
text:"Single"
|
|
||||||
onClicked: {
|
|
||||||
btn_selection_model.text = text
|
|
||||||
tree_view.selectionMode = FluTabViewType.SizeToContent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FluMenuItem{
|
|
||||||
text:"Muiltple"
|
|
||||||
onClicked: {
|
|
||||||
btn_selection_model.text = text
|
|
||||||
tree_view.selectionMode = FluTabViewType.Compact
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FluFilledButton{
|
|
||||||
text:"获取选中的数据"
|
|
||||||
onClicked: {
|
|
||||||
if(tree_view.selectionMode === FluTreeViewType.None){
|
|
||||||
showError("当前非选择模式,没有选中的数据")
|
|
||||||
}
|
|
||||||
if(tree_view.selectionMode === FluTreeViewType.Single){
|
|
||||||
if(!tree_view.signleData()){
|
|
||||||
showError("没有选中数据")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
showSuccess(tree_view.signleData().text)
|
|
||||||
}
|
|
||||||
if(tree_view.selectionMode === FluTreeViewType.Multiple){
|
|
||||||
if(tree_view.multipData().length===0){
|
|
||||||
showError("没有选中数据")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var info = []
|
|
||||||
tree_view.multipData().map((value)=>info.push(value.text))
|
|
||||||
showSuccess(info.join(","))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FluArea{
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 10
|
|
||||||
paddings: 10
|
|
||||||
height: 400
|
|
||||||
FluTreeView{
|
|
||||||
id:tree_view
|
|
||||||
width:240
|
|
||||||
anchors{
|
anchors{
|
||||||
|
topMargin: 20
|
||||||
top:parent.top
|
top:parent.top
|
||||||
left: parent.left
|
left: parent.left
|
||||||
|
leftMargin: 10
|
||||||
bottom:parent.bottom
|
bottom:parent.bottom
|
||||||
}
|
bottomMargin: 20
|
||||||
onItemClicked:
|
|
||||||
(model)=>{
|
|
||||||
showSuccess(model.text)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
FluText{
|
||||||
var org = createOrg(3, 3, 3)
|
text:"共计%1条数据,当前显示的%2条数据".arg(tree_view.count()).arg(tree_view.visibleCount())
|
||||||
createItem()
|
|
||||||
updateData(org)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeExpander{
|
FluText{
|
||||||
Layout.fillWidth: true
|
text:"共计选中%1条数据".arg(tree_view.selectionModel().length)
|
||||||
Layout.topMargin: -1
|
}
|
||||||
code:'FluTreeView{
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FluArea{
|
||||||
|
anchors{
|
||||||
|
left: layout_column.right
|
||||||
|
top: parent.top
|
||||||
|
bottom: parent.bottom
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: 5
|
||||||
|
topMargin: 5
|
||||||
|
bottomMargin: 5
|
||||||
|
}
|
||||||
|
FluShadow{}
|
||||||
|
FluTreeView{
|
||||||
id:tree_view
|
id:tree_view
|
||||||
width:240
|
anchors.fill: parent
|
||||||
height:600
|
cellHeight: slider_cell_height.value
|
||||||
|
draggable:switch_draggable.checked
|
||||||
|
showLine: switch_showline.checked
|
||||||
|
checkable:switch_checkable.checked
|
||||||
|
depthPadding: slider_depth_padding.value
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
var datas = []
|
var data = treeData()
|
||||||
datas.push(createItem("Node1",false))
|
dataSource = data
|
||||||
datas.push(createItem("Node2",false))
|
|
||||||
datas.push(createItem("Node2",true,[createItem("Node2-1",false),createItem("Node2-2",false)]))
|
|
||||||
updateData(datas)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
13
example/qml/viewmodel/SettingsViewModel.qml
Normal file
13
example/qml/viewmodel/SettingsViewModel.qml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import QtQuick 2.15
|
||||||
|
import FluentUI 1.0
|
||||||
|
|
||||||
|
FluViewModel{
|
||||||
|
|
||||||
|
objectName: "SettingsViewModel"
|
||||||
|
property int displayMode
|
||||||
|
|
||||||
|
onInitData: {
|
||||||
|
displayMode = FluNavigationViewType.Auto
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
8
example/qml/viewmodel/TextBoxViewModel.qml
Normal file
8
example/qml/viewmodel/TextBoxViewModel.qml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import QtQuick 2.15
|
||||||
|
import FluentUI 1.0
|
||||||
|
|
||||||
|
FluViewModel {
|
||||||
|
objectName: "TextBoxView"
|
||||||
|
property string text1
|
||||||
|
property string text2
|
||||||
|
}
|
@ -36,7 +36,7 @@ CustomWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
FluText{
|
FluText{
|
||||||
text:"v%1".arg(appInfo.version)
|
text:"v%1".arg(AppInfo.version)
|
||||||
font: FluTextStyle.Body
|
font: FluTextStyle.Body
|
||||||
Layout.alignment: Qt.AlignBottom
|
Layout.alignment: Qt.AlignBottom
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,11 @@ import Qt.labs.platform 1.1
|
|||||||
import FluentUI 1.0
|
import FluentUI 1.0
|
||||||
import example 1.0
|
import example 1.0
|
||||||
import "qrc:///example/qml/component"
|
import "qrc:///example/qml/component"
|
||||||
import "../component"
|
|
||||||
import "qrc:///example/qml/global"
|
import "qrc:///example/qml/global"
|
||||||
|
import "qrc:///example/qml/viewmodel"
|
||||||
|
import "../component"
|
||||||
|
import "../viewmodel"
|
||||||
|
import "../global"
|
||||||
|
|
||||||
CustomWindow {
|
CustomWindow {
|
||||||
|
|
||||||
@ -21,15 +24,32 @@ CustomWindow {
|
|||||||
appBarVisible: false
|
appBarVisible: false
|
||||||
launchMode: FluWindowType.SingleTask
|
launchMode: FluWindowType.SingleTask
|
||||||
|
|
||||||
|
SettingsViewModel{
|
||||||
|
id:viewmodel_settings
|
||||||
|
}
|
||||||
|
|
||||||
closeFunc:function(event){
|
closeFunc:function(event){
|
||||||
dialog_close.open()
|
dialog_close.open()
|
||||||
event.accepted = false
|
event.accepted = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FluEvent{
|
||||||
|
id:event_checkupdate
|
||||||
|
name: "checkUpdate"
|
||||||
|
onTriggered: {
|
||||||
|
checkUpdate(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
FluTools.setQuitOnLastWindowClosed(false)
|
FluTools.setQuitOnLastWindowClosed(false)
|
||||||
tour.open()
|
tour.open()
|
||||||
checkUpdate()
|
checkUpdate(true)
|
||||||
|
FluEventBus.registerEvent(event_checkupdate)
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
FluEventBus.unRegisterEvent(event_checkupdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemTrayIcon {
|
SystemTrayIcon {
|
||||||
@ -139,7 +159,7 @@ CustomWindow {
|
|||||||
id:loader
|
id:loader
|
||||||
lazy: true
|
lazy: true
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
source: "https://zhu-zichu.gitee.io/Qt6_156_LieflatPage.qml"
|
source: "https://zhu-zichu.gitee.io/Qt5_156_LieflatPage.qml"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
front: Item{
|
front: Item{
|
||||||
@ -165,13 +185,13 @@ CustomWindow {
|
|||||||
height: parent.height
|
height: parent.height
|
||||||
z:999
|
z:999
|
||||||
//Stack模式,每次切换都会将页面压入栈中,随着栈的页面增多,消耗的内存也越多,内存消耗多就会卡顿,这时候就需要按返回将页面pop掉,释放内存。该模式可以配合FluPage中的launchMode属性,设置页面的启动模式
|
//Stack模式,每次切换都会将页面压入栈中,随着栈的页面增多,消耗的内存也越多,内存消耗多就会卡顿,这时候就需要按返回将页面pop掉,释放内存。该模式可以配合FluPage中的launchMode属性,设置页面的启动模式
|
||||||
pageMode: FluNavigationViewType.Stack
|
// pageMode: FluNavigationViewType.Stack
|
||||||
//NoStack模式,每次切换都会销毁之前的页面然后创建一个新的页面,只需消耗少量内存(推荐)
|
//NoStack模式,每次切换都会销毁之前的页面然后创建一个新的页面,只需消耗少量内存,可以配合FluViewModel保存页面数据(推荐)
|
||||||
// pageMode: FluNavigationViewType.NoStack
|
pageMode: FluNavigationViewType.NoStack
|
||||||
items: ItemsOriginal
|
items: ItemsOriginal
|
||||||
footerItems:ItemsFooter
|
footerItems:ItemsFooter
|
||||||
topPadding:FluTools.isMacos() ? 20 : 0
|
topPadding:FluTools.isMacos() ? 20 : 0
|
||||||
displayMode:MainEvent.displayMode
|
displayMode:viewmodel_settings.displayMode
|
||||||
logo: "qrc:/example/res/image/favicon.ico"
|
logo: "qrc:/example/res/image/favicon.ico"
|
||||||
title:"FluentUI"
|
title:"FluentUI"
|
||||||
onLogoClicked:{
|
onLogoClicked:{
|
||||||
@ -301,7 +321,7 @@ CustomWindow {
|
|||||||
property string body
|
property string body
|
||||||
id:dialog_update
|
id:dialog_update
|
||||||
title:"升级提示"
|
title:"升级提示"
|
||||||
message:"FluentUI目前最新版本 "+ newVerson +" -- 当前应用版本 "+appInfo.version+" \n现在是否去下载新版本?\n\n更新内容:\n"+body
|
message:"FluentUI目前最新版本 "+ newVerson +" -- 当前应用版本 "+AppInfo.version+" \n现在是否去下载新版本?\n\n更新内容:\n"+body
|
||||||
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
|
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
|
||||||
negativeText: "取消"
|
negativeText: "取消"
|
||||||
positiveText:"确定"
|
positiveText:"确定"
|
||||||
@ -312,30 +332,40 @@ CustomWindow {
|
|||||||
|
|
||||||
HttpCallable{
|
HttpCallable{
|
||||||
id:callable
|
id:callable
|
||||||
|
property bool silent: true
|
||||||
onStart: {
|
onStart: {
|
||||||
console.debug("satrt check update...")
|
console.debug("satrt check update...")
|
||||||
}
|
}
|
||||||
onFinish: {
|
onFinish: {
|
||||||
console.debug("check update finish")
|
console.debug("check update finish")
|
||||||
|
FluEventBus.post("checkUpdateFinish");
|
||||||
}
|
}
|
||||||
onSuccess:
|
onSuccess:
|
||||||
(result)=>{
|
(result)=>{
|
||||||
var data = JSON.parse(result)
|
var data = JSON.parse(result)
|
||||||
console.debug("current version "+appInfo.version)
|
console.debug("current version "+AppInfo.version)
|
||||||
console.debug("new version "+data.tag_name)
|
console.debug("new version "+data.tag_name)
|
||||||
if(data.tag_name !== appInfo.version){
|
if(data.tag_name !== AppInfo.version){
|
||||||
dialog_update.newVerson = data.tag_name
|
dialog_update.newVerson = data.tag_name
|
||||||
dialog_update.body = data.body
|
dialog_update.body = data.body
|
||||||
dialog_update.open()
|
dialog_update.open()
|
||||||
|
}else{
|
||||||
|
if(!silent){
|
||||||
|
showInfo("当前版本已经是最新版")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onError:
|
onError:
|
||||||
(status,errorString)=>{
|
(status,errorString)=>{
|
||||||
|
if(!silent){
|
||||||
|
showError("网络异常!")
|
||||||
|
}
|
||||||
console.debug(status+";"+errorString)
|
console.debug(status+";"+errorString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkUpdate(){
|
function checkUpdate(silent){
|
||||||
|
callable.silent = silent
|
||||||
var request = http.newRequest("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
|
var request = http.newRequest("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
|
||||||
http.get(request,callable);
|
http.get(request,callable);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QGuiApplication>
|
||||||
#include "lang/En.h"
|
#include "lang/En.h"
|
||||||
#include "lang/Zh.h"
|
#include "lang/Zh.h"
|
||||||
#include "Version.h"
|
#include "Version.h"
|
||||||
@ -20,7 +21,6 @@ void AppInfo::init(QQmlApplicationEngine *engine){
|
|||||||
QObject::connect(this,&AppInfo::langChanged,this,[=]{
|
QObject::connect(this,&AppInfo::langChanged,this,[=]{
|
||||||
context->setContextProperty("lang",this->lang());
|
context->setContextProperty("lang",this->lang());
|
||||||
});
|
});
|
||||||
context->setContextProperty("appInfo",this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInfo::changeLang(const QString& locale){
|
void AppInfo::changeLang(const QString& locale){
|
||||||
@ -35,3 +35,7 @@ void AppInfo::changeLang(const QString& locale){
|
|||||||
lang(new En());
|
lang(new En());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppInfo::restart(){
|
||||||
|
qApp->exit(931);
|
||||||
|
}
|
||||||
|
@ -5,16 +5,20 @@
|
|||||||
#include <QQmlApplicationEngine>
|
#include <QQmlApplicationEngine>
|
||||||
#include "lang/Lang.h"
|
#include "lang/Lang.h"
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
class AppInfo : public QObject
|
class AppInfo : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY_AUTO(QString,version)
|
Q_PROPERTY_AUTO(QString,version)
|
||||||
Q_PROPERTY_AUTO(Lang*,lang)
|
Q_PROPERTY_AUTO(Lang*,lang)
|
||||||
public:
|
private:
|
||||||
explicit AppInfo(QObject *parent = nullptr);
|
explicit AppInfo(QObject *parent = nullptr);
|
||||||
|
public:
|
||||||
|
SINGLETONG(AppInfo)
|
||||||
void init(QQmlApplicationEngine *engine);
|
void init(QQmlApplicationEngine *engine);
|
||||||
Q_INVOKABLE void changeLang(const QString& locale);
|
Q_INVOKABLE void changeLang(const QString& locale);
|
||||||
|
Q_INVOKABLE void restart();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // APPINFO_H
|
#endif // APPINFO_H
|
||||||
|
40
example/src/helper/SettingsHelper.cpp
Normal file
40
example/src/helper/SettingsHelper.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "SettingsHelper.h"
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
|
SettingsHelper::SettingsHelper(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsHelper::~SettingsHelper() = default;
|
||||||
|
|
||||||
|
void SettingsHelper::save(const QString& key,QVariant val)
|
||||||
|
{
|
||||||
|
QByteArray data = {};
|
||||||
|
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||||
|
stream.setVersion(QDataStream::Qt_5_6);
|
||||||
|
stream << val;
|
||||||
|
m_settings->setValue(key, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant SettingsHelper::get(const QString& key){
|
||||||
|
const QByteArray data = m_settings->value(key).toByteArray();
|
||||||
|
if (data.isEmpty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
QDataStream stream(data);
|
||||||
|
stream.setVersion(QDataStream::Qt_5_6);
|
||||||
|
QVariant val;
|
||||||
|
stream >> val;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsHelper::init(char *argv[]){
|
||||||
|
auto applicationPath = QString::fromStdString(argv[0]);
|
||||||
|
const QFileInfo fileInfo(applicationPath);
|
||||||
|
const QString iniFileName = fileInfo.completeBaseName() + ".ini";
|
||||||
|
const QString iniFilePath = fileInfo.dir().path() + "/" + iniFileName;
|
||||||
|
qDebug()<<iniFilePath;
|
||||||
|
m_settings.reset(new QSettings(iniFilePath, QSettings::IniFormat));
|
||||||
|
}
|
33
example/src/helper/SettingsHelper.h
Normal file
33
example/src/helper/SettingsHelper.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef SETTINGSHELPER_H
|
||||||
|
#define SETTINGSHELPER_H
|
||||||
|
|
||||||
|
#include <QtCore/qobject.h>
|
||||||
|
#include <QtQml/qqml.h>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QDir>
|
||||||
|
#include "src/singleton.h"
|
||||||
|
|
||||||
|
class SettingsHelper : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
explicit SettingsHelper(QObject* parent = nullptr);
|
||||||
|
public:
|
||||||
|
SINGLETONG(SettingsHelper)
|
||||||
|
~SettingsHelper() override;
|
||||||
|
void init(char *argv[]);
|
||||||
|
Q_INVOKABLE void saveRender(const QString& render){save("render",render);}
|
||||||
|
Q_INVOKABLE QString getReander(){return get("render").toString();}
|
||||||
|
Q_INVOKABLE void saveDarkMode(int darkModel){save("darkMode",darkModel);}
|
||||||
|
Q_INVOKABLE int getDarkMode(){return get("darkMode").toInt(0);}
|
||||||
|
private:
|
||||||
|
void save(const QString& key,QVariant val);
|
||||||
|
QVariant get(const QString& key);
|
||||||
|
private:
|
||||||
|
QScopedPointer<QSettings> m_settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SETTINGSHELPER_H
|
@ -8,15 +8,25 @@
|
|||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <FramelessHelper/Quick/framelessquickmodule.h>
|
#include <FramelessHelper/Quick/framelessquickmodule.h>
|
||||||
#include <FramelessHelper/Core/private/framelessconfig_p.h>
|
#include <FramelessHelper/Core/private/framelessconfig_p.h>
|
||||||
|
#include <QtQml/qqmlextensionplugin.h>
|
||||||
#include "AppInfo.h"
|
#include "AppInfo.h"
|
||||||
#include "src/component/CircularReveal.h"
|
#include "src/component/CircularReveal.h"
|
||||||
#include "src/component/FileWatcher.h"
|
#include "src/component/FileWatcher.h"
|
||||||
#include "src/component/FpsItem.h"
|
#include "src/component/FpsItem.h"
|
||||||
|
#include "src/helper/SettingsHelper.h"
|
||||||
|
|
||||||
|
#ifdef FLUENTUI_BUILD_STATIC_LIB
|
||||||
|
#if (QT_VERSION > QT_VERSION_CHECK(6, 2, 0))
|
||||||
|
Q_IMPORT_QML_PLUGIN(FluentUIPlugin)
|
||||||
|
#endif
|
||||||
|
#include <FluentUI.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
FRAMELESSHELPER_USE_NAMESPACE
|
FRAMELESSHELPER_USE_NAMESPACE
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
SettingsHelper::getInstance()->init(argv);
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
@ -24,34 +34,42 @@ int main(int argc, char *argv[])
|
|||||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
//将样式设置为Basic,不然会导致组件显示异常
|
|
||||||
qputenv("QT_QUICK_CONTROLS_STYLE","Basic");
|
qputenv("QT_QUICK_CONTROLS_STYLE","Basic");
|
||||||
FramelessHelper::Quick::initialize();
|
FramelessHelper::Quick::initialize();
|
||||||
QGuiApplication::setOrganizationName("ZhuZiChu");
|
QGuiApplication::setOrganizationName("ZhuZiChu");
|
||||||
QGuiApplication::setOrganizationDomain("https://zhuzichu520.github.io");
|
QGuiApplication::setOrganizationDomain("https://zhuzichu520.github.io");
|
||||||
QGuiApplication::setApplicationName("FluentUI");
|
QGuiApplication::setApplicationName("FluentUI");
|
||||||
|
if(SettingsHelper::getInstance()->getReander()=="software"){
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
QQuickWindow::setGraphicsApi(QSGRendererInterface::Software);
|
||||||
|
#elif (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||||
|
QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
|
FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
|
||||||
FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
|
FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
|
||||||
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
|
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
|
||||||
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||||
#ifdef Q_OS_WIN // 此设置仅在Windows下生效
|
#ifdef Q_OS_WIN
|
||||||
FramelessConfig::instance()->set(Global::Option::ForceHideWindowFrameBorder);
|
FramelessConfig::instance()->set(Global::Option::ForceHideWindowFrameBorder);
|
||||||
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow,false);
|
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow,false);
|
||||||
#endif
|
#endif
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur,false);
|
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur,false);
|
||||||
#endif
|
#endif
|
||||||
AppInfo* appInfo = new AppInfo();
|
|
||||||
QQmlApplicationEngine engine;
|
QQmlApplicationEngine engine;
|
||||||
|
AppInfo::getInstance()->init(&engine);
|
||||||
|
engine.rootContext()->setContextProperty("AppInfo",AppInfo::getInstance());
|
||||||
|
engine.rootContext()->setContextProperty("SettingsHelper",SettingsHelper::getInstance());
|
||||||
FramelessHelper::Quick::registerTypes(&engine);
|
FramelessHelper::Quick::registerTypes(&engine);
|
||||||
#ifdef FLUENTUI_BUILD_STATIC_LIB
|
#ifdef FLUENTUI_BUILD_STATIC_LIB
|
||||||
engine.addImportPath("qrc:/"); // 让静态资源可以被QML引擎搜索到
|
FluentUI::getInstance()->registerTypes(&engine);
|
||||||
#endif
|
#endif
|
||||||
|
qDebug()<<engine.importPathList();
|
||||||
qmlRegisterType<CircularReveal>("example", 1, 0, "CircularReveal");
|
qmlRegisterType<CircularReveal>("example", 1, 0, "CircularReveal");
|
||||||
qmlRegisterType<FileWatcher>("example", 1, 0, "FileWatcher");
|
qmlRegisterType<FileWatcher>("example", 1, 0, "FileWatcher");
|
||||||
qmlRegisterType<FpsItem>("example", 1, 0, "FpsItem");
|
qmlRegisterType<FpsItem>("example", 1, 0, "FpsItem");
|
||||||
appInfo->init(&engine);
|
|
||||||
const QUrl url(QStringLiteral("qrc:/example/qml/App.qml"));
|
const QUrl url(QStringLiteral("qrc:/example/qml/App.qml"));
|
||||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
|
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
|
||||||
&app, [url](QObject *obj, const QUrl &objUrl) {
|
&app, [url](QObject *obj, const QUrl &objUrl) {
|
||||||
@ -59,5 +77,9 @@ int main(int argc, char *argv[])
|
|||||||
QCoreApplication::exit(-1);
|
QCoreApplication::exit(-1);
|
||||||
}, Qt::QueuedConnection);
|
}, Qt::QueuedConnection);
|
||||||
engine.load(url);
|
engine.load(url);
|
||||||
return app.exec();
|
const int exec = QGuiApplication::exec();
|
||||||
|
if (exec == 931) {
|
||||||
|
QProcess::startDetached(qApp->applicationFilePath(), QStringList());
|
||||||
|
}
|
||||||
|
return exec;
|
||||||
}
|
}
|
||||||
|
47
example/src/singleton.h
Normal file
47
example/src/singleton.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#ifndef SINGLETON_H
|
||||||
|
#define SINGLETON_H
|
||||||
|
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Singleton {
|
||||||
|
public:
|
||||||
|
static T* getInstance();
|
||||||
|
|
||||||
|
Singleton(const Singleton& other) = delete;
|
||||||
|
Singleton<T>& operator=(const Singleton& other) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::mutex mutex;
|
||||||
|
static T* instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::mutex Singleton<T>::mutex;
|
||||||
|
template <typename T>
|
||||||
|
T* Singleton<T>::instance;
|
||||||
|
template <typename T>
|
||||||
|
T* Singleton<T>::getInstance() {
|
||||||
|
if (instance == nullptr) {
|
||||||
|
std::lock_guard<std::mutex> locker(mutex);
|
||||||
|
if (instance == nullptr) {
|
||||||
|
instance = new T();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SINGLETONG(Class) \
|
||||||
|
private: \
|
||||||
|
friend class Singleton<Class>; \
|
||||||
|
friend struct QScopedPointerDeleter<Class>; \
|
||||||
|
\
|
||||||
|
public: \
|
||||||
|
static Class* getInstance() { \
|
||||||
|
return Singleton<Class>::getInstance(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SINGLETON_H
|
Submodule framelesshelper updated: 75ca85ec42...96f3981f0a
@ -1,16 +1,21 @@
|
|||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
|
||||||
if (FLUENTUI_BUILD_STATIC_LIB)
|
if (FLUENTUI_BUILD_STATIC_LIB AND (QT_VERSION VERSION_GREATER_EQUAL "6.2"))
|
||||||
project(fluentui LANGUAGES CXX)
|
project(fluentui LANGUAGES CXX)
|
||||||
else()
|
else()
|
||||||
project(fluentuiplugin LANGUAGES CXX)
|
project(fluentuiplugin LANGUAGES CXX)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#配置通用编译
|
#配置通用编译
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
|
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (FLUENTUI_BUILD_STATIC_LIB)
|
||||||
|
add_definitions(-DFLUENTUI_BUILD_STATIC_LIB)
|
||||||
|
endif()
|
||||||
|
|
||||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Quick Qml)
|
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Quick Qml)
|
||||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick Qml)
|
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick Qml)
|
||||||
|
|
||||||
@ -32,6 +37,9 @@ endforeach(filepath)
|
|||||||
if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
||||||
#删除fluentuiplugin.cpp与fluentuiplugin.h,这些只要Qt5使用,Qt6不需要
|
#删除fluentuiplugin.cpp与fluentuiplugin.h,这些只要Qt5使用,Qt6不需要
|
||||||
list(REMOVE_ITEM sources_files fluentuiplugin.h fluentuiplugin.cpp)
|
list(REMOVE_ITEM sources_files fluentuiplugin.h fluentuiplugin.cpp)
|
||||||
|
if (NOT FLUENTUI_BUILD_STATIC_LIB)
|
||||||
|
list(REMOVE_ITEM sources_files FluentUI.h FluentUI.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
#遍历所有qml文件
|
#遍历所有qml文件
|
||||||
file(GLOB_RECURSE QML_PATHS *.qml)
|
file(GLOB_RECURSE QML_PATHS *.qml)
|
||||||
@ -83,6 +91,9 @@ if(WIN32)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
||||||
|
if(FLUENTUI_BUILD_STATIC_LIB)
|
||||||
|
set(FLUENTUI_QML_PLUGIN_DIRECTORY ${CMAKE_BINARY_DIR}/FluentUI)
|
||||||
|
endif()
|
||||||
qt_add_library(${PROJECT_NAME} ${LIB_TYPE})
|
qt_add_library(${PROJECT_NAME} ${LIB_TYPE})
|
||||||
qt_add_qml_module(${PROJECT_NAME}
|
qt_add_qml_module(${PROJECT_NAME}
|
||||||
PLUGIN_TARGET ${PLUGIN_TARGET_NAME}
|
PLUGIN_TARGET ${PLUGIN_TARGET_NAME}
|
||||||
@ -94,14 +105,14 @@ if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
|||||||
SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH}
|
SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH}
|
||||||
QML_FILES ${qml_files}
|
QML_FILES ${qml_files}
|
||||||
RESOURCES ${resource_files}
|
RESOURCES ${resource_files}
|
||||||
RESOURCE_PREFIX "/"
|
RESOURCE_PREFIX "/qt/qml"
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
include(QmlPlugin)
|
include(QmlPlugin)
|
||||||
add_qmlplugin(${PROJECT_NAME}
|
add_qmlplugin(${PROJECT_NAME}
|
||||||
URI "FluentUI"
|
URI "FluentUI"
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH} resource.qrc
|
SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH} Qt5/imports/fluentui.qrc
|
||||||
QMLFILES ${qml_files}
|
QMLFILES ${qml_files}
|
||||||
QMLDIR imports/FluentUI
|
QMLDIR imports/FluentUI
|
||||||
BINARY_DIR ${FLUENTUI_QML_PLUGIN_DIRECTORY}
|
BINARY_DIR ${FLUENTUI_QML_PLUGIN_DIRECTORY}
|
||||||
@ -109,6 +120,9 @@ else()
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
#去掉mingw生成的动态库libxxx前缀lib,不去掉前缀会导致 module "FluentUI" plugin "fluentuiplugin" not found
|
||||||
|
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
|
||||||
|
|
||||||
#链接库
|
#链接库
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||||
Qt${QT_VERSION_MAJOR}::CorePrivate
|
Qt${QT_VERSION_MAJOR}::CorePrivate
|
||||||
|
17
src/Def.h
17
src/Def.h
@ -4,19 +4,22 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QtQml/qqml.h>
|
#include <QtQml/qqml.h>
|
||||||
|
|
||||||
|
namespace FluViewModelType {
|
||||||
|
Q_NAMESPACE
|
||||||
|
enum Scope {
|
||||||
|
Window = 0x0000,
|
||||||
|
Application = 0x0001
|
||||||
|
};
|
||||||
|
Q_ENUM_NS(Scope)
|
||||||
|
QML_NAMED_ELEMENT(FluViewModelType)
|
||||||
|
}
|
||||||
|
|
||||||
namespace FluHttpType {
|
namespace FluHttpType {
|
||||||
Q_NAMESPACE
|
Q_NAMESPACE
|
||||||
enum CacheMode {
|
enum CacheMode {
|
||||||
/** 不使用缓存 */
|
|
||||||
NoCache = 0x0000,
|
NoCache = 0x0000,
|
||||||
|
|
||||||
/** 请求网络失败后,读取缓存 */
|
|
||||||
RequestFailedReadCache = 0x0001,
|
RequestFailedReadCache = 0x0001,
|
||||||
|
|
||||||
/** 如果缓存不存在才请求网络,否则使用缓存 */
|
|
||||||
IfNoneCacheRequest = 0x0002,
|
IfNoneCacheRequest = 0x0002,
|
||||||
|
|
||||||
/** 先使用缓存,不管是否存在,仍然请求网络 */
|
|
||||||
FirstCacheThenRequest = 0x0004,
|
FirstCacheThenRequest = 0x0004,
|
||||||
};
|
};
|
||||||
Q_ENUM_NS(CacheMode)
|
Q_ENUM_NS(CacheMode)
|
||||||
|
@ -10,19 +10,7 @@
|
|||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include "Def.h"
|
#include "Def.h"
|
||||||
|
|
||||||
FluApp* FluApp::m_instance = nullptr;
|
FluApp::FluApp(QObject *parent):QObject{parent}{
|
||||||
|
|
||||||
FluApp *FluApp::getInstance()
|
|
||||||
{
|
|
||||||
if(FluApp::m_instance == nullptr){
|
|
||||||
FluApp::m_instance = new FluApp;
|
|
||||||
}
|
|
||||||
return FluApp::m_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
FluApp::FluApp(QObject *parent)
|
|
||||||
: QObject{parent}
|
|
||||||
{
|
|
||||||
httpInterceptor(nullptr);
|
httpInterceptor(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,8 +71,7 @@ void FluApp::navigate(const QString& route,const QJsonObject& argument,FluRegist
|
|||||||
view->setColor(QColor(Qt::transparent));
|
view->setColor(QColor(Qt::transparent));
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonArray FluApp::awesomelist(const QString& keyword)
|
QJsonArray FluApp::awesomelist(const QString& keyword){
|
||||||
{
|
|
||||||
QJsonArray arr;
|
QJsonArray arr;
|
||||||
QMetaEnum enumType = Fluent_Awesome::staticMetaObject.enumerator(Fluent_Awesome::staticMetaObject.indexOfEnumerator("Fluent_AwesomeType"));
|
QMetaEnum enumType = Fluent_Awesome::staticMetaObject.enumerator(Fluent_Awesome::staticMetaObject.indexOfEnumerator("Fluent_AwesomeType"));
|
||||||
for(int i=0; i < enumType.keyCount(); ++i){
|
for(int i=0; i < enumType.keyCount(); ++i){
|
||||||
|
73
src/FluApp.h
73
src/FluApp.h
@ -11,6 +11,7 @@
|
|||||||
#include "FluRegister.h"
|
#include "FluRegister.h"
|
||||||
#include "FluHttpInterceptor.h"
|
#include "FluHttpInterceptor.h"
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The FluApp class
|
* @brief The FluApp class
|
||||||
@ -18,80 +19,26 @@
|
|||||||
class FluApp : public QObject
|
class FluApp : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
/**
|
|
||||||
* @brief initialRoute 初始路由
|
|
||||||
*/
|
|
||||||
Q_PROPERTY_AUTO(QString,initialRoute);
|
Q_PROPERTY_AUTO(QString,initialRoute);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief routes 路由表
|
|
||||||
*/
|
|
||||||
Q_PROPERTY_AUTO(QJsonObject,routes);
|
Q_PROPERTY_AUTO(QJsonObject,routes);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief http拦截器
|
|
||||||
*/
|
|
||||||
Q_PROPERTY_AUTO(FluHttpInterceptor*,httpInterceptor);
|
Q_PROPERTY_AUTO(FluHttpInterceptor*,httpInterceptor);
|
||||||
|
|
||||||
QML_NAMED_ELEMENT(FluApp)
|
QML_NAMED_ELEMENT(FluApp)
|
||||||
QML_SINGLETON
|
QML_SINGLETON
|
||||||
private:
|
private:
|
||||||
/**
|
|
||||||
* @brief FluApp 将默认构造函数设置为私有,则qml创建单例就会走create工厂方法创建单例
|
|
||||||
* @param parent
|
|
||||||
*/
|
|
||||||
explicit FluApp(QObject *parent = nullptr);
|
explicit FluApp(QObject *parent = nullptr);
|
||||||
public:
|
|
||||||
~FluApp();
|
~FluApp();
|
||||||
static FluApp *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
|
|
||||||
{
|
|
||||||
return getInstance();
|
|
||||||
}
|
|
||||||
static FluApp *getInstance();
|
|
||||||
/**
|
|
||||||
* @brief run
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE void run();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief navigate
|
|
||||||
* @param route
|
|
||||||
* @param argument
|
|
||||||
* @param fluRegister
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE void navigate(const QString& route,const QJsonObject& argument = {},FluRegister* fluRegister = nullptr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief init
|
|
||||||
* @param window
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE void init(QQuickWindow *window);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief awesomelist
|
|
||||||
* @param keyword
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QJsonArray awesomelist(const QString& keyword = "");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief closeApp
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE void closeApp();
|
|
||||||
|
|
||||||
Q_INVOKABLE void deleteWindow(QQuickWindow* window);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
SINGLETONG(FluApp)
|
||||||
* @brief wnds
|
static FluApp *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
|
||||||
*/
|
Q_INVOKABLE void run();
|
||||||
|
Q_INVOKABLE void navigate(const QString& route,const QJsonObject& argument = {},FluRegister* fluRegister = nullptr);
|
||||||
|
Q_INVOKABLE void init(QQuickWindow *window);
|
||||||
|
Q_INVOKABLE QJsonArray awesomelist(const QString& keyword = "");
|
||||||
|
Q_INVOKABLE void closeApp();
|
||||||
|
Q_INVOKABLE void deleteWindow(QQuickWindow* window);
|
||||||
|
public:
|
||||||
QMap<quint64, QQuickWindow*> wnds;
|
QMap<quint64, QQuickWindow*> wnds;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static FluApp* m_instance;
|
|
||||||
/**
|
|
||||||
* @brief appWindow
|
|
||||||
*/
|
|
||||||
QWindow *appWindow;
|
QWindow *appWindow;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,17 +5,18 @@
|
|||||||
#include <QRandomGenerator>
|
#include <QRandomGenerator>
|
||||||
#include <qmath.h>
|
#include <qmath.h>
|
||||||
|
|
||||||
FluCaptcha::FluCaptcha(QQuickItem *parent)
|
FluCaptcha::FluCaptcha(QQuickItem *parent):QQuickPaintedItem(parent){
|
||||||
: QQuickPaintedItem(parent)
|
ignoreCase(true);
|
||||||
{
|
QFont fontStype;
|
||||||
font(QFont("楷体",25,QFont::Bold,true));
|
fontStype.setPixelSize(28);
|
||||||
|
fontStype.setBold(true);
|
||||||
|
font(fontStype);
|
||||||
setWidth(180);
|
setWidth(180);
|
||||||
setHeight(80);
|
setHeight(80);
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FluCaptcha::paint(QPainter* painter)
|
void FluCaptcha::paint(QPainter* painter){
|
||||||
{
|
|
||||||
painter->save();
|
painter->save();
|
||||||
painter->fillRect(boundingRect().toRect(),QColor(255,255,255,255));
|
painter->fillRect(boundingRect().toRect(),QColor(255,255,255,255));
|
||||||
QPen pen;
|
QPen pen;
|
||||||
@ -69,5 +70,8 @@ void FluCaptcha::refresh(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool FluCaptcha::verify(const QString& code){
|
bool FluCaptcha::verify(const QString& code){
|
||||||
|
if(_ignoreCase){
|
||||||
|
return this->_code.toUpper() == code.toUpper();
|
||||||
|
}
|
||||||
return this->_code == code;
|
return this->_code == code;
|
||||||
}
|
}
|
||||||
|
@ -10,15 +10,17 @@ class FluCaptcha : public QQuickPaintedItem
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY_AUTO(QFont,font);
|
Q_PROPERTY_AUTO(QFont,font);
|
||||||
|
Q_PROPERTY_AUTO(bool,ignoreCase);
|
||||||
QML_NAMED_ELEMENT(FluCaptcha)
|
QML_NAMED_ELEMENT(FluCaptcha)
|
||||||
private:
|
private:
|
||||||
int _generaNumber(int number);
|
int _generaNumber(int number);
|
||||||
QString _code;
|
|
||||||
public:
|
public:
|
||||||
explicit FluCaptcha(QQuickItem *parent = nullptr);
|
explicit FluCaptcha(QQuickItem *parent = nullptr);
|
||||||
void paint(QPainter* painter) override;
|
void paint(QPainter* painter) override;
|
||||||
Q_INVOKABLE void refresh();
|
Q_INVOKABLE void refresh();
|
||||||
Q_INVOKABLE bool verify(const QString& code);
|
Q_INVOKABLE bool verify(const QString& code);
|
||||||
|
private:
|
||||||
|
QString _code;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FLUCAPTCHA_H
|
#endif // FLUCAPTCHA_H
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
#include "FluColorSet.h"
|
#include "FluColorSet.h"
|
||||||
|
|
||||||
FluColorSet::FluColorSet(QObject *parent)
|
FluColorSet::FluColorSet(QObject *parent):QObject{parent}{
|
||||||
: QObject{parent}
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,6 @@
|
|||||||
#include "FluColors.h"
|
#include "FluColors.h"
|
||||||
|
|
||||||
FluColors* FluColors::m_instance = nullptr;
|
FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||||
|
|
||||||
FluColors *FluColors::getInstance()
|
|
||||||
{
|
|
||||||
if(FluColors::m_instance == nullptr){
|
|
||||||
FluColors::m_instance = new FluColors;
|
|
||||||
}
|
|
||||||
return FluColors::m_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
FluColors::FluColors(QObject *parent)
|
|
||||||
: QObject{parent}
|
|
||||||
{
|
|
||||||
Transparent("#00000000");
|
Transparent("#00000000");
|
||||||
Black("#000000");
|
Black("#000000");
|
||||||
White("#ffffff");
|
White("#ffffff");
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <QtQml/qqml.h>
|
#include <QtQml/qqml.h>
|
||||||
#include "FluColorSet.h"
|
#include "FluColorSet.h"
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The FluColors class
|
* @brief The FluColors class
|
||||||
@ -49,13 +50,9 @@ class FluColors : public QObject
|
|||||||
QML_SINGLETON
|
QML_SINGLETON
|
||||||
private:
|
private:
|
||||||
explicit FluColors(QObject *parent = nullptr);
|
explicit FluColors(QObject *parent = nullptr);
|
||||||
static FluColors* m_instance;
|
|
||||||
public:
|
public:
|
||||||
static FluColors *getInstance();
|
SINGLETONG(FluColors)
|
||||||
static FluColors *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
|
static FluColors *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
|
||||||
{
|
|
||||||
return getInstance();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FLUCOLORS_H
|
#endif // FLUCOLORS_H
|
||||||
|
23
src/FluEventBus.cpp
Normal file
23
src/FluEventBus.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "FluEventBus.h"
|
||||||
|
|
||||||
|
FluEvent::FluEvent(QObject *parent):QObject{parent}{
|
||||||
|
}
|
||||||
|
|
||||||
|
FluEventBus::FluEventBus(QObject *parent):QObject{parent}{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluEventBus::registerEvent(FluEvent* event){
|
||||||
|
_eventData.append(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluEventBus::unRegisterEvent(FluEvent* event){
|
||||||
|
_eventData.removeOne(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluEventBus::post(const QString& name,const QMap<QString, QVariant>& data){
|
||||||
|
foreach (auto event, _eventData) {
|
||||||
|
if(event->name()==name){
|
||||||
|
Q_EMIT event->triggered(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
src/FluEventBus.h
Normal file
35
src/FluEventBus.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef FLUEVENTBUS_H
|
||||||
|
#define FLUEVENTBUS_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QtQml/qqml.h>
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
|
class FluEvent : public QObject{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY_AUTO(QString,name);
|
||||||
|
QML_NAMED_ELEMENT(FluEvent)
|
||||||
|
public:
|
||||||
|
explicit FluEvent(QObject *parent = nullptr);
|
||||||
|
Q_SIGNAL void triggered(QMap<QString, QVariant> data);
|
||||||
|
};
|
||||||
|
|
||||||
|
class FluEventBus : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
QML_NAMED_ELEMENT(FluEventBus)
|
||||||
|
QML_SINGLETON
|
||||||
|
private:
|
||||||
|
explicit FluEventBus(QObject *parent = nullptr);
|
||||||
|
public:
|
||||||
|
SINGLETONG(FluEventBus)
|
||||||
|
static FluEventBus *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
|
||||||
|
Q_INVOKABLE void registerEvent(FluEvent* event);
|
||||||
|
Q_INVOKABLE void unRegisterEvent(FluEvent* event);
|
||||||
|
Q_INVOKABLE void post(const QString& name,const QMap<QString, QVariant>& params = {});
|
||||||
|
private:
|
||||||
|
QList<FluEvent*> _eventData;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FLUEVENTBUS_H
|
@ -14,9 +14,7 @@
|
|||||||
#include "FluApp.h"
|
#include "FluApp.h"
|
||||||
#include "FluTools.h"
|
#include "FluTools.h"
|
||||||
|
|
||||||
HttpRequest::HttpRequest(QObject *parent)
|
HttpRequest::HttpRequest(QObject *parent):QObject{parent}{
|
||||||
: QObject{parent}
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QMap<QString, QVariant> HttpRequest::toMap(){
|
QMap<QString, QVariant> HttpRequest::toMap(){
|
||||||
@ -55,14 +53,10 @@ QString HttpRequest::httpId(){
|
|||||||
return FluTools::getInstance()->sha256(QJsonDocument::fromVariant(QVariant(toMap())).toJson(QJsonDocument::Compact));
|
return FluTools::getInstance()->sha256(QJsonDocument::fromVariant(QVariant(toMap())).toJson(QJsonDocument::Compact));
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpCallable::HttpCallable(QObject *parent)
|
HttpCallable::HttpCallable(QObject *parent):QObject{parent}{
|
||||||
: QObject{parent}
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FluHttp::FluHttp(QObject *parent)
|
FluHttp::FluHttp(QObject *parent):QObject{parent}{
|
||||||
: QObject{parent}
|
|
||||||
{
|
|
||||||
retry(3);
|
retry(3);
|
||||||
timeout(15000);
|
timeout(15000);
|
||||||
cacheMode(FluHttpType::CacheMode::NoCache);
|
cacheMode(FluHttpType::CacheMode::NoCache);
|
||||||
@ -82,7 +76,9 @@ void FluHttp::cancel(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FluHttp::post(HttpRequest* request,HttpCallable* callable){
|
void FluHttp::post(HttpRequest* r,HttpCallable* c){
|
||||||
|
auto request = QPointer(r);
|
||||||
|
auto callable = QPointer(c);
|
||||||
request->method("post");
|
request->method("post");
|
||||||
auto requestMap = request->toMap();
|
auto requestMap = request->toMap();
|
||||||
auto httpId = request->httpId();
|
auto httpId = request->httpId();
|
||||||
@ -123,7 +119,8 @@ void FluHttp::post(HttpRequest* request,HttpCallable* callable){
|
|||||||
QString result = QString::fromUtf8(reply->readAll());
|
QString result = QString::fromUtf8(reply->readAll());
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
QString errorString = reply->errorString();
|
QString errorString = reply->errorString();
|
||||||
bool isSuccess = reply->error() == QNetworkReply::NoError;
|
QNetworkReply::NetworkError error = reply->error();
|
||||||
|
bool isSuccess = error == QNetworkReply::NoError;
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
reply = nullptr;
|
reply = nullptr;
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
@ -138,12 +135,17 @@ void FluHttp::post(HttpRequest* request,HttpCallable* callable){
|
|||||||
onError(callable,status,errorString,result);
|
onError(callable,status,errorString,result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(error == QNetworkReply::OperationCanceledError){
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onFinish(callable,request);
|
onFinish(callable,request);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FluHttp::postString(HttpRequest* request,HttpCallable* callable){
|
void FluHttp::postString(HttpRequest* r,HttpCallable* c){
|
||||||
|
auto request = QPointer(r);
|
||||||
|
auto callable = QPointer(c);
|
||||||
request->method("postString");
|
request->method("postString");
|
||||||
auto requestMap = request->toMap();
|
auto requestMap = request->toMap();
|
||||||
auto httpId = request->httpId();
|
auto httpId = request->httpId();
|
||||||
@ -176,7 +178,8 @@ void FluHttp::postString(HttpRequest* request,HttpCallable* callable){
|
|||||||
QString result = QString::fromUtf8(reply->readAll());
|
QString result = QString::fromUtf8(reply->readAll());
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
QString errorString = reply->errorString();
|
QString errorString = reply->errorString();
|
||||||
bool isSuccess = reply->error() == QNetworkReply::NoError;
|
QNetworkReply::NetworkError error = reply->error();
|
||||||
|
bool isSuccess = error == QNetworkReply::NoError;
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
reply = nullptr;
|
reply = nullptr;
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
@ -191,12 +194,17 @@ void FluHttp::postString(HttpRequest* request,HttpCallable* callable){
|
|||||||
onError(callable,status,errorString,result);
|
onError(callable,status,errorString,result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(error == QNetworkReply::OperationCanceledError){
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onFinish(callable,request);
|
onFinish(callable,request);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FluHttp::postJson(HttpRequest* request,HttpCallable* callable){
|
void FluHttp::postJson(HttpRequest* r,HttpCallable* c){
|
||||||
|
auto request = QPointer(r);
|
||||||
|
auto callable = QPointer(c);
|
||||||
request->method("postJson");
|
request->method("postJson");
|
||||||
auto requestMap = request->toMap();
|
auto requestMap = request->toMap();
|
||||||
auto httpId = request->httpId();
|
auto httpId = request->httpId();
|
||||||
@ -228,7 +236,8 @@ void FluHttp::postJson(HttpRequest* request,HttpCallable* callable){
|
|||||||
QString result = QString::fromUtf8(reply->readAll());
|
QString result = QString::fromUtf8(reply->readAll());
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
QString errorString = reply->errorString();
|
QString errorString = reply->errorString();
|
||||||
bool isSuccess = reply->error() == QNetworkReply::NoError;
|
QNetworkReply::NetworkError error = reply->error();
|
||||||
|
bool isSuccess = error == QNetworkReply::NoError;
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
reply = nullptr;
|
reply = nullptr;
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
@ -243,12 +252,17 @@ void FluHttp::postJson(HttpRequest* request,HttpCallable* callable){
|
|||||||
onError(callable,status,errorString,result);
|
onError(callable,status,errorString,result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(error == QNetworkReply::OperationCanceledError){
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onFinish(callable,request);
|
onFinish(callable,request);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FluHttp::get(HttpRequest* request,HttpCallable* callable){
|
void FluHttp::get(HttpRequest* r,HttpCallable* c){
|
||||||
|
auto request = QPointer(r);
|
||||||
|
auto callable = QPointer(c);
|
||||||
request->method("get");
|
request->method("get");
|
||||||
auto requestMap = request->toMap();
|
auto requestMap = request->toMap();
|
||||||
auto httpId = request->httpId();
|
auto httpId = request->httpId();
|
||||||
@ -271,14 +285,15 @@ void FluHttp::get(HttpRequest* request,HttpCallable* callable){
|
|||||||
QNetworkRequest req(url);
|
QNetworkRequest req(url);
|
||||||
addHeaders(&req,data["headers"].toMap());
|
addHeaders(&req,data["headers"].toMap());
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
QNetworkReply* reply = manager.get(req);
|
auto reply = QPointer(manager.get(req));
|
||||||
_cacheReply.append(reply);
|
_cacheReply.append(reply);
|
||||||
connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();});
|
connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();});
|
||||||
connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop](){loop.quit();});
|
connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop](){loop.quit();});
|
||||||
loop.exec();
|
loop.exec();
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
QString errorString = reply->errorString();
|
QString errorString = reply->errorString();
|
||||||
bool isSuccess = reply->error() == QNetworkReply::NoError;
|
QNetworkReply::NetworkError error = reply->error();
|
||||||
|
bool isSuccess = error == QNetworkReply::NoError;
|
||||||
QString result = QString::fromUtf8(reply->readAll());
|
QString result = QString::fromUtf8(reply->readAll());
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
handleCache(httpId,result);
|
handleCache(httpId,result);
|
||||||
@ -294,12 +309,17 @@ void FluHttp::get(HttpRequest* request,HttpCallable* callable){
|
|||||||
}
|
}
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
reply = nullptr;
|
reply = nullptr;
|
||||||
|
if(error == QNetworkReply::OperationCanceledError){
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onFinish(callable,request);
|
onFinish(callable,request);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FluHttp::download(HttpRequest* request,HttpCallable* callable){
|
void FluHttp::download(HttpRequest* r,HttpCallable* c){
|
||||||
|
auto request = QPointer(r);
|
||||||
|
auto callable = QPointer(c);
|
||||||
request->method("download");
|
request->method("download");
|
||||||
auto requestMap = request->toMap();
|
auto requestMap = request->toMap();
|
||||||
auto httpId = request->httpId();
|
auto httpId = request->httpId();
|
||||||
@ -535,11 +555,11 @@ void FluHttp::onStart(QPointer<HttpCallable> callable){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FluHttp::onFinish(QPointer<HttpCallable> callable,HttpRequest* request){
|
void FluHttp::onFinish(QPointer<HttpCallable> callable,QPointer<HttpRequest> request){
|
||||||
if(callable){
|
if(callable){
|
||||||
Q_EMIT callable->finish();
|
Q_EMIT callable->finish();
|
||||||
}
|
}
|
||||||
if(request->parent()->inherits("FluHttp")){
|
if(request&&request->parent()->inherits("FluHttp")){
|
||||||
request->deleteLater();
|
request->deleteLater();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ private:
|
|||||||
bool cacheExists(const QString& httpId);
|
bool cacheExists(const QString& httpId);
|
||||||
QString getCacheFilePath(const QString& httpId);
|
QString getCacheFilePath(const QString& httpId);
|
||||||
void onStart(QPointer<HttpCallable> callable);
|
void onStart(QPointer<HttpCallable> callable);
|
||||||
void onFinish(QPointer<HttpCallable> callable,HttpRequest* request);
|
void onFinish(QPointer<HttpCallable> callable,QPointer<HttpRequest> request);
|
||||||
void onError(QPointer<HttpCallable> callable,int status,QString errorString,QString result);
|
void onError(QPointer<HttpCallable> callable,int status,QString errorString,QString result);
|
||||||
void onSuccess(QPointer<HttpCallable> callable,QString result);
|
void onSuccess(QPointer<HttpCallable> callable,QString result);
|
||||||
void onCache(QPointer<HttpCallable> callable,QString result);
|
void onCache(QPointer<HttpCallable> callable,QString result);
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
#include "FluHttpInterceptor.h"
|
#include "FluHttpInterceptor.h"
|
||||||
|
|
||||||
FluHttpInterceptor::FluHttpInterceptor(QObject *parent)
|
FluHttpInterceptor::FluHttpInterceptor(QObject *parent):QObject{parent}{
|
||||||
: QObject{parent}
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,6 @@ class FluHttpInterceptor : public QObject
|
|||||||
QML_NAMED_ELEMENT(FluHttpInterceptor)
|
QML_NAMED_ELEMENT(FluHttpInterceptor)
|
||||||
public:
|
public:
|
||||||
explicit FluHttpInterceptor(QObject *parent = nullptr);
|
explicit FluHttpInterceptor(QObject *parent = nullptr);
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FLUHTTPINTERCEPTOR_H
|
#endif // FLUHTTPINTERCEPTOR_H
|
||||||
|
28
src/FluRectangle.cpp
Normal file
28
src/FluRectangle.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "FluRectangle.h"
|
||||||
|
#include <QPainterPath>
|
||||||
|
|
||||||
|
FluRectangle::FluRectangle(QQuickItem* parent) : QQuickPaintedItem(parent){
|
||||||
|
setFlag(ItemHasContents, true);
|
||||||
|
color(QColor(255,255,255,255));
|
||||||
|
radius({0,0,0,0});
|
||||||
|
connect(this,&FluRectangle::colorChanged,this,[=]{update();});
|
||||||
|
connect(this,&FluRectangle::radiusChanged,this,[=]{update();});
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluRectangle::paint(QPainter* painter){
|
||||||
|
painter->save();
|
||||||
|
painter->setRenderHint(QPainter::Antialiasing);
|
||||||
|
QPainterPath path;
|
||||||
|
QRectF rect = boundingRect();
|
||||||
|
path.moveTo(rect.bottomRight() - QPointF(0, _radius[2]));
|
||||||
|
path.lineTo(rect.topRight() + QPointF(0, _radius[1]));
|
||||||
|
path.arcTo(QRectF(QPointF(rect.topRight() - QPointF(_radius[1] * 2, 0)), QSize(_radius[1] * 2, _radius[1] * 2)), 0, 90);
|
||||||
|
path.lineTo(rect.topLeft() + QPointF(_radius[0], 0));
|
||||||
|
path.arcTo(QRectF(QPointF(rect.topLeft()), QSize(_radius[0] * 2, _radius[0] * 2)), 90, 90);
|
||||||
|
path.lineTo(rect.bottomLeft() - QPointF(0, _radius[3]));
|
||||||
|
path.arcTo(QRectF(QPointF(rect.bottomLeft() - QPointF(0, _radius[3] * 2)), QSize(_radius[3] * 2, _radius[3] * 2)), 180, 90);
|
||||||
|
path.lineTo(rect.bottomRight() - QPointF(_radius[2], 0));
|
||||||
|
path.arcTo(QRectF(QPointF(rect.bottomRight() - QPointF(_radius[2] * 2, _radius[2] * 2)), QSize(_radius[2] * 2, _radius[2] * 2)), 270, 90);
|
||||||
|
painter->fillPath(path,_color);
|
||||||
|
painter->restore();
|
||||||
|
}
|
20
src/FluRectangle.h
Normal file
20
src/FluRectangle.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef FLURECTANGLE_H
|
||||||
|
#define FLURECTANGLE_H
|
||||||
|
|
||||||
|
#include <QQuickItem>
|
||||||
|
#include <QQuickPaintedItem>
|
||||||
|
#include <QPainter>
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
class FluRectangle : public QQuickPaintedItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY_AUTO(QColor,color)
|
||||||
|
Q_PROPERTY_AUTO(QList<int>,radius)
|
||||||
|
QML_NAMED_ELEMENT(FluRectangle)
|
||||||
|
public:
|
||||||
|
explicit FluRectangle(QQuickItem *parent = nullptr);
|
||||||
|
void paint(QPainter* painter) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FLURECTANGLE_H
|
@ -3,9 +3,7 @@
|
|||||||
#include "FluApp.h"
|
#include "FluApp.h"
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
FluRegister::FluRegister(QObject *parent)
|
FluRegister::FluRegister(QObject *parent):QObject{parent}{
|
||||||
: QObject{parent}
|
|
||||||
{
|
|
||||||
from(nullptr);
|
from(nullptr);
|
||||||
to(nullptr);
|
to(nullptr);
|
||||||
path("");
|
path("");
|
||||||
|
@ -17,25 +17,9 @@ class FluRegister : public QObject
|
|||||||
Q_PROPERTY_AUTO(QString,path);
|
Q_PROPERTY_AUTO(QString,path);
|
||||||
public:
|
public:
|
||||||
explicit FluRegister(QObject *parent = nullptr);
|
explicit FluRegister(QObject *parent = nullptr);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief launch 窗口跳转
|
|
||||||
* @param argument 跳转携带参数
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE void launch(const QJsonObject& argument = {});
|
Q_INVOKABLE void launch(const QJsonObject& argument = {});
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief onResult 将结果数据回传到上一个窗口
|
|
||||||
* @param data 结果数据
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE void onResult(const QJsonObject& data = {});
|
Q_INVOKABLE void onResult(const QJsonObject& data = {});
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief result 收到结果数据的信号
|
|
||||||
* @param data 结果数据
|
|
||||||
*/
|
|
||||||
Q_SIGNAL void result(const QJsonObject& data);
|
Q_SIGNAL void result(const QJsonObject& data);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FLUREGISTER_H
|
#endif // FLUREGISTER_H
|
||||||
|
@ -1,19 +1,6 @@
|
|||||||
#include "FluTextStyle.h"
|
#include "FluTextStyle.h"
|
||||||
|
|
||||||
FluTextStyle* FluTextStyle::m_instance = nullptr;
|
FluTextStyle::FluTextStyle(QObject *parent):QObject{parent}{
|
||||||
|
|
||||||
FluTextStyle *FluTextStyle::getInstance()
|
|
||||||
{
|
|
||||||
if(FluTextStyle::m_instance == nullptr){
|
|
||||||
FluTextStyle::m_instance = new FluTextStyle;
|
|
||||||
}
|
|
||||||
return FluTextStyle::m_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FluTextStyle::FluTextStyle(QObject *parent)
|
|
||||||
: QObject{parent}
|
|
||||||
{
|
|
||||||
QFont caption;
|
QFont caption;
|
||||||
caption.setPixelSize(12);
|
caption.setPixelSize(12);
|
||||||
Caption(caption);
|
Caption(caption);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <QtQml/qqml.h>
|
#include <QtQml/qqml.h>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
class FluTextStyle : public QObject
|
class FluTextStyle : public QObject
|
||||||
{
|
{
|
||||||
@ -21,13 +22,9 @@ public:
|
|||||||
QML_SINGLETON
|
QML_SINGLETON
|
||||||
private:
|
private:
|
||||||
explicit FluTextStyle(QObject *parent = nullptr);
|
explicit FluTextStyle(QObject *parent = nullptr);
|
||||||
static FluTextStyle* m_instance;
|
|
||||||
public:
|
public:
|
||||||
static FluTextStyle *getInstance();
|
SINGLETONG(FluTextStyle)
|
||||||
static FluTextStyle *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
|
static FluTextStyle *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
|
||||||
{
|
|
||||||
return getInstance();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FLUTEXTSTYLE_H
|
#endif // FLUTEXTSTYLE_H
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include "FluTheme.h"
|
#include "FluTheme.h"
|
||||||
|
|
||||||
#include "Def.h"
|
#include <QGuiApplication>
|
||||||
#include "FluColors.h"
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
|
||||||
#include <QStyleHints>
|
#include <QStyleHints>
|
||||||
#elif ((QT_VERSION >= QT_VERSION_CHECK(6, 2, 1)))
|
#elif ((QT_VERSION >= QT_VERSION_CHECK(6, 2, 1)))
|
||||||
@ -10,22 +9,10 @@
|
|||||||
#else
|
#else
|
||||||
#include <QPalette>
|
#include <QPalette>
|
||||||
#endif
|
#endif
|
||||||
|
#include "Def.h"
|
||||||
|
#include "FluColors.h"
|
||||||
|
|
||||||
#include <QGuiApplication>
|
FluTheme::FluTheme(QObject *parent):QObject{parent}{
|
||||||
|
|
||||||
FluTheme* FluTheme::m_instance = nullptr;
|
|
||||||
|
|
||||||
FluTheme *FluTheme::getInstance()
|
|
||||||
{
|
|
||||||
if(FluTheme::m_instance == nullptr){
|
|
||||||
FluTheme::m_instance = new FluTheme;
|
|
||||||
}
|
|
||||||
return FluTheme::m_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
FluTheme::FluTheme(QObject *parent)
|
|
||||||
: QObject{parent}
|
|
||||||
{
|
|
||||||
connect(this,&FluTheme::darkModeChanged,this,[=]{
|
connect(this,&FluTheme::darkModeChanged,this,[=]{
|
||||||
Q_EMIT darkChanged();
|
Q_EMIT darkChanged();
|
||||||
});
|
});
|
||||||
@ -37,8 +24,7 @@ FluTheme::FluTheme(QObject *parent)
|
|||||||
qApp->installEventFilter(this);
|
qApp->installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FluTheme::eventFilter(QObject *obj, QEvent *event)
|
bool FluTheme::eventFilter(QObject *obj, QEvent *event){
|
||||||
{
|
|
||||||
Q_UNUSED(obj);
|
Q_UNUSED(obj);
|
||||||
if (event->type() == QEvent::ApplicationPaletteChange || event->type() == QEvent::ThemeChange)
|
if (event->type() == QEvent::ApplicationPaletteChange || event->type() == QEvent::ThemeChange)
|
||||||
{
|
{
|
||||||
@ -50,8 +36,7 @@ bool FluTheme::eventFilter(QObject *obj, QEvent *event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FluTheme::systemDark()
|
bool FluTheme::systemDark(){
|
||||||
{
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
|
||||||
return (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark);
|
return (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark);
|
||||||
#elif ((QT_VERSION >= QT_VERSION_CHECK(6, 2, 1)))
|
#elif ((QT_VERSION >= QT_VERSION_CHECK(6, 2, 1)))
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <QtQml/qqml.h>
|
#include <QtQml/qqml.h>
|
||||||
#include "FluColorSet.h"
|
#include "FluColorSet.h"
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The FluTheme class
|
* @brief The FluTheme class
|
||||||
@ -12,49 +13,25 @@
|
|||||||
class FluTheme : public QObject
|
class FluTheme : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
/**
|
|
||||||
* @brief dark 改变窗口夜间样式,只读属性,可以通过darkMode切换
|
|
||||||
*/
|
|
||||||
Q_PROPERTY(bool dark READ dark NOTIFY darkChanged)
|
Q_PROPERTY(bool dark READ dark NOTIFY darkChanged)
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief primaryColor 主题颜色
|
|
||||||
*/
|
|
||||||
Q_PROPERTY_AUTO(FluColorSet*,primaryColor)
|
Q_PROPERTY_AUTO(FluColorSet*,primaryColor)
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief darkMode 夜间模式,支持System=0、Light=1、Dark=2
|
|
||||||
*/
|
|
||||||
Q_PROPERTY_AUTO(int,darkMode);
|
Q_PROPERTY_AUTO(int,darkMode);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief nativeText 本地渲染文本
|
|
||||||
*/
|
|
||||||
Q_PROPERTY_AUTO(bool,nativeText);
|
Q_PROPERTY_AUTO(bool,nativeText);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 是否开启动画效果
|
|
||||||
*/
|
|
||||||
Q_PROPERTY_AUTO(bool,enableAnimation);
|
Q_PROPERTY_AUTO(bool,enableAnimation);
|
||||||
|
|
||||||
QML_NAMED_ELEMENT(FluTheme)
|
QML_NAMED_ELEMENT(FluTheme)
|
||||||
QML_SINGLETON
|
QML_SINGLETON
|
||||||
private:
|
private:
|
||||||
static FluTheme* m_instance;
|
|
||||||
explicit FluTheme(QObject *parent = nullptr);
|
explicit FluTheme(QObject *parent = nullptr);
|
||||||
|
bool eventFilter(QObject *obj, QEvent *event);
|
||||||
|
bool systemDark();
|
||||||
public:
|
public:
|
||||||
static FluTheme *getInstance();
|
SINGLETONG(FluTheme)
|
||||||
static FluTheme *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
|
static FluTheme *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
|
||||||
{
|
|
||||||
return getInstance();
|
|
||||||
}
|
|
||||||
bool dark();
|
bool dark();
|
||||||
Q_SIGNAL void darkChanged();
|
Q_SIGNAL void darkChanged();
|
||||||
private:
|
private:
|
||||||
bool _dark;
|
bool _dark;
|
||||||
bool _systemDark;
|
bool _systemDark;
|
||||||
bool eventFilter(QObject *obj, QEvent *event);
|
|
||||||
bool systemDark();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FLUTHEME_H
|
#endif // FLUTHEME_H
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "FluTools.h"
|
#include "FluTools.h"
|
||||||
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
@ -8,23 +9,13 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QOpenGLContext>
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
|
#include <QQuickWindow>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
FluTools* FluTools::m_instance = nullptr;
|
FluTools::FluTools(QObject *parent):QObject{parent}{
|
||||||
|
|
||||||
FluTools *FluTools::getInstance()
|
|
||||||
{
|
|
||||||
if(FluTools::m_instance == nullptr){
|
|
||||||
FluTools::m_instance = new FluTools;
|
|
||||||
}
|
|
||||||
return FluTools::m_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FluTools::FluTools(QObject *parent)
|
|
||||||
: QObject{parent}
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,8 +27,7 @@ QString FluTools::uuid(){
|
|||||||
return QUuid::createUuid().toString();
|
return QUuid::createUuid().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FluTools::readFile(const QString &fileName)
|
QString FluTools::readFile(const QString &fileName){
|
||||||
{
|
|
||||||
QString content;
|
QString content;
|
||||||
QFile file(fileName);
|
QFile file(fileName);
|
||||||
if (file.open(QIODevice::ReadOnly)) {
|
if (file.open(QIODevice::ReadOnly)) {
|
||||||
@ -132,18 +122,15 @@ QColor FluTools::colorAlpha(const QColor& color,qreal alpha){
|
|||||||
return QColor(color.red(),color.green(),color.blue(),255*alpha);
|
return QColor(color.red(),color.green(),color.blue(),255*alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FluTools::md5(QString text)
|
QString FluTools::md5(QString text){
|
||||||
{
|
|
||||||
return QCryptographicHash::hash(text.toUtf8(), QCryptographicHash::Md5).toHex();
|
return QCryptographicHash::hash(text.toUtf8(), QCryptographicHash::Md5).toHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FluTools::toBase64(QString text)
|
QString FluTools::toBase64(QString text){
|
||||||
{
|
|
||||||
return text.toUtf8().toBase64();
|
return text.toUtf8().toBase64();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FluTools::fromBase64(QString text)
|
QString FluTools::fromBase64(QString text){
|
||||||
{
|
|
||||||
return QByteArray::fromBase64(text.toUtf8());
|
return QByteArray::fromBase64(text.toUtf8());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,3 +163,15 @@ void FluTools::showFileInFolder(QString path){
|
|||||||
QProcess::execute("/usr/bin/osascript", {"-e", "tell application \"Finder\" to activate"});
|
QProcess::execute("/usr/bin/osascript", {"-e", "tell application \"Finder\" to activate"});
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FluTools::isSoftware(){
|
||||||
|
return QQuickWindow::sceneGraphBackend() == "software";
|
||||||
|
}
|
||||||
|
|
||||||
|
QPoint FluTools::cursorPos(){
|
||||||
|
return QCursor::pos();
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 FluTools::currentTimestamp(){
|
||||||
|
return QDateTime::currentMSecsSinceEpoch();
|
||||||
|
}
|
||||||
|
156
src/FluTools.h
156
src/FluTools.h
@ -5,6 +5,7 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QtQml/qqml.h>
|
#include <QtQml/qqml.h>
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The FluTools class
|
* @brief The FluTools class
|
||||||
@ -12,187 +13,42 @@
|
|||||||
class FluTools : public QObject
|
class FluTools : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
QML_NAMED_ELEMENT(FluTools)
|
QML_NAMED_ELEMENT(FluTools)
|
||||||
QML_SINGLETON
|
QML_SINGLETON
|
||||||
private:
|
private:
|
||||||
explicit FluTools(QObject *parent = nullptr);
|
explicit FluTools(QObject *parent = nullptr);
|
||||||
static FluTools* m_instance;
|
|
||||||
public:
|
public:
|
||||||
static FluTools *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
|
SINGLETONG(FluTools)
|
||||||
{
|
static FluTools *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
|
||||||
return getInstance();
|
|
||||||
}
|
|
||||||
static FluTools *getInstance();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief qtMajor Qt Major版本
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE int qtMajor();
|
Q_INVOKABLE int qtMajor();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief qtMajor Qt Minor版本
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE int qtMinor();
|
Q_INVOKABLE int qtMinor();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief isMacos 是否是Macos系统
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE bool isMacos();
|
Q_INVOKABLE bool isMacos();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief isLinux 是否是Linux系统
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE bool isLinux();
|
Q_INVOKABLE bool isLinux();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief isWin 是否是Windows系统
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE bool isWin();
|
Q_INVOKABLE bool isWin();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief clipText 将字符串添加到剪切板
|
|
||||||
* @param text
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE void clipText(const QString& text);
|
Q_INVOKABLE void clipText(const QString& text);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief uuid 获取uuid
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QString uuid();
|
Q_INVOKABLE QString uuid();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief readFile 读取文件内容
|
|
||||||
* @param fileName
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QString readFile(const QString& fileName);
|
Q_INVOKABLE QString readFile(const QString& fileName);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief setQuitOnLastWindowClosed 设置关闭最后一个窗口是否退出程序
|
|
||||||
* @param val
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE void setQuitOnLastWindowClosed(bool val);
|
Q_INVOKABLE void setQuitOnLastWindowClosed(bool val);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief setOverrideCursor 设置全局鼠标样式
|
|
||||||
* @param shape
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE void setOverrideCursor(Qt::CursorShape shape);
|
Q_INVOKABLE void setOverrideCursor(Qt::CursorShape shape);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief restoreOverrideCursor 还原全局鼠标样式
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE void restoreOverrideCursor();
|
Q_INVOKABLE void restoreOverrideCursor();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief html2PlantText 将html转换成纯文本
|
|
||||||
* @param html
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QString html2PlantText(const QString& html);
|
Q_INVOKABLE QString html2PlantText(const QString& html);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief toLocalPath 获取文件路径,可以去掉windows系统下的file:///,macos下的file://
|
|
||||||
* @param url
|
|
||||||
* @return 返回文件路径
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QString toLocalPath(const QUrl& url);
|
Q_INVOKABLE QString toLocalPath(const QUrl& url);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief deleteItem 销毁Item对象
|
|
||||||
* @param p
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE void deleteItem(QObject *p);
|
Q_INVOKABLE void deleteItem(QObject *p);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief getFileNameByUrl
|
|
||||||
* @param url
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QString getFileNameByUrl(const QUrl& url);
|
Q_INVOKABLE QString getFileNameByUrl(const QUrl& url);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief getVirtualGeometry
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QRect getVirtualGeometry();
|
Q_INVOKABLE QRect getVirtualGeometry();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief getApplicationDirPath
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QString getApplicationDirPath();
|
Q_INVOKABLE QString getApplicationDirPath();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief getUrlByFilePath
|
|
||||||
* @param path
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QUrl getUrlByFilePath(const QString& path);
|
Q_INVOKABLE QUrl getUrlByFilePath(const QString& path);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief colorAlpha
|
|
||||||
* @param color
|
|
||||||
* @param alpha
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QColor colorAlpha(const QColor&,qreal alpha);
|
Q_INVOKABLE QColor colorAlpha(const QColor&,qreal alpha);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief md5
|
|
||||||
* @param text
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QString md5(QString text);
|
Q_INVOKABLE QString md5(QString text);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief sha256
|
|
||||||
* @param text
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QString sha256(QString text);
|
Q_INVOKABLE QString sha256(QString text);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief toBase64
|
|
||||||
* @param text
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QString toBase64(QString text);
|
Q_INVOKABLE QString toBase64(QString text);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief fromBase64
|
|
||||||
* @param text
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QString fromBase64(QString text);
|
Q_INVOKABLE QString fromBase64(QString text);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief removeDir
|
|
||||||
* @param dirPath
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE bool removeDir(QString dirPath);
|
Q_INVOKABLE bool removeDir(QString dirPath);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief removeFile
|
|
||||||
* @param filePath
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE bool removeFile(QString filePath);
|
Q_INVOKABLE bool removeFile(QString filePath);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief showFileInFolder
|
|
||||||
* @param path
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE void showFileInFolder(QString path);
|
Q_INVOKABLE void showFileInFolder(QString path);
|
||||||
|
Q_INVOKABLE bool isSoftware();
|
||||||
|
Q_INVOKABLE qint64 currentTimestamp();
|
||||||
|
Q_INVOKABLE QPoint cursorPos();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FLUTOOLS_H
|
#endif // FLUTOOLS_H
|
||||||
|
368
src/FluTreeModel.cpp
Normal file
368
src/FluTreeModel.cpp
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
#include "FluTreeModel.h"
|
||||||
|
|
||||||
|
#include <QMetaEnum>
|
||||||
|
|
||||||
|
Node::Node(QObject *parent): QObject{parent}{
|
||||||
|
}
|
||||||
|
|
||||||
|
FluTreeModel::FluTreeModel(QObject *parent): QAbstractItemModel{parent}{
|
||||||
|
dataSourceSize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex FluTreeModel::parent(const QModelIndex &child) const{
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex FluTreeModel::index(int row, int column,const QModelIndex &parent) const{
|
||||||
|
if (!hasIndex(row, column, parent) || parent.isValid())
|
||||||
|
return QModelIndex();
|
||||||
|
return createIndex(row, column, _rows.at(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
int FluTreeModel::rowCount(const QModelIndex &parent) const {
|
||||||
|
return _rows.count();
|
||||||
|
};
|
||||||
|
|
||||||
|
int FluTreeModel::columnCount(const QModelIndex &parent) const {
|
||||||
|
return 1;;
|
||||||
|
};
|
||||||
|
|
||||||
|
QVariant FluTreeModel::data(const QModelIndex &index, int role) const {
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
return QVariant::fromValue(_rows.at(index.row()));
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
};
|
||||||
|
|
||||||
|
QHash<int, QByteArray> FluTreeModel::roleNames() const {
|
||||||
|
return { {Qt::DisplayRole, "modelData"} };
|
||||||
|
};
|
||||||
|
|
||||||
|
void FluTreeModel::setData(QList<Node*> data){
|
||||||
|
beginResetModel();
|
||||||
|
_rows = data;
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluTreeModel::removeRows(int row,int count){
|
||||||
|
if (row < 0 || row + count > _rows.size() || count==0)
|
||||||
|
return;
|
||||||
|
beginRemoveRows(QModelIndex(),row, row + count - 1);
|
||||||
|
QList<Node*> firstPart = _rows.mid(0,row);
|
||||||
|
QList<Node*> secondPart = _rows.mid(row + count);
|
||||||
|
_rows.clear();
|
||||||
|
_rows.append(firstPart);
|
||||||
|
_rows.append(secondPart);
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluTreeModel::insertRows(int row,QList<Node*> data){
|
||||||
|
if (row < 0 || row > _rows.size() || data.size() == 0)
|
||||||
|
return;;
|
||||||
|
beginInsertRows(QModelIndex(), row, row + data.size() - 1);
|
||||||
|
QList<Node*> firstPart = _rows.mid(0, row);
|
||||||
|
QList<Node*> secondPart = _rows.mid(row);
|
||||||
|
_rows.clear();
|
||||||
|
_rows.append(firstPart);
|
||||||
|
_rows.append(data);
|
||||||
|
_rows.append(secondPart);
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject* FluTreeModel::getRow(int row){
|
||||||
|
return _rows.at(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluTreeModel::checkRow(int row,bool chekced){
|
||||||
|
auto itemData = _rows.at(row);
|
||||||
|
if(itemData->hasChildren()){
|
||||||
|
QList<Node*> stack = itemData->_children;
|
||||||
|
std::reverse(stack.begin(), stack.end());
|
||||||
|
while (stack.count() > 0) {
|
||||||
|
auto item = stack.at(stack.count()-1);
|
||||||
|
stack.pop_back();
|
||||||
|
if(!item->hasChildren()){
|
||||||
|
item->_checked = chekced;
|
||||||
|
}
|
||||||
|
QList<Node*> children = item->_children;
|
||||||
|
if(!children.isEmpty()){
|
||||||
|
std::reverse(children.begin(), children.end());
|
||||||
|
foreach (auto c, children) {
|
||||||
|
stack.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(itemData->_checked == chekced){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
itemData->_checked = chekced;
|
||||||
|
}
|
||||||
|
Q_EMIT layoutChanged(QList<QPersistentModelIndex>(),QAbstractItemModel::VerticalSortHint);
|
||||||
|
QList<Node*> data;
|
||||||
|
foreach (auto item, _dataSource) {
|
||||||
|
if(!item->hasChildren()){
|
||||||
|
if(item->_checked){
|
||||||
|
data.append(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectionModel(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluTreeModel::setDataSource(QList<QMap<QString,QVariant>> data){
|
||||||
|
_dataSource.clear();
|
||||||
|
if(_root){
|
||||||
|
delete _root;
|
||||||
|
_root = nullptr;
|
||||||
|
}
|
||||||
|
_root = new Node(this);
|
||||||
|
std::reverse(data.begin(), data.end());
|
||||||
|
while (data.count() > 0) {
|
||||||
|
auto item = data.at(data.count()-1);
|
||||||
|
data.pop_back();
|
||||||
|
Node* node = new Node(this);
|
||||||
|
node->_title = item.value("title").toString();
|
||||||
|
node->_key = item.value("key").toString();
|
||||||
|
node->_depth = item.value("__depth").toInt();
|
||||||
|
node->_parent = item.value("__parent").value<Node*>();
|
||||||
|
node->_isExpanded = true;
|
||||||
|
if(node->_parent){
|
||||||
|
node->_parent->_children.append(node);
|
||||||
|
}else{
|
||||||
|
node->_parent = _root;
|
||||||
|
_root->_children.append(node);
|
||||||
|
}
|
||||||
|
_dataSource.append(node);
|
||||||
|
if (item.contains("children")) {
|
||||||
|
QList<QVariant> children = item.value("children").toList();
|
||||||
|
if(!children.isEmpty()){
|
||||||
|
std::reverse(children.begin(), children.end());
|
||||||
|
for (int i = 0; i < children.count(); ++i) {
|
||||||
|
auto child = children.at(i).toMap();
|
||||||
|
child.insert("__depth",item.value("__depth").toInt(0)+1);
|
||||||
|
child.insert("__parent",QVariant::fromValue(node));
|
||||||
|
data.append(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
beginResetModel();
|
||||||
|
_rows = _dataSource;
|
||||||
|
endResetModel();
|
||||||
|
dataSourceSize(_dataSource.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluTreeModel::collapse(int row){
|
||||||
|
if(!_rows.at(row)->_isExpanded){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_rows.at(row)->_isExpanded = false;
|
||||||
|
Q_EMIT dataChanged(index(row,0),index(row,0));
|
||||||
|
auto modelData = _rows.at(row);
|
||||||
|
int removeCount = 0;
|
||||||
|
for(int i=row+1;i<_rows.count();i++){
|
||||||
|
auto obj = _rows[i];
|
||||||
|
if(obj->_depth<=modelData->_depth){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
removeCount = removeCount + 1;
|
||||||
|
}
|
||||||
|
removeRows(row+1,removeCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluTreeModel::expand(int row){
|
||||||
|
if(_rows.at(row)->_isExpanded){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_rows.at(row)->_isExpanded = true;
|
||||||
|
Q_EMIT dataChanged(index(row,0),index(row,0));
|
||||||
|
auto modelData = _rows.at(row);
|
||||||
|
QList<Node*> insertData;
|
||||||
|
QList<Node*> stack = modelData->_children;
|
||||||
|
std::reverse(stack.begin(), stack.end());
|
||||||
|
while (stack.count() > 0) {
|
||||||
|
auto item = stack.at(stack.count()-1);
|
||||||
|
stack.pop_back();
|
||||||
|
if(item->isShown()){
|
||||||
|
insertData.append(item);
|
||||||
|
}
|
||||||
|
QList<Node*> children = item->_children;
|
||||||
|
if(!children.isEmpty()){
|
||||||
|
std::reverse(children.begin(), children.end());
|
||||||
|
foreach (auto c, children) {
|
||||||
|
stack.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
insertRows(row+1,insertData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluTreeModel::dragAnddrop(int dragIndex,int dropIndex,bool isDropTopArea){
|
||||||
|
if(dropIndex>_rows.count() || dropIndex<0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto dragItem = _rows[dragIndex];
|
||||||
|
auto dropItem = _rows[dropIndex];
|
||||||
|
int targetIndex;
|
||||||
|
if(dropIndex > dragIndex){
|
||||||
|
if(isDropTopArea){
|
||||||
|
targetIndex = dropIndex;
|
||||||
|
}else{
|
||||||
|
targetIndex = dropIndex+1;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(isDropTopArea){
|
||||||
|
targetIndex = dropIndex;
|
||||||
|
}else{
|
||||||
|
targetIndex = dropIndex+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!beginMoveRows(QModelIndex(), dragIndex, dragIndex, QModelIndex(), targetIndex)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(dropIndex > dragIndex){
|
||||||
|
if(isDropTopArea){
|
||||||
|
targetIndex = dropIndex-1;
|
||||||
|
}else{
|
||||||
|
targetIndex = dropIndex;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(isDropTopArea){
|
||||||
|
targetIndex = dropIndex;
|
||||||
|
}else{
|
||||||
|
targetIndex = dropIndex+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_rows.move(dragIndex,targetIndex);
|
||||||
|
endMoveRows();
|
||||||
|
|
||||||
|
Q_EMIT layoutAboutToBeChanged();
|
||||||
|
if(dragItem->_parent == dropItem->_parent){
|
||||||
|
QList<Node*>* children = &(dragItem->_parent->_children);
|
||||||
|
int srcIndex = children->indexOf(dragItem);
|
||||||
|
int destIndex = children->indexOf(dropItem);
|
||||||
|
if(dropIndex > dragIndex){
|
||||||
|
if(isDropTopArea){
|
||||||
|
targetIndex = destIndex-1;
|
||||||
|
}else{
|
||||||
|
targetIndex = destIndex;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(isDropTopArea){
|
||||||
|
targetIndex = destIndex;
|
||||||
|
}else{
|
||||||
|
targetIndex = destIndex+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
children->move(srcIndex,targetIndex);
|
||||||
|
}else{
|
||||||
|
QList<Node*>* srcChildren = &(dragItem->_parent->_children);
|
||||||
|
QList<Node*>* destChildren = &(dropItem->_parent->_children);
|
||||||
|
int srcIndex = srcChildren->indexOf(dragItem);
|
||||||
|
int destIndex = destChildren->indexOf(dropItem);
|
||||||
|
dragItem->_depth = dropItem->_depth;
|
||||||
|
dragItem->_parent = dropItem->_parent;
|
||||||
|
if(dragItem->hasChildren()){
|
||||||
|
QList<Node*> stack = dragItem->_children;
|
||||||
|
foreach (auto node, stack) {
|
||||||
|
node->_depth = dragItem->_depth+1;
|
||||||
|
}
|
||||||
|
std::reverse(stack.begin(), stack.end());
|
||||||
|
while (stack.count() > 0) {
|
||||||
|
auto item = stack.at(stack.count()-1);
|
||||||
|
stack.pop_back();
|
||||||
|
QList<Node*> children = item->_children;
|
||||||
|
if(!children.isEmpty()){
|
||||||
|
std::reverse(children.begin(), children.end());
|
||||||
|
foreach (auto c, children) {
|
||||||
|
c->_depth = item->_depth+1;
|
||||||
|
stack.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
srcChildren->removeAt(srcIndex);
|
||||||
|
if(dropIndex > dragIndex){
|
||||||
|
if(isDropTopArea){
|
||||||
|
targetIndex = destIndex;
|
||||||
|
}else{
|
||||||
|
targetIndex = destIndex + 1;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(isDropTopArea){
|
||||||
|
targetIndex = destIndex;
|
||||||
|
}else{
|
||||||
|
targetIndex = destIndex + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
destChildren->insert(targetIndex,dragItem);
|
||||||
|
}
|
||||||
|
changePersistentIndex(index(qMin(dragIndex,dropIndex),0),index(qMax(dragIndex,dropIndex),0));
|
||||||
|
Q_EMIT layoutChanged(QList<QPersistentModelIndex>(),QAbstractItemModel::VerticalSortHint);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FluTreeModel::hitHasChildrenExpanded(int row){
|
||||||
|
auto itemData = _rows.at(row);
|
||||||
|
if(itemData->hasChildren() && itemData->_isExpanded){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluTreeModel::refreshNode(int row){
|
||||||
|
Q_EMIT dataChanged(index(row,0),index(row,0));
|
||||||
|
};
|
||||||
|
|
||||||
|
Node* FluTreeModel::getNode(int row){
|
||||||
|
return _rows.at(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluTreeModel::allExpand(){
|
||||||
|
beginResetModel();
|
||||||
|
QList<Node*> data;
|
||||||
|
QList<Node*> stack = _root->_children;
|
||||||
|
std::reverse(stack.begin(), stack.end());
|
||||||
|
while (stack.count() > 0) {
|
||||||
|
auto item = stack.at(stack.count()-1);
|
||||||
|
stack.pop_back();
|
||||||
|
if(item->hasChildren()){
|
||||||
|
item->_isExpanded = true;
|
||||||
|
}
|
||||||
|
data.append(item);
|
||||||
|
QList<Node*> children = item->_children;
|
||||||
|
if(!children.isEmpty()){
|
||||||
|
std::reverse(children.begin(), children.end());
|
||||||
|
foreach (auto c, children) {
|
||||||
|
stack.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_rows = data;
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
void FluTreeModel::allCollapse(){
|
||||||
|
beginResetModel();
|
||||||
|
QList<Node*> stack = _root->_children;
|
||||||
|
std::reverse(stack.begin(), stack.end());
|
||||||
|
while (stack.count() > 0) {
|
||||||
|
auto item = stack.at(stack.count()-1);
|
||||||
|
stack.pop_back();
|
||||||
|
if(item->hasChildren()){
|
||||||
|
item->_isExpanded = false;
|
||||||
|
}
|
||||||
|
QList<Node*> children = item->_children;
|
||||||
|
if(!children.isEmpty()){
|
||||||
|
std::reverse(children.begin(), children.end());
|
||||||
|
foreach (auto c, children) {
|
||||||
|
stack.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_rows = _root->_children;
|
||||||
|
endResetModel();
|
||||||
|
}
|
115
src/FluTreeModel.h
Normal file
115
src/FluTreeModel.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#ifndef FLUTREEMODEL_H
|
||||||
|
#define FLUTREEMODEL_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QtQml/qqml.h>
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
class Node : public QObject{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString key READ key CONSTANT)
|
||||||
|
Q_PROPERTY(QString title READ title CONSTANT)
|
||||||
|
Q_PROPERTY(int depth READ depth CONSTANT)
|
||||||
|
Q_PROPERTY(bool isExpanded READ isExpanded CONSTANT)
|
||||||
|
Q_PROPERTY(bool checked READ checked CONSTANT)
|
||||||
|
public:
|
||||||
|
explicit Node(QObject *parent = nullptr);
|
||||||
|
Q_INVOKABLE QString key(){return _key;};
|
||||||
|
Q_INVOKABLE QString title(){return _title;};
|
||||||
|
Q_INVOKABLE int depth(){return _depth;};
|
||||||
|
Q_INVOKABLE bool isExpanded(){return _isExpanded;};
|
||||||
|
Q_INVOKABLE bool hasChildren(){ return !_children.isEmpty();};
|
||||||
|
Q_INVOKABLE bool hasNextNodeByIndex(int index){
|
||||||
|
Node* p = this;
|
||||||
|
for(int i=0;i<(_depth - index -1);i++){
|
||||||
|
p = p->_parent;
|
||||||
|
}
|
||||||
|
if(p->_parent->_children.indexOf(p) == p->_parent->_children.count()-1){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Q_INVOKABLE bool checked(){
|
||||||
|
if(!hasChildren()){
|
||||||
|
return _checked;
|
||||||
|
}
|
||||||
|
foreach (auto item, _children) {
|
||||||
|
if(!item->checked()){
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
Q_INVOKABLE bool hideLineFooter(){
|
||||||
|
if(_parent){
|
||||||
|
auto childIndex = _parent->_children.indexOf(this);
|
||||||
|
if(childIndex==_parent->_children.count()-1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(_parent->_children.at(childIndex+1)->hasChildren()){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
bool isShown(){
|
||||||
|
auto p = _parent;
|
||||||
|
while (p) {
|
||||||
|
if(!p->_isExpanded){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
p = p->_parent;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
QString _key="";
|
||||||
|
QString _title="";
|
||||||
|
int _depth=0;
|
||||||
|
bool _checked = false;
|
||||||
|
bool _isExpanded=true;
|
||||||
|
QList<Node*> _children;
|
||||||
|
Node* _parent = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FluTreeModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY_AUTO(int,dataSourceSize)
|
||||||
|
Q_PROPERTY_AUTO(QList<Node*>,selectionModel)
|
||||||
|
QML_NAMED_ELEMENT(FluTreeModel)
|
||||||
|
QML_ADDED_IN_MINOR_VERSION(1)
|
||||||
|
public:
|
||||||
|
explicit FluTreeModel(QObject *parent = nullptr);
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
QModelIndex parent(const QModelIndex &child) const override;
|
||||||
|
QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
Q_INVOKABLE void removeRows(int row,int count);
|
||||||
|
Q_INVOKABLE void insertRows(int row,QList<Node*> data);
|
||||||
|
Q_INVOKABLE QObject* getRow(int row);
|
||||||
|
Q_INVOKABLE void setData(QList<Node*> data);
|
||||||
|
Q_INVOKABLE void setDataSource(QList<QMap<QString,QVariant>> data);
|
||||||
|
Q_INVOKABLE void collapse(int row);
|
||||||
|
Q_INVOKABLE void expand(int row);
|
||||||
|
Q_INVOKABLE void dragAnddrop(int dragIndex,int dropIndex,bool isDropTopArea);
|
||||||
|
Q_INVOKABLE Node* getNode(int row);
|
||||||
|
Q_INVOKABLE void refreshNode(int row);
|
||||||
|
Q_INVOKABLE void checkRow(int row,bool chekced);
|
||||||
|
Q_INVOKABLE bool hitHasChildrenExpanded(int row);
|
||||||
|
Q_INVOKABLE void allExpand();
|
||||||
|
Q_INVOKABLE void allCollapse();
|
||||||
|
private:
|
||||||
|
QList<Node*> _rows;
|
||||||
|
QList<Node*> _dataSource;
|
||||||
|
Node* _root = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FLUTREEMODEL_H
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user