Compare commits

...

52 Commits

Author SHA1 Message Date
a9ceff8f6f Merge branch 'zhuzichu520:main' into add_disable_behavior_on_flutext 2024-11-22 16:45:43 +08:00
8ab0cde2e9 Merge pull request #574 from lucky9loogn/fix
尝试修复 FluChart 和 FluProgressBar 的一些问题
2024-11-22 16:42:03 +08:00
0b371ecd3f Merge branch 'zhuzichu520:main' into add_disable_behavior_on_flutext 2024-11-22 16:33:02 +08:00
0171c3609a Update README.md 2024-11-22 15:58:45 +08:00
489526988d 修复 FluProgressBar 放到 FluContentDialog 内对话框刚打开时动画卡顿问题 2024-11-22 15:40:32 +08:00
9d32e8e13b 修复 FluChart 在 Qt 5.15.2 下可选链 (?.) 报错 2024-11-22 14:56:32 +08:00
c9e0732f99 Merge pull request #570 from gaetandezeiraud/feature-fluscrollablepage-reset-scroll
Add property autoResetScroll to FluScrollablePage
2024-11-17 15:11:42 +08:00
4920407ed7 Merge pull request #569 from gaetandezeiraud/wrap-anywhere-to-wordwrap
Convert WrapAnywhere toWordWrap
2024-11-17 15:11:19 +08:00
3647197d3b Merge pull request #568 from gaetandezeiraud/fluchart-avoid-error
Update FluChart.qml
2024-11-17 15:10:44 +08:00
a72ff03eeb Merge pull request #567 from gaetandezeiraud/combobox-fix-appbar
Fix FluComboBox click issue with AppBar
2024-11-17 15:09:36 +08:00
3eaaa228d8 Add property autoResetScroll to FluScrollablePage
I use it in my app, I think it can be useful to integrate the featurein the main project. This property autoResetScroll  if true reset the scroll at the top when the StackView.onActivated is called.

So the first time a page is view but also when the user go back in the stack.
2024-11-16 20:27:48 +01:00
e0892fdb66 Convert WrapAnywhere toWordWrap
Maybe you have a valid reason to use Wrap Anywhere, but for english and french text, it is very unpleasant to read.

