Compare commits

..

195 Commits
1.3.2 ... 1.5.2

Author SHA1 Message Date
855305f197 update 2023-08-11 22:47:36 +08:00
6fe3081d23 update 2023-08-11 14:31:23 +08:00
b1a2266c5e update 2023-08-10 20:05:38 +08:00
048abb5dbd update 2023-08-10 18:59:34 +08:00
991ea383e7 update 2023-08-10 18:29:43 +08:00
73518fb831 update 2023-08-10 16:22:43 +08:00
312aebae73 update 2023-08-10 16:08:27 +08:00
3c349da98f update 2023-08-08 21:59:18 +08:00
dba7332d89 update 2023-08-08 21:57:08 +08:00
3fefb08140 update 2023-08-08 21:33:16 +08:00
1c69d5daab update 2023-08-08 21:31:33 +08:00
ec76240aed update 2023-08-08 21:03:15 +08:00
0a967ca47b update 2023-08-08 20:21:32 +08:00
8dbbf4e547 update 2023-08-08 19:59:06 +08:00
ebad24e809 update 2023-08-08 15:44:10 +08:00
b7acae1470 update 2023-08-07 22:11:08 +08:00
f8340bdf59 update 2023-08-07 21:46:54 +08:00
e4fb9989d0 update 2023-08-07 18:18:04 +08:00
9bd98c68e4 Merge pull request #232 from FeJQ/FluNavigationView-pr
给FluPaneItemSeparator增加spacing和size属性
2023-08-04 12:05:15 +08:00
7cd9b7c6bc 给FluPaneItemSeparator增加spacing和size属性 2023-08-03 18:14:52 +08:00
dde817923c update 2023-07-28 16:22:15 +08:00
ceaae1276e update 2023-07-28 16:18:49 +08:00
29c57bcdc3 update 2023-07-28 16:08:58 +08:00
7ba60ee570 update 2023-07-27 18:13:50 +08:00
f531f5b138 update 2023-07-27 17:46:18 +08:00
4f27ff41b9 update 2023-07-26 22:06:55 +08:00
42f058ca69 update 2023-07-26 17:48:35 +08:00
502044ebd2 update 2023-07-26 11:02:33 +08:00
5d902dc66e update 2023-07-25 21:24:45 +08:00
b22e79148b update 2023-07-25 17:57:37 +08:00
7122407b0b update 2023-07-24 21:49:32 +08:00
be7b2dcc34 update 2023-07-24 18:23:26 +08:00
db805ef85d update 2023-07-24 16:48:45 +08:00
d0e283747e Merge pull request #214 from mentalfl0w/dev
examlple: Make the items in searchbox more readable.
2023-07-24 09:38:34 +08:00
2d8a05f310 examlple: Make the items in searchbox more readable. 2023-07-24 01:20:23 +08:00
2d855e1aaa update 2023-07-23 21:19:07 +08:00
56188cfa51 update 2023-07-23 21:06:46 +08:00
169ca17a6a update 2023-07-23 20:56:04 +08:00
e4908e409b Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2023-07-23 20:44:47 +08:00
f141af154a update 2023-07-23 20:44:43 +08:00
10da873701 Merge pull request #210 from mentalfl0w/dev
Fix the FolderDialog and macOS download bug.
2023-07-23 15:42:59 +08:00
c23c0b5f42 Fix the FolderDialog and macOS download bug.
1. fix the "FolderDialog is not a type" error in Qt 6.2.4 and below.
2. fix download error in macOS.
2023-07-22 12:27:55 +08:00
4d78262277 update 2023-07-21 18:58:09 +08:00
2b88634c2f Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2023-07-21 11:19:33 +08:00
59f9495f31 update 2023-07-21 11:19:30 +08:00
29329d10df update 2023-07-20 21:54:45 +08:00
d014997d52 update 2023-07-20 18:26:47 +08:00
98e0aafb44 update 2023-07-18 18:24:06 +08:00
4b3548563b update 2023-07-18 14:07:07 +08:00
47c84ed60e update 2023-07-17 11:05:14 +08:00
d5ca38dec2 update framelesshelper 2023-07-17 10:12:57 +08:00
cb50c31e1e update 2023-07-17 09:25:12 +08:00
561b4ec8c0 update 2023-07-15 00:20:33 +08:00
4df6800ea4 update 2023-07-14 23:56:08 +08:00
1ecc1bd569 update 2023-07-14 18:18:46 +08:00
0810572e27 update 2023-07-14 16:15:25 +08:00
5ac0ba7463 update 2023-07-13 12:18:38 +08:00
596457cf59 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2023-07-13 10:21:13 +08:00
8595b2fdec update 2023-07-13 10:20:45 +08:00
2337680aaf Merge pull request #200 from mentalfl0w/dev
Add Svg module to resolve unsupported image format error.
2023-07-12 08:37:49 +08:00
ba06480436 Add Svg module to resolve unsupported image format error. 2023-07-11 23:38:36 +08:00
0d87dadc61 update 2023-07-11 17:16:21 +08:00
7290b98fdb update 2023-07-11 16:43:28 +08:00
78815224fe update 2023-07-11 10:46:57 +08:00
6275c161fe Merge pull request #195 from mentalfl0w/main
Fix the bug of static resources didn't imported by engine.
2023-07-10 21:37:40 +08:00
9f24cdaebd Fix the bug of static resources didn't imported by engine. 2023-07-10 19:09:50 +08:00
e2ff752ed9 Merge pull request #193 from mentalfl0w/main
Add Build static lib option and fix the bug of static lib build.
2023-07-10 09:18:55 +08:00
ea88707366 Add Build static lib option and fix the bug of static lib build. 2023-07-10 00:03:41 +08:00
112bb6e07a update 2023-07-07 17:58:00 +08:00
26ad581072 update 2023-07-07 16:56:29 +08:00
03771cd7c9 update 2023-07-07 16:04:17 +08:00
9223d5f937 update 2023-07-07 11:47:03 +08:00
a273aa4588 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2023-07-07 09:04:58 +08:00
fbcb65f549 update 2023-07-07 09:04:43 +08:00
082fd79c51 update 2023-07-06 18:50:15 +08:00
80619f6974 update 2023-07-06 18:17:52 +08:00
ad4d077480 update 2023-07-05 21:34:08 +08:00
ff93a6204a update 2023-07-05 19:18:32 +08:00
5a7dfeea6e update 2023-07-04 22:47:55 +08:00
0240244bba update 2023-07-04 22:39:57 +08:00
887fd2c02b update 2023-07-04 22:38:56 +08:00
e625b91b08 update 2023-07-04 16:08:04 +08:00
a5cf6f734b updatre 2023-07-04 15:45:50 +08:00
414bc14996 updatre 2023-07-04 15:43:29 +08:00
7276eb5f2f update 2023-07-04 15:15:58 +08:00
b6c689e0ec update 2023-07-04 15:09:48 +08:00
a48bc51edc update 2023-07-03 21:25:26 +08:00
b2d0975ed7 update 2023-07-03 18:44:43 +08:00
7dea573069 update 2023-07-03 18:08:25 +08:00
0d4dd483da update 2023-07-03 11:50:26 +08:00
d1656cfb63 update 2023-07-01 11:37:58 +08:00
73cc5bccc8 update 2023-07-01 11:37:08 +08:00
9ff81251c8 update 2023-07-01 07:54:43 +08:00
74940665ae update 2023-06-30 22:55:03 +08:00
21ddc79f3f update 2023-06-30 22:50:44 +08:00
64bbae9266 update 2023-06-30 18:47:25 +08:00
bbb6fe9329 update 2023-06-30 17:39:58 +08:00
c42f3ef70f update 2023-06-30 17:22:27 +08:00
f13f1727af update 2023-06-30 12:08:57 +08:00
9f9e48659b update 2023-06-29 23:36:36 +08:00
294606d019 update 2023-06-29 22:30:15 +08:00
bfa5c93d40 update 2023-06-29 18:47:10 +08:00
9656b3dd95 update 2023-06-29 17:48:48 +08:00
8a52f143d7 update 2023-06-29 10:07:02 +08:00
dc3b1acaa5 update 2023-06-29 10:03:24 +08:00
1a8d06331f update 2023-06-28 18:12:33 +08:00
d09414db1b update 2023-06-28 18:07:39 +08:00
bf3006415b update 2023-06-28 13:16:21 +08:00
cdba8b7921 update 2023-06-28 13:15:33 +08:00
192c65a510 update 2023-06-28 13:13:39 +08:00
90943674b3 update 2023-06-28 12:12:15 +08:00
157dc9166b update 2023-06-28 09:45:47 +08:00
a7e8a5e4cf update 2023-06-28 02:28:34 +08:00
96071ac8d7 update 2023-06-27 22:14:27 +08:00
e25b944704 update 2023-06-27 21:14:20 +08:00
1566e3934e update 2023-06-27 21:02:57 +08:00
16e71f01b1 Merge pull request #172 from mentalfl0w/dev
Make the FluTableView readonly text copiable.
2023-06-27 20:47:21 +08:00
e54c161aa6 Make the FluTableView readonly text copiable. 2023-06-27 20:39:57 +08:00
2147965b00 update 2023-06-27 00:17:01 +08:00
3a940466d5 update 2023-06-27 00:00:41 +08:00
564b27cd02 update 2023-06-26 23:57:50 +08:00
4be2ad6ba0 Merge pull request #171 from mentalfl0w/dev
FluTableView bug fixed.
2023-06-26 23:41:14 +08:00
1d9f6f5eff FluTableView bug fixed. 2023-06-26 23:21:15 +08:00
0610f63f26 update 2023-06-26 19:59:28 +08:00
d741b3eb4f update 2023-06-26 18:20:01 +08:00
cb7d2097f2 update 2023-06-26 18:12:58 +08:00
dff77d3d4f update 2023-06-26 11:43:49 +08:00
6d0834c653 update 2023-06-25 23:39:23 +08:00
059a1b17cc update 2023-06-25 23:17:44 +08:00
e1096b8e22 update 2023-06-25 19:01:22 +08:00
cd577c5599 update 2023-06-25 11:44:13 +08:00
d43532986a update 2023-06-25 11:30:25 +08:00
4c9e576072 update 2023-06-25 10:13:50 +08:00
b254064e26 Merge pull request #168 from mentalfl0w/dev
Fix qt_standard_project_setup for Qt 6.2 and below.
2023-06-25 09:03:12 +08:00
ffd8072826 Fix qt_standard_project_setup for Qt 6.2 and below. 2023-06-24 21:57:00 +08:00
9a1db0b230 update 2023-06-24 11:56:32 +08:00
9786e69fc2 update 2023-06-24 10:27:28 +08:00
82be3b12e3 update 2023-06-21 17:17:25 +08:00
1c0f5acaf8 update 2023-06-21 16:12:07 +08:00
243f8aa248 update 2023-06-21 11:47:05 +08:00
cbb8c3122b update 2023-06-21 00:43:05 +08:00
9f2c58306c update 2023-06-20 19:18:18 +08:00
adc3558e02 update .gitignore 2023-06-20 19:02:18 +08:00
98d73eb6cb update 2023-06-20 18:32:10 +08:00
b442696f92 update 2023-06-20 18:02:15 +08:00
82f606dd65 update 2023-06-20 12:53:32 +08:00
4efb91084a update 2023-06-19 18:08:49 +08:00
103dbe9d56 update 2023-06-19 17:50:54 +08:00
b829fa572f update 2023-06-19 09:52:19 +08:00
d2c5cc779b update 2023-06-19 09:50:11 +08:00
5acf664492 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2023-06-19 09:12:59 +08:00
75d226947f update 2023-06-18 23:54:39 +08:00
752ff3c4f2 update 2023-06-18 13:56:30 +08:00
e591c483d5 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2023-06-16 17:17:25 +08:00
fdff068752 update 2023-06-16 17:17:21 +08:00
24f28d8945 update 2023-06-16 12:45:57 +08:00
ed51143e9b update 2023-06-16 12:25:50 +08:00
9d94bc65d5 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2023-06-16 09:30:33 +08:00
7bfa9f0191 update 2023-06-16 09:30:21 +08:00
6db144c751 Update README.md 2023-06-15 15:58:56 +08:00
a574cd9230 update 2023-06-15 15:01:33 +08:00
8c45c125e6 update 2023-06-15 14:46:32 +08:00
aab4802d7e update 2023-06-15 07:39:45 +08:00
441c1ab03c update 2023-06-15 00:42:07 +08:00
91f4f508cc update 2023-06-15 00:21:54 +08:00
94f8047508 update 2023-06-14 19:29:23 +08:00
d926a84f72 update 2023-06-14 00:04:37 +08:00
c07011408c update 2023-06-13 23:57:52 +08:00
4f9ec6abf2 update 2023-06-13 22:24:22 +08:00
c3b3dc904e update 2023-06-13 22:00:15 +08:00
2a5acb45a1 update 2023-06-13 20:13:49 +08:00
d29580f8f2 update 2023-06-13 18:17:40 +08:00
fd0ddbf5aa update 2023-06-13 11:48:29 +08:00
ac602c5afa update 2023-06-13 10:26:14 +08:00
8dbfcfd994 Merge pull request #157 from mentalfl0w/dev
Fix FluNavigationView push function in Standard mode.
2023-06-13 09:20:58 +08:00
c5ce34cbc3 Fix FluNavigationView push function in Standard mode. 2023-06-12 22:41:58 +08:00
a4d04499bc update 2023-06-12 18:03:25 +08:00
47b0c71f95 update 2023-06-12 17:36:36 +08:00
e651b731cf update 2023-06-12 17:04:35 +08:00
31bdea8d44 update 2023-06-12 16:46:02 +08:00
2fbc5696f7 update 2023-06-12 10:53:35 +08:00
f2ea9a19a1 update 2023-06-11 21:48:43 +08:00
aee97c2aab update 2023-06-11 21:44:54 +08:00
05b41f3383 update 2023-06-10 22:46:17 +08:00
b3ca045936 update 2023-06-10 11:11:28 +08:00
18205851f6 update 2023-06-10 11:01:36 +08:00
221361369e update 2023-06-09 18:15:09 +08:00
cf730bc769 update 2023-06-09 09:29:28 +08:00
49029164ff update 2023-06-08 23:19:38 +08:00
6da4a2e10e fix bub 2023-06-08 17:44:32 +08:00
021745c366 update version 2023-06-08 17:16:08 +08:00
2cfd5b3ab2 update 2023-06-08 17:05:52 +08:00
2c7d556042 update 2023-06-08 17:00:43 +08:00
609df92f8c update 2023-06-08 14:51:13 +08:00
ca57b16521 update 2023-06-08 14:32:04 +08:00
292 changed files with 28314 additions and 3428 deletions

View File

