Compare commits

..

89 Commits
1.1.7 ... 1.2.5

Author SHA1 Message Date
60c2ebee56 update 2023-04-19 10:14:35 +08:00
88fed82260 update 2023-04-19 09:41:08 +08:00
cb94db8a97 Merge pull request #53 from mentalfl0w/dev
Add automatic dark color mode switching function.
2023-04-16 02:30:08 +08:00
88008e16be update 2023-04-16 02:28:58 +08:00
f2db544be0 Add automatic dark color mode switching function. 2023-04-16 01:18:17 +08:00
6db8c4d4ac update 2023-04-15 21:20:00 +08:00
4ab78bbaba 修改registerForPageResult崩溃问题 2023-04-15 09:45:54 +08:00
11b2b04cb9 update 2023-04-14 17:43:19 +08:00
9f2e066a9f update 2023-04-14 17:36:33 +08:00
5b8312dcb9 update 2023-04-14 17:10:36 +08:00
b28f15c23b update 2023-04-14 17:07:54 +08:00
935f515a49 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2023-04-14 15:18:32 +08:00
70585c007e 新增FluRatingControl组件 2023-04-14 15:18:08 +08:00
bdde046a4d Update README.md 2023-04-14 12:35:16 +08:00
ad420366f1 Update README.md 2023-04-14 12:34:51 +08:00
727a0220b4 update 2023-04-13 18:10:38 +08:00
ab0fcf5d9c FluWindowd新增launchMode枚举值,支持Standard、SingleTask、SingleInstance 2023-04-13 17:41:34 +08:00
f43bfec992 Merge pull request #43 from LiangLiang723/main
🔧 重构 FluWindow 后 CMakeLists 做对应修改
2023-04-13 16:36:12 +08:00
6bf38b5e5e 🔧 重构 FluWindow 后 CMakeLists 做对应修改 2023-04-13 15:01:04 +08:00
73ff2b45b9 update 2023-04-12 22:02:05 +08:00
7303e7d900 update 2023-04-12 13:42:45 +08:00
5ca1b715f3 update 2023-04-12 11:55:39 +08:00
cd984fddf5 update 2023-04-12 00:15:38 +08:00
2acb3c34bd update 2023-04-11 23:43:20 +08:00
1df3b4ba96 update 2023-04-11 23:39:20 +08:00
5ea3cb1054 Merge pull request #39 from zhuzichu520/dev1.2.4
update
2023-04-11 23:17:51 +08:00
5afd2ec518 update 2023-04-11 23:12:31 +08:00
59527fc954 Merge pull request #38 from zhuzichu520/dev1.2.4
update
2023-04-11 18:06:06 +08:00
c26fdfaee3 update 2023-04-11 18:05:07 +08:00
878dbd668b Merge pull request #36 from zhuzichu520/dev1.2.4
update
2023-04-11 16:31:35 +08:00
b10a0752fb update 2023-04-11 16:30:54 +08:00
51e73e7f8e fix bug 2023-04-11 16:30:07 +08:00
3a46fd11c6 update 2023-04-10 22:07:30 +08:00
70f048f629 update 2023-04-10 22:05:20 +08:00
1f2d0d9b9f update 2023-04-10 18:17:22 +08:00
09e87e0fb8 update 2023-04-09 19:29:50 +08:00
0603a7603d update 2023-04-09 18:08:37 +08:00
d9a4f01e20 update 2023-04-09 17:59:00 +08:00
93709cd1dd update 2023-04-08 21:23:03 +08:00
0000e557a7 update 2023-04-08 20:44:27 +08:00
d2183e350e update 2023-04-08 20:26:49 +08:00
47caf4bb52 update 2023-04-08 20:20:44 +08:00
6fb9ee41fb update 2023-04-08 20:12:28 +08:00
b349c22434 update 2023-04-08 20:08:26 +08:00
12fa3487bb Merge pull request #29 from LiangLiang723/win32_cmake_fix
🐛 修复 windows 下生成 dll 库带 linux 前缀导致查找不到控件
2023-04-08 19:57:14 +08:00
a76806645a 🐛 修复 windows 下生成 dll 库带 linux 前缀导致查找不到控件 2023-04-08 19:45:39 +08:00
738db25c2c Merge pull request #28 from LiangLiang723/win32_cmake_fix
🐛 修复 windows 下生成 dll 库带 linux 前缀导致查找不到控件
2023-04-08 19:43:35 +08:00
9f8a5f5646 🐛 修复 windows 下生成 dll 库带 linux 前缀导致查找不到控件 2023-04-08 19:32:35 +08:00
c59c07e756 update 2023-04-07 20:48:04 +08:00
2084b5afa3 update 2023-04-07 20:19:18 +08:00
f8d717f41b update 2023-04-07 18:27:50 +08:00
be58fc5e7d update 2023-04-06 19:55:53 +08:00
1c0bc7208a update 2023-04-06 19:27:37 +08:00
d89aaec062 update 2023-04-06 17:32:21 +08:00
13abd275b4 update 2023-04-06 00:29:33 +08:00
e8460c2409 update 2023-04-05 21:42:12 +08:00
6de1b9d78f update 2023-04-05 17:48:17 +08:00
64fa2b6370 update 2023-04-05 17:05:05 +08:00
8970a0c09a update 2023-04-05 17:04:12 +08:00
e7cea72825 update 2023-04-05 16:37:27 +08:00
93186edfbe Merge pull request #16 from JesseGuoX/main
Optimize workflow
2023-04-04 17:21:19 +08:00
e60883bc60 Optimize workflow 2023-04-04 17:06:10 +08:00
47ab4dabbd update 2023-04-04 16:39:41 +08:00
206669e5f0 update 2023-04-04 15:09:34 +08:00
08457dc75e update 2023-04-04 09:08:10 +08:00
0c59a233ea update 2023-04-04 03:15:10 +08:00
fcb8da2c50 update 2023-04-04 02:37:20 +08:00
a8701256d4 update 2023-04-04 00:37:37 +08:00
8eaa4b6cbb update 2023-04-04 00:33:24 +08:00
af80a882d0 update 2023-04-04 00:18:39 +08:00
9d89328a43 update 2023-04-03 22:45:18 +08:00
0d4477437f update 2023-04-03 21:16:07 +08:00
6b3e73ce0b update 2023-04-03 21:13:50 +08:00
625bc74e26 update 2023-04-03 21:04:41 +08:00
731e4f27b4 update 2023-04-03 20:04:46 +08:00
fce64eccc6 Merge pull request #12 from JesseGuoX/main
add tag name into workflow release assets
2023-04-03 15:58:00 +08:00
689e0805e7 add tag name into update workflow release assets
before: example_ubuntu-20.04_6.4.3.AppImage

after: example_v1.1.8_ubuntu-20.04_Qt6.4.3.AppImage
2023-04-03 14:22:01 +08:00
986f1242dd update 2023-04-03 09:32:06 +08:00
a9c97a5c56 Merge pull request #10 from JesseGuoX/main
update workflow, speed up ci
2023-04-03 08:41:22 +08:00
81e78834d0 update workflow, speed up ci 2023-04-02 23:36:23 +08:00
5279a2c7b2 update 2023-04-02 14:05:54 +08:00
6391fc8dc6 update 2023-04-01 21:51:59 +08:00
9cf4b4b1af update 2023-04-01 21:42:32 +08:00
32c0b4ccd6 update 2023-04-01 21:37:07 +08:00
b2bfdd17da update 2023-04-01 21:06:39 +08:00
27db8160d4 update 2023-04-01 21:01:46 +08:00
ed0c9048b0 update 2023-04-01 10:22:05 +08:00
de2c891912 Create License 2023-04-01 09:31:18 +08:00
16daeb5268 update 2023-03-31 22:54:23 +08:00
151 changed files with 5480 additions and 2204 deletions

View File

@ -16,24 +16,23 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [macos-11.0] os: [macos-12]
qt_ver: [6.4.3] qt_ver: [6.4.3]
qt_arch: [clang_64] qt_arch: [clang_64]
env: env:
targetName: example targetName: example
steps: steps:
# macos 11.0 默认环境变了,要指定 - name: '⚙️ Cache Qt'
- name: prepare env id: cache-qt
if: ${{ matrix.os == 'macos-11.0' }} uses: actions/cache@v3
run: | with:
softwareupdate --all --install --force path: ${{ runner.workspace }}/Qt
sudo xcode-select --print-path key: ${{runner.os}}-qtcachedir-${{ matrix.qt_ver }}
sudo xcode-select --switch /Library/Developer/CommandLineTools
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v3 uses: jurplel/install-qt-action@v3
with: with:
version: ${{ matrix.qt_ver }} version: ${{ matrix.qt_ver }}
cached: 'false' cache: ${{steps.cache-qt.outputs.cache-hit}}
arch: ${{ matrix.qt_arch }} arch: ${{ matrix.qt_arch }}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats' modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -60,6 +59,6 @@ jobs:
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
file: bin/release/${{ env.targetName }}.dmg file: bin/release/${{ env.targetName }}.dmg
asset_name: ${{ env.targetName }}_${{ matrix.os }}_${{ matrix.qt_ver }}.dmg asset_name: ${{ env.targetName }}_${{ github.ref_name }}_${{ matrix.os }}_Qt${{ matrix.qt_ver }}.dmg
tag: ${{ github.ref }} tag: ${{ github.ref }}
overwrite: true overwrite: true

View File

@ -24,15 +24,21 @@ jobs:
env: env:
targetName: example targetName: example
steps: steps:
- name: '⚙️ Cache Qt'
id: cache-qt
uses: actions/cache@v3
with:
path: ${{ runner.workspace }}/Qt
key: ${{runner.os}}-qtcachedir-${{ matrix.qt_ver }}
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v3 uses: jurplel/install-qt-action@v3
with: with:
version: ${{ matrix.qt_ver }} version: ${{ matrix.qt_ver }}
cached: 'false' cache: ${{steps.cache-qt.outputs.cache-hit}}
arch: ${{ matrix.qt_arch }} arch: ${{ matrix.qt_arch }}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats' modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
- name: ubuntu install GL library - name: ubuntu install GL library
run: sudo apt-get install -y libglew-dev libglfw3-dev qml-module-qtquick-controls qml-module-qtquick-controls2 run: sudo apt-get install -y libxkbcommon-x11-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxcb-xinerama0-dev libxcb-sync-dev libxcb-render-util0-dev libxcb-shm0-dev
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
fetch-depth: 1 fetch-depth: 1
@ -44,6 +50,8 @@ jobs:
uses: miurahr/install-linuxdeploy-action@v1 uses: miurahr/install-linuxdeploy-action@v1
with: with:
plugins: qt appimage plugins: qt appimage
- name: Check if svg file exists
run: if [ ! -f "${targetName}.svg" ]; then echo "File not found, creating..."; touch ${targetName}.svg; fi
# 打包 # 打包
- name: package - name: package
run: | run: |
@ -64,6 +72,6 @@ jobs:
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ env.targetName }}.AppImage file: ${{ env.targetName }}.AppImage
asset_name: ${{ env.targetName }}_${{ matrix.os }}_${{ matrix.qt_ver }}.AppImage asset_name: ${{ env.targetName }}_${{ github.ref_name }}_${{ matrix.os }}_Qt${{ matrix.qt_ver }}.AppImage
tag: ${{ github.ref }} tag: ${{ github.ref }}
overwrite: true overwrite: true

76
.github/workflows/windows-mingw.yml vendored Normal file
View File

@ -0,0 +1,76 @@
name: Windows MinGW
on:
push:
paths:
- '*.pro'
- 'src/**'
- '.github/workflows/windows-mingw.yml'
pull_request:
paths:
- '*.pro'
- 'src/**'
- '.github/workflows/windows-mingw.yml'
jobs:
build:
name: Build
runs-on: windows-2022
strategy:
matrix:
include:
- qt_arch: win64_mingw
qt_ver: 6.4.3
qt_tools: "tools_mingw,9.0.0-1-202203221220,qt.tools.win64_mingw900"
qt_tools_mingw_install: mingw900_64
env:
targetName: example.exe
fileName: example
steps:
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
cache: ${{steps.cache-qt.outputs.cache-hit}}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Qt6 environment configuration
if: ${{ startsWith( matrix.qt_ver, 6 ) }}
shell: pwsh
run: |
Write-Output "${{ env.Qt6_DIR }}/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
Write-Output "${{ env.Qt6_DIR }}/../../Tools/${{ matrix.qt_tools_mingw_install }}/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: where is qmake & where is mingw32-make
shell: pwsh
run: |
Get-Command -Name 'qmake' | Format-List
Get-Command -Name 'mingw32-make' | Format-List
- name: mingw-build
id: build
shell: cmd
run: |
qmake
mingw32-make
- name: package
id: package
env:
archiveName: ${{ env.fileName }}-${{ matrix.qt_arch }}-${{ matrix.qt_ver }}
shell: pwsh
run: |
& scripts\windows-mingw-publish.ps1 ${env:archiveName} ${env:targetName}
$name = ${env:archiveName}
echo "::set-output name=packageName::$name"
- uses: actions/upload-artifact@v2
with:
name: ${{ steps.package.outputs.packageName }}
path: ${{ steps.package.outputs.packageName }}
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.package.outputs.packageName }}.zip
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.zip
tag: ${{ github.ref }}
overwrite: true

View File

@ -16,10 +16,11 @@ jobs:
name: Build name: Build
# 运行平台, windows-latest目前是windows server 2019 # 运行平台, windows-latest目前是windows server 2019
# 参考文档 https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md # 参考文档 https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md
runs-on: windows-2019 runs-on: ${{ matrix.os }}
strategy: strategy:
# 矩阵配置 # 矩阵配置
matrix: matrix:
os: [windows-2019]
include: include:
- qt_ver: 6.4.3 - qt_ver: 6.4.3
qt_arch: win64_msvc2019_64 qt_arch: win64_msvc2019_64
@ -30,6 +31,12 @@ jobs:
fileName: example fileName: example
# 步骤 # 步骤
steps: steps:
- name: '⚙️ Cache Qt'
id: cache-qt
uses: actions/cache@v3
with:
path: ${{ runner.workspace }}\Qt
key: ${{runner.os}}-qtcachedir-${{ matrix.qt_ver }}
# 安装Qt # 安装Qt
- name: Install Qt - name: Install Qt
# 使用外部action。这个action专门用来安装Qt # 使用外部action。这个action专门用来安装Qt
@ -37,7 +44,7 @@ jobs:
with: with:
version: ${{ matrix.qt_ver }} version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }} arch: ${{ matrix.qt_arch }}
cached: 'false' cache: ${{steps.cache-qt.outputs.cache-hit}}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats' modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
# 拉取代码 # 拉取代码
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -80,6 +87,6 @@ jobs:
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.package.outputs.packageName }}.zip file: ${{ steps.package.outputs.packageName }}.zip
asset_name: ${{ steps.package.outputs.packageName }}.zip asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.zip
tag: ${{ github.ref }} tag: ${{ github.ref }}
overwrite: true overwrite: true

1
.gitignore vendored
View File

@ -33,3 +33,4 @@ CMakeLists.txt.user*
src/build-preset/plugins.qmltypes src/build-preset/plugins.qmltypes
bin bin
.DS_Store

5
CMakeLists.txt Normal file
View File

@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.16)
project(FluentUI VERSION 0.1 LANGUAGES CXX)
add_subdirectory(src)
add_subdirectory(example)

