Compare commits

..

82 Commits
1.5.8 ... 1.6.0

Author SHA1 Message Date
4b6fa1e65c update 2023-10-16 00:23:01 +08:00
f265753228 update 2023-10-15 23:57:37 +08:00
45b96faf7e update 2023-10-15 23:38:42 +08:00
473dec0990 update 2023-10-15 22:57:14 +08:00
939e04e4ca update 2023-10-15 17:24:33 +08:00
332c0ee54e update 2023-10-15 16:29:50 +08:00
d805147627 update 2023-10-14 13:18:45 +08:00
0ecab11e3c update 2023-10-14 01:34:00 +08:00
f0f2814d5e update 2023-10-14 01:24:01 +08:00
d71e474f40 update 2023-10-13 19:50:24 +08:00
aeca953d32 update 2023-10-13 18:38:27 +08:00
b1c0074a10 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2023-10-13 09:23:18 +08:00
f2feb19d68 update 2023-10-13 01:12:36 +08:00
992d8c142c update 2023-10-12 18:25:08 +08:00
16da5f1633 update 2023-10-11 23:56:16 +08:00
1003b34139 update 2023-10-11 22:37:07 +08:00
a2e15fc3b0 update 2023-10-11 11:18:48 +08:00
fecbf48482 Update README.md 2023-10-10 23:05:04 +08:00
20d52ac49a update 2023-10-10 20:04:26 +08:00
e8a77613bc update 2023-10-10 18:31:22 +08:00
54f52e0886 update 2023-10-10 15:06:44 +08:00
79ab73105e update 2023-10-09 12:23:25 +08:00
2bd961ee77 update 2023-10-09 10:22:01 +08:00
17829bac69 update 2023-10-08 19:59:55 +08:00
1d68de9287 update 2023-10-08 19:48:32 +08:00
9e8e55cb73 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2023-10-08 18:19:23 +08:00
29f363afdd update 2023-10-08 18:19:08 +08:00
ecced8abfb Merge pull request #304 from imaben/feat-delete-method
add delete method for http
2023-10-08 12:37:12 +08:00
5a49ffb7e0 add delete method for http 2023-10-08 11:38:57 +08:00
e631465231 update 2023-10-04 21:13:38 +08:00
50b1aaf8f5 update 2023-10-04 21:04:26 +08:00
93b55e7fea update 2023-10-04 19:28:05 +08:00
33fda1d025 update 2023-10-03 16:18:53 +08:00
a6e494d1c7 update 2023-10-03 10:36:19 +08:00
bfaff95fee update 2023-10-02 22:17:02 +08:00
f20bfc0466 update 2023-10-02 21:32:10 +08:00
69b371e807 update 2023-10-02 21:02:06 +08:00
b0545ffa2a update 2023-10-02 21:00:40 +08:00
91ba4d4792 update 2023-10-02 20:16:38 +08:00
3c7499c48b update 2023-10-02 10:16:23 +08:00
1b6743efeb update 2023-10-01 16:18:37 +08:00
68127a7303 update 2023-10-01 15:27:38 +08:00
895332f867 update 2023-10-01 14:59:35 +08:00
8127f7c3ed update 2023-09-29 20:40:27 +08:00
cbe26ce4cd update 2023-09-29 19:30:22 +08:00
c048336de1 update 2023-09-29 18:15:24 +08:00
d65d6fbbac update 2023-09-29 17:49:05 +08:00
674009e394 update 2023-09-29 17:39:45 +08:00
d8e3cf00b4 update 2023-09-29 17:22:22 +08:00
8e84ea1e3a update 2023-09-29 16:08:42 +08:00
5221c5bc63 update 2023-09-28 14:41:24 +08:00
a5b5a5b942 update 2023-09-28 13:12:39 +08:00
52c806eeff update 2023-09-28 12:31:20 +08:00
0e4d81c7c8 update 2023-09-27 18:15:39 +08:00
4a03ad4227 update 2023-09-27 18:10:20 +08:00
8e1e8a9db5 update 2023-09-27 15:18:10 +08:00
9354b8c0bf update 2023-09-26 20:57:52 +08:00
7723ac97fb update 2023-09-26 17:59:08 +08:00
5240f826c5 update 2023-09-26 11:29:11 +08:00
36da8cd785 update 2023-09-26 11:21:24 +08:00
7716ab02a6 update 2023-09-25 18:10:24 +08:00
7a1776407f update 2023-09-23 15:55:29 +08:00
f88b330f8e update 2023-09-22 17:35:02 +08:00
67ef7f13aa update 2023-09-22 09:48:54 +08:00
23ec52ce6a update 2023-09-22 09:31:47 +08:00
5b7fdab1d9 update 2023-09-22 09:21:17 +08:00
4c1a96c03e update 2023-09-22 01:00:32 +08:00
ab4090ea9b update 2023-09-22 00:40:09 +08:00
8fb2ef723e update 2023-09-22 00:31:25 +08:00
77d9b4bde9 update 2023-09-22 00:11:58 +08:00
a96191b2af update 2023-09-21 18:29:09 +08:00
28e1799ca4 update 2023-09-20 18:38:15 +08:00
8337e278ff update 2023-09-19 23:41:56 +08:00
7ad8c969da update 2023-09-19 18:31:29 +08:00
66ae37a023 update 2023-09-19 00:31:49 +08:00
b27a88d261 update 2023-09-18 18:10:27 +08:00
257f3a7b3d update 2023-09-18 00:12:39 +08:00
4710379324 update 2023-09-17 21:34:02 +08:00
8fc74fe43b update 2023-09-17 20:36:33 +08:00
be194e7624 update 2023-09-15 19:11:55 +08:00
e6d9de34ea update 2023-09-15 01:28:03 +08:00
c47fa5ebc7 update 2023-09-14 18:50:36 +08:00
204 changed files with 5420 additions and 2627 deletions

View File

@ -34,7 +34,7 @@ function(get_git_head_revision _refspecvar _hashvar)
endif()
if(NOT "${GIT_DIR}" STREQUAL "")
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
"${GIT_DIR}")
"${GIT_DIR}")
if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
set(GIT_DIR "")
endif()
@ -52,23 +52,23 @@ function(get_git_head_revision _refspecvar _hashvar)
if(NOT IS_DIRECTORY ${GIT_DIR})
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-parse
--show-superproject-working-tree
--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})
${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)
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})
${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")
@ -88,7 +88,7 @@ function(get_git_head_revision _refspecvar _hashvar)
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
"${GIT_DATA}/grabRef.cmake" @ONLY)
"${GIT_DATA}/grabRef.cmake" @ONLY)
include("${GIT_DATA}/grabRef.cmake")
set(${_refspecvar}
@ -299,12 +299,12 @@ git_describe(GIT_DESCRIBE)
git_commit_counts(GIT_COMMIT_COUNT)
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
if(NOT IS_DIRECTORY ${GIT_DIR})
message(STATUS "Current .git not exist")
set(GIT_COMMIT_COUNT "1")
set(GIT_DESCRIBE "1.0.0")
set(GIT_TAG "1.0.0")
message(STATUS "Current .git not exist")
set(GIT_COMMIT_COUNT "1")
set(GIT_DESCRIBE "1.0.0")
set(GIT_TAG "1.0.0")
else()
message(STATUS "Current .git exist")
message(STATUS "Current .git exist")
endif()
string(REPLACE "." "," GIT_TAG_WITH_COMMA ${GIT_TAG})
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" GIT_SEMVER "${GIT_TAG}")

View File

@ -1,43 +1,21 @@
#
# 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()
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)
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)
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
string(STRIP "${HEAD_HASH}" HEAD_HASH)
endif()

View File

@ -0,0 +1,51 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "example"
#define MyAppVersion "${GIT_SEMVER}"
#define MyAppPublisher "ZhuZiChu"
#define MyAppURL "https://zhuzichu520.github.io/"
#define MyAppExeName "example.exe"
#define MyAppFileDir "dist"
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{A053D1AE-AEA9-4105-A79B-B5F5BEDC9208}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={autopf}\{#MyAppName}
DisableProgramGroupPage=yes
; Uncomment the following line to run in non administrative install mode (install for current user only.)
;PrivilegesRequired=lowest
OutputDir=.\
OutputBaseFilename=installer
Compression=lzma
SolidCompression=yes
WizardStyle=modern
UninstallDisplayIcon={app}\{#MyAppExeName}
SetupIconFile=.\..\favicon.ico
[Languages]
Name: "chinesesimplified"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: checkablealone
[Files]
Source: ".\..\{#MyAppFileDir}\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: ".\..\{#MyAppFileDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

View File

@ -38,7 +38,7 @@ jobs:
version: ${{ matrix.qt_ver }}
cache: ${{steps.cache-qt.outputs.cache-hit}}
arch: ${{ matrix.qt_arch }}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats qt3d'
- name: Set up Ninja
uses: seanmiddleditch/gha-setup-ninja@v3

View File

@ -39,7 +39,7 @@ jobs:
version: ${{ matrix.qt_ver }}
cache: ${{steps.cache-qt.outputs.cache-hit}}
arch: ${{ matrix.qt_arch }}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats qt3d'
- name: Set up Ninja
uses: seanmiddleditch/gha-setup-ninja@v3

View File

@ -18,9 +18,10 @@ on:
jobs:
build:
name: Build
runs-on: windows-2022
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-2022]
include:
- qt_arch: win64_mingw
qt_ver: 6.5.0
@ -34,6 +35,11 @@ jobs:
uses: actions/checkout@v3
with:
submodules: recursive
- name: Setup ninja
uses: seanmiddleditch/gha-setup-ninja@master
with:
version: 1.10.2
- name: Install Qt
uses: jurplel/install-qt-action@v3
@ -41,7 +47,7 @@ jobs:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
cache: ${{steps.cache-qt.outputs.cache-hit}}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats qt3d'
- name: Qt6 environment configuration
if: ${{ startsWith( matrix.qt_ver, 6 ) }}
@ -62,6 +68,7 @@ jobs:
run: |
mkdir build
cd build
ninja --version
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\FluentUI\Qt\6.5.0\mingw_64 -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release -GNinja ..
cmake --build . --target all --config Release --parallel
@ -78,14 +85,20 @@ jobs:
- uses: actions/upload-artifact@v2
with:
name: ${{ steps.package.outputs.packageName }}
path: ${{ steps.package.outputs.packageName }}
path: dist
- name: inno setup install
if: startsWith(github.event.ref, 'refs/tags/')
uses: zhuzichu520/inno-setup-action@v1.0.1
with:
filepath: ./action-cli/InstallerScript.iss
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.package.outputs.packageName }}.zip
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.zip
file: ./action-cli/installer.exe
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.exe
tag: ${{ github.ref }}
overwrite: true
overwrite: true

View File

@ -6,14 +6,14 @@ on:
- 'src/**'
- 'example/**'
- 'scripts/**'
- '.github/workflows/windows_qt5.yml'
- '.github/workflows/windows-qt5.yml'
pull_request:
paths:
- '*.txt'
- 'example/**'
- 'src/**'
- 'scripts/**'
- '.github/workflows/windows_qt5.yml'
- '.github/workflows/windows-qt5.yml'
jobs:
build:
@ -72,14 +72,20 @@ jobs:
- uses: actions/upload-artifact@v2
with:
name: ${{ steps.package.outputs.packageName }}
path: ${{ steps.package.outputs.packageName }}
path: dist
- name: inno setup install
if: startsWith(github.event.ref, 'refs/tags/')
uses: zhuzichu520/inno-setup-action@v1.0.1
with:
filepath: ./action-cli/InstallerScript.iss
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.package.outputs.packageName }}.zip
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.zip
file: ./action-cli/installer.exe
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.exe
tag: ${{ github.ref }}
overwrite: true
overwrite: true

View File

@ -42,13 +42,14 @@ jobs:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
cache: ${{steps.cache-qt.outputs.cache-hit}}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats qtspeech'
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats qtspeech qt3d'
- name: msvc-build
id: build
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.msvc_arch }}
ninja --version
mkdir build
cd build
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\FluentUI\Qt\6.5.0\msvc2019_64 -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=Release -GNinja ..
@ -73,14 +74,20 @@ jobs:
- uses: actions/upload-artifact@v2
with:
name: ${{ steps.package.outputs.packageName }}
path: ${{ steps.package.outputs.packageName }}
path: dist
- name: inno setup install
if: startsWith(github.event.ref, 'refs/tags/')
uses: zhuzichu520/inno-setup-action@v1.0.1
with:
filepath: ./action-cli/InstallerScript.iss
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.package.outputs.packageName }}.zip
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.zip
file: ./action-cli/installer.exe
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.exe
tag: ${{ github.ref }}
overwrite: true

5
.gitignore vendored
View File

@ -37,4 +37,7 @@ build
cmake-build-*
.idea
example/Version.h
example/Version.h
action-cli
dist

View File

@ -8,7 +8,6 @@ list(APPEND CMAKE_MODULE_PATH ${FLUENTUI_DIRECTORY}/.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)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
@ -32,14 +31,12 @@ if (FLUENTUI_BUILD_EXAMPLES)
add_subdirectory(example)
endif ()
if (FLUENTUI_BUILD_FRAMELESSHEPLER)
set(FRAMELESSHELPER_BUILD_STATIC ON)
set(FRAMELESSHELPER_NO_DEBUG_OUTPUT ON)
add_subdirectory(framelesshelper)
endif ()
set(FRAMELESSHELPER_BUILD_STATIC ON)
set(FRAMELESSHELPER_NO_DEBUG_OUTPUT ON)
set(FRAMELESSHELPER_BUILD_WIDGETS OFF)
add_subdirectory(framelesshelper)
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

@ -6,7 +6,7 @@
QML FluentUI
</h1>
<p align="center">
A fluent design component library for Qt QML <a href="https://zhuzichu520.github.io">official wasm app.</a>
A fluent design component library for Qt QML You need Pyside6 <a href="https://github.com/zhuzichu520/PySide6-FluentUI-QML">PySide6-FluentUI-QML</a>
</p>
![win-badge] ![ubuntu-badge] ![macos-badge] ![release-badge] ![download-badge] ![download-latest]

View File