@ -0,0 +1,308 @@
if(__get_git_revision_description)
return()
endif()
set(__get_git_revision_description YES)
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
function(_git_find_closest_git_dir _start_dir _git_dir_var)
set(cur_dir "${_start_dir}")
set(git_dir "${_start_dir}/.git")
while(NOT EXISTS "${git_dir}")
set(git_previous_parent "${cur_dir}")
get_filename_component(cur_dir ${cur_dir} DIRECTORY)
if(cur_dir STREQUAL git_previous_parent)
set(${_git_dir_var}
""
PARENT_SCOPE)
return()
endif()
set(git_dir "${cur_dir}/.git")
endwhile()
set(${_git_dir_var}
"${git_dir}"
PARENT_SCOPE)
endfunction()
function(get_git_head_revision _refspecvar _hashvar)
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR")
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE)
else()
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE)
endif()
if(NOT "${GIT_DIR}" STREQUAL "")
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
"${GIT_DIR}")
if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
set(GIT_DIR "")
endif()
endif()
if("${GIT_DIR}" STREQUAL "")
set(${_refspecvar}
"GITDIR-NOTFOUND"
PARENT_SCOPE)
set(${_hashvar}
"GITDIR-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT IS_DIRECTORY ${GIT_DIR})
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-parse
--show-superproject-working-tree
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT "${out}" STREQUAL "")
file(READ ${GIT_DIR} submodule)
string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE
${submodule})
string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
ABSOLUTE)
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
else()
file(READ ${GIT_DIR} worktree_ref)
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
${worktree_ref})
string(STRIP ${git_worktree_dir} git_worktree_dir)
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
endif()
else()
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
endif()
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
if(NOT EXISTS "${GIT_DATA}")
file(MAKE_DIRECTORY "${GIT_DATA}")
endif()
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
return()
endif()
set(HEAD_FILE "${GIT_DATA}/HEAD")
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
"${GIT_DATA}/grabRef.cmake" @ONLY)
include("${GIT_DATA}/grabRef.cmake")
set(${_refspecvar}
"${HEAD_REF}"
PARENT_SCOPE)
set(${_hashvar}
"${HEAD_HASH}"
PARENT_SCOPE)
endfunction()
function(git_latest_tag _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --abbrev=0 --tag
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "GIT-TAG-NOTFOUND")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_commit_counts _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-list HEAD --count
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "GIT-TAG-NOTFOUND")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_describe _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_release_version _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" symbolic-ref --short -q HEAD
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
string(FIND ${out} "release/" found})
if(${out} MATCHES "^release/.+$")
string(REPLACE "release/" "" tmp_out ${out})
set(${_var} "${tmp_out}" PARENT_SCOPE)
else()
set(${_var} "" PARENT_SCOPE)
endif()
endfunction()
function(git_describe_working_tree _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_get_exact_tag _var)
git_describe(out --exact-match ${ARGN})
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_local_changes _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(res EQUAL 0)
set(${_var}
"CLEAN"
PARENT_SCOPE)
else()
set(${_var}
"DIRTY"
PARENT_SCOPE)
endif()
endfunction()
git_release_version(GIT_TAG)
git_get_exact_tag(GIT_EXACT_TAG)
if(GIT_TAG STREQUAL "")
git_latest_tag(GIT_TAG)
endif()
if(GIT_TAG STREQUAL "GIT-TAG-NOTFOUND")
set(GIT_TAG "1.0.0")
endif ()
git_describe(GIT_DESCRIBE)
git_commit_counts(GIT_COMMIT_COUNT)
string(REPLACE "." "," GIT_TAG_WITH_COMMA ${GIT_TAG})
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" GIT_SEMVER "${GIT_TAG}")
string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" SEMVER_SPLITED "${GIT_SEMVER}")
set(MAJOR_VERSION ${CMAKE_MATCH_1})
set(MINOR_VERSION ${CMAKE_MATCH_2})
set(PATCH_VERSION ${CMAKE_MATCH_3})
MATH(EXPR VERSION_COUNTER "${MAJOR_VERSION} * 10000 + ${MINOR_VERSION} * 100 + ${PATCH_VERSION}")
message(STATUS "Current git tag: ${GIT_TAG}, commit count: ${GIT_COMMIT_COUNT}, describe: ${GIT_DESCRIBE}")
message(STATUS "Current semver: major: ${MAJOR_VERSION}, minor: ${MINOR_VERSION}, patch: ${PATCH_VERSION}, counter: ${VERSION_COUNTER}")

View File

@ -0,0 +1,43 @@
#
# Internal file for GetGitRevisionDescription.cmake
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright 2009-2012, Iowa State University
# Copyright 2011-2015, Contributors
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
# SPDX-License-Identifier: BSL-1.0
set(HEAD_HASH)
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
if(HEAD_CONTENTS MATCHES "ref")
# named branch
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
else()
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
set(HEAD_HASH "${CMAKE_MATCH_1}")
endif()
endif()
else()
# detached HEAD
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
endif()
if(NOT HEAD_HASH)
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
string(STRIP "${HEAD_HASH}" HEAD_HASH)
endif()

12
.cmake/Version.h.in Normal file
View File

@ -0,0 +1,12 @@
// 应用程序版本信息
// 请勿修改此头文件,因为这个文件是自动生成的
#ifndef VERSION_H
#define VERSION_H
#include <QtGlobal>
#define APPLICATION_VERSION "${GIT_SEMVER}.${GIT_COMMIT_COUNT}"
#define VERSION_COUNTER ${GIT_COMMIT_COUNT}
#define COMMIT_HASH "${GIT_DESCRIBE}"
#endif // VERSION_H

32
.cmake/version_dll.rc.in Normal file
View File

@ -0,0 +1,32 @@
1 VERSIONINFO
FILEVERSION ${GIT_TAG_WITH_COMMA},${GIT_COMMIT_COUNT}
PRODUCTVERSION ${GIT_TAG_WITH_COMMA},${GIT_COMMIT_COUNT}
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404b0"
BEGIN
VALUE "CompanyName", "ZhuZiChu"
VALUE "FileDescription", "${PROJECT_DESCRIPTION}"
VALUE "FileVersion", "${GIT_SEMVER}.${GIT_COMMIT_COUNT}"
VALUE "InternalName", "${PROJECT_NAME}.dll"
VALUE "LegalCopyright", "Copyright (C) 2023 ZhuZiChu. All rights reserved."
VALUE "OriginalFilename", "${PROJECT_NAME}.dll"
VALUE "ProductName", "${PROJECT_NAME}"
VALUE "ProductVersion", "${GIT_SEMVER}.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 1200
END
END

34
.cmake/version_exe.rc.in Normal file
View File

@ -0,0 +1,34 @@
1 VERSIONINFO
FILEVERSION ${GIT_TAG_WITH_COMMA},${GIT_COMMIT_COUNT}
PRODUCTVERSION ${GIT_TAG_WITH_COMMA},${GIT_COMMIT_COUNT}
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404b0"
BEGIN
VALUE "CompanyName", "ZhuZiChu"
VALUE "FileDescription", "${PROJECT_DESCRIPTION}"
VALUE "FileVersion", "${GIT_SEMVER}.${GIT_COMMIT_COUNT}"
VALUE "InternalName", "${PROJECT_NAME}.exe"
VALUE "LegalCopyright", "Copyright (C) 2023 ZhuZiChu. All rights reserved."
VALUE "OriginalFilename", "${PROJECT_NAME}.exe"
VALUE "ProductName", "${PROJECT_NAME}"
VALUE "ProductVersion", "${GIT_SEMVER}.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 1200
END
END
IDI_ICON1 ICON DISCARDABLE "${CMAKE_SOURCE_DIR}/example/favicon.ico"

3
.gitignore vendored
View File

@ -31,9 +31,10 @@ target_wrapper.*
# QtCreator CMake
CMakeLists.txt.user*
src/build-preset/plugins.qmltypes
bin
.DS_Store
build
cmake-build-*
.idea
example/Version.h

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "framelesshelper"]
path = framelesshelper
url = https://github.com/zhuzichu520/framelesshelper.git
[submodule "zxing-cpp"]
path = zxing-cpp
url = https://github.com/zhuzichu520/zxing-cpp.git

View File

@ -1,7 +1,40 @@
cmake_minimum_required(VERSION 3.16)
cmake_minimum_required(VERSION 3.20)
project(FluentUI VERSION 0.1 LANGUAGES CXX)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/.cmake/")
include(GetGitRevisionDescription)
option(FLUENTUI_BUILD_EXAMPLES "Build FluentUI demo applications." ON)
option(FLUENTUI_BUILD_FRAMELESSHEPLER "Build FramelessHelper." ON)
option(FLUENTUI_BUILD_STATIC_LIB "Build static library." OFF)
#设置QML插件输出目录可以通过外部设置如果外部没有设置就默认到<QT_SDK_DIR_PATH>\qml\FluentUI目录下
set(FLUENTUI_QML_PLUGIN_DIRECTORY "" CACHE PATH "Path to FluentUI plugin")
if(NOT FLUENTUI_QML_PLUGIN_DIRECTORY)
set(FLUENTUI_QML_PLUGIN_DIRECTORY ${CMAKE_PREFIX_PATH}/qml/FluentUI)
endif()
add_subdirectory(src)
add_subdirectory(example)
add_subdirectory(framelesshelper)
add_subdirectory(zxing-cpp)
if (FLUENTUI_BUILD_EXAMPLES)
add_subdirectory(example)
endif ()
if (FLUENTUI_BUILD_FRAMELESSHEPLER)
set(FRAMELESSHELPER_BUILD_STATIC ON)
set(FRAMELESSHELPER_NO_SUMMARY OFF)
set(FRAMELESSHELPER_NO_DEBUG_OUTPUT OFF)
set(FRAMELESSHELPER_BUILD_WIDGETS OFF)
add_definitions(-DFRAMELESSHELPER_CORE_NO_DEBUG_OUTPUT)
add_definitions(-DFRAMELESSHELPER_QUICK_NO_DEBUG_OUTPUT)
add_subdirectory(framelesshelper)
endif ()
message("------------------------ FluentUI ------------------------")
message("Build FluentUI demo applications.: ${FLUENTUI_BUILD_EXAMPLES}")
message("Build FramelessHelper.: ${FLUENTUI_BUILD_FRAMELESSHEPLER}")
message("Build static library.: ${FLUENTUI_BUILD_STATIC_LIB}")
message("Path to FluentUI plugin.: ${FLUENTUI_QML_PLUGIN_DIRECTORY}")

View File

@ -115,5 +115,9 @@ View more [`here`](doc/md/all_components.md)!
This FluentUI library currently licensed under [MIT License](./License)
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=zhuzichu520/FluentUI&type=Date)](https://star-history.com/#zhuzichu520/FluentUI&Date)
## ⚡ Visitor count
![](https://profile-counter.glitch.me/zhuzichu520-FluentUI/count.svg)

0
doc/preview/demo_content_dialog.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

0
doc/preview/demo_filledbtn.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

0
doc/preview/demo_icon.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

0
doc/preview/demo_infobar.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

0
doc/preview/demo_large.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 192 KiB

0
doc/preview/demo_multiline_textbox.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

0
doc/preview/demo_progress_bar_ring.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

0
doc/preview/demo_radiobtn.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

0
doc/preview/demo_rectangle.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

0
doc/preview/demo_slider.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 997 B

After

Width:  |  Height:  |  Size: 997 B

0
doc/preview/demo_standardbtn.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

0
doc/preview/demo_textbox.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

0
doc/preview/demo_textbtn.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

0
doc/preview/demo_toggle_switch.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

0
doc/preview/demo_tooltip.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

0
doc/preview/demo_tree_view.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

0
doc/preview/qt_creator_project.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -1,14 +1,21 @@
cmake_minimum_required(VERSION 3.16)
cmake_minimum_required(VERSION 3.20)
project(example VERSION 0.1 LANGUAGES CXX)
#配置通用编译
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(APPLE)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
endif()
#导入exmaple的QML位置不然import example有时候会爆红
set(QML_IMPORT_PATH ${CMAKE_BINARY_DIR}/example CACHE STRING "Qt Creator extra QML import paths" FORCE)
#判断FluentUI库类型
if(FLUENTUI_BUILD_STATIC_LIB)
add_definitions(-DFLUENTUI_BUILD_STATIC_LIB)
endif()
#设置可执行文件输出目录
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/debug)
@ -19,10 +26,22 @@ endif()
#获取文件路径分隔符(解决执行命令的时候有些平台会报错)
file(TO_CMAKE_PATH "/" PATH_SEPARATOR)
#设置版本号
add_definitions(-DVERSION=1,3,2,0)
find_package(Qt6 REQUIRED COMPONENTS Quick Svg Network)
find_package(Qt6 REQUIRED COMPONENTS Quick REQUIRED)
if(QT_VERSION VERSION_GREATER_EQUAL "6.3")
qt_standard_project_setup()
else()
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
endif()
##生成版本信息头文件
set(HEADER_FILE_VERSION_PATH ${CMAKE_SOURCE_DIR}/example/Version.h)
configure_file(
${CMAKE_SOURCE_DIR}/.cmake/Version.h.in
${HEADER_FILE_VERSION_PATH}
)
#遍历所有Cpp文件
file(GLOB_RECURSE CPP_FILES *.cpp *.h)
@ -45,11 +64,21 @@ foreach(filepath ${RES_PATHS})
list(APPEND resource_files ${filename})
endforeach(filepath)
#如果是Windows平台则生成rc文件
set(EXAMPLE_VERSION_RC_PATH "")
if(WIN32)
set(EXAMPLE_VERSION_RC_PATH ${CMAKE_BINARY_DIR}/version_${PROJECT_NAME}.rc)
configure_file(
${CMAKE_SOURCE_DIR}/.cmake/version_exe.rc.in
${EXAMPLE_VERSION_RC_PATH}
)
endif()
#添加可执行文件
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
if (WIN32)
qt_add_executable(example
${sources_files}
example.rc
${EXAMPLE_VERSION_RC_PATH}
)
else ()
qt_add_executable(example
@ -75,12 +104,17 @@ endif()
#添加qml模块
qt_add_qml_module(example
URI example
URI "example"
VERSION 1.0
QML_FILES ${qml_files}
RESOURCES ${resource_files}
)
#导入component头文件,不然通过QML_NAMED_ELEMENT生成的c++类会找不到头文件报错
target_include_directories(example PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/component
)
#设置属性
set_target_properties(example PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
@ -91,14 +125,30 @@ set_target_properties(example PROPERTIES
)
#链接库
target_link_libraries(example PRIVATE
if (FLUENTUI_BUILD_STATIC_LIB)
target_link_libraries(example PRIVATE
Qt6::Quick
Qt6::Svg
Qt6::Network
fluentui
fluentuiplugin
FramelessHelper::Core
FramelessHelper::Quick
)
)
else()
target_link_libraries(example PRIVATE
Qt6::Quick
Qt6::Svg
Qt6::Network
fluentuiplugin
FramelessHelper::Core
FramelessHelper::Quick
)
endif()
#安装
install(TARGETS example
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

View File

@ -1,42 +0,0 @@
#include <windows.h>
IDI_ICON1 ICON "favicon.ico"
#define STR(x) #x
#define VER_JOIN(a,b,c,d) STR(a.b.c.d)
#define VER_JOIN_(x) VER_JOIN x
#define VER_STR VER_JOIN_((VERSION))
VS_VERSION_INFO VERSIONINFO
FILEVERSION VERSION
PRODUCTVERSION VERSION
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "Built by the FluentUI."
VALUE "CompanyName", "zhuzichu"
VALUE "FileDescription", "example"
VALUE "FileVersion", VER_STR
VALUE "InternalName", ""
VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", ""
VALUE "ProductName", "example"
VALUE "ProductVersion", VER_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View File

@ -5,20 +5,40 @@ import QtQuick.Layouts
import FluentUI
Window {
id:app
id: app
flags: Qt.SplashScreen
FluHttpInterceptor{
id:interceptor
function onIntercept(request){
if(request.method === "get"){
request.params["method"] = "get"
}
if(request.method === "post"){
request.params["method"] = "post"
}
request.headers["token"] ="yyds"
request.headers["os"] ="pc"
console.debug(JSON.stringify(request))
return request
}
}
Component.onCompleted: {
FluApp.init(app)
FluTheme.darkMode = FluDarkMode.System
FluTheme.darkMode = FluThemeType.System
FluTheme.enableAnimation = true
FluApp.routes = {
"/":"qrc:/example/qml/window/MainWindow.qml",
"/about":"qrc:/example/qml/window/AboutWindow.qml",
"/login":"qrc:/example/qml/window/LoginWindow.qml",
"/media":"qrc:/example/qml/window/MediaWindow.qml",
"/hotload":"qrc:/example/qml/window/HotloadWindow.qml",
"/singleTaskWindow":"qrc:/example/qml/window/SingleTaskWindow.qml",
"/standardWindow":"qrc:/example/qml/window/StandardWindow.qml",
"/singleInstanceWindow":"qrc:/example/qml/window/SingleInstanceWindow.qml"
}
FluApp.initialRoute = "/"
FluApp.httpInterceptor = interceptor
FluApp.run()
}
}

View File

@ -26,11 +26,6 @@ FluExpander{
color:FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(247/255,247/255,247/255,1)
border.color: FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
border.width: 1
Behavior on color{
ColorAnimation {
duration: 300
}
}
}
}
@ -42,13 +37,8 @@ FluExpander{
rightMargin: 5
topMargin: 5
}
onActiveFocusChanged: {
if(activeFocus){
control.expand = true
}
}
onClicked:{
FluTools.clipText(content.text)
FluTools.clipText(FluTools.html2PlantText(content.text))
showSuccess("复制成功")
}
}
@ -134,13 +124,22 @@ FluExpander{
"FluPasswordBox",
"FluBreadcrumbBar",
"FluCopyableText",
"FluAcrylic"
"FluAcrylic",
"FluRemoteLoader",
"FluMenuBar",
"FluPagination",
"FluRadioButtons",
"FluImage",
"FluSpinBox",
"FluHttp",
"FluWatermark",
"FluTour",
"FluQRCode",
"FluTimeline",
"FluChart"
];
code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;");
return code.replace(RegExp("\\b(" + qmlKeywords.join("|") + ")\\b", "g"), "<span style='color: #c23a80'>$1</span>");
}
}