21
License Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 zhuzichu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -2,7 +2,7 @@
## 简介 ## 简介
这是一个漂亮的Fluent组件库使用QML插件开发的 这是一个漂亮的Fluent组件库使用QML插件开发的。main分支是Qt6.4.3如果需要qt5的请切换至qt5分支
## 编译状态 ## 编译状态
| [Windows][win-link]| [Ubuntu][ubuntu-link]|[MacOS][macos-link]| | [Windows][win-link]| [Ubuntu][ubuntu-link]|[MacOS][macos-link]|
@ -62,6 +62,12 @@
|FluDatePicker|日期选择器|| |FluDatePicker|日期选择器||
|FluMenu|菜单Popup|| |FluMenu|菜单Popup||
|FluNavigationView|响应式导航布局|| |FluNavigationView|响应式导航布局||
|FluScrollbar|滚动条||
|FluToggleButton|开关按钮||
|FluPagination|分页组件||
|FluTableView|表格组件||
|FluMediaPlayer|播放器||
|FluFlipView|FlipView||
# 部分效果预览 # 部分效果预览
@ -77,6 +83,10 @@
![](doc/preview/theme.png) ![](doc/preview/theme.png)
## TableView表格组件
![](doc/preview/tableview.png)
## FluTreeView树组件 ## FluTreeView树组件
![](doc/preview/treeview.png) ![](doc/preview/treeview.png)
@ -85,13 +95,5 @@
![](doc/preview/carousel.png) ![](doc/preview/carousel.png)
## InfoBar提示框组件
![](doc/preview/infobar.png)
## 多窗口路由跳转
![](doc/preview/multiwindow.png)
### ⚡ Visitor count ### ⚡ Visitor count
![](https://profile-counter.glitch.me/zhuzichu520-FluentUI/count.svg) ![](https://profile-counter.glitch.me/zhuzichu520-FluentUI/count.svg)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 KiB

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

BIN
doc/preview/tableview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -6,9 +6,8 @@ import FluentUI
Window { Window {
id:app id:app
color: "#00000000"
Component.onCompleted: { Component.onCompleted: {
FluApp.init(app,properties) FluApp.init(app)
FluTheme.frameless = ("windows" === Qt.platform.os) FluTheme.frameless = ("windows" === Qt.platform.os)
FluTheme.dark = false FluTheme.dark = false
FluApp.routes = { FluApp.routes = {
@ -17,9 +16,11 @@ Window {
"/login":"qrc:/page/LoginPage.qml", "/login":"qrc:/page/LoginPage.qml",
"/chat":"qrc:/page/ChatPage.qml", "/chat":"qrc:/page/ChatPage.qml",
"/media":"qrc:/page/MediaPage.qml", "/media":"qrc:/page/MediaPage.qml",
"/singleTaskWindow":"qrc:/page/SingleTaskWindow.qml",
"/standardWindow":"qrc:/page/StandardWindow.qml",
"/singleInstanceWindow":"qrc:/page/SingleInstanceWindow.qml"
} }
FluApp.initialRoute = "/" FluApp.initialRoute = "/"
FluApp.run() FluApp.run()
} }
} }

25
example/AppInfo.cpp Normal file
View File

@ -0,0 +1,25 @@
#include "AppInfo.h"
#include "lang/En.h"
#include "lang/Zh.h"
AppInfo::AppInfo(QObject *parent)
: QObject{parent}
{
version("1.2.5");
lang(new En());
}
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());
}
}

18
example/AppInfo.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef APPINFO_H
#define APPINFO_H
#include <QObject>
#include "lang/Lang.h"
#include "stdafx.h"
class AppInfo : public QObject
{
Q_OBJECT
Q_PROPERTY_AUTO(QString,version)
Q_PROPERTY_AUTO(Lang*,lang)
public:
explicit AppInfo(QObject *parent = nullptr);
Q_INVOKABLE void changeLang(const QString& locale);
};
#endif // APPINFO_H

87
example/CMakeLists.txt Normal file
View File