If this is a problem for Chinese, maybe a global variable to define the behavior?
2024-11-16 20:05:54 +01:00
8f5fbb4053 Update FluChart.qml
In some cases, not sure why but animateToNewData is called and jsChart is undefined so it generate an error. Adding a "?" operator avoid the issue if jsChart is not ready, no error and can be called later.
2024-11-16 20:03:37 +01:00
b5295ffe4c Fix FluComboBox click issue with AppBar
Fixed bug with Popup topMargin because click is consumed by FluAppBar
2024-11-16 20:02:23 +01:00
875bba2bd6 修复icon按钮,单选按钮等控件disable后,控件文本仍然高亮问题
为flutext 和 fluicon增加disable时的alpha值,简化其他控件中对text的disable时颜色的独立控制
2024-11-06 10:13:07 +08:00
d82e0ed529 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
2024-10-31 11:33:19 +08:00
5c63b7b73a update 2024-10-31 11:32:57 +08:00
77a5c347fc Merge pull request #562 from gaetandezeiraud/optimize-images
Optimize images bundle with FluentUI
2024-10-22 16:57:38 +08:00
add1a86376 Optimize images bundle with FluentUI 2024-10-21 15:17:55 +02:00
e771293269 update workflows 2024-09-20 13:51:50 +08:00
4420c6c608 update 2024-09-20 13:46:57 +08:00
a3b4c6cb28 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2024-09-20 13:41:56 +08:00
29fe40002c update 2024-09-20 13:38:51 +08:00
1797276e52 Merge pull request #552 from jeffrey0326/main
修复FluWindow部分bug,修复qmltypes生成空白的bug
2024-09-02 09:20:53 +08:00
d07de0d33c Merge branch 'main' of https://github.com/jeffrey0326/FluentUI 2024-08-31 20:53:34 +08:00
fb8c0b79b3 update 2024-08-31 20:53:18 +08:00
80eadd5d19 update 2024-08-31 20:51:20 +08:00
8ef4bbe322 Merge branch 'main' of https://github.com/jeffrey0326/FluentUI 2024-08-31 20:12:17 +08:00
901ca8077e update 2024-08-31 20:12:01 +08:00
8de79d3336 Merge branch 'zhuzichu520:main' into main 2024-08-30 23:42:28 +08:00
dbde052d4a update 2024-08-30 23:41:06 +08:00
9716c3c98c FluWindowbug修复,qmltypes生成bug修复 2024-08-30 23:39:45 +08:00
8f8a1a6124 修复generate-qmltypes生成空白的bug 2024-08-30 23:34:01 +08:00
12300ef081 调整支持使用系统标题栏 2024-08-28 14:04:50 +08:00
5ea71e2c1a 切换窗口会闪一下边框,需修复 2024-08-27 17:27:17 +08:00
a26f643ba3 调整适应系统标题栏 2024-08-24 19:27:54 +08:00
4b49fb1340 调整适应系统标题栏 2024-08-24 19:22:42 +08:00
3e28c42e1c Merge pull request #549 from jeffrey0326/main
整理dwmapi相关代码,修复Win11设置效果出错的bug
2024-08-22 00:44:45 +08:00
50b89e7eb2 整理代码,修复win11设置效果崩溃的错误 2024-08-21 22:50:43 +08:00
893000e40f Merge branch 'zhuzichu520:main' into main 2024-08-21 22:08:49 +08:00
f2eca9a2b9 修复win11设置效果崩溃的错误 2024-08-21 22:08:13 +08:00
76f40a6265 修复win11设置效果崩溃的错误 2024-08-21 22:07:20 +08:00
86f347edad Merge pull request #548 from jeffrey0326/main
添加windows窗口背景效果,修改夜间模式动画
2024-08-21 19:06:51 +08:00
b6c7afc744 调整支持mingw编译 2024-08-21 17:56:23 +08:00
f099d3c737 调整支持mingw编译 2024-08-21 17:16:39 +08:00
cfbaf44a05 update 2024-08-21 16:16:47 +08:00
0f5e16464c 添加支持windows系统窗口win7-win10(area、blur)、win11(mica、mica-alt)效果切换,修改夜间模式切换动画效果,支持动画打断; 2024-08-21 16:12:35 +08:00
13bfae4681 Merge pull request #545 from ChaXxl/dev
refactor: 使用三元表达式来选择头像的 source (#543)
2024-08-11 17:37:24 +08:00
2ee9bfed73 docs: 更新翻译、修正 "The verification code is correct" 的中文翻译 2024-08-11 14:18:08 +08:00
4a457e15fa refactor: 使用三元表达式来选择头像的 source 2024-08-11 14:02:32 +08:00
b723cfec4e Merge pull request #542 from Hzlin7/main
fix: 修改Badge显示
2024-08-06 22:14:28 +08:00
1b92928487 fix: 修改Badge显示 2024-08-03 10:34:47 +08:00
71 changed files with 1321 additions and 359 deletions

View File

@ -60,7 +60,7 @@ jobs:
# 拷贝依赖
sudo macdeployqt bin/Release/${targetName}.app -qmldir=. -dmg
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: ${{ env.targetName }}_${{ matrix.os }}_${{matrix.qt_ver}}
path: bin/release/${{ env.targetName }}.app

View File

@ -77,7 +77,7 @@ jobs:
linuxdeploy-x86_64.AppImage --plugin=qt --output=appimage --create-desktop-file --icon-file=${targetName}.svg --executable=bin/Release/${targetName} --appdir bin/release/
mv ${{ env.targetName }}-*.AppImage ${{ env.targetName }}.AppImage
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: ${{ env.targetName }}_${{ matrix.os }}_${{matrix.qt_ver}}
path: ${{ env.targetName }}.AppImage

View File

@ -82,7 +82,7 @@ jobs:
$name = ${env:archiveName}
echo "::set-output name=packageName::$name"
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: ${{ steps.package.outputs.packageName }}
path: dist

View File

@ -69,7 +69,7 @@ jobs:
$name = ${env:archiveName}
echo "::set-output name=packageName::$name"
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: ${{ steps.package.outputs.packageName }}
path: dist

View File

@ -76,7 +76,7 @@ jobs:
$name = ${env:archiveName}
echo "::set-output name=packageName::$name"
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: ${{ steps.package.outputs.packageName }}
path: dist

View File

@ -1,3 +1,6 @@
# ATTENTION! THIS REPO HAS BEEN DEPRECATED!
# PLEASE USE THE BRAND NEW [FluentUI2](https://github.com/zhuzichu520/FluentUI2) INSTEAD!
# THIS REPO IS NO LONGER MAINTAINED.
<div align=center>
<img width=64 src="doc/preview/fluent_design.svg">

View File

@ -639,7 +639,7 @@
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="95"/>
<location filename="qml/window/MainWindow.qml" line="339"/>
<location filename="qml/window/MainWindow.qml" line="337"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
@ -659,57 +659,57 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="304"/>
<location filename="qml/window/MainWindow.qml" line="302"/>
<source>Finish</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="305"/>
<location filename="qml/window/MainWindow.qml" line="303"/>
<source>Next</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="306"/>
<location filename="qml/window/MainWindow.qml" line="304"/>
<source>Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="310"/>
<location filename="qml/window/MainWindow.qml" line="308"/>
<source>Dark Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="310"/>
<location filename="qml/window/MainWindow.qml" line="308"/>
<source>Here you can switch to night mode.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="312"/>
<location filename="qml/window/MainWindow.qml" line="310"/>
<source>Hide Easter eggs</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="312"/>
<location filename="qml/window/MainWindow.qml" line="310"/>
<source>Try a few more clicks!!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="336"/>
<location filename="qml/window/MainWindow.qml" line="334"/>
<source>Upgrade Tips</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="337"/>
<location filename="qml/window/MainWindow.qml" line="335"/>
<source>FluentUI is currently up to date </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="337"/>
<location filename="qml/window/MainWindow.qml" line="335"/>
<source> -- The current app version</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="337"/>
<location filename="qml/window/MainWindow.qml" line="335"/>
<source>
Now go and download the new version
@ -718,17 +718,17 @@ Updated content:
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="340"/>
<location filename="qml/window/MainWindow.qml" line="338"/>
<source>OK</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="367"/>
<location filename="qml/window/MainWindow.qml" line="365"/>
<source>The current version is already the latest</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="374"/>
<location filename="qml/window/MainWindow.qml" line="372"/>
<source>The network is abnormal</source>
<translation type="unfinished"></translation>
</message>
@ -902,7 +902,7 @@ Updated content:
<location filename="qml/page/T_Buttons.qml" line="199"/>
<location filename="qml/page/T_Buttons.qml" line="320"/>
<location filename="qml/page/T_Buttons.qml" line="368"/>
<location filename="qml/page/T_Buttons.qml" line="421"/>
<location filename="qml/page/T_Buttons.qml" line="422"/>
<source>Disabled</source>
<translation type="unfinished"></translation>
</message>
@ -1017,17 +1017,17 @@ Updated content:
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Buttons.qml" line="404"/>
<location filename="qml/page/T_Buttons.qml" line="405"/>
<source>Radio Button_1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Buttons.qml" line="408"/>
<location filename="qml/page/T_Buttons.qml" line="409"/>
<source>Radio Button_2</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Buttons.qml" line="412"/>
<location filename="qml/page/T_Buttons.qml" line="413"/>
<source>Radio Button_3</source>
<translation type="unfinished"></translation>
</message>
@ -1494,27 +1494,27 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
</message>
<message>
<location filename="qml/page/T_InfoBar.qml" line="64"/>
<location filename="qml/page/T_InfoBar.qml" line="74"/>
<location filename="qml/page/T_InfoBar.qml" line="84"/>
<location filename="qml/page/T_InfoBar.qml" line="75"/>
<location filename="qml/page/T_InfoBar.qml" line="85"/>
<source>close &apos;%1&apos;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_InfoBar.qml" line="64"/>
<location filename="qml/page/T_InfoBar.qml" line="74"/>
<location filename="qml/page/T_InfoBar.qml" line="84"/>
<location filename="qml/page/T_InfoBar.qml" line="75"/>
<location filename="qml/page/T_InfoBar.qml" line="85"/>
<source>show &apos;%1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_InfoBar.qml" line="70"/>
<location filename="qml/page/T_InfoBar.qml" line="80"/>
<location filename="qml/page/T_InfoBar.qml" line="90"/>
<location filename="qml/page/T_InfoBar.qml" line="81"/>
<location filename="qml/page/T_InfoBar.qml" line="91"/>
<source>This is an &apos;%1&apos;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_InfoBar.qml" line="94"/>
<location filename="qml/page/T_InfoBar.qml" line="95"/>
<source>clear all info</source>
<translation type="unfinished"></translation>
</message>
@ -2092,7 +2092,7 @@ Some contents...</source>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="176"/>
<location filename="qml/page/T_TableView.qml" line="508"/>
<location filename="qml/page/T_TableView.qml" line="503"/>
<source>Name</source>
<translation type="unfinished"></translation>
</message>
@ -2112,67 +2112,67 @@ Some contents...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="364"/>
<location filename="qml/page/T_TableView.qml" line="359"/>
<source>Age</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="439"/>
<location filename="qml/page/T_TableView.qml" line="434"/>
<source>Clear All</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="446"/>
<location filename="qml/page/T_TableView.qml" line="441"/>
<source>Delete Selection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="469"/>
<location filename="qml/page/T_TableView.qml" line="464"/>
<source>Add a row of Data</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="475"/>
<location filename="qml/page/T_TableView.qml" line="470"/>
<source>Insert a Row</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="482"/>
<location filename="qml/page/T_TableView.qml" line="477"/>
<source>Focus not acquired: Please click any item in the form as the target for insertion!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="513"/>
<location filename="qml/page/T_TableView.qml" line="508"/>
<source>Avatar</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="527"/>
<location filename="qml/page/T_TableView.qml" line="522"/>
<source>Address</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="535"/>
<location filename="qml/page/T_TableView.qml" line="530"/>
<source>Nickname</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="542"/>
<location filename="qml/page/T_TableView.qml" line="537"/>
<source>Long String</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="550"/>
<location filename="qml/page/T_TableView.qml" line="545"/>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="568"/>
<location filename="qml/page/T_TableView.qml" line="563"/>
<source>&lt;Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="569"/>
<location filename="qml/page/T_TableView.qml" line="564"/>
<source>Next&gt;</source>
<translation type="unfinished"></translation>
</message>
@ -2262,8 +2262,29 @@ Some contents...</source>
<message>
<location filename="qml/page/T_Theme.qml" line="123"/>
<source>Open Blur Window</source>
<oldsource>Rounded Window</oldsource>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Theme.qml" line="158"/>
<source>window tintOpacity</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Theme.qml" line="175"/>
<source>window blurRadius</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Theme.qml" line="135"/>
<source>window effect</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Theme.qml" line="178"/>
<source></source>
<translation></translation>
</message>
</context>
<context>
<name>T_TimePicker</name>

View File

@ -616,7 +616,7 @@
<context>
<name>MainWindow</name>
<message>
<location filename="qml/window/MainWindow.qml" line="310"/>
<location filename="qml/window/MainWindow.qml" line="308"/>
<source>Dark Mode</source>
<translation type="unfinished"></translation>
</message>
@ -648,7 +648,7 @@
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="95"/>
<location filename="qml/window/MainWindow.qml" line="339"/>
<location filename="qml/window/MainWindow.qml" line="337"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
@ -668,52 +668,52 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="304"/>
<location filename="qml/window/MainWindow.qml" line="302"/>
<source>Finish</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="305"/>
<location filename="qml/window/MainWindow.qml" line="303"/>
<source>Next</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="306"/>
<location filename="qml/window/MainWindow.qml" line="304"/>
<source>Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="310"/>
<location filename="qml/window/MainWindow.qml" line="308"/>
<source>Here you can switch to night mode.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="312"/>
<location filename="qml/window/MainWindow.qml" line="310"/>
<source>Hide Easter eggs</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="312"/>
<location filename="qml/window/MainWindow.qml" line="310"/>
<source>Try a few more clicks!!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="336"/>
<location filename="qml/window/MainWindow.qml" line="334"/>
<source>Upgrade Tips</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="337"/>
<location filename="qml/window/MainWindow.qml" line="335"/>
<source>FluentUI is currently up to date </source>
<translation type="unfinished">FluentUI </translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="337"/>
<location filename="qml/window/MainWindow.qml" line="335"/>
<source> -- The current app version</source>
<translation type="unfinished"> -- </translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="337"/>
<location filename="qml/window/MainWindow.qml" line="335"/>
<source>
Now go and download the new version
@ -726,17 +726,17 @@ Updated content:
</translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="340"/>
<location filename="qml/window/MainWindow.qml" line="338"/>
<source>OK</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="367"/>
<location filename="qml/window/MainWindow.qml" line="365"/>
<source>The current version is already the latest</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="374"/>
<location filename="qml/window/MainWindow.qml" line="372"/>
<source>The network is abnormal</source>
<translation type="unfinished"></translation>
</message>
@ -929,7 +929,7 @@ Updated content:
<location filename="qml/page/T_Buttons.qml" line="199"/>
<location filename="qml/page/T_Buttons.qml" line="320"/>
<location filename="qml/page/T_Buttons.qml" line="368"/>
<location filename="qml/page/T_Buttons.qml" line="421"/>
<location filename="qml/page/T_Buttons.qml" line="422"/>
<source>Disabled</source>
<translation type="unfinished"></translation>
</message>
@ -1044,17 +1044,17 @@ Updated content:
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Buttons.qml" line="404"/>
<location filename="qml/page/T_Buttons.qml" line="405"/>
<source>Radio Button_1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Buttons.qml" line="408"/>
<location filename="qml/page/T_Buttons.qml" line="409"/>
<source>Radio Button_2</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Buttons.qml" line="412"/>
<location filename="qml/page/T_Buttons.qml" line="413"/>
<source>Radio Button_3</source>
<translation type="unfinished"></translation>
</message>
@ -1092,7 +1092,7 @@ Updated content:
<message>
<location filename="qml/page/T_Captcha.qml" line="52"/>
<source>The verification code is correct</source>
<translation type="unfinished"></translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Captcha.qml" line="54"/>
@ -1620,27 +1620,27 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
</message>
<message>
<location filename="qml/page/T_InfoBar.qml" line="64"/>
<location filename="qml/page/T_InfoBar.qml" line="74"/>
<location filename="qml/page/T_InfoBar.qml" line="84"/>
<location filename="qml/page/T_InfoBar.qml" line="75"/>
<location filename="qml/page/T_InfoBar.qml" line="85"/>
<source>close &apos;%1&apos;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_InfoBar.qml" line="64"/>
<location filename="qml/page/T_InfoBar.qml" line="74"/>
<location filename="qml/page/T_InfoBar.qml" line="84"/>
<location filename="qml/page/T_InfoBar.qml" line="75"/>
<location filename="qml/page/T_InfoBar.qml" line="85"/>
<source>show &apos;%1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_InfoBar.qml" line="70"/>
<location filename="qml/page/T_InfoBar.qml" line="80"/>
<location filename="qml/page/T_InfoBar.qml" line="90"/>
<location filename="qml/page/T_InfoBar.qml" line="81"/>
<location filename="qml/page/T_InfoBar.qml" line="91"/>
<source>This is an &apos;%1&apos;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_InfoBar.qml" line="94"/>
<location filename="qml/page/T_InfoBar.qml" line="95"/>
<source>clear all info</source>
<translation type="unfinished"></translation>
</message>
@ -2274,7 +2274,7 @@ Some contents...</source>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="176"/>
<location filename="qml/page/T_TableView.qml" line="508"/>
<location filename="qml/page/T_TableView.qml" line="503"/>
<source>Name</source>
<translation type="unfinished">名称</translation>
</message>
@ -2294,67 +2294,67 @@ Some contents...</source>
<translation type="unfinished">全选</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="364"/>
<location filename="qml/page/T_TableView.qml" line="359"/>
<source>Age</source>
<translation type="unfinished">年龄</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="439"/>
<location filename="qml/page/T_TableView.qml" line="434"/>
<source>Clear All</source>
<translation type="unfinished">清除所有</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="475"/>
<location filename="qml/page/T_TableView.qml" line="470"/>
<source>Insert a Row</source>
<translation type="unfinished">插入一行</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="482"/>
<location filename="qml/page/T_TableView.qml" line="477"/>
<source>Focus not acquired: Please click any item in the form as the target for insertion!</source>
<translation type="unfinished">焦点未获取:请点击表格中的任意一项,作为插入的靶点!</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="513"/>
<location filename="qml/page/T_TableView.qml" line="508"/>
<source>Avatar</source>
<translation type="unfinished">头像</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="527"/>
<location filename="qml/page/T_TableView.qml" line="522"/>
<source>Address</source>
<translation type="unfinished">地址</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="535"/>
<location filename="qml/page/T_TableView.qml" line="530"/>
<source>Nickname</source>
<translation type="unfinished">昵称</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="542"/>
<location filename="qml/page/T_TableView.qml" line="537"/>
<source>Long String</source>
<translation type="unfinished">长字符串</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="550"/>
<location filename="qml/page/T_TableView.qml" line="545"/>
<source>Options</source>
<translation type="unfinished">操作</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="568"/>
<location filename="qml/page/T_TableView.qml" line="563"/>
<source>&lt;Previous</source>
<translation type="unfinished">&lt;上一页</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="569"/>
<location filename="qml/page/T_TableView.qml" line="564"/>
<source>Next&gt;</source>
<translation type="unfinished">下一页&gt;</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="446"/>
<location filename="qml/page/T_TableView.qml" line="441"/>
<source>Delete Selection</source>
<translation type="unfinished">删除选中</translation>
</message>
<message>
<location filename="qml/page/T_TableView.qml" line="469"/>
<location filename="qml/page/T_TableView.qml" line="464"/>
<source>Add a row of Data</source>
<translation type="unfinished">添加一行数据</translation>
</message>
@ -2444,7 +2444,28 @@ Some contents...</source>
<message>
<location filename="qml/page/T_Theme.qml" line="123"/>
<source>Open Blur Window</source>
<translation type="unfinished"></translation>
<oldsource>Rounded Window</oldsource>
<translation>亚克力背景</translation>
</message>
<message>
<location filename="qml/page/T_Theme.qml" line="158"/>
<source>window tintOpacity</source>
<translation>背景透明度</translation>
</message>
<message>
<location filename="qml/page/T_Theme.qml" line="175"/>
<source>window blurRadius</source>
<translation>背景模糊度</translation>
</message>
<message>
<location filename="qml/page/T_Theme.qml" line="135"/>
<source>window effect</source>
<translation>窗口效果</translation>
</message>
<message>
<location filename="qml/page/T_Theme.qml" line="178"/>
<source></source>
<translation></translation>
</message>
</context>
<context>

View File

@ -1,4 +1,4 @@
import QtQuick 2.15
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
@ -265,7 +265,7 @@ FluScrollablePage{
}
FluIconButton{
disabled: icon_button_switch.checked
iconDelegate: Image{ sourceSize: Qt.size(40,40) ; width: 20; height: 20; source: "qrc:/example/res/image/ic_home_github.png" }
iconDelegate: FluImage{ sourceSize: Qt.size(40,40) ; width: 20; height: 20; source: "qrc:/example/res/image/ic_home_github.png" }
onClicked:{
showSuccess(qsTr("Click IconButton"))
}
@ -395,6 +395,7 @@ FluScrollablePage{
Layout.topMargin: 20
FluRadioButtons{
spacing: 8
disabled: radio_button_switch.checked
anchors{
verticalCenter: parent.verticalCenter
left: parent.left

View File

@ -68,6 +68,7 @@ FluScrollablePage{
return
}
info1 = showInfo(qsTr("This is an '%1'").arg("info1"), 0)
info1.close()
}
}
FluButton{

View File

@ -315,12 +315,7 @@ FluContentPage{
radius: [20,20,20,20]
Image{
anchors.fill: parent
source: {
if(options && options.avatar){
return options.avatar
}
return ""
}
source: options && options.avatar ? options.avatar : ""
sourceSize: Qt.size(80,80)
}
}

View File

@ -13,7 +13,7 @@ FluScrollablePage{
FluFrame{
Layout.fillWidth: true
Layout.preferredHeight: 408
Layout.fillHeight: true
padding: 10
ColumnLayout{
@ -124,12 +124,69 @@ FluScrollablePage{
Layout.topMargin: 20
}
FluToggleSwitch{
id: toggle_blur
Layout.topMargin: 5
checked: FluTheme.blurBehindWindowEnabled
onClicked: {
FluTheme.blurBehindWindowEnabled = !FluTheme.blurBehindWindowEnabled
}
}
FluText{
text: qsTr("window effect")
Layout.topMargin: 20
}
Row{
spacing: 10
Repeater{
model: window.availableEffects
delegate: FluRadioButton{
checked: window.effect === modelData
text: qsTr(`${modelData}`)
clickListener:function(){
window.effect = modelData
if(window.effective){
FluTheme.blurBehindWindowEnabled = false
toggle_blur.checked = Qt.binding( function() {return FluTheme.blurBehindWindowEnabled})
}
}
}
}
}
FluText{
visible: FluTheme.blurBehindWindowEnabled || window.effect === "dwm-blur"
text: qsTr("window tintOpacity")
Layout.topMargin: 20
}
FluSlider{
visible: FluTheme.blurBehindWindowEnabled || window.effect === "dwm-blur"
Layout.topMargin: 5
to:1
stepSize:0.1
onValueChanged: {
window.tintOpacity = value
}
Component.onCompleted: {
value = window.tintOpacity
}
}
FluText{
visible: FluTheme.blurBehindWindowEnabled
text: qsTr("window blurRadius")
Layout.topMargin: 20
}
FluSlider{
visible: FluTheme.blurBehindWindowEnabled
Layout.topMargin: 5
to:100
stepSize:1
onValueChanged: {
window.blurRadius = value
}
Component.onCompleted: {
value = window.blurRadius
}
}
}
}
CodeExpander{

View File

@ -236,6 +236,7 @@ FluWindow {
id: reveal
target: window.containerItem()
anchors.fill: parent
darkToLight: FluTheme.dark
onAnimationFinished:{
//动画结束后释放资源
loader_reveal.sourceComponent = undefined
@ -256,17 +257,14 @@ FluWindow {
}
function handleDarkChanged(button){
if(!FluTheme.animationEnabled || window.fitsAppBarWindows === false){
if(FluTools.isMacos() || !FluTheme.animationEnabled){
changeDark()
}else{
if(loader_reveal.sourceComponent){
return
}
loader_reveal.sourceComponent = com_reveal
var target = window.containerItem()
var pos = button.mapToItem(target,0,0)
var mouseX = pos.x
var mouseY = pos.y
var mouseX = pos.x + button.width / 2
var mouseY = pos.y + button.height / 2
var radius = Math.max(distance(mouseX,mouseY,0,0),distance(mouseX,mouseY,target.width,0),distance(mouseX,mouseY,0,target.height),distance(mouseX,mouseY,target.width,target.height))
var reveal = loader_reveal.item
reveal.start(reveal.width*Screen.devicePixelRatio,reveal.height*Screen.devicePixelRatio,Qt.point(mouseX,mouseY),radius)

View File

@ -72,11 +72,6 @@ install(TARGETS ${PROJECT_NAME}
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(QT_VERSION_MAJOR EQUAL 6)
qt_import_qml_plugins(${PROJECT_NAME})
qt_finalize_executable(${PROJECT_NAME})
endif()
if (CMAKE_BUILD_TYPE MATCHES "Release")
if (APPLE)
find_program(QT_DEPLOY_QT NAMES macdeployqt)

View File

@ -25,13 +25,32 @@ void CircularReveal::paint(QPainter *painter) {
path.moveTo(_center.x(), _center.y());
path.addEllipse(QPointF(_center.x(), _center.y()), _radius, _radius);
painter->setCompositionMode(QPainter::CompositionMode_Clear);
painter->fillPath(path, Qt::black);
if(_darkToLight){
painter->fillPath(path, Qt::white);
}else{
QPainterPath outerRect;
outerRect.addRect(0, 0, width(), height());
outerRect = outerRect.subtracted(path);
painter->fillPath(outerRect, Qt::black);
}
painter->restore();
}
[[maybe_unused]] void CircularReveal::start(int w, int h, const QPoint &center, int radius) {
_anim->setStartValue(0);
_anim->setEndValue(radius);
if (_anim->state() == QAbstractAnimation::Running) {
_anim->stop();
int currentRadius = _radius;
_anim->setStartValue(currentRadius);
_anim->setEndValue(_darkToLight ? 0 : radius);
} else {
if(_darkToLight){
_anim->setStartValue(radius);
_anim->setEndValue(0);
}else{
_anim->setStartValue(0);
_anim->setEndValue(radius);
}
}
_center = center;
_grabResult = _target->grabToImage(QSize(w, h));
connect(_grabResult.data(), &QQuickItemGrabResult::ready, this,

View File

@ -10,6 +10,7 @@ class CircularReveal : public QQuickPaintedItem {
Q_OBJECT
Q_PROPERTY_AUTO_P(QQuickItem *, target)
Q_PROPERTY_AUTO(int, radius)
Q_PROPERTY_AUTO(bool, darkToLight)
public:
explicit CircularReveal(QQuickItem *parent = nullptr);
void paint(QPainter *painter) override;

View File

@ -227,7 +227,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE
if ((${QT_VERSION_MAJOR} LESS_EQUAL 6) AND (CMAKE_BUILD_TYPE MATCHES "Release"))
find_program(QML_PLUGIN_DUMP NAMES qmlplugindump)
add_custom_target(Script-Generate-QmlTypes
COMMAND ${QML_PLUGIN_DUMP} -nonrelocatable FluentUI 1.0 ${CMAKE_CURRENT_BINARY_DIR} > ${CMAKE_CURRENT_SOURCE_DIR}/Qt5/imports/FluentUI/plugins.qmltypes
COMMAND ${QML_PLUGIN_DUMP} -nonrelocatable -noinstantiate FluentUI 1.0 ${CMAKE_CURRENT_BINARY_DIR} > ${CMAKE_CURRENT_SOURCE_DIR}/Qt5/imports/FluentUI/plugins.qmltypes
COMMENT "Generate qmltypes........."
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Qt5/imports/FluentUI/plugins.qmltypes
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}

View File

@ -4,32 +4,156 @@
#include <QGuiApplication>
#include <QScreen>
#include <QDateTime>
#include <optional>
#include "FluTools.h"
#ifdef Q_OS_WIN
#pragma comment (lib, "user32.lib")
#pragma comment (lib, "dwmapi.lib")
static DwmSetWindowAttributeFunc pDwmSetWindowAttribute = nullptr;
static DwmExtendFrameIntoClientAreaFunc pDwmExtendFrameIntoClientArea = nullptr;
static DwmIsCompositionEnabledFunc pDwmIsCompositionEnabled = nullptr;
static DwmEnableBlurBehindWindowFunc pDwmEnableBlurBehindWindow = nullptr;
static SetWindowCompositionAttributeFunc pSetWindowCompositionAttribute = nullptr;
static GetDpiForWindowFunc pGetDpiForWindow = nullptr;
static GetSystemMetricsForDpiFunc pGetSystemMetricsForDpi = nullptr;
#include <windows.h>
#include <windowsx.h>
#include <dwmapi.h>
static RTL_OSVERSIONINFOW GetRealOSVersionImpl() {
HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
using RtlGetVersionPtr = NTSTATUS(WINAPI *)(PRTL_OSVERSIONINFOW);
auto pRtlGetVersion =
reinterpret_cast<RtlGetVersionPtr>(::GetProcAddress(hMod, "RtlGetVersion"));
RTL_OSVERSIONINFOW rovi{};
rovi.dwOSVersionInfoSize = sizeof(rovi);
pRtlGetVersion(&rovi);
return rovi;
}
RTL_OSVERSIONINFOW GetRealOSVersion() {
static const auto result = GetRealOSVersionImpl();
return result;
}
static inline bool isWin8OrGreater() {
RTL_OSVERSIONINFOW rovi = GetRealOSVersion();
return (rovi.dwMajorVersion > 6) || (rovi.dwMajorVersion == 6 && rovi.dwMinorVersion >= 2);
}
static inline bool isWin8Point1OrGreater() {
RTL_OSVERSIONINFOW rovi = GetRealOSVersion();
return (rovi.dwMajorVersion > 6) || (rovi.dwMajorVersion == 6 && rovi.dwMinorVersion >= 3);
}
static inline bool isWin10OrGreater() {
RTL_OSVERSIONINFOW rovi = GetRealOSVersion();
return (rovi.dwMajorVersion > 10) || (rovi.dwMajorVersion == 10 && rovi.dwMinorVersion >= 0);
}
static inline bool isWin101809OrGreater() {
RTL_OSVERSIONINFOW rovi = GetRealOSVersion();
return (rovi.dwMajorVersion > 10) ||
(rovi.dwMajorVersion == 10 && rovi.dwMinorVersion >= 0 && rovi.dwBuildNumber >= 17763);
}
static inline bool isWin101903OrGreater() {
RTL_OSVERSIONINFOW rovi = GetRealOSVersion();
return (rovi.dwMajorVersion > 10) ||
(rovi.dwMajorVersion == 10 && rovi.dwMinorVersion >= 0 && rovi.dwBuildNumber >= 18362);
}
static inline bool isWin11OrGreater() {
RTL_OSVERSIONINFOW rovi = GetRealOSVersion();
return (rovi.dwMajorVersion > 10) ||
(rovi.dwMajorVersion == 10 && rovi.dwMinorVersion >= 0 && rovi.dwBuildNumber >= 22000);
}
static inline bool isWin1122H2OrGreater() {
RTL_OSVERSIONINFOW rovi = GetRealOSVersion();
return (rovi.dwMajorVersion > 10) ||
(rovi.dwMajorVersion == 10 && rovi.dwMinorVersion >= 0 && rovi.dwBuildNumber >= 22621);
}
static inline bool isWin10Only() {
return isWin10OrGreater() && !isWin11OrGreater();
}
static inline bool isWin7Only() {
RTL_OSVERSIONINFOW rovi = GetRealOSVersion();
return rovi.dwMajorVersion == 7;
}
static inline QByteArray qtNativeEventType() {
static const auto result = "windows_generic_MSG";
return result;
}
static inline bool isCompositionEnabled() {
typedef HRESULT (WINAPI *DwmIsCompositionEnabledPtr)(BOOL *pfEnabled);
HMODULE module = ::LoadLibraryW(L"dwmapi.dll");
static inline bool initializeFunctionPointers() {
HMODULE module = LoadLibraryW(L"dwmapi.dll");
if (module) {
BOOL composition_enabled = false;
DwmIsCompositionEnabledPtr dwm_is_composition_enabled;
dwm_is_composition_enabled = reinterpret_cast<DwmIsCompositionEnabledPtr>(::GetProcAddress(module, "DwmIsCompositionEnabled"));
if (dwm_is_composition_enabled) {
dwm_is_composition_enabled(&composition_enabled);
if (!pDwmSetWindowAttribute) {
pDwmSetWindowAttribute = reinterpret_cast<DwmSetWindowAttributeFunc>(
GetProcAddress(module, "DwmSetWindowAttribute"));
if (!pDwmSetWindowAttribute) {
return false;
}
}
if (!pDwmExtendFrameIntoClientArea) {
pDwmExtendFrameIntoClientArea = reinterpret_cast<DwmExtendFrameIntoClientAreaFunc>(
GetProcAddress(module, "DwmExtendFrameIntoClientArea"));
if (!pDwmExtendFrameIntoClientArea) {
return false;
}
}
if (!pDwmIsCompositionEnabled) {
pDwmIsCompositionEnabled = reinterpret_cast<DwmIsCompositionEnabledFunc>(
::GetProcAddress(module, "DwmIsCompositionEnabled"));
if (!pDwmIsCompositionEnabled) {
return false;
}
}
if (!pDwmEnableBlurBehindWindow) {
pDwmEnableBlurBehindWindow = reinterpret_cast<DwmEnableBlurBehindWindowFunc>(
GetProcAddress(module, "DwmEnableBlurBehindWindow"));
if (!pDwmEnableBlurBehindWindow) {
return false;
}
}
}
HMODULE user32 = LoadLibraryW(L"user32.dll");
if (module) {
if (!pSetWindowCompositionAttribute) {
pSetWindowCompositionAttribute = reinterpret_cast<SetWindowCompositionAttributeFunc>(
GetProcAddress(user32, "SetWindowCompositionAttribute"));
if (!pSetWindowCompositionAttribute) {
return false;
}
}
if (!pGetDpiForWindow) {
pGetDpiForWindow =
reinterpret_cast<GetDpiForWindowFunc>(GetProcAddress(user32, "GetDpiForWindow"));
if (!pGetDpiForWindow) {
return false;
}
}
if (!pGetSystemMetricsForDpi) {
pGetSystemMetricsForDpi = reinterpret_cast<GetSystemMetricsForDpiFunc>(
GetProcAddress(user32, "GetSystemMetricsForDpi"));
if (!pGetSystemMetricsForDpi) {
return false;
}
}
}
return true;
}
static inline bool isCompositionEnabled() {
if (initializeFunctionPointers()) {
BOOL composition_enabled = false;
pDwmIsCompositionEnabled(&composition_enabled);
return composition_enabled;
}
return false;
@ -37,15 +161,195 @@ static inline bool isCompositionEnabled() {
static inline void setShadow(HWND hwnd) {
const MARGINS shadow = {1, 0, 0, 0};
typedef HRESULT (WINAPI *DwmExtendFrameIntoClientAreaPtr)(HWND hWnd, const MARGINS *pMarInset);
HMODULE module = LoadLibraryW(L"dwmapi.dll");
if (module) {
DwmExtendFrameIntoClientAreaPtr dwm_extendframe_into_client_area_;
dwm_extendframe_into_client_area_ = reinterpret_cast<DwmExtendFrameIntoClientAreaPtr>(GetProcAddress(module, "DwmExtendFrameIntoClientArea"));
if (dwm_extendframe_into_client_area_) {
dwm_extendframe_into_client_area_(hwnd, &shadow);
if (initializeFunctionPointers()) {
pDwmExtendFrameIntoClientArea(hwnd, &shadow);
}
if (isWin7Only()) {
SetClassLong(hwnd, GCL_STYLE, GetClassLong(hwnd, GCL_STYLE) | CS_DROPSHADOW);
}
}
static inline bool setWindowDarkMode(HWND hwnd, const BOOL enable) {
if (!initializeFunctionPointers()) {
return false;
}
return bool(pDwmSetWindowAttribute(hwnd, 20, &enable, sizeof(BOOL)));
}
static inline std::optional<MONITORINFOEXW> getMonitorForWindow(const HWND hwnd) {
Q_ASSERT(hwnd);
if (!hwnd) {
return std::nullopt;
}
const HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (!monitor) {
return std::nullopt;
}
MONITORINFOEXW monitorInfo;
::SecureZeroMemory(&monitorInfo, sizeof(monitorInfo));
monitorInfo.cbSize = sizeof(monitorInfo);
if (::GetMonitorInfoW(monitor, &monitorInfo) == FALSE) {
return std::nullopt;
}
return monitorInfo;
};
static inline bool isFullScreen(const HWND hwnd) {
RECT windowRect = {};
if (::GetWindowRect(hwnd, &windowRect) == FALSE) {
return false;
}
const std::optional<MONITORINFOEXW> mi = getMonitorForWindow(hwnd);
if (!mi.has_value()) {
return false;
}
RECT rcMonitor = mi.value().rcMonitor;
return windowRect.top == rcMonitor.top && windowRect.left == rcMonitor.left &&
windowRect.right == rcMonitor.right && windowRect.bottom == rcMonitor.bottom;
}
static inline bool isMaximized(const HWND hwnd) {
WINDOWPLACEMENT wp;
::GetWindowPlacement(hwnd, &wp);
return wp.showCmd == SW_MAXIMIZE;
}
static inline quint32 getDpiForWindow(const HWND hwnd, const bool horizontal) {
if (const UINT dpi = pGetDpiForWindow(hwnd)) {
return dpi;
}
if (const HDC hdc = ::GetDC(hwnd)) {
bool valid = false;
const int dpiX = ::GetDeviceCaps(hdc, LOGPIXELSX);
const int dpiY = ::GetDeviceCaps(hdc, LOGPIXELSY);
if ((dpiX > 0) && (dpiY > 0)) {
valid = true;
}
::ReleaseDC(hwnd, hdc);
if (valid) {
return (horizontal ? dpiX : dpiY);
}
}
return 96;
}
static inline int getSystemMetrics(const HWND hwnd, const int index, const bool horizontal) {
const UINT dpi = getDpiForWindow(hwnd, horizontal);
if (const int result = pGetSystemMetricsForDpi(index, dpi); result > 0) {
return result;
}
return ::GetSystemMetrics(index);
}
static inline quint32 getResizeBorderThickness(const HWND hwnd, const bool horizontal,
const qreal devicePixelRatio) {
auto frame = horizontal ? SM_CXSIZEFRAME : SM_CYSIZEFRAME;
auto result =
getSystemMetrics(hwnd, frame, horizontal) + getSystemMetrics(hwnd, 92, horizontal);
if (result > 0) {
return result;
}
int thickness = isCompositionEnabled() ? 8 : 4;
return qRound(thickness * devicePixelRatio);
}
static inline bool setWindowEffect(HWND hwnd, const QString &key, const bool &enable) {
static constexpr const MARGINS extendedMargins = {-1, -1, -1, -1};
if (key == QStringLiteral("mica")) {
if (!isWin11OrGreater() || !initializeFunctionPointers()) {
return false;
}
if (enable) {
pDwmExtendFrameIntoClientArea(hwnd, &extendedMargins);
if (isWin1122H2OrGreater()) {
const DWORD backdropType = _DWMSBT_MAINWINDOW;
pDwmSetWindowAttribute(hwnd, 38, &backdropType, sizeof(backdropType));
} else {
const BOOL enable = TRUE;
pDwmSetWindowAttribute(hwnd, 1029, &enable, sizeof(enable));
}
} else {
if (isWin1122H2OrGreater()) {
const DWORD backdropType = _DWMSBT_AUTO;
pDwmSetWindowAttribute(hwnd, 38, &backdropType, sizeof(backdropType));
} else {
const BOOL enable = FALSE;
pDwmSetWindowAttribute(hwnd, 1029, &enable, sizeof(enable));
}
}
return true;
}
if (key == QStringLiteral("mica-alt")) {
if (!isWin1122H2OrGreater() || !initializeFunctionPointers()) {
return false;
}
if (enable) {
pDwmExtendFrameIntoClientArea(hwnd, &extendedMargins);
const DWORD backdropType = _DWMSBT_TABBEDWINDOW;
pDwmSetWindowAttribute(hwnd, 38, &backdropType, sizeof(backdropType));
} else {
const DWORD backdropType = _DWMSBT_AUTO;
pDwmSetWindowAttribute(hwnd, 38, &backdropType, sizeof(backdropType));
}
return true;
}
if (key == QStringLiteral("acrylic")) {
if (!isWin11OrGreater() || !initializeFunctionPointers()) {
return false;
}
if (enable) {
pDwmExtendFrameIntoClientArea(hwnd, &extendedMargins);
DWORD system_backdrop_type = _DWMSBT_TRANSIENTWINDOW;
pDwmSetWindowAttribute(hwnd, 38, &system_backdrop_type, sizeof(DWORD));
} else {
const DWORD backdropType = _DWMSBT_AUTO;
pDwmSetWindowAttribute(hwnd, 38, &backdropType, sizeof(backdropType));
}
return true;
}
if (key == QStringLiteral("dwm-blur")) {
if ((isWin7Only() && !isCompositionEnabled()) || !initializeFunctionPointers()) {
return false;
}
if (enable) {
if (isWin8OrGreater()) {
ACCENT_POLICY policy{};
policy.dwAccentState = ACCENT_ENABLE_BLURBEHIND;
policy.dwAccentFlags = ACCENT_NONE;
WINDOWCOMPOSITIONATTRIBDATA wcad{};
wcad.Attrib = WCA_ACCENT_POLICY;
wcad.pvData = &policy;
wcad.cbData = sizeof(policy);
pSetWindowCompositionAttribute(hwnd, &wcad);
} else {
DWM_BLURBEHIND bb{};
bb.fEnable = TRUE;
bb.dwFlags = DWM_BB_ENABLE;
pDwmEnableBlurBehindWindow(hwnd, &bb);
}
} else {
if (isWin8OrGreater()) {
ACCENT_POLICY policy{};
policy.dwAccentState = ACCENT_DISABLED;
policy.dwAccentFlags = ACCENT_NONE;
WINDOWCOMPOSITIONATTRIBDATA wcad{};
wcad.Attrib = WCA_ACCENT_POLICY;
wcad.pvData = &policy;
wcad.cbData = sizeof(policy);
pSetWindowCompositionAttribute(hwnd, &wcad);
} else {
DWM_BLURBEHIND bb{};
bb.fEnable = FALSE;
bb.dwFlags = DWM_BB_ENABLE;
pDwmEnableBlurBehindWindow(hwnd, &bb);
}
}
return true;
}
return false;
}
#endif
@ -70,6 +374,8 @@ FluFrameless::FluFrameless(QQuickItem *parent) : QQuickItem{parent} {
_closeButton = nullptr;
_topmost = false;
_disabled = false;
_effect = "normal";
_effective = false;
_isWindows11OrGreater = FluTools::getInstance()->isWindows11OrGreater();
}
@ -80,16 +386,62 @@ FluFrameless::~FluFrameless() = default;
}
void FluFrameless::componentComplete() {
#ifdef Q_OS_WIN
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
if (isWin11OrGreater()) {
availableEffects({"mica", "mica-alt", "acrylic", "dwm-blur", "normal"});
} else {
availableEffects({"dwm-blur", "normal"});
}
if (!_effect.isEmpty() && _useSystemEffect) {
effective(setWindowEffect(hwnd, _effect, true));
if (effective()) {
_currentEffect = effect();
}
}
connect(this, &FluFrameless::effectChanged, this, [hwnd, this] {
if (effect() == _currentEffect) {
return;
}
if (effective()) {
setWindowEffect(hwnd, _currentEffect, false);
}
effective(setWindowEffect(hwnd, effect(), true));
if (effective()) {
_currentEffect = effect();
_useSystemEffect = true;
} else {
_effect = "normal";
_currentEffect = "normal";
_useSystemEffect = false;
}
});
connect(this, &FluFrameless::useSystemEffectChanged, this, [this] {
if (!_useSystemEffect) {
effect("normal");
}
});
connect(this, &FluFrameless::isDarkModeChanged, this, [hwnd, this] {
if (effective() && !_currentEffect.isEmpty() && _currentEffect != "normal") {
setWindowDarkMode(hwnd, _isDarkMode);
}
});
#endif
if (_disabled) {
return;
}
int w = window()->width();
int h = window()->height();
_current = window()->winId();
window()->setFlags((window()->flags()) | Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint);
if (!_fixSize) {
window()->setFlag(Qt::WindowMaximizeButtonHint);
}
#ifdef Q_OS_MACOS
window()->setFlag(Qt::FramelessWindowHint, true);
window()->setProperty("__borderWidth", 1);
#endif
#ifdef Q_OS_LINUX
window()->setFlag(Qt::CustomizeWindowHint, true);
window()->setFlag(Qt::FramelessWindowHint, true);
window()->setProperty("__borderWidth", 1);
#endif
window()->installEventFilter(this);
QGuiApplication::instance()->installNativeEventFilter(this);
if (_maximizeButton) {
@ -102,24 +454,36 @@ void FluFrameless::componentComplete() {
setHitTestVisible(_closeButton);
}
#ifdef Q_OS_WIN
#if (QT_VERSION == QT_VERSION_CHECK(6, 5, 3))
qWarning()<<"Qt's own frameless bug, currently only exist in 6.5.3, please use other versions";
#endif
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
# if (QT_VERSION == QT_VERSION_CHECK(6, 5, 3))
qWarning()
<< "Qt's own frameless bug, currently only exist in 6.5.3, please use other versions";
# endif
if (!hwnd) {
hwnd = reinterpret_cast<HWND>(window()->winId());
}
DWORD style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
# if (QT_VERSION == QT_VERSION_CHECK(6, 7, 2))
style &= ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU);
# endif
if (_fixSize) {
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME | WS_CAPTION);;
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME | WS_CAPTION);
;
for (int i = 0; i <= QGuiApplication::screens().count() - 1; ++i) {
connect(QGuiApplication::screens().at(i), &QScreen::logicalDotsPerInchChanged, this, [=] {
SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_FRAMECHANGED);
});
connect(
QGuiApplication::screens().at(i), &QScreen::logicalDotsPerInchChanged, this, [=] {
SetWindowPos(hwnd, nullptr, 0, 0, 0, 0,
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_FRAMECHANGED);
});
}
} else {
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION);
}
SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
SetWindowPos(hwnd, nullptr, 0, 0, 0, 0,
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
connect(window(), &QQuickWindow::screenChanged, this, [hwnd] {
::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED |
SWP_NOOWNERZORDER);
::RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
});
if (!window()->property("_hideShadow").toBool()) {
@ -136,13 +500,12 @@ void FluFrameless::componentComplete() {
window()->setMaximumHeight(window()->maximumHeight() + appBarHeight);
}
window()->resize(QSize(w, h));
connect(this, &FluFrameless::topmostChanged, this, [this] {
_setWindowTopmost(topmost());
});
connect(this, &FluFrameless::topmostChanged, this, [this] { _setWindowTopmost(topmost()); });
_setWindowTopmost(topmost());
}
[[maybe_unused]] bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) {
[[maybe_unused]] bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message,
QT_NATIVE_EVENT_RESULT_TYPE *result) {
#ifdef Q_OS_WIN
if ((eventType != qtNativeEventType()) || !message) {
return false;
@ -163,19 +526,71 @@ void FluFrameless::componentComplete() {
auto *wp = reinterpret_cast<WINDOWPOS *>(lParam);
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0) {
wp->flags |= SWP_NOCOPYBITS;
*result = static_cast<QT_NATIVE_EVENT_RESULT_TYPE>(::DefWindowProcW(hwnd, uMsg, wParam, lParam));
*result = static_cast<QT_NATIVE_EVENT_RESULT_TYPE>(
::DefWindowProcW(hwnd, uMsg, wParam, lParam));
return true;
}
return false;
} else if (uMsg == WM_NCCALCSIZE && wParam == TRUE) {
bool isMaximum = ::IsZoomed(hwnd);
if (isMaximum) {
window()->setProperty("__margins",7);
}else{
window()->setProperty("__margins",0);
const auto clientRect =
((wParam == FALSE) ? reinterpret_cast<LPRECT>(lParam)
: &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0]);
bool isMax = ::isMaximized(hwnd);
bool isFull = ::isFullScreen(hwnd);
if (isMax && !isFull) {
auto ty = getResizeBorderThickness(hwnd, false, window()->devicePixelRatio());
clientRect->top += ty;
clientRect->bottom -= ty;
auto tx = getResizeBorderThickness(hwnd, true, window()->devicePixelRatio());
clientRect->left += tx;
clientRect->right -= tx;
}
_setMaximizeHovered(false);
*result = WVR_REDRAW;
if (isMax || isFull) {
APPBARDATA abd;
SecureZeroMemory(&abd, sizeof(abd));
abd.cbSize = sizeof(abd);
const UINT taskbarState = ::SHAppBarMessage(ABM_GETSTATE, &abd);
if (taskbarState & ABS_AUTOHIDE) {
bool top = false, bottom = false, left = false, right = false;
int edge = -1;
APPBARDATA abd2;
SecureZeroMemory(&abd2, sizeof(abd2));
abd2.cbSize = sizeof(abd2);
abd2.hWnd = ::FindWindowW(L"Shell_TrayWnd", nullptr);
if (abd2.hWnd) {
const HMONITOR windowMonitor =
::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (windowMonitor) {
const HMONITOR taskbarMonitor =
::MonitorFromWindow(abd2.hWnd, MONITOR_DEFAULTTOPRIMARY);
if (taskbarMonitor) {
if (taskbarMonitor == windowMonitor) {
::SHAppBarMessage(ABM_GETTASKBARPOS, &abd2);
edge = abd2.uEdge;
}
}
}
}
top = (edge == ABE_TOP);
bottom = (edge == ABE_BOTTOM);
left = (edge == ABE_LEFT);
right = (edge == ABE_RIGHT);
if (top) {
clientRect->top += 1;
} else if (bottom) {
clientRect->bottom -= 1;
} else if (left) {
clientRect->left += 1;
} else if (right) {
clientRect->right -= 1;
} else {
clientRect->bottom -= 1;
}
} else {
clientRect->bottom += 1;
}
}
*result = 0;
return true;
} else if (uMsg == WM_NCHITTEST) {
if (_isWindows11OrGreater) {
@ -231,21 +646,29 @@ void FluFrameless::componentComplete() {
*result = HTCLIENT;
return true;
} else if (uMsg == WM_NCPAINT) {
if (isCompositionEnabled() && !this->_isFullScreen()) {
return false;
}
*result = FALSE;
return false;
return true;
} else if (uMsg == WM_NCACTIVATE) {
*result = TRUE;
if (isCompositionEnabled()) {
return false;
}
*result = true;
return true;
} else if (_isWindows11OrGreater && (uMsg == WM_NCLBUTTONDBLCLK || uMsg == WM_NCLBUTTONDOWN)) {
if (_hitMaximizeButton()) {
QMouseEvent event = QMouseEvent(QEvent::MouseButtonPress, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QMouseEvent event = QMouseEvent(QEvent::MouseButtonPress, QPoint(), QPoint(),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QGuiApplication::sendEvent(_maximizeButton, &event);
_setMaximizePressed(true);
return true;
}
} else if (_isWindows11OrGreater && (uMsg == WM_NCLBUTTONUP || uMsg == WM_NCRBUTTONUP)) {
if (_hitMaximizeButton()) {
QMouseEvent event = QMouseEvent(QEvent::MouseButtonRelease, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QMouseEvent event = QMouseEvent(QEvent::MouseButtonRelease, QPoint(), QPoint(),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QGuiApplication::sendEvent(_maximizeButton, &event);
_setMaximizePressed(false);
return true;
@ -300,7 +723,8 @@ void FluFrameless::_showSystemMenu(QPoint point) {
return;
}
const QPoint origin = screen->geometry().topLeft();
auto nativePos = QPointF(QPointF(point - origin) * window()->devicePixelRatio()).toPoint() + origin;
auto nativePos =
QPointF(QPointF(point - origin) * window()->devicePixelRatio()).toPoint() + origin;
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
auto hMenu = ::GetSystemMenu(hwnd, FALSE);
if (_isMaximized() || _isFullScreen()) {
@ -317,8 +741,10 @@ void FluFrameless::_showSystemMenu(QPoint point) {
::EnableMenuItem(hMenu, SC_SIZE, MFS_DISABLED);
::EnableMenuItem(hMenu, SC_MAXIMIZE, MFS_DISABLED);
}
const int result = ::TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), nativePos.x(),
nativePos.y(), 0, hwnd, nullptr);
const int result = ::TrackPopupMenu(
hMenu,
(TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)),
nativePos.x(), nativePos.y(), 0, hwnd, nullptr);
if (result) {
::PostMessageW(hwnd, WM_SYSCOMMAND, result, 0);
}
@ -359,27 +785,27 @@ void FluFrameless::_setMaximizeHovered(bool val) {
void FluFrameless::_updateCursor(int edges) {
switch (edges) {
case 0:
window()->setCursor(Qt::ArrowCursor);
break;
case Qt::LeftEdge:
case Qt::RightEdge:
window()->setCursor(Qt::SizeHorCursor);
break;
case Qt::TopEdge:
case Qt::BottomEdge:
window()->setCursor(Qt::SizeVerCursor);
break;
case Qt::LeftEdge | Qt::TopEdge:
case Qt::RightEdge | Qt::BottomEdge:
window()->setCursor(Qt::SizeFDiagCursor);
break;
case Qt::RightEdge | Qt::TopEdge:
case Qt::LeftEdge | Qt::BottomEdge:
window()->setCursor(Qt::SizeBDiagCursor);
break;
default:
break;
case 0:
window()->setCursor(Qt::ArrowCursor);
break;
case Qt::LeftEdge:
case Qt::RightEdge:
window()->setCursor(Qt::SizeHorCursor);
break;
case Qt::TopEdge:
case Qt::BottomEdge:
window()->setCursor(Qt::SizeVerCursor);
break;
case Qt::LeftEdge | Qt::TopEdge:
case Qt::RightEdge | Qt::BottomEdge:
window()->setCursor(Qt::SizeFDiagCursor);
break;
case Qt::RightEdge | Qt::TopEdge:
case Qt::LeftEdge | Qt::BottomEdge:
window()->setCursor(Qt::SizeBDiagCursor);
break;
default:
break;
}
}
@ -424,79 +850,80 @@ void FluFrameless::_setWindowTopmost(bool topmost) {
::SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
#else
window()->setFlag(Qt::WindowStaysOnTopHint,topmost);
window()->setFlag(Qt::WindowStaysOnTopHint, topmost);
#endif
}
bool FluFrameless::eventFilter(QObject *obj, QEvent *ev) {
#ifndef Q_OS_WIN
switch (ev->type()) {
case QEvent::MouseButtonPress:
if(_edges!=0){
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
if(event->button() == Qt::LeftButton){
_updateCursor(_edges);
window()->startSystemResize(Qt::Edges(_edges));
}
}else{
if(_hitAppBar()){
qint64 clickTimer = QDateTime::currentMSecsSinceEpoch();
qint64 offset = clickTimer - this->_clickTimer;
this->_clickTimer = clickTimer;
if(offset<300){
if(_isMaximized()){
showNormal();
}else{
showMaximized();
case QEvent::MouseButtonPress:
if (_edges != 0) {
QMouseEvent *event = static_cast<QMouseEvent *>(ev);
if (event->button() == Qt::LeftButton) {
_updateCursor(_edges);
window()->startSystemResize(Qt::Edges(_edges));
}
} else {
if (_hitAppBar()) {
qint64 clickTimer = QDateTime::currentMSecsSinceEpoch();
qint64 offset = clickTimer - this->_clickTimer;
this->_clickTimer = clickTimer;
if (offset < 300) {
if (_isMaximized()) {
showNormal();
} else {
showMaximized();
}
} else {
window()->startSystemMove();
}
}else{
window()->startSystemMove();
}
}
}
break;
case QEvent::MouseButtonRelease:
_edges = 0;
break;
case QEvent::MouseMove: {
if(_isMaximized() || _isFullScreen()){
break;
}
if(_fixSize){
case QEvent::MouseButtonRelease:
_edges = 0;
break;
}
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
QPoint p =
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
event->pos();
#else
event->position().toPoint();
#endif
if(p.x() >= _margins && p.x() <= (window()->width() - _margins) && p.y() >= _margins && p.y() <= (window()->height() - _margins)){
if(_edges != 0){
_edges = 0;
_updateCursor(_edges);
case QEvent::MouseMove: {
if (_isMaximized() || _isFullScreen()) {
break;
}
if (_fixSize) {
break;
}
QMouseEvent *event = static_cast<QMouseEvent *>(ev);
QPoint p =
# if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
event->pos();
# else
event->position().toPoint();
# endif
if (p.x() >= _margins && p.x() <= (window()->width() - _margins) && p.y() >= _margins &&
p.y() <= (window()->height() - _margins)) {
if (_edges != 0) {
_edges = 0;
_updateCursor(_edges);
}
break;
}
_edges = 0;
if (p.x() < _margins) {
_edges |= Qt::LeftEdge;
}
if (p.x() > (window()->width() - _margins)) {
_edges |= Qt::RightEdge;
}
if (p.y() < _margins) {
_edges |= Qt::TopEdge;
}
if (p.y() > (window()->height() - _margins)) {
_edges |= Qt::BottomEdge;
}
_updateCursor(_edges);
break;
}
_edges = 0;
if ( p.x() < _margins ) {
_edges |= Qt::LeftEdge;
}
if ( p.x() > (window()->width() - _margins) ) {
_edges |= Qt::RightEdge;
}
if ( p.y() < _margins ) {
_edges |= Qt::TopEdge;
}
if ( p.y() > (window()->height() - _margins) ) {
_edges |= Qt::BottomEdge;
}
_updateCursor(_edges);
break;
}
default:
break;
default:
break;
}
#endif
return QObject::eventFilter(obj, ev);

View File

@ -6,6 +6,102 @@
#include <QQmlProperty>
#include "stdafx.h"
#ifdef Q_OS_WIN
# pragma comment(lib, "user32.lib")
# pragma comment(lib, "dwmapi.lib")
# include <windows.h>
# include <windowsx.h>
# include <dwmapi.h>
enum _DWM_SYSTEMBACKDROP_TYPE {
_DWMSBT_AUTO, // [Default] Let DWM automatically decide the system-drawn backdrop for this
// window.
_DWMSBT_NONE, // [Disable] Do not draw any system backdrop.
_DWMSBT_MAINWINDOW, // [Mica] Draw the backdrop material effect corresponding to a
// long-lived window.
_DWMSBT_TRANSIENTWINDOW, // [Acrylic] Draw the backdrop material effect corresponding to a
// transient window.
_DWMSBT_TABBEDWINDOW, // [Mica Alt] Draw the backdrop material effect corresponding to a
// window with a tabbed title bar.
};
enum WINDOWCOMPOSITIONATTRIB {
WCA_UNDEFINED = 0,
WCA_NCRENDERING_ENABLED = 1,
WCA_NCRENDERING_POLICY = 2,
WCA_TRANSITIONS_FORCEDISABLED = 3,
WCA_ALLOW_NCPAINT = 4,
WCA_CAPTION_BUTTON_BOUNDS = 5,
WCA_NONCLIENT_RTL_LAYOUT = 6,
WCA_FORCE_ICONIC_REPRESENTATION = 7,
WCA_EXTENDED_FRAME_BOUNDS = 8,
WCA_HAS_ICONIC_BITMAP = 9,
WCA_THEME_ATTRIBUTES = 10,
WCA_NCRENDERING_EXILED = 11,
WCA_NCADORNMENTINFO = 12,
WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
WCA_VIDEO_OVERLAY_ACTIVE = 14,
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
WCA_DISALLOW_PEEK = 16,
WCA_CLOAK = 17,
WCA_CLOAKED = 18,
WCA_ACCENT_POLICY = 19,
WCA_FREEZE_REPRESENTATION = 20,
WCA_EVER_UNCLOAKED = 21,
WCA_VISUAL_OWNER = 22,
WCA_HOLOGRAPHIC = 23,
WCA_EXCLUDED_FROM_DDA = 24,
WCA_PASSIVEUPDATEMODE = 25,
WCA_USEDARKMODECOLORS = 26,
WCA_CORNER_STYLE = 27,
WCA_PART_COLOR = 28,
WCA_DISABLE_MOVESIZE_FEEDBACK = 29,
WCA_LAST = 30
};
enum ACCENT_STATE {
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3, // Traditional DWM blur
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, // RS4 1803
ACCENT_ENABLE_HOST_BACKDROP = 5, // RS5 1809
ACCENT_INVALID_STATE = 6 // Using this value will remove the window background
};
enum ACCENT_FLAG {
ACCENT_NONE = 0,
ACCENT_ENABLE_ACRYLIC = 1,
ACCENT_ENABLE_ACRYLIC_WITH_LUMINOSITY = 482
};
struct ACCENT_POLICY {
DWORD dwAccentState;
DWORD dwAccentFlags;
DWORD dwGradientColor; // #AABBGGRR
DWORD dwAnimationId;
};
using PACCENT_POLICY = ACCENT_POLICY *;
struct WINDOWCOMPOSITIONATTRIBDATA {
WINDOWCOMPOSITIONATTRIB Attrib;
PVOID pvData;
SIZE_T cbData;
};
using PWINDOWCOMPOSITIONATTRIBDATA = WINDOWCOMPOSITIONATTRIBDATA *;
typedef HRESULT(WINAPI *DwmSetWindowAttributeFunc)(HWND hwnd, DWORD dwAttribute,
LPCVOID pvAttribute, DWORD cbAttribute);
typedef HRESULT(WINAPI *DwmExtendFrameIntoClientAreaFunc)(HWND hwnd, const MARGINS *pMarInset);
typedef HRESULT(WINAPI *DwmIsCompositionEnabledFunc)(BOOL *pfEnabled);
typedef HRESULT(WINAPI *DwmEnableBlurBehindWindowFunc)(HWND hWnd,
const DWM_BLURBEHIND *pBlurBehind);
typedef BOOL(WINAPI *SetWindowCompositionAttributeFunc)(HWND hwnd,
const WINDOWCOMPOSITIONATTRIBDATA *);
typedef UINT(WINAPI *GetDpiForWindowFunc)(HWND hWnd);
typedef int(WINAPI *GetSystemMetricsForDpiFunc)(int nIndex, UINT dpi);
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
using QT_NATIVE_EVENT_RESULT_TYPE = qintptr;
using QT_ENTER_EVENT_TYPE = QEnterEvent;
@ -23,6 +119,11 @@ class FluFrameless : public QQuickItem, QAbstractNativeEventFilter {
Q_PROPERTY_AUTO(bool, topmost)
Q_PROPERTY_AUTO(bool, disabled)
Q_PROPERTY_AUTO(bool, fixSize)
Q_PROPERTY_AUTO(QString, effect)
Q_PROPERTY_READONLY_AUTO(bool, effective)
Q_PROPERTY_READONLY_AUTO(QStringList, availableEffects)
Q_PROPERTY_AUTO(bool, isDarkMode)
Q_PROPERTY_AUTO(bool, useSystemEffect)
QML_NAMED_ELEMENT(FluFrameless)
public:
explicit FluFrameless(QQuickItem *parent = nullptr);
@ -68,6 +169,7 @@ private:
void _setMaximizeHovered(bool val);
private:
quint64 _current = 0;
int _edges = 0;
@ -75,4 +177,5 @@ private:
quint64 _clickTimer = 0;
bool _isWindows11OrGreater = false;
QList<QPointer<QQuickItem>> _hitTestList;
QString _currentEffect;
};

View File

@ -162,31 +162,41 @@ void FluentUI::registerTypes(const char *uri) const {
qmlRegisterUncreatableMetaObject(FluTimelineType::staticMetaObject, uri, major, minor, "FluTimelineType", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluSheetType::staticMetaObject, uri, major, minor, "FluSheetType", "Access to enums & flags only");
qmlRegisterSingletonType(uri, major, minor, "FluApp", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QJSValue {
Q_UNUSED(engine)
return scriptEngine->newQObject(FluApp::getInstance());
});
qmlRegisterSingletonType(uri, major, minor, "FluColors", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QJSValue {
Q_UNUSED(engine)
return scriptEngine->newQObject(FluColors::getInstance());
});
qmlRegisterSingletonType(uri, major, minor, "FluTheme", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QJSValue {
Q_UNUSED(engine)
return scriptEngine->newQObject(FluTheme::getInstance());
});
qmlRegisterSingletonType(uri, major, minor, "FluTools", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QJSValue {
Q_UNUSED(engine)
return scriptEngine->newQObject(FluTools::getInstance());
});
qmlRegisterSingletonType(uri, major, minor, "FluTextStyle", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QJSValue {
Q_UNUSED(engine)
return scriptEngine->newQObject(FluTextStyle::getInstance());
});
// qmlRegisterSingletonInstance(uri, major, minor, "FluApp", FluApp::getInstance());
// qmlRegisterSingletonInstance(uri, major, minor, "FluColors", FluColors::getInstance());
// qmlRegisterSingletonInstance(uri, major, minor, "FluTheme", FluTheme::getInstance());
// qmlRegisterSingletonInstance(uri, major, minor, "FluTools", FluTools::getInstance());
// qmlRegisterSingletonInstance(uri, major, minor, "FluTextStyle", FluTextStyle::getInstance());
qmlRegisterSingletonType<FluApp>(uri, major, minor, "FluApp",
[](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject* {
Q_UNUSED(scriptEngine)
QObject *instance = FluApp::getInstance();
engine->setObjectOwnership(instance, QQmlEngine::CppOwnership);
return instance;
});
qmlRegisterSingletonType<FluColors>(uri, major, minor, "FluColors",
[](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject* {
Q_UNUSED(scriptEngine)
QObject *instance = FluColors::getInstance();
engine->setObjectOwnership(instance, QQmlEngine::CppOwnership);
return instance;
});
qmlRegisterSingletonType<FluTheme>(uri, major, minor, "FluTheme",
[](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject* {
Q_UNUSED(scriptEngine)
QObject *instance = FluTheme::getInstance();
engine->setObjectOwnership(instance, QQmlEngine::CppOwnership);
return instance;
});
qmlRegisterSingletonType<FluTools>(uri, major, minor, "FluTools",
[](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject* {
Q_UNUSED(scriptEngine)
QObject *instance = FluTools::getInstance();
engine->setObjectOwnership(instance, QQmlEngine::CppOwnership);
return instance;
});
qmlRegisterSingletonType<FluTextStyle>(uri, major, minor, "FluTextStyle",
[](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject* {
Q_UNUSED(scriptEngine)
QObject *instance = FluTextStyle::getInstance();
engine->setObjectOwnership(instance, QQmlEngine::CppOwnership);
return instance;
});
qmlRegisterModule(uri, major, minor);
#endif
}

View File

@ -73,7 +73,7 @@ Rectangle{
text:{
if(count<100)
return count
return count+"+"
return "100+"
}
}
}

View File

@ -1,4 +1,4 @@
import QtQuick 2.15
import QtQuick 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
@ -11,17 +11,11 @@ Button {
property color dividerColor: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(233/255,233/255,233/255,1)
property color textColor: {
if(FluTheme.dark){
if(!enabled){
return Qt.rgba(131/255,131/255,131/255,1)
}
if(pressed){
return Qt.rgba(162/255,162/255,162/255,1)
}
return Qt.rgba(1,1,1,1)
}else{
if(!enabled){
return Qt.rgba(160/255,160/255,160/255,1)
}
if(pressed){
return Qt.rgba(96/255,96/255,96/255,1)
}
@ -59,6 +53,6 @@ Button {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font: control.font
color: control.textColor
textColor: control.textColor
}
}

View File

@ -15,7 +15,9 @@ Canvas {
function animateToNewData()
{
chartAnimationProgress = 0.1;
d.jsChart.update();
if (d.jsChart) {
d.jsChart.update();
}
chartAnimator.restart();
}
QtObject{

View File

@ -107,7 +107,7 @@ T.ComboBox {
y: control.height
width: control.width
height: Math.min(contentItem.implicitHeight, control.Window.height - topMargin - bottomMargin)
topMargin: 6
topMargin: 32
bottomMargin: 6
modal: true
contentItem: ListView {

View File

@ -41,7 +41,7 @@ FluPopup {
FluText{
id:text_message
font: FluTextStyle.Body
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
text:message
width: parent.width
topPadding: 4
@ -67,7 +67,7 @@ FluPopup {
topPadding: 20
leftPadding: 20
rightPadding: 20
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
}
FluLoader{
sourceComponent: com_message

View File

@ -1,4 +1,4 @@
import QtQuick 2.15
import QtQuick 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
@ -11,7 +11,8 @@ Text {
font.pixelSize: iconSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: iconColor
color: enabled ? iconColor : Qt.rgba(iconColor.r, iconColor.g, iconColor.b, iconColor.a * 0.5)
text: (String.fromCharCode(iconSource).toString(16))
opacity: iconSource>0
FontLoader{

View File

@ -1,4 +1,4 @@
import QtQuick 2.15
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import FluentUI 1.0
@ -26,14 +26,8 @@ Button {
}
property color iconColor: {
if(FluTheme.dark){
if(!enabled){
return Qt.rgba(130/255,130/255,130/255,1)
}
return Qt.rgba(1,1,1,1)
}else{
if(!enabled){
return Qt.rgba(161/255,161/255,161/255,1)
}
return Qt.rgba(0,0,0,1)
}
}
@ -82,7 +76,7 @@ Button {
text:control.text
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
visible: display !== Button.IconOnly
color: control.textColor
textColor: control.textColor
font: control.font
}
}
@ -99,7 +93,7 @@ Button {
text:control.text
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
visible: display !== Button.IconOnly
color: control.textColor
textColor: control.textColor
font: control.font
}
}

View File

@ -1,4 +1,4 @@
import QtQuick 2.15
import QtQuick 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
@ -11,6 +11,7 @@ Image {
property Component errorItem : com_error
property Component loadingItem: com_loading
id: control
opacity: enabled ? 1 : 0.5
FluLoader{
anchors.fill: parent
sourceComponent: {

View File

@ -190,13 +190,13 @@ FluObject {
spacing: 5
FluText{
text:_super.text
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
width: Math.min(implicitWidth,mcontrol.maxWidth)
}
FluText{
text: _super.moremsg
visible: _super.moremsg
wrapMode : Text.WrapAnywhere
wrapMode : Text.WordWrap
textColor: FluColors.Grey120
width: Math.min(implicitWidth,mcontrol.maxWidth)
}

View File

@ -1,4 +1,4 @@
import QtQuick 2.15
import QtQuick 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
@ -13,7 +13,7 @@ FluButton {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font: control.font
color: control.textColor
textColor: control.textColor
anchors.verticalCenter: parent.verticalCenter
}
Item{

View File

@ -20,7 +20,7 @@ TextArea{
return normalColor
}
font:FluTextStyle.Body
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
padding: 8
leftPadding: padding+4
renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering

View File

@ -41,13 +41,15 @@ ProgressBar{
height: parent.height
radius: d._radius
color: control.color
PropertyAnimation on x {
id:animator_x
SequentialAnimation on x {
id: animator_x
running: control.indeterminate && control.visible
from: -rect_progress.width
to:control.width+rect_progress.width
loops: Animation.Infinite
duration: control.duration
PropertyAnimation {
from: -rect_progress.width
to: control.width + rect_progress.width
duration: control.duration
}
}
}
}

View File

@ -5,8 +5,11 @@ import QtQuick.Controls 2.15
import FluentUI 1.0
FluPage {
property bool autoResetScroll: false
default property alias content: container.data
Flickable{
id: flickable
clip: true
anchors.fill: parent
ScrollBar.vertical: FluScrollBar {}
@ -17,4 +20,14 @@ FluPage {
width: parent.width
}
}
function resetScroll() {
flickable.contentY = 0;
}
StackView.onActivated: {
if (autoResetScroll) {
resetScroll(); // Call this function to reset the scroll position to the top
}
}
}

View File

@ -1,11 +1,11 @@
import QtQuick 2.15
import QtQuick 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
Text {
property color textColor: FluTheme.fontPrimaryColor
id:text
color: textColor
color: enabled ? textColor : Qt.rgba(textColor.r, textColor.g, textColor.b, textColor.a * 0.7)
renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering
font: FluTextStyle.Body
}

View File

@ -335,7 +335,7 @@ FluButton {
if (hours === "12") {
hours24 = (period === control.amText) ? 0 : 12;
} else {
hours24 = (period === control.pmText) ? hours24 : hours24 + 12;
hours24 = (period === control.pmText) ? hours24 + 12 : hours24;
}
}
date.setHours(hours24);

View File

@ -98,7 +98,7 @@ Item{
Component{
id:com_lable
FluText{
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
horizontalAlignment: isRight ? Qt.AlignRight : Qt.AlignLeft
text: {
if(modelData.lable){
@ -113,7 +113,7 @@ Item{
Component{
id:com_text
FluText{
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
horizontalAlignment: isRight ? Qt.AlignRight : Qt.AlignLeft
text: modelData.text
textFormat: Text.RichText

View File

@ -175,7 +175,7 @@ Popup{
FluText{
id: text_desc
font: FluTextStyle.Body
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
maximumLineCount: 4
elide: Text.ElideRight
text: {

View File

@ -13,6 +13,11 @@ Window {
property bool fixSize: false
property Component loadingItem: com_loading
property bool fitsAppBarWindows: false
property var tintOpacity: FluTheme.dark ? 0.80 : 0.75
property int blurRadius: 60
property alias effect: frameless.effect
readonly property alias effective: frameless.effective
readonly property alias availableEffects: frameless.availableEffects
property Item appBar: FluAppBar {
title: window.title
height: 30
@ -24,6 +29,15 @@ Window {
icon: window.windowIcon
}
property color backgroundColor: {
if(frameless.effective && active){
var backcolor
if(frameless.effect==="dwm-blur"){
backcolor = FluTools.withOpacity(FluTheme.windowActiveBackgroundColor, window.tintOpacity)
}else{
backcolor = "transparent"
}
return backcolor
}
if(active){
return FluTheme.windowActiveBackgroundColor
}
@ -100,6 +114,8 @@ Window {
fixSize: window.fixSize
topmost: window.stayTop
disabled: FluApp.useSystemAppBar
isDarkMode: FluTheme.dark
useSystemEffect: !FluTheme.blurBehindWindowEnabled
Component.onCompleted: {
frameless.setHitTestVisible(appBar.layoutMacosButtons)
frameless.setHitTestVisible(appBar.layoutStandardbuttons)
@ -107,6 +123,11 @@ Window {
Component.onDestruction: {
frameless.onDestruction()
}
onEffectiveChanged: {
if(effective){
FluTheme.blurBehindWindowEnabled = false
}
}
}
Component{
id:com_background
@ -162,8 +183,8 @@ Window {
FluAcrylic{
anchors.fill: parent
target: img_back
tintOpacity: FluTheme.dark ? 0.80 : 0.75
blurRadius: 64
tintOpacity: window.tintOpacity
blurRadius: window.blurRadius
visible: window.active && FluTheme.blurBehindWindowEnabled
tintColor: FluTheme.dark ? Qt.rgba(0, 0, 0, 1) : Qt.rgba(1, 1, 1, 1)
targetRect: Qt.rect(window.x-window.screen.virtualX,window.y-window.screen.virtualY,window.width,window.height)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 559 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 395 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 KiB

After

Width:  |  Height:  |  Size: 142 KiB

View File

@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
// 'qmlplugindump -nonrelocatable FluentUI 1.0 D:/QtProjects/build-FluentUI-Desktop_Qt_5_15_2_MSVC2019_64bit-Release/src'
// 'qmlplugindump -nonrelocatable -noinstantiate FluentUI 1.0 F:/FluentUI/build/Desktop_Qt_5_15_2_MSVC2019_32bit-Release/src'
Module {
dependencies: ["QtQuick 2.0"]
@ -150,6 +150,11 @@ Module {
Property { name: "topmost"; type: "bool" }
Property { name: "disabled"; type: "bool" }
Property { name: "fixSize"; type: "bool" }
Property { name: "effect"; type: "string" }
Property { name: "effective"; type: "bool"; isReadonly: true }
Property { name: "availableEffects"; type: "QStringList"; isReadonly: true }
Property { name: "isDarkMode"; type: "bool" }
Property { name: "useSystemEffect"; type: "bool" }
Method { name: "showFullScreen" }
Method { name: "showMaximized" }
Method { name: "showMinimized" }
@ -669,12 +674,12 @@ Module {
}
}
Component {
name: "Fluent_Icons"
name: "FluentIcons"
exports: ["FluentUI/FluentIcons 1.0"]
isCreatable: false
exportMetaObjectRevisions: [0]
Enum {
name: "Fluent_IconType"
name: "Type"
values: {
"GlobalNavButton": 59136,
"Wifi": 59137,
@ -2449,6 +2454,240 @@ Module {
Method { name: "clear" }
Method { name: "invalidate" }
}
Component {
name: "QmlQCustomPlot::Axis"
prototype: "QObject"
exports: ["FluentUI/Axis 1.0"]
isCreatable: false
exportMetaObjectRevisions: [0]
Enum {
name: "TickerType"
values: {
"Fixed": 0,
"Log": 1,
"Pi": 2,
"Text": 3,
"DateTime": 4,
"Time": 5
}
}
Property { name: "visible"; type: "bool" }
Property { name: "label"; type: "string" }
Property { name: "upper"; type: "float" }
Property { name: "lower"; type: "float" }
Property { name: "grid"; type: "QmlQCustomPlot::Grid"; isReadonly: true; isPointer: true }
Property { name: "ticker"; type: "QmlQCustomPlot::Ticker"; isReadonly: true; isPointer: true }
Signal {
name: "visibleChanged"
Parameter { type: "bool" }
}
Signal {
name: "labelChanged"
Parameter { type: "string" }
}
Signal {
name: "upperChanged"
Parameter { type: "float" }
}
Signal {
name: "lowerChanged"
Parameter { type: "float" }
}
Signal {
name: "gridChanged"
Parameter { type: "QmlQCustomPlot::Grid"; isPointer: true }
}
Signal {
name: "tickerChanged"
Parameter { type: "QmlQCustomPlot::Ticker"; isPointer: true }
}
Method {
name: "setTickerType"
Parameter { name: "type"; type: "TickerType" }
}
Method {
name: "setRange"
Parameter { name: "position"; type: "float" }
Parameter { name: "size"; type: "float" }
Parameter { name: "align"; type: "Qt::AlignmentFlag" }
}
Method {
name: "setRange"
Parameter { name: "lower"; type: "float" }
Parameter { name: "upper"; type: "float" }
}
}
Component {
name: "QmlQCustomPlot::BasePlot"
defaultProperty: "data"
prototype: "QQuickPaintedItem"
exports: ["FluentUI/BasePlot 1.0"]
exportMetaObjectRevisions: [0]
Property { name: "backgroundColor"; type: "QColor" }
Property { name: "xAxis"; type: "QmlQCustomPlot::Axis"; isReadonly: true; isPointer: true }
Property { name: "x1Axis"; type: "QmlQCustomPlot::Axis"; isReadonly: true; isPointer: true }
Property { name: "yAxis"; type: "QmlQCustomPlot::Axis"; isReadonly: true; isPointer: true }
Property { name: "y1Axis"; type: "QmlQCustomPlot::Axis"; isReadonly: true; isPointer: true }
Property { name: "graphs"; type: "QVariantMap"; isReadonly: true }
Signal {
name: "backgroundColorChanged"
Parameter { type: "QColor" }
}
Signal {
name: "xAxisChanged"
Parameter { type: "QmlQCustomPlot::Axis"; isPointer: true }
}
Signal {
name: "x1AxisChanged"
Parameter { type: "QmlQCustomPlot::Axis"; isPointer: true }
}
Signal {
name: "yAxisChanged"
Parameter { type: "QmlQCustomPlot::Axis"; isPointer: true }
}
Signal {
name: "y1AxisChanged"
Parameter { type: "QmlQCustomPlot::Axis"; isPointer: true }
}
Method {
name: "addGraph"
Parameter { name: "key"; type: "string" }
}
Method {
name: "removeGraph"
Parameter { name: "key"; type: "string" }
}
Method {
name: "rescaleAxes"
Parameter { name: "onlyVisiblePlottables"; type: "bool" }
}
Method { name: "rescaleAxes" }
}
Component {
name: "QmlQCustomPlot::Grid"
prototype: "QObject"
exports: ["FluentUI/PlotGrid 1.0"]
isCreatable: false
exportMetaObjectRevisions: [0]
Enum {
name: "LineType"
values: {
"NoPen": 0,
"SolidLine": 1,
"DashLine": 2,
"DotLine": 3,
"DashDotLine": 4,
"DashDotDotLine": 5
}
}
Property { name: "visible"; type: "bool" }
Property { name: "subVisible"; type: "bool" }
Property { name: "lineWidth"; type: "int" }
Property { name: "lineColor"; type: "QColor" }
Property { name: "lineType"; type: "LineType" }
Property { name: "subLineWidth"; type: "int" }
Property { name: "subLineColor"; type: "QColor" }
Property { name: "subLineType"; type: "LineType" }
Signal {
name: "visibleChanged"
Parameter { type: "bool" }
}
Signal {
name: "subVisibleChanged"
Parameter { type: "bool" }
}
Signal {
name: "lineWidthChanged"
Parameter { type: "int" }
}
Signal {
name: "lineColorChanged"
Parameter { type: "QColor" }
}
Signal {
name: "lineTypeChanged"
Parameter { type: "LineType" }
}
Signal {
name: "subLineWidthChanged"
Parameter { type: "int" }
}
Signal {
name: "subLineColorChanged"
Parameter { type: "QColor" }
}
Signal {
name: "subLineTypeChanged"
Parameter { type: "LineType" }
}
}
Component {
name: "QmlQCustomPlot::Ticker"
prototype: "QObject"
exports: ["FluentUI/Ticker 1.0"]
isCreatable: false
exportMetaObjectRevisions: [0]
Property { name: "ticks"; type: "bool" }
Property { name: "subTicks"; type: "bool" }
Property { name: "tickCount"; type: "int" }
Property { name: "baseWidth"; type: "int" }
Property { name: "baseColor"; type: "QColor" }
Property { name: "tickColor"; type: "QColor" }
Property { name: "subTickColor"; type: "QColor" }
Signal {
name: "ticksChanged"
Parameter { type: "bool" }
}
Signal {
name: "subTicksChanged"
Parameter { type: "bool" }
}
Signal {
name: "tickCountChanged"
Parameter { type: "int" }
}
Signal {
name: "baseWidthChanged"
Parameter { type: "int" }
}
Signal {
name: "baseColorChanged"
Parameter { type: "QColor" }
}
Signal {
name: "tickColorChanged"
Parameter { type: "QColor" }
}
Signal {
name: "subTickColorChanged"
Parameter { type: "QColor" }
}
}
Component {
name: "QmlQCustomPlot::TimePlot"
defaultProperty: "data"
prototype: "QmlQCustomPlot::BasePlot"
exports: ["FluentUI/TimePlot 1.0"]
exportMetaObjectRevisions: [0]
Property { name: "plotTimeRangeInMilliseconds"; type: "int" }
Signal {
name: "plotTimeRangeInMillisecondsChanged"
Parameter { type: "int" }
}
Method {
name: "setTimeFormat"
Parameter { name: "format"; type: "string" }
}
Method {
name: "addCurrentTimeValue"
Parameter { name: "name"; type: "string" }
Parameter { name: "value"; type: "double" }
}
Method {
name: "addCurrentTimeValues"
Parameter { name: "values"; type: "QVariantMap" }
}
}
Component {
prototype: "QQuickItem"
name: "FluentUI/FluAcrylic 1.0"
@ -2507,37 +2746,37 @@ Module {
Property { name: "darkClickListener"; type: "QVariant" }
Property {
name: "buttonStayTop"
type: "FluIconButton_QMLTYPE_18"
type: "FluIconButton_QMLTYPE_19"
isReadonly: true
isPointer: true
}
Property {
name: "buttonMinimize"
type: "FluIconButton_QMLTYPE_18"
type: "FluIconButton_QMLTYPE_19"
isReadonly: true
isPointer: true
}
Property {
name: "buttonMaximize"
type: "FluIconButton_QMLTYPE_18"
type: "FluIconButton_QMLTYPE_19"
isReadonly: true
isPointer: true
}
Property {
name: "buttonClose"
type: "FluIconButton_QMLTYPE_18"
type: "FluIconButton_QMLTYPE_19"
isReadonly: true
isPointer: true
}
Property {
name: "buttonDark"
type: "FluIconButton_QMLTYPE_18"
type: "FluIconButton_QMLTYPE_19"
isReadonly: true
isPointer: true
}
Property {
name: "layoutMacosButtons"
type: "FluLoader_QMLTYPE_16"
type: "FluLoader_QMLTYPE_11"
isReadonly: true
isPointer: true
}
@ -3230,15 +3469,15 @@ Module {
defaultProperty: "data"
Property { name: "logo"; type: "QUrl" }
Property { name: "title"; type: "string" }
Property { name: "items"; type: "FluObject_QMLTYPE_164"; isPointer: true }
Property { name: "footerItems"; type: "FluObject_QMLTYPE_164"; isPointer: true }
Property { name: "items"; type: "FluObject_QMLTYPE_176"; isPointer: true }
Property { name: "footerItems"; type: "FluObject_QMLTYPE_176"; isPointer: true }
Property { name: "displayMode"; type: "int" }
Property { name: "autoSuggestBox"; type: "QQmlComponent"; isPointer: true }
Property { name: "actionItem"; type: "QQmlComponent"; isPointer: true }
Property { name: "topPadding"; type: "int" }
Property { name: "pageMode"; type: "int" }
Property { name: "navItemRightMenu"; type: "FluMenu_QMLTYPE_36"; isPointer: true }
Property { name: "navItemExpanderRightMenu"; type: "FluMenu_QMLTYPE_36"; isPointer: true }
Property { name: "navItemRightMenu"; type: "FluMenu_QMLTYPE_48"; isPointer: true }
Property { name: "navItemExpanderRightMenu"; type: "FluMenu_QMLTYPE_48"; isPointer: true }
Property { name: "navCompactWidth"; type: "int" }
Property { name: "navTopMargin"; type: "int" }
Property { name: "cellHeight"; type: "int" }
@ -3246,13 +3485,13 @@ Module {
Property { name: "hideNavAppBar"; type: "bool" }
Property {
name: "buttonMenu"
type: "FluIconButton_QMLTYPE_18"
type: "FluIconButton_QMLTYPE_19"
isReadonly: true
isPointer: true
}
Property {
name: "buttonBack"
type: "FluIconButton_QMLTYPE_18"
type: "FluIconButton_QMLTYPE_19"
isReadonly: true
isPointer: true
}
@ -3620,7 +3859,7 @@ Module {
Method {
name: "removeWindow"
type: "QVariant"
Parameter { name: "window"; type: "QVariant" }
Parameter { name: "win"; type: "QVariant" }
}
Method {
name: "exit"
@ -4138,6 +4377,9 @@ Module {
Property { name: "fixSize"; type: "bool" }
Property { name: "loadingItem"; type: "QQmlComponent"; isPointer: true }
Property { name: "fitsAppBarWindows"; type: "bool" }
Property { name: "tintOpacity"; type: "QVariant" }
Property { name: "blurRadius"; type: "int" }
Property { name: "availableEffects"; type: "QVariant"; isReadonly: true }
Property { name: "appBar"; type: "QQuickItem"; isPointer: true }
Property { name: "backgroundColor"; type: "QColor" }
Property { name: "stayTop"; type: "bool" }
@ -4151,6 +4393,7 @@ Module {
Property { name: "autoCenter"; type: "bool" }
Property { name: "autoDestroy"; type: "bool" }
Property { name: "useSystemAppBar"; type: "bool" }
Property { name: "__margins"; type: "int" }
Property { name: "resizeBorderColor"; type: "QColor" }
Property { name: "resizeBorderWidth"; type: "int" }
Property { name: "closeListener"; type: "QVariant" }
@ -4158,6 +4401,8 @@ Module {
Property { name: "_route"; type: "string" }
Property { name: "_hideShadow"; type: "bool" }
Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true }
Property { name: "effect"; type: "string" }
Property { name: "effective"; type: "bool"; isReadonly: true }
Signal {
name: "initArgument"
Parameter { name: "argument"; type: "QVariant" }
@ -4195,11 +4440,6 @@ Module {
Method { name: "clearAllInfo"; type: "QVariant" }
Method { name: "moveWindowToDesktopCenter"; type: "QVariant" }
Method { name: "fixWindowSize"; type: "QVariant" }
Method {
name: "registerForWindowResult"
type: "QVariant"
Parameter { name: "path"; type: "QVariant" }
}
Method {
name: "setResult"
type: "QVariant"
@ -4219,6 +4459,8 @@ Module {
type: "QVariant"
Parameter { name: "val"; type: "QVariant" }
}
Method { name: "deleteLater"; type: "QVariant" }
Method { name: "containerItem"; type: "QVariant" }
}
Component {
prototype: "QQuickWindowQmlImpl"
@ -4241,6 +4483,9 @@ Module {
Property { name: "fixSize"; type: "bool" }
Property { name: "loadingItem"; type: "QQmlComponent"; isPointer: true }
Property { name: "fitsAppBarWindows"; type: "bool" }
Property { name: "tintOpacity"; type: "QVariant" }
Property { name: "blurRadius"; type: "int" }
Property { name: "availableEffects"; type: "QVariant"; isReadonly: true }
Property { name: "appBar"; type: "QQuickItem"; isPointer: true }
Property { name: "backgroundColor"; type: "QColor" }
Property { name: "stayTop"; type: "bool" }
@ -4254,6 +4499,7 @@ Module {
Property { name: "autoCenter"; type: "bool" }
Property { name: "autoDestroy"; type: "bool" }
Property { name: "useSystemAppBar"; type: "bool" }
Property { name: "__margins"; type: "int" }
Property { name: "resizeBorderColor"; type: "QColor" }
Property { name: "resizeBorderWidth"; type: "int" }
Property { name: "closeListener"; type: "QVariant" }
@ -4261,6 +4507,8 @@ Module {
Property { name: "_route"; type: "string" }
Property { name: "_hideShadow"; type: "bool" }
Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true }
Property { name: "effect"; type: "string" }
Property { name: "effective"; type: "bool"; isReadonly: true }
Signal {
name: "initArgument"
Parameter { name: "argument"; type: "QVariant" }
@ -4298,11 +4546,6 @@ Module {
Method { name: "clearAllInfo"; type: "QVariant" }
Method { name: "moveWindowToDesktopCenter"; type: "QVariant" }
Method { name: "fixWindowSize"; type: "QVariant" }
Method {
name: "registerForWindowResult"
type: "QVariant"
Parameter { name: "path"; type: "QVariant" }
}
Method {
name: "setResult"
type: "QVariant"
@ -4322,6 +4565,8 @@ Module {
type: "QVariant"
Parameter { name: "val"; type: "QVariant" }
}
Method { name: "deleteLater"; type: "QVariant" }
Method { name: "containerItem"; type: "QVariant" }
}
Component {
prototype: "QQuickItem"

View File

@ -73,7 +73,7 @@ Rectangle{
text:{
if(count<100)
return count
return count+"+"
return "100+"
}
}
}

View File

@ -14,7 +14,9 @@ Canvas {
function animateToNewData()
{
chartAnimationProgress = 0.1;
d.jsChart.update();
if (d.jsChart) {
d.jsChart.update();
}
chartAnimator.restart();
}
QtObject{

View File

@ -107,7 +107,7 @@ T.ComboBox {
y: control.height
width: control.width
height: Math.min(contentItem.implicitHeight, control.Window.height - topMargin - bottomMargin)
topMargin: 6
topMargin: 32
bottomMargin: 6
modal: true
contentItem: ListView {

View File

@ -41,7 +41,7 @@ FluPopup {
FluText{
id:text_message
font: FluTextStyle.Body
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
text:message
width: parent.width
topPadding: 4
@ -67,7 +67,7 @@ FluPopup {
topPadding: 20
leftPadding: 20
rightPadding: 20
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
}
FluLoader{
sourceComponent: com_message

View File

@ -190,13 +190,13 @@ FluObject {
spacing: 5
FluText{
text:_super.text
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
width: Math.min(implicitWidth,mcontrol.maxWidth)
}
FluText{
text: _super.moremsg
visible: _super.moremsg
wrapMode : Text.WrapAnywhere
wrapMode : Text.WordWrap
textColor: FluColors.Grey120
width: Math.min(implicitWidth,mcontrol.maxWidth)
}

View File

@ -21,7 +21,7 @@ TextArea{
return normalColor
}
font:FluTextStyle.Body
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
padding: 8
leftPadding: padding+4
renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering

View File

@ -42,13 +42,15 @@ ProgressBar{
height: parent.height
radius: d._radius
color: control.color
PropertyAnimation on x {
id:animator_x
SequentialAnimation on x {
id: animator_x
running: control.indeterminate && control.visible
from: -rect_progress.width
to:control.width+rect_progress.width
loops: Animation.Infinite
duration: control.duration
PropertyAnimation {
from: -rect_progress.width
to: control.width + rect_progress.width
duration: control.duration
}
}
}
}

View File

@ -5,8 +5,11 @@ import QtQuick.Controls
import FluentUI
FluPage {
property bool autoResetScroll: false
default property alias content: container.data
Flickable{
id: flickable
clip: true
anchors.fill: parent
ScrollBar.vertical: FluScrollBar {}
@ -17,4 +20,14 @@ FluPage {
width: parent.width
}
}
function resetScroll() {
flickable.contentY = 0;
}
StackView.onActivated: {
if (autoResetScroll) {
resetScroll(); // Call this function to reset the scroll position to the top
}
}
}

View File

@ -335,7 +335,7 @@ FluButton {
if (hours === "12") {
hours24 = (period === control.amText) ? 0 : 12;
} else {
hours24 = (period === control.pmText) ? hours24 : hours24 + 12;
hours24 = (period === control.pmText) ? hours24 + 12 : hours24;
}
}
date.setHours(hours24);

View File

@ -98,7 +98,7 @@ Item{
Component{
id:com_lable
FluText{
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
horizontalAlignment: isRight ? Qt.AlignRight : Qt.AlignLeft
text: {
if(modelData.lable){
@ -113,7 +113,7 @@ Item{
Component{
id:com_text
FluText{
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
horizontalAlignment: isRight ? Qt.AlignRight : Qt.AlignLeft
text: modelData.text
textFormat: Text.RichText

View File

@ -175,7 +175,7 @@ Popup{
FluText{
id: text_desc
font: FluTextStyle.Body
wrapMode: Text.WrapAnywhere
wrapMode: Text.WordWrap
maximumLineCount: 4
elide: Text.ElideRight
text: {

View File

@ -12,6 +12,11 @@ Window {
property bool fixSize: false
property Component loadingItem: com_loading
property bool fitsAppBarWindows: false
property var tintOpacity: FluTheme.dark ? 0.80 : 0.75
property int blurRadius: 60
property alias effect: frameless.effect
readonly property alias effective: frameless.effective
readonly property alias availableEffects: frameless.availableEffects
property Item appBar: FluAppBar {
title: window.title
height: 30
@ -23,6 +28,15 @@ Window {
icon: window.windowIcon
}
property color backgroundColor: {
if(frameless.effective && active){
var backcolor
if(frameless.effect==="dwm-blur"){
backcolor = FluTools.withOpacity(FluTheme.windowActiveBackgroundColor, window.tintOpacity)
}else{
backcolor = "transparent"
}
return backcolor
}
if(active){
return FluTheme.windowActiveBackgroundColor
}
@ -99,6 +113,8 @@ Window {
fixSize: window.fixSize
topmost: window.stayTop
disabled: FluApp.useSystemAppBar
isDarkMode: FluTheme.dark
useSystemEffect: !FluTheme.blurBehindWindowEnabled
Component.onCompleted: {
frameless.setHitTestVisible(appBar.layoutMacosButtons)
frameless.setHitTestVisible(appBar.layoutStandardbuttons)
@ -106,6 +122,11 @@ Window {
Component.onDestruction: {
frameless.onDestruction()
}
onEffectiveChanged: {
if(effective){
FluTheme.blurBehindWindowEnabled = false
}
}
}
Component{
id:com_background
@ -161,8 +182,8 @@ Window {
FluAcrylic{
anchors.fill: parent
target: img_back
tintOpacity: FluTheme.dark ? 0.80 : 0.75
blurRadius: 64
tintOpacity: window.tintOpacity
blurRadius: window.blurRadius
visible: window.active && FluTheme.blurBehindWindowEnabled
tintColor: FluTheme.dark ? Qt.rgba(0, 0, 0, 1) : Qt.rgba(1, 1, 1, 1)
targetRect: Qt.rect(window.x-window.screen.virtualX,window.y-window.screen.virtualY,window.width,window.height)
@ -274,7 +295,7 @@ Window {
sourceComponent: window.useSystemAppBar ? undefined : com_app_bar
}
Item{
id:layout_content
id: layout_content
anchors{
top: loader_app_bar.bottom
left: parent.left
@ -293,7 +314,6 @@ Window {
id:info_bar
root: layout_container
}
FluLoader{
id:loader_border
anchors.fill: parent

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 559 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 395 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 KiB

After

Width:  |  Height:  |  Size: 142 KiB