View File

@ -4,14 +4,11 @@ import FluentUI
import org.wangwenx190.FramelessHelper
FluWindow {
id:window
property bool fixSize
property alias titleVisible: title_bar.titleVisible
property bool appBarVisible: true
default property alias content: container.data
FluAppBar {
id: title_bar
title: window.title
@ -23,7 +20,6 @@ FluWindow {
}
darkText: lang.dark_mode
}
Item{
id:container
anchors{
@ -34,20 +30,19 @@ FluWindow {
}
clip: true
}
FramelessHelper{
id:framless_helper
onReady: {
setTitleBarItem(title_bar)
framless_helper.moveWindowToDesktopCenter()
moveWindowToDesktopCenter()
setHitTestVisible(title_bar.minimizeButton())
setHitTestVisible(title_bar.maximizeButton())
setHitTestVisible(title_bar.closeButton())
framless_helper.setWindowFixedSize(fixSize)
setWindowFixedSize(fixSize)
title_bar.maximizeButton.visible = !fixSize
if (blurBehindWindowEnabled)
window.backgroundVisible = false
window.visible = true
window.background = undefined
window.show()
}
}
Connections{
@ -59,13 +54,10 @@ FluWindow {
FramelessUtils.systemTheme = FramelessHelperConstants.Light
}
}
function setHitTestVisible(com){
framless_helper.setHitTestVisible(com)
}
function setTitleBarItem(com){
framless_helper.setTitleBarItem(com)
}
}

View File

@ -8,16 +8,17 @@ FluObject{
property var navigationView
FluPaneItem{
id:item_home
count: 9
title:lang.home
infoBadge:FluBadge{
count: item_home.count
}
icon:FluentIcons.Home
// cusIcon: Image{
// anchors.centerIn: parent
// source: FluTheme.dark ? "qrc:/example/res/svg/home_dark.svg" : "qrc:/example/res/svg/home.svg"
// sourceSize: Qt.size(30,30)
// width: 18
// height: 18
// }
onTap:{
if(navigationView.getCurrentUrl()){
item_home.count = 0
}
navigationView.push("qrc:/example/qml/page/T_Home.qml")
}
}
@ -26,20 +27,39 @@ FluObject{
title:lang.basic_input
icon:FluentIcons.CheckboxComposite
FluPaneItem{
id:item_buttons
count: 99
infoBadge:FluBadge{
count: item_buttons.count
}
title:"Buttons"
image:"qrc:/example/res/image/control/Button.png"
recentlyUpdated:true
desc:"A control that responds to user input and raisesa Click event."
onTap:{
item_buttons.count = 0
navigationView.push("qrc:/example/qml/page/T_Buttons.qml")
}
}
FluPaneItem{
id:item_text
title:"Text"
count: 5
infoBadge:FluBadge{
count: item_text.count
color: Qt.rgba(82/255,196/255,26/255,1)
}
onTap:{
item_text.count = 0
navigationView.push("qrc:/example/qml/page/T_Text.qml")
}
}
FluPaneItem{
title:"Image"
onTap:{
navigationView.push("qrc:/example/qml/page/T_Image.qml")
}
}
FluPaneItem{
title:"Slider"
image:"qrc:/example/res/image/control/Slider.png"
@ -58,6 +78,12 @@ FluObject{
navigationView.push("qrc:/example/qml/page/T_CheckBox.qml")
}
}
FluPaneItem{
title:"RadioButton"
onTap:{
navigationView.push("qrc:/example/qml/page/T_RadioButton.qml")
}
}
FluPaneItem{
title:"ToggleSwitch"
onTap:{
@ -155,6 +181,12 @@ FluObject{
navigationView.push("qrc:/example/qml/page/T_Expander.qml")
}
}
FluPaneItem{
title:"Watermark"
onTap:{
navigationView.push("qrc:/example/qml/page/T_Watermark.qml")
}
}
}
FluPaneItemExpander{
@ -167,8 +199,15 @@ FluObject{
}
}
FluPaneItem{
id:item_combobox
title:"ComboBox"
count: 9
infoBadge:FluBadge{
count: item_combobox.count
color: Qt.rgba(250/255,173/255,20/255,1)
}
onTap:{
item_combobox.count = 0
navigationView.push("qrc:/example/qml/page/T_ComboBox.qml")
}
}
@ -231,6 +270,12 @@ FluObject{
navigationView.push("qrc:/example/qml/page/T_TableView.qml")
}
}
FluPaneItem{
title:"Pagination"
onTap:{
navigationView.push("qrc:/example/qml/page/T_Pagination.qml")
}
}
FluPaneItem{
title:"MultiWindow"
onTap:{
@ -278,17 +323,61 @@ FluObject{
}
}
FluPaneItemSeparator{
spacing:20
size:1
}
FluPaneItemExpander{
title:lang.media
icon:FluentIcons.Media
title:lang.other
icon:FluentIcons.Shop
FluPaneItem{
title:"MediaPlayer"
image:"qrc:/example/res/image/control/MediaPlayerElement.png"
recentlyAdded:true
order:0
desc:"A control to display video and image content."
title:"QRCode"
onTap:{
navigationView.push("qrc:/example/qml/page/T_MediaPlayer.qml")
navigationView.push("qrc:/example/qml/page/T_QRCode.qml")
}
}
FluPaneItem{
title:"Tour"
onTap:{
navigationView.push("qrc:/example/qml/page/T_Tour.qml")
}
}
FluPaneItem{
title:"Timeline"
onTap:{
navigationView.push("qrc:/example/qml/page/T_Timeline.qml")
}
}
FluPaneItem{
title:"Chart"
onTap:{
navigationView.push("qrc:/example/qml/page/T_Chart.qml")
}
}
FluPaneItem{
title:"Http"
onTap:{
navigationView.push("qrc:/example/qml/page/T_Http.qml")
}
}
FluPaneItem{
id:item_other
title:"RemoteLoader"
count: 99
infoBadge:FluBadge{
count: item_other.count
color: Qt.rgba(82/255,196/255,26/255,1)
}
onTap:{
item_other.count = 0
navigationView.push("qrc:/example/qml/page/T_RemoteLoader.qml")
}
}
FluPaneItem{
title:"HotLoader"
tapFunc:function(){
FluApp.navigate("/hotload")
}
}
}
@ -331,6 +420,11 @@ FluObject{
for(var i=0;i<items.length;i++){
var item = items[i]
if(item instanceof FluPaneItem){
if (item.parent instanceof FluPaneItemExpander)
{
arr.push({title:`${item.parent.title} -> ${item.title}`,key:item.key})
}
else
arr.push({title:item.title,key:item.key})
}
}

View File

@ -5,5 +5,5 @@ import QtQuick.Controls
import FluentUI
QtObject {
property int displayMode : FluNavigationView.Auto
property int displayMode : FluNavigationViewType.Auto
}

View File

@ -3,41 +3,90 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Acrylic"
RowLayout{
spacing: 10
Layout.topMargin: 20
FluText{
text:"tintColor:"
Layout.alignment: Qt.AlignVCenter
}
FluColorPicker{
id:color_picker
}
}
RowLayout{
spacing: 10
FluText{
text:"tintOpacity:"
Layout.alignment: Qt.AlignVCenter
}
FluSlider{
id:slider_tint_opacity
value: 65
}
}
RowLayout{
spacing: 10
FluText{
text:"blurRadius:"
Layout.alignment: Qt.AlignVCenter
}
FluSlider{
id:slider_blur_radius
value: 32
}
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 1200/5+20
height: 1200/4+20
paddings: 10
Layout.topMargin: 10
FluRectangle{
width: 1920/5
height: 1200/5
width: 1920/4
height: 1200/4
radius:[15,15,15,15]
Image {
id:image
asynchronous: true
source: "qrc:/example/res/image/banner_3.jpg"
source: "qrc:/example/res/image/bg_scenic.png"
anchors.fill: parent
sourceSize: Qt.size(2*width,2*height)
}
FluAcrylic {
sourceItem:image
anchors.bottom: parent.bottom
anchors.right: parent.right
width: 100
height: 100
id:acrylic
target: image
width: 200
height: 200
tintOpacity: slider_tint_opacity.value/100
tintColor: color_picker.colorValue
blurRadius: slider_blur_radius.value
x:(image.width-width)/2
y:(image.height-height)/2
FluText {
anchors.centerIn: parent
text: "Acrylic"
color: "#FFFFFF"
font.bold: true
}
MouseArea {
property point clickPos: Qt.point(0,0)
id:drag_area
anchors.fill: parent
onPressed: (mouse)=>{
clickPos = Qt.point(mouse.x, mouse.y)
}
onPositionChanged: (mouse)=>{
var delta = Qt.point(mouse.x - clickPos.x,mouse.y - clickPos.y)
acrylic.x = acrylic.x + delta.x
acrylic.y = acrylic.y + delta.y
}
}
}
Layout.topMargin: 20
}
@ -54,10 +103,11 @@ FluScrollablePage{
radius: 8
}
FluAcrylic{
sourceItem:image
target:image
width: 100
height: 100
anchors.centerIn: parent
}
}'
}

View File

@ -33,6 +33,7 @@ FluContentPage {
cellWidth: 80
cellHeight: 80
clip: true
boundsBehavior: GridView.StopAtBounds
model:FluApp.awesomelist()
ScrollBar.vertical: FluScrollBar {}
anchors{

View File

@ -3,7 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -33,6 +33,8 @@ FluScrollablePage{
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
topRight: true
showZero: true
count:0
}
}
@ -43,6 +45,8 @@ FluScrollablePage{
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
topRight: true
showZero: true
count:5
}
}
@ -52,6 +56,8 @@ FluScrollablePage{
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
topRight: true
showZero: true
count:50
}
}
@ -61,6 +67,8 @@ FluScrollablePage{
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
topRight: true
showZero: true
count:100
}
}
@ -70,6 +78,8 @@ FluScrollablePage{
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
topRight: true
showZero: true
isDot:true
}
}
@ -79,6 +89,8 @@ FluScrollablePage{
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
topRight: true
showZero: true
count:99
color: Qt.rgba(250/255,173/255,20/255,1)
}
@ -89,6 +101,8 @@ FluScrollablePage{
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
topRight: true
showZero: true
count:99
color: Qt.rgba(82/255,196/255,26/255,1)
}

View File