@ -64,14 +64,14 @@ if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
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 *.obj qmldir)
foreach(filepath ${RES_PATHS})
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
list(APPEND resource_files ${filename})
endforeach(filepath)
endif()
#如果是Windows平台则生成rc文件
#如果是Windows平台则生成rc文件还有inno setup脚本文件
set(EXAMPLE_VERSION_RC_PATH "")
if(WIN32)
set(EXAMPLE_VERSION_RC_PATH ${CMAKE_BINARY_DIR}/version_${PROJECT_NAME}.rc)
@ -79,6 +79,10 @@ if(WIN32)
${FLUENTUI_DIRECTORY}/.cmake/version_exe.rc.in
${EXAMPLE_VERSION_RC_PATH}
)
configure_file(
${FLUENTUI_DIRECTORY}/.cmake/InstallerScript.iss.in
${CMAKE_SOURCE_DIR}/action-cli/InstallerScript.iss
)
endif()
#添加可执行文件
@ -100,9 +104,9 @@ if(WIN32)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(3RDPARTY_ARCH_DIR ${CMAKE_SOURCE_DIR}/3rdparty/Win_x64)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
if(MSVC)
set(DLLPATH ${3RDPARTY_ARCH_DIR}/msvc/*.dll)
else()
elseif(MINGW)
set(DLLPATH ${3RDPARTY_ARCH_DIR}/mingw/*.dll)
endif()
string(REPLACE "/" ${PATH_SEPARATOR} DLLPATH "${DLLPATH}")
@ -156,8 +160,6 @@ target_link_libraries(example PRIVATE
Qt${QT_VERSION_MAJOR}::Svg
Qt${QT_VERSION_MAJOR}::Network
fluentuiplugin
FramelessHelper::Core
FramelessHelper::Quick
)
#安装

View File

@ -123,7 +123,6 @@
<file>res/image/qrcode_zfb.jpg</file>
<file>qml/App.qml</file>
<file>qml/component/CodeExpander.qml</file>
<file>qml/component/CustomWindow.qml</file>
<file>qml/global/ItemsFooter.qml</file>
<file>qml/global/ItemsOriginal.qml</file>
<file>qml/global/qmldir</file>
@ -187,5 +186,8 @@
<file>qml/page/T_StaggeredView.qml</file>
<file>qml/viewmodel/SettingsViewModel.qml</file>
<file>qml/viewmodel/TextBoxViewModel.qml</file>
<file>qml/page/T_Clip.qml</file>
<file>qml/page/T_3D.qml</file>
<file>qml/global/Lang.qml</file>
</qresource>
</RCC>

View File

@ -8,6 +8,20 @@ Window {
id: app
flags: Qt.SplashScreen
Connections{
target: FluTheme
function onDarkModeChanged(){
SettingsHelper.saveDarkMode(FluTheme.darkMode)
}
}
Connections{
target: FluApp
function onVsyncChanged(){
SettingsHelper.saveVsync(FluApp.vsync)
}
}
FluHttpInterceptor{
id:interceptor
function onIntercept(request){
@ -26,9 +40,9 @@ Window {
Component.onCompleted: {
FluApp.init(app)
FluTheme.darkMode = FluThemeType.System
FluApp.vsync = SettingsHelper.getVsync()
FluTheme.darkMode = SettingsHelper.getDarkMode()
FluTheme.enableAnimation = true
FluTheme.nativeText = true
FluApp.routes = {
"/":"qrc:/example/qml/window/MainWindow.qml",
"/about":"qrc:/example/qml/window/AboutWindow.qml",

View File

@ -80,7 +80,6 @@ FluExpander{
"FluIcon",
"FluIconButton",
"FluInfoBar",
"FluItem",
"FluMediaPlayer",
"FluMenu",
"FluMenuItem",
@ -140,7 +139,8 @@ FluExpander{
"FluRangeSlider",
"FluStaggeredView",
"FluProgressButton",
"FluLoadingButton"
"FluLoadingButton",
"FluClip"
];
code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;");

View File

@ -1,64 +0,0 @@
import QtQuick
import QtQuick.Layouts
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
visible: window.appBarVisible
icon:"qrc:/example/res/image/favicon.ico"
anchors {
top: parent.top
left: parent.left
right: parent.right
}
darkText: lang.dark_mode
}
Item{
id:container
anchors{
top: title_bar.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
clip: true
}
FramelessHelper{
id:framless_helper
onReady: {
setTitleBarItem(title_bar)
moveWindowToDesktopCenter()
setHitTestVisible(title_bar.minimizeButton())
setHitTestVisible(title_bar.maximizeButton())
setHitTestVisible(title_bar.closeButton())
setWindowFixedSize(fixSize)
title_bar.maximizeButton.visible = !fixSize
if (blurBehindWindowEnabled)
window.background = undefined
window.show()
}
}
Connections{
target: FluTheme
function onDarkChanged(){
if (FluTheme.dark)
FramelessUtils.systemTheme = FramelessHelperConstants.Dark
else
FramelessUtils.systemTheme = FramelessHelperConstants.Light
}
}
function setHitTestVisible(com){
framless_helper.setHitTestVisible(com)
}
function setTitleBarItem(com){
framless_helper.setTitleBarItem(com)
}
}

View File

@ -12,7 +12,7 @@ FluObject{
FluPaneItemSeparator{}
FluPaneItem{
title:lang.about
title:Lang.about
icon:FluentIcons.Contact
onDropped: { FluApp.navigate("/about") }
onTapListener:function(){
@ -21,7 +21,7 @@ FluObject{
}
FluPaneItem{
title:lang.settings
title:Lang.settings
icon:FluentIcons.Settings
url:"qrc:/example/qml/page/T_Settings.qml"
onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) }

View File

@ -16,7 +16,7 @@ FluObject{
FluPaneItem{
id:item_home
count: 9
title:lang.home
title:Lang.home
infoBadge:FluBadge{
count: item_home.count
}
@ -45,9 +45,15 @@ FluObject{
}
}
FluPaneItemExpander{
title:"PaneItemExpander Disabled"
iconVisible: false
disabled: true
}
FluPaneItemExpander{
id:item_expander_basic_input
title:lang.basic_input
title:Lang.basic_input
icon:FluentIcons.CheckboxComposite
editDelegate: FluTextBox{
text:item_expander_basic_input.title
@ -129,10 +135,15 @@ FluObject{
onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) }
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:"PaneItem Disabled"
disabled: true
icon: FluentIcons.Error
}
}
FluPaneItemExpander{
title:lang.form
title:Lang.form
icon:FluentIcons.GridView
FluPaneItem{
title:"TextBox"
@ -167,7 +178,7 @@ FluObject{
}
FluPaneItemExpander{
title:lang.surface
title:Lang.surface
icon:FluentIcons.SurfaceHub
FluPaneItem{
title:"InfoBar"
@ -202,6 +213,12 @@ FluObject{
onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) }
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:"Clip"
url:"qrc:/example/qml/page/T_Clip.qml"
onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) }
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:"StatusView"
url:"qrc:/example/qml/page/T_StatusView.qml"
@ -235,7 +252,7 @@ FluObject{
}
FluPaneItemExpander{
title:lang.popus
title:Lang.popus
icon:FluentIcons.ButtonMenu
FluPaneItem{
title:"Dialog"
@ -273,7 +290,7 @@ FluObject{
}
FluPaneItemExpander{
title:lang.navigation
title:Lang.navigation
icon:FluentIcons.AllApps
FluPaneItem{
title:"Pivot"
@ -342,7 +359,7 @@ FluObject{
}
FluPaneItemExpander{
title:lang.theming
title:Lang.theming
icon:FluentIcons.Brightness
FluPaneItem{
title:"Acrylic"
@ -376,7 +393,7 @@ FluObject{
}
FluPaneItemExpander{
title:lang.other
title:Lang.other
icon:FluentIcons.Shop
FluPaneItem{
title:"QRCode"
@ -442,6 +459,12 @@ FluObject{
}
onDropped:{ FluApp.navigate("/hotload") }
}
FluPaneItem{
title:"3D"
url:"qrc:/example/qml/page/T_3D.qml"
onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) }
onTap:{ navigationView.push(url) }
}
}
function getRecentlyAddedData(){
@ -477,6 +500,9 @@ FluObject{
}
function getSearchData(){
if(!navigationView){
return
}
var arr = []
var items = navigationView.getItems();
for(var i=0;i<items.length;i++){

View File

@ -0,0 +1,77 @@
pragma Singleton
import QtQuick
QtObject {
property string home
property string basic_input
property string form
property string surface
property string popus
property string navigation
property string theming
property string media
property string dark_mode
property string sys_dark_mode
property string search
property string about
property string settings
property string locale
property string navigation_view_display_mode
property string other
function zh(){
home="首页"
basic_input="基本输入"
form="表单"
surface="表面"
popus="弹窗"
navigation="导航"
theming="主题"
media="媒体"
dark_mode="夜间模式"
sys_dark_mode="跟随系统"
search="查找"
about="关于"
settings="设置"
locale="语言环境"
navigation_view_display_mode="导航视图显示模式"
other="其他"
}
function en(){
home="Home"
basic_input="Basic Input"
form="Form"
surface="Surfaces"
popus="Popus"
navigation="Navigation"
theming="Theming"
media="Media"
dark_mode="Dark Mode"
sys_dark_mode="Sync with system"
search="Search"
about="About"
settings="Settings"
locale="Locale"
navigation_view_display_mode="NavigationView Display Mode"
other="Other"
}
property string __locale
property var __localeList: ["Zh","En"]
on__LocaleChanged: {
if(__locale === "Zh"){
zh()
}else{
en()
}
}
Component.onCompleted: {
__locale = "En"
}
}

View File

@ -1,2 +1,3 @@
singleton ItemsOriginal 1.0 ItemsOriginal.qml
singleton ItemsFooter 1.0 ItemsFooter.qml
singleton Lang 1.0 Lang.qml

View File

@ -0,0 +1,120 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Window
import FluentUI
import Qt3D.Core
import Qt3D.Render
import Qt3D.Input
import Qt3D.Extras
import QtQuick.Scene3D
import QtQuick.Dialogs
import Qt.labs.platform
import "qrc:///example/qml/component"
FluContentPage{
id:root
title:"3D"
Scene3D{
id:scene_3d
anchors.fill: parent
focus: true
aspects: ["input", "logic"]
cameraAspectRatioMode: Scene3D.AutomaticAspectRatio
Entity {
Camera {
id: camera
projectionType: CameraLens.PerspectiveProjection
fieldOfView: 22.5
aspectRatio: scene_3d.width / scene_3d.height
nearPlane: 1
farPlane: 1000.0
viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
position: Qt.vector3d( 0.0, 0.0, 15.0 )
}
FirstPersonCameraController {
linearSpeed: 100
lookSpeed: 50
camera: camera
}
components: [
RenderSettings{
activeFrameGraph: ForwardRenderer{
clearColor: Qt.rgba(0,0,0,0);
camera: camera
}
},
InputSettings{}
]
Mesh {
id: mesh
source: "https://zhu-zichu.gitee.io/test.obj"
}
PhongMaterial {
id: material
ambient: color_picker.colorValue
}
Transform{
id:transform
scale: 1.0
translation: Qt.vector3d(0, 0, 0)
rotation: fromEulerAngles(0, 0, 0)
property real hAngle:0.0
NumberAnimation on hAngle{
from:0
to:360.0
duration: 5000
loops: Animation.Infinite
}
matrix:{
var m=Qt.matrix4x4();
m.rotate(hAngle,Qt.vector3d(0,1,0));
m.translate(Qt.vector3d(0,0,0));
return m;
}
}
Entity {
id: entity
components: [mesh, material,transform]
}
}
}
ColumnLayout{
RowLayout{
spacing: 10
Layout.topMargin: 20
FluText{
text:"tintColor:"
Layout.alignment: Qt.AlignVCenter
}
FluColorPicker{
id:color_picker
enableAlphaChannel:false
Component.onCompleted: {
setColor("gray")
}
}
}
FluButton{
text:"选择obj资源"
onClicked: {
file_dialog.open()
}
}
}
FileDialog {
id: file_dialog
nameFilters: ["Obj files (*.obj)"]
folder: StandardPaths.writableLocation(StandardPaths.DocumentsLocation)
onAccepted: {
var fileUrl = file_dialog.currentFile
mesh.source = fileUrl
}
}
}

View File

@ -47,7 +47,7 @@ FluScrollablePage{
height: 1200/4+20
paddings: 10
Layout.topMargin: 10
FluRectangle{
FluClip{
width: 1920/4
height: 1200/4
radius:[8,8,8,8]

View File

@ -25,7 +25,7 @@ FluContentPage {
leftMargin: 14
}
onClicked: {
grid_view.model = FluApp.awesomelist(text_box.text)
grid_view.model = FluTheme.awesomeList(text_box.text)
}
}
GridView{
@ -34,7 +34,7 @@ FluContentPage {
cellHeight: 80
clip: true
boundsBehavior: GridView.StopAtBounds
model:FluApp.awesomelist()
model:FluTheme.awesomeList()
ScrollBar.vertical: FluScrollBar {}
anchors{
topMargin: 10

View File

@ -36,7 +36,7 @@ FluScrollablePage{
left: parent.left
}
FluCalendarPicker{
current:Date.fromLocaleString("2013年7月11日 21:17:42")
current:new Date()
onAccepted:{
showSuccess(current.toLocaleString())
}

View File

@ -44,7 +44,6 @@ FluScrollablePage{
}
FluCarousel{
anchors.fill: parent
radius:[8,8,8,8]
delegate: Component{
Image {
anchors.fill: parent
@ -82,7 +81,6 @@ FluScrollablePage{
}
FluCarousel{
anchors.fill: parent
radius:[8,8,8,8]
loopTime:1500
indicatorGravity: Qt.AlignHCenter | Qt.AlignTop
indicatorMarginTop:15

View File

@ -11,27 +11,35 @@ FluScrollablePage{
FluArea{
Layout.fillWidth: true
height: 68
height: 72
paddings: 10
Layout.topMargin: 20
FluText{
text:"A 2-state CheckBox"
}
Row{
spacing: 30
anchors.verticalCenter: parent.verticalCenter
FluCheckBox{
disabled: check_box_switch.checked
anchors{
top: parent.top
topMargin: 30
}
FluCheckBox{
disabled: check_box_switch.checked
disabled: check_box_switch_two.checked
}
FluCheckBox{
disabled: check_box_switch_two.checked
text:"Right"
}
FluCheckBox{
disabled: check_box_switch.checked
disabled: check_box_switch_two.checked
text:"Left"
textRight: false
}
}
FluToggleSwitch{
id:check_box_switch
id:check_box_switch_two
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
@ -47,4 +55,60 @@ FluScrollablePage{
}'
}
FluArea{
Layout.fillWidth: true
height: 72
paddings: 10
Layout.topMargin: 20
FluText{
text:"A 3-state CheckBox"
}
Row{
spacing: 30
anchors{
top: parent.top
topMargin: 30
}
FluCheckBox{
property int count: 1
text:"Three State"
disabled: check_box_switch_three.checked
clickListener: function(){
var flag = count%3
if(flag === 0){
checked = false
indeterminate = false
}
if(flag === 1){
checked = true
indeterminate = false
}
if(flag === 2){
checked = true
indeterminate = true
}
count++
}
}
}
FluToggleSwitch{
id:check_box_switch_three
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
}
text:"Disabled"
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluCheckBox{
text:"Text"
indeterminate:true
}'
}
}

View File

@ -0,0 +1,107 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Window
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Clip"
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 380
paddings: 10
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluText{
text:"配合图片使用(software渲染下该组件将没有效果)"
font: FluTextStyle.Subtitle
Layout.topMargin: 20
}
RowLayout{
spacing: 14
FluClip{
width: 50
height: 50
radius:[25,0,25,25]
Image {
asynchronous: true
anchors.fill: parent
source: "qrc:/example/res/svg/avatar_1.svg"
sourceSize: Qt.size(width,height)
}
}
FluClip{
width: 50
height: 50
radius:[10,10,10,10]
Image {
asynchronous: true
anchors.fill: parent
sourceSize: Qt.size(width,height)
source: "qrc:/example/res/svg/avatar_2.svg"
}
}
FluClip{
width: 50
height: 50
radius:[25,25,25,25]
Image {
asynchronous: true
anchors.fill: parent
sourceSize: Qt.size(width,height)
source: "qrc:/example/res/svg/avatar_3.svg"
}
}
FluClip{
width: 50
height: 50
radius:[0,25,25,25]
Image {
asynchronous: true
anchors.fill: parent
sourceSize: Qt.size(width,height)
source: "qrc:/example/res/svg/avatar_4.svg"
}
}
}
FluClip{
width: 1920/5
height: 1200/5
radius:[8,8,8,8]
Image {
asynchronous: true
source: "qrc:/example/res/image/banner_1.jpg"
anchors.fill: parent
sourceSize: Qt.size(2*width,2*height)
}
Layout.topMargin: 20
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluClip{
radius: [25,25,25,25]
width: 50
height: 50
Image{
asynchronous: true
anchors.fill: parent
source: "qrc:/example/res/svg/avatar_4.svg"
sourceSize: Qt.size(width,height)
}
}'
}
}

View File

@ -46,7 +46,6 @@ FluScrollablePage{
}
FluComboBox {
editable: true
font:FluTextStyle.BodyStrong
model: ListModel {
id: model_2
ListElement { text: "Banana" }

View File

@ -58,6 +58,7 @@ FluScrollablePage{
width: parent.width
height: parent.height
contentWidth: width
boundsBehavior: Flickable.StopAtBounds
contentHeight: text_info.height
ScrollBar.vertical: FluScrollBar {}
FluText{

View File

@ -27,6 +27,7 @@ FluScrollablePage{
id: bg
fillMode:Image.PreserveAspectCrop
anchors.fill: parent
asynchronous: true
verticalAlignment: Qt.AlignTop
sourceSize: Qt.size(960,640)
source: "qrc:/example/res/image/bg_home_header.png"
@ -49,23 +50,9 @@ FluScrollablePage{
}
}
ListView{
id: list
anchors{
left: parent.left
right: parent.right
bottom: parent.bottom
}
orientation: ListView.Horizontal
height: 240
model: model_header
header: Item{height: 10;width: 10}
footer: Item{height: 10;width: 10}
ScrollBar.horizontal: FluScrollBar{
id: scrollbar_header
}
clip: false
delegate:Item{
Component{
id:com_grallery
Item{
id: control
width: 220
height: 240
@ -73,7 +60,7 @@ FluScrollablePage{
radius:5
anchors.fill: item_content
}
FluItem{
FluClip{
id:item_content
radius: [5,5,5,5]
width: 200
@ -90,19 +77,14 @@ FluScrollablePage{
Rectangle{
anchors.fill: parent
radius: 5
color:{
if(FluTheme.dark){
if(item_mouse.containsMouse){
return Qt.rgba(1,1,1,0.03)
}
return Qt.rgba(0,0,0,0.0)
}else{
if(item_mouse.containsMouse){
return Qt.rgba(0,0,0,0.03)
}
return Qt.rgba(0,0,0,0.0)
}
}
color:FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03)
visible: item_mouse.containsMouse
}
Rectangle{
anchors.fill: parent
radius: 5
color:Qt.rgba(0,0,0,0.0)
visible: !item_mouse.containsMouse
}
ColumnLayout{
Image {
@ -154,11 +136,31 @@ FluScrollablePage{
}
}
}
ListView{
id: list
anchors{
left: parent.left
right: parent.right
bottom: parent.bottom
}
orientation: ListView.Horizontal
height: 240
model: model_header
header: Item{height: 10;width: 10}
footer: Item{height: 10;width: 10}
ScrollBar.horizontal: FluScrollBar{
id: scrollbar_header
}
clip: false
delegate: com_grallery
}
}
Component{
id:com_item
Item{
property string desc: modelData.desc
width: 320
height: 120
FluArea{
@ -194,7 +196,6 @@ FluScrollablePage{
verticalCenter: parent.verticalCenter
}
}
FluText{
id:item_title
text:modelData.title
@ -205,10 +206,9 @@ FluScrollablePage{
top: item_icon.top
}
}
FluText{
id:item_desc
text:modelData.desc
text:desc
color:FluColors.Grey120
wrapMode: Text.WrapAnywhere
elide: Text.ElideRight

View File

@ -10,7 +10,7 @@ import "qrc:///example/qml/component"
FluContentPage{
title:"Http"
property string cacheDirPath: FluTools.getApplicationDirPath() + "/cache/http"
property string cacheDirPath: StandardPaths.writableLocation(StandardPaths.AppLocalDataLocation) + "/cache/http"
property bool isDownCompleted: false
FluHttp{
@ -100,6 +100,9 @@ FluContentPage{
params.custtel = "1234567890"
params.custemail = "zhuzichu520@gmail.com"
request.params = params
var headers = {}
headers.test = "123456789456465321354"
request.headers = headers
http.post(request,callable)
}
}
@ -127,6 +130,15 @@ FluContentPage{
http.postString(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Delete请求"
onClicked: {
var request = http.newRequest("https://httpbingo.org/delete")
http.deleteResource(request,callable)
}
}
FluProgressButton{
id:btn_download
implicitWidth: parent.width
@ -264,7 +276,7 @@ FluContentPage{
implicitHeight: 36
text: "打开缓存路径"
onClicked: {
Qt.openUrlExternally("file:///"+cacheDirPath)
Qt.openUrlExternally(cacheDirPath)
}
}
FluButton{

View File

@ -12,7 +12,7 @@ FluScrollablePage{
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 240
height: 270
paddings: 10
ColumnLayout{
spacing: 14
@ -44,6 +44,12 @@ FluScrollablePage{
showSuccess("这是一个Success样式的InfoBar这是一个Success样式的InfoBar")
}
}
FluButton{
text:"手动关闭的InfoBar"
onClicked: {
showInfo("这是一个Info样式的InfoBar",0,"支持手动关闭")
}
}
FluButton{
text:"Loading"
onClicked: {

View File

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

View File

@ -12,16 +12,15 @@ FluScrollablePage{
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 460
height: 80
paddings: 10
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
verticalCenter: parent.verticalCenter
}
RowLayout{
Layout.topMargin: 20
FluRectangle{
@ -61,70 +60,6 @@ FluScrollablePage{
radius:[0,0,0,15]
}
}
FluText{
text:"配合图片使用"
font: FluTextStyle.Subtitle
Layout.topMargin: 20
}
RowLayout{
spacing: 14
FluRectangle{
width: 50
height: 50
radius:[25,0,25,25]
Image {
asynchronous: true
anchors.fill: parent
source: "qrc:/example/res/svg/avatar_1.svg"
sourceSize: Qt.size(width,height)
}
}
FluRectangle{
width: 50
height: 50
radius:[10,10,10,10]
Image {
asynchronous: true
anchors.fill: parent
sourceSize: Qt.size(width,height)
source: "qrc:/example/res/svg/avatar_2.svg"
}
}
FluRectangle{
width: 50
height: 50
radius:[25,25,25,25]
Image {
asynchronous: true
anchors.fill: parent
sourceSize: Qt.size(width,height)
source: "qrc:/example/res/svg/avatar_3.svg"
}
}
FluRectangle{
width: 50
height: 50
radius:[0,25,25,25]
Image {
asynchronous: true
anchors.fill: parent
sourceSize: Qt.size(width,height)
source: "qrc:/example/res/svg/avatar_4.svg"
}
}
}
FluRectangle{
width: 1920/5
height: 1200/5
radius:[8,8,8,8]
Image {
asynchronous: true
source: "qrc:/example/res/image/banner_1.jpg"
anchors.fill: parent
sourceSize: Qt.size(2*width,2*height)
}
Layout.topMargin: 20
}
}
}
CodeExpander{
@ -134,14 +69,6 @@ FluScrollablePage{
radius: [25,25,25,25]
width: 50
height: 50
Image{
asynchronous: true
anchors.fill: parent
source: "qrc:/example/res/svg/avatar_4.svg"
sourceSize: Qt.size(width,height)
}
}'
}
}

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import Qt.labs.platform
import "qrc:///example/qml/component"
FluScrollablePage{
@ -47,7 +48,7 @@ FluScrollablePage{
FluScreenshot{
id:screenshot
captrueMode: FluScreenshotType.File
saveFolder: FluTools.getApplicationDirPath()+"/screenshot"
saveFolder: StandardPaths.writableLocation(StandardPaths.AppLocalDataLocation)+"/screenshot"
onCaptrueCompleted:
(captrue)=>{
image.source = captrue

View File

@ -40,7 +40,7 @@ FluScrollablePage{
spacing: 20
anchors.verticalCenter: parent.verticalCenter
FluText{
text:"当前版本 v%1".arg(appInfo.version)
text:"当前版本 v%1".arg(AppInfo.version)
font: FluTextStyle.Body
anchors.verticalCenter: parent.verticalCenter
}
@ -56,6 +56,54 @@ FluScrollablePage{
}
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 50
paddings: 10
FluCheckBox{
text:"V-Sync"
checked: FluApp.vsync
anchors.verticalCenter: parent.verticalCenter
onClicked: {
FluApp.vsync = !FluApp.vsync
dialog_restart.open()
}
}
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 50
paddings: 10
FluCheckBox{
text:"Software Render"
checked: SettingsHelper.getRender() === "software"
anchors.verticalCenter: parent.verticalCenter
onClicked: {
if(SettingsHelper.getRender() === "software"){
SettingsHelper.saveRender("")
}else{
SettingsHelper.saveRender("software")
}
dialog_restart.open()
}
}
}
FluContentDialog{
id:dialog_restart
title:"友情提示"
message:"此操作需要重启才能生效,是否重新启动?"
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
negativeText: "取消"
positiveText:"确定"
onPositiveClicked:{
FluApp.exit(931)
}
}
FluArea{
Layout.fillWidth: true
@ -70,7 +118,7 @@ FluScrollablePage{
left: parent.left
}
FluText{
text:lang.dark_mode
text:Lang.dark_mode
font: FluTextStyle.BodyStrong
Layout.bottomMargin: 4
}
@ -100,7 +148,7 @@ FluScrollablePage{
left: parent.left
}
FluText{
text:lang.navigation_view_display_mode
text:Lang.navigation_view_display_mode
font: FluTextStyle.BodyStrong
Layout.bottomMargin: 4
}
@ -131,7 +179,7 @@ FluScrollablePage{
}
FluText{
text:lang.locale
text:Lang.locale
font: FluTextStyle.BodyStrong
Layout.bottomMargin: 4
}
@ -139,12 +187,12 @@ FluScrollablePage{
Flow{
spacing: 5
Repeater{
model: ["Zh","En"]
model: Lang.__localeList
delegate: FluRadioButton{
checked: appInfo.lang.objectName === modelData
checked: Lang.__locale === modelData
text:modelData
clickListener:function(){
appInfo.changeLang(modelData)
Lang.__locale = modelData
}
}
}

View File

@ -7,12 +7,45 @@ import "qrc:///example/qml/component"
FluContentPage{
id:root
title:"TableView"
signal checkBoxChanged
property var dataSource : []
property int sortType: 0
Component.onCompleted: {
loadData(1,1000)
}
onSortTypeChanged: {
table_view.closeEditor()
if(sortType === 0){
table_view.sort()
}else if(sortType === 1){
table_view.sort((a, b) => a.age - b.age);
}else if(sortType === 2){
table_view.sort((a, b) => b.age - a.age);
}
}
Component{
id:com_checbox
Item{
FluCheckBox{
anchors.centerIn: parent
checked: true === options.checked
enableAnimation: false
clickListener: function(){
var obj = tableModel.getRow(row)
obj.checkbox = table_view.customItem(com_checbox,{checked:!options.checked})
tableModel.setRow(row,obj)
checkBoxChanged()
}
}
}
}
Component{
id:com_action
Item{
@ -23,11 +56,15 @@ FluContentPage{
onClicked: {
table_view.closeEditor()
tableModel.removeRow(row)
checkBoxChanged()
}
}
FluFilledButton{
text:"编辑"
onClicked: {
var obj = tableModel.getRow(row)
obj.name = "12345"
tableModel.setRow(row,obj)
showSuccess(JSON.stringify(tableModel.getRow(row)))
}
}
@ -35,39 +72,44 @@ FluContentPage{
}
}
function loadData(page,count){
var numbers = [100, 300, 500, 1000];
function getRandomAge() {
var randomIndex = Math.floor(Math.random() * numbers.length);
return numbers[randomIndex];
Component{
id:com_column_checbox
Item{
RowLayout{
anchors.centerIn: parent
FluText{
text:"全选"
Layout.alignment: Qt.AlignVCenter
}
FluCheckBox{
checked: true === options.checked
enableAnimation: false
Layout.alignment: Qt.AlignVCenter
clickListener: function(){
var checked = !options.checked
itemModel.display = table_view.customItem(com_column_checbox,{"checked":checked})
for(var i =0;i< tableModel.rowCount ;i++){
var rowData = tableModel.getRow(i)
rowData.checkbox = table_view.customItem(com_checbox,{"checked":checked})
tableModel.setRow(i,rowData)
}
}
}
Connections{
target: root
function onCheckBoxChanged(){
for(var i =0;i< tableModel.rowCount ;i++){
if(false === tableModel.getRow(i).checkbox.options.checked){
itemModel.display = table_view.customItem(com_column_checbox,{"checked":false})
return
}
}
itemModel.display = table_view.customItem(com_column_checbox,{"checked":true})
}
}
}
}
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: getRandomName(),
age:getRandomAge(),
address: getRandomAddresses(),
nickname: getRandomNickname(),
longstring:"你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好",
action:com_action
})
}
table_view.dataSource = dataSource
}
Component{
@ -94,6 +136,88 @@ FluContentPage{
}
}
Component{
id:com_avatar
Item{
FluClip{
anchors.centerIn: parent
width: 40
height: 40
radius: [20,20,20,20]
Image{
anchors.fill: parent
source: {
if(options && options.avatar){
return options.avatar
}
return ""
}
sourceSize: Qt.size(80,80)
}
}
}
}
Component{
id:com_column_sort_age
Item{
FluText{
text:"年龄"
anchors.centerIn: parent
}
ColumnLayout{
spacing: 0
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
rightMargin: 4
}
FluIconButton{
Layout.preferredWidth: 20
Layout.preferredHeight: 15
iconSize: 12
verticalPadding:0
horizontalPadding:0
iconSource: FluentIcons.ChevronUp
iconColor: {
if(1 === root.sortType){
return FluTheme.primaryColor.dark
}
return FluTheme.dark ? Qt.rgba(1,1,1,1) : Qt.rgba(0,0,0,1)
}
onClicked: {
if(root.sortType === 1){
root.sortType = 0
return
}
root.sortType = 1
}
}
FluIconButton{
Layout.preferredWidth: 20
Layout.preferredHeight: 15
iconSize: 12
verticalPadding:0
horizontalPadding:0
iconSource: FluentIcons.ChevronDown
iconColor: {
if(2 === root.sortType){
return FluTheme.primaryColor.dark
}
return FluTheme.dark ? Qt.rgba(1,1,1,1) : Qt.rgba(0,0,0,1)
}
onClicked: {
if(root.sortType === 2){
root.sortType = 0
return
}
root.sortType = 2
}
}
}
}
}
FluTableView{
id:table_view
anchors{
@ -104,13 +228,27 @@ FluContentPage{
}
anchors.topMargin: 20
columnSource:[
{
title: table_view.customItem(com_column_checbox,{checked:true}),
dataIndex: 'checkbox',
width:80,
minimumWidth:80,
maximumWidth:80,
},
{
title: '头像',
dataIndex: 'avatar',
width:100,
minimumWidth:100,
maximumWidth:100
},
{
title: '姓名',
dataIndex: 'name',
readOnly:true,
},
{
title: '年龄',
title: table_view.customItem(com_column_sort_age,{sort:0}),
dataIndex: 'age',
editDelegate:com_combobox,
width:100,
@ -166,6 +304,50 @@ FluContentPage{
}
}
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];
}
var avatars = ["qrc:/example/res/svg/avatar_1.svg", "qrc:/example/res/svg/avatar_2.svg", "qrc:/example/res/svg/avatar_3.svg", "qrc:/example/res/svg/avatar_4.svg","qrc:/example/res/svg/avatar_5.svg","qrc:/example/res/svg/avatar_6.svg","qrc:/example/res/svg/avatar_7.svg","qrc:/example/res/svg/avatar_8.svg","qrc:/example/res/svg/avatar_9.svg","qrc:/example/res/svg/avatar_10.svg","qrc:/example/res/svg/avatar_11.svg","qrc:/example/res/svg/avatar_12.svg"];
function getAvatar(){
var randomIndex = Math.floor(Math.random() * avatars.length);
return avatars[randomIndex];
}
const dataSource = []
for(var i=0;i<count;i++){
dataSource.push({
checkbox: table_view.customItem(com_checbox,{checked:true}),
avatar:table_view.customItem(com_avatar,{avatar:getAvatar()}),
name: getRandomName(),
age:getRandomAge(),
address: getRandomAddresses(),
nickname: getRandomNickname(),
longstring:"你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好",
action: table_view.customItem(com_action),
minimumHeight:50
})
}
root.dataSource = dataSource
table_view.dataSource = root.dataSource
}
}

View File

@ -84,7 +84,7 @@ FluScrollablePage{
text:"找到一份Android外包开发岗位开发了一个Android应用满满成就感前端、服务端、Flutter也都懂一丢丢什么都会什么都不精通钱途无望"
}
ListElement{
lable:"2020-06-01"
lable:"2021-06-01"
text:"由于某个项目紧急临时加入Qt项目组就因为大学学了点C++),本来是想进去打个酱油,到后面竟然成开发主力,坑啊"
}
ListElement{

View File

@ -5,152 +5,127 @@ import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage {
FluContentPage {
title:"TreeView"
function randomName() {
var names = ["张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"]
return names[Math.floor(Math.random() * names.length)]
function treeData(){
const dig = (path = '0', level = 4) => {
const list = [];
for (let i = 0; i < 6; i += 1) {
const key = `${path}-${i}`;
const treeNode = {
title: key,
key,
};
if (level > 0) {
treeNode.children = dig(key, level - 1);
}
list.push(treeNode);
}
return list;
};
return dig();
}
function randomCompany() {
var companies = ["阿里巴巴", "腾讯", "百度", "京东", "华为", "小米", "字节跳动", "美团", "滴滴"]
return companies[Math.floor(Math.random() * companies.length)]
}
function randomDepartment() {
var departments = ["技术部", "销售部", "市场部", "人事部", "财务部", "客服部", "产品部", "设计部", "运营部"]
return departments[Math.floor(Math.random() * departments.length)]
}
function createEmployee() {
var name = randomName()
return tree_view.createItem(name, false)
}
function createSubtree(numEmployees) {
var employees = []
for (var i = 0; i < numEmployees; i++) {
employees.push(createEmployee())
Column{
id:layout_column
spacing: 12
width: 300
anchors{
topMargin: 20
top:parent.top
left: parent.left
leftMargin: 10
bottom:parent.bottom
bottomMargin: 20
}
return tree_view.createItem(randomDepartment(), true, employees)
}
function createOrg(numLevels, numSubtrees, numEmployees) {
if (numLevels === 0) {
return []
FluText{
text:"共计%1条数据当前显示的%2条数据".arg(tree_view.count()).arg(tree_view.visibleCount())
}
FluText{
text:"共计选中%1条数据".arg(tree_view.selectionModel().length)
}
var subtrees = []
for (var i = 0; i < numSubtrees; i++) {
subtrees.push(createSubtree(numEmployees))
}
return [tree_view.createItem(randomCompany(), true, subtrees)].concat(createOrg(numLevels - 1, numSubtrees, numEmployees))
}
FluArea{
id:layout_actions
Layout.fillWidth: true
Layout.topMargin: 20
height: 50
paddings: 10
RowLayout{
spacing: 14
FluDropDownButton{
id:btn_selection_model
Layout.preferredWidth: 140
text:"None"
FluMenuItem{
text:"None"
onClicked: {
btn_selection_model.text = text
tree_view.selectionMode = FluTabViewType.Equal
}
}
FluMenuItem{
text:"Single"
onClicked: {
btn_selection_model.text = text
tree_view.selectionMode = FluTabViewType.SizeToContent
}
}
FluMenuItem{
text:"Muiltple"
onClicked: {
btn_selection_model.text = text
tree_view.selectionMode = FluTabViewType.Compact
}
}
spacing: 10
FluText{
text:"cellHeight:"
Layout.alignment: Qt.AlignVCenter
}
FluFilledButton{
text:"获取选中的数据"
onClicked: {
if(tree_view.selectionMode === FluTreeViewType.None){
showError("当前非选择模式,没有选中的数据")
}
if(tree_view.selectionMode === FluTreeViewType.Single){
if(!tree_view.signleData()){
showError("没有选中数据")
return
}
showSuccess(tree_view.signleData().text)
}
if(tree_view.selectionMode === FluTreeViewType.Multiple){
if(tree_view.multipData().length===0){
showError("没有选中数据")
return
}
var info = []
tree_view.multipData().map((value)=>info.push(value.text))
showSuccess(info.join(","))
}
}
FluSlider{
id:slider_cell_height
value: 30
from: 30
to:100
}
}
RowLayout{
spacing: 10
FluText{
text:"depthPadding:"
Layout.alignment: Qt.AlignVCenter
}
FluSlider{
id:slider_depth_padding
value: 30
from: 30
to:100
}
}
FluToggleSwitch{
id:switch_showline
text:"showLine"
checked: false
}
FluToggleSwitch{
id:switch_draggable
text:"draggable"
checked: false
}
FluToggleSwitch{
id:switch_checkable
text:"checkable"
checked: false
}
FluButton{
text:"all expand"
onClicked: {
tree_view.allExpand()
}
}
FluButton{
text:"all collapse"
onClicked: {
tree_view.allCollapse()
}
}
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 10
paddings: 10
height: 400
anchors{
left: layout_column.right
top: parent.top
bottom: parent.bottom
right: parent.right
rightMargin: 5
topMargin: 5
bottomMargin: 5
}
FluShadow{}
FluTreeView{
id:tree_view
width:240
anchors{
top:parent.top
left:parent.left
bottom:parent.bottom
}
onItemClicked:
(model)=>{
showSuccess(model.text)
}
anchors.fill: parent
cellHeight: slider_cell_height.value
draggable:switch_draggable.checked
showLine: switch_showline.checked
checkable:switch_checkable.checked
depthPadding: slider_depth_padding.value
Component.onCompleted: {
var org = createOrg(3, 3, 3)
createItem()
updateData(org)
var data = treeData()
dataSource = data
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluTreeView{
id:tree_view
width:240
height:600
Component.onCompleted: {
var datas = []
datas.push(createItem("Node1",false))
datas.push(createItem("Node2",false))
datas.push(createItem("Node2",true,[createItem("Node2-1",false),createItem("Node2-2",false)]))
updateData(datas)
}
}
'
}
}

View File

@ -4,7 +4,7 @@ import QtQuick.Layouts
import FluentUI
import "qrc:///example/qml/component"
CustomWindow {
FluWindow {
id:window
title:"关于"
@ -35,7 +35,7 @@ CustomWindow {
}
}
FluText{
text:"v%1".arg(appInfo.version)
text:"v%1".arg(AppInfo.version)
font: FluTextStyle.Body
Layout.alignment: Qt.AlignBottom
}

View File

@ -5,7 +5,7 @@ import FluentUI
import example
import "qrc:///example/qml/component"
CustomWindow {
FluWindow {
id:window
title:"热加载"

View File

@ -4,7 +4,7 @@ import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
CustomWindow {
FluWindow {
id:window
title:"登录"

View File

@ -9,7 +9,7 @@ import "qrc:///example/qml/component"
import "qrc:///example/qml/global"
import "qrc:///example/qml/viewmodel"
CustomWindow {
FluWindow {
id:window
title: "FluentUI"
@ -18,14 +18,15 @@ CustomWindow {
closeDestory:false
minimumWidth: 520
minimumHeight: 200
appBarVisible: false
launchMode: FluWindowType.SingleTask
appBar: undefined
SettingsViewModel{
id:viewmodel_settings
}
closeFunc:function(event){
closeListener:function(event){
dialog_close.open()
event.accepted = false
}
@ -37,7 +38,6 @@ CustomWindow {
checkUpdate(false)
}
}
Component.onCompleted: {
FluTools.setQuitOnLastWindowClosed(false)
tour.open()
@ -58,8 +58,7 @@ CustomWindow {
MenuItem {
text: "退出"
onTriggered: {
window.deleteWindow()
FluApp.closeApp()
FluApp.exit()
}
}
}
@ -86,8 +85,7 @@ CustomWindow {
positiveText:"退出"
neutralText:"取消"
onPositiveClicked:{
window.deleteWindow()
FluApp.closeApp()
FluApp.exit()
}
}
@ -120,7 +118,7 @@ CustomWindow {
left: parent.left
right: parent.right
}
darkText: lang.dark_mode
darkText: Lang.dark_mode
showDark: true
z:7
darkClickListener:(button)=>handleDarkChanged(button)
@ -170,7 +168,7 @@ CustomWindow {
left: parent.left
right: parent.right
}
darkText: lang.dark_mode
darkText: Lang.dark_mode
showDark: true
darkClickListener:(button)=>handleDarkChanged(button)
z:7
@ -183,7 +181,7 @@ CustomWindow {
z:999
//Stack模式每次切换都会将页面压入栈中随着栈的页面增多消耗的内存也越多内存消耗多就会卡顿这时候就需要按返回将页面pop掉释放内存。该模式可以配合FluPage中的launchMode属性设置页面的启动模式
// pageMode: FluNavigationViewType.Stack
//NoStack模式每次切换都会销毁之前的页面然后创建一个新的页面只需消耗少量内存推荐
//NoStack模式每次切换都会销毁之前的页面然后创建一个新的页面只需消耗少量内存可以配合FluViewModel保存页面数据(推荐)
pageMode: FluNavigationViewType.NoStack
items: ItemsOriginal
footerItems:ItemsFooter
@ -201,11 +199,9 @@ CustomWindow {
}
}
autoSuggestBox:FluAutoSuggestBox{
width: 280
anchors.centerIn: parent
iconSource: FluentIcons.Search
items: ItemsOriginal.getSearchData()
placeholderText: lang.search
placeholderText: Lang.search
onItemClicked:
(data)=>{
ItemsOriginal.startPageByItem(data)
@ -318,7 +314,7 @@ CustomWindow {
property string body
id:dialog_update
title:"升级提示"
message:"FluentUI目前最新版本 "+ newVerson +" -- 当前应用版本 "+appInfo.version+" \n现在是否去下载新版本\n\n更新内容\n"+body
message:"FluentUI目前最新版本 "+ newVerson +" -- 当前应用版本 "+AppInfo.version+" \n现在是否去下载新版本\n\n更新内容\n"+body
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
negativeText: "取消"
positiveText:"确定"
@ -340,9 +336,9 @@ CustomWindow {
onSuccess:
(result)=>{
var data = JSON.parse(result)
console.debug("current version "+appInfo.version)
console.debug("current version "+AppInfo.version)
console.debug("new version "+data.tag_name)
if(data.tag_name !== appInfo.version){
if(data.tag_name !== AppInfo.version){
dialog_update.newVerson = data.tag_name
dialog_update.body = data.body
dialog_update.open()

View File

@ -5,7 +5,7 @@ import FluentUI
import example
import "qrc:///example/qml/component"
CustomWindow {
FluWindow {
id:window
width: 800

View File

@ -4,7 +4,7 @@ import QtQuick.Layouts
import FluentUI
import "qrc:///example/qml/component"
CustomWindow {
FluWindow {
id:window
title:"SingleInstance"

View File

@ -4,7 +4,7 @@ import QtQuick.Layouts
import FluentUI
import "qrc:///example/qml/component"
CustomWindow {
FluWindow {
id:window
title:"SingleTask"

View File

@ -4,7 +4,7 @@ import QtQuick.Layouts
import FluentUI
import "qrc:///example/qml/component"
CustomWindow {
FluWindow {
id:window
title:"Standard"

View File

@ -8,6 +8,20 @@ Window {
id: app
flags: Qt.SplashScreen
Connections{
target: FluTheme
function onDarkModeChanged(){
SettingsHelper.saveDarkMode(FluTheme.darkMode)
}
}
Connections{
target: FluApp
function onVsyncChanged(){
SettingsHelper.saveVsync(FluApp.vsync)
}
}
FluHttpInterceptor{
id:interceptor
function onIntercept(request){
@ -26,9 +40,9 @@ Window {
Component.onCompleted: {
FluApp.init(app)
FluTheme.darkMode = FluThemeType.System
FluApp.vsync = SettingsHelper.getVsync()
FluTheme.darkMode = SettingsHelper.getDarkMode()
FluTheme.enableAnimation = true
FluTheme.nativeText = true
FluApp.routes = {
"/":"qrc:/example/qml/window/MainWindow.qml",
"/about":"qrc:/example/qml/window/AboutWindow.qml",

View File

@ -80,7 +80,6 @@ FluExpander{
"FluIcon",
"FluIconButton",
"FluInfoBar",
"FluItem",
"FluMediaPlayer",
"FluMenu",
"FluMenuItem",
@ -140,7 +139,8 @@ FluExpander{
"FluRangeSlider",
"FluStaggeredView",
"FluProgressButton",
"FluLoadingButton"
"FluLoadingButton",
"FluClip"
];
code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;");

View File

@ -1,64 +0,0 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import FluentUI 1.0
import org.wangwenx190.FramelessHelper 1.0
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
visible: window.appBarVisible
icon:"qrc:/example/res/image/favicon.ico"
anchors {
top: parent.top
left: parent.left
right: parent.right
}
darkText: lang.dark_mode
}
Item{
id:container
anchors{
top: title_bar.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
clip: true
}
FramelessHelper{
id:framless_helper
onReady: {
setTitleBarItem(title_bar)
moveWindowToDesktopCenter()
setHitTestVisible(title_bar.minimizeButton())
setHitTestVisible(title_bar.maximizeButton())
setHitTestVisible(title_bar.closeButton())
setWindowFixedSize(fixSize)
title_bar.maximizeButton.visible = !fixSize
if (blurBehindWindowEnabled)
window.background = undefined
window.show()
}
}
Connections{
target: FluTheme
function onDarkChanged(){
if (FluTheme.dark)
FramelessUtils.systemTheme = FramelessHelperConstants.Dark
else
FramelessUtils.systemTheme = FramelessHelperConstants.Light
}
}
function setHitTestVisible(com){
framless_helper.setHitTestVisible(com)
}
function setTitleBarItem(com){
framless_helper.setTitleBarItem(com)
}
}

View File

@ -12,7 +12,7 @@ FluObject{
FluPaneItemSeparator{}
FluPaneItem{
title:lang.about
title:Lang.about
icon:FluentIcons.Contact
onDropped: { FluApp.navigate("/about") }
onTapListener:function(){
@ -21,7 +21,7 @@ FluObject{
}
FluPaneItem{
title:lang.settings
title:Lang.settings
icon:FluentIcons.Settings
url:"qrc:/example/qml/page/T_Settings.qml"
onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) }

View File

@ -16,7 +16,7 @@ FluObject{
FluPaneItem{
id:item_home
count: 9
title:lang.home
title:Lang.home
infoBadge:FluBadge{
count: item_home.count
}
@ -45,9 +45,15 @@ FluObject{
}
}
FluPaneItemExpander{
title:"PaneItemExpander Disabled"
iconVisible: false
disabled: true
}
FluPaneItemExpander{
id:item_expander_basic_input
title:lang.basic_input
title:Lang.basic_input
icon:FluentIcons.CheckboxComposite
editDelegate: FluTextBox{
text:item_expander_basic_input.title
@ -129,10 +135,15 @@ FluObject{
onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) }
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:"PaneItem Disabled"
disabled: true
icon: FluentIcons.Error
}
}
FluPaneItemExpander{
title:lang.form
title:Lang.form
icon:FluentIcons.GridView
FluPaneItem{
title:"TextBox"
@ -167,7 +178,7 @@ FluObject{
}
FluPaneItemExpander{
title:lang.surface
title:Lang.surface
icon:FluentIcons.SurfaceHub
FluPaneItem{
title:"InfoBar"
@ -202,6 +213,12 @@ FluObject{
onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) }
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:"Clip"
url:"qrc:/example/qml/page/T_Clip.qml"
onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) }
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:"StatusView"
url:"qrc:/example/qml/page/T_StatusView.qml"
@ -235,7 +252,7 @@ FluObject{
}
FluPaneItemExpander{
title:lang.popus
title:Lang.popus
icon:FluentIcons.ButtonMenu
FluPaneItem{
title:"Dialog"
@ -273,7 +290,7 @@ FluObject{
}
FluPaneItemExpander{
title:lang.navigation
title:Lang.navigation
icon:FluentIcons.AllApps
FluPaneItem{
title:"Pivot"
@ -342,7 +359,7 @@ FluObject{
}
FluPaneItemExpander{
title:lang.theming
title:Lang.theming
icon:FluentIcons.Brightness
FluPaneItem{
title:"Acrylic"
@ -376,7 +393,7 @@ FluObject{
}
FluPaneItemExpander{
title:lang.other
title:Lang.other
icon:FluentIcons.Shop
FluPaneItem{
title:"QRCode"
@ -442,6 +459,12 @@ FluObject{
}
onDropped:{ FluApp.navigate("/hotload") }
}
FluPaneItem{
title:"3D"
url:"qrc:/example/qml/page/T_3D.qml"
onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) }
onTap:{ navigationView.push(url) }
}
}
function getRecentlyAddedData(){
@ -477,6 +500,9 @@ FluObject{
}
function getSearchData(){
if(!navigationView){
return
}
var arr = []
var items = navigationView.getItems();
for(var i=0;i<items.length;i++){

View File

@ -0,0 +1,77 @@
pragma Singleton
import QtQuick 2.15
QtObject {
property string home
property string basic_input
property string form
property string surface
property string popus
property string navigation
property string theming
property string media
property string dark_mode
property string sys_dark_mode
property string search
property string about
property string settings
property string locale
property string navigation_view_display_mode
property string other
function zh(){
home="首页"
basic_input="基本输入"
form="表单"
surface="表面"
popus="弹窗"
navigation="导航"
theming="主题"
media="媒体"
dark_mode="夜间模式"
sys_dark_mode="跟随系统"
search="查找"
about="关于"
settings="设置"
locale="语言环境"
navigation_view_display_mode="导航视图显示模式"
other="其他"
}
function en(){
home="Home"
basic_input="Basic Input"
form="Form"
surface="Surfaces"
popus="Popus"
navigation="Navigation"
theming="Theming"
media="Media"
dark_mode="Dark Mode"
sys_dark_mode="Sync with system"
search="Search"
about="About"
settings="Settings"
locale="Locale"
navigation_view_display_mode="NavigationView Display Mode"
other="Other"
}
property string __locale
property var __localeList: ["Zh","En"]
on__LocaleChanged: {
if(__locale === "Zh"){
zh()
}else{
en()
}
}
Component.onCompleted: {
__locale = "En"
}
}

View File

@ -1,2 +1,3 @@
singleton ItemsOriginal 1.0 ItemsOriginal.qml
singleton ItemsFooter 1.0 ItemsFooter.qml
singleton Lang 1.0 Lang.qml

121
example/qml/page/T_3D.qml Normal file
View File

@ -0,0 +1,121 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
import Qt3D.Core 2.15
import Qt3D.Render 2.15
import Qt3D.Input 2.12
import Qt3D.Extras 2.15
import QtQuick.Scene3D 2.15
import QtQuick.Dialogs 1.3
import Qt.labs.platform 1.1
import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
FluContentPage{
id:root
title:"3D"
Scene3D{
id:scene_3d
anchors.fill: parent
focus: true
aspects: ["input", "logic"]
cameraAspectRatioMode: Scene3D.AutomaticAspectRatio
Entity {
Camera {
id: camera
projectionType: CameraLens.PerspectiveProjection
fieldOfView: 22.5
aspectRatio: scene_3d.width / scene_3d.height
nearPlane: 1
farPlane: 1000.0
viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
position: Qt.vector3d( 0.0, 0.0, 15.0 )
}
FirstPersonCameraController {
linearSpeed: 100
lookSpeed: 50
camera: camera
}
components: [
RenderSettings{
activeFrameGraph: ForwardRenderer{
clearColor: Qt.rgba(0,0,0,0);
camera: camera
}
},
InputSettings{}
]
Mesh {
id: mesh
source: "https://zhu-zichu.gitee.io/test.obj"
}
PhongMaterial {
id: material
ambient: color_picker.colorValue
}
Transform{
id:transform
scale: 1.0
translation: Qt.vector3d(0, 0, 0)
rotation: fromEulerAngles(0, 0, 0)
property real hAngle:0.0
NumberAnimation on hAngle{
from:0
to:360.0
duration: 5000
loops: Animation.Infinite
}
matrix:{
var m=Qt.matrix4x4();
m.rotate(hAngle,Qt.vector3d(0,1,0));
m.translate(Qt.vector3d(0,0,0));
return m;
}
}
Entity {
id: entity
components: [mesh, material,transform]
}
}
}
ColumnLayout{
RowLayout{
spacing: 10
Layout.topMargin: 20
FluText{
text:"tintColor:"
Layout.alignment: Qt.AlignVCenter
}
FluColorPicker{
id:color_picker
enableAlphaChannel:false
Component.onCompleted: {
setColor("gray")
}
}
}
FluButton{
text:"选择obj资源"
onClicked: {
file_dialog.open()
}
}
}
FileDialog {
id: file_dialog
nameFilters: ["Obj files (*.obj)"]
folder: StandardPaths.writableLocation(StandardPaths.DocumentsLocation)
onAccepted: {
var fileUrl = file_dialog.currentFile
mesh.source = fileUrl
}
}
}

View File

@ -48,7 +48,7 @@ FluScrollablePage{
height: 1200/4+20
paddings: 10
Layout.topMargin: 10
FluRectangle{
FluClip{
width: 1920/4
height: 1200/4
radius:[8,8,8,8]

View File

@ -25,7 +25,7 @@ FluContentPage {
leftMargin: 14
}
onClicked: {
grid_view.model = FluApp.awesomelist(text_box.text)
grid_view.model = FluTheme.awesomeList(text_box.text)
}
}
GridView{
@ -34,7 +34,7 @@ FluContentPage {
cellHeight: 80
clip: true
boundsBehavior: GridView.StopAtBounds
model:FluApp.awesomelist()
model:FluTheme.awesomeList()
ScrollBar.vertical: FluScrollBar {}
anchors{
topMargin: 10

View File

@ -37,7 +37,7 @@ FluScrollablePage{
left: parent.left
}
FluCalendarPicker{
current:Date.fromLocaleString("2013年7月11日 21:17:42")
current:new Date()
onAccepted:{
showSuccess(current.toLocaleString())
}

View File

@ -45,7 +45,6 @@ FluScrollablePage{
}
FluCarousel{
anchors.fill: parent
radius:[8,8,8,8]
delegate: Component{
Image {
anchors.fill: parent
@ -83,7 +82,6 @@ FluScrollablePage{
}
FluCarousel{
anchors.fill: parent
radius:[8,8,8,8]
loopTime:1500
indicatorGravity: Qt.AlignHCenter | Qt.AlignTop
indicatorMarginTop:15

View File

@ -12,27 +12,35 @@ FluScrollablePage{
FluArea{
Layout.fillWidth: true
height: 68
height: 72
paddings: 10
Layout.topMargin: 20
FluText{
text:"A 2-state CheckBox"
}
Row{
spacing: 30
anchors.verticalCenter: parent.verticalCenter
FluCheckBox{
disabled: check_box_switch.checked
anchors{
top: parent.top
topMargin: 30
}
FluCheckBox{
disabled: check_box_switch.checked
disabled: check_box_switch_two.checked
}
FluCheckBox{
disabled: check_box_switch_two.checked
text:"Right"
}
FluCheckBox{
disabled: check_box_switch.checked
disabled: check_box_switch_two.checked
text:"Left"
textRight: false
}
}
FluToggleSwitch{
id:check_box_switch
id:check_box_switch_two
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
@ -48,4 +56,60 @@ FluScrollablePage{
}'
}
FluArea{
Layout.fillWidth: true
height: 72
paddings: 10
Layout.topMargin: 20
FluText{
text:"A 3-state CheckBox"
}
Row{
spacing: 30
anchors{
top: parent.top
topMargin: 30
}
FluCheckBox{
property int count: 1
text:"Three State"
disabled: check_box_switch_three.checked
clickListener: function(){
var flag = count%3
if(flag === 0){
checked = false
indeterminate = false
}
if(flag === 1){
checked = true
indeterminate = false
}
if(flag === 2){
checked = true
indeterminate = true
}
count++
}
}
}
FluToggleSwitch{
id:check_box_switch_three
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
}
text:"Disabled"
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluCheckBox{
text:"Text"
indeterminate:true
}'
}
}

108
example/qml/page/T_Clip.qml Normal file
View File

@ -0,0 +1,108 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
import FluentUI 1.0
import "../component"
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Clip"
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 380
paddings: 10
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluText{
text:"配合图片使用(software渲染下该组件将没有效果)"
font: FluTextStyle.Subtitle
Layout.topMargin: 20
}
RowLayout{
spacing: 14
FluClip{
width: 50
height: 50
radius:[25,0,25,25]
Image {
asynchronous: true
anchors.fill: parent
source: "qrc:/example/res/svg/avatar_1.svg"
sourceSize: Qt.size(width,height)
}
}
FluClip{
width: 50
height: 50
radius:[10,10,10,10]
Image {
asynchronous: true
anchors.fill: parent
sourceSize: Qt.size(width,height)
source: "qrc:/example/res/svg/avatar_2.svg"
}
}
FluClip{
width: 50
height: 50
radius:[25,25,25,25]
Image {
asynchronous: true
anchors.fill: parent
sourceSize: Qt.size(width,height)
source: "qrc:/example/res/svg/avatar_3.svg"
}
}
FluClip{
width: 50
height: 50
radius:[0,25,25,25]
Image {
asynchronous: true
anchors.fill: parent
sourceSize: Qt.size(width,height)
source: "qrc:/example/res/svg/avatar_4.svg"
}
}
}
FluClip{
width: 1920/5
height: 1200/5
radius:[8,8,8,8]
Image {
asynchronous: true
source: "qrc:/example/res/image/banner_1.jpg"
anchors.fill: parent
sourceSize: Qt.size(2*width,2*height)
}
Layout.topMargin: 20
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluClip{
radius: [25,25,25,25]
width: 50
height: 50
Image{
asynchronous: true
anchors.fill: parent
source: "qrc:/example/res/svg/avatar_4.svg"
sourceSize: Qt.size(width,height)
}
}'
}
}

View File

@ -47,7 +47,6 @@ FluScrollablePage{
}
FluComboBox {
editable: true
font:FluTextStyle.BodyStrong
model: ListModel {
id: model_2
ListElement { text: "Banana" }

View File

@ -59,6 +59,7 @@ FluScrollablePage{
width: parent.width
height: parent.height
contentWidth: width
boundsBehavior: Flickable.StopAtBounds
contentHeight: text_info.height
ScrollBar.vertical: FluScrollBar {}
FluText{

View File

@ -2,6 +2,7 @@ import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtGraphicalEffects 1.0
import "qrc:///example/qml/global"
import FluentUI 1.0
@ -50,23 +51,9 @@ FluScrollablePage{
}
}
ListView{
id: list
anchors{
left: parent.left
right: parent.right
bottom: parent.bottom
}
orientation: ListView.Horizontal
height: 240
model: model_header
header: Item{height: 10;width: 10}
footer: Item{height: 10;width: 10}
ScrollBar.horizontal: FluScrollBar{
id: scrollbar_header
}
clip: false
delegate:Item{
Component{
id:com_grallery
Item{
id: control
width: 220
height: 240
@ -74,7 +61,7 @@ FluScrollablePage{
radius:5
anchors.fill: item_content
}
FluItem{
FluClip{
id:item_content
radius: [5,5,5,5]
width: 200
@ -91,19 +78,14 @@ FluScrollablePage{
Rectangle{
anchors.fill: parent
radius: 5
color:{
if(FluTheme.dark){
if(item_mouse.containsMouse){
return Qt.rgba(1,1,1,0.03)
}
return Qt.rgba(0,0,0,0.0)
}else{
if(item_mouse.containsMouse){
return Qt.rgba(0,0,0,0.03)
}
return Qt.rgba(0,0,0,0.0)
}
}
color:FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03)
visible: item_mouse.containsMouse
}
Rectangle{
anchors.fill: parent
radius: 5
color:Qt.rgba(0,0,0,0.0)
visible: !item_mouse.containsMouse
}
ColumnLayout{
Image {
@ -155,11 +137,31 @@ FluScrollablePage{
}
}
}
ListView{
id: list
anchors{
left: parent.left
right: parent.right
bottom: parent.bottom
}
orientation: ListView.Horizontal
height: 240
model: model_header
header: Item{height: 10;width: 10}
footer: Item{height: 10;width: 10}
ScrollBar.horizontal: FluScrollBar{
id: scrollbar_header
}
clip: false
delegate: com_grallery
}
}
Component{
id:com_item
Item{
property string desc: modelData.desc
width: 320
height: 120
FluArea{
@ -195,7 +197,6 @@ FluScrollablePage{
verticalCenter: parent.verticalCenter
}
}
FluText{
id:item_title
text:modelData.title
@ -206,10 +207,9 @@ FluScrollablePage{
top: item_icon.top
}
}
FluText{
id:item_desc
text:modelData.desc
text:desc
color:FluColors.Grey120
wrapMode: Text.WrapAnywhere
elide: Text.ElideRight

View File

@ -11,7 +11,7 @@ import "../component"
FluContentPage{
title:"Http"
property string cacheDirPath: FluTools.getApplicationDirPath() + "/cache/http"
property string cacheDirPath: StandardPaths.writableLocation(StandardPaths.AppLocalDataLocation) + "/cache/http"
property bool isDownCompleted: false
FluHttp{
@ -101,6 +101,9 @@ FluContentPage{
params.custtel = "1234567890"
params.custemail = "zhuzichu520@gmail.com"
request.params = params
var headers = {}
headers.test = "123456789456465321354"
request.headers = headers
http.post(request,callable)
}
}
@ -128,6 +131,15 @@ FluContentPage{
http.postString(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Delete请求"
onClicked: {
var request = http.newRequest("https://httpbingo.org/delete")
http.deleteResource(request,callable)
}
}
FluProgressButton{
id:btn_download
implicitWidth: parent.width
@ -265,7 +277,7 @@ FluContentPage{
implicitHeight: 36
text: "打开缓存路径"
onClicked: {
Qt.openUrlExternally("file:///"+cacheDirPath)
Qt.openUrlExternally(cacheDirPath)
}
}
FluButton{

View File

@ -13,7 +13,7 @@ FluScrollablePage{
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 240
height: 270
paddings: 10
ColumnLayout{
spacing: 14
@ -45,6 +45,12 @@ FluScrollablePage{
showSuccess("这是一个Success样式的InfoBar这是一个Success样式的InfoBar")
}
}
FluButton{
text:"手动关闭的InfoBar"
onClicked: {
showInfo("这是一个Info样式的InfoBar",0,"支持手动关闭")
}
}
FluButton{
text:"Loading"
onClicked: {

View File

@ -3,7 +3,6 @@ import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import FluentUI 1.0
import QtGraphicalEffects 1.15
import "qrc:///example/qml/component"
import "../component"

View File

@ -13,16 +13,15 @@ FluScrollablePage{
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 460
height: 80
paddings: 10
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
verticalCenter: parent.verticalCenter
}
RowLayout{
Layout.topMargin: 20
FluRectangle{
@ -62,70 +61,6 @@ FluScrollablePage{
radius:[0,0,0,15]
}
}
FluText{
text:"配合图片使用"
font: FluTextStyle.Subtitle
Layout.topMargin: 20
}
RowLayout{
spacing: 14
FluRectangle{
width: 50
height: 50
radius:[25,0,25,25]
Image {
asynchronous: true
anchors.fill: parent
source: "qrc:/example/res/svg/avatar_1.svg"
sourceSize: Qt.size(width,height)
}
}
FluRectangle{
width: 50
height: 50
radius:[10,10,10,10]
Image {
asynchronous: true
anchors.fill: parent
sourceSize: Qt.size(width,height)
source: "qrc:/example/res/svg/avatar_2.svg"
}
}
FluRectangle{
width: 50
height: 50
radius:[25,25,25,25]
Image {
asynchronous: true
anchors.fill: parent
sourceSize: Qt.size(width,height)
source: "qrc:/example/res/svg/avatar_3.svg"
}
}
FluRectangle{
width: 50
height: 50
radius:[0,25,25,25]
Image {
asynchronous: true
anchors.fill: parent
sourceSize: Qt.size(width,height)
source: "qrc:/example/res/svg/avatar_4.svg"
}
}
}
FluRectangle{
width: 1920/5
height: 1200/5
radius:[8,8,8,8]
Image {
asynchronous: true
source: "qrc:/example/res/image/banner_1.jpg"
anchors.fill: parent
sourceSize: Qt.size(2*width,2*height)
}
Layout.topMargin: 20
}
}
}
CodeExpander{
@ -135,14 +70,6 @@ FluScrollablePage{
radius: [25,25,25,25]
width: 50
height: 50
Image{
asynchronous: true
anchors.fill: parent
source: "qrc:/example/res/svg/avatar_4.svg"
sourceSize: Qt.size(width,height)
}
}'
}
}

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import Qt.labs.platform 1.0
import "qrc:///example/qml/component"
import "../component"
@ -48,7 +49,7 @@ FluScrollablePage{
FluScreenshot{
id:screenshot
captrueMode: FluScreenshotType.File
saveFolder: FluTools.getApplicationDirPath()+"/screenshot"
saveFolder: StandardPaths.writableLocation(StandardPaths.AppLocalDataLocation)+"/screenshot"
onCaptrueCompleted:
(captrue)=>{
image.source = captrue

View File

@ -43,7 +43,7 @@ FluScrollablePage{
spacing: 20
anchors.verticalCenter: parent.verticalCenter
FluText{
text:"当前版本 v%1".arg(appInfo.version)
text:"当前版本 v%1".arg(AppInfo.version)
font: FluTextStyle.Body
anchors.verticalCenter: parent.verticalCenter
}
@ -59,6 +59,54 @@ FluScrollablePage{
}
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 50
paddings: 10
FluCheckBox{
text:"V-Sync"
checked: FluApp.vsync
anchors.verticalCenter: parent.verticalCenter
onClicked: {
FluApp.vsync = !FluApp.vsync
dialog_restart.open()
}
}
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 50
paddings: 10
FluCheckBox{
text:"Software Render"
checked: SettingsHelper.getRender() === "software"
anchors.verticalCenter: parent.verticalCenter
onClicked: {
if(SettingsHelper.getRender() === "software"){
SettingsHelper.saveRender("")
}else{
SettingsHelper.saveRender("software")
}
dialog_restart.open()
}
}
}
FluContentDialog{
id:dialog_restart
title:"友情提示"
message:"此操作需要重启才能生效,是否重新启动?"
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
negativeText: "取消"
positiveText:"确定"
onPositiveClicked:{
FluApp.exit(931)
}
}
FluArea{
Layout.fillWidth: true
@ -73,7 +121,7 @@ FluScrollablePage{
left: parent.left
}
FluText{
text:lang.dark_mode
text:Lang.dark_mode
font: FluTextStyle.BodyStrong
Layout.bottomMargin: 4
}
@ -103,7 +151,7 @@ FluScrollablePage{
left: parent.left
}
FluText{
text:lang.navigation_view_display_mode
text:Lang.navigation_view_display_mode
font: FluTextStyle.BodyStrong
Layout.bottomMargin: 4
}
@ -134,7 +182,7 @@ FluScrollablePage{
}
FluText{
text:lang.locale
text:Lang.locale
font: FluTextStyle.BodyStrong
Layout.bottomMargin: 4
}
@ -142,12 +190,12 @@ FluScrollablePage{
Flow{
spacing: 5
Repeater{
model: ["Zh","En"]
model: Lang.__localeList
delegate: FluRadioButton{
checked: appInfo.lang.objectName === modelData
checked: Lang.__locale === modelData
text:modelData
clickListener:function(){
appInfo.changeLang(modelData)
Lang.__locale = modelData
}
}
}

View File

@ -8,12 +8,45 @@ import "../component"
FluContentPage{
id:root
title:"TableView"
signal checkBoxChanged
property var dataSource : []
property int sortType: 0
Component.onCompleted: {
loadData(1,1000)
}
onSortTypeChanged: {
table_view.closeEditor()
if(sortType === 0){
table_view.sort()
}else if(sortType === 1){
table_view.sort((a, b) => a.age - b.age);
}else if(sortType === 2){
table_view.sort((a, b) => b.age - a.age);
}
}
Component{
id:com_checbox
Item{
FluCheckBox{
anchors.centerIn: parent
checked: true === options.checked
enableAnimation: false
clickListener: function(){
var obj = tableModel.getRow(row)
obj.checkbox = table_view.customItem(com_checbox,{checked:!options.checked})
tableModel.setRow(row,obj)
checkBoxChanged()
}
}
}
}
Component{
id:com_action
Item{
@ -24,11 +57,15 @@ FluContentPage{
onClicked: {
table_view.closeEditor()
tableModel.removeRow(row)
checkBoxChanged()
}
}
FluFilledButton{
text:"编辑"
onClicked: {
var obj = tableModel.getRow(row)
obj.name = "12345"
tableModel.setRow(row,obj)
showSuccess(JSON.stringify(tableModel.getRow(row)))
}
}
@ -36,39 +73,44 @@ FluContentPage{
}
}
function loadData(page,count){
var numbers = [100, 300, 500, 1000];
function getRandomAge() {
var randomIndex = Math.floor(Math.random() * numbers.length);
return numbers[randomIndex];
Component{
id:com_column_checbox
Item{
RowLayout{
anchors.centerIn: parent
FluText{
text:"全选"
Layout.alignment: Qt.AlignVCenter
}
FluCheckBox{
checked: true === options.checked
enableAnimation: false
Layout.alignment: Qt.AlignVCenter
clickListener: function(){
var checked = !options.checked
itemModel.display = table_view.customItem(com_column_checbox,{"checked":checked})
for(var i =0;i< tableModel.rowCount ;i++){
var rowData = tableModel.getRow(i)
rowData.checkbox = table_view.customItem(com_checbox,{"checked":checked})
tableModel.setRow(i,rowData)
}
}
}
Connections{
target: root
function onCheckBoxChanged(){
for(var i =0;i< tableModel.rowCount ;i++){
if(false === tableModel.getRow(i).checkbox.options.checked){
itemModel.display = table_view.customItem(com_column_checbox,{"checked":false})
return
}
}
itemModel.display = table_view.customItem(com_column_checbox,{"checked":true})
}
}
}
}
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: getRandomName(),
age:getRandomAge(),
address: getRandomAddresses(),
nickname: getRandomNickname(),
longstring:"你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好",
action:com_action
})
}
table_view.dataSource = dataSource
}
Component{
@ -95,6 +137,88 @@ FluContentPage{
}
}
Component{
id:com_avatar
Item{
FluClip{
anchors.centerIn: parent
width: 40
height: 40
radius: [20,20,20,20]
Image{
anchors.fill: parent
source: {
if(options && options.avatar){
return options.avatar
}
return ""
}
sourceSize: Qt.size(80,80)
}
}
}
}
Component{
id:com_column_sort_age
Item{
FluText{
text:"年龄"
anchors.centerIn: parent
}
ColumnLayout{
spacing: 0
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
rightMargin: 4
}
FluIconButton{
Layout.preferredWidth: 20
Layout.preferredHeight: 15
iconSize: 12
verticalPadding:0
horizontalPadding:0
iconSource: FluentIcons.ChevronUp
iconColor: {
if(1 === root.sortType){
return FluTheme.primaryColor.dark
}
return FluTheme.dark ? Qt.rgba(1,1,1,1) : Qt.rgba(0,0,0,1)
}
onClicked: {
if(root.sortType === 1){
root.sortType = 0
return
}
root.sortType = 1
}
}
FluIconButton{
Layout.preferredWidth: 20
Layout.preferredHeight: 15
iconSize: 12
verticalPadding:0
horizontalPadding:0
iconSource: FluentIcons.ChevronDown
iconColor: {
if(2 === root.sortType){
return FluTheme.primaryColor.dark
}
return FluTheme.dark ? Qt.rgba(1,1,1,1) : Qt.rgba(0,0,0,1)
}
onClicked: {
if(root.sortType === 2){
root.sortType = 0
return
}
root.sortType = 2
}
}
}
}
}
FluTableView{
id:table_view
anchors{
@ -105,13 +229,27 @@ FluContentPage{
}
anchors.topMargin: 20
columnSource:[
{
title: table_view.customItem(com_column_checbox,{checked:true}),
dataIndex: 'checkbox',
width:80,
minimumWidth:80,
maximumWidth:80,
},
{
title: '头像',
dataIndex: 'avatar',
width:100,
minimumWidth:100,
maximumWidth:100
},
{
title: '姓名',
dataIndex: 'name',
readOnly:true,
},
{
title: '年龄',
title: table_view.customItem(com_column_sort_age,{sort:0}),
dataIndex: 'age',
editDelegate:com_combobox,
width:100,
@ -167,6 +305,50 @@ FluContentPage{
}
}
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];
}
var avatars = ["qrc:/example/res/svg/avatar_1.svg", "qrc:/example/res/svg/avatar_2.svg", "qrc:/example/res/svg/avatar_3.svg", "qrc:/example/res/svg/avatar_4.svg","qrc:/example/res/svg/avatar_5.svg","qrc:/example/res/svg/avatar_6.svg","qrc:/example/res/svg/avatar_7.svg","qrc:/example/res/svg/avatar_8.svg","qrc:/example/res/svg/avatar_9.svg","qrc:/example/res/svg/avatar_10.svg","qrc:/example/res/svg/avatar_11.svg","qrc:/example/res/svg/avatar_12.svg"];
function getAvatar(){
var randomIndex = Math.floor(Math.random() * avatars.length);
return avatars[randomIndex];
}
const dataSource = []
for(var i=0;i<count;i++){
dataSource.push({
checkbox: table_view.customItem(com_checbox,{checked:true}),
avatar:table_view.customItem(com_avatar,{avatar:getAvatar()}),
name: getRandomName(),
age:getRandomAge(),
address: getRandomAddresses(),
nickname: getRandomNickname(),
longstring:"你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好",
action: table_view.customItem(com_action),
minimumHeight:50
})
}
root.dataSource = dataSource
table_view.dataSource = root.dataSource
}
}

View File

@ -85,7 +85,7 @@ FluScrollablePage{
text:"找到一份Android外包开发岗位开发了一个Android应用满满成就感前端、服务端、Flutter也都懂一丢丢什么都会什么都不精通钱途无望"
}
ListElement{
lable:"2020-06-01"
lable:"2021-06-01"
text:"由于某个项目紧急临时加入Qt项目组就因为大学学了点C++),本来是想进去打个酱油,到后面竟然成开发主力,坑啊"
}
ListElement{

View File

@ -6,152 +6,127 @@ import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
FluScrollablePage {
FluContentPage {
title:"TreeView"
function randomName() {
var names = ["张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"]
return names[Math.floor(Math.random() * names.length)]
function treeData(){
const dig = (path = '0', level = 4) => {
const list = [];
for (let i = 0; i < 6; i += 1) {
const key = `${path}-${i}`;
const treeNode = {
title: key,
key,
};
if (level > 0) {
treeNode.children = dig(key, level - 1);
}
list.push(treeNode);
}
return list;
};
return dig();
}
function randomCompany() {
var companies = ["阿里巴巴", "腾讯", "百度", "京东", "华为", "小米", "字节跳动", "美团", "滴滴"]
return companies[Math.floor(Math.random() * companies.length)]
}
function randomDepartment() {
var departments = ["技术部", "销售部", "市场部", "人事部", "财务部", "客服部", "产品部", "设计部", "运营部"]
return departments[Math.floor(Math.random() * departments.length)]
}
function createEmployee() {
var name = randomName()
return tree_view.createItem(name, false)
}
function createSubtree(numEmployees) {
var employees = []
for (var i = 0; i < numEmployees; i++) {
employees.push(createEmployee())
Column{
id:layout_column
spacing: 12
width: 300
anchors{
topMargin: 20
top:parent.top
left: parent.left
leftMargin: 10
bottom:parent.bottom
bottomMargin: 20
}
return tree_view.createItem(randomDepartment(), true, employees)
}
function createOrg(numLevels, numSubtrees, numEmployees) {
if (numLevels === 0) {
return []
FluText{
text:"共计%1条数据当前显示的%2条数据".arg(tree_view.count()).arg(tree_view.visibleCount())
}
FluText{
text:"共计选中%1条数据".arg(tree_view.selectionModel().length)
}
var subtrees = []
for (var i = 0; i < numSubtrees; i++) {
subtrees.push(createSubtree(numEmployees))
}
return [tree_view.createItem(randomCompany(), true, subtrees)].concat(createOrg(numLevels - 1, numSubtrees, numEmployees))
}
FluArea{
id:layout_actions
Layout.fillWidth: true
Layout.topMargin: 20
height: 50
paddings: 10
RowLayout{
spacing: 14
FluDropDownButton{
id:btn_selection_model
Layout.preferredWidth: 140
text:"None"
FluMenuItem{
text:"None"
onClicked: {
btn_selection_model.text = text
tree_view.selectionMode = FluTabViewType.Equal
}
}
FluMenuItem{
text:"Single"
onClicked: {
btn_selection_model.text = text
tree_view.selectionMode = FluTabViewType.SizeToContent
}
}
FluMenuItem{
text:"Muiltple"
onClicked: {
btn_selection_model.text = text
tree_view.selectionMode = FluTabViewType.Compact
}
}
spacing: 10
FluText{
text:"cellHeight:"
Layout.alignment: Qt.AlignVCenter
}
FluFilledButton{
text:"获取选中的数据"
onClicked: {
if(tree_view.selectionMode === FluTreeViewType.None){
showError("当前非选择模式,没有选中的数据")
}
if(tree_view.selectionMode === FluTreeViewType.Single){
if(!tree_view.signleData()){
showError("没有选中数据")
return
}
showSuccess(tree_view.signleData().text)
}
if(tree_view.selectionMode === FluTreeViewType.Multiple){
if(tree_view.multipData().length===0){
showError("没有选中数据")
return
}
var info = []
tree_view.multipData().map((value)=>info.push(value.text))
showSuccess(info.join(","))
}
}
FluSlider{
id:slider_cell_height
value: 30
from: 30
to:100
}
}
RowLayout{
spacing: 10
FluText{
text:"depthPadding:"
Layout.alignment: Qt.AlignVCenter
}
FluSlider{
id:slider_depth_padding
value: 30
from: 30
to:100
}
}
FluToggleSwitch{
id:switch_showline
text:"showLine"
checked: false
}
FluToggleSwitch{
id:switch_draggable
text:"draggable"
checked: false
}
FluToggleSwitch{
id:switch_checkable
text:"checkable"
checked: false
}
FluButton{
text:"all expand"
onClicked: {
tree_view.allExpand()
}
}
FluButton{
text:"all collapse"
onClicked: {
tree_view.allCollapse()
}
}
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 10
paddings: 10
height: 400
anchors{
left: layout_column.right
top: parent.top
bottom: parent.bottom
right: parent.right
rightMargin: 5
topMargin: 5
bottomMargin: 5
}
FluShadow{}
FluTreeView{
id:tree_view
width:240
anchors{
top:parent.top
left:parent.left
bottom:parent.bottom
}
onItemClicked:
(model)=>{
showSuccess(model.text)
}
anchors.fill: parent
cellHeight: slider_cell_height.value
draggable:switch_draggable.checked
showLine: switch_showline.checked
checkable:switch_checkable.checked
depthPadding: slider_depth_padding.value
Component.onCompleted: {
var org = createOrg(3, 3, 3)
createItem()
updateData(org)
var data = treeData()
dataSource = data
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluTreeView{
id:tree_view
width:240
height:600
Component.onCompleted: {
var datas = []
datas.push(createItem("Node1",false))
datas.push(createItem("Node2",false))
datas.push(createItem("Node2",true,[createItem("Node2-1",false),createItem("Node2-2",false)]))
updateData(datas)
}
}
'
}
}

View File

@ -5,7 +5,7 @@ import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
CustomWindow {
FluWindow {
id:window
title:"关于"
@ -36,7 +36,7 @@ CustomWindow {
}
}
FluText{
text:"v%1".arg(appInfo.version)
text:"v%1".arg(AppInfo.version)
font: FluTextStyle.Body
Layout.alignment: Qt.AlignBottom
}

View File

@ -6,7 +6,7 @@ import example 1.0
import "qrc:///example/qml/component"
import "../component"
CustomWindow {
FluWindow {
id:window
title:"热加载"

View File

@ -5,7 +5,7 @@ import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
CustomWindow {
FluWindow {
id:window
title:"登录"

View File

@ -12,7 +12,7 @@ import "../component"
import "../viewmodel"
import "../global"
CustomWindow {
FluWindow {
id:window
title: "FluentUI"
@ -21,14 +21,14 @@ CustomWindow {
closeDestory:false
minimumWidth: 520
minimumHeight: 200
appBarVisible: false
launchMode: FluWindowType.SingleTask
appBar: undefined
SettingsViewModel{
id:viewmodel_settings
}
closeFunc:function(event){
closeListener:function(event){
dialog_close.open()
event.accepted = false
}
@ -61,8 +61,7 @@ CustomWindow {
MenuItem {
text: "退出"
onTriggered: {
window.deleteWindow()
FluApp.closeApp()
FluApp.exit()
}
}
}
@ -89,8 +88,7 @@ CustomWindow {
positiveText:"退出"
neutralText:"取消"
onPositiveClicked:{
window.deleteWindow()
FluApp.closeApp()
FluApp.exit()
}
}
@ -123,7 +121,7 @@ CustomWindow {
left: parent.left
right: parent.right
}
darkText: lang.dark_mode
darkText: Lang.dark_mode
showDark: true
z:7
darkClickListener:(button)=>handleDarkChanged(button)
@ -173,7 +171,7 @@ CustomWindow {
left: parent.left
right: parent.right
}
darkText: lang.dark_mode
darkText: Lang.dark_mode
showDark: true
darkClickListener:(button)=>handleDarkChanged(button)
z:7
@ -186,7 +184,7 @@ CustomWindow {
z:999
//Stack模式每次切换都会将页面压入栈中随着栈的页面增多消耗的内存也越多内存消耗多就会卡顿这时候就需要按返回将页面pop掉释放内存。该模式可以配合FluPage中的launchMode属性设置页面的启动模式
// pageMode: FluNavigationViewType.Stack
//NoStack模式每次切换都会销毁之前的页面然后创建一个新的页面只需消耗少量内存推荐
//NoStack模式每次切换都会销毁之前的页面然后创建一个新的页面只需消耗少量内存可以配合FluViewModel保存页面数据(推荐)
pageMode: FluNavigationViewType.NoStack
items: ItemsOriginal
footerItems:ItemsFooter
@ -204,11 +202,9 @@ CustomWindow {
}
}
autoSuggestBox:FluAutoSuggestBox{
width: 280
anchors.centerIn: parent
iconSource: FluentIcons.Search
items: ItemsOriginal.getSearchData()
placeholderText: lang.search
placeholderText: Lang.search
onItemClicked:
(data)=>{
ItemsOriginal.startPageByItem(data)
@ -321,7 +317,7 @@ CustomWindow {
property string body
id:dialog_update
title:"升级提示"
message:"FluentUI目前最新版本 "+ newVerson +" -- 当前应用版本 "+appInfo.version+" \n现在是否去下载新版本\n\n更新内容\n"+body
message:"FluentUI目前最新版本 "+ newVerson +" -- 当前应用版本 "+AppInfo.version+" \n现在是否去下载新版本\n\n更新内容\n"+body
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
negativeText: "取消"
positiveText:"确定"
@ -343,9 +339,9 @@ CustomWindow {
onSuccess:
(result)=>{
var data = JSON.parse(result)
console.debug("current version "+appInfo.version)
console.debug("current version "+AppInfo.version)
console.debug("new version "+data.tag_name)
if(data.tag_name !== appInfo.version){
if(data.tag_name !== AppInfo.version){
dialog_update.newVerson = data.tag_name
dialog_update.body = data.body
dialog_update.open()

View File

@ -6,7 +6,7 @@ import example 1.0
import "qrc:///example/qml/component"
import "../component"
CustomWindow {
FluWindow {
id:window
width: 800

View File

@ -5,7 +5,7 @@ import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
CustomWindow {
FluWindow {
id:window
title:"SingleInstance"

View File

@ -5,7 +5,7 @@ import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
CustomWindow {
FluWindow {
id:window
title:"SingleTask"

View File

@ -5,7 +5,7 @@ import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
CustomWindow {
FluWindow {
id:window
title:"Standard"

View File

@ -2,36 +2,15 @@
#include <QQmlContext>
#include <QDebug>
#include "lang/En.h"
#include "lang/Zh.h"
#include <QGuiApplication>
#include "Version.h"
AppInfo::AppInfo(QObject *parent)
: QObject{parent}
{
version(APPLICATION_VERSION);
lang(new En());
}
void AppInfo::init(QQmlApplicationEngine *engine){
QQmlContext * context = engine->rootContext();
Lang* lang = this->lang();
context->setContextProperty("lang",lang);
QObject::connect(this,&AppInfo::langChanged,this,[=]{
context->setContextProperty("lang",this->lang());
});
context->setContextProperty("appInfo",this);
}
void AppInfo::changeLang(const QString& locale){
if(_lang){
_lang->deleteLater();
}
if(locale=="Zh"){
lang(new Zh());
}else if(locale=="En"){
lang(new En());
}else {
lang(new En());
}
engine->rootContext();
}

View File

@ -3,18 +3,18 @@
#include <QObject>
#include <QQmlApplicationEngine>
#include "lang/Lang.h"
#include "stdafx.h"
#include "singleton.h"
class AppInfo : public QObject
{
Q_OBJECT
Q_PROPERTY_AUTO(QString,version)
Q_PROPERTY_AUTO(Lang*,lang)
public:
private:
explicit AppInfo(QObject *parent = nullptr);
public:
SINGLETONG(AppInfo)
void init(QQmlApplicationEngine *engine);
Q_INVOKABLE void changeLang(const QString& locale);
};
#endif // APPINFO_H

View File

@ -0,0 +1,41 @@
#include "SettingsHelper.h"
#include <QDataStream>
#include <QStandardPaths>
SettingsHelper::SettingsHelper(QObject *parent) : QObject(parent)
{
}
SettingsHelper::~SettingsHelper() = default;
void SettingsHelper::save(const QString& key,QVariant val)
{
QByteArray data = {};
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_6);
stream << val;
m_settings->setValue(key, data);
}
QVariant SettingsHelper::get(const QString& key){
const QByteArray data = m_settings->value(key).toByteArray();
if (data.isEmpty()) {
return {};
}
QDataStream stream(data);
stream.setVersion(QDataStream::Qt_5_6);
QVariant val;
stream >> val;
return val;
}
void SettingsHelper::init(char *argv[]){
auto applicationPath = QString::fromStdString(argv[0]);
const QFileInfo fileInfo(applicationPath);
const QString iniFileName = fileInfo.completeBaseName() + ".ini";
const QString iniFilePath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/" + iniFileName;
qDebug()<<"Application configuration file path->"<<iniFilePath;
m_settings.reset(new QSettings(iniFilePath, QSettings::IniFormat));
}

View File

@ -0,0 +1,35 @@
#ifndef SETTINGSHELPER_H
#define SETTINGSHELPER_H
#include <QtCore/qobject.h>
#include <QtQml/qqml.h>
#include <QSettings>
#include <QScopedPointer>
#include <QFileInfo>
#include <QCoreApplication>
#include <QDir>
#include "src/singleton.h"
class SettingsHelper : public QObject
{
Q_OBJECT
private:
explicit SettingsHelper(QObject* parent = nullptr);
public:
SINGLETONG(SettingsHelper)
~SettingsHelper() override;
void init(char *argv[]);
Q_INVOKABLE void saveRender(const QString& render){save("render",render);}
Q_INVOKABLE QString getRender(){return get("render").toString();}
Q_INVOKABLE void saveDarkMode(int darkModel){save("darkMode",darkModel);}
Q_INVOKABLE int getDarkMode(){return get("darkMode").toInt(0);}
Q_INVOKABLE void saveVsync(bool vsync){save("vsync",vsync);}
Q_INVOKABLE bool getVsync(){return get("vsync").toBool();}
private:
void save(const QString& key,QVariant val);
QVariant get(const QString& key);
private:
QScopedPointer<QSettings> m_settings;
};
#endif // SETTINGSHELPER_H

View File

@ -1,23 +0,0 @@
#include "En.h"
En::En(QObject *parent)
: Lang{parent}
{
setObjectName("En");
home("Home");
basic_input("Basic Input");
form("Form");
surface("Surfaces");
popus("Popus");
navigation("Navigation");
theming("Theming");
media("Media");
dark_mode("Dark Mode");
sys_dark_mode("Sync with system");
search("Search");
about("About");
settings("Settings");
locale("Locale");
navigation_view_display_mode("NavigationView Display Mode");
other("Other");
}

View File

@ -1,17 +0,0 @@
#ifndef EN_H
#define EN_H
#include <QObject>
#include "Lang.h"
class En : public Lang
{
Q_OBJECT
public:
explicit En(QObject *parent = nullptr);
signals:
};
#endif // EN_H

View File

@ -1,7 +0,0 @@
#include "Lang.h"
Lang::Lang(QObject *parent)
: QObject{parent}
{
}

View File

@ -1,31 +0,0 @@
#ifndef LANG_H
#define LANG_H
#include <QObject>
#include "../stdafx.h"
class Lang : public QObject
{
Q_OBJECT
Q_PROPERTY_AUTO(QString,home);
Q_PROPERTY_AUTO(QString,basic_input);
Q_PROPERTY_AUTO(QString,form);
Q_PROPERTY_AUTO(QString,surface);
Q_PROPERTY_AUTO(QString,popus);
Q_PROPERTY_AUTO(QString,navigation);
Q_PROPERTY_AUTO(QString,theming);
Q_PROPERTY_AUTO(QString,media);
Q_PROPERTY_AUTO(QString,dark_mode);
Q_PROPERTY_AUTO(QString,sys_dark_mode);
Q_PROPERTY_AUTO(QString,search);
Q_PROPERTY_AUTO(QString,about);
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);
};
#endif // LANG_H

View File

@ -1,23 +0,0 @@
#include "Zh.h"
Zh::Zh(QObject *parent)
: Lang{parent}
{
setObjectName("Zh");
home("首页");
basic_input("基本输入");
form("表单");
surface("表面");
popus("弹窗");
navigation("导航");
theming("主题");
media("媒体");
dark_mode("夜间模式");
sys_dark_mode("跟随系统");
search("查找");
about("关于");
settings("设置");
locale("语言环境");
navigation_view_display_mode("导航视图显示模式");
other("其他");
}

View File

@ -1,17 +0,0 @@
#ifndef ZH_H
#define ZH_H
#include <QObject>
#include "Lang.h"
class Zh : public Lang
{
Q_OBJECT
public:
explicit Zh(QObject *parent = nullptr);
signals:
};
#endif // ZH_H

View File

@ -6,13 +6,14 @@
#include <QNetworkProxy>
#include <QSslConfiguration>
#include <QProcess>
#include <FramelessHelper/Quick/framelessquickmodule.h>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
#include <QtQml/qqmlextensionplugin.h>
#include <QLoggingCategory>
#include "AppInfo.h"
#include "src/component/CircularReveal.h"
#include "src/component/FileWatcher.h"
#include "src/component/FpsItem.h"
#include "src/helper/SettingsHelper.h"
#ifdef FLUENTUI_BUILD_STATIC_LIB
#if (QT_VERSION > QT_VERSION_CHECK(6, 2, 0))
Q_IMPORT_QML_PLUGIN(FluentUIPlugin)
@ -20,10 +21,9 @@ Q_IMPORT_QML_PLUGIN(FluentUIPlugin)
#include <FluentUI.h>
#endif
FRAMELESSHELPER_USE_NAMESPACE
int main(int argc, char *argv[])
int main(int argc, char *argv[])
{
QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
@ -32,25 +32,24 @@ FRAMELESSHELPER_USE_NAMESPACE
#endif
#endif
qputenv("QT_QUICK_CONTROLS_STYLE","Basic");
FramelessHelper::Quick::initialize();
QGuiApplication::setOrganizationName("ZhuZiChu");
QGuiApplication::setOrganizationDomain("https://zhuzichu520.github.io");
QGuiApplication::setApplicationName("FluentUI");
SettingsHelper::getInstance()->init(argv);
if(SettingsHelper::getInstance()->getRender()=="software"){
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
QQuickWindow::setGraphicsApi(QSGRendererInterface::Software);
#elif (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software);
#endif
}
QGuiApplication app(argc, argv);
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
FramelessConfig::instance()->set(Global::Option::ForceHideWindowFrameBorder);
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow,false);
#endif
#ifdef Q_OS_MACOS
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur,false);
#endif
AppInfo* appInfo = new AppInfo();
// QLoggingCategory::setFilterRules(QStringLiteral("qt.scenegraph.general=true"));
// qSetMessagePattern("%{category}: %{message}");
QQmlApplicationEngine engine;
FramelessHelper::Quick::registerTypes(&engine);
AppInfo::getInstance()->init(&engine);
engine.rootContext()->setContextProperty("AppInfo",AppInfo::getInstance());
engine.rootContext()->setContextProperty("SettingsHelper",SettingsHelper::getInstance());
#ifdef FLUENTUI_BUILD_STATIC_LIB
FluentUI::getInstance()->registerTypes(&engine);
#endif
@ -58,7 +57,6 @@ FRAMELESSHELPER_USE_NAMESPACE
qmlRegisterType<CircularReveal>("example", 1, 0, "CircularReveal");
qmlRegisterType<FileWatcher>("example", 1, 0, "FileWatcher");
qmlRegisterType<FpsItem>("example", 1, 0, "FpsItem");
appInfo->init(&engine);
const QUrl url(QStringLiteral("qrc:/example/qml/App.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
@ -66,5 +64,9 @@ FRAMELESSHELPER_USE_NAMESPACE
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
const int exec = QGuiApplication::exec();
if (exec == 931) {
QProcess::startDetached(qApp->applicationFilePath(), QStringList());
}
return exec;
}

47
example/src/singleton.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef SINGLETON_H
#define SINGLETON_H
#include <QMutex>
#include <QScopedPointer>
#include <memory>
#include <mutex>
template <typename T>
class Singleton {
public:
static T* getInstance();
Singleton(const Singleton& other) = delete;
Singleton<T>& operator=(const Singleton& other) = delete;
private:
static std::mutex mutex;
static T* instance;
};
template <typename T>
std::mutex Singleton<T>::mutex;
template <typename T>
T* Singleton<T>::instance;
template <typename T>
T* Singleton<T>::getInstance() {
if (instance == nullptr) {
std::lock_guard<std::mutex> locker(mutex);
if (instance == nullptr) {
instance = new T();
}
}
return instance;
}
#define SINGLETONG(Class) \
private: \
friend class Singleton<Class>; \
friend struct QScopedPointerDeleter<Class>; \
\
public: \
static Class* getInstance() { \
return Singleton<Class>::getInstance(); \
}
#endif // SINGLETON_H

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

View File

@ -15,16 +15,16 @@ Write-Host "scriptDir" $scriptDir
function Main() {
New-Item -ItemType Directory $archiveName
New-Item -ItemType Directory dist
# 拷贝exe
Copy-Item bin\release\* $archiveName\ -Force -Recurse | Out-Null
Copy-Item bin\release\* dist\ -Force -Recurse | Out-Null
# 拷贝依赖
windeployqt --qmldir . --plugindir $archiveName\plugins --no-translations --compiler-runtime $archiveName\$targetName
windeployqt --qmldir . --plugindir dist\plugins --no-translations --compiler-runtime dist\$targetName
# 删除不必要的文件
$excludeList = @("*.qmlc", "*.ilk", "*.exp", "*.lib", "*.pdb")
Remove-Item -Path $archiveName -Include $excludeList -Recurse -Force
Remove-Item -Path dist -Include $excludeList -Recurse -Force
# 打包zip
Compress-Archive -Path $archiveName $archiveName'.zip'
Compress-Archive -Path dist $archiveName'.zip'
}
if ($null -eq $archiveName || $null -eq $targetName) {

View File

@ -25,22 +25,22 @@ Write-Host "scriptDir" $scriptDir
function Main() {
New-Item -ItemType Directory $archiveName
New-Item -ItemType Directory dist
# 拷贝exe
Copy-Item bin\release\* $archiveName\ -Force -Recurse | Out-Null
Copy-Item bin\release\* dist -Force -Recurse | Out-Null
# 拷贝依赖
windeployqt --qmldir . --plugindir $archiveName\plugins --no-translations --compiler-runtime $archiveName\$targetName
windeployqt --qmldir . --plugindir dist\plugins --no-translations --compiler-runtime dist\$targetName
# 删除不必要的文件
$excludeList = @("*.qmlc", "*.ilk", "*.exp", "*.lib", "*.pdb")
Remove-Item -Path $archiveName -Include $excludeList -Recurse -Force
Remove-Item -Path dist -Include $excludeList -Recurse -Force
# 拷贝vcRedist dll
$redistDll="{0}{1}\*.CRT\*.dll" -f $env:vcToolsRedistDir.Trim(),$env:msvcArch
Copy-Item $redistDll $archiveName\
Copy-Item $redistDll dist\
# 拷贝WinSDK dll
$sdkDll="{0}Redist\{1}ucrt\DLLs\{2}\*.dll" -f $env:winSdkDir.Trim(),$env:winSdkVer.Trim(),$env:msvcArch
Copy-Item $sdkDll $archiveName\
Copy-Item $sdkDll dist\
# 打包zip
Compress-Archive -Path $archiveName $archiveName'.zip'
Compress-Archive -Path dist $archiveName'.zip'
}
if ($null -eq $archiveName || $null -eq $targetName) {

View File

@ -120,8 +120,17 @@ else()
)
endif()
#去掉mingw生成的动态库libxxx前缀lib不去掉前缀会导致 module "FluentUI" plugin "fluentuiplugin" not found
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
if(MINGW)
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX ".debug")
endif()
#MSVC Debug 添加后缀d与Qt插件风格保持一致
if(MSVC)
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "d")
endif()
#链接库
target_link_libraries(${PROJECT_NAME} PUBLIC
@ -129,6 +138,8 @@ target_link_libraries(${PROJECT_NAME} PUBLIC
Qt${QT_VERSION_MAJOR}::QuickPrivate
Qt${QT_VERSION_MAJOR}::QmlPrivate
ZXing
FramelessHelper::Core
FramelessHelper::Quick
)
#安装

View File

@ -8,9 +8,13 @@
#include <QUuid>
#include <QFontDatabase>
#include <QClipboard>
#include "Def.h"
#include <FramelessHelper/Quick/framelessquickmodule.h>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
FRAMELESSHELPER_USE_NAMESPACE
FluApp::FluApp(QObject *parent):QObject{parent}{
vsync(false);
httpInterceptor(nullptr);
}
@ -18,7 +22,20 @@ FluApp::~FluApp(){
}
void FluApp::init(QQuickWindow *window){
this->appWindow = window;
this->_application = window;
FramelessHelper::Quick::initialize();
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
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow,false);
#endif
#ifdef Q_OS_MACOS
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur,false);
#endif
QQmlEngine *engine = qmlEngine(_application);
FramelessHelper::Quick::registerTypes(engine);
}
void FluApp::run(){
@ -30,7 +47,7 @@ void FluApp::navigate(const QString& route,const QJsonObject& argument,FluRegist
qCritical()<<"No route found "<<route;
return;
}
QQmlEngine *engine = qmlEngine(appWindow);
QQmlEngine *engine = qmlEngine(_application);
QQmlComponent component(engine, routes().value(route).toString());
if (component.isError()) {
qCritical() << component.errors();
@ -42,65 +59,47 @@ void FluApp::navigate(const QString& route,const QJsonObject& argument,FluRegist
properties.insert("_pageRegister",QVariant::fromValue(fluRegister));
}
properties.insert("argument",argument);
QQuickWindow *view=nullptr;
for (auto& pair : wnds) {
QString r = pair->property("_route").toString();
QQuickWindow *win=nullptr;
for (const auto& pair : _windows.toStdMap()) {
QString r = pair.second->property("_route").toString();
if(r == route){
view = pair;
win = pair.second;
break;
}
}
if(view){
//如果窗口存在,则判断启动模式
int launchMode = view->property("launchMode").toInt();
if(win){
int launchMode = win->property("launchMode").toInt();
if(launchMode == 1){
view->setProperty("argument",argument);
view->show();
view->raise();
view->requestActivate();
win->setProperty("argument",argument);
win->show();
win->raise();
win->requestActivate();
return;
}else if(launchMode == 2){
view->close();
win->close();
}
}
view = qobject_cast<QQuickWindow*>(component.createWithInitialProperties(properties));
wnds.insert(view->winId(),view);
win = qobject_cast<QQuickWindow*>(component.createWithInitialProperties(properties));
if(fluRegister){
fluRegister->to(view);
fluRegister->to(win);
}
view->setColor(QColor(Qt::transparent));
win->setColor(QColor(Qt::transparent));
}
QJsonArray FluApp::awesomelist(const QString& keyword){
QJsonArray arr;
QMetaEnum enumType = Fluent_Awesome::staticMetaObject.enumerator(Fluent_Awesome::staticMetaObject.indexOfEnumerator("Fluent_AwesomeType"));
for(int i=0; i < enumType.keyCount(); ++i){
QString name = enumType.key(i);
int icon = enumType.value(i);
if(keyword.isEmpty()){
QJsonObject obj;
obj.insert("name",name);
obj.insert("icon",icon);
arr.append(obj);
}else{
if(name.contains(keyword)){
QJsonObject obj;
obj.insert("name",name);
obj.insert("icon",icon);
arr.append(obj);
}
}
void FluApp::exit(int retCode){
for (const auto& pair : _windows.toStdMap()) {
removeWindow(pair.second);
}
return arr;
qApp->exit(retCode);
}
void FluApp::closeApp(){
qApp->exit(0);
void FluApp::addWindow(QQuickWindow* window){
_windows.insert(window->winId(),window);
}
void FluApp::deleteWindow(QQuickWindow* window){
void FluApp::removeWindow(QQuickWindow* window){
if(window){
wnds.remove(window->winId());
_windows.remove(window->winId());
window->deleteLater();
window = nullptr;
}

View File

@ -19,6 +19,7 @@
class FluApp : public QObject
{
Q_OBJECT
Q_PROPERTY_AUTO(bool,vsync)
Q_PROPERTY_AUTO(QString,initialRoute);
Q_PROPERTY_AUTO(QJsonObject,routes);
Q_PROPERTY_AUTO(FluHttpInterceptor*,httpInterceptor);
@ -33,13 +34,12 @@ public:
Q_INVOKABLE void run();
Q_INVOKABLE void navigate(const QString& route,const QJsonObject& argument = {},FluRegister* fluRegister = nullptr);
Q_INVOKABLE void init(QQuickWindow *window);
Q_INVOKABLE QJsonArray awesomelist(const QString& keyword = "");
Q_INVOKABLE void closeApp();
Q_INVOKABLE void deleteWindow(QQuickWindow* window);
public:
QMap<quint64, QQuickWindow*> wnds;
Q_INVOKABLE void exit(int retCode = 0);
void addWindow(QQuickWindow* window);
void removeWindow(QQuickWindow* window);
private:
QWindow *appWindow;
QMap<quint64, QQuickWindow*> _windows;
QWindow* _application;
};
#endif // FLUAPP_H

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