mirror of
https://github.com/zhuzichu520/FluentUI.git
synced 2025-07-01 23:51:48 +08:00
Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
855305f197 | |||
6fe3081d23 | |||
b1a2266c5e | |||
048abb5dbd | |||
991ea383e7 | |||
73518fb831 | |||
312aebae73 | |||
3c349da98f | |||
dba7332d89 | |||
3fefb08140 | |||
1c69d5daab | |||
ec76240aed | |||
0a967ca47b | |||
8dbbf4e547 | |||
ebad24e809 | |||
b7acae1470 | |||
f8340bdf59 | |||
e4fb9989d0 | |||
9bd98c68e4 | |||
7cd9b7c6bc |
308
.cmake/GetGitRevisionDescription.cmake
Normal file
308
.cmake/GetGitRevisionDescription.cmake
Normal 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}")
|
43
.cmake/GetGitRevisionDescription.cmake.in
Normal file
43
.cmake/GetGitRevisionDescription.cmake.in
Normal 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
12
.cmake/Version.h.in
Normal 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
32
.cmake/version_dll.rc.in
Normal 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
34
.cmake/version_exe.rc.in
Normal 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"
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -31,9 +31,10 @@ target_wrapper.*
|
||||
# QtCreator CMake
|
||||
CMakeLists.txt.user*
|
||||
|
||||
src/build-preset/plugins.qmltypes
|
||||
bin
|
||||
.DS_Store
|
||||
build
|
||||
cmake-build-*
|
||||
.idea
|
||||
.idea
|
||||
|
||||
example/Version.h
|
5
.gitmodules
vendored
5
.gitmodules
vendored
@ -1,3 +1,6 @@
|
||||
[submodule "framelesshelper"]
|
||||
path = framelesshelper
|
||||
url = https://github.com/zhuzichu520/framelesshelper.git
|
||||
url = https://github.com/zhuzichu520/framelesshelper.git
|
||||
[submodule "zxing-cpp"]
|
||||
path = zxing-cpp
|
||||
url = https://github.com/zhuzichu520/zxing-cpp.git
|
@ -2,6 +2,10 @@ 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)
|
||||
@ -13,6 +17,7 @@ if(NOT FLUENTUI_QML_PLUGIN_DIRECTORY)
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(zxing-cpp)
|
||||
|
||||
if (FLUENTUI_BUILD_EXAMPLES)
|
||||
add_subdirectory(example)
|
||||
|
@ -26,9 +26,6 @@ endif()
|
||||
#获取文件路径分隔符(解决执行命令的时候有些平台会报错)
|
||||
file(TO_CMAKE_PATH "/" PATH_SEPARATOR)
|
||||
|
||||
#设置版本号
|
||||
add_definitions(-DVERSION=1,4,0,0)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Quick Svg Network)
|
||||
|
||||
if(QT_VERSION VERSION_GREATER_EQUAL "6.3")
|
||||
@ -39,6 +36,13 @@ else()
|
||||
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)
|
||||
foreach(filepath ${CPP_FILES})
|
||||
@ -60,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
|
||||
|
@ -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
|
@ -38,7 +38,7 @@ FluExpander{
|
||||
topMargin: 5
|
||||
}
|
||||
onClicked:{
|
||||
FluTools.clipText(content.text)
|
||||
FluTools.clipText(FluTools.html2PlantText(content.text))
|
||||
showSuccess("复制成功")
|
||||
}
|
||||
}
|
||||
@ -132,7 +132,11 @@ FluExpander{
|
||||
"FluImage",
|
||||
"FluSpinBox",
|
||||
"FluHttp",
|
||||
"FluWatermark"
|
||||
"FluWatermark",
|
||||
"FluTour",
|
||||
"FluQRCode",
|
||||
"FluTimeline",
|
||||
"FluChart"
|
||||
];
|
||||
code = code.replace(/\n/g, "<br>");
|
||||
code = code.replace(/ /g, " ");
|
||||
|
@ -41,7 +41,7 @@ FluWindow {
|
||||
setWindowFixedSize(fixSize)
|
||||
title_bar.maximizeButton.visible = !fixSize
|
||||
if (blurBehindWindowEnabled)
|
||||
window.backgroundVisible = false
|
||||
window.background = undefined
|
||||
window.show()
|
||||
}
|
||||
}
|
||||
|
@ -323,9 +323,38 @@ FluObject{
|
||||
}
|
||||
}
|
||||
|
||||
FluPaneItemSeparator{
|
||||
spacing:20
|
||||
size:1
|
||||
}
|
||||
|
||||
FluPaneItemExpander{
|
||||
title:lang.other
|
||||
icon:FluentIcons.Shop
|
||||
FluPaneItem{
|
||||
title:"QRCode"
|
||||
onTap:{
|
||||
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:{
|
||||
|
@ -9,6 +9,19 @@ 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"}]
|
||||
}
|
||||
}'
|
||||
}
|
||||
|
331
example/qml/page/T_Chart.qml
Normal file
331
example/qml/page/T_Chart.qml
Normal 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'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -77,6 +77,7 @@ FluScrollablePage{
|
||||
anchors.fill: parent
|
||||
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{
|
||||
@ -85,14 +86,14 @@ 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
75
example/qml/page/T_QRCode.qml
Normal file
75
example/qml/page/T_QRCode.qml
Normal 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
|
||||
}'
|
||||
}
|
||||
|
||||
}
|
157
example/qml/page/T_Timeline.qml
Normal file
157
example/qml/page/T_Timeline.qml
Normal 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
|
||||
}
|
||||
|
||||
}
|
80
example/qml/page/T_Tour.qml
Normal file
80
example/qml/page/T_Tour.qml
Normal 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}
|
||||
]
|
||||
}'
|
||||
}
|
||||
|
||||
}
|
@ -27,6 +27,7 @@ CustomWindow {
|
||||
|
||||
Component.onCompleted: {
|
||||
FluTools.setQuitOnLastWindowClosed(false)
|
||||
tour.open()
|
||||
}
|
||||
|
||||
SystemTrayIcon {
|
||||
@ -146,6 +147,7 @@ CustomWindow {
|
||||
visible: flipable.flipAngle !== 180
|
||||
anchors.fill: flipable
|
||||
FluAppBar {
|
||||
id:app_bar_front
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
@ -174,7 +176,8 @@ CustomWindow {
|
||||
title:"FluentUI"
|
||||
onLogoClicked:{
|
||||
clickCount += 1
|
||||
if(clickCount === 1){
|
||||
showSuccess("点击%1次".arg(clickCount))
|
||||
if(clickCount === 5){
|
||||
loader.reload()
|
||||
flipable.flipped = true
|
||||
clickCount = 0
|
||||
@ -258,4 +261,20 @@ CustomWindow {
|
||||
}
|
||||
}
|
||||
|
||||
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()}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -21,13 +21,13 @@ FRAMELESSHELPER_USE_NAMESPACE
|
||||
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
|
||||
|
@ -11,9 +11,6 @@ if(APPLE)
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
#设置版本号
|
||||
add_definitions(-DVERSION=1,4,0,0)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Quick Qml)
|
||||
|
||||
if(QT_VERSION VERSION_GREATER_EQUAL "6.3")
|
||||
@ -39,7 +36,7 @@ foreach(filepath ${QML_PATHS})
|
||||
endforeach(filepath)
|
||||
|
||||
#遍历所有资源文件
|
||||
file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp qmldir)
|
||||
file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp *.js qmldir)
|
||||
foreach(filepath ${RES_PATHS})
|
||||
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
|
||||
list(APPEND resource_files ${filename})
|
||||
@ -66,6 +63,16 @@ else()
|
||||
set(PLUGIN_TARGET_NAME ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
#如果是Windows平台,则生成rc文件
|
||||
set(FLUENTUI_VERSION_RC_PATH "")
|
||||
if(WIN32)
|
||||
set(FLUENTUI_VERSION_RC_PATH ${CMAKE_BINARY_DIR}/version_${PROJECT_NAME}.rc)
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/.cmake/version_dll.rc.in
|
||||
${FLUENTUI_VERSION_RC_PATH}
|
||||
)
|
||||
endif()
|
||||
|
||||
qt_add_qml_module(${PROJECT_NAME}
|
||||
PLUGIN_TARGET ${PLUGIN_TARGET_NAME}
|
||||
OUTPUT_DIRECTORY ${FLUENTUI_QML_PLUGIN_DIRECTORY}
|
||||
@ -73,7 +80,7 @@ qt_add_qml_module(${PROJECT_NAME}
|
||||
URI "FluentUI"
|
||||
#修改qmltypes文件名称。默认fluentuiplugin.qmltypes,使用默认名称有时候import FluentUI会爆红,所以修改成plugins.qmltypes
|
||||
TYPEINFO "plugins.qmltypes"
|
||||
SOURCES ${sources_files} fluentui.rc
|
||||
SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH}
|
||||
QML_FILES ${qml_files}
|
||||
RESOURCES ${resource_files}
|
||||
)
|
||||
@ -83,6 +90,7 @@ target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
Qt::CorePrivate
|
||||
Qt::QuickPrivate
|
||||
Qt::QmlPrivate
|
||||
ZXing
|
||||
)
|
||||
|
||||
#安装
|
||||
|
11
src/Def.h
11
src/Def.h
@ -15,6 +15,17 @@ Q_ENUM_NS(DarkMode)
|
||||
QML_NAMED_ELEMENT(FluThemeType)
|
||||
}
|
||||
|
||||
namespace FluTimelineType {
|
||||
Q_NAMESPACE
|
||||
enum Mode {
|
||||
Left = 0x0000,
|
||||
Right = 0x0001,
|
||||
Alternate = 0x0002,
|
||||
};
|
||||
Q_ENUM_NS(Mode)
|
||||
QML_NAMED_ELEMENT(FluTimelineType)
|
||||
}
|
||||
|
||||
namespace FluPageType {
|
||||
Q_NAMESPACE
|
||||
enum LaunchMode {
|
||||
|
@ -49,14 +49,14 @@ void FluApp::navigate(const QString& route,const QJsonObject& argument,FluRegist
|
||||
return;
|
||||
}
|
||||
QVariantMap properties;
|
||||
properties.insert("route",route);
|
||||
properties.insert("_route",route);
|
||||
if(fluRegister){
|
||||
properties.insert("pageRegister",QVariant::fromValue(fluRegister));
|
||||
properties.insert("_pageRegister",QVariant::fromValue(fluRegister));
|
||||
}
|
||||
properties.insert("argument",argument);
|
||||
QQuickWindow *view=nullptr;
|
||||
for (auto& pair : wnds) {
|
||||
QString r = pair->property("route").toString();
|
||||
QString r = pair->property("_route").toString();
|
||||
if(r == route){
|
||||
view = pair;
|
||||
break;
|
||||
|
@ -32,8 +32,8 @@ void FluHttp::handleReply(QNetworkReply* reply){
|
||||
_cache.append(reply);
|
||||
}
|
||||
|
||||
void FluHttp::post(QString url,QJSValue callable,QVariantMap params,QVariantMap headers){
|
||||
QVariantMap data = invokeIntercept(params,headers,"post").toMap();
|
||||
void FluHttp::post(QString url,QJSValue callable,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){
|
||||
QMap<QString, QVariant> data = invokeIntercept(params,headers,"post").toMap();
|
||||
QThreadPool::globalInstance()->start([=](){
|
||||
onStart(callable);
|
||||
for (int i = 0; i < retry(); ++i) {
|
||||
@ -82,8 +82,8 @@ void FluHttp::post(QString url,QJSValue callable,QVariantMap params,QVariantMap
|
||||
});
|
||||
}
|
||||
|
||||
void FluHttp::postString(QString url,QJSValue callable,QString params,QVariantMap headers){
|
||||
QVariantMap data = invokeIntercept(params,headers,"postString").toMap();
|
||||
void FluHttp::postString(QString url,QJSValue callable,QString params,QMap<QString, QVariant> headers){
|
||||
QMap<QString, QVariant> data = invokeIntercept(params,headers,"postString").toMap();
|
||||
QThreadPool::globalInstance()->start([=](){
|
||||
onStart(callable);
|
||||
for (int i = 0; i < retry(); ++i) {
|
||||
@ -121,8 +121,8 @@ void FluHttp::postString(QString url,QJSValue callable,QString params,QVariantMa
|
||||
});
|
||||
}
|
||||
|
||||
void FluHttp::postJson(QString url,QJSValue callable,QVariantMap params,QVariantMap headers){
|
||||
QVariantMap data = invokeIntercept(params,headers,"postJson").toMap();
|
||||
void FluHttp::postJson(QString url,QJSValue callable,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){
|
||||
QMap<QString, QVariant> data = invokeIntercept(params,headers,"postJson").toMap();
|
||||
QThreadPool::globalInstance()->start([=](){
|
||||
onStart(callable);
|
||||
for (int i = 0; i < retry(); ++i) {
|
||||
@ -160,8 +160,8 @@ void FluHttp::postJson(QString url,QJSValue callable,QVariantMap params,QVariant
|
||||
});
|
||||
}
|
||||
|
||||
void FluHttp::get(QString url,QJSValue callable,QVariantMap params,QVariantMap headers){
|
||||
QVariantMap data = invokeIntercept(params,headers,"get").toMap();
|
||||
void FluHttp::get(QString url,QJSValue callable,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){
|
||||
QMap<QString, QVariant> data = invokeIntercept(params,headers,"get").toMap();
|
||||
QThreadPool::globalInstance()->start([=](){
|
||||
for (int i = 0; i < retry(); ++i) {
|
||||
onStart(callable);
|
||||
@ -198,8 +198,8 @@ void FluHttp::get(QString url,QJSValue callable,QVariantMap params,QVariantMap h
|
||||
});
|
||||
}
|
||||
|
||||
void FluHttp::download(QString url,QJSValue callable,QString filePath,QVariantMap params,QVariantMap headers){
|
||||
QVariantMap data = invokeIntercept(params,headers,"download").toMap();
|
||||
void FluHttp::download(QString url,QJSValue callable,QString filePath,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){
|
||||
QMap<QString, QVariant> data = invokeIntercept(params,headers,"download").toMap();
|
||||
QThreadPool::globalInstance()->start([=](){
|
||||
onStart(callable);
|
||||
QNetworkAccessManager manager;
|
||||
@ -239,7 +239,7 @@ void FluHttp::download(QString url,QJSValue callable,QString filePath,QVariantMa
|
||||
}
|
||||
|
||||
QVariant FluHttp::invokeIntercept(const QVariant& params,const QVariant& headers,const QString& method){
|
||||
QVariantMap requet = {
|
||||
QMap<QString, QVariant> requet = {
|
||||
{"params",params},
|
||||
{"headers",headers},
|
||||
{"method",method}
|
||||
|
@ -26,11 +26,12 @@ private:
|
||||
public:
|
||||
explicit FluHttp(QObject *parent = nullptr);
|
||||
~FluHttp();
|
||||
Q_INVOKABLE void get(QString url,QJSValue callable,QVariantMap params = {},QVariantMap headers = {});
|
||||
Q_INVOKABLE void post(QString url,QJSValue callable,QVariantMap params = {},QVariantMap headers = {});
|
||||
Q_INVOKABLE void postString(QString url,QJSValue callable,QString params = "",QVariantMap headers = {});
|
||||
Q_INVOKABLE void postJson(QString url,QJSValue callable,QVariantMap params = {},QVariantMap headers = {});
|
||||
Q_INVOKABLE void download(QString url,QJSValue callable,QString filePath,QVariantMap params = {},QVariantMap headers = {});
|
||||
//神坑!!! 如果参数使用QVariantMap会有问题,在6.4.3版本中QML一调用就会编译失败。所以改用QMap<QString, QVariant>
|
||||
Q_INVOKABLE void get(QString url,QJSValue callable,QMap<QString, QVariant> = {},QMap<QString, QVariant> headers = {});
|
||||
Q_INVOKABLE void post(QString url,QJSValue callable,QMap<QString, QVariant> = {},QMap<QString, QVariant> headers = {});
|
||||
Q_INVOKABLE void postString(QString url,QJSValue callable,QString params = "",QMap<QString, QVariant> headers = {});
|
||||
Q_INVOKABLE void postJson(QString url,QJSValue callable,QMap<QString, QVariant> params = {},QMap<QString, QVariant> headers = {});
|
||||
Q_INVOKABLE void download(QString url,QJSValue callable,QString filePath,QMap<QString, QVariant> params = {},QMap<QString, QVariant> headers = {});
|
||||
Q_INVOKABLE void cancel();
|
||||
private:
|
||||
QList<QPointer<QNetworkReply>> _cache;
|
||||
|
53
src/FluQRCode.cpp
Normal file
53
src/FluQRCode.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include "FluQRCode.h"
|
||||
|
||||
#include "BarcodeFormat.h"
|
||||
#include "BitMatrix.h"
|
||||
#include "MultiFormatWriter.h"
|
||||
|
||||
using namespace ZXing;
|
||||
|
||||
FluQRCode::FluQRCode(QQuickItem* parent) : QQuickPaintedItem(parent)
|
||||
{
|
||||
color(QColor(0,0,0,255));
|
||||
size(100);
|
||||
setWidth(_size);
|
||||
setHeight(_size);
|
||||
connect(this,&FluQRCode::textChanged,this,[=]{update();});
|
||||
connect(this,&FluQRCode::colorChanged,this,[=]{update();});
|
||||
connect(this,&FluQRCode::sizeChanged,this,[=]{
|
||||
setWidth(_size);
|
||||
setHeight(_size);
|
||||
update();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void FluQRCode::paint(QPainter* painter)
|
||||
{
|
||||
if(_text.isEmpty()){
|
||||
return;
|
||||
}
|
||||
if(_text.length()>1108){
|
||||
return;
|
||||
}
|
||||
painter->save();
|
||||
painter->eraseRect(boundingRect());
|
||||
auto format = ZXing::BarcodeFormatFromString("QRCode");
|
||||
auto writer = MultiFormatWriter(format);
|
||||
writer.setMargin(0);
|
||||
writer.setEncoding(ZXing::CharacterSet::UTF8);
|
||||
auto matrix = writer.encode(_text.toUtf8().constData(), 0, 0);
|
||||
auto bitmap = ToMatrix<uint8_t>(matrix);
|
||||
auto image = QImage(bitmap.data(), bitmap.width(), bitmap.height(), bitmap.width(), QImage::Format::Format_Grayscale8).copy();
|
||||
QImage rgbImage = image.convertToFormat(QImage::Format_ARGB32);
|
||||
for (int y = 0; y < rgbImage.height(); ++y) {
|
||||
for (int x = 0; x < rgbImage.width(); ++x) {
|
||||
QRgb pixel = rgbImage.pixel(x, y);
|
||||
if (qRed(pixel) == 0 && qGreen(pixel) == 0 && qBlue(pixel) == 0) {
|
||||
rgbImage.setPixelColor(x, y, _color);
|
||||
}
|
||||
}
|
||||
}
|
||||
painter->drawImage(QRect(0, 0, static_cast<int>(width()), static_cast<int>(height())), rgbImage);
|
||||
painter->restore();
|
||||
}
|
22
src/FluQRCode.h
Normal file
22
src/FluQRCode.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef FLUQRCODE_H
|
||||
#define FLUQRCODE_H
|
||||
|
||||
#include <QQuickItem>
|
||||
#include <QQuickPaintedItem>
|
||||
#include <QPainter>
|
||||
#include "stdafx.h"
|
||||
|
||||
class FluQRCode : public QQuickPaintedItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(QString,text)
|
||||
Q_PROPERTY_AUTO(QColor,color)
|
||||
Q_PROPERTY_AUTO(int,size);
|
||||
QML_NAMED_ELEMENT(FluQRCode)
|
||||
public:
|
||||
explicit FluQRCode(QQuickItem *parent = nullptr);
|
||||
void paint(QPainter* painter) override;
|
||||
|
||||
};
|
||||
|
||||
#endif // FLUQRCODE_H
|
@ -3,6 +3,7 @@
|
||||
#include <QClipboard>
|
||||
#include <QUuid>
|
||||
#include <QCursor>
|
||||
#include <QTextDocument>
|
||||
|
||||
FluTools* FluTools::m_instance = nullptr;
|
||||
|
||||
@ -98,3 +99,9 @@ void FluTools::deleteItem(QObject *p){
|
||||
QString FluTools::toLocalPath(const QUrl& url){
|
||||
return url.toLocalFile();
|
||||
}
|
||||
|
||||
QString FluTools::html2PlantText(const QString& html){
|
||||
QTextDocument textDocument;
|
||||
textDocument.setHtml(html);
|
||||
return textDocument.toPlainText();
|
||||
}
|
||||
|
@ -90,6 +90,12 @@ public:
|
||||
*/
|
||||
Q_INVOKABLE void restoreOverrideCursor();
|
||||
|
||||
/**
|
||||
* @brief html2PlantText 将html转换成纯文本
|
||||
* @param html
|
||||
*/
|
||||
Q_INVOKABLE QString html2PlantText(const QString& html);
|
||||
|
||||
/**
|
||||
* @brief toLocalPath 获取文件路径,可以去掉windows系统下的file:///,macos下的file://
|
||||
* @param url
|
||||
|
@ -1,40 +0,0 @@
|
||||
#include <windows.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))
|
||||
|
||||
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", "FluentUI for QML."
|
||||
VALUE "CompanyName", "zhuzichu"
|
||||
VALUE "FileDescription", "fluentui"
|
||||
VALUE "FileVersion", VER_STR
|
||||
VALUE "InternalName", ""
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||
VALUE "OriginalFilename", ""
|
||||
VALUE "ProductName", "fluentui"
|
||||
VALUE "ProductVersion", VER_STR
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
@ -2,102 +2,170 @@ import QtQuick
|
||||
import QtQuick.Controls
|
||||
import FluentUI
|
||||
|
||||
Item {
|
||||
property bool flagXChanged: true
|
||||
property int radius : 5
|
||||
FluItem {
|
||||
property int loopTime: 2000
|
||||
property var model
|
||||
property Component delegate
|
||||
property bool showIndicator: true
|
||||
property int indicatorGravity : Qt.AlignBottom | Qt.AlignHCenter
|
||||
property int indicatorMarginLeft: 0
|
||||
property int indicatorMarginRight: 0
|
||||
property int indicatorMarginTop: 0
|
||||
property int indicatorMarginBottom: 20
|
||||
property int indicatorSpacing: 10
|
||||
property alias indicatorAnchors: layout_indicator.anchors
|
||||
property Component indicatorDelegate : com_indicator
|
||||
id:control
|
||||
width: 400
|
||||
height: 300
|
||||
ListModel{
|
||||
id:content_model
|
||||
}
|
||||
FluRectangle{
|
||||
anchors.fill: parent
|
||||
radius: [control.radius,control.radius,control.radius,control.radius]
|
||||
FluShadow{
|
||||
radius:control.radius
|
||||
QtObject{
|
||||
id:d
|
||||
property bool flagXChanged: true
|
||||
function setData(data){
|
||||
if(!data){
|
||||
return
|
||||
}
|
||||
content_model.clear()
|
||||
content_model.append(data[data.length-1])
|
||||
content_model.append(data)
|
||||
content_model.append(data[0])
|
||||
list_view.highlightMoveDuration = 0
|
||||
list_view.currentIndex = 1
|
||||
list_view.highlightMoveDuration = 250
|
||||
timer_run.restart()
|
||||
}
|
||||
ListView{
|
||||
id:list_view
|
||||
anchors.fill: parent
|
||||
snapMode: ListView.SnapOneItem
|
||||
clip: true
|
||||
boundsBehavior: ListView.StopAtBounds
|
||||
model:content_model
|
||||
maximumFlickVelocity: 4 * (list_view.orientation === Qt.Horizontal ? width : height)
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
orientation : ListView.Horizontal
|
||||
delegate: Item{
|
||||
width: ListView.view.width
|
||||
height: ListView.view.height
|
||||
property int displayIndex: {
|
||||
if(index === 0)
|
||||
return content_model.count-3
|
||||
if(index === content_model.count-1)
|
||||
return 0
|
||||
return index-1
|
||||
}
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: model.url
|
||||
asynchronous: true
|
||||
fillMode:Image.PreserveAspectCrop
|
||||
}
|
||||
}
|
||||
ListView{
|
||||
id:list_view
|
||||
anchors.fill: parent
|
||||
snapMode: ListView.SnapOneItem
|
||||
clip: true
|
||||
boundsBehavior: ListView.StopAtBounds
|
||||
model:content_model
|
||||
maximumFlickVelocity: 4 * (list_view.orientation === Qt.Horizontal ? width : height)
|
||||
preferredHighlightBegin: 0
|
||||
preferredHighlightEnd: 0
|
||||
highlightMoveDuration: 0
|
||||
Component.onCompleted: {
|
||||
d.setData(control.model)
|
||||
}
|
||||
Connections{
|
||||
target: control
|
||||
function onModelChanged(){
|
||||
d.setData(control.model)
|
||||
}
|
||||
onMovementEnded:{
|
||||
currentIndex = list_view.contentX/list_view.width
|
||||
if(currentIndex === 0){
|
||||
currentIndex = list_view.count-2
|
||||
}else if(currentIndex === list_view.count-1){
|
||||
currentIndex = 1
|
||||
}
|
||||
flagXChanged = false
|
||||
timer_run.start()
|
||||
}
|
||||
orientation : ListView.Horizontal
|
||||
delegate: Item{
|
||||
id:item_control
|
||||
width: ListView.view.width
|
||||
height: ListView.view.height
|
||||
property int displayIndex: {
|
||||
if(index === 0)
|
||||
return content_model.count-3
|
||||
if(index === content_model.count-1)
|
||||
return 0
|
||||
return index-1
|
||||
}
|
||||
onMovementStarted: {
|
||||
flagXChanged = true
|
||||
timer_run.stop()
|
||||
}
|
||||
onContentXChanged: {
|
||||
if(flagXChanged){
|
||||
var maxX = Math.min(list_view.width*(currentIndex+1),list_view.count*list_view.width)
|
||||
var minY = Math.max(0,(list_view.width*(currentIndex-1)))
|
||||
if(contentX>=maxX){
|
||||
contentX = maxX
|
||||
}
|
||||
if(contentX<=minY){
|
||||
contentX = minY
|
||||
Loader{
|
||||
property int displayIndex : item_control.displayIndex
|
||||
property var model: list_view.model.get(index)
|
||||
anchors.fill: parent
|
||||
sourceComponent: {
|
||||
if(model){
|
||||
return control.delegate
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
onMovementEnded:{
|
||||
currentIndex = list_view.contentX/list_view.width
|
||||
if(currentIndex === 0){
|
||||
currentIndex = list_view.count-2
|
||||
}else if(currentIndex === list_view.count-1){
|
||||
currentIndex = 1
|
||||
}
|
||||
d.flagXChanged = false
|
||||
timer_run.restart()
|
||||
}
|
||||
onMovementStarted: {
|
||||
d.flagXChanged = true
|
||||
timer_run.stop()
|
||||
}
|
||||
onContentXChanged: {
|
||||
if(d.flagXChanged){
|
||||
var maxX = Math.min(list_view.width*(currentIndex+1),list_view.count*list_view.width)
|
||||
var minY = Math.max(0,(list_view.width*(currentIndex-1)))
|
||||
if(contentX>=maxX){
|
||||
contentX = maxX
|
||||
}
|
||||
if(contentX<=minY){
|
||||
contentX = minY
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Component{
|
||||
id:com_indicator
|
||||
Rectangle{
|
||||
width: 8
|
||||
height: 8
|
||||
radius: 4
|
||||
FluShadow{
|
||||
radius: 4
|
||||
}
|
||||
scale: checked ? 1.2 : 1
|
||||
color: checked ? FluTheme.primaryColor.dark : Qt.rgba(1,1,1,0.7)
|
||||
border.width: mouse_item.containsMouse ? 1 : 0
|
||||
border.color: FluTheme.primaryColor.dark
|
||||
MouseArea{
|
||||
id:mouse_item
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
changedIndex(realIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Row{
|
||||
spacing: 10
|
||||
id:layout_indicator
|
||||
spacing: control.indicatorSpacing
|
||||
anchors{
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
bottom: parent.bottom
|
||||
bottomMargin: 20
|
||||
horizontalCenter:(indicatorGravity & Qt.AlignHCenter) ? parent.horizontalCenter : undefined
|
||||
verticalCenter: (indicatorGravity & Qt.AlignVCenter) ? parent.verticalCenter : undefined
|
||||
bottom: (indicatorGravity & Qt.AlignBottom) ? parent.bottom : undefined
|
||||
top: (indicatorGravity & Qt.AlignTop) ? parent.top : undefined
|
||||
left: (indicatorGravity & Qt.AlignLeft) ? parent.left : undefined
|
||||
right: (indicatorGravity & Qt.AlignRight) ? parent.right : undefined
|
||||
bottomMargin: control.indicatorMarginBottom
|
||||
leftMargin: control.indicatorMarginBottom
|
||||
rightMargin: control.indicatorMarginBottom
|
||||
topMargin: control.indicatorMarginBottom
|
||||
}
|
||||
visible: showIndicator
|
||||
Repeater{
|
||||
id:repeater_indicator
|
||||
model: list_view.count
|
||||
Rectangle{
|
||||
width: 8
|
||||
height: 8
|
||||
radius: 4
|
||||
visible: {
|
||||
if(index===0 || index===list_view.count-1)
|
||||
return false
|
||||
return true
|
||||
Loader{
|
||||
property int displayIndex: {
|
||||
if(index === 0)
|
||||
return list_view.count-3
|
||||
if(index === list_view.count-1)
|
||||
return 0
|
||||
return index-1
|
||||
}
|
||||
property int realIndex: index
|
||||
property bool checked: list_view.currentIndex === index
|
||||
sourceComponent: {
|
||||
if(index===0 || index===list_view.count-1)
|
||||
return undefined
|
||||
return control.indicatorDelegate
|
||||
}
|
||||
border.width: 1
|
||||
border.color: FluColors.Grey100
|
||||
color: list_view.currentIndex === index ? FluTheme.primaryColor.dark : Qt.rgba(1,1,1,0.5)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -121,12 +189,13 @@ Item {
|
||||
timer_anim.start()
|
||||
}
|
||||
}
|
||||
function setData(data){
|
||||
content_model.clear()
|
||||
content_model.append(data[data.length-1])
|
||||
content_model.append(data)
|
||||
content_model.append(data[0])
|
||||
list_view.currentIndex = 1
|
||||
|
||||
function changedIndex(index){
|
||||
d.flagXChanged = true
|
||||
timer_run.stop()
|
||||
list_view.currentIndex = index
|
||||
d.flagXChanged = false
|
||||
timer_run.restart()
|
||||
}
|
||||
|
||||
}
|
||||
|
122
src/imports/FluentUI/Controls/FluChart.qml
Normal file
122
src/imports/FluentUI/Controls/FluChart.qml
Normal file
@ -0,0 +1,122 @@
|
||||
import QtQuick 2.13
|
||||
import "./../JS/Chart.js" as Chart
|
||||
|
||||
Canvas {
|
||||
id: control
|
||||
|
||||
property var jsChart: undefined
|
||||
property string chartType
|
||||
property var chartData
|
||||
property var chartOptions
|
||||
property double chartAnimationProgress: 0.1
|
||||
property int animationEasingType: Easing.InOutExpo
|
||||
property double animationDuration: 500
|
||||
property var memorizedContext
|
||||
property var memorizedData
|
||||
property var memorizedOptions
|
||||
property alias animationRunning: chartAnimator.running
|
||||
signal animationFinished()
|
||||
function animateToNewData()
|
||||
{
|
||||
chartAnimationProgress = 0.1;
|
||||
jsChart.update();
|
||||
chartAnimator.restart();
|
||||
}
|
||||
MouseArea {
|
||||
id: event
|
||||
anchors.fill: control
|
||||
hoverEnabled: true
|
||||
enabled: true
|
||||
property var handler: undefined
|
||||
property QtObject mouseEvent: QtObject {
|
||||
property int left: 0
|
||||
property int top: 0
|
||||
property int x: 0
|
||||
property int y: 0
|
||||
property int clientX: 0
|
||||
property int clientY: 0
|
||||
property string type: ""
|
||||
property var target
|
||||
}
|
||||
function submitEvent(mouse, type) {
|
||||
mouseEvent.type = type
|
||||
mouseEvent.clientX = mouse ? mouse.x : 0;
|
||||
mouseEvent.clientY = mouse ? mouse.y : 0;
|
||||
mouseEvent.x = mouse ? mouse.x : 0;
|
||||
mouseEvent.y = mouse ? mouse.y : 0;
|
||||
mouseEvent.left = 0;
|
||||
mouseEvent.top = 0;
|
||||
mouseEvent.target = control;
|
||||
|
||||
if(handler) {
|
||||
handler(mouseEvent);
|
||||
}
|
||||
|
||||
control.requestPaint();
|
||||
}
|
||||
onClicked:(mouse)=> {
|
||||
submitEvent(mouse, "click");
|
||||
}
|
||||
onPositionChanged:(mouse)=> {
|
||||
submitEvent(mouse, "mousemove");
|
||||
}
|
||||
onExited: {
|
||||
submitEvent(undefined, "mouseout");
|
||||
}
|
||||
onEntered: {
|
||||
submitEvent(undefined, "mouseenter");
|
||||
}
|
||||
onPressed:(mouse)=> {
|
||||
submitEvent(mouse, "mousedown");
|
||||
}
|
||||
onReleased:(mouse)=> {
|
||||
submitEvent(mouse, "mouseup");
|
||||
}
|
||||
}
|
||||
PropertyAnimation {
|
||||
id: chartAnimator
|
||||
target: control
|
||||
property: "chartAnimationProgress"
|
||||
alwaysRunToEnd: true
|
||||
to: 1
|
||||
duration: control.animationDuration
|
||||
easing.type: control.animationEasingType
|
||||
onFinished: {
|
||||
control.animationFinished();
|
||||
}
|
||||
}
|
||||
onChartAnimationProgressChanged: {
|
||||
control.requestPaint();
|
||||
}
|
||||
onPaint: {
|
||||
if(control.getContext('2d') !== null && memorizedContext !== control.getContext('2d') || memorizedData !== control.chartData || memorizedOptions !== control.chartOptions) {
|
||||
var ctx = control.getContext('2d');
|
||||
|
||||
jsChart = Chart.build(ctx, {
|
||||
type: control.chartType,
|
||||
data: control.chartData,
|
||||
options: control.chartOptions
|
||||
});
|
||||
|
||||
memorizedData = control.chartData ;
|
||||
memorizedContext = control.getContext('2d');
|
||||
memorizedOptions = control.chartOptions;
|
||||
|
||||
control.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;});
|
||||
|
||||
chartAnimator.start();
|
||||
}
|
||||
|
||||
jsChart.draw(chartAnimationProgress);
|
||||
}
|
||||
onWidthChanged: {
|
||||
if(jsChart) {
|
||||
jsChart.resize();
|
||||
}
|
||||
}
|
||||
onHeightChanged: {
|
||||
if(jsChart) {
|
||||
jsChart.resize();
|
||||
}
|
||||
}
|
||||
}
|
@ -3,5 +3,16 @@ import QtQuick.Window
|
||||
import FluentUI
|
||||
|
||||
Rectangle {
|
||||
color: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1)
|
||||
property real spacing
|
||||
property alias separatorHeight:separator.height
|
||||
|
||||
id:root
|
||||
color:Qt.rgba(0,0,0,0)
|
||||
height: spacing*2+separator.height
|
||||
Rectangle{
|
||||
id:separator
|
||||
color: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1)
|
||||
width:parent.width
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,6 @@ Button {
|
||||
contentItem: FluText {
|
||||
id:title
|
||||
text: control.text
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: control.textColor
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ Item {
|
||||
property int pageMode: FluNavigationViewType.Stack
|
||||
signal logoClicked
|
||||
id:control
|
||||
QtObject{
|
||||
Item{
|
||||
id:d
|
||||
property bool animDisabled:false
|
||||
property var stackItems: []
|
||||
@ -66,6 +66,10 @@ Item {
|
||||
}
|
||||
return data
|
||||
}
|
||||
function refreshWindow(){
|
||||
Window.window.height = Window.window.height-1
|
||||
Window.window.height = Window.window.height+1
|
||||
}
|
||||
}
|
||||
Component.onCompleted: {
|
||||
d.displayMode = Qt.binding(function(){
|
||||
@ -110,11 +114,12 @@ Item {
|
||||
id:com_panel_item_separatorr
|
||||
FluDivider{
|
||||
width: layout_list.width
|
||||
height: {
|
||||
spacing: model.spacing
|
||||
separatorHeight: {
|
||||
if(model.parent){
|
||||
return model.parent.isExpand ? 1 : 0
|
||||
return model.parent.isExpand ? model.size : 0
|
||||
}
|
||||
return 1
|
||||
return model.size
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -708,6 +713,11 @@ Item {
|
||||
NumberAnimation{
|
||||
duration: 167
|
||||
easing.type: Easing.OutCubic
|
||||
onRunningChanged: {
|
||||
if(!running){
|
||||
d.refreshWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Behavior on x {
|
||||
@ -715,6 +725,11 @@ Item {
|
||||
NumberAnimation{
|
||||
duration: 167
|
||||
easing.type: Easing.OutCubic
|
||||
onRunningChanged: {
|
||||
if(!running){
|
||||
d.refreshWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
visible: {
|
||||
@ -1109,4 +1124,7 @@ Item {
|
||||
function navButton(){
|
||||
return btn_nav
|
||||
}
|
||||
function logoButton(){
|
||||
return image_logo
|
||||
}
|
||||
}
|
||||
|
@ -6,4 +6,6 @@ QtObject {
|
||||
readonly property string key : FluTools.uuid()
|
||||
property int _idx
|
||||
property var parent
|
||||
property real spacing
|
||||
property int size:1
|
||||
}
|
||||
|
@ -40,27 +40,27 @@ Item{
|
||||
anchors.fill: parent
|
||||
visible: false
|
||||
onPaint: {
|
||||
var ctx = getContext("2d");
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
var w = control.width;
|
||||
var h = control.height;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.save();
|
||||
var ctx = getContext("2d")
|
||||
var x = 0
|
||||
var y = 0
|
||||
var w = control.width
|
||||
var h = control.height
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
||||
ctx.save()
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x + radius[0], y);
|
||||
ctx.lineTo(x + w - radius[1], y);
|
||||
ctx.arcTo(x + w, y, x + w, y + radius[1], radius[1]);
|
||||
ctx.lineTo(x + w, y + h - radius[2]);
|
||||
ctx.arcTo(x + w, y + h, x + w - radius[2], y + h, radius[2]);
|
||||
ctx.lineTo(x + radius[3], y + h);
|
||||
ctx.arcTo(x, y + h, x, y + h - radius[3], radius[3]);
|
||||
ctx.lineTo(x, y + radius[0]);
|
||||
ctx.arcTo(x, y, x + radius[0], y, radius[0]);
|
||||
ctx.closePath();
|
||||
ctx.fillStyle = control.color;
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
ctx.moveTo(x + radius[0], y)
|
||||
ctx.lineTo(x + w - radius[1], y)
|
||||
ctx.arcTo(x + w, y, x + w, y + radius[1], radius[1])
|
||||
ctx.lineTo(x + w, y + h - radius[2])
|
||||
ctx.arcTo(x + w, y + h, x + w - radius[2], y + h, radius[2])
|
||||
ctx.lineTo(x + radius[3], y + h)
|
||||
ctx.arcTo(x, y + h, x, y + h - radius[3], radius[3])
|
||||
ctx.lineTo(x, y + radius[0])
|
||||
ctx.arcTo(x, y, x + radius[0], y, radius[0])
|
||||
ctx.closePath()
|
||||
ctx.fillStyle = "#000000"
|
||||
ctx.fill()
|
||||
ctx.restore()
|
||||
}
|
||||
}
|
||||
OpacityMask {
|
||||
|
298
src/imports/FluentUI/Controls/FluTimeline.qml
Normal file
298
src/imports/FluentUI/Controls/FluTimeline.qml
Normal file
@ -0,0 +1,298 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import FluentUI
|
||||
|
||||
Item{
|
||||
property int mode: FluTimelineType.Left
|
||||
property alias model: repeater.model
|
||||
property color lineColor: Qt.rgba(240/255,240/255,240/255,1)
|
||||
id:control
|
||||
implicitWidth: 380
|
||||
implicitHeight: layout_column.height
|
||||
QtObject{
|
||||
id:d
|
||||
property bool isLeft: control.mode === FluTimelineType.Left
|
||||
property bool isRight: control.mode === FluTimelineType.Right
|
||||
property bool isAlternate: control.mode === FluTimelineType.Alternate
|
||||
property bool hasLable: {
|
||||
for(var i=0;i<model.count;i++){
|
||||
var lable = model.get(i).lable
|
||||
if(lable !== undefined && undefined !== ""){
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
property string stateName : {
|
||||
if(hasLable){
|
||||
return "Center"
|
||||
}
|
||||
if(isRight){
|
||||
return "Right"
|
||||
}
|
||||
if(isAlternate){
|
||||
return "Center"
|
||||
}
|
||||
return "Left"
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
id:rect_line
|
||||
color: control.lineColor
|
||||
height: parent.height
|
||||
width: 2
|
||||
state: d.stateName
|
||||
states: [
|
||||
State {
|
||||
name: "Left"
|
||||
AnchorChanges {
|
||||
target: rect_line
|
||||
anchors.left: control.left
|
||||
}
|
||||
PropertyChanges {
|
||||
target: rect_line
|
||||
anchors.leftMargin: 7
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "Right"
|
||||
AnchorChanges {
|
||||
target: rect_line
|
||||
anchors.right: control.right
|
||||
}
|
||||
PropertyChanges {
|
||||
target: rect_line
|
||||
anchors.rightMargin: 7
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "Center"
|
||||
AnchorChanges {
|
||||
target: rect_line
|
||||
anchors.horizontalCenter: control.horizontalCenter
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Component{
|
||||
id:com_dot
|
||||
Rectangle{
|
||||
width: 16
|
||||
height: 16
|
||||
radius: 8
|
||||
border.width: 4
|
||||
color:FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1)
|
||||
border.color: FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark
|
||||
}
|
||||
}
|
||||
|
||||
Component{
|
||||
id:com_lable
|
||||
FluText{
|
||||
wrapMode: Text.WrapAnywhere
|
||||
horizontalAlignment: textAlignment
|
||||
text: modelData.lable
|
||||
color: FluTheme.primaryColor.dark
|
||||
}
|
||||
}
|
||||
|
||||
Component{
|
||||
id:com_text
|
||||
|
||||
FluText{
|
||||
wrapMode: Text.WrapAnywhere
|
||||
horizontalAlignment: textAlignment
|
||||
text: modelData.text
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Column{
|
||||
id:layout_column
|
||||
spacing: 30
|
||||
width: control.width
|
||||
Repeater{
|
||||
id:repeater
|
||||
Item{
|
||||
id:item_layout
|
||||
width: layout_column.width
|
||||
height: loader_text.height
|
||||
Loader{
|
||||
id:item_loader
|
||||
state: d.stateName
|
||||
states: [
|
||||
State {
|
||||
name: "Left"
|
||||
AnchorChanges {
|
||||
target: item_loader
|
||||
anchors.left: item_layout.left
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "Right"
|
||||
AnchorChanges {
|
||||
target: item_loader
|
||||
anchors.right: item_layout.right
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "Center"
|
||||
AnchorChanges {
|
||||
target: item_loader
|
||||
anchors.horizontalCenter: item_layout.horizontalCenter
|
||||
}
|
||||
}
|
||||
]
|
||||
sourceComponent: {
|
||||
if(model.dot)
|
||||
return model.dot()
|
||||
return com_dot
|
||||
}
|
||||
}
|
||||
|
||||
Loader{
|
||||
property var modelData: control.model.get(index)
|
||||
property int textAlignment: state === "Right" ? Qt.AlignRight : Qt.AlignLeft
|
||||
id:loader_lable
|
||||
sourceComponent: {
|
||||
if(!modelData){
|
||||
return undefined
|
||||
}
|
||||
var lableDelegate = model.lableDelegate
|
||||
if(lableDelegate instanceof Function && lableDelegate() instanceof Component){
|
||||
return lableDelegate()
|
||||
}
|
||||
return com_lable
|
||||
}
|
||||
state: {
|
||||
if(d.isRight){
|
||||
return "Left"
|
||||
}
|
||||
if(d.isAlternate){
|
||||
if(index%2===0){
|
||||
return "Right"
|
||||
}else{
|
||||
return "Left"
|
||||
}
|
||||
}
|
||||
return "Right"
|
||||
}
|
||||
states: [
|
||||
State {
|
||||
name: "Left"
|
||||
AnchorChanges {
|
||||
target: loader_lable
|
||||
anchors.left: item_loader.right
|
||||
anchors.right: item_layout.right
|
||||
}
|
||||
PropertyChanges {
|
||||
target: loader_lable
|
||||
anchors.leftMargin: 14
|
||||
anchors.rightMargin: 14
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "Right"
|
||||
AnchorChanges {
|
||||
target: loader_lable
|
||||
anchors.right: item_loader.left
|
||||
anchors.left: item_layout.left
|
||||
}
|
||||
PropertyChanges {
|
||||
target: loader_lable
|
||||
anchors.leftMargin: 14
|
||||
anchors.rightMargin: 14
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "Center"
|
||||
AnchorChanges {
|
||||
target: loader_lable
|
||||
anchors.right: item_loader.left
|
||||
anchors.left: item_layout.left
|
||||
}
|
||||
PropertyChanges {
|
||||
target: loader_lable
|
||||
anchors.leftMargin: 14
|
||||
anchors.rightMargin: 14
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Loader{
|
||||
id:loader_text
|
||||
property var modelData: control.model.get(index)
|
||||
property int textAlignment: state === "Right" ? Qt.AlignRight : Qt.AlignLeft
|
||||
state: {
|
||||
if(d.isRight){
|
||||
return "Right"
|
||||
}
|
||||
if(d.isAlternate){
|
||||
if(index%2===0){
|
||||
return "Left"
|
||||
}else{
|
||||
return "Right"
|
||||
}
|
||||
}
|
||||
return "Left"
|
||||
}
|
||||
sourceComponent: {
|
||||
if(!modelData){
|
||||
return undefined
|
||||
}
|
||||
var textDelegate = model.textDelegate
|
||||
if(textDelegate instanceof Function && textDelegate() instanceof Component){
|
||||
return textDelegate()
|
||||
}
|
||||
return com_text
|
||||
}
|
||||
states: [
|
||||
State {
|
||||
name: "Left"
|
||||
AnchorChanges {
|
||||
target: loader_text
|
||||
anchors.left: item_loader.right
|
||||
anchors.right: item_layout.right
|
||||
}
|
||||
PropertyChanges {
|
||||
target: loader_text
|
||||
anchors.leftMargin: 14
|
||||
anchors.rightMargin: 14
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "Right"
|
||||
AnchorChanges {
|
||||
target: loader_text
|
||||
anchors.right: item_loader.left
|
||||
anchors.left: item_layout.left
|
||||
}
|
||||
PropertyChanges {
|
||||
target: loader_text
|
||||
anchors.leftMargin: 14
|
||||
anchors.rightMargin: 14
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "Center"
|
||||
AnchorChanges {
|
||||
target: loader_text
|
||||
anchors.right: item_loader.left
|
||||
anchors.left: item_layout.left
|
||||
}
|
||||
PropertyChanges {
|
||||
target: loader_text
|
||||
anchors.leftMargin: 14
|
||||
anchors.rightMargin: 14
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
178
src/imports/FluentUI/Controls/FluTour.qml
Normal file
178
src/imports/FluentUI/Controls/FluTour.qml
Normal file
@ -0,0 +1,178 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Shapes
|
||||
import QtQuick.Window
|
||||
import FluentUI
|
||||
|
||||
Popup{
|
||||
property var steps : []
|
||||
property int targetMargins: 5
|
||||
property Component nextButton: com_next_button
|
||||
property Component prevButton: com_prev_button
|
||||
property int index : 0
|
||||
id:control
|
||||
padding: 0
|
||||
anchors.centerIn: Overlay.overlay
|
||||
width: d.window?.width
|
||||
height: d.window?.height
|
||||
background: Item{}
|
||||
contentItem: Item{}
|
||||
onVisibleChanged: {
|
||||
if(visible){
|
||||
control.index = 0
|
||||
}
|
||||
}
|
||||
onIndexChanged: {
|
||||
canvas.requestPaint()
|
||||
}
|
||||
Component{
|
||||
id:com_next_button
|
||||
FluFilledButton{
|
||||
text: isEnd ? "结束导览" :"下一步"
|
||||
onClicked: {
|
||||
if(isEnd){
|
||||
control.close()
|
||||
}else{
|
||||
control.index = control.index + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Component{
|
||||
id:com_prev_button
|
||||
FluButton{
|
||||
text: "上一步"
|
||||
onClicked: {
|
||||
control.index = control.index - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
Item{
|
||||
id:d
|
||||
property var window: Window.window
|
||||
property var pos:Qt.point(0,0)
|
||||
property var step : steps[index]
|
||||
property var target : step.target()
|
||||
}
|
||||
Connections{
|
||||
target: d.window
|
||||
function onWidthChanged(){
|
||||
canvas.requestPaint()
|
||||
}
|
||||
function onHeightChanged(){
|
||||
canvas.requestPaint()
|
||||
}
|
||||
}
|
||||
Canvas{
|
||||
id:canvas
|
||||
anchors.fill: parent
|
||||
onPaint: {
|
||||
d.pos = d.target.mapToGlobal(0,0)
|
||||
d.pos = Qt.point(d.pos.x-d.window.x,d.pos.y-d.window.y)
|
||||
var ctx = canvas.getContext("2d")
|
||||
ctx.clearRect(0, 0, canvasSize.width, canvasSize.height)
|
||||
ctx.save()
|
||||
ctx.fillStyle = "#88000000"
|
||||
ctx.fillRect(0, 0, canvasSize.width, canvasSize.height)
|
||||
ctx.globalCompositeOperation = 'destination-out'
|
||||
ctx.fillStyle = 'black'
|
||||
drawRoundedRect(Qt.rect(d.pos.x-control.targetMargins,d.pos.y-control.targetMargins, d.target.width+control.targetMargins*2, d.target.height+control.targetMargins*2),2,ctx)
|
||||
ctx.restore()
|
||||
}
|
||||
function drawRoundedRect(rect, r, ctx) {
|
||||
var ptA = Qt.point(rect.x + r, rect.y)
|
||||
var ptB = Qt.point(rect.x + rect.width, rect.y)
|
||||
var ptC = Qt.point(rect.x + rect.width, rect.y + rect.height)
|
||||
var ptD = Qt.point(rect.x, rect.y + rect.height)
|
||||
var ptE = Qt.point(rect.x, rect.y)
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(ptA.x, ptA.y)
|
||||
ctx.arcTo(ptB.x, ptB.y, ptC.x, ptC.y, r)
|
||||
ctx.arcTo(ptC.x, ptC.y, ptD.x, ptD.y, r)
|
||||
ctx.arcTo(ptD.x, ptD.y, ptE.x, ptE.y, r)
|
||||
ctx.arcTo(ptE.x, ptE.y, ptA.x, ptA.y, r)
|
||||
ctx.fill()
|
||||
ctx.closePath()
|
||||
}
|
||||
}
|
||||
FluArea{
|
||||
id:layout_panne
|
||||
radius: 5
|
||||
width: 500
|
||||
height: 88 + text_desc.height
|
||||
color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
|
||||
x: Math.min(Math.max(0,d.pos.x+d.target.width/2-width/2),d.window?.width-width)
|
||||
y: d.pos.y+d.target.height+control.targetMargins + 15
|
||||
border.width: 0
|
||||
FluText{
|
||||
text: d.step.title
|
||||
font: FluTextStyle.BodyStrong
|
||||
elide: Text.ElideRight
|
||||
anchors{
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
topMargin: 15
|
||||
leftMargin: 15
|
||||
right: parent.right
|
||||
rightMargin: 32
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
id:text_desc
|
||||
font: FluTextStyle.Body
|
||||
wrapMode: Text.WrapAnywhere
|
||||
maximumLineCount: 4
|
||||
elide: Text.ElideRight
|
||||
text: d.step.description
|
||||
anchors{
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
rightMargin: 15
|
||||
topMargin: 42
|
||||
leftMargin: 15
|
||||
}
|
||||
}
|
||||
Loader{
|
||||
id:loader_next
|
||||
property bool isEnd: control.index === steps.length-1
|
||||
sourceComponent: com_next_button
|
||||
anchors{
|
||||
top:text_desc.bottom
|
||||
topMargin: 10
|
||||
right: parent.right
|
||||
rightMargin: 15
|
||||
}
|
||||
}
|
||||
Loader{
|
||||
id:loader_prev
|
||||
visible: control.index !== 0
|
||||
sourceComponent: com_prev_button
|
||||
anchors{
|
||||
right:loader_next.left
|
||||
top: loader_next.top
|
||||
rightMargin: 14
|
||||
}
|
||||
}
|
||||
FluIconButton{
|
||||
anchors{
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
margins: 10
|
||||
}
|
||||
width: 26
|
||||
height: 26
|
||||
iconSize: 12
|
||||
iconSource : FluentIcons.ChromeClose
|
||||
onClicked: {
|
||||
control.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
FluIcon{
|
||||
iconSource: FluentIcons.FlickDown
|
||||
color: layout_panne.color
|
||||
x: d.pos.x+d.target.width/2-10
|
||||
y: d.pos.y+d.target.height
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import FluentUI
|
||||
@ -8,10 +7,11 @@ Window {
|
||||
default property alias content: container.data
|
||||
property bool closeDestory: true
|
||||
property int launchMode: FluWindowType.Standard
|
||||
property string route
|
||||
property var argument:({})
|
||||
property var pageRegister
|
||||
property var background : com_background
|
||||
property Component loadingItem: com_loading
|
||||
property var _pageRegister
|
||||
property string _route
|
||||
property var closeFunc: function(event){
|
||||
if(closeDestory){
|
||||
deleteWindow()
|
||||
@ -20,26 +20,31 @@ Window {
|
||||
event.accepted = false
|
||||
}
|
||||
}
|
||||
property color backgroundColor: {
|
||||
if(active){
|
||||
return FluTheme.dark ? Qt.rgba(26/255,34/255,40/255,1) : Qt.rgba(238/255,244/255,249/255,1)
|
||||
}
|
||||
return FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
|
||||
}
|
||||
property alias backgroundOpacity: bg.opacity
|
||||
property alias backgroundVisible: bg.visible
|
||||
signal initArgument(var argument)
|
||||
id:window
|
||||
color:"transparent"
|
||||
onClosing:(event)=>closeFunc(event)
|
||||
Component.onCompleted: {
|
||||
helper.initWindow(window)
|
||||
initArgument(argument)
|
||||
}
|
||||
Rectangle{
|
||||
id: bg
|
||||
Connections{
|
||||
target: window
|
||||
function onClosing(event){closeFunc(event)}
|
||||
}
|
||||
Component{
|
||||
id:com_background
|
||||
Rectangle{
|
||||
color: {
|
||||
if(active){
|
||||
return FluTheme.dark ? Qt.rgba(26/255,34/255,40/255,1) : Qt.rgba(238/255,244/255,249/255,1)
|
||||
}
|
||||
return FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loader{
|
||||
anchors.fill: parent
|
||||
color: backgroundColor
|
||||
sourceComponent: background
|
||||
}
|
||||
Item{
|
||||
id:container
|
||||
@ -124,8 +129,8 @@ Window {
|
||||
FluApp.deleteWindow(window)
|
||||
}
|
||||
function onResult(data){
|
||||
if(pageRegister){
|
||||
pageRegister.onResult(data)
|
||||
if(_pageRegister){
|
||||
_pageRegister.onResult(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.7 MiB After Width: | Height: | Size: 266 KiB |
20782
src/imports/FluentUI/JS/Chart.js
vendored
Normal file
20782
src/imports/FluentUI/JS/Chart.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,10 @@
|
||||
module FluentUI
|
||||
module FluentUI
|
||||
classname FluentUIPlugin
|
||||
designersupported
|
||||
typeinfo plugins.qmltypes
|
||||
|
||||
FluAcrylic 1.0 Controls/FluAcrylic.qml
|
||||
FluAppBar 1.0 Controls/FluAppBar.qml
|
||||
FluArea 1.0 Controls/FluArea.qml
|
||||
FluAcrylic 1.0 Controls/FluAcrylic.qml
|
||||
FluAutoSuggestBox 1.0 Controls/FluAutoSuggestBox.qml
|
||||
FluBadge 1.0 Controls/FluBadge.qml
|
||||
FluBreadcrumbBar 1.0 Controls/FluBreadcrumbBar.qml
|
||||
@ -17,9 +16,9 @@ FluCheckBox 1.0 Controls/FluCheckBox.qml
|
||||
FluColorPicker 1.0 Controls/FluColorPicker.qml
|
||||
FluColorView 1.0 Controls/FluColorView.qml
|
||||
FluComboBox 1.0 Controls/FluComboBox.qml
|
||||
FluControl 1.0 Controls/FluControl.qml
|
||||
FluContentDialog 1.0 Controls/FluContentDialog.qml
|
||||
FluContentPage 1.0 Controls/FluContentPage.qml
|
||||
FluControl 1.0 Controls/FluControl.qml
|
||||
FluCopyableText 1.0 Controls/FluCopyableText.qml
|
||||
FluDatePicker 1.0 Controls/FluDatePicker.qml
|
||||
FluDivider 1.0 Controls/FluDivider.qml
|
||||
@ -30,15 +29,15 @@ FluFlipView 1.0 Controls/FluFlipView.qml
|
||||
FluFocusRectangle 1.0 Controls/FluFocusRectangle.qml
|
||||
FluIcon 1.0 Controls/FluIcon.qml
|
||||
FluIconButton 1.0 Controls/FluIconButton.qml
|
||||
FluImage 1.0 Controls/FluImage.qml
|
||||
FluInfoBar 1.0 Controls/FluInfoBar.qml
|
||||
FluItem 1.0 Controls/FluItem.qml
|
||||
FluImage 1.0 Controls/FluImage.qml
|
||||
FluMediaPlayer 1.0 Controls/FluMediaPlayer.qml
|
||||
FluItemDelegate 1.0 Controls/FluItemDelegate.qml
|
||||
FluMenu 1.0 Controls/FluMenu.qml
|
||||
FluMenuItem 1.0 Controls/FluMenuItem.qml
|
||||
FluMenuSeparator 1.0 Controls/FluMenuSeparator.qml
|
||||
FluMenuBar 1.0 Controls/FluMenuBar.qml
|
||||
FluMenuBarItem 1.0 Controls/FluMenuBarItem.qml
|
||||
FluMenuItem 1.0 Controls/FluMenuItem.qml
|
||||
FluMenuSeparator 1.0 Controls/FluMenuSeparator.qml
|
||||
FluMultilineTextBox 1.0 Controls/FluMultilineTextBox.qml
|
||||
FluNavigationView 1.0 Controls/FluNavigationView.qml
|
||||
FluObject 1.0 Controls/FluObject.qml
|
||||
@ -60,14 +59,16 @@ FluRadioButtons 1.0 Controls/FluRadioButtons.qml
|
||||
FluRatingControl 1.0 Controls/FluRatingControl.qml
|
||||
FluRectangle 1.0 Controls/FluRectangle.qml
|
||||
FluRemoteLoader 1.0 Controls/FluRemoteLoader.qml
|
||||
FluScrollablePage 1.0 Controls/FluScrollablePage.qml
|
||||
FluScrollBar 1.0 Controls/FluScrollBar.qml
|
||||
FluScrollIndicator 1.0 Controls/FluScrollIndicator.qml
|
||||
FluScrollablePage 1.0 Controls/FluScrollablePage.qml
|
||||
FluShadow 1.0 Controls/FluShadow.qml
|
||||
FluSlider 1.0 Controls/FluSlider.qml
|
||||
FluSpinBox 1.0 Controls/FluSpinBox.qml
|
||||
FluStatusView 1.0 Controls/FluStatusView.qml
|
||||
FluTableView 1.0 Controls/FluTableView.qml
|
||||
FluTabView 1.0 Controls/FluTabView.qml
|
||||
FluTableModelColumn 1.0 Controls/FluTableModelColumn.qml
|
||||
FluTableView 1.0 Controls/FluTableView.qml
|
||||
FluText 1.0 Controls/FluText.qml
|
||||
FluTextBox 1.0 Controls/FluTextBox.qml
|
||||
FluTextBoxBackground 1.0 Controls/FluTextBoxBackground.qml
|
||||
@ -77,7 +78,9 @@ FluTimePicker 1.0 Controls/FluTimePicker.qml
|
||||
FluToggleButton 1.0 Controls/FluToggleButton.qml
|
||||
FluToggleSwitch 1.0 Controls/FluToggleSwitch.qml
|
||||
FluTooltip 1.0 Controls/FluTooltip.qml
|
||||
FluTour 1.0 Controls/FluTour.qml
|
||||
FluTreeView 1.0 Controls/FluTreeView.qml
|
||||
FluWindow 1.0 Controls/FluWindow.qml
|
||||
FluSingleton 1.0 Controls/FluSingleton.qml
|
||||
FluTimeline 1.0 Controls/FluTimeline.qml
|
||||
FluChart 1.0 Controls/FluChart.qml
|
||||
plugin fluentuiplugin
|
||||
|
1
zxing-cpp
Submodule
1
zxing-cpp
Submodule
Submodule zxing-cpp added at cf9becfa1b
Reference in New Issue
Block a user