@ -3,7 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{

View File

@ -4,7 +4,7 @@ import QtQuick.Window
import QtQuick.Controls
import QtQuick.Controls.Basic
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -24,6 +24,7 @@ FluScrollablePage{
FluTextButton{
disabled:text_button_switch.checked
text:"Text Button"
contentDescription: "文本按钮"
onClicked: {
showInfo("点击Text Button")
}
@ -210,20 +211,21 @@ FluScrollablePage{
verticalCenter: parent.verticalCenter
left: parent.left
}
items:[
FluMenuItem{
text:"Menu_1"
},
}
FluMenuItem{
text:"Menu_2"
},
}
FluMenuItem{
text:"Menu_3"
},
}
FluMenuItem{
text:"Menu_4"
onClicked: {
}
}
]
}
FluToggleSwitch{
id:drop_down_button_switch
@ -239,7 +241,6 @@ FluScrollablePage{
Layout.topMargin: -1
code:'FluDropDownButton{
text:"DropDownButton"
items:[
FluMenuItem{
text:"Menu_1"
},
@ -252,7 +253,6 @@ FluScrollablePage{
FluMenuItem{
text:"Menu_4"
}
]
}'
}
@ -261,24 +261,23 @@ FluScrollablePage{
height: 100
paddings: 10
Layout.topMargin: 20
ColumnLayout{
FluRadioButtons{
spacing: 8
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
Repeater{
id:repeater
property int selecIndex : 0
model: 3
delegate: FluRadioButton{
checked : repeater.selecIndex===index
FluRadioButton{
disabled:radio_button_switch.checked
text:"Radio Button_"+index
clickListener:function(){
repeater.selecIndex = index
text:"Radio Button_1"
}
FluRadioButton{
disabled:radio_button_switch.checked
text:"Radio Button_2"
}
FluRadioButton{
disabled:radio_button_switch.checked
text:"Radio Button_3"
}
}
FluToggleSwitch{

View File

@ -3,7 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{

View File

@ -3,12 +3,25 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Carousel"
ListModel{
id:data_model
ListElement{
url:"qrc:/example/res/image/banner_1.jpg"
}
ListElement{
url:"qrc:/example/res/image/banner_2.jpg"
}
ListElement{
url:"qrc:/example/res/image/banner_3.jpg"
}
}
FluArea{
Layout.fillWidth: true
height: 370
@ -24,23 +37,95 @@ FluScrollablePage{
text:"轮播图支持无限轮播无限滑动用ListView实现的组件"
}
FluCarousel{
id:carousel
radius:[5,5,5,5]
delegate: Component{
Image {
anchors.fill: parent
source: model.url
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
}
Layout.topMargin: 20
Layout.leftMargin: 5
Component.onCompleted: {
carousel.setData([{url:"qrc:/example/res/image/banner_1.jpg"},{url:"qrc:/example/res/image/banner_2.jpg"},{url:"qrc:/example/res/image/banner_3.jpg"}])
model = [{url:"qrc:/example/res/image/banner_1.jpg"},{url:"qrc:/example/res/image/banner_2.jpg"},{url:"qrc:/example/res/image/banner_3.jpg"}]
}
}
}
}
FluArea{
Layout.fillWidth: true
height: 340
paddings: 10
Layout.topMargin: 10
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left:parent.left
}
FluCarousel{
radius:[15,15,15,15]
loopTime:1500
indicatorGravity: Qt.AlignHCenter | Qt.AlignTop
indicatorMarginTop:15
delegate: Component{
Item{
anchors.fill: parent
Image {
anchors.fill: parent
source: model.url
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
Rectangle{
height: 40
width: parent.width
anchors.bottom: parent.bottom
color: "#33000000"
FluText{
anchors.fill: parent
verticalAlignment: Qt.AlignVCenter
horizontalAlignment: Qt.AlignHCenter
text:model.title
color: FluColors.Grey10
font.pixelSize: 15
}
}
}
}
Layout.topMargin: 20
Layout.leftMargin: 5
Component.onCompleted: {
var arr = []
arr.push({url:"qrc:/example/res/image/banner_1.jpg",title:"共同应对全球性问题"})
arr.push({url:"qrc:/example/res/image/banner_2.jpg",title:"三小只全程没互动"})
arr.push({url:"qrc:/example/res/image/banner_3.jpg",title:"有效投资扩大 激发增长动能"})
model = arr
}
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluCarousel{
id:carousel
width: 400
height: 300
delegate: Component{
Image {
anchors.fill: parent
source: model.url
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
}
Component.onCompleted: {
setData([{url:"qrc:/example/res/image/banner_1.jpg"},{url:"qrc:/example/res/image/banner_2.jpg"},{url:"qrc:/example/res/image/banner_3.jpg"}])
carousel.model = [{url:"qrc:/example/res/image/banner_1.jpg"},{url:"qrc:/example/res/image/banner_2.jpg"},{url:"qrc:/example/res/image/banner_3.jpg"}]
}
}'
}

View File

@ -0,0 +1,331 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Chart"
function randomScalingFactor() {
return Math.random().toFixed(1);
}
FluArea{
height: 370
width: 500
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'scatter'
chartData: {
return {
datasets: [{
label: 'My First dataset',
xAxisID: 'x-axis-1',
yAxisID: 'y-axis-1',
borderColor: '#ff5555',
backgroundColor: 'rgba(255,192,192,0.3)',
data: [{
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}]
}, {
label: 'My Second dataset',
xAxisID: 'x-axis-1',
yAxisID: 'y-axis-2',
borderColor: '#5555ff',
backgroundColor: 'rgba(192,192,255,0.3)',
data: [{
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}]
}]
}}
chartOptions: {return {
maintainAspectRatio: false,
responsive: true,
hoverMode: 'nearest',
intersect: true,
title: {
display: true,
text: 'Chart.js Scatter Chart - Multi Axis'
},
scales: {
xAxes: [{
position: 'bottom',
gridLines: {
zeroLineColor: 'rgba(0,0,0,1)'
}
}],
yAxes: [{
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: 'left',
id: 'y-axis-1',
}, {
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: 'right',
reverse: true,
id: 'y-axis-2',
// grid line settings
gridLines: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
}],
}
}
}
}
}
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'bar'
chartData: { return {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'Dataset 1',
backgroundColor: '#ff9999',
stack: 'Stack 0',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
]
}, {
label: 'Dataset 2',
backgroundColor: '#9999ff',
stack: 'Stack 0',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
]
}, {
label: 'Dataset 3',
backgroundColor: '#99ff99',
stack: 'Stack 1',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
]
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Bar Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
}
}
}
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'pie'
chartData: {return {
datasets: [{
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
],
backgroundColor: [
'#ffbbbb',
'#ffddaa',
'#ffffbb',
'#bbffbb',
'#bbbbff'
],
label: 'Dataset 1'
}],
labels: [
'Red',
'Orange',
'Yellow',
'Green',
'Blue'
]
}}
chartOptions: {return {maintainAspectRatio: false, responsive: true}}
}
}
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'line'
chartData: { return {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'Filled',
fill: true,
backgroundColor: 'rgba(192,222,255,0.3)',
borderColor: 'rgba(128,192,255,255)',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
],
}, {
label: 'Dashed',
fill: false,
backgroundColor: 'rgba(0,0,0,0)',
borderColor: '#009900',
borderDash: [5, 5],
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
],
}, {
label: 'Filled',
backgroundColor: 'rgba(0,0,0,0)',
borderColor: '#990000',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
],
fill: false,
}]
}
}
chartOptions: {return {
maintainAspectRatio: false,
responsive: true,
title: {
display: true,
text: 'Chart.js Line Chart'
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Month'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Value'
}
}]
}
}
}
}
}
}

View File

@ -3,7 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -22,7 +22,12 @@ FluScrollablePage{
}
FluCheckBox{
disabled: check_box_switch.checked
text:"Text"
text:"Right"
}
FluCheckBox{
disabled: check_box_switch.checked
text:"Left"
textRight: false
}
}
FluToggleSwitch{

View File

@ -3,7 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -23,8 +23,6 @@ FluScrollablePage{
text:"此颜色组件是Github上的开源项目"
}
FluTextButton{
leftPadding: 0
rightPadding: 0
text:"https://github.com/rshest/qml-colorpicker"
onClicked: {
Qt.openUrlExternally(text)

View File

@ -3,7 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -28,10 +28,6 @@ FluScrollablePage{
ListElement { text: "Apple" }
ListElement { text: "Coconut" }
}
onAccepted: {
if (find(editText) === -1)
model_1.append({text: editText})
}
}
}
}
@ -50,6 +46,7 @@ FluScrollablePage{
}
FluComboBox {
editable: true
font:FluTextStyle.BodyStrong
model: ListModel {
id: model_2
ListElement { text: "Banana" }

View File

@ -3,7 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -23,6 +23,9 @@ FluScrollablePage{
text:"showYear=true"
}
FluDatePicker{
onCurrentChanged: {
showSuccess(current.toLocaleDateString())
}
}
}
}
@ -50,7 +53,9 @@ FluScrollablePage{
FluDatePicker{
showYear:false
onCurrentChanged: {
showSuccess(current.toLocaleDateString())
}
}
}
}

View File