@ -0,0 +1,87 @@
cmake_minimum_required(VERSION 3.16)
project(example)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_CXX_STANDARD 17)
file(TO_CMAKE_PATH "/" PATH_SEPARATOR)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(platform 64)
else()
set(platform 32)
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../bin/debug)
else()
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../bin/release)
endif()
find_package(Qt6 COMPONENTS Core Quick QuickControls2 Concurrent Network Multimedia REQUIRED)
set(SOURCES
ChatController.cpp
AppInfo.cpp
main.cpp
)
set(HEADERS
ChatController.h
AppInfo.h
)
set(RESOURCES
qml.qrc
)
set(RC_ICONS
favicon.ico
)
qt_add_resources(QT_RESOURCES ${RESOURCES})
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS} ${QT_RESOURCES} ${RC_ICONS})
if(WIN32)
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
set(DLLPATH ${CMAKE_CURRENT_SOURCE_DIR}/../third/msvc/*.dll)
else()
set(DLLPATH ${CMAKE_CURRENT_SOURCE_DIR}/../third/mingw/*.dll)
endif()
string(REPLACE "/" ${PATH_SEPARATOR} DLLPATH "${DLLPATH}")
file(GLOB DLL_FILES ${DLLPATH})
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${DLL_FILES}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
)
endif()
target_compile_definitions(${PROJECT_NAME} PRIVATE
QT_DEPRECATED_WARNINGS
QT_NO_WARNING_OUTPUT
)
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt6::Core
Qt6::Quick
Qt6::QuickControls2
Qt6::Concurrent
Qt6::Network
Qt6::Multimedia
)
if(WIN32)
target_compile_definitions(${PROJECT_NAME} PRIVATE UNICODE WIN32 _WINDOWS)
target_link_libraries(${PROJECT_NAME} PRIVATE dwmapi user32)
endif()
if(APPLE)
set_target_properties(${PROJECT_NAME} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST Info.plist
)
endif()

View File

@ -67,7 +67,6 @@ FluContentPage {
width:parent.width width:parent.width
wrapMode: Text.WrapAnywhere wrapMode: Text.WrapAnywhere
text: modelData.name text: modelData.name
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
} }
} }

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -11,9 +12,10 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
height: 106 height: 106
paddings: 10 paddings: 10
@ -99,5 +101,19 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'Rectangle{
width: 40
height: 40
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
count: 100
isDot: false
color: Qt.rgba(82/255,196/255,26/255,1)
}
}'
}
} }

View File

@ -3,15 +3,15 @@ import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
title:"Buttons" title:"Buttons"
spacing: 20
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluText{ FluText{
Layout.topMargin: 20 Layout.topMargin: 20
@ -19,9 +19,10 @@ FluScrollablePage{
} }
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
height: 68 height: 68
paddings: 10 paddings: 10
Layout.topMargin: 20
FluTextButton{ FluTextButton{
disabled:text_button_switch.selected disabled:text_button_switch.selected
@ -48,11 +49,21 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluTextButton{
text:"Text Button"
onClicked: {
}
}'
}
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
height: 68 height: 68
paddings: 10 paddings: 10
Layout.topMargin: 20
FluButton{ FluButton{
disabled:button_switch.selected disabled:button_switch.selected
@ -79,10 +90,20 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluButton{
text:"Standard Button"
onClicked: {
}
}'
}
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
height: 68 height: 68
Layout.topMargin: 20
paddings: 10 paddings: 10
FluFilledButton{ FluFilledButton{
@ -110,13 +131,63 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluFilledButton{
text:"Filled Button"
onClicked: {
}
}'
}
FluArea{
Layout.fillWidth: true
height: 68
Layout.topMargin: 20
paddings: 10
FluToggleButton{
disabled:toggle_button_switch.selected
text:"Toggle Button"
onClicked: {
selected = !selected
}
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
}
Row{
spacing: 5
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
}
FluToggleSwitch{
id:toggle_button_switch
Layout.alignment: Qt.AlignRight
text:"Disabled"
}
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluToggleButton{
text:"Toggle Button"
onClicked: {
selected = !selected
}
}'
}
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
height: 68 height: 68
paddings: 10 paddings: 10
Layout.topMargin: 20
FluIconButton{ FluIconButton{
iconSource:FluentIcons.ChromeCloseContrast iconSource:FluentIcons.ChromeCloseContrast
disabled:icon_button_switch.selected disabled:icon_button_switch.selected
@ -143,12 +214,21 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluIconButton{
iconSource:FluentIcons.ChromeCloseContrast
onClicked: {
}
}'
}
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
height: 68 height: 68
paddings: 10 paddings: 10
Layout.topMargin: 20
FluDropDownButton{ FluDropDownButton{
disabled:drop_down_button_switch.selected disabled:drop_down_button_switch.selected
text:"DropDownButton" text:"DropDownButton"
@ -184,12 +264,32 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluDropDownButton{
text:"DropDownButton"
items:[
FluMenuItem{
text:"Menu_1"
},
FluMenuItem{
text:"Menu_2"
},
FluMenuItem{
text:"Menu_3"
},
FluMenuItem{
text:"Menu_4"
}
]
}'
}
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
height: 100 height: 100
paddings: 10 paddings: 10
Layout.topMargin: 20
ColumnLayout{ ColumnLayout{
spacing: 8 spacing: 8
anchors{ anchors{
@ -225,13 +325,23 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluRadioButton{
selected:true
text:"Text Button"
onClicked: {
}
}'
}
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
height: 68 height: 68
paddings: 10 paddings: 10
Layout.topMargin: 20
FluCheckBox{ FluCheckBox{
disabled:check_box_switch.selected disabled:check_box_switch.selected
text:"Check Box" text:"Check Box"
@ -240,8 +350,6 @@ FluScrollablePage{
left: parent.left left: parent.left
} }
} }
Row{ Row{
spacing: 5 spacing: 5
anchors{ anchors{
@ -255,6 +363,10 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluCheckBox{
text:"Check Box"
}'
}
} }

View File

@ -3,6 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,18 +11,25 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
height: 350 height: 350
paddings: 10 paddings: 10
FluCalendarView{ FluCalendarView{
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluCalendarView{
}'
}
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
height: 80 height: 80
paddings: 10 paddings: 10
@ -34,5 +42,11 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluCalendarPicker{
}'
}
} }

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,9 +11,10 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
height: 370 height: 370
paddings: 10 paddings: 10
Layout.topMargin: 20 Layout.topMargin: 20
@ -35,4 +37,14 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluCarousel{
width: 400
height: 300
Component.onCompleted: {
setData([{url:"qrc:/res/image/banner_1.jpg"},{url:"qrc:/res/image/banner_2.jpg"},{url:"qrc:/res/image/banner_3.jpg"}])
}
}'
}
} }

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,14 +11,28 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluCheckBox{ FluArea{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20 Layout.topMargin: 20
Row{
spacing: 30
anchors.verticalCenter: parent.verticalCenter
FluCheckBox{
} }
FluCheckBox{ FluCheckBox{
Layout.topMargin: 20
text:"Text" text:"Text"
} }
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluCheckBox{
text:"Text"
}'
}
} }

View File

@ -3,6 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,9 +11,10 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
height: 280 height: 280
Layout.topMargin: 20 Layout.topMargin: 20
paddings: 10 paddings: 10
@ -37,9 +39,15 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluColorView{
}'
}
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
height: 60 height: 60
paddings: 10 paddings: 10
@ -54,6 +62,12 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluColorPicker{
}'
}
} }

View File

@ -3,6 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,44 +11,42 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
height: 80 height: 80
paddings: 10 paddings: 10
ColumnLayout{ ColumnLayout{
anchors{ anchors{
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
left: parent.left left: parent.left
} }
FluText{ FluText{
text:"showYear=true" text:"showYear=true"
} }
FluDatePicker{ FluDatePicker{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluDatePicker{
}'
}
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
height: 80 height: 80
paddings: 10 paddings: 10
ColumnLayout{ ColumnLayout{
anchors{ anchors{
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
left: parent.left left: parent.left
} }
FluText{ FluText{
text:"showYear=false" text:"showYear=false"
} }
@ -56,8 +55,13 @@ FluScrollablePage{
showYear:false showYear:false
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluDatePicker{
showYear:false
}'
}
} }

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,6 +11,40 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluArea{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
FluButton{
anchors.verticalCenter: parent.verticalCenter
Layout.topMargin: 20
text:"Show Dialog"
onClicked: {
dialog.open()
}
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluContentDialog{
id:dialog
title:"友情提示"
message:"确定要退出程序么?"
negativeText:"取消"
onNegativeClicked:{
showSuccess("点击取消按钮")
}
positiveText:"确定"
onPositiveClicked:{
showSuccess("点击确定按钮")
}
}
dialog.open()
'
}
FluContentDialog{ FluContentDialog{
id:dialog id:dialog
@ -25,11 +60,5 @@ FluScrollablePage{
} }
} }
FluButton{
Layout.topMargin: 20
text:"Show Dialog"
onClicked: {
dialog.open()
}
}
} }

View File

@ -3,6 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,6 +11,20 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluArea{
Layout.fillWidth: true
height: layout_column.height+40
paddings: 10
Layout.topMargin: 20
Column{
id:layout_column
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left:parent.left
}
FluExpander{ FluExpander{
headerText:"打开一个单选框" headerText:"打开一个单选框"
@ -62,4 +77,33 @@ FluScrollablePage{
} }
} }
} }
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluExpander{
headerText:"打开一个单选框"
Item{
anchors.fill: parent
Flickable{
width: parent.width
height: parent.height
contentWidth: width
contentHeight: text_info.height
ScrollBar.vertical: FluScrollBar {}
FluText{
id:text_info
width: scrollview.width
wrapMode: Text.WrapAnywhere
padding: 14
text:"先帝创业未半而中道崩殂,今天下三分......""
}
}
}
}'
}
} }

120
example/T_FlipView.qml Normal file
View File

@ -0,0 +1,120 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "./component"
FluScrollablePage{
title:"FlipView"
leftPadding:10
rightPadding:10
bottomPadding:20
spacing: 0
FluArea{
Layout.fillWidth: true
height: 340
paddings: 10
Layout.topMargin: 20
ColumnLayout{
anchors.verticalCenter: parent.verticalCenter
FluText{
text:"水平方向的FlipView"
}
FluFlipView{
Image{
source: "qrc:/res/image/banner_1.jpg"
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
Image{
source: "qrc:/res/image/banner_2.jpg"
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
Image{
source: "qrc:/res/image/banner_3.jpg"
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
}
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluFlipView{
Image{
source: "qrc:/res/image/banner_1.jpg"
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
Image{
source: "qrc:/res/image/banner_1.jpg"
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
Image{
source: "qrc:/res/image/banner_1.jpg"
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
}
'
}
FluArea{
Layout.fillWidth: true
height: 340
paddings: 10
Layout.topMargin: 20
ColumnLayout{
anchors.verticalCenter: parent.verticalCenter
FluText{
text:"垂直方向的FlipView"
}
FluFlipView{
vertical:true
Image{
source: "qrc:/res/image/banner_1.jpg"
asynchronous: true
sourceSize: Qt.size(400,300)
fillMode:Image.PreserveAspectCrop
}
Image{
source: "qrc:/res/image/banner_2.jpg"
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
Image{
source: "qrc:/res/image/banner_3.jpg"
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
}
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluFlipView{
vertical:true
Image{
source: "qrc:/res/image/banner_1.jpg"
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
Image{
source: "qrc:/res/image/banner_1.jpg"
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
Image{
source: "qrc:/res/image/banner_1.jpg"
asynchronous: true
fillMode:Image.PreserveAspectCrop
}
}
'
}
}

View File

@ -129,7 +129,7 @@ FluScrollablePage{
id:item_mouse id:item_mouse
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
onWheel: { onWheel: (wheel)=>{
if (wheel.angleDelta.y > 0) scrollbar_header.decrease() if (wheel.angleDelta.y > 0) scrollbar_header.decrease()
else scrollbar_header.increase() else scrollbar_header.increase()
} }

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,33 +11,53 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 200
paddings: 10
ColumnLayout{
spacing: 14
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluButton{ FluButton{
text:"Info" text:"Info"
Layout.topMargin: 20
onClicked: { onClicked: {
showInfo("这是一个Info样式的InfoBar") showInfo("这是一个Info样式的InfoBar")
} }
} }
FluButton{ FluButton{
text:"Warning" text:"Warning"
Layout.topMargin: 20
onClicked: { onClicked: {
showWarning("这是一个Warning样式的InfoBar") showWarning("这是一个Warning样式的InfoBar")
} }
} }
FluButton{ FluButton{
text:"Error" text:"Error"
Layout.topMargin: 20
onClicked: { onClicked: {
showError("这是一个Error样式的InfoBar") showError("这是一个Error样式的InfoBar")
} }
} }
FluButton{ FluButton{
text:"Success" text:"Success"
Layout.topMargin: 20
onClicked: { onClicked: {
showSuccess("这是一个Success样式的InfoBar这是一个Success样式的InfoBar") showSuccess("这是一个Success样式的InfoBar这是一个Success样式的InfoBar")
} }
} }
} }
}
CodeExpander{
Layout.fillWidth: true
code:'showInfo("这是一个Info样式的InfoBar")
showWarning("这是一个Warning样式的InfoBar")
showError("这是一个Error样式的InfoBar")
showSuccess("这是一个Success样式的InfoBar这是一个Success样式的InfoBar")'
}
}

View File

@ -3,6 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,6 +11,7 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
onVisibleChanged: { onVisibleChanged: {
if(visible){ if(visible){
@ -18,9 +20,8 @@ FluScrollablePage{
player.pause() player.pause()
} }
} }
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
height: 320 height: 320
Layout.topMargin: 20 Layout.topMargin: 20
paddings: 10 paddings: 10
@ -31,11 +32,34 @@ FluScrollablePage{
} }
FluMediaPlayer{ FluMediaPlayer{
id:player id:player
// source:"http://mirror.aarnet.edu.au/pub/TED-talks/911Mothers_2010W-480p.mp4"
source:"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" source:"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
// source:"http://video.chinanews.com/flv/2019/04/23/400/111773_web.mp4"
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluMediaPlayer{
id:player
source:"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
}
'
}
FluArea{
Layout.fillWidth: true
height: 68
Layout.topMargin: 20
paddings: 10
FluButton{
text:"跳转到视频播放器窗口"
anchors.verticalCenter: parent.verticalCenter
onClicked:{
FluApp.navigate("/media",{source:"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"})
}
}
}
} }

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,6 +11,20 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluArea{
Layout.fillWidth: true
height: 100
paddings: 10
Layout.topMargin: 20
Column{
id:layout_column
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left:parent.left
}
FluButton{ FluButton{
text:"左击菜单" text:"左击菜单"
@ -19,7 +34,6 @@ FluScrollablePage{
} }
} }
FluButton{ FluButton{
text:"右击菜单" text:"右击菜单"
Layout.topMargin: 20 Layout.topMargin: 20
@ -34,6 +48,29 @@ FluScrollablePage{
} }
} }
} }
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluMenu{
id:menu
FluMenuItem:{
text:"删除"
onClicked: {
showError("删除")
}
}
FluMenuItem:{
text:"修改"
onClicked: {
showInfo"修改")
}
}
}
menu.popup()
'
}
FluMenu{ FluMenu{
id:menu id:menu
@ -46,7 +83,7 @@ FluScrollablePage{
FluMenuItem{ FluMenuItem{
text:"修改" text:"修改"
onClicked: { onClicked: {
showError("修改") showInfo("修改")
} }
} }
} }

View File

@ -3,17 +3,18 @@ import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
property string password: ""
property var loginPageRegister: registerForPageResult("/login")
title:"MultiWindow" title:"MultiWindow"
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
property string password: ""
property var loginPageRegister: registerForPageResult("/login")
Connections{ Connections{
target: loginPageRegister target: loginPageRegister
@ -24,11 +25,90 @@ FluScrollablePage{
} }
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
height: 86
paddings: 10
Layout.topMargin: 20
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluText{
text:"<font color='red'>Standard</font>模式窗口,每次都会创建新窗口"
}
FluButton{
text:"点击创建窗口"
onClicked: {
FluApp.navigate("/standardWindow")
}
}
}
}
FluArea{
Layout.fillWidth: true
height: 86
paddings: 10
Layout.topMargin: 10
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluText{
text:"<font color='red'>SingleTask</font>模式窗口,如果窗口存在,这激活该窗口"
textFormat: Text.RichText
}
FluButton{
text:"点击创建窗口"
onClicked: {
FluApp.navigate("/singleTaskWindow")
}
}
}
}
FluArea{
Layout.fillWidth: true
height: 86
paddings: 10
Layout.topMargin: 10
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluText{
text:"<font color='red'>SingleInstance</font>模式窗口,如果窗口存在,则销毁窗口,然后新建窗口"
}
FluButton{
text:"点击创建窗口"
onClicked: {
FluApp.navigate("/singleInstanceWindow")
}
}
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluWindow{
//launchMode: FluWindow.Standard
//launchMode: FluWindow.SingleTask
launchMode: FluWindow.SingleInstance
}
'
}
FluArea{
Layout.fillWidth: true
height: 100 height: 100
paddings: 10 paddings: 10
Layout.topMargin: 20 Layout.topMargin: 20
Column{ Column{
spacing: 15 spacing: 15
anchors{ anchors{
@ -46,9 +126,19 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluButton{
text:"点击跳转"
onClicked: {
FluApp.navigate("/about")
}
}
'
}
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
height: 130 height: 130
paddings: 10 paddings: 10
Layout.topMargin: 20 Layout.topMargin: 20
@ -68,13 +158,30 @@ FluScrollablePage{
loginPageRegister.launch({username:"zhuzichu"}) loginPageRegister.launch({username:"zhuzichu"})
} }
} }
FluText{ FluText{
text:"登录窗口返回过来的密码->"+password text:"登录窗口返回过来的密码->"+password
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'property var loginPageRegister: registerForPageResult("/login")
Connections{
target: loginPageRegister
function onResult(data)
{
password = data.password
}
}
FluButton{
text:"点击跳转"
onClicked: {
loginPageRegister.launch({username:"zhuzichu"})
}
}
'
}
} }

83
example/T_Pivot.qml Normal file
View File

@ -0,0 +1,83 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "./component"
FluScrollablePage{
title:"Pivot"
leftPadding:10
rightPadding:10
bottomPadding:20
spacing: 0
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 400
paddings: 10
FluPivot{
anchors.fill: parent
currentIndex: 2
FluPivotItem{
title:"All"
contentItem:FluText{
text:"All emails go here."
}
}
FluPivotItem{
title:"Unread"
contentItem:FluText{
text:"Unread emails go here."
}
}
FluPivotItem{
title:"Flagged"
contentItem:FluText{
text:"Flagged emails go here."
}
}
FluPivotItem{
title:"Urgent"
contentItem:FluText{
text:"Urgent emails go here."
}
}
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluPivot{
anchors.fill: parent
FluPivotItem:{
text:"All"
contentItem: FluText{
text:"All emails go here."
}
}
FluPivotItem:{
text:"Unread"
contentItem: FluText{
text:"Unread emails go here."
}
}
FluPivotItem:{
text:"Flagged"
contentItem: FluText{
text:"Flagged emails go here."
}
}
FluPivotItem:{
text:"Urgent"
contentItem: FluText{
text:"Urgent emails go here."
}
}
}
'
}
}

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,30 +11,59 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluProgressBar{ FluArea{
Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
height: 260
paddings: 10
ColumnLayout{
spacing: 20
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluProgressBar{
} }
FluProgressRing{ FluProgressRing{
Layout.topMargin: 10
} }
FluProgressBar{ FluProgressBar{
id:progress_bar id:progress_bar
Layout.topMargin: 20
indeterminate: false indeterminate: false
} }
FluProgressRing{ FluProgressRing{
id:progress_ring id:progress_ring
Layout.topMargin: 10
indeterminate: false indeterminate: false
} }
FluSlider{ FluSlider{
Layout.topMargin: 30
value:50 value:50
onValueChanged:{ onValueChanged:{
progress_bar.progress = value/100 progress_bar.progress = value/100
progress_ring.progress = value/100 progress_ring.progress = value/100
} }
Layout.bottomMargin: 30
} }
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluProgressBar{
}
FluProgressRing{
}
FluProgressBar{
indeterminate: false
}
FluProgressRing{
indeterminate: false
}'
}
} }

View File

@ -0,0 +1,43 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "./component"
FluScrollablePage{
title:"RatingControl"
leftPadding:10
rightPadding:10
bottomPadding:20
spacing: 0
FluArea{
Layout.fillWidth: true
height: 100
paddings: 10
Layout.topMargin: 20
Column{
spacing: 10
anchors.verticalCenter: parent.verticalCenter
FluRatingControl{
}
FluRatingControl{
number:10
}
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluRatingControl{
}'
}
}

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Window import QtQuick.Window
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,6 +11,20 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 480
paddings: 10
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
RowLayout{ RowLayout{
Layout.topMargin: 20 Layout.topMargin: 20
@ -114,4 +129,23 @@ FluScrollablePage{
} }
Layout.topMargin: 10 Layout.topMargin: 10
} }
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluRectangle{
radius: [25,25,25,25]
width: 50
height: 50
Image{
asynchronous: true
anchors.fill: parent
source: "qrc:/res/svg/avatar_4.svg"
sourceSize: Qt.size(width,height)
}
}'
}
} }

88
example/T_Settings.qml Normal file
View File

@ -0,0 +1,88 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///global/"
import "./component"
FluScrollablePage{
title:"Settings"
leftPadding:10
rightPadding:10
bottomPadding:20
spacing: 0
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 168
paddings: 10
ColumnLayout{
spacing: 10
anchors{
top: parent.top
left: parent.left
}
FluText{
text:lang.navigation_view_display_mode
fontStyle: FluText.BodyStrong
Layout.bottomMargin: 4
}
Repeater{
id:repeater
model: [{title:"Open",mode:FluNavigationView.Open},{title:"Compact",mode:FluNavigationView.Compact},{title:"Minimal",mode:FluNavigationView.Minimal},{title:"Auto",mode:FluNavigationView.Auto}]
delegate: FluRadioButton{
selected : MainEvent.displayMode===modelData.mode
text:modelData.title
onClicked:{
MainEvent.displayMode = modelData.mode
}
}
}
}
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 168
paddings: 10
ColumnLayout{
spacing: 10
anchors{
top: parent.top
left: parent.left
}
FluText{
text:lang.locale
fontStyle: FluText.BodyStrong
Layout.bottomMargin: 4
}
Flow{
spacing: 5
Repeater{
model: ["Zh","En"]
delegate: FluRadioButton{
selected : appInfo.lang.objectName === modelData
text:modelData
onClicked:{
console.debug(modelData)
appInfo.changeLang(modelData)
}
}
}
}
}
}
}

View File

@ -2,6 +2,7 @@
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import "./component"
import FluentUI import FluentUI
FluScrollablePage{ FluScrollablePage{
@ -10,17 +11,46 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluSlider{ FluArea{
Layout.fillWidth: true
height: 100
paddings: 10
Layout.topMargin: 20 Layout.topMargin: 20
value: 50
Layout.leftMargin: 10
}
FluSlider{ FluSlider{
value: 50
anchors.verticalCenter: parent.verticalCenter
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluSlider{
value:50
}'
}
FluArea{
Layout.fillWidth: true
height: 200
paddings: 10
Layout.topMargin: 20
FluSlider{
value: 50
vertical:true
anchors.left: parent.left
anchors.leftMargin: 20
anchors.verticalCenter: parent.verticalCenter
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluSlider{
vertical:true vertical:true
Layout.topMargin: 20
Layout.leftMargin: 10
Layout.bottomMargin: 20
value:50 value:50
}'
} }
} }

91
example/T_StatusView.qml Normal file
View File

@ -0,0 +1,91 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Window
import FluentUI
import "./component"
FluScrollablePage{
title:"StatusView"
leftPadding:10
rightPadding:10
bottomPadding:20
spacing: 0
FluArea{
id:layout_actions
Layout.fillWidth: true
Layout.topMargin: 20
height: 50
paddings: 10
RowLayout{
spacing: 14
FluDropDownButton{
id:btn_status_mode
Layout.preferredWidth: 140
text:"Loading"
items:[
FluMenuItem{
text:"Loading"
onClicked: {
btn_status_mode.text = text
status_view.statusMode = FluStatusView.Loading
}
},
FluMenuItem{
text:"Empty"
onClicked: {
btn_status_mode.text = text
status_view.statusMode = FluStatusView.Empty
}
},
FluMenuItem{
text:"Error"
onClicked: {
btn_status_mode.text = text
status_view.statusMode = FluStatusView.Error
}
},
FluMenuItem{
text:"Success"
onClicked: {
btn_status_mode.text = text
status_view.statusMode = FluStatusView.Success
}
}
]
}
}
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 10
height: 380
paddings: 10
FluStatusView{
id:status_view
anchors.fill: parent
onErrorClicked:{
showError("点击重新加载")
}
Rectangle {
anchors.fill: parent
color:FluTheme.primaryColor.dark
}
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluStatusView{
anchors.fill: parent
statusMode: FluStatusView.Loading
Rectangle{
anchors.fill: parent
color:FluTheme.primaryColor.dark
}
}'
}
}

View File

@ -3,6 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,6 +11,7 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
property var colors : [FluColors.Yellow,FluColors.Orange,FluColors.Red,FluColors.Magenta,FluColors.Purple,FluColors.Blue,FluColors.Teal,FluColors.Green] property var colors : [FluColors.Yellow,FluColors.Orange,FluColors.Red,FluColors.Magenta,FluColors.Purple,FluColors.Blue,FluColors.Teal,FluColors.Green]
@ -32,7 +34,7 @@ FluScrollablePage{
} }
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
height: 50 height: 50
paddings: 10 paddings: 10
@ -98,8 +100,8 @@ FluScrollablePage{
} }
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
Layout.topMargin: 5 Layout.topMargin: 15
height: 400 height: 400
paddings: 10 paddings: 10
FluTabView{ FluTabView{
@ -109,5 +111,27 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluTabView{
anchors.fill: parent
Component.onCompleted: {
newTab()
newTab()
newTab()
}
Component{
id:com_page
Rectangle{
anchors.fill: parent
color: argument
}
}
function newTab(){
tab_view.appendTab("qrc:/res/image/favicon.ico","Document 1",com_page,argument)
}
}
'
}
} }

160
example/T_TableView.qml Normal file
View File

@ -0,0 +1,160 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "./component"
FluScrollablePage{
title:"TableView"
leftPadding:10
rightPadding:10
bottomPadding:20
spacing: 0
Component.onCompleted: {
const columns = [
{
title: '姓名',
dataIndex: 'name',
width:100
},
{
title: '年龄',
dataIndex: 'age',
width:100
},
{
title: '住址',
dataIndex: 'address',
width:200
},
{
title: '别名',
dataIndex: 'nickname',
width:100
},
{
title: '操作',
dataIndex: 'action',
width:100
},
];
table_view.columns = columns
loadData(1,10)
}
FluTableView{
id:table_view
Layout.fillWidth: true
Layout.topMargin: 20
pageCurrent:1
pageCount:10
itemCount: 1000
onRequestPage:
(page,count)=> {
loadData(page,count)
}
}
Component{
id:com_action
Item{
Row{
anchors.centerIn: parent
spacing: 10
FluFilledButton{
text:"编辑"
topPadding:3
bottomPadding:3
leftPadding:3
rightPadding:3
onClicked:{
console.debug(dataModel.index)
showSuccess(JSON.stringify(dataObject))
}
}
FluFilledButton{
text:"删除"
topPadding:3
bottomPadding:3
leftPadding:3
rightPadding:3
onClicked:{
showError(JSON.stringify(dataObject))
}
}
}
}
}
function loadData(page,count){
const dataSource = []
for(var i=0;i<count;i++){
dataSource.push({
name: "孙悟空%1".arg(((page-1)*count+i)),
age: 500,
address: "钟灵毓秀的花果山,如神仙仙境的水帘洞",
nickname: "齐天大圣",
action:com_action
})
}
table_view.dataSource = dataSource
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: 10
code:'FluTableView{
id:table_view
Layout.fillWidth: true
Layout.topMargin: 20
width:parent.width
pageCurrent:1
pageCount:10
itemCount: 1000
onRequestPage:
(page,count)=> {
loadData(page,count)
}
Component.onCompleted: {
const columns = [
{
title: "姓名",
dataIndex: "name",
width:100
},
{
title: "年龄",
dataIndex: "age",
width:100
},
{
title: "住址",
dataIndex: "address",
width:200
},
{
title: "别名",
dataIndex: "nickname",
width:100
}
];
table_view.columns = columns
const dataSource = [
{
name: "孙悟空”,
age: 500,
address:"钟灵毓秀的花果山,如神仙仙境的水帘洞",
nickname:"齐天大圣"
}
];
table_view.dataSource = columns
}
}'
}
}

View File

@ -3,6 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,32 +11,122 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluArea{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
FluTextBox{ FluTextBox{
Layout.topMargin: 20 Layout.topMargin: 20
placeholderText: "单行输入框" placeholderText: "单行输入框"
Layout.preferredWidth: 300 Layout.preferredWidth: 300
disabled:toggle_switch.selected disabled:text_box_switch.selected
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
} }
FluMultiLineTextBox{
Layout.topMargin: 20
Layout.preferredWidth: 300
placeholderText: "多行输入框"
disabled:toggle_switch.selected
}
FluAutoSuggestBox{
Layout.topMargin: 20
items:generateRandomNames(100)
placeholderText: "AutoSuggestBox"
Layout.preferredWidth: 300
disabled:toggle_switch.selected
} }
FluToggleSwitch{ Row{
id:toggle_switch spacing: 5
text:"Disabled" anchors{
Layout.topMargin: 20 verticalCenter: parent.verticalCenter
right: parent.right
} }
FluToggleSwitch{
id:text_box_switch
Layout.alignment: Qt.AlignRight
text:"Disabled"
}
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluTextBox{
placeholderText:"单行输入框"
}'
}
FluArea{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
FluMultilineTextBox{
Layout.topMargin: 20
placeholderText: "多行输入框"
Layout.preferredWidth: 300
disabled:text_box_multi_switch.selected
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
}
Row{
spacing: 5
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
}
FluToggleSwitch{
id:text_box_multi_switch
Layout.alignment: Qt.AlignRight
text:"Disabled"
}
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluMultilineTextBox{
placeholderText:"多行输入框"
}'
}
FluArea{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
FluAutoSuggestBox{
Layout.topMargin: 20
placeholderText: "AutoSuggestBox"
Layout.preferredWidth: 300
items:generateRandomNames(100)
disabled:text_box_suggest_switch.selected
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
}
Row{
spacing: 5
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
}
FluToggleSwitch{
id:text_box_suggest_switch
Layout.alignment: Qt.AlignRight
text:"Disabled"
}
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluAutoSuggestBox{
placeholderText:"AutoSuggestBox"
}'
}
function generateRandomNames(numNames) { function generateRandomNames(numNames) {
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,9 +11,20 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
RowLayout{ FluArea{
Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
height: 210
paddings: 10
ColumnLayout{
spacing:0
anchors{
left: parent.left
}
RowLayout{
Layout.topMargin: 10
Repeater{ Repeater{
model: [FluColors.Yellow,FluColors.Orange,FluColors.Red,FluColors.Magenta,FluColors.Purple,FluColors.Blue,FluColors.Teal,FluColors.Green] model: [FluColors.Yellow,FluColors.Orange,FluColors.Red,FluColors.Magenta,FluColors.Purple,FluColors.Blue,FluColors.Teal,FluColors.Green]
delegate: FluRectangle{ delegate: FluRectangle{
@ -43,6 +55,7 @@ FluScrollablePage{
Layout.topMargin: 20 Layout.topMargin: 20
} }
FluToggleSwitch{ FluToggleSwitch{
Layout.topMargin: 5
selected: FluTheme.dark selected: FluTheme.dark
clickFunc:function(){ clickFunc:function(){
FluTheme.dark = !FluTheme.dark FluTheme.dark = !FluTheme.dark
@ -53,9 +66,23 @@ FluScrollablePage{
Layout.topMargin: 20 Layout.topMargin: 20
} }
FluToggleSwitch{ FluToggleSwitch{
Layout.topMargin: 5
selected: FluTheme.nativeText selected: FluTheme.nativeText
clickFunc:function(){ clickFunc:function(){
FluTheme.nativeText = !FluTheme.nativeText FluTheme.nativeText = !FluTheme.nativeText
} }
} }
} }
}
CodeExpander{
Layout.fillWidth: true
code:'FluTheme.primaryColor = FluColors.Orange
FluTheme.dark = true
FluTheme.nativeText = true
'
}
}

View File

@ -3,6 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,9 +11,10 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
height: 80 height: 80
paddings: 10 paddings: 10
@ -33,10 +35,15 @@ FluScrollablePage{
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluTimePicker{
}'
}
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
height: 80 height: 80
paddings: 10 paddings: 10
@ -49,7 +56,7 @@ FluScrollablePage{
} }
FluText{ FluText{
text:"hourFormat=FluTimePicker.HH" text:"hourFormat=FluTimePicker.H"
} }
FluTimePicker{ FluTimePicker{
@ -58,6 +65,11 @@ FluScrollablePage{
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluTimePicker{
hourFormat:FluTimePicker.HH
}'
}
} }

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,12 +11,29 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluToggleSwitch{ FluArea{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20 Layout.topMargin: 20
Row{
spacing: 30
anchors.verticalCenter: parent.verticalCenter
FluToggleSwitch{
} }
FluToggleSwitch{ FluToggleSwitch{
Layout.topMargin: 20
text:"Text" text:"Text"
} }
} }
}
CodeExpander{
Layout.fillWidth: true
code:'FluToggleSwitch{
text:"Text"
}'
}
}

View File

@ -3,6 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import FluentUI import FluentUI
import "./component"
FluScrollablePage{ FluScrollablePage{
@ -10,15 +11,15 @@ FluScrollablePage{
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
FluText{ FluText{
Layout.topMargin: 20 Layout.topMargin: 20
text:"鼠标悬停不动弹出Tooltip" text:"鼠标悬停不动弹出Tooltip"
} }
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
height: 68 height: 68
paddings: 10 paddings: 10
@ -42,9 +43,21 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluIconButton{
iconSource:FluentIcons.ChromeCloseContrast
iconSize: 15
text:"删除"
onClicked:{
showSuccess("点击IconButton")
}
}
'
}
FluArea{ FluArea{
width: parent.width Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
height: 68 height: 68
paddings: 10 paddings: 10
@ -72,6 +85,22 @@ FluScrollablePage{
} }
} }
} }
CodeExpander{
Layout.fillWidth: true
code:'FluButton{
id:button_1
text:"删除"
FluTooltip{
visible: button_1.hovered
text:button_1.text
delay: 1000
}
onClicked:{
showSuccess("点击一个Button")
}
}
'
}
} }

View File

@ -3,13 +3,15 @@ import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import FluentUI import FluentUI
import "./component"
FluContentPage { FluScrollablePage {
title:"TreeView" title:"TreeView"
leftPadding:10 leftPadding:10
rightPadding:10 rightPadding:10
bottomPadding:20 bottomPadding:20
spacing: 0
function randomName() { function randomName() {
var names = ["张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"] var names = ["张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"]
@ -50,71 +52,42 @@ FluContentPage {
return [tree_view.createItem(randomCompany(), true, subtrees)].concat(createOrg(numLevels - 1, numSubtrees, numEmployees)) return [tree_view.createItem(randomCompany(), true, subtrees)].concat(createOrg(numLevels - 1, numSubtrees, numEmployees))
} }
FluArea{
FluTreeView{ id:layout_actions
id:tree_view Layout.fillWidth: true
width:240 Layout.topMargin: 20
anchors{ height: 50
top:parent.top paddings: 10
left:parent.left RowLayout{
bottom:parent.bottom spacing: 14
} FluDropDownButton{
onItemClicked: id:btn_selection_model
(model)=>{ Layout.preferredWidth: 140
showSuccess(model.text) text:"None"
} items:[
FluMenuItem{
Component.onCompleted: {
var org = createOrg(3, 3, 3)
updateData(org)
}
}
ColumnLayout{
anchors{
left: tree_view.right
right: parent.right
top: parent.top
}
FluText{
text:{
if(tree_view.selectionMode === FluTreeView.None){
return "selectionMode->FluTreeView.None"
}
if(tree_view.selectionMode === FluTreeView.Single){
return "selectionMode->FluTreeView.Single"
}
if(tree_view.selectionMode === FluTreeView.Multiple){
return "selectionMode->FluTreeView.Multiple"
}
}
}
FluButton{
text:"None" text:"None"
onClicked: { onClicked: {
tree_view.selectionMode = FluTreeView.None btn_selection_model.text = text
tree_view.selectionMode = FluTabView.Equal
} }
} },
FluMenuItem{
FluButton{
text:"Single" text:"Single"
onClicked: { onClicked: {
tree_view.selectionMode = FluTreeView.Single btn_selection_model.text = text
tree_view.selectionMode = FluTabView.SizeToContent
} }
} },
FluMenuItem{
FluButton{ text:"Muiltple"
text:"Multiple"
onClicked: { onClicked: {
tree_view.selectionMode = FluTreeView.Multiple btn_selection_model.text = text
tree_view.selectionMode = FluTabView.Compact
} }
} }
]
}
FluFilledButton{ FluFilledButton{
text:"获取选中的数据" text:"获取选中的数据"
onClicked: { onClicked: {
@ -139,6 +112,50 @@ FluContentPage {
} }
} }
} }
}
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 10
paddings: 10
height: 400
FluTreeView{
id:tree_view
width:240
anchors{
top:parent.top
left:parent.left
bottom:parent.bottom
}
onItemClicked:
(model)=>{
showSuccess(model.text)
}
Component.onCompleted: {
var org = createOrg(3, 3, 3)
createItem()
updateData(org)
}
}
}
CodeExpander{
Layout.fillWidth: true
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

@ -15,15 +15,19 @@ FluContentPage {
slider.seek(0) slider.seek(0)
} }
ScrollView{ FluArea{
clip: true anchors{
width: parent.width top:parent.top
contentWidth: parent.width left: parent.left
right: parent.right
bottom: parent.bottom
topMargin: 20
}
paddings: 10
ColumnLayout{ ColumnLayout{
spacing: 0 spacing: 0
FluText{ FluText{
text:"Display" text:"Display"
Layout.topMargin: 20
padding: 0 padding: 0
pixelSize: textSize pixelSize: textSize
fontStyle: FluText.Display fontStyle: FluText.Display
@ -65,8 +69,6 @@ FluContentPage {
fontStyle: FluText.Caption fontStyle: FluText.Caption
} }
} }
}
FluSlider{ FluSlider{
id:slider id:slider
@ -83,3 +85,10 @@ FluContentPage {
} }
} }
}

View File

@ -0,0 +1,131 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
FluExpander{
property string code: ""
headerText: "Source"
contentHeight:content.height
FluMultilineTextBox{
id:content
width:parent.width
readOnly:true
text:highlightQmlCode(code)
focus:false
textFormat: FluMultilineTextBox.RichText
KeyNavigation.priority: KeyNavigation.BeforeItem
background:Rectangle{
radius: 4
color:FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(247/255,247/255,247/255,1)
border.color: FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
border.width: 1
}
}
FluIconButton{
iconSource:FluentIcons.Copy
anchors{
right: parent.right
top: parent.top
rightMargin: 5
topMargin: 5
}
onClicked:{
FluApp.clipText(content.text)
showSuccess("复制成功")
}
}
function htmlEncode(e){
var i,s;
for(i in s={
"&":/&/g,//""//":/"/g,"'":/'/g,
"<":/</g,">":/>/g,"<br/>":/\n/g,
" ":/ /g," ":/\t/g
})e=e.replace(s[i],i);
return e;
}
function highlightQmlCode(code) {
// 定义 QML 关键字列表
var qmlKeywords = [
"FluTextButton",
"FluAppBar",
"FluAutoSuggestBox",
"FluBadge",
"FluButton",
"FluCalendarPicker",
"FluCalendarView",
"FluCarousel",
"FluCheckBox",
"FluColorPicker",
"FluColorView",
"FluComboBox",
"FluContentDialog",
"FluContentPage",
"FluControl",
"FluDatePicker",
"FluDivider",
"FluDropDownButton",
"FluExpander",
"FluFilledButton",
"FluFlipView",
"FluFocusRectangle",
"FluIcon",
"FluIconButton",
"FluInfoBar",
"FluItem",
"FluMediaPlayer",
"FluMenu",
"FluMenuItem",
"FluMultilineTextBox",
"FluNavigationView",
"FluObject",
"FluPaneItem",
"FluPaneItemExpander",
"FluPaneItemHeader",
"FluPaneItemSeparator",
"FluPivot",
"FluPivotItem",
"FluProgressBar",
"FluProgressRing",
"FluRadioButton",
"FluRectangle",
"FluScrollablePage",
"FluScrollBar",
"FluShadow",
"FluSlider",
"FluTabView",
"FluText",
"FluTextArea",
"FluTextBox",
"FluTextBoxBackground",
"FluTextBoxMenu",
"FluTextButton",
"FluTextFiled",
"FluTimePicker",
"FluToggleSwitch",
"FluTooltip",
"FluTreeView",
"FluWindow",
"FluWindowResize",
"FluToggleButton",
"FluTableView",
"FluColors",
"FluTheme",
"FluStatusView",
"FluRatingControl"
];
code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;");
return code.replace(RegExp("\\b(" + qmlKeywords.join("|") + ")\\b", "g"), "<span style='color: #c23a80'>$1</span>");
}
}

View File

@ -3,10 +3,19 @@ CONFIG += c++17
DEFINES += QT_DEPRECATED_WARNINGS QT_NO_WARNING_OUTPUT DEFINES += QT_DEPRECATED_WARNINGS QT_NO_WARNING_OUTPUT
HEADERS += \ HEADERS += \
ChatController.h lang/En.h \
lang/Lang.h \
lang/Zh.h \
stdafx.h \
ChatController.h \
AppInfo.h
SOURCES += \ SOURCES += \
ChatController.cpp \ ChatController.cpp \
AppInfo.cpp \
lang/En.cpp \
lang/Lang.cpp \
lang/Zh.cpp \
main.cpp main.cpp
RESOURCES += qml.qrc RESOURCES += qml.qrc
@ -23,21 +32,15 @@ CONFIG(debug,debug|release) {
} }
win32 { win32 {
contains(QT_ARCH, i386) {
COPYDLL = $$absolute_path($${_PRO_FILE_PWD_}/../third/Win_x86/*.dll) $$DESTDIR
contains(QMAKE_CC, cl) { contains(QMAKE_CC, cl) {
QMAKE_PRE_LINK += $$QMAKE_COPY $$replace(COPYDLL, /, \\) COPYDLL = $$absolute_path($${_PRO_FILE_PWD_}/../third/msvc/*.dll) $$DESTDIR
QMAKE_PRE_LINK += $$QMAKE_COPY $$replace(COPYDLL, /, $$QMAKE_DIR_SEP)
} else { } else {
QMAKE_PRE_LINK += $$QMAKE_COPY $$COPYDLL COPYDLL = $$absolute_path($${_PRO_FILE_PWD_}/../third/mingw/*.dll) $$DESTDIR
} QMAKE_PRE_LINK += $$QMAKE_COPY $$replace(COPYDLL, /, $$QMAKE_DIR_SEP)
} else {
COPYDLL = $$absolute_path($${_PRO_FILE_PWD_}/../third/Win_x64/*.dll) $$DESTDIR
contains(QMAKE_CC, cl) {
QMAKE_PRE_LINK += $$QMAKE_COPY $$replace(COPYDLL, /, \\)
} else {
QMAKE_PRE_LINK += $$QMAKE_COPY $$COPYDLL
}
} }
} }
qnx: target.path = /tmp/$${TARGET}/bin qnx: target.path = /tmp/$${TARGET}/bin

View File

@ -5,17 +5,22 @@ import FluentUI
FluObject{ FluObject{
id:footer_items id:footer_items
property var navigationView
FluPaneItemSeparator{} FluPaneItemSeparator{}
FluPaneItem{ FluPaneItem{
title:"意见反馈" title:lang.about
onTap:{ icon:FluentIcons.Contact
Qt.openUrlExternally("https://github.com/zhuzichu520/FluentUI/issues/new") tapFunc:function(){
}
}
FluPaneItem{
title:"关于"
onTap:{
FluApp.navigate("/about") FluApp.navigate("/about")
} }
} }
FluPaneItem{
title:lang.settings
icon:FluentIcons.Settings
onTap:{
navigationView.push("qrc:/T_Settings.qml")
}
}
} }

View File

@ -3,23 +3,28 @@
import QtQuick import QtQuick
import FluentUI import FluentUI
FluObject{ FluObject{
property var navigationView property var navigationView
FluPaneItem{ FluPaneItem{
title:"Home" title:lang.home
icon:FluentIcons.Home // icon:FluentIcons.Home
cusIcon: Image{
anchors.centerIn: parent
source: FluTheme.dark ? "qrc:/res/svg/home_dark.svg" : "qrc:/res/svg/home.svg"
sourceSize: Qt.size(30,30)
width: 18
height: 18
}
onTap:{ onTap:{
navigationView.push("qrc:/T_Home.qml") navigationView.push("qrc:/T_Home.qml")
} }
} }
FluPaneItemExpander{ FluPaneItemExpander{
title:"Basic input" title:lang.basic_input
icon:FluentIcons.CheckboxComposite icon:FluentIcons.CheckboxComposite
FluPaneItem{ FluPaneItem{
title:"Buttons" title:"Buttons"
image:"qrc:/res/image/control/Button.png" image:"qrc:/res/image/control/Button.png"
@ -38,7 +43,6 @@ FluObject{
navigationView.push("qrc:/T_Slider.qml") navigationView.push("qrc:/T_Slider.qml")
} }
} }
FluPaneItem{ FluPaneItem{
title:"CheckBox" title:"CheckBox"
image:"qrc:/res/image/control/Checkbox.png" image:"qrc:/res/image/control/Checkbox.png"
@ -48,7 +52,6 @@ FluObject{
navigationView.push("qrc:/T_CheckBox.qml") navigationView.push("qrc:/T_CheckBox.qml")
} }
} }
FluPaneItem{ FluPaneItem{
title:"ToggleSwitch" title:"ToggleSwitch"
onTap:{ onTap:{
@ -58,7 +61,7 @@ FluObject{
} }
FluPaneItemExpander{ FluPaneItemExpander{
title:"Form" title:lang.form
icon:FluentIcons.GridView icon:FluentIcons.GridView
FluPaneItem{ FluPaneItem{
title:"TextBox" title:"TextBox"
@ -92,11 +95,9 @@ FluObject{
} }
} }
FluPaneItemExpander{ FluPaneItemExpander{
title:"Surface" title:lang.surface
icon:FluentIcons.SurfaceHub icon:FluentIcons.SurfaceHub
FluPaneItem{ FluPaneItem{
title:"InfoBar" title:"InfoBar"
image:"qrc:/res/image/control/InfoBar.png" image:"qrc:/res/image/control/InfoBar.png"
@ -106,46 +107,52 @@ FluObject{
navigationView.push("qrc:/T_InfoBar.qml") navigationView.push("qrc:/T_InfoBar.qml")
} }
} }
FluPaneItem{ FluPaneItem{
title:"Progress" title:"Progress"
onTap:{ onTap:{
navigationView.push("qrc:/T_Progress.qml") navigationView.push("qrc:/T_Progress.qml")
} }
} }
FluPaneItem{
title:"RatingControl"
onTap:{
navigationView.push("qrc:/T_RatingControl.qml")
}
}
FluPaneItem{ FluPaneItem{
title:"Badge" title:"Badge"
onTap:{ onTap:{
navigationView.push("qrc:/T_Badge.qml") navigationView.push("qrc:/T_Badge.qml")
} }
} }
FluPaneItem{ FluPaneItem{
title:"Rectangle" title:"Rectangle"
onTap:{ onTap:{
navigationView.push("qrc:/T_Rectangle.qml") navigationView.push("qrc:/T_Rectangle.qml")
} }
} }
FluPaneItem{
title:"StatusView"
onTap:{
navigationView.push("qrc:/T_StatusView.qml")
}
}
FluPaneItem{ FluPaneItem{
title:"Carousel" title:"Carousel"
onTap:{ onTap:{
navigationView.push("qrc:/T_Carousel.qml") navigationView.push("qrc:/T_Carousel.qml")
} }
} }
FluPaneItem{ FluPaneItem{
title:"Expander" title:"Expander"
onTap:{ onTap:{
navigationView.push("qrc:/T_Expander.qml") navigationView.push("qrc:/T_Expander.qml")
} }
} }
} }
FluPaneItemExpander{ FluPaneItemExpander{
title:"Popus" title:lang.popus
icon:FluentIcons.ButtonMenu icon:FluentIcons.ButtonMenu
FluPaneItem{ FluPaneItem{
title:"Dialog" title:"Dialog"
@ -153,14 +160,12 @@ FluObject{
navigationView.push("qrc:/T_Dialog.qml") navigationView.push("qrc:/T_Dialog.qml")
} }
} }
FluPaneItem{ FluPaneItem{
title:"Tooltip" title:"Tooltip"
onTap:{ onTap:{
navigationView.push("qrc:/T_Tooltip.qml") navigationView.push("qrc:/T_Tooltip.qml")
} }
} }
FluPaneItem{ FluPaneItem{
title:"Menu" title:"Menu"
onTap:{ onTap:{
@ -170,12 +175,23 @@ FluObject{
} }
FluPaneItemExpander{ FluPaneItemExpander{
title:"Navigation" title:lang.navigation
icon:FluentIcons.AllApps icon:FluentIcons.AllApps
FluPaneItem{
title:"Pivot"
image:"qrc:/res/image/control/Pivot.png"
recentlyAdded:true
order:3
desc:"Presents information from different sources in atabbed view."
onTap:{
navigationView.push("qrc:/T_Pivot.qml")
}
}
FluPaneItem{ FluPaneItem{
title:"TabView" title:"TabView"
image:"qrc:/res/image/control/TabView.png" image:"qrc:/res/image/control/TabView.png"
recentlyAdded:true recentlyAdded:true
order:1
desc:"A control that displays a collection of tabs thatcan be used to display several documents." desc:"A control that displays a collection of tabs thatcan be used to display several documents."
onTap:{ onTap:{
navigationView.push("qrc:/T_TabView.qml") navigationView.push("qrc:/T_TabView.qml")
@ -187,18 +203,36 @@ FluObject{
navigationView.push("qrc:/T_TreeView.qml") navigationView.push("qrc:/T_TreeView.qml")
} }
} }
FluPaneItem{
title:"TableView"
image:"qrc:/res/image/control/DataGrid.png"
recentlyAdded:true
order:4
desc:"The TableView control provides a flexible way to display a collection of data in rows and columns"
onTap:{
navigationView.push("qrc:/T_TableView.qml")
}
}
FluPaneItem{ FluPaneItem{
title:"MultiWindow" title:"MultiWindow"
onTap:{ onTap:{
navigationView.push("qrc:/T_MultiWindow.qml") navigationView.push("qrc:/T_MultiWindow.qml")
} }
} }
FluPaneItem{
title:"FlipView"
image:"qrc:/res/image/control/FlipView.png"
recentlyAdded:true
order:2
desc:"Presents a collection of items that the user canflip through, one item at a time."
onTap:{
navigationView.push("qrc:/T_FlipView.qml")
}
}
} }
FluPaneItemExpander{ FluPaneItemExpander{
title:"Theming" title:lang.theming
icon:FluentIcons.Brightness icon:FluentIcons.Brightness
FluPaneItem{ FluPaneItem{
title:"Theme" title:"Theme"
@ -206,28 +240,28 @@ FluObject{
navigationView.push("qrc:/T_Theme.qml") navigationView.push("qrc:/T_Theme.qml")
} }
} }
FluPaneItem{
title:"Awesome"
onTap:{
navigationView.push("qrc:/T_Awesome.qml")
}
}
FluPaneItem{ FluPaneItem{
title:"Typography" title:"Typography"
onTap:{ onTap:{
navigationView.push("qrc:/T_Typography.qml") navigationView.push("qrc:/T_Typography.qml")
} }
} }
FluPaneItem{
title:"Awesome"
onTap:{
navigationView.push("qrc:/T_Awesome.qml")
}
}
} }
FluPaneItemExpander{ FluPaneItemExpander{
title:"Media" title:lang.media
icon:FluentIcons.Media icon:FluentIcons.Media
FluPaneItem{ FluPaneItem{
title:"MediaPlayer" title:"MediaPlayer"
image:"qrc:/res/image/control/MediaPlayerElement.png" image:"qrc:/res/image/control/MediaPlayerElement.png"
recentlyAdded:true recentlyAdded:true
order:0
desc:"A control to display video and image content." desc:"A control to display video and image content."
onTap:{ onTap:{
navigationView.push("qrc:/T_MediaPlayer.qml") navigationView.push("qrc:/T_MediaPlayer.qml")
@ -251,6 +285,7 @@ FluObject{
} }
} }
} }
arr.sort(function(o1,o2){ return o2.order-o1.order })
return arr return arr
} }
@ -279,21 +314,7 @@ FluObject{
} }
function startPageByItem(data){ function startPageByItem(data){
var items = navigationView.getItems(); navigationView.startPageByItem(data)
for(var i=0;i<items.length;i++){
var item = items[i]
if(item.key === data.key){
if(navigationView.getCurrentIndex() === i){
return
}
item.tap()
navigationView.setCurrentIndex(i)
if(item.parent){
item.parent.isExpand = true
}
return
}
}
} }
} }

View File

@ -0,0 +1,9 @@
pragma Singleton
import QtQuick
import QtQuick.Controls
import FluentUI
QtObject {
property int displayMode : FluNavigationView.Auto
}

View File

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

21
example/lang/En.cpp Normal file
View File

@ -0,0 +1,21 @@
#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");
search("Search");
about("About");
settings("Settings");
locale("Locale");
navigation_view_display_mode("NavigationView Display Mode");
}

17
example/lang/En.h Normal file
View File

@ -0,0 +1,17 @@
#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

7
example/lang/Lang.cpp Normal file
View File

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

29
example/lang/Lang.h Normal file
View File

@ -0,0 +1,29 @@
#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,search);
Q_PROPERTY_AUTO(QString,about);
Q_PROPERTY_AUTO(QString,settings);
Q_PROPERTY_AUTO(QString,navigation_view_display_mode);
Q_PROPERTY_AUTO(QString,locale);
public:
explicit Lang(QObject *parent = nullptr);
};
#endif // LANG_H

21
example/lang/Zh.cpp Normal file
View File

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

17
example/lang/Zh.h Normal file
View File

@ -0,0 +1,17 @@
#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

@ -5,14 +5,10 @@
#include <QQuickWindow> #include <QQuickWindow>
#include <QQuickStyle> #include <QQuickStyle>
#include <QProcess> #include <QProcess>
#include "lang/Lang.h"
#include "AppInfo.h"
#include "ChatController.h" #include "ChatController.h"
QMap<QString, QVariant> properties(){
QMap<QString, QVariant> map;
// map["installHelper"] = QVariant::fromValue(QVariant::fromValue(InstallHelper::getInstance()));
return map;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication::setOrganizationName("ZhuZiChu"); QCoreApplication::setOrganizationName("ZhuZiChu");
@ -20,18 +16,17 @@ int main(int argc, char *argv[])
QCoreApplication::setApplicationName("FluentUI"); QCoreApplication::setApplicationName("FluentUI");
QQuickStyle::setStyle("Basic"); QQuickStyle::setStyle("Basic");
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
app.setQuitOnLastWindowClosed(false);
QQmlApplicationEngine engine; QQmlApplicationEngine engine;
qmlRegisterType<ChatController>("Controller",1,0,"ChatController"); qmlRegisterType<ChatController>("Controller",1,0,"ChatController");
AppInfo* appInfo = new AppInfo();
QMapIterator<QString, QVariant> iterator(properties()); QQmlContext * context = engine.rootContext();
while (iterator.hasNext()) { Lang* lang = appInfo->lang();
iterator.next(); context->setContextProperty("lang",lang);
QString key = iterator.key(); QObject::connect(appInfo,&AppInfo::langChanged,&app,[context,appInfo]{
QVariant value = iterator.value(); context->setContextProperty("lang",appInfo->lang());
engine.rootContext()->setContextProperty(key,value); });
} context->setContextProperty("appInfo",appInfo);
engine.rootContext()->setContextProperty("properties",properties());
const QUrl url(QStringLiteral("qrc:/App.qml")); const QUrl url(QStringLiteral("qrc:/App.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) { &app, [url](QObject *obj, const QUrl &objUrl) {

View File

@ -5,12 +5,15 @@ import FluentUI
FluWindow { FluWindow {
width: 500 id:window
width: 600
height: 600 height: 600
minimumWidth: 500 minimumWidth: 600
minimumHeight: 600 minimumHeight: 600
maximumWidth: 500 maximumWidth: 600
maximumHeight: 600 maximumHeight: 600
launchMode: FluWindow.SingleTask
title:"关于" title:"关于"
@ -36,7 +39,7 @@ FluWindow {
fontStyle: FluText.Title fontStyle: FluText.Title
} }
FluText{ FluText{
text:"v1.1.7" text:"v%1".arg(appInfo.version)
fontStyle: FluText.Body fontStyle: FluText.Body
Layout.alignment: Qt.AlignBottom Layout.alignment: Qt.AlignBottom
} }
@ -57,7 +60,6 @@ FluWindow {
RowLayout{ RowLayout{
spacing: 14 spacing: 14
Layout.topMargin: 20
Layout.leftMargin: 15 Layout.leftMargin: 15
FluText{ FluText{
text:"GitHub" text:"GitHub"
@ -71,13 +73,28 @@ FluWindow {
} }
} }
} }
RowLayout{
spacing: 14
Layout.leftMargin: 15
FluText{
text:"B站"
}
FluTextButton{
text:"https://www.bilibili.com/video/BV1mg4y1M71w/"
Layout.alignment: Qt.AlignBottom
onClicked: {
Qt.openUrlExternally(text)
}
}
}
RowLayout{ RowLayout{
spacing: 14 spacing: 14
Layout.topMargin: 20
Layout.leftMargin: 15 Layout.leftMargin: 15
FluText{ FluText{
id:text_info id:text_info
text:"如果该项目对你有作用就请点击上方链接给一个免费的star" text:"如果该项目对你有作用就请点击上方链接给一个免费的star,或者一键三连,谢谢"
ColorAnimation { ColorAnimation {
id: animation id: animation
target: text_info target: text_info
@ -91,5 +108,43 @@ FluWindow {
} }
} }
} }
RowLayout{
spacing: 14
Layout.leftMargin: 15
FluText{
text:"捐赠:"
}
}
Item{
Layout.preferredWidth: parent.width
Layout.preferredHeight: 252
Row{
anchors.horizontalCenter: parent.horizontalCenter
spacing: 60
Image{
width: 164.55
height: 224.25
source: "qrc:/res/image/qrcode_wx.jpg"
}
Image{
width: 162
height: 252
source: "qrc:/res/image/qrcode_zfb.jpg"
}
}
}
RowLayout{
spacing: 14
Layout.leftMargin: 15
FluText{
id:text_desc
text:"个人开发,维护不易,你们的捐赠就是我继续更新的动力!\n有什么问题提Issues只要时间充足我就会解决的"
}
}
} }
} }

View File

@ -183,7 +183,7 @@ FluWindow {
rightMargin: 10 rightMargin: 10
} }
height: Math.min(textbox.implicitHeight,64) height: Math.min(textbox.implicitHeight,64)
FluMultiLineTextBox{ FluMultilineTextBox{
id:textbox id:textbox
focus:true focus:true
placeholderText: "请输入消息" placeholderText: "请输入消息"

View File

@ -1,5 +1,6 @@
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Controls
import FluentUI import FluentUI
FluWindow { FluWindow {
@ -11,8 +12,6 @@ FluWindow {
minimumHeight: 400 minimumHeight: 400
maximumWidth: 400 maximumWidth: 400
maximumHeight: 400 maximumHeight: 400
modality:2
title:"登录" title:"登录"
onInitArgument: onInitArgument:

View File

@ -2,22 +2,48 @@
import QtQuick.Window import QtQuick.Window
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import "qrc:///global/" import Qt.labs.platform
import FluentUI import FluentUI
import "qrc:///global/"
FluWindow { FluWindow {
id:rootwindow id:window
width: 1000 width: 1000
height: 640 height: 640
title: "FluentUI" title: "FluentUI"
closeDestory:false
minimumWidth: 520 minimumWidth: 520
minimumHeight: 460 minimumHeight: 460
FluAppBar{ FluAppBar{
id:appbar id:appbar
z:10 z:9
showDark: true showDark: true
width:parent.width width:parent.width
darkText: lang.dark_mode
}
SystemTrayIcon {
visible: true
icon.source: "qrc:/res/image/favicon.ico"
tooltip: "FluentUI"
menu: Menu {
MenuItem {
text: "退出"
onTriggered: {
window.destoryWindow()
FluApp.closeApp()
}
}
}
onActivated:
(reason)=>{
if(reason === SystemTrayIcon.Trigger){
window.show()
window.raise()
window.requestActivate()
}
}
} }
@ -26,15 +52,16 @@ FluWindow {
anchors.fill: parent anchors.fill: parent
items: ItemsOriginal items: ItemsOriginal
footerItems:ItemsFooter footerItems:ItemsFooter
logo: "qrc:/res/image/favicon.ico"
z:11 z:11
displayMode:MainEvent.displayMode
logo: "qrc:/res/image/favicon.ico"
title:"FluentUI" title:"FluentUI"
autoSuggestBox:FluAutoSuggestBox{ autoSuggestBox:FluAutoSuggestBox{
width: 280 width: 280
anchors.centerIn: parent anchors.centerIn: parent
iconSource: FluentIcons.Zoom iconSource: FluentIcons.Search
items: ItemsOriginal.getSearchData() items: ItemsOriginal.getSearchData()
placeholderText: "查找" placeholderText: lang.search
onItemClicked: onItemClicked:
(data)=>{ (data)=>{
ItemsOriginal.startPageByItem(data) ItemsOriginal.startPageByItem(data)
@ -42,8 +69,8 @@ FluWindow {
} }
Component.onCompleted: { Component.onCompleted: {
ItemsOriginal.navigationView = nav_view ItemsOriginal.navigationView = nav_view
ItemsFooter.navigationView = nav_view
nav_view.setCurrentIndex(0) nav_view.setCurrentIndex(0)
nav_view.push("qrc:/T_Home.qml")
} }
} }

View File

@ -12,6 +12,10 @@ FluWindow {
title:"视频播放器" title:"视频播放器"
onInitArgument:
(argument)=>{
player.source = argument.source
}
FluAppBar{ FluAppBar{
id:appbar id:appbar
@ -28,10 +32,6 @@ FluWindow {
top: appbar.bottom top: appbar.bottom
bottom: parent.bottom bottom: parent.bottom
} }
// source:"http://mirror.aarnet.edu.au/pub/TED-talks/911Mothers_2010W-480p.mp4"
source:"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
// source:"http://video.chinanews.com/flv/2019/04/23/400/111773_web.mp4"
} }
} }

View File

@ -0,0 +1,46 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
FluWindow {
id:window
width: 500
height: 600
minimumWidth: 500
minimumHeight: 600
maximumWidth: 500
maximumHeight: 600
launchMode: FluWindow.SingleInstance
title:"SingleInstance"
FluAppBar{
id:appbar
title:"SingleInstance"
width:parent.width
}
FluTextBox{
anchors{
top:parent.top
topMargin:60
horizontalCenter: parent.horizontalCenter
}
}
FluText{
wrapMode: Text.WrapAnywhere
anchors{
left: parent.left
right: parent.right
leftMargin: 20
rightMargin: 20
verticalCenter: parent.verticalCenter
}
text:"我是一个SingleInstance模式的窗口如果我存在我会销毁之前的窗口并创建一个新窗口"
}
}

View File

@ -0,0 +1,31 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
FluWindow {
id:window
width: 500
height: 600
minimumWidth: 500
minimumHeight: 600
maximumWidth: 500
maximumHeight: 600
launchMode: FluWindow.SingleTask
title:"SingleTask"
FluAppBar{
id:appbar
title:"SingleTask"
width:parent.width
}
FluText{
anchors.centerIn: parent
text:"我是一个SingleTask模式的窗口如果我存在我就激活窗口"
}
}

View File

@ -0,0 +1,31 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
FluWindow {
id:window
width: 500
height: 600
minimumWidth: 500
minimumHeight: 600
maximumWidth: 500
maximumHeight: 600
launchMode: FluWindow.Standard
title:"Standard"
FluAppBar{
id:appbar
title:"Standard"
width:parent.width
}
FluText{
anchors.centerIn: parent
text:"我是一个Standard模式的窗口每次我都会创建一个新的窗口"
}
}

View File

@ -153,5 +153,20 @@
<file>global/qmldir</file> <file>global/qmldir</file>
<file>global/ItemsFooter.qml</file> <file>global/ItemsFooter.qml</file>
<file>page/MediaPage.qml</file> <file>page/MediaPage.qml</file>
<file>T_FlipView.qml</file>
<file>T_Pivot.qml</file>
<file>component/CodeExpander.qml</file>
<file>T_TableView.qml</file>
<file>T_StatusView.qml</file>
<file>T_Settings.qml</file>
<file>global/MainEvent.qml</file>
<file>res/svg/home.svg</file>
<file>res/svg/home_dark.svg</file>
<file>page/StandardWindow.qml</file>
<file>page/SingleTaskWindow.qml</file>
<file>page/SingleInstanceWindow.qml</file>
<file>T_RatingControl.qml</file>
<file>res/image/qrcode_wx.jpg</file>
<file>res/image/qrcode_zfb.jpg</file>
</qresource> </qresource>
</RCC> </RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

1
example/res/svg/home.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1681271578882" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3664" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M923.733333 394.666667c-85.333333-70.4-206.933333-174.933333-362.666666-309.333334C533.333333 61.866667 490.666667 61.866667 462.933333 85.333333c-155.733333 134.4-277.333333 238.933333-362.666666 309.333334-14.933333 14.933333-25.6 34.133333-25.6 53.333333 0 38.4 32 70.4 70.4 70.4H192v358.4c0 29.866667 23.466667 53.333333 53.333333 53.333333H405.333333c29.866667 0 53.333333-23.466667 53.333334-53.333333v-206.933333h106.666666v206.933333c0 29.866667 23.466667 53.333333 53.333334 53.333333h160c29.866667 0 53.333333-23.466667 53.333333-53.333333V518.4h46.933333c38.4 0 70.4-32 70.4-70.4 0-21.333333-10.666667-40.533333-25.6-53.333333z m-44.8 59.733333h-57.6c-29.866667 0-53.333333 23.466667-53.333333 53.333333v358.4h-138.666667V661.333333c0-29.866667-23.466667-53.333333-53.333333-53.333333h-128c-29.866667 0-53.333333 23.466667-53.333333 53.333333v206.933334H256V507.733333c0-29.866667-23.466667-53.333333-53.333333-53.333333H145.066667c-4.266667 0-6.4-2.133333-6.4-6.4 0-2.133333 2.133333-4.266667 2.133333-6.4 85.333333-70.4 206.933333-174.933333 362.666667-309.333333 4.266667-4.266667 10.666667-4.266667 14.933333 0 155.733333 134.4 277.333333 238.933333 362.666667 309.333333 2.133333 2.133333 2.133333 2.133333 2.133333 4.266667 2.133333 6.4-2.133333 8.533333-4.266667 8.533333z" fill="#2c2c2c" p-id="3665"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1681277986581" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3875" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M923.733333 394.666667c-85.333333-70.4-206.933333-174.933333-362.666666-309.333334C533.333333 61.866667 490.666667 61.866667 462.933333 85.333333c-155.733333 134.4-277.333333 238.933333-362.666666 309.333334-14.933333 14.933333-25.6 34.133333-25.6 53.333333 0 38.4 32 70.4 70.4 70.4H192v358.4c0 29.866667 23.466667 53.333333 53.333333 53.333333H405.333333c29.866667 0 53.333333-23.466667 53.333334-53.333333v-206.933333h106.666666v206.933333c0 29.866667 23.466667 53.333333 53.333334 53.333333h160c29.866667 0 53.333333-23.466667 53.333333-53.333333V518.4h46.933333c38.4 0 70.4-32 70.4-70.4 0-21.333333-10.666667-40.533333-25.6-53.333333z m-44.8 59.733333h-57.6c-29.866667 0-53.333333 23.466667-53.333333 53.333333v358.4h-138.666667V661.333333c0-29.866667-23.466667-53.333333-53.333333-53.333333h-128c-29.866667 0-53.333333 23.466667-53.333333 53.333333v206.933334H256V507.733333c0-29.866667-23.466667-53.333333-53.333333-53.333333H145.066667c-4.266667 0-6.4-2.133333-6.4-6.4 0-2.133333 2.133333-4.266667 2.133333-6.4 85.333333-70.4 206.933333-174.933333 362.666667-309.333333 4.266667-4.266667 10.666667-4.266667 14.933333 0 155.733333 134.4 277.333333 238.933333 362.666667 309.333333 2.133333 2.133333 2.133333 2.133333 2.133333 4.266667 2.133333 6.4-2.133333 8.533333-4.266667 8.533333z" fill="#ffffff" p-id="3876"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,34 @@
[CmdletBinding()]
param (
[string] $archiveName, [string] $targetName
)
# 外部环境变量包括:
# archiveName: ${{ matrix.qt_ver }}-${{ matrix.qt_arch }}
# archiveName: 5.15.2-win64_mingw81
$scriptDir = $PSScriptRoot
$currentDir = Get-Location
Write-Host "currentDir" $currentDir
Write-Host "scriptDir" $scriptDir
function Main() {
New-Item -ItemType Directory $archiveName
# 拷贝exe
Copy-Item bin\release\* $archiveName\
# 拷贝依赖
windeployqt --qmldir . --plugindir $archiveName\plugins --no-translations --compiler-runtime $archiveName\$targetName
# 删除不必要的文件
$excludeList = @("*.qmlc", "*.ilk", "*.exp", "*.lib", "*.pdb")
Remove-Item -Path $archiveName -Include $excludeList -Recurse -Force
# 打包zip
Compress-Archive -Path $archiveName $archiveName'.zip'
}
if ($null -eq $archiveName || $null -eq $targetName) {
Write-Host "args missing, archiveName is" $archiveName ", targetName is" $targetName
return
}
Main

67
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,67 @@
cmake_minimum_required(VERSION 3.16)
project(FluentUI)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt6 COMPONENTS Core Quick Svg REQUIRED)
set(QT_INSTALL_QML ${Qt6Core_DIR}/../../../qml)
set(TARGET_TYPE SHARED)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/FluentUI)
if(WIN32)
set(CMAKE_SHARED_LIBRARY_PREFIX "")
endif()
set(TARGET_RESOURCES res.qrc)
set(TARGET_SOURCES
Def.cpp
FluApp.cpp
FluColorSet.cpp
FluColors.cpp
FluRegister.cpp
FluTheme.cpp
Fluent.cpp
FluentUI.cpp
NativeEventFilter.cpp
WindowHelper.cpp
qml_plugin.cpp
)
set(TARGET_HEADERS
Def.h
FluApp.h
FluColorSet.h
FluColors.h
FluRegister.h
FluTheme.h
Fluent.h
FluentUI.h
NativeEventFilter.h
WindowHelper.h
qml_plugin.h
stdafx.h
)
add_definitions(-DVERSION_IN="1.0.0")
add_definitions(-DVURI_STR="FluentUI")
add_library(${PROJECT_NAME} ${TARGET_TYPE} ${TARGET_SOURCES} ${TARGET_HEADERS} ${TARGET_RESOURCES})
set_target_properties(${PROJECT_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/FluentUI)
if(WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE dwmapi user32)
else()
endif()
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick Qt6::Svg)
if(WIN32)
include(build_windows.cmake)
else()
include(build_macos.cmake)
endif()

View File

@ -7,8 +7,20 @@
#include <QTimer> #include <QTimer>
#include <QUuid> #include <QUuid>
#include <QClipboard> #include <QClipboard>
#include "FluTheme.h"
#include "Def.h" #include "Def.h"
#ifdef Q_OS_WIN
#include <dwmapi.h>
#include <Windows.h>
#include <windowsx.h>
static bool isCompositionEnabled()
{
BOOL composition_enabled = FALSE;
bool success = ::DwmIsCompositionEnabled(&composition_enabled) == S_OK;
return composition_enabled && success;
}
#endif
FluApp* FluApp::m_instance = nullptr; FluApp* FluApp::m_instance = nullptr;
@ -25,12 +37,16 @@ FluApp::FluApp(QObject *parent)
{ {
} }
void FluApp::init(QWindow *window,QMap<QString, QVariant> properties){ void FluApp::init(QQuickWindow *window){
this->appWindow = window; this->appWindow = window;
this->properties = properties;
} }
void FluApp::run(){ void FluApp::run(){
#ifdef Q_OS_WIN
if(!isCompositionEnabled()){
FluTheme::getInstance()->frameless(false);
}
#endif
navigate(initialRoute()); navigate(initialRoute());
} }
@ -39,38 +55,45 @@ void FluApp::navigate(const QString& route,const QJsonObject& argument,FluRegist
qErrnoWarning("没有找到当前路由"); qErrnoWarning("没有找到当前路由");
return; return;
} }
bool isAppWindow = route == initialRoute(); QQmlEngine *engine = qmlEngine(appWindow);
FramelessView *view = new FramelessView(); QQmlComponent component(engine, routes().value(route).toString());
QVariantMap properties;
properties.insert("route",route);
if(fluRegister){ if(fluRegister){
fluRegister->to(view); properties.insert("pageRegister",QVariant::fromValue(fluRegister));
view->setProperty("pageRegister",QVariant::fromValue(fluRegister));
} }
view->setProperty("argument",argument); properties.insert("argument",argument);
QMapIterator<QString, QVariant> iterator(properties); QQuickWindow *view = qobject_cast<QQuickWindow*>(component.createWithInitialProperties(properties));
while (iterator.hasNext()) {
iterator.next(); int launchMode = view->property("launchMode").toInt();
QString key = iterator.key(); if(launchMode==1){
QVariant value = iterator.value(); for (auto& pair : wnds) {
view->engine()->rootContext()->setContextProperty(key,value); QString r = pair->property("route").toString();
if(r == route){
pair->requestActivate();
view->deleteLater();
return;
} }
view->setColor(QColor(Qt::transparent));
QObject::connect(view, &QQuickView::statusChanged, view, [&](QQuickView::Status status) {
if (status == QQuickView::Status::Ready) {
Q_EMIT windowReady(view);
view->moveToScreenCenter();
view->show();
} }
}); }else if(launchMode==2){
view->setSource((routes().value(route).toString())); for (auto& pair : wnds) {
if(isAppWindow){ QString r = pair->property("route").toString();
QObject::connect(view->engine(), &QQmlEngine::quit, qApp, &QCoreApplication::quit); if(r == route){
}else{ pair->close();
view->closeDeleteLater(); break;
}
} }
} }
bool FluApp::equalsWindow(FramelessView *view,QWindow *window){ if(FluTheme::getInstance()->frameless()){
return view->winId() == window->winId(); view->setFlag(Qt::FramelessWindowHint,true);
}
wnds.insert(view->winId(),view);
if(fluRegister){
fluRegister->to(view);
}
view->setColor(QColor(Qt::transparent));
view->show();
} }
QJsonArray FluApp::awesomelist(const QString& keyword) QJsonArray FluApp::awesomelist(const QString& keyword)
@ -104,3 +127,7 @@ void FluApp::clipText(const QString& text){
QString FluApp::uuid(){ QString FluApp::uuid(){
return QUuid::createUuid().toString(); return QUuid::createUuid().toString();
} }
void FluApp::closeApp(){
qApp->exit(0);
}

View File

@ -8,7 +8,6 @@
#include <QJsonObject> #include <QJsonObject>
#include <QQmlEngine> #include <QQmlEngine>
#include "FluRegister.h" #include "FluRegister.h"
#include "FramelessView.h"
#include "stdafx.h" #include "stdafx.h"
class FluApp : public QObject class FluApp : public QObject
@ -27,11 +26,7 @@ public:
Q_INVOKABLE void navigate(const QString& route,const QJsonObject& argument = {},FluRegister* fluRegister = nullptr); Q_INVOKABLE void navigate(const QString& route,const QJsonObject& argument = {},FluRegister* fluRegister = nullptr);
Q_INVOKABLE void init(QWindow *window,QMap<QString, QVariant> properties); Q_INVOKABLE void init(QQuickWindow *window);
Q_SIGNAL void windowReady(FramelessView *view);
Q_INVOKABLE bool equalsWindow(FramelessView *view,QWindow *window);
Q_INVOKABLE QJsonArray awesomelist(const QString& keyword = ""); Q_INVOKABLE QJsonArray awesomelist(const QString& keyword = "");
@ -39,11 +34,13 @@ public:
Q_INVOKABLE QString uuid(); Q_INVOKABLE QString uuid();
Q_INVOKABLE void closeApp();
public:
QMap<quint64, QQuickWindow*> wnds;
private: private:
QMap<QString, QVariant> properties;
static FluApp* m_instance; static FluApp* m_instance;
QWindow *appWindow; QWindow *appWindow;
}; };
#endif // FLUAPP_H #endif // FLUAPP_H

View File

@ -2,15 +2,15 @@
#define FLUREGISTER_H #define FLUREGISTER_H
#include <QObject> #include <QObject>
#include <FramelessView.h> #include <QQuickWindow>
#include <QJsonObject> #include <QJsonObject>
#include "stdafx.h" #include "stdafx.h"
class FluRegister : public QObject class FluRegister : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY_AUTO(FramelessView*,from) Q_PROPERTY_AUTO(QQuickWindow*,from)
Q_PROPERTY_AUTO(FramelessView*,to) Q_PROPERTY_AUTO(QQuickWindow*,to)
Q_PROPERTY_AUTO(QString,path); Q_PROPERTY_AUTO(QString,path);
public: public:
explicit FluRegister(QObject *parent = nullptr); explicit FluRegister(QObject *parent = nullptr);

View File

@ -1,6 +1,8 @@
#include "FluTheme.h" #include "FluTheme.h"
#include "FluColors.h" #include "FluColors.h"
#include <QPalette>
#include <QGuiApplication>
FluTheme* FluTheme::m_instance = nullptr; FluTheme* FluTheme::m_instance = nullptr;
@ -19,5 +21,13 @@ FluTheme::FluTheme(QObject *parent)
textSize(13); textSize(13);
nativeText(true); nativeText(true);
frameless(true); frameless(true);
dark(false); std::function<bool()> isDark = [](){
QPalette palette = (qobject_cast<QGuiApplication *>(QCoreApplication::instance()))->palette();
QColor color = palette.color(QPalette::Window).rgb();
return !(color.red() * 0.2126 + color.green() * 0.7152 + color.blue() * 0.0722 > 255 / 2);
};
dark(isDark());
connect(qobject_cast<QGuiApplication *>(QCoreApplication::instance()), &QGuiApplication::paletteChanged, this, [=] (const QPalette &) {
dark(isDark());
});
} }

View File

@ -5,6 +5,7 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QQuickWindow> #include <QQuickWindow>
#include "FluColors.h" #include "FluColors.h"
#include "NativeEventFilter.h"
#include "FluTheme.h" #include "FluTheme.h"
#include "WindowHelper.h" #include "WindowHelper.h"
#include "FluApp.h" #include "FluApp.h"
@ -33,6 +34,14 @@ void Fluent::registerTypes(const char *uri){
qmlRegisterType<WindowHelper>(uri,major,minor,"WindowHelper"); qmlRegisterType<WindowHelper>(uri,major,minor,"WindowHelper");
qmlRegisterType<FluColorSet>(uri,major,minor,"FluColorSet"); qmlRegisterType<FluColorSet>(uri,major,minor,"FluColorSet");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluRatingControl.qml"),uri,major,minor,"FluRatingControl");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluStatusView.qml"),uri,major,minor,"FluStatusView");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluPagination.qml"),uri,major,minor,"FluPagination");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluToggleButton.qml"),uri,major,minor,"FluToggleButton");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluTableView.qml"),uri,major,minor,"FluTableView");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluPivotItem.qml"),uri,major,minor,"FluPivotItem");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluPivot.qml"),uri,major,minor,"FluPivot");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluFlipView.qml"),uri,major,minor,"FluFlipView");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluPaneItemExpander.qml"),uri,major,minor,"FluPaneItemExpander"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluPaneItemExpander.qml"),uri,major,minor,"FluPaneItemExpander");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluTabView.qml"),uri,major,minor,"FluTabView"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluTabView.qml"),uri,major,minor,"FluTabView");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluArea.qml"),uri,major,minor,"FluArea"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluArea.qml"),uri,major,minor,"FluArea");
@ -59,7 +68,7 @@ void Fluent::registerTypes(const char *uri){
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluMenu.qml"),uri,major,minor,"FluMenu"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluMenu.qml"),uri,major,minor,"FluMenu");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluScrollBar.qml"),uri,major,minor,"FluScrollBar"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluScrollBar.qml"),uri,major,minor,"FluScrollBar");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluTextButton.qml"),uri,major,minor,"FluTextButton"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluTextButton.qml"),uri,major,minor,"FluTextButton");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluMultiLineTextBox.qml"),uri,major,minor,"FluMultiLineTextBox"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluMultilineTextBox.qml"),uri,major,minor,"FluMultilineTextBox");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluTooltip.qml"),uri,major,minor,"FluTooltip"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluTooltip.qml"),uri,major,minor,"FluTooltip");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluDivider.qml"),uri,major,minor,"FluDivider"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluDivider.qml"),uri,major,minor,"FluDivider");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluIcon.qml"),uri,major,minor,"FluIcon"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluIcon.qml"),uri,major,minor,"FluIcon");
@ -88,6 +97,8 @@ void Fluent::registerTypes(const char *uri){
void Fluent::initializeEngine(QQmlEngine *engine, const char *uri) void Fluent::initializeEngine(QQmlEngine *engine, const char *uri)
{ {
nativeEvent = new NativeEventFilter();
qApp->installNativeEventFilter(nativeEvent);
Q_UNUSED(engine) Q_UNUSED(engine)
Q_UNUSED(uri) Q_UNUSED(uri)
#ifdef Q_OS_WIN #ifdef Q_OS_WIN

View File

@ -3,17 +3,25 @@
#include <QObject> #include <QObject>
#include <QQmlEngine> #include <QQmlEngine>
#include "NativeEventFilter.h"
class Fluent: public QObject class Fluent: public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
Q_INVOKABLE QString version() const; Q_INVOKABLE QString version() const;
~Fluent(){
if (nativeEvent != Q_NULLPTR) {
delete nativeEvent;
nativeEvent = Q_NULLPTR;
}
}
void registerTypes(const char *uri); void registerTypes(const char *uri);
void initializeEngine(QQmlEngine *engine, const char *uri); void initializeEngine(QQmlEngine *engine, const char *uri);
static Fluent *getInstance(); static Fluent *getInstance();
private: private:
static Fluent* m_instance; static Fluent* m_instance;
NativeEventFilter *nativeEvent = Q_NULLPTR;
}; };
#endif // FLUENT_H #endif // FLUENT_H

View File

@ -19,7 +19,7 @@ HEADERS += \
FluTheme.h \ FluTheme.h \
Fluent.h \ Fluent.h \
FluentUI.h \ FluentUI.h \
FramelessView.h \ NativeEventFilter.h \
WindowHelper.h \ WindowHelper.h \
qml_plugin.h \ qml_plugin.h \
stdafx.h stdafx.h
@ -33,16 +33,12 @@ SOURCES += \
FluTheme.cpp \ FluTheme.cpp \
Fluent.cpp \ Fluent.cpp \
FluentUI.cpp \ FluentUI.cpp \
NativeEventFilter.cpp \
WindowHelper.cpp \ WindowHelper.cpp \
qml_plugin.cpp \ qml_plugin.cpp \
win32 { win32 {
LIBS += -ldwmapi -luser32 LIBS += -ldwmapi -luser32
SOURCES += \
FramelessView_win.cpp
} else {
SOURCES += \
FramelessView_unix.cpp
} }
DEFINES += VERSION_IN=\\\"1.0.0\\\" DEFINES += VERSION_IN=\\\"1.0.0\\\"

View File

@ -1,56 +0,0 @@
#pragma once
#include <QMouseEvent>
#include <QQuickView>
#include <QRegion>
class FramelessViewPrivate;
class FramelessView : public QQuickView
{
Q_OBJECT
using Super = QQuickView;
Q_PROPERTY(bool isMax READ isMax NOTIFY isMaxChanged)
Q_PROPERTY(bool isFull READ isFull NOTIFY isFullChanged)
public:
explicit FramelessView(QWindow *parent = nullptr);
~FramelessView();
void moveToScreenCenter();
void closeDeleteLater();
bool isMax() const;
bool isFull() const;
QQuickItem *titleItem() const;
static QMap<WId,FramelessView*> *windowCache;
static QRect calcCenterGeo(const QRect &screenGeo, const QSize &normalSize);
public slots:
void setIsMax(bool isMax);
void setIsFull(bool isFull);
void setTitleItem(QQuickItem* item);
signals:
void isMaxChanged(bool isMax);
void isFullChanged(bool isFull);
void mousePressed(int xPos, int yPos, int button);
protected:
void showEvent(QShowEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
bool event(QEvent *ev) override;
# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
# else
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
# endif
void mousePressEvent(QMouseEvent* event) override
{
# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
emit mousePressed(event->position().x(), event->position().y(), event->button());
#else
emit mousePressed(event->x(), event->y(), event->button());
#endif
Super::mousePressEvent(event);
}
private:
FramelessViewPrivate *d;
};

View File

@ -1,138 +0,0 @@
#include "FramelessView.h"
#include <QGuiApplication>
#include <QQuickItem>
#include <QScreen>
#include <QWindow>
#include <FluTheme.h>
class FramelessViewPrivate
{
public:
bool m_isMax = false;
bool m_isFull = false;
bool m_deleteLater = false;
QQuickItem *m_titleItem = nullptr;
};
FramelessView::FramelessView(QWindow *parent) : Super(parent), d(new FramelessViewPrivate)
{
if(FluTheme::getInstance()->frameless()){
setFlags( Qt::Window | Qt::FramelessWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
}
setResizeMode(SizeRootObjectToView);
setIsMax(windowState() == Qt::WindowMaximized);
setIsFull(windowState() == Qt::WindowFullScreen);
connect(this, &QWindow::windowStateChanged, this, [&](Qt::WindowState state) {
(void)state;
setIsMax(windowState() == Qt::WindowMaximized);
setIsFull(windowState() == Qt::WindowFullScreen);
});
connect(FluTheme::getInstance(),&FluTheme::framelessChanged,this,[=](){
setFlag(Qt::Window,false);
setFlag(Qt::Window,true);
});
}
FramelessView::~FramelessView()
{
delete d;
}
void FramelessView::showEvent(QShowEvent *e)
{
Super::showEvent(e);
}
QRect FramelessView::calcCenterGeo(const QRect &screenGeo, const QSize &normalSize)
{
int w = normalSize.width();
int h = normalSize.height();
int x = screenGeo.x() + (screenGeo.width() - w) / 2;
int y = screenGeo.y() + (screenGeo.height() - h) / 2;
if (screenGeo.width() < w) {
x = screenGeo.x();
w = screenGeo.width();
}
if (screenGeo.height() < h) {
y = screenGeo.y();
h = screenGeo.height();
}
return { x, y, w, h };
}
void FramelessView::moveToScreenCenter()
{
auto geo = calcCenterGeo(screen()->availableGeometry(), size());
if (minimumWidth() > geo.width() || minimumHeight() > geo.height()) {
setMinimumSize(geo.size());
}
setGeometry(geo);
update();
}
void FramelessView::closeDeleteLater(){
d->m_deleteLater = true;
}
bool FramelessView::isMax() const
{
return d->m_isMax;
}
bool FramelessView::isFull() const
{
return d->m_isFull;
}
QQuickItem *FramelessView::titleItem() const
{
return d->m_titleItem;
}
void FramelessView::setIsMax(bool isMax)
{
if (d->m_isMax == isMax)
return;
d->m_isMax = isMax;
emit isMaxChanged(d->m_isMax);
}
void FramelessView::setIsFull(bool isFull)
{
if(d->m_isFull == isFull)
return;
d->m_isFull = isFull;
emit isFullChanged(d->m_isFull);
}
void FramelessView::setTitleItem(QQuickItem *item)
{
d->m_titleItem = item;
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool FramelessView::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
#else
bool FramelessView::nativeEvent(const QByteArray &eventType, void *message, long *result)
#endif
{
return Super::nativeEvent(eventType, message, result);
}
void FramelessView::resizeEvent(QResizeEvent *e)
{
Super::resizeEvent(e);
}
bool FramelessView::event(QEvent *ev)
{
if (ev->type() == QEvent::Close) {
if(d->m_deleteLater){
deleteLater();
ev->setAccepted(false);
}
}
return QQuickWindow::event(ev);
}

View File

@ -1,268 +0,0 @@
#include "FramelessView.h"
#include <QGuiApplication>
#include <QQuickItem>
#include <QScreen>
#include <QWindow>
#include <FluTheme.h>
#include <QTimer>
#include <dwmapi.h>
#include <windowsx.h>
#pragma comment(lib, "Dwmapi.lib")
#pragma comment(lib, "User32.lib")
static bool isCompositionEnabled()
{
BOOL composition_enabled = FALSE;
bool success = ::DwmIsCompositionEnabled(&composition_enabled) == S_OK;
return composition_enabled && success;
}
static bool isMaxWin(QWindow* win)
{
return win->windowState() == Qt::WindowMaximized;
}
static bool isFullWin(QQuickView* win)
{
return win->windowState() == Qt::WindowFullScreen;
}
static bool isFixWin(QQuickView* win)
{
return win->minimumWidth() == win->maximumWidth() && win->minimumHeight() == win->maximumHeight();
}
static long hitTest(RECT winrect, long x, long y, int borderWidth)
{
if ((x >= winrect.left) && (x < winrect.left + borderWidth) && (y >= winrect.top) && (y < winrect.top + borderWidth))
{
return HTTOPLEFT;
}
else if (x < winrect.right && x >= winrect.right - borderWidth && y >= winrect.top && y < winrect.top + borderWidth)
{
return HTTOPRIGHT;
}
else if (x >= winrect.left && x < winrect.left + borderWidth && y < winrect.bottom && y >= winrect.bottom - borderWidth)
{
return HTBOTTOMLEFT;
}
else if (x < winrect.right && x >= winrect.right - borderWidth && y < winrect.bottom && y >= winrect.bottom - borderWidth)
{
return HTBOTTOMRIGHT;
}
else if (x >= winrect.left && x < winrect.left + borderWidth)
{
return HTLEFT;
}
else if (x < winrect.right && x >= winrect.right - borderWidth)
{
return HTRIGHT;
}
else if (y >= winrect.top && y < winrect.top + borderWidth)
{
return HTTOP;
}
else if (y < winrect.bottom && y >= winrect.bottom - borderWidth)
{
return HTBOTTOM;
}
else
{
return 0;
}
}
class FramelessViewPrivate
{
public:
bool m_isMax = false;
bool m_isFull = false;
bool m_deleteLater = false;
bool m_isFirst = true;
QQuickItem *m_titleItem = nullptr;
};
FramelessView::FramelessView(QWindow *parent) : Super(parent), d(new FramelessViewPrivate)
{
if(!isCompositionEnabled()){
FluTheme::getInstance()->frameless(false);
}
if(FluTheme::getInstance()->frameless()){
setFlag(Qt::FramelessWindowHint,true);
}
setResizeMode(SizeRootObjectToView);
setIsMax(windowState() == Qt::WindowMaximized);
setIsFull(windowState() == Qt::WindowFullScreen);
connect(this, &QWindow::windowStateChanged, this, [=](Qt::WindowState state) {
(void)state;
setIsMax(windowState() == Qt::WindowMaximized);
setIsFull(windowState() == Qt::WindowFullScreen);
});
connect(FluTheme::getInstance(),&FluTheme::framelessChanged,this,[=](){
setFlag(Qt::Window,false);
setFlag(Qt::Window,true);
});
}
FramelessView::~FramelessView()
{
delete d;
}
void FramelessView::showEvent(QShowEvent *e)
{
static const MARGINS shadow_state[2] { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } };
::DwmExtendFrameIntoClientArea((HWND)(winId()), &shadow_state[true]);
if(FluTheme::getInstance()->frameless()){
setFlag(Qt::FramelessWindowHint,false);
}
Super::showEvent(e);
}
QRect FramelessView::calcCenterGeo(const QRect &screenGeo, const QSize &normalSize)
{
int w = normalSize.width();
int h = normalSize.height();
int x = screenGeo.x() + (screenGeo.width() - w) / 2;
int y = screenGeo.y() + (screenGeo.height() - h) / 2;
if (screenGeo.width() < w) {
x = screenGeo.x();
w = screenGeo.width();
}
if (screenGeo.height() < h) {
y = screenGeo.y();
h = screenGeo.height();
}
return { x, y, w, h };
}
void FramelessView::moveToScreenCenter()
{
auto geo = calcCenterGeo(screen()->availableGeometry(), size());
if (minimumWidth() > geo.width() || minimumHeight() > geo.height()) {
setMinimumSize(geo.size());
}
setGeometry(geo);
update();
}
void FramelessView::closeDeleteLater(){
d->m_deleteLater = true;
}
bool FramelessView::isMax() const
{
return d->m_isMax;
}
bool FramelessView::isFull() const
{
return d->m_isFull;
}
QQuickItem *FramelessView::titleItem() const
{
return d->m_titleItem;
}
void FramelessView::setIsMax(bool isMax)
{
if (d->m_isMax == isMax)
return;
d->m_isMax = isMax;
emit isMaxChanged(d->m_isMax);
}
void FramelessView::setIsFull(bool isFull)
{
if(d->m_isFull == isFull)
return;
d->m_isFull = isFull;
emit isFullChanged(d->m_isFull);
}
int count = 1;
void FramelessView::setTitleItem(QQuickItem *item)
{
d->m_titleItem = item;
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool FramelessView::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
#else
bool FramelessView::nativeEvent(const QByteArray &eventType, void *message, long *result)
#endif
{
MSG* msg = static_cast<MSG*>(message);
if (!msg || !msg->hwnd)
{
return false;
}
if (msg->message == WM_NCHITTEST && FluTheme::getInstance()->frameless())
{
RECT winrect;
GetWindowRect(HWND(winId()), &winrect);
long x = GET_X_LPARAM(msg->lParam);
long y = GET_Y_LPARAM(msg->lParam);
*result = 0;
if (!isMaxWin(this) && !isFullWin(this) && !isFixWin(this))
{
*result = hitTest(winrect, x, y, 4);
if (0 != *result)
{
return true;
}
}
}else if (msg->message == WM_NCCALCSIZE && FluTheme::getInstance()->frameless())
{
const auto mode = static_cast<BOOL>(msg->wParam);
const auto clientRect = mode ? &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(msg->lParam)->rgrc[0]) : reinterpret_cast<LPRECT>(msg->lParam);
if (mode == TRUE)
{
*result = WVR_REDRAW;
if (!isMaxWin(this) && !isFullWin(this))
{
if (clientRect->top != 0)
{
clientRect->top -= 0.1;
}
}
else
{
if (clientRect->top != 0)
{
clientRect->top += 0.1;
}
}
return true;
}
}else if (msg->message == WM_WINDOWPOSCHANGING)
{
WINDOWPOS* wp = reinterpret_cast<WINDOWPOS*>(msg->lParam);
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0)
{
wp->flags |= SWP_NOCOPYBITS;
*result = 0;
return true;
}
}
return Super::nativeEvent(eventType, message, result);
}
void FramelessView::resizeEvent(QResizeEvent *e)
{
Super::resizeEvent(e);
}
bool FramelessView::event(QEvent *ev)
{
if (ev->type() == QEvent::Close) {
if(d->m_deleteLater){
deleteLater();
ev->setAccepted(false);
}
}
return QQuickWindow::event(ev);
}

76
src/NativeEventFilter.cpp Normal file
View File

@ -0,0 +1,76 @@
#include "NativeEventFilter.h"
#include "FluTheme.h"
#include "FluApp.h"
#ifdef Q_OS_WIN
#include <Windows.h>
#include <windowsx.h>
#endif
bool NativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result)
{
#ifdef Q_OS_WIN
if (eventType == "windows_generic_MSG" && FluTheme::getInstance()->frameless()) {
MSG* msg = static_cast<MSG *>(message);
if (msg == Q_NULLPTR)
return false;
switch(msg->message) {
case WM_NCCALCSIZE:{
NCCALCSIZE_PARAMS& params = *reinterpret_cast<NCCALCSIZE_PARAMS*>(msg->lParam);
if (params.rgrc[0].top != 0)
params.rgrc[0].top -= 1;
*result = WVR_REDRAW;
return true;
}
case WM_NCHITTEST: {
auto view = FluApp::getInstance()->wnds[(WId)msg->hwnd];
bool isResize = !(view->maximumWidth()==view->minimumWidth()&&view->maximumHeight()==view->minimumHeight());
const LONG borderWidth = 8;
RECT winrect;
GetWindowRect(msg->hwnd, &winrect);
long x = GET_X_LPARAM(msg->lParam);
long y = GET_Y_LPARAM(msg->lParam);
if (x >= winrect.left && x < winrect.left + borderWidth &&
y < winrect.bottom && y >= winrect.bottom - borderWidth && isResize) {
*result = HTBOTTOMLEFT;
return true;
}
if (x < winrect.right && x >= winrect.right - borderWidth &&
y < winrect.bottom && y >= winrect.bottom - borderWidth && isResize) {
*result = HTBOTTOMRIGHT;
return true;
}
if (x >= winrect.left && x < winrect.left + borderWidth &&
y >= winrect.top && y < winrect.top + borderWidth && isResize) {
*result = HTTOPLEFT;
return true;
}
if (x < winrect.right && x >= winrect.right - borderWidth &&
y >= winrect.top && y < winrect.top + borderWidth && isResize) {
*result = HTTOPRIGHT;
return true;
}
if (x >= winrect.left && x < winrect.left + borderWidth && isResize) {
*result = HTLEFT;
return true;
}
if (x < winrect.right && x >= winrect.right - borderWidth && isResize) {
*result = HTRIGHT;
return true;
}
if (y < winrect.bottom && y >= winrect.bottom - borderWidth && isResize) {
*result = HTBOTTOM;
return true;
}
if (y >= winrect.top && y < winrect.top + borderWidth && isResize) {
*result = HTTOP;
return true;
}
return false;
}
default:
break;
}
}
#endif
return false;
}

14
src/NativeEventFilter.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef NATIVEEVENTFILTER_H
#define NATIVEEVENTFILTER_H
#include <QObject>
#include <QAbstractNativeEventFilter>
class NativeEventFilter : public QAbstractNativeEventFilter
{
public:
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;
};
#endif // NATIVEEVENTFILTER_H

View File

@ -1,6 +1,19 @@
#include "WindowHelper.h" #include "WindowHelper.h"
#include "FluRegister.h" #include "FluRegister.h"
#include "FluApp.h"
#include "FluTheme.h"
#ifdef Q_OS_WIN
#include <dwmapi.h>
#include <Windows.h>
#include <windowsx.h>
enum class Style : DWORD
{
windowed = (WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CLIPCHILDREN),
aero_borderless = (WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CLIPCHILDREN)
};
#endif
WindowHelper::WindowHelper(QObject *parent) WindowHelper::WindowHelper(QObject *parent)
: QObject{parent} : QObject{parent}
@ -8,56 +21,38 @@ WindowHelper::WindowHelper(QObject *parent)
} }
void WindowHelper::setTitle(const QString& text){ void WindowHelper::initWindow(QQuickWindow* window){
window->setTitle(text);
}
void WindowHelper::initWindow(FramelessView* window){
this->window = window; this->window = window;
} }
QJsonObject WindowHelper::getArgument(){ void WindowHelper::firstUpdate(){
return window->property("argument").toJsonObject(); if(isFisrt){
#ifdef Q_OS_WIN
if(FluTheme::getInstance()->frameless()){
HWND wnd = (HWND)window->winId();
SetWindowLongPtr(wnd, GWL_STYLE, static_cast<LONG>(Style::aero_borderless));
const MARGINS shadow_on = { 1, 1, 1, 1 };
DwmExtendFrameIntoClientArea(wnd, &shadow_on);
SetWindowPos(wnd, Q_NULLPTR, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
ShowWindow(wnd, SW_SHOW);
window->setFlag(Qt::FramelessWindowHint,false);
}
#endif
isFisrt = false;
} }
QVariant WindowHelper::getPageRegister(){
return window->property("pageRegister");
} }
void WindowHelper::setMinimumWidth(int width){ QVariant WindowHelper::createRegister(QQuickWindow* window,const QString& path){
this->window->setMinimumWidth(width); FluRegister *p = new FluRegister(window);
} p->from(window);
void WindowHelper::setMaximumWidth(int width){
this->window->setMaximumWidth(width);
}
void WindowHelper::setMinimumHeight(int height){
this->window->setMinimumHeight(height);
}
void WindowHelper::setMaximumHeight(int height){
this->window->setMaximumHeight(height);
}
void WindowHelper::updateWindow(){
this->window->setFlag(Qt::Window,false);
this->window->setFlag(Qt::Window,true);
}
void WindowHelper::setOpacity(qreal opacity){
this->window->setOpacity(opacity);
}
void WindowHelper::setModality(int type){
if(type == 0){
this->window->setModality(Qt::NonModal);
}else if(type == 1){
this->window->setModality(Qt::WindowModal);
}else if(type == 2){
this->window->setModality(Qt::ApplicationModal);
}else{
this->window->setModality(Qt::NonModal);
}
}
QVariant WindowHelper::createRegister(const QString& path){
FluRegister *p = new FluRegister(this->window);
p->from(this->window);
p->path(path); p->path(path);
return QVariant::fromValue(p); return QVariant::fromValue(p);
} }
void WindowHelper::destoryWindow(){
if(this->window){
FluApp::getInstance()->wnds.remove(this->window->winId());
this->window->deleteLater();
}
}

View File

@ -6,7 +6,6 @@
#include <QQuickItem> #include <QQuickItem>
#include <QWindow> #include <QWindow>
#include <QJsonObject> #include <QJsonObject>
#include "FramelessView.h"
class WindowHelper : public QObject class WindowHelper : public QObject
{ {
@ -15,22 +14,15 @@ class WindowHelper : public QObject
public: public:
explicit WindowHelper(QObject *parent = nullptr); explicit WindowHelper(QObject *parent = nullptr);
Q_INVOKABLE void initWindow(FramelessView* window); Q_INVOKABLE void initWindow(QQuickWindow* window);
Q_INVOKABLE void setTitle(const QString& text); Q_INVOKABLE void destoryWindow();
Q_INVOKABLE void setMinimumWidth(int width); Q_INVOKABLE QVariant createRegister(QQuickWindow* window,const QString& path);
Q_INVOKABLE void setMaximumWidth(int width);
Q_INVOKABLE void setMinimumHeight(int height); Q_INVOKABLE void firstUpdate();
Q_INVOKABLE void setMaximumHeight(int height);
Q_INVOKABLE QJsonObject getArgument();
Q_INVOKABLE QVariant getPageRegister();
Q_INVOKABLE void updateWindow();
Q_INVOKABLE void setOpacity(qreal opacity);
Q_INVOKABLE void setModality(int type);
Q_INVOKABLE QVariant createRegister(const QString& path);
private: private:
FramelessView* window; QQuickWindow* window;
bool isFisrt=true;
}; };
#endif // WINDOWHELPER_H #endif // WINDOWHELPER_H

32
src/build_macos.cmake Normal file
View File

@ -0,0 +1,32 @@
set(OUTP ${CMAKE_BINARY_DIR}/bin/FluentUI/)
add_definitions(-DMACOS)
set(CMAKE_INSTALL_PREFIX ${OUTP})
set(CMAKE_INSTALL_DESTDIR ${OUTP})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(QMAKE_MOC_OPTIONS -Muri=${uri})
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND chmod -R 777 ${CMAKE_CURRENT_SOURCE_DIR}/macos_install.sh
)
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/macos_install.sh PRESET ${CMAKE_CURRENT_SOURCE_DIR}/ ${OUTP}
)
if(${TARGET_TYPE} STREQUAL "SHARED")
set(INST_QMLPATH ${QT_INSTALL_QML}/FluentUI)
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/macos_install.sh INSTALL ${CMAKE_CURRENT_SOURCE_DIR}/ ${OUTP} ${INST_QMLPATH}
)
endif()

27
src/build_windows.cmake Normal file
View File

@ -0,0 +1,27 @@
set(OUTP "${CMAKE_BINARY_DIR}/bin/FluentUI")
set(BUILDBIN_PATH "${OUTP}")
set(QTQMLFLUENT_PATH "${QT_INSTALL_QML}/FluentUI")
set(PRESET_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build-preset")
set(SOLIBFILE_PATH "${CMAKE_BINARY_DIR}/libFluentUI.so")
set(ANDROID NO)
if (ANDROID)
set(ANDROID YES)
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTP})
else()
set(CMAKE_INSTALL_PREFIX "${OUTP}")
endif()
set(SHAREDSCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/win_install.bat SHARED ${CMAKE_CURRENT_SOURCE_DIR} ${PRESET_PATH} ${BUILDBIN_PATH} ${QTQMLFLUENT_PATH} ${ANDROID} ${SOLIBFILE_PATH})
set(STATICSCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/win_install.bat STATIC ${CMAKE_CURRENT_SOURCE_DIR} ${PRESET_PATH} ${BUILDBIN_PATH} ${QTQMLFLUENT_PATH} ${ANDROID} ${SOLIBFILE_PATH})
string(REPLACE "/" "\\" SHAREDSCRIPT "${SHAREDSCRIPT}")
string(REPLACE "/" "\\" STATICSCRIPT "${STATICSCRIPT}")
if (${TARGET_TYPE} STREQUAL "SHARED")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${SHAREDSCRIPT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
else()
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${STATICSCRIPT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
endif()

View File

@ -4,17 +4,14 @@ QTQMLFLUENT_PATH = $$[QT_INSTALL_QML]/FluentUI
PRESET_PATH = $$PWD/build-preset PRESET_PATH = $$PWD/build-preset
SOLIBFILE_PATH = $$OUT_PWD/libFluentUI.so SOLIBFILE_PATH = $$OUT_PWD/libFluentUI.so
ANDROID = NO ANDROID = NO
android{ android{
ANDROID=YES ANDROID=YES
QMAKE_PRE_LINK *= md $$replace(OUTP, /, \\) QMAKE_PRE_LINK *= md $$replace(OUTP, /, \\)
}else{ }else{
DESTDIR += $$OUTP DESTDIR += $$OUTP
} }
SHAREDSCRIPT = "$$PWD\win_install.bat" SHARED "$$PWD" "$$PRESET_PATH" "$$BUILDBIN_PATH" "$$QTQMLFLUENT_PATH" $$ANDROID "$$SOLIBFILE_PATH" SHAREDSCRIPT = "$$PWD\win_install.bat" SHARED "$$PWD" "$$PRESET_PATH" "$$BUILDBIN_PATH" "$$QTQMLFLUENT_PATH" $$ANDROID "$$SOLIBFILE_PATH"
STATICSCRIPT = "$$PWD\win_install.bat" STATIC "$$PWD" "$$PRESET_PATH" "$$BUILDBIN_PATH" "$$QTQMLFLUENT_PATH" $$ANDROID "$$SOLIBFILE_PATH" STATICSCRIPT = "$$PWD\win_install.bat" STATIC "$$PWD" "$$PRESET_PATH" "$$BUILDBIN_PATH" "$$QTQMLFLUENT_PATH" $$ANDROID "$$SOLIBFILE_PATH"
CONFIG(sharedlib){ CONFIG(sharedlib){
QMAKE_POST_LINK *= $$replace(SHAREDSCRIPT, /, \\) QMAKE_POST_LINK *= $$replace(SHAREDSCRIPT, /, \\)
} }

View File

@ -30,10 +30,10 @@ Item {
pickerCursor.y = Math.max(0, Math.min(height, mouse.y)-cursorHeight) pickerCursor.y = Math.max(0, Math.min(height, mouse.y)-cursorHeight)
} }
} }
onPositionChanged: { onPositionChanged:(mouse)=> {
handleMouse(mouse) handleMouse(mouse)
} }
onPressed: handleMouse(mouse) onPressed:(mouse)=> handleMouse(mouse)
} }
function setValue(val) { function setValue(val) {

View File

@ -7,23 +7,35 @@ import FluentUI
Rectangle{ Rectangle{
property string title: "" property string title: ""
property string darkText : "夜间模式"
property string minimizeText : "最小化"
property string restoreText : "向下还原"
property string maximizeText : "最大化"
property string closeText : "关闭"
property color textColor: FluTheme.dark ? "#FFFFFF" : "#000000" property color textColor: FluTheme.dark ? "#FFFFFF" : "#000000"
property color minimizeNormalColor: Qt.rgba(0,0,0,0)
property color minimizeHoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.1) : Qt.rgba(0,0,0,0.06)
property color maximizeNormalColor: Qt.rgba(0,0,0,0)
property color maximizeHoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.1) : Qt.rgba(0,0,0,0.06)
property color closeNormalColor: Qt.rgba(0,0,0,0)
property color closeHoverColor: Qt.rgba(251/255,115/255,115/255,1)
property bool showDark: false property bool showDark: false
property bool showFps: false
property var window: Window.window
property color borerlessColor : FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark property color borerlessColor : FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark
property bool resizable: {
if(window == null){ Item{
return false id:d
} property var win: Window.window
return !(window.minimumHeight === window.maximumHeight && window.maximumWidth === window.minimumWidth) property bool isRestore: win && Window.Maximized === win.visibility
property bool resizable: win && !(win.minimumHeight === win.maximumHeight && win.maximumWidth === win.minimumWidth)
} }
id:root id:root
color: Qt.rgba(0,0,0,0) color: Qt.rgba(0,0,0,0)
visible: FluTheme.frameless visible: FluTheme.frameless
height: visible ? 30 : 0 height: visible ? 30 : 0
clip: true opacity: visible
z: 65535 z: 65535
TapHandler { TapHandler {
@ -34,7 +46,7 @@ Rectangle{
DragHandler { DragHandler {
target: null target: null
grabPermissions: TapHandler.CanTakeOverFromAnything grabPermissions: TapHandler.CanTakeOverFromAnything
onActiveChanged: if (active) { window.startSystemMove(); } onActiveChanged: if (active) { d.win.startSystemMove(); }
} }
FluText { FluText {
@ -55,14 +67,13 @@ Rectangle{
height: root.height height: root.height
spacing: 0 spacing: 0
RowLayout{ RowLayout{
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
Layout.rightMargin: 5 Layout.rightMargin: 5
visible: showDark visible: showDark
spacing: 5 spacing: 5
FluText{ FluText{
text:"夜间模式" text:darkText
color:root.textColor color:root.textColor
} }
FluToggleSwitch{ FluToggleSwitch{
@ -79,53 +90,24 @@ Rectangle{
iconSource : FluentIcons.ChromeMinimize iconSource : FluentIcons.ChromeMinimize
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
iconSize: 11 iconSize: 11
text:"最小化" text:minimizeText
radius: 0 radius: 0
textColor: root.textColor iconColor: root.textColor
color:{ color: hovered ? minimizeHoverColor : minimizeNormalColor
if(FluTheme.dark){
if(hovered){
return Qt.rgba(1,1,1,0.06)
}
return Qt.rgba(0,0,0,0)
}else{
if(hovered){
return Qt.rgba(0,0,0,0.06)
}
return Qt.rgba(0,0,0,0)
}
}
onClicked: { onClicked: {
window.showMinimized() d.win.showMinimized()
} }
} }
FluIconButton{ FluIconButton{
width: 40 width: 40
height: 30 height: 30
property bool isRestore:{ iconSource : d.isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize
if(window == null) color: hovered ? maximizeHoverColor : maximizeNormalColor
return false
return Window.Maximized === window.visibility
}
iconSource : isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize
color:{
if(FluTheme.dark){
if(hovered){
return Qt.rgba(1,1,1,0.06)
}
return Qt.rgba(0,0,0,0)
}else{
if(hovered){
return Qt.rgba(0,0,0,0.06)
}
return Qt.rgba(0,0,0,0)
}
}
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
visible: resizable visible: d.resizable
radius: 0 radius: 0
textColor: root.textColor iconColor: root.textColor
text:isRestore?"向下还原":"最大化" text:d.isRestore?restoreText:maximizeText
iconSize: 11 iconSize: 11
onClicked: { onClicked: {
toggleMaximized() toggleMaximized()
@ -134,26 +116,26 @@ Rectangle{
FluIconButton{ FluIconButton{
iconSource : FluentIcons.ChromeClose iconSource : FluentIcons.ChromeClose
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
text:"关闭" text:closeText
width: 40 width: 40
height: 30 height: 30
radius: 0 radius: 0
iconSize: 10 iconSize: 10
textColor: hovered ? Qt.rgba(1,1,1,1) : root.textColor iconColor: hovered ? Qt.rgba(1,1,1,1) : root.textColor
color:hovered ? Qt.rgba(251/255,115/255,115/255,1) : "#00000000" color:hovered ? closeHoverColor : closeNormalColor
onClicked: { onClicked: {
Window.window.close() d.win.close()
} }
} }
} }
function toggleMaximized() { function toggleMaximized() {
if(!resizable) if(!d.resizable)
return return
if (window.visibility === Window.Maximized) { if (d.win.visibility === Window.Maximized) {
window.showNormal(); d.win.showNormal();
} else { } else {
window.showMaximized(); d.win.showMaximized();
} }
} }

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