@ -3,7 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -31,7 +31,7 @@ FluScrollablePage{
title:"友情提示"
message:"确定要退出程序么?"
negativeText:"取消"
buttonFlags: FluContentDialog.NegativeButton | FluContentDialog.PositiveButton
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
onNegativeClicked:{
showSuccess("点击取消按钮")
}
@ -47,7 +47,7 @@ FluScrollablePage{
id:double_btn_dialog
title:"友情提示"
message:"确定要退出程序么?"
buttonFlags: FluContentDialog.NegativeButton | FluContentDialog.PositiveButton
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
negativeText:"取消"
onNegativeClicked:{
showSuccess("点击取消按钮")
@ -80,7 +80,7 @@ FluScrollablePage{
title:"友情提示"
message:"确定要退出程序么?"
negativeText:"取消"
buttonFlags: FluContentDialog.NeutralButton | FluContentDialog.NegativeButton | FluContentDialog.PositiveButton
buttonFlags: FluContentDialogType.NeutralButton | FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
negativeText:"取消"
onNegativeClicked:{
showSuccess("点击取消按钮")
@ -101,7 +101,7 @@ FluScrollablePage{
id:triple_btn_dialog
title:"友情提示"
message:"确定要退出程序么?"
buttonFlags: FluContentDialog.NeutralButton | FluContentDialog.NegativeButton | FluContentDialog.PositiveButton
buttonFlags: FluContentDialogType.NeutralButton | FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
negativeText:"取消"
onNegativeClicked:{
showSuccess("点击取消按钮")

View File

@ -3,7 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -27,7 +27,7 @@ FluScrollablePage{
Layout.topMargin: 20
Item{
anchors.fill: parent
ColumnLayout{
FluRadioButtons{
spacing: 8
anchors{
top: parent.top
@ -35,17 +35,14 @@ FluScrollablePage{
topMargin: 15
leftMargin: 15
}
Repeater{
id:repeater
property int selecIndex : 0
model: 3
delegate: FluRadioButton{
checked : repeater.selecIndex===index
text:"Radio Button_"+index
clickListener:function() {
repeater.selecIndex = index
FluRadioButton{
text:"Radio Button_1"
}
FluRadioButton{
text:"Radio Button_2"
}
FluRadioButton{
text:"Radio Button_3"
}
}
}

View File

@ -3,7 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -76,7 +76,6 @@ FluScrollablePage{
Image{
source: "qrc:/example/res/image/banner_1.jpg"
asynchronous: true
sourceSize: Qt.size(400,300)
fillMode:Image.PreserveAspectCrop
}
Image{

View File

@ -2,11 +2,14 @@ import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import "qrc:///example/qml/global/"
import "qrc:///example/qml/global"
import FluentUI
FluScrollablePage{
launchMode: FluPageType.SingleTask
animDisabled: true
ListModel{
id:model_header
ListElement{
@ -15,7 +18,6 @@ FluScrollablePage{
desc:"The latest FluentUI controls and styles for your applications."
url:"https://github.com/zhuzichu520/FluentUI"
}
}
Item{
@ -66,19 +68,17 @@ FluScrollablePage{
id: control
width: 220
height: 240
FluArea{
radius: 8
FluItem{
radius: [8,8,8,8]
width: 200
height: 220
anchors.centerIn: parent
color: 'transparent'
FluAcrylic {
sourceItem:bg
FluAcrylic{
anchors.fill: parent
color: FluTheme.dark ? Window.active ? Qt.rgba(38/255,44/255,54/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
rectX: list.x-list.contentX+10+(control.width)*index
rectY: list.y+10
acrylicOpacity:0.8
tintColor: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1)
target: bg
blurRadius : 40
targetRect: Qt.rect(list.x-list.contentX+10+(control.width)*index,list.y+10,width,height)
}
Rectangle{
anchors.fill: parent
@ -86,18 +86,17 @@ FluScrollablePage{
color:{
if(FluTheme.dark){
if(item_mouse.containsMouse){
return Qt.rgba(1,1,1,0.03)
return Qt.rgba(1,1,1,0.06)
}
return Qt.rgba(0,0,0,0)
return Qt.rgba(0,0,0,0.03)
}else{
if(item_mouse.containsMouse){
return Qt.rgba(0,0,0,0.03)
return Qt.rgba(0,0,0,0.09)
}
return Qt.rgba(0,0,0,0)
return Qt.rgba(0,0,0,0.06)
}
}
}
ColumnLayout{
Image {
Layout.topMargin: 20

214
example/qml/page/T_Http.qml Normal file
View File

@ -0,0 +1,214 @@
import QtQuick
import Qt.labs.platform
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Dialogs
import FluentUI
import "qrc:///example/qml/component"
FluContentPage{
title:"Http"
FluHttp{
id:http
}
Flickable{
id:layout_flick
width: 160
clip: true
anchors{
top: parent.top
topMargin: 20
bottom: parent.bottom
left: parent.left
}
ScrollBar.vertical: FluScrollBar {}
contentHeight:layout_column.height
Column{
spacing: 2
id:layout_column
width: parent.width
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Get请求"
onClicked: {
var callable = {}
callable.onStart = function(){
showLoading()
}
callable.onFinish = function(){
hideLoading()
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString){
console.debug(status+";"+errorString)
}
http.get("https://httpbingo.org/get",callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Post表单请求"
onClicked: {
var callable = {}
callable.onStart = function(){
showLoading()
}
callable.onFinish = function(){
hideLoading()
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString){
console.debug(status+";"+errorString)
}
var param = {}
param.custname = "朱子楚"
param.custtel = "1234567890"
param.custemail = "zhuzichu520@gmail.com"
http.post("https://httpbingo.org/post",callable,param)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Post Json请求"
onClicked: {
var callable = {}
callable.onStart = function(){
showLoading()
}
callable.onFinish = function(){
hideLoading()
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString){
console.debug(status+";"+errorString)
}
var param = {}
param.custname = "朱子楚"
param.custtel = "1234567890"
param.custemail = "zhuzichu520@gmail.com"
http.postJson("https://httpbingo.org/post",callable,param)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Post String请求"
onClicked: {
var callable = {}
callable.onStart = function(){
showLoading()
}
callable.onFinish = function(){
hideLoading()
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString){
console.debug(status+";"+errorString)
}
var param = "我命由我不由天"
http.postString("https://httpbingo.org/post",callable,param)
}
}
FluButton{
id:btn_download
implicitWidth: parent.width
implicitHeight: 36
text: "下载文件"
onClicked: {
file_dialog.open()
}
}
}
}
FolderDialog {
id: file_dialog
currentFolder: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0]
onAccepted: {
var callable = {}
callable.onStart = function(){
btn_download.disabled = true
}
callable.onFinish = function(){
btn_download.disabled = false
btn_download.text = "下载文件"
layout_file_size.visible = false
text_file_size.text = ""
}
callable.onSuccess = function(result){
showSuccess(result)
}
callable.onError = function(status,errorString){
showError(errorString)
}
callable.onDownloadProgress = function(recv,total){
var locale = Qt.locale()
var precent = (recv/total * 100).toFixed(0) + "%"
btn_download.text = "下载中..."+precent
text_file_size.text = "%1/%2".arg(locale.formattedDataSize(recv)).arg(locale.formattedDataSize(total))
layout_file_size.visible = true
}
var path = FluTools.toLocalPath(currentFolder)+ "/big_buck_bunny.mp4"
http.download("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4",callable,path)
}
}
FluArea{
anchors{
top: layout_flick.top
bottom: layout_flick.bottom
left: layout_flick.right
right: parent.right
leftMargin: 8
}
Flickable{
clip: true
id:scrollview
width: parent.width
height: parent.height
contentWidth: width
contentHeight: text_info.height
ScrollBar.vertical: FluScrollBar {}
FluText{
id:text_info
width: scrollview.width
wrapMode: Text.WrapAnywhere
padding: 14
}
}
}
FluRectangle{
id:layout_file_size
radius: [4,4,4,4]
height: 36
width: 160
visible: false
x:layout_flick.width
y: 173 - layout_flick.contentY
FluText{
id:text_file_size
anchors.centerIn: parent
}
}
}

View File

@ -0,0 +1,48 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Image"
FluArea{
Layout.fillWidth: true
height: 260
paddings: 10
Layout.topMargin: 20
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left:parent.left
}
FluImage{
width: 384
height: 240
source: "https://gitee.com/zhu-zichu/zhu-zichu/raw/74f075efe2f8d3c3bb7ba3c2259e403450e4050b/image/banner_4.jpg"
onStatusChanged:{
if(status === Image.Error){
showError("图片加载失败,请重新加载")
}
}
clickErrorListener: function(){
source = "https://gitee.com/zhu-zichu/zhu-zichu/raw/74f075efe2f8d3c3bb7ba3c2259e403450e4050b/image/banner_1.jpg"
}
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluImage{
width: 400
height: 300
source: "https://gitee.com/zhu-zichu/zhu-zichu/raw/74f075efe2f8d3c3bb7ba3c2259e403450e4050b/image/banner_1.jpg"
}'
}
}

View File

@ -3,7 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -12,7 +12,7 @@ FluScrollablePage{
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 200
height: 240
paddings: 10
ColumnLayout{
spacing: 14
@ -44,6 +44,12 @@ FluScrollablePage{
showSuccess("这是一个Success样式的InfoBar这是一个Success样式的InfoBar")
}
}
FluButton{
text:"Loading"
onClicked: {
showLoading()
}
}
}
}
CodeExpander{

View File

@ -1,62 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
FluScrollablePage{
title:"MediaPlayer"
onVisibleChanged: {
if(visible){
player.play()
}else{
player.pause()
}
}
FluArea{
Layout.fillWidth: true
height: 320
Layout.topMargin: 20
paddings: 10
ColumnLayout{
anchors{
verticalCenter: parent.verticalCenter
left:parent.left
}
FluMediaPlayer{
id:player
source:"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluMediaPlayer{
id:player
source:"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
}
'
}
FluArea{
Layout.fillWidth: true
height: 68
Layout.topMargin: 20
paddings: 10
FluButton{
text:"跳转到视频播放器窗口"
anchors.verticalCenter: parent.verticalCenter
onClicked:{
FluApp.navigate("/media",{source:"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"})
}
}
}
}

View File

@ -3,12 +3,42 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Menu"
FluMenu {
id:menu
title: qsTr("File")
Action { text: qsTr("New...")}
Action { text: qsTr("Open...") }
Action { text: qsTr("Save") }
FluMenuSeparator { }
Action {
text: qsTr("Quit")
onTriggered: {
showError("Quit")
}
}
Action {
text: qsTr("Disable")
enabled:false
onTriggered: {
showError("Disable")
}
}
FluMenuSeparator { }
Action { text: qsTr("Check");checkable: true;checked: true}
FluMenu{
title: "Save As..."
Action { text: qsTr("Doc") }
Action { text: qsTr("PDF") }
}
}
FluArea{
Layout.fillWidth: true
height: 100
@ -22,28 +52,19 @@ FluScrollablePage{
left:parent.left
}
FluText{
text:"Menu"
}
FluButton{
text:"左击菜单"
text:"Show Menu Popup"
Layout.topMargin: 20
onClicked:{
menu.popup()
}
}
FluButton{
text:"右击菜单"
Layout.topMargin: 20
onClicked: {
showSuccess("请按鼠标右击")
}
MouseArea{
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked: {
menu.popup()
}
}
}
}
}
@ -69,20 +90,78 @@ menu.popup()
'
}
FluArea{
Layout.fillWidth: true
height: 100
paddings: 10
Layout.topMargin: 20
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left:parent.left
}
FluText{
text:"MenuBar"
}
FluMenuBar {
id:menu_bar
FluMenu {
title: qsTr("File")
Action { text: qsTr("New...") }
Action { text: qsTr("Open...") }
Action { text: qsTr("Save") }
FluMenuSeparator { }
Action { text: qsTr("Quit") }
Action {
text: qsTr("Disable")
enabled:false
}
FluMenu{
id:menu
FluMenuItem{
text:"删除"
onClicked: {
showError("删除")
title: "Save As..."
Action { text: qsTr("Doc") }
Action { text: qsTr("PDF") }
}
}
FluMenuItem{
text:"修改"
onClicked: {
showInfo("修改")
FluMenu {
title: qsTr("Edit")
Action { text: qsTr("Cut") }
Action { text: qsTr("Copy") }
Action { text: qsTr("Paste") }
}
FluMenu {
title: qsTr("Help")
Action { text: qsTr("About") }
}
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluMenuBar{
id:menu
FluMenu:{
title:"File"
Action { text: qsTr("New...") }
}
FluMenu:{
title:"Edit"
Action { text: qsTr("Cut") }
Action { text: qsTr("Copy") }
Action { text: qsTr("Paste") }
}
}
menu.popup()
'
}
}

View File

@ -3,7 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -93,9 +93,9 @@ FluScrollablePage{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluWindow{
//launchMode: FluWindow.Standard
//launchMode: FluWindow.SingleTask
launchMode: FluWindow.SingleInstance
//launchMode: FluWindowType.Standard
//launchMode: FluWindowType.SingleTask
launchMode: FluWindowType.SingleInstance
}
'
}

View File

@ -0,0 +1,49 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import "qrc:///example/qml/component"
import FluentUI
FluScrollablePage{
title:"Pagination"
FluArea{
Layout.fillWidth: true
height: 200
paddings: 10
Layout.topMargin: 20
ColumnLayout{
spacing: 20
anchors.verticalCenter: parent.verticalCenter
FluPagination{
pageCurrent: 1
pageButtonCount: 5
itemCount: 5000
}
FluPagination{
pageCurrent: 2
itemCount: 5000
pageButtonCount: 7
}
FluPagination{
pageCurrent: 3
itemCount: 5000
pageButtonCount: 9
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluPagination{
pageCurrent: 1
itemCount: 1000
pageButtonCount: 9
}'
}
}

View File

@ -3,7 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -76,5 +76,4 @@ FluScrollablePage{
}
'
}
}

View File

@ -3,7 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -12,33 +12,22 @@ FluScrollablePage{
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 260
height: 130
paddings: 10
ColumnLayout{
spacing: 20
spacing: 10
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluText{
text: "indeterminate = true"
}
FluProgressBar{
}
FluProgressRing{
}
FluProgressBar{
id:progress_bar
indeterminate: false
}
FluProgressRing{
id:progress_ring
indeterminate: false
}
FluSlider{
value:50
onValueChanged:{
progress_bar.progress = value/100
progress_ring.progress = value/100
}
}
}
}
CodeExpander{
@ -47,20 +36,68 @@ FluScrollablePage{
code:'FluProgressBar{
}
FluProgressRing{
}
'
}
FluProgressBar{
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 286
paddings: 10
ColumnLayout{
spacing: 10
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluText{
text: "indeterminate = false"
}
FluProgressBar{
indeterminate: false
value:slider.value/100
Layout.topMargin: 10
}
FluProgressBar{
indeterminate: false
value:slider.value/100
progressVisible: true
Layout.topMargin: 10
}
FluProgressRing{
indeterminate: false
value: slider.value/100
Layout.topMargin: 10
}
FluProgressRing{
progressVisible: true
indeterminate: false
value: slider.value/100
}
FluSlider{
id:slider
Component.onCompleted: {
value = 50
}
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluProgressBar{
indeterminate: false
}
FluProgressRing{
indeterminate: false
}'
progressVisible: true
}
'
}
}

View File

@ -0,0 +1,75 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import Qt5Compat.GraphicalEffects
import "qrc:///example/qml/component"
FluScrollablePage{
title:"QRCode"
FluQRCode{
id:qrcode
Layout.topMargin: 20
size:slider_size.value
text:text_box.text
color:color_picker.colorValue
Layout.preferredWidth: size
Layout.preferredHeight: size
}
RowLayout{
spacing: 10
Layout.topMargin: 20
FluText{
text:"text:"
Layout.alignment: Qt.AlignVCenter
}
FluTextBox{
id:text_box
text:"会磨刀的小猪"
}
}
RowLayout{
spacing: 10
Layout.topMargin: 10
FluText{
text:"color:"
Layout.alignment: Qt.AlignVCenter
}
FluColorPicker{
id:color_picker
Component.onCompleted: {
setColor(Qt.rgba(0,0,0,1))
}
}
}
RowLayout{
spacing: 10
FluText{
text:"size:"
Layout.alignment: Qt.AlignVCenter
}
FluSlider{
id:slider_size
from:60
to:260
value: 120
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: 20
code:'FluQRCode{
color:"red"
text:"会磨刀的小猪"
size:100
}'
}
}

View File

@ -0,0 +1,101 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"RadioButton"
FluArea{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
Row{
spacing: 30
anchors.verticalCenter: parent.verticalCenter
FluRadioButton{
disabled: radio_button_switch.checked
}
FluRadioButton{
disabled: radio_button_switch.checked
text:"Right"
}
FluRadioButton{
disabled: radio_button_switch.checked
text:"Left"
textRight: false
}
}
FluToggleSwitch{
id:radio_button_switch
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
}
text:"Disabled"
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluRadioButton{
text:"Text"
}'
}
FluArea{
Layout.fillWidth: true
height: 100
paddings: 10
Layout.topMargin: 20
FluRadioButtons{
spacing: 8
anchors.verticalCenter: parent.verticalCenter
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluRadioButton{
disabled: radio_button_switch2.checked
text:"Radio Button_1"
}
FluRadioButton{
disabled: radio_button_switch2.checked
text:"Radio Button_2"
}
FluRadioButton{
disabled: radio_button_switch2.checked
text:"Radio Button_3"
}
}
FluToggleSwitch{
id:radio_button_switch2
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
}
text:"Disabled"
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluRadioButtons{
spacing: 8
FluRadioButton{
text:"Radio Button_1"
}
FluRadioButton{
text:"Radio Button_2"
}
FluRadioButton{
text:"Radio Button_3"
}
}'
}
}

View File

@ -3,38 +3,33 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
FluScrollablePage {
title:"RatingControl"
title: "RatingControl"
FluArea{
FluArea {
Layout.fillWidth: true
height: 100
paddings: 10
Layout.topMargin: 20
Column{
Column {
spacing: 10
anchors.verticalCenter: parent.verticalCenter
FluRatingControl{
FluRatingControl {}
FluRatingControl {
number: 10
}
FluRatingControl{
number:10
}
}
}
CodeExpander{
CodeExpander {
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluRatingControl{
code: 'FluRatingControl{
}'
}
}

View File

@ -3,7 +3,7 @@ import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -12,7 +12,7 @@ FluScrollablePage{
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 480
height: 460
paddings: 10
Column{

View File

@ -0,0 +1,14 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluPage{
launchMode: FluPageType.SingleTop
FluRemoteLoader{
anchors.fill: parent
source: "https://zhu-zichu.gitee.io/T_RemoteLoader.qml"
}
}

View File

@ -3,8 +3,8 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/global/"
import "../component"
import "qrc:///example/qml/global"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -13,11 +13,11 @@ FluScrollablePage{
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 136
height: 128
paddings: 10
ColumnLayout{
spacing: 10
spacing: 5
anchors{
top: parent.top
left: parent.left
@ -28,7 +28,7 @@ FluScrollablePage{
Layout.bottomMargin: 4
}
Repeater{
model: [{title:"System",mode:FluDarkMode.System},{title:"Light",mode:FluDarkMode.Light},{title:"Dark",mode:FluDarkMode.Dark}]
model: [{title:"System",mode:FluThemeType.System},{title:"Light",mode:FluThemeType.Light},{title:"Dark",mode:FluThemeType.Dark}]
delegate: FluRadioButton{
checked : FluTheme.darkMode === modelData.mode
text:modelData.title
@ -43,23 +43,22 @@ FluScrollablePage{
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 168
height: 160
paddings: 10
ColumnLayout{
spacing: 10
spacing: 5
anchors{
top: parent.top
left: parent.left
}
FluText{
text:lang.navigation_view_display_mode
font: FluTextStyle.BodyStrong
Layout.bottomMargin: 4
}
Repeater{
model: [{title:"Open",mode:FluNavigationView.Open},{title:"Compact",mode:FluNavigationView.Compact},{title:"Minimal",mode:FluNavigationView.Minimal},{title:"Auto",mode:FluNavigationView.Auto}]
model: [{title:"Open",mode:FluNavigationViewType.Open},{title:"Compact",mode:FluNavigationViewType.Compact},{title:"Minimal",mode:FluNavigationViewType.Minimal},{title:"Auto",mode:FluNavigationViewType.Auto}]
delegate: FluRadioButton{
checked : MainEvent.displayMode===modelData.mode
text:modelData.title

View File

@ -2,7 +2,7 @@ import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import "../component"
import "qrc:///example/qml/component"
import FluentUI
FluScrollablePage{
@ -15,7 +15,6 @@ FluScrollablePage{
paddings: 10
Layout.topMargin: 20
FluSlider{
value: 50
anchors.verticalCenter: parent.verticalCenter
}
}
@ -27,17 +26,14 @@ FluScrollablePage{
}'
}
FluArea{
Layout.fillWidth: true
height: 200
paddings: 10
Layout.topMargin: 20
FluSlider{
value: 50
vertical:true
orientation: Qt.Vertical
anchors.left: parent.left
anchors.leftMargin: 20
anchors.verticalCenter: parent.verticalCenter
}
}
@ -45,7 +41,7 @@ FluScrollablePage{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluSlider{
vertical:true
orientation: Qt.Vertical
value:50
}'
}

View File

@ -3,7 +3,7 @@ import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -21,36 +21,34 @@ FluScrollablePage{
id:btn_status_mode
Layout.preferredWidth: 140
text:"Loading"
items:[
FluMenuItem{
text:"Loading"
onClicked: {
btn_status_mode.text = text
status_view.statusMode = FluStatusView.Loading
status_view.statusMode = FluStatusViewType.Loading
}
}
},
FluMenuItem{
text:"Empty"
onClicked: {
btn_status_mode.text = text
status_view.statusMode = FluStatusView.Empty
status_view.statusMode = FluStatusViewType.Empty
}
}
},
FluMenuItem{
text:"Error"
onClicked: {
btn_status_mode.text = text
status_view.statusMode = FluStatusView.Error
status_view.statusMode = FluStatusViewType.Error
}
}
},
FluMenuItem{
text:"Success"
onClicked: {
btn_status_mode.text = text
status_view.statusMode = FluStatusView.Success
status_view.statusMode = FluStatusViewType.Success
}
}
]
}
}
}
@ -77,7 +75,7 @@ FluScrollablePage{
Layout.topMargin: -1
code:'FluStatusView{
anchors.fill: parent
statusMode: FluStatusView.Loading
statusMode: FluStatusViewType.Loading
Rectangle{
anchors.fill: parent
color:FluTheme.primaryColor.dark

View File

@ -3,7 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -40,57 +40,53 @@ FluScrollablePage{
id:btn_tab_width_behavior
Layout.preferredWidth: 140
text:"Equal"
items:[
FluMenuItem{
text:"Equal"
onClicked: {
btn_tab_width_behavior.text = text
tab_view.tabWidthBehavior = FluTabView.Equal
tab_view.tabWidthBehavior = FluTabViewType.Equal
}
}
},
FluMenuItem{
text:"SizeToContent"
onClicked: {
btn_tab_width_behavior.text = text
tab_view.tabWidthBehavior = FluTabView.SizeToContent
tab_view.tabWidthBehavior = FluTabViewType.SizeToContent
}
}
},
FluMenuItem{
text:"Compact"
onClicked: {
btn_tab_width_behavior.text = text
tab_view.tabWidthBehavior = FluTabView.Compact
tab_view.tabWidthBehavior = FluTabViewType.Compact
}
}
]
}
FluDropDownButton{
id:btn_close_button_visibility
text:"Always"
Layout.preferredWidth: 120
items:[
FluMenuItem{
text:"Nerver"
onClicked: {
btn_close_button_visibility.text = text
tab_view.closeButtonVisibility = FluTabView.Nerver
tab_view.closeButtonVisibility = FluTabViewType.Nerver
}
}
},
FluMenuItem{
text:"Always"
onClicked: {
btn_close_button_visibility.text = text
tab_view.closeButtonVisibility = FluTabView.Always
tab_view.closeButtonVisibility = FluTabViewType.Always
}
}
},
FluMenuItem{
text:"OnHover"
onClicked: {
btn_close_button_visibility.text = text
tab_view.closeButtonVisibility = FluTabView.OnHover
tab_view.closeButtonVisibility = FluTabViewType.OnHover
}
}
]
}
}
}

View File

@ -3,143 +3,175 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
FluContentPage{
title:"TableView"
Component.onCompleted: {
const columns = [
{
title: '姓名',
dataIndex: 'name',
width:100
},
{
title: '年龄',
dataIndex: 'age',
width:100
},
{
title: '住址',
dataIndex: 'address',
width:200
},
{
title: '别名',
dataIndex: 'nickname',
width:100
},
{
title: '操作',
dataIndex: 'action',
width:120
},
];
table_view.columns = columns
loadData(1,10)
}
FluTableView{
id:table_view
Layout.fillWidth: true
Layout.topMargin: 20
pageCurrent:1
pageCount:10
itemCount: 1000
onRequestPage:
(page,count)=> {
loadData(page,count)
}
loadData(1,1000)
}
Component{
id:com_action
Item{
Row{
RowLayout{
anchors.centerIn: parent
spacing: 10
FluButton{
text:"删除"
onClicked: {
table_view.closeEditor()
tableModel.removeRow(row)
}
}
FluFilledButton{
text:"编辑"
horizontalPadding: 6
onClicked:{
showSuccess(JSON.stringify(dataObject))
}
}
FluFilledButton{
text:"删除"
horizontalPadding: 6
onClicked:{
showError(JSON.stringify(dataObject))
onClicked: {
showSuccess(JSON.stringify(tableModel.getRow(row)))
}
}
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: 10
code:'FluTableView{
id:table_view
Layout.fillWidth: true
Layout.topMargin: 20
pageCurrent:1
pageCount:10
itemCount: 1000
onRequestPage:
(page,count)=> {
loadData(page,count)
}
Component.onCompleted: {
const columns = [
{
title: "姓名",
dataIndex: "name",
width:100
},
{
title: "年龄",
dataIndex: "age",
width:100
},
{
title: "住址",
dataIndex: "address",
width:200
},
{
title: "别名",
dataIndex: "nickname",
width:100
}
];
table_view.columns = columns
const dataSource = [
{
name: "孙悟空”,
age: 500,
address:"钟灵毓秀的花果山,如神仙仙境的水帘洞",
nickname:"齐天大圣"
}
];
table_view.dataSource = columns
}
}'
}
function loadData(page,count){
var numbers = [100, 300, 500, 1000];
function getRandomAge() {
var randomIndex = Math.floor(Math.random() * numbers.length);
return numbers[randomIndex];
}
var names = ["孙悟空", "猪八戒", "沙和尚", "唐僧","白骨夫人","金角大王","熊山君","黄风怪","银角大王"];
function getRandomName(){
var randomIndex = Math.floor(Math.random() * names.length);
return names[randomIndex];
}
var nicknames = ["复海大圣","混天大圣","移山大圣","通风大圣","驱神大圣","齐天大圣","平天大圣"]
function getRandomNickname(){
var randomIndex = Math.floor(Math.random() * nicknames.length);
return nicknames[randomIndex];
}
var addresses = ["傲来国界花果山水帘洞","傲来国界坎源山脏水洞","大唐国界黑风山黑风洞","大唐国界黄风岭黄风洞","大唐国界骷髅山白骨洞","宝象国界碗子山波月洞","宝象国界平顶山莲花洞","宝象国界压龙山压龙洞","乌鸡国界号山枯松涧火云洞","乌鸡国界衡阳峪黑水河河神府"]
function getRandomAddresses(){
var randomIndex = Math.floor(Math.random() * addresses.length);
return addresses[randomIndex];
}
const dataSource = []
for(var i=0;i<count;i++){
dataSource.push({
name: "孙悟空%1".arg(((page-1)*count+i)),
age: 500,
address: "钟灵毓秀的花果山,如神仙仙境的水帘洞",
nickname: "齐天大圣",
name: getRandomName(),
age:getRandomAge(),
address: getRandomAddresses(),
nickname: getRandomNickname(),
longstring:"你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好",
height:42,
minimumHeight:42,
maximumHeight:300,
action:com_action
})
}
table_view.dataSource = dataSource
}
Component{
id:com_combobox
FluComboBox {
anchors.fill: parent
focus: true
currentIndex: display
editable: true
model: ListModel {
ListElement { text: 100 }
ListElement { text: 300 }
ListElement { text: 500 }
ListElement { text: 1000 }
}
Component.onCompleted: {
currentIndex=[100,300,500,1000].findIndex((element) => element === Number(display))
selectAll()
}
onCommit: {
display = editText
tableView.closeEditor()
}
}
}
FluTableView{
id:table_view
anchors{
left: parent.left
right: parent.right
top: parent.top
bottom: gagination.top
}
anchors.topMargin: 20
columnSource:[
{
title: '姓名',
dataIndex: 'name',
width:100,
minimumWidth:80,
maximumWidth:200,
readOnly:true
},
{
title: '年龄',
dataIndex: 'age',
editDelegate:com_combobox,
width:100,
minimumWidth:100,
maximumWidth:100
},
{
title: '住址',
dataIndex: 'address',
width:200,
minimumWidth:100,
maximumWidth:250
},
{
title: '别名',
dataIndex: 'nickname',
width:100,
minimumWidth:80,
maximumWidth:200
},
{
title: '长字符串',
dataIndex: 'longstring',
width:200,
minimumWidth:100,
maximumWidth:300
},
{
title: '操作',
dataIndex: 'action',
width:160,
minimumWidth:160,
maximumWidth:160
}
]
}
FluPagination{
id:gagination
anchors{
bottom: parent.bottom
left: parent.left
}
pageCurrent: 1
itemCount: 100000
pageButtonCount: 7
__itemPerPage: 1000
onRequestPage:
(page,count)=> {
table_view.closeEditor()
loadData(page,count)
table_view.resetPosition()
}
}
}

View File

@ -3,7 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{

View File

@ -3,12 +3,13 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
title:"TextBox"
launchMode: FluPageType.SingleInstance
title:"TextBox"
FluArea{
Layout.fillWidth: true
height: 68
@ -16,29 +17,24 @@ FluScrollablePage{
Layout.topMargin: 20
FluTextBox{
Layout.topMargin: 20
placeholderText: "单行输入框"
Layout.preferredWidth: 300
disabled:text_box_switch.checked
cleanEnabled: true
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
}
Row{
spacing: 5
FluToggleSwitch{
id:text_box_switch
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
}
FluToggleSwitch{
id:text_box_switch
Layout.alignment: Qt.AlignRight
text:"Disabled"
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
@ -54,29 +50,22 @@ FluScrollablePage{
Layout.topMargin: 20
FluPasswordBox{
Layout.topMargin: 20
placeholderText: "请输入密码"
Layout.preferredWidth: 300
disabled:password_box_switch.checked
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
}
Row{
spacing: 5
FluToggleSwitch{
id:password_box_switch
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
}
FluToggleSwitch{
id:password_box_switch
Layout.alignment: Qt.AlignRight
text:"Disabled"
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
@ -94,9 +83,7 @@ FluScrollablePage{
FluMultilineTextBox{
id:multiine_textbox
Layout.topMargin: 20
placeholderText: "多行输入框"
Layout.preferredWidth: 300
disabled:text_box_multi_switch.checked
anchors{
verticalCenter: parent.verticalCenter
@ -104,19 +91,15 @@ FluScrollablePage{
}
}
Row{
spacing: 5
FluToggleSwitch{
id:text_box_multi_switch
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
}
FluToggleSwitch{
id:text_box_multi_switch
Layout.alignment: Qt.AlignRight
text:"Disabled"
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
@ -125,17 +108,13 @@ FluScrollablePage{
}'
}
FluArea{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
FluAutoSuggestBox{
Layout.topMargin: 20
placeholderText: "AutoSuggestBox"
Layout.preferredWidth: 300
items:generateRandomNames(100)
disabled:text_box_suggest_switch.checked
anchors{
@ -143,20 +122,15 @@ FluScrollablePage{
left: parent.left
}
}
Row{
spacing: 5
FluToggleSwitch{
id:text_box_suggest_switch
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
}
FluToggleSwitch{
id:text_box_suggest_switch
Layout.alignment: Qt.AlignRight
text:"Disabled"
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
@ -165,6 +139,34 @@ FluScrollablePage{
}'
}
FluArea{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
FluSpinBox{
disabled: spin_box_switch.checked
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
}
FluToggleSwitch{
id:spin_box_switch
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
}
text:"Disabled"
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluSpinBox{
}'
}
function generateRandomNames(numNames) {
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

View File

@ -3,7 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -12,7 +12,7 @@ FluScrollablePage{
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 210
height: 270
paddings: 10
ColumnLayout{
spacing:0
@ -55,9 +55,9 @@ FluScrollablePage{
checked: FluTheme.dark
onClicked: {
if(FluTheme.dark){
FluTheme.darkMode = FluDarkMode.Light
FluTheme.darkMode = FluThemeType.Light
}else{
FluTheme.darkMode = FluDarkMode.Dark
FluTheme.darkMode = FluThemeType.Dark
}
}
}
@ -72,6 +72,17 @@ FluScrollablePage{
FluTheme.nativeText = !FluTheme.nativeText
}
}
FluText{
text:"开启动画效果"
Layout.topMargin: 20
}
FluToggleSwitch{
Layout.topMargin: 5
checked: FluTheme.enableAnimation
onClicked: {
FluTheme.enableAnimation = !FluTheme.enableAnimation
}
}
}
}
CodeExpander{

View File

@ -3,12 +3,12 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
title:"TimePicker"
launchMode: FluPageType.SingleInstance
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
@ -23,10 +23,13 @@ FluScrollablePage{
}
FluText{
text:"hourFormat=FluTimePicker.H"
text:"hourFormat=FluTimePickerType.H"
}
FluTimePicker{
onCurrentChanged: {
showSuccess(current.toLocaleTimeString(Qt.locale("de_DE")))
}
}
}
@ -53,11 +56,14 @@ FluScrollablePage{
}
FluText{
text:"hourFormat=FluTimePicker.H"
text:"hourFormat=FluTimePickerType.HH"
}
FluTimePicker{
hourFormat:FluTimePicker.HH
hourFormat:FluTimePickerType.HH
onCurrentChanged: {
showSuccess(current.toLocaleTimeString(Qt.locale("de_DE")))
}
}
}
@ -66,7 +72,7 @@ FluScrollablePage{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluTimePicker{
hourFormat:FluTimePicker.HH
hourFormat:FluTimePickerType.HH
}'
}

View File

@ -0,0 +1,157 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Timeline"
Component{
id:com_dot
Rectangle{
width: 16
height: 16
radius: 8
border.width: 4
border.color: FluColors.Red.dark
}
}
Component{
id:com_lable
FluText{
wrapMode: Text.WrapAnywhere
horizontalAlignment: textAlignment
text: modelData.lable
color: FluTheme.primaryColor.dark
MouseArea{
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
showSuccess(modelData.lable)
}
}
}
}
Component{
id:com_text
FluText{
wrapMode: Text.WrapAnywhere
horizontalAlignment: textAlignment
text: modelData.text
font.bold: true
MouseArea{
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
showSuccess(modelData.text)
}
}
}
}
ListModel{
id:list_model
ListElement{
lable:"2013-09-01"
lableDelegate:()=>com_lable
textDelegate:()=>com_text
text:"考上家里蹲大学"
}
ListElement{
lable:"2017-07-01"
text:"大学毕业在寝室打了4年LOL没想到毕业还要找工作瞬间蒙蔽~害"
}
ListElement{
lable:"2017-09-01"
text:"开始找工作,毕业即失业!回农村老家躺平,继承三亩良田!!"
dot:()=>com_dot
}
ListElement{
lable:"2018-02-01"
text:"玩了一年没钱,惨,出去找工作上班"
}
ListElement{
lable:"2018-03-01"
text:"找到一份Android外包开发岗位开发了一个Android应用满满成就感前端、服务端、Flutter也都懂一丢丢什么都会什么都不精通钱途无望"
}
ListElement{
lable:"2020-06-01"
text:"由于某个项目紧急临时加入Qt项目组就因为大学学了点C++),本来是想进去打个酱油,到后面竟然成开发主力,坑啊"
}
ListElement{
lable:"2022-08-01"
text:"额,被老板卖到甲方公司,走时老板还问我想不想去,我说:'哪里工资高就去哪里?',老板:'无语'"
}
ListElement{
lable:"2023-02-28"
text:"开发FluentUI组件库"
}
}
RowLayout{
spacing: 20
Layout.topMargin: 20
FluTextBox{
id:text_box
text:"Technical testing 2015-09-01"
}
FluFilledButton{
text:"Append"
onClicked: {
list_model.append({text:text_box.text})
}
}
FluFilledButton{
text:"clear"
onClicked: {
list_model.clear()
}
}
}
RowLayout{
Layout.topMargin: 10
FluText{
text:"mode:"
}
FluDropDownButton{
id:btn_mode
Layout.preferredWidth: 100
text:"Alternate"
FluMenuItem{
text:"Left"
onClicked: {
btn_mode.text = text
time_line.mode = FluTimelineType.Left
}
}
FluMenuItem{
text:"Right"
onClicked: {
btn_mode.text = text
time_line.mode = FluTimelineType.Right
}
}
FluMenuItem{
text:"Alternate"
onClicked: {
btn_mode.text = text
time_line.mode = FluTimelineType.Alternate
}
}
}
}
FluTimeline{
id:time_line
Layout.fillWidth: true
mode: FluTimelineType.Alternate
model:list_model
}
}

View File

@ -3,7 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
@ -22,6 +22,12 @@ FluScrollablePage{
}
FluToggleSwitch{
disabled: toggle_switch.checked
text:"Right"
}
FluToggleSwitch{
disabled: toggle_switch.checked
text:"Left"
textRight: false
}
}
FluToggleSwitch{

View File

@ -3,7 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{

View File

@ -0,0 +1,80 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Tour"
FluTour{
id:tour
steps:[
{title:"Upload File",description: "Put your files here.",target:()=>btn_upload},
{title:"Save",description: "Save your changes.",target:()=>btn_save},
{title:"Other Actions",description: "Click to see other actions.",target:()=>btn_more}
]
}
FluArea{
Layout.fillWidth: true
height: 130
paddings: 10
Layout.topMargin: 20
FluFilledButton{
anchors{
top: parent.top
topMargin: 14
}
text:"Begin Tour"
onClicked: {
tour.open()
}
}
Row{
spacing: 20
anchors{
top: parent.top
topMargin: 60
}
FluButton{
id:btn_upload
text:"Upload"
onClicked: {
showInfo("Upload")
}
}
FluFilledButton{
id:btn_save
text:"Save"
onClicked: {
showInfo("Save")
}
}
FluIconButton{
id:btn_more
iconSource: FluentIcons.More
onClicked: {
showInfo("More")
}
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluTour{
id:tour
steps:[
{title:"Upload File",description: "Put your files here.",target:()=>btn_upload},
{title:"Save",description: "Save your changes.",target:()=>btn_save},
{title:"Other Actions",description: "Click to see other actions.",target:()=>btn_more}
]
}'
}
}

View File

@ -3,7 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage {
@ -60,44 +60,42 @@ FluScrollablePage {
id:btn_selection_model
Layout.preferredWidth: 140
text:"None"
items:[
FluMenuItem{
text:"None"
onClicked: {
btn_selection_model.text = text
tree_view.selectionMode = FluTabView.Equal
tree_view.selectionMode = FluTabViewType.Equal
}
}
},
FluMenuItem{
text:"Single"
onClicked: {
btn_selection_model.text = text
tree_view.selectionMode = FluTabView.SizeToContent
tree_view.selectionMode = FluTabViewType.SizeToContent
}
}
},
FluMenuItem{
text:"Muiltple"
onClicked: {
btn_selection_model.text = text
tree_view.selectionMode = FluTabView.Compact
tree_view.selectionMode = FluTabViewType.Compact
}
}
]
}
FluFilledButton{
text:"获取选中的数据"
onClicked: {
if(tree_view.selectionMode === FluTreeView.None){
if(tree_view.selectionMode === FluTreeViewType.None){
showError("当前非选择模式,没有选中的数据")
}
if(tree_view.selectionMode === FluTreeView.Single){
if(tree_view.selectionMode === FluTreeViewType.Single){
if(!tree_view.signleData()){
showError("没有选中数据")
return
}
showSuccess(tree_view.signleData().text)
}
if(tree_view.selectionMode === FluTreeView.Multiple){
if(tree_view.selectionMode === FluTreeViewType.Multiple){
if(tree_view.multipData().length===0){
showError("没有选中数据")
return

View File

@ -10,10 +10,6 @@ FluContentPage {
title: "Typography"
rightPadding: 10
Component.onCompleted: {
slider.seek(0)
}
FluArea{
anchors{
top:parent.top
@ -73,7 +69,7 @@ FluContentPage {
FluSlider{
id:slider
vertical:true
orientation: Qt.Vertical
anchors{
right: parent.right
rightMargin: 45

View File

@ -0,0 +1,132 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "qrc:///example/qml/component"
FluContentPage{
title:"Watermark"
FluArea{
anchors.fill: parent
anchors.topMargin: 20
ColumnLayout{
anchors{
left: parent.left
leftMargin: 14
}
RowLayout{
spacing: 10
Layout.topMargin: 14
FluText{
text:"text:"
Layout.alignment: Qt.AlignVCenter
}
FluTextBox{
id:text_box
text:"会磨刀的小猪"
}
}
RowLayout{
spacing: 10
FluText{
text:"textSize:"
Layout.alignment: Qt.AlignVCenter
}
FluSlider{
id:slider_text_size
value: 20
from: 13
to:50
}
}
RowLayout{
spacing: 10
FluText{
text:"gapX:"
Layout.alignment: Qt.AlignVCenter
}
FluSlider{
id:slider_gap_x
value: 100
}
}
RowLayout{
spacing: 10
FluText{
text:"gapY:"
Layout.alignment: Qt.AlignVCenter
}
FluSlider{
id:slider_gap_y
value: 100
}
}
RowLayout{
spacing: 10
FluText{
text:"offsetX:"
Layout.alignment: Qt.AlignVCenter
}
FluSlider{
id:slider_offset_x
value: 50
}
}
RowLayout{
spacing: 10
FluText{
text:"offsetY:"
Layout.alignment: Qt.AlignVCenter
}
FluSlider{
id:slider_offset_y
value: 50
}
}
RowLayout{
spacing: 10
FluText{
text:"rotate:"
Layout.alignment: Qt.AlignVCenter
}
FluSlider{
id:slider_rotate
value: 22
from: 0
to:360
}
}
RowLayout{
spacing: 10
FluText{
text:"textColor:"
Layout.alignment: Qt.AlignVCenter
}
FluColorPicker{
id:color_picker
Component.onCompleted: {
setColor(Qt.rgba(0,0,0,0.1))
}
}
}
}
FluWatermark{
id:water_mark
anchors.fill: parent
text:text_box.text
textColor: color_picker.colorValue
textSize: slider_text_size.value
rotate: slider_rotate.value
gap:Qt.point(slider_gap_x.value,slider_gap_y.value)
offset: Qt.point(slider_offset_x.value,slider_offset_y.value)
}
}
}

View File

@ -2,7 +2,7 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
import "../component"
import "qrc:///example/qml/component"
CustomWindow {
@ -11,7 +11,7 @@ CustomWindow {
width: 600
height: 600
fixSize: true
launchMode: FluWindow.SingleTask
launchMode: FluWindowType.SingleTask
ColumnLayout{
anchors{

View File

@ -0,0 +1,85 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
import example
import "qrc:///example/qml/component"
CustomWindow {
id:window
title:"热加载"
width: 800
height: 600
minimumWidth: 520
minimumHeight: 200
launchMode: FluWindowType.SingleTask
FileWatcher{
id:watcher
onFileChanged: {
loader.reload()
}
}
FluArea{
anchors.fill: parent
FluRemoteLoader{
id:loader
anchors.fill: parent
statusMode: FluStatusViewType.Success
lazy: true
errorItem: Item{
FluText{
text:loader.itemLodaer().sourceComponent.errorString()
color:"red"
anchors.fill: parent
wrapMode: Text.WrapAnywhere
padding: 20
verticalAlignment: Qt.AlignVCenter
horizontalAlignment: Qt.AlignHCenter
}
}
}
FluText{
text:"拖入qml文件"
font.pixelSize: 26
anchors.centerIn: parent
visible: !loader.itemLodaer().item && loader.statusMode === FluStatusViewType.Success
}
Rectangle{
radius: 4
anchors.fill: parent
color: "#33333333"
visible: drop_area.containsDrag
}
DropArea{
id:drop_area
anchors.fill: parent
onEntered:
(event)=>{
if(!event.hasUrls){
event.accepted = false
return
}
if (event.urls.length !== 1) {
event.accepted = false
return
}
var url = event.urls[0].toString()
var fileExtension = url.substring(url.lastIndexOf(".") + 1)
if (fileExtension !== "qml") {
event.accepted = false
return
}
return true
}
onDropped:
(event)=>{
var path = event.urls[0].toString()
loader.source = path
watcher.path = path
loader.reload()
}
}
}
}

View File

@ -2,7 +2,7 @@ import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import FluentUI
import "../component"
import "qrc:///example/qml/component"
CustomWindow {

View File

@ -4,8 +4,9 @@ import QtQuick.Controls
import QtQuick.Layouts
import Qt.labs.platform
import FluentUI
import "../component"
import "qrc:///example/qml/global/"
import example
import "qrc:///example/qml/component"
import "qrc:///example/qml/global"
CustomWindow {
@ -15,22 +16,18 @@ CustomWindow {
height: 640
closeDestory:false
minimumWidth: 520
minimumHeight: 460
minimumHeight: 200
appBarVisible: false
launchMode: FluWindow.SingleTask
launchMode: FluWindowType.SingleTask
closeFunc:function(event){
close_app.open()
dialog_close.open()
event.accepted = false
}
Connections{
target: appInfo
function onActiveWindow(){
window.show()
window.raise()
window.requestActivate()
}
Component.onCompleted: {
FluTools.setQuitOnLastWindowClosed(false)
tour.open()
}
SystemTrayIcon {
@ -58,26 +55,47 @@ CustomWindow {
}
FluContentDialog{
id:close_app
id:dialog_close
title:"退出"
message:"确定要退出程序吗?"
negativeText:"最小化"
buttonFlags: FluContentDialog.NeutralButton | FluContentDialog.NegativeButton | FluContentDialog.PositiveButton
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.NeutralButton | FluContentDialogType.PositiveButton
onNegativeClicked:{
window.hide()
system_tray.showMessage("友情提示","FluentUI已隐藏至托盘,点击托盘可再次激活窗口");
}
positiveText:"退出"
neutralText:"取消"
blurSource: nav_view
onPositiveClicked:{
window.deleteWindow()
FluApp.closeApp()
}
}
Flipable{
id:flipable
anchors.fill: parent
property bool flipped: false
property real flipAngle: 0
transform: Rotation {
id: rotation
origin.x: flipable.width/2
origin.y: flipable.height/2
axis { x: 0; y: 1; z: 0 }
angle: flipable.flipAngle
}
states: State {
PropertyChanges { target: flipable; flipAngle: 180 }
when: flipable.flipped
}
transitions: Transition {
NumberAnimation { target: flipable; property: "flipAngle"; duration: 1000 ; easing.type: Easing.OutCubic}
}
back: Item{
anchors.fill: flipable
visible: flipable.flipAngle !== 0
FluAppBar {
id: title_bar
anchors {
top: parent.top
left: parent.left
@ -86,23 +104,85 @@ CustomWindow {
darkText: lang.dark_mode
showDark: true
z:7
darkClickListener:(button)=>handleDarkChanged(button)
}
FluNavigationView{
id:nav_view
Row{
z:8
anchors{
top: parent.top
left: parent.left
right: parent.right
bottom: parent.bottom
topMargin: FluTools.isMacos() ? 20 : 5
leftMargin: 5
}
FluIconButton{
iconSource: FluentIcons.ChromeBack
width: 30
height: 30
iconSize: 13
onClicked: {
flipable.flipped = false
}
}
FluIconButton{
iconSource: FluentIcons.Sync
width: 30
height: 30
iconSize: 13
onClicked: {
loader.reload()
}
}
}
FluRemoteLoader{
id:loader
lazy: true
anchors.fill: parent
// source: "http://localhost:9000/RemoteComponent.qml"
source: "https://zhu-zichu.gitee.io/RemoteComponent.qml"
}
}
front: Item{
id:page_front
visible: flipable.flipAngle !== 180
anchors.fill: flipable
FluAppBar {
id:app_bar_front
anchors {
top: parent.top
left: parent.left
right: parent.right
}
darkText: lang.dark_mode
showDark: true
darkClickListener:(button)=>handleDarkChanged(button)
z:7
}
FluNavigationView{
property int clickCount: 0
id:nav_view
width: parent.width
height: parent.height
z:999
//Stack模式每次切换都会将页面压入栈中随着栈的页面增多消耗的内存也越多内存消耗多就会卡顿这时候就需要按返回将页面pop掉释放内存。该模式可以配合FluPage中的launchMode属性设置页面的启动模式
pageMode: FluNavigationViewType.Stack
//NoStack模式每次切换都会销毁之前的页面然后创建一个新的页面只需消耗少量内存推荐
// pageMode: FluNavigationViewType.NoStack
items: ItemsOriginal
footerItems:ItemsFooter
topPadding:FluTools.isMacos() ? 20 : 5
displayMode:MainEvent.displayMode
logo: "qrc:/example/res/image/favicon.ico"
title:"FluentUI"
onLogoClicked:{
clickCount += 1
showSuccess("点击%1次".arg(clickCount))
if(clickCount === 5){
loader.reload()
flipable.flipped = true
clickCount = 0
}
}
autoSuggestBox:FluAutoSuggestBox{
width: 280
anchors.centerIn: parent
@ -117,7 +197,84 @@ CustomWindow {
Component.onCompleted: {
ItemsOriginal.navigationView = nav_view
ItemsFooter.navigationView = nav_view
nav_view.setCurrentIndex(0)
setCurrentIndex(0)
}
}
}
}
Component{
id:com_reveal
CircularReveal{
id:reveal
target:window.contentItem
anchors.fill: parent
onAnimationFinished:{
//动画结束后释放资源
loader_reveal.sourceComponent = undefined
}
onImageChanged: {
changeDark()
}
}
}
Loader{
id:loader_reveal
anchors.fill: parent
}
function distance(x1,y1,x2,y2){
return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
}
function handleDarkChanged(button){
if(FluTools.isMacos() || !FluTheme.enableAnimation){
changeDark()
}else{
loader_reveal.sourceComponent = com_reveal
var target = window.contentItem
var pos = button.mapToItem(target,0,0)
var mouseX = pos.x
var mouseY = pos.y
var radius = Math.max(distance(mouseX,mouseY,0,0),distance(mouseX,mouseY,target.width,0),distance(mouseX,mouseY,0,target.height),distance(mouseX,mouseY,target.width,target.height))
var reveal = loader_reveal.item
reveal.start(reveal.width*Screen.devicePixelRatio,reveal.height*Screen.devicePixelRatio,Qt.point(mouseX,mouseY),radius)
}
}
function changeDark(){
if(FluTheme.dark){
FluTheme.darkMode = FluThemeType.Light
}else{
FluTheme.darkMode = FluThemeType.Dark
}
}
Shortcut {
sequence: "F5"
context: Qt.WindowShortcut
onActivated: {
if(flipable.flipped){
loader.reload()
}
}
}
Shortcut {
sequence: "F6"
context: Qt.WindowShortcut
onActivated: {
tour.open()
}
}
FluTour{
id:tour
steps:[
{title:"夜间模式",description: "这里可以切换夜间模式.",target:()=>app_bar_front.darkButton()},
{title:"隐藏彩蛋",description: "多点几下试试!!",target:()=>nav_view.logoButton()}
]
}
}

View File

@ -1,30 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
import "../component"
CustomWindow {
title:"视频播放器"
width: 640
height: 480
minimumWidth: 640
minimumHeight: 480
onInitArgument:
(argument)=>{
player.source = argument.source
}
FluMediaPlayer{
id:player
anchors{
left: parent.left
right: parent.right
top: parent.top
bottom: parent.bottom
}
}
}

View File

@ -2,7 +2,7 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
import "../component"
import "qrc:///example/qml/component"
CustomWindow {
@ -11,7 +11,7 @@ CustomWindow {
width: 500
height: 600
fixSize: true
launchMode: FluWindow.SingleInstance
launchMode: FluWindowType.SingleInstance
FluTextBox{
anchors{

View File

@ -2,7 +2,7 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
import "../component"
import "qrc:///example/qml/component"
CustomWindow {
@ -11,7 +11,7 @@ CustomWindow {
width: 500
height: 600
fixSize: true
launchMode: FluWindow.SingleTask
launchMode: FluWindowType.SingleTask
FluText{
anchors.centerIn: parent

View File

@ -2,7 +2,7 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
import "../component"
import "qrc:///example/qml/component"
CustomWindow {
@ -11,7 +11,29 @@ CustomWindow {
width: 500
height: 600
fixSize: true
launchMode: FluWindow.Standard
launchMode: FluWindowType.Standard
FluMenuBar {
FluMenu {
title: qsTr("File")
Action { text: qsTr("New...") }
Action { text: qsTr("Open...") }
Action { text: qsTr("Save") }
Action { text: qsTr("Save As...") }
FluMenuSeparator { }
Action { text: qsTr("Quit") }
}
FluMenu {
title: qsTr("Edit")
Action { text: qsTr("Cut") }
Action { text: qsTr("Copy") }
Action { text: qsTr("Paste") }
}
FluMenu {
title: qsTr("Help")
Action { text: qsTr("About") }
}
}
FluText{
anchors.centerIn: parent

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

View File

@ -4,16 +4,12 @@
#include <QDebug>
#include "lang/En.h"
#include "lang/Zh.h"
#define STR(x) #x
#define VER_JOIN(a,b,c,d) STR(a.b.c.d)
#define VER_JOIN_(x) VER_JOIN x
#define VER_STR VER_JOIN_((VERSION))
#include "Version.h"
AppInfo::AppInfo(QObject *parent)
: QObject{parent}
{
version(VER_STR);
version(APPLICATION_VERSION);
lang(new En());
}
@ -39,18 +35,3 @@ void AppInfo::changeLang(const QString& locale){
lang(new En());
}
}
bool AppInfo::isOwnerProcess(IPC *ipc){
QString activeWindowEvent = "activeWindow";
if(!ipc->isCurrentOwner()){
ipc->postEvent(activeWindowEvent,QString().toUtf8(),0);
return false;
}
if(ipc->isAttached()){
ipc->registerEventHandler(activeWindowEvent,[=](const QByteArray&){
Q_EMIT this->activeWindow();
return true;
});
}
return true;
}

View File

@ -3,7 +3,6 @@
#include <QObject>
#include <QQmlApplicationEngine>
#include "tool/IPC.h"
#include "lang/Lang.h"
#include "stdafx.h"
@ -15,9 +14,7 @@ class AppInfo : public QObject
public:
explicit AppInfo(QObject *parent = nullptr);
void init(QQmlApplicationEngine *engine);
bool isOwnerProcess(IPC *ipc);
Q_INVOKABLE void changeLang(const QString& locale);
Q_SIGNAL void activeWindow();
};
#endif // APPINFO_H

View File

@ -0,0 +1,48 @@
#include "CircularReveal.h"
#include <QGuiApplication>
#include <QQuickItemGrabResult>
#include <QPainterPath>
CircularReveal::CircularReveal(QQuickItem* parent) : QQuickPaintedItem(parent)
{
setVisible(false);
_anim.setDuration(333);
_anim.setEasingCurve(QEasingCurve::OutCubic);
connect(&_anim, &QPropertyAnimation::finished,this,[=](){
update();
setVisible(false);
Q_EMIT animationFinished();
});
connect(this,&CircularReveal::radiusChanged,this,[=](){
update();
});
}
void CircularReveal::paint(QPainter* painter)
{
painter->save();
painter->eraseRect(boundingRect());
painter->drawImage(QRect(0, 0, static_cast<int>(width()), static_cast<int>(height())), _source);
QPainterPath path;
path.moveTo(_center.x(),_center.y());
path.addEllipse(QPointF(_center.x(),_center.y()), _radius, _radius);
painter->setCompositionMode(QPainter::CompositionMode_Clear);
painter->fillPath(path, Qt::black);
painter->restore();
}
void CircularReveal::start(int w,int h,const QPoint& center,int radius){
_anim.setStartValue(0);
_anim.setEndValue(radius);
_center = center;
_grabResult = _target->grabToImage(QSize(w,h));
connect(_grabResult.data(), &QQuickItemGrabResult::ready, this, &CircularReveal::handleGrabResult);
}
void CircularReveal::handleGrabResult(){
_grabResult.data()->image().swap(_source);
update();
setVisible(true);
Q_EMIT imageChanged();
_anim.start();
}

View File

@ -0,0 +1,30 @@
#ifndef CIRCULARREVEAL_H
#define CIRCULARREVEAL_H
#include <QQuickItem>
#include <QQuickPaintedItem>
#include <QPainter>
#include <QPropertyAnimation>
#include "src/stdafx.h"
class CircularReveal : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY_AUTO(QQuickItem*,target)
Q_PROPERTY_AUTO(int,radius)
QML_NAMED_ELEMENT(CircularReveal)
public:
CircularReveal(QQuickItem* parent = nullptr);
void paint(QPainter* painter) override;
Q_INVOKABLE void start(int w,int h,const QPoint& center,int radius);
Q_SIGNAL void imageChanged();
Q_SIGNAL void animationFinished();
Q_SLOT void handleGrabResult();
private:
QImage _source;
QPropertyAnimation _anim = QPropertyAnimation(this, "radius", this);
QPoint _center;
QSharedPointer<QQuickItemGrabResult> _grabResult;
};
#endif // CIRCULARREVEAL_H

View File

@ -0,0 +1,24 @@
#include "FileWatcher.h"
FileWatcher::FileWatcher(QObject *parent)
: QObject{parent}
{
connect(&_watcher, &QFileSystemWatcher::fileChanged, this, [=](const QString &path){
Q_EMIT fileChanged();
clean();
_watcher.addPath(_path);
});
connect(this,&FileWatcher::pathChanged,this,[=](){
clean();
_watcher.addPath(_path.replace("file:///",""));
});
if(!_path.isEmpty()){
_watcher.addPath(_path);
}
}
void FileWatcher::clean(){
foreach (const QString &item, _watcher.files()) {
_watcher.removePath(item);
}
}

View File

@ -0,0 +1,23 @@
#ifndef FILEWATCHER_H
#define FILEWATCHER_H
#include <QObject>
#include <QFileSystemWatcher>
#include <QtQml/qqml.h>
#include "src/stdafx.h"
class FileWatcher : public QObject
{
Q_OBJECT
Q_PROPERTY_AUTO(QString,path);
QML_NAMED_ELEMENT(FileWatcher)
public:
explicit FileWatcher(QObject *parent = nullptr);
Q_SIGNAL void fileChanged();
private:
void clean();
private:
QFileSystemWatcher _watcher;
};
#endif // FILEWATCHER_H

View File

@ -19,4 +19,5 @@ En::En(QObject *parent)
settings("Settings");
locale("Locale");
navigation_view_display_mode("NavigationView Display Mode");
other("Other");
}

View File

@ -22,6 +22,7 @@ class Lang : public QObject
Q_PROPERTY_AUTO(QString,settings);
Q_PROPERTY_AUTO(QString,navigation_view_display_mode);
Q_PROPERTY_AUTO(QString,locale);
Q_PROPERTY_AUTO(QString,other);
public:
explicit Lang(QObject *parent = nullptr);

View File

@ -19,4 +19,5 @@ Zh::Zh(QObject *parent)
settings("设置");
locale("语言环境");
navigation_view_display_mode("导航视图显示模式");
other("其他");
}

View File

@ -3,6 +3,8 @@
#include <QQmlContext>
#include <QDir>
#include <QQuickWindow>
#include <QNetworkProxy>
#include <QSslConfiguration>
#include <QProcess>
#include <FramelessHelper/Quick/framelessquickmodule.h>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
@ -10,7 +12,7 @@
FRAMELESSHELPER_USE_NAMESPACE
int main(int argc, char *argv[])
int main(int argc, char *argv[])
{
//将样式设置为Basic不然会导致组件显示异常
qputenv("QT_QUICK_CONTROLS_STYLE","Basic");
@ -19,24 +21,22 @@ int main(int argc, char *argv[])
QGuiApplication::setOrganizationDomain("https://zhuzichu520.github.io");
QGuiApplication::setApplicationName("FluentUI");
QGuiApplication app(argc, argv);
#ifdef Q_OS_WIN // 此设置仅在Windows下生效
FramelessConfig::instance()->set(Global::Option::ForceHideWindowFrameBorder);
#endif
FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
#ifdef Q_OS_WIN // 此设置仅在Windows下生效
FramelessConfig::instance()->set(Global::Option::ForceHideWindowFrameBorder);
#endif
#ifdef Q_OS_MACOS
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur,false);
#endif
AppInfo* appInfo = new AppInfo();
IPC ipc(0);
if(!appInfo->isOwnerProcess(&ipc)){
return 0;
}
app.setQuitOnLastWindowClosed(false);
QQmlApplicationEngine engine;
FramelessHelper::Quick::registerTypes(&engine);
#ifdef FLUENTUI_BUILD_STATIC_LIB
engine.addImportPath("qrc:/"); // 让静态资源可以被QML引擎搜索到
#endif
appInfo->init(&engine);
const QUrl url(QStringLiteral("qrc:/example/qml/App.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,

View File

@ -1,250 +0,0 @@
#include "IPC.h"
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include <ctime>
#include <random>
IPC::IPC(uint32_t profileId)
: profileId{profileId}
, globalMemory{"ipc-" IPC_PROTOCOL_VERSION}
{
qRegisterMetaType<IPCEventHandler>("IPCEventHandler");
timer.setInterval(EVENT_TIMER_MS);
timer.setSingleShot(true);
connect(&timer, &QTimer::timeout, this, &IPC::processEvents);
std::default_random_engine randEngine((std::random_device())());
std::uniform_int_distribution<uint64_t> distribution;
globalId = distribution(randEngine);
qDebug() << "Our global IPC ID is " << globalId;
if (globalMemory.create(sizeof(IPCMemory))) {
if (globalMemory.lock()) {
IPCMemory* mem = global();
memset(mem, 0, sizeof(IPCMemory));
mem->globalId = globalId;
mem->lastProcessed = time(nullptr);
globalMemory.unlock();
} else {
qWarning() << "Couldn't lock to take ownership";
}
} else if (globalMemory.attach()) {
qDebug() << "Attaching to the global shared memory";
} else {
qDebug() << "Failed to attach to the global shared memory, giving up. Error:"
<< globalMemory.error();
return;
}
processEvents();
}
IPC::~IPC()
{
if (!globalMemory.lock()) {
qWarning() << "Failed to lock in ~IPC";
return;
}
if (isCurrentOwnerNoLock()) {
global()->globalId = 0;
}
globalMemory.unlock();
}
time_t IPC::postEvent(const QString& name, const QByteArray& data, uint32_t dest)
{
QByteArray binName = name.toUtf8();
if (binName.length() > (int32_t)sizeof(IPCEvent::name)) {
return 0;
}
if (data.length() > (int32_t)sizeof(IPCEvent::data)) {
return 0;
}
if (!globalMemory.lock()) {
qDebug() << "Failed to lock in postEvent()";
return 0;
}
IPCEvent* evt = nullptr;
IPCMemory* mem = global();
time_t result = 0;
for (uint32_t i = 0; !evt && i < EVENT_QUEUE_SIZE; ++i) {
if (mem->events[i].posted == 0) {
evt = &mem->events[i];
}
}
if (evt) {
memset(evt, 0, sizeof(IPCEvent));
memcpy(evt->name, binName.constData(), binName.length());
memcpy(evt->data, data.constData(), data.length());
mem->lastEvent = evt->posted = result = qMax(mem->lastEvent + 1, time(nullptr));
evt->dest = dest;
evt->sender = qApp->applicationPid();
qDebug() << "postEvent " << name << "to" << dest;
}
globalMemory.unlock();
return result;
}
bool IPC::isCurrentOwner()
{
if (globalMemory.lock()) {
const bool isOwner = isCurrentOwnerNoLock();
globalMemory.unlock();
return isOwner;
} else {
qWarning() << "isCurrentOwner failed to lock, returning false";
return false;
}
}
void IPC::registerEventHandler(const QString& name, IPCEventHandler handler)
{
eventHandlers[name] = handler;
}
bool IPC::isEventAccepted(time_t time)
{
bool result = false;
if (!globalMemory.lock()) {
return result;
}
if (difftime(global()->lastProcessed, time) > 0) {
IPCMemory* mem = global();
for (uint32_t i = 0; i < EVENT_QUEUE_SIZE; ++i) {
if (mem->events[i].posted == time && mem->events[i].processed) {
result = mem->events[i].accepted;
break;
}
}
}
globalMemory.unlock();
return result;
}
bool IPC::waitUntilAccepted(time_t postTime, int32_t timeout /*=-1*/)
{
bool result = false;
time_t start = time(nullptr);
forever
{
result = isEventAccepted(postTime);
if (result || (timeout > 0 && difftime(time(nullptr), start) >= timeout)) {
break;
}
qApp->processEvents();
QThread::msleep(0);
}
return result;
}
bool IPC::isAttached() const
{
return globalMemory.isAttached();
}
void IPC::setProfileId(uint32_t profileId)
{
this->profileId = profileId;
}
IPC::IPCEvent* IPC::fetchEvent()
{
IPCMemory* mem = global();
for (uint32_t i = 0; i < EVENT_QUEUE_SIZE; ++i) {
IPCEvent* evt = &mem->events[i];
if ((evt->processed && difftime(time(nullptr), evt->processed) > EVENT_GC_TIMEOUT)
|| (!evt->processed && difftime(time(nullptr), evt->posted) > EVENT_GC_TIMEOUT)) {
memset(evt, 0, sizeof(IPCEvent));
}
if (evt->posted && !evt->processed && evt->sender != qApp->applicationPid()
&& (evt->dest == profileId || (evt->dest == 0 && isCurrentOwnerNoLock()))) {
return evt;
}
}
return nullptr;
}
bool IPC::runEventHandler(IPCEventHandler handler, const QByteArray& arg)
{
bool result = false;
if (QThread::currentThread() == qApp->thread()) {
result = handler(arg);
} else {
QMetaObject::invokeMethod(this, "runEventHandler", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(bool, result), Q_ARG(IPCEventHandler, handler),
Q_ARG(const QByteArray&, arg));
}
return result;
}
void IPC::processEvents()
{
if (!globalMemory.lock()) {
timer.start();
return;
}
IPCMemory* mem = global();
if (mem->globalId == globalId) {
mem->lastProcessed = time(nullptr);
} else {
if (difftime(time(nullptr), mem->lastProcessed) >= OWNERSHIP_TIMEOUT_S) {
qDebug() << "Previous owner timed out, taking ownership" << mem->globalId << "->"
<< globalId;
memset(mem, 0, sizeof(IPCMemory));
mem->globalId = globalId;
mem->lastProcessed = time(nullptr);
}
}
while (IPCEvent* evt = fetchEvent()) {
QString name = QString::fromUtf8(evt->name);
auto it = eventHandlers.find(name);
if (it != eventHandlers.end()) {
evt->accepted = runEventHandler(it.value(), evt->data);
qDebug() << "Processed event:" << name << "posted:" << evt->posted
<< "accepted:" << evt->accepted;
if (evt->dest == 0) {
if (evt->accepted) {
evt->processed = time(nullptr);
}
} else {
evt->processed = time(nullptr);
}
} else {
qDebug() << "Received event:" << name << "without handler";
qDebug() << "Available handlers:" << eventHandlers.keys();
}
}
globalMemory.unlock();
timer.start();
}
bool IPC::isCurrentOwnerNoLock()
{
const void* const data = globalMemory.data();
if (!data) {
qWarning() << "isCurrentOwnerNoLock failed to access the memory, returning false";
return false;
}
return (*static_cast<const uint64_t*>(data) == globalId);
}
IPC::IPCMemory* IPC::global()
{
return static_cast<IPCMemory*>(globalMemory.data());
}

View File

@ -1,75 +0,0 @@
#ifndef IPC_H
#define IPC_H
#include <QMap>
#include <QObject>
#include <QSharedMemory>
#include <QTimer>
#include <ctime>
#include <functional>
using IPCEventHandler = std::function<bool(const QByteArray&)>;
#define IPC_PROTOCOL_VERSION "1"
class IPC : public QObject
{
Q_OBJECT
protected:
static const int EVENT_TIMER_MS = 1000;
static const int EVENT_GC_TIMEOUT = 5;
static const int EVENT_QUEUE_SIZE = 32;
static const int OWNERSHIP_TIMEOUT_S = 5;
public:
IPC(uint32_t profileId);
~IPC();
struct IPCEvent
{
uint32_t dest;
int32_t sender;
char name[16];
char data[128];
time_t posted;
time_t processed;
uint32_t flags;
bool accepted;
bool global;
};
struct IPCMemory
{
uint64_t globalId;
time_t lastEvent;
time_t lastProcessed;
IPCEvent events[IPC::EVENT_QUEUE_SIZE];
};
time_t postEvent(const QString& name, const QByteArray& data = QByteArray(), uint32_t dest = 0);
bool isCurrentOwner();
void registerEventHandler(const QString& name, IPCEventHandler handler);
bool isEventAccepted(time_t time);
bool waitUntilAccepted(time_t time, int32_t timeout = -1);
bool isAttached() const;
public slots:
void setProfileId(uint32_t profileId);
private:
IPCMemory* global();
bool runEventHandler(IPCEventHandler handler, const QByteArray& arg);
IPCEvent* fetchEvent();
void processEvents();
bool isCurrentOwnerNoLock();
private:
QTimer timer;
uint64_t globalId;
uint32_t profileId;
QSharedMemory globalMemory;
QMap<QString, IPCEventHandler> eventHandlers;
};
#endif // IPC_H

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