Merge branch '1.7.5-dev'

This commit is contained in:
朱子楚\zhuzi 2024-04-24 09:53:59 +08:00
commit 789d9164a1
130 changed files with 8113 additions and 6586 deletions

View File

@ -91,14 +91,14 @@ jobs:
if: startsWith(github.event.ref, 'refs/tags/')
uses: zhuzichu520/inno-setup-action@v1.0.1
with:
filepath: ./action-cli/InstallerScript.iss
filepath: ./package/InstallerScript.iss
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ./action-cli/installer.exe
file: ./package/installer.exe
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.exe
tag: ${{ github.ref }}
overwrite: true

View File

@ -78,14 +78,14 @@ jobs:
if: startsWith(github.event.ref, 'refs/tags/')
uses: zhuzichu520/inno-setup-action@v1.0.1
with:
filepath: ./action-cli/InstallerScript.iss
filepath: ./package/InstallerScript.iss
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ./action-cli/installer.exe
file: ./package/installer.exe
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.exe
tag: ${{ github.ref }}
overwrite: true

View File

@ -85,14 +85,14 @@ jobs:
if: startsWith(github.event.ref, 'refs/tags/')
uses: zhuzichu520/inno-setup-action@v1.0.1
with:
filepath: ./action-cli/InstallerScript.iss
filepath: ./package/InstallerScript.iss
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ./action-cli/installer.exe
file: ./package/installer.exe
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.exe
tag: ${{ github.ref }}
overwrite: true

4
.gitignore vendored
View File

@ -36,10 +36,8 @@ bin
build
cmake-build-*
.idea
package
example/Version.h
action-cli
dist
*.qm

View File

@ -8,7 +8,7 @@ if(MSVC)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")
endif ()
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/.cmake/)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/.cmake/)
include(GetGitRevisionDescription)

View File

@ -69,7 +69,7 @@ if(WIN32)
)
configure_file(
${CMAKE_SOURCE_DIR}/.cmake/InstallerScript.iss.in
${CMAKE_SOURCE_DIR}/action-cli/InstallerScript.iss
${CMAKE_SOURCE_DIR}/package/InstallerScript.iss
)
endif ()

View File

@ -127,7 +127,6 @@
<file>qml/global/ItemsOriginal.qml</file>
<file>qml/global/qmldir</file>
<file>qml/page/T_Acrylic.qml</file>
<file>qml/page/T_Awesome.qml</file>
<file>qml/page/T_Badge.qml</file>
<file>qml/page/T_BreadcrumbBar.qml</file>
<file>qml/page/T_Buttons.qml</file>
@ -181,7 +180,6 @@
<file>qml/window/PageWindow.qml</file>
<file>qml/page/T_StaggeredLayout.qml</file>
<file>qml/page/T_Clip.qml</file>
<file>qml/page/T_3D.qml</file>
<file>qml/page/T_Network.qml</file>
<file>qml/page/T_ShortcutPicker.qml</file>
<file>qml/chart/T_BarChart.qml</file>
@ -209,5 +207,8 @@
<file>qml/page/T_GroupBox.qml</file>
<file>res/image/bg_scenic.jpg</file>
<file>qml/window/FluentInitializrWindow.qml</file>
<file>qml/page/T_OpenGL.qml</file>
<file>qml/page/T_Icons.qml</file>
</qresource>
<qresource prefix="/"/>
</RCC>

View File

@ -87,22 +87,22 @@
<context>
<name>InitializrHelper</name>
<message>
<location filename="src/helper/InitializrHelper.cpp" line="77"/>
<location filename="src/helper/InitializrHelper.cpp" line="69"/>
<source>The name cannot be empty</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/helper/InitializrHelper.cpp" line="81"/>
<location filename="src/helper/InitializrHelper.cpp" line="73"/>
<source>The creation path cannot be empty</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/helper/InitializrHelper.cpp" line="86"/>
<location filename="src/helper/InitializrHelper.cpp" line="78"/>
<source>The path does not exist</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/helper/InitializrHelper.cpp" line="92"/>
<location filename="src/helper/InitializrHelper.cpp" line="84"/>
<source>%1 folder already exists</source>
<translation type="unfinished"></translation>
</message>
@ -425,7 +425,7 @@
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="367"/>
<source>Awesome</source>
<source>Icons</source>
<translation type="unfinished"></translation>
</message>
<message>
@ -475,42 +475,42 @@
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="430"/>
<source>QRCode</source>
<source>OpenGL</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="436"/>
<source>Tour</source>
<source>QRCode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="442"/>
<source>Timeline</source>
<source>Tour</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="448"/>
<source>Captcha</source>
<source>Timeline</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="454"/>
<source>Captcha</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="460"/>
<source>Network</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="461"/>
<location filename="qml/global/ItemsOriginal.qml" line="467"/>
<source>Remote Loader</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="475"/>
<source>Hot Loader</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="481"/>
<source>3D</source>
<source>Hot Loader</source>
<translation type="unfinished"></translation>
</message>
<message>
@ -546,104 +546,104 @@
<context>
<name>MainWindow</name>
<message>
<location filename="qml/window/MainWindow.qml" line="307"/>
<source>Dark Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="83"/>
<location filename="qml/window/MainWindow.qml" line="91"/>
<location filename="qml/window/MainWindow.qml" line="87"/>
<location filename="qml/window/MainWindow.qml" line="95"/>
<source>Quit</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="84"/>
<location filename="qml/window/MainWindow.qml" line="88"/>
<source>Are you sure you want to exit the program?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="85"/>
<location filename="qml/window/MainWindow.qml" line="89"/>
<source>Minimize</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="88"/>
<location filename="qml/window/MainWindow.qml" line="92"/>
<source>Friendly Reminder</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="88"/>
<location filename="qml/window/MainWindow.qml" line="92"/>
<source>FluentUI is hidden from the tray, click on the tray to activate the window again</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="92"/>
<location filename="qml/window/MainWindow.qml" line="336"/>
<location filename="qml/window/MainWindow.qml" line="96"/>
<location filename="qml/window/MainWindow.qml" line="340"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="103"/>
<location filename="qml/window/MainWindow.qml" line="107"/>
<source>Open in Separate Window</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="200"/>
<location filename="qml/window/MainWindow.qml" line="204"/>
<source>Click Time</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="210"/>
<location filename="qml/window/MainWindow.qml" line="214"/>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="301"/>
<location filename="qml/window/MainWindow.qml" line="305"/>
<source>Finish</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="302"/>
<location filename="qml/window/MainWindow.qml" line="306"/>
<source>Next</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="303"/>
<location filename="qml/window/MainWindow.qml" line="307"/>
<source>Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="307"/>
<location filename="qml/window/MainWindow.qml" line="311"/>
<source>Dark Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="311"/>
<source>Here you can switch to night mode.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="309"/>
<location filename="qml/window/MainWindow.qml" line="313"/>
<source>Hide Easter eggs</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="309"/>
<location filename="qml/window/MainWindow.qml" line="313"/>
<source>Try a few more clicks!!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="333"/>
<location filename="qml/window/MainWindow.qml" line="337"/>
<source>Upgrade Tips</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="334"/>
<location filename="qml/window/MainWindow.qml" line="338"/>
<source>FluentUI is currently up to date </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="334"/>
<location filename="qml/window/MainWindow.qml" line="338"/>
<source> -- The current app version</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="334"/>
<location filename="qml/window/MainWindow.qml" line="338"/>
<source>
Now go and download the new version
@ -652,17 +652,17 @@ Updated content:
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="337"/>
<location filename="qml/window/MainWindow.qml" line="341"/>
<source>OK</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="364"/>
<location filename="qml/window/MainWindow.qml" line="368"/>
<source>The current version is already the latest</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="371"/>
<location filename="qml/window/MainWindow.qml" line="375"/>
<source>The network is abnormal</source>
<translation type="unfinished"></translation>
</message>
@ -769,29 +769,6 @@ Updated content:
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_Awesome</name>
<message>
<location filename="qml/page/T_Awesome.qml" line="9"/>
<source>Awesome</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Awesome.qml" line="13"/>
<source>Please enter a keyword</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Awesome.qml" line="20"/>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Awesome.qml" line="55"/>
<source>You Copied </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_Badge</name>
<message>
@ -1107,46 +1084,6 @@ Updated content:
<source>Click to Select a Color - &gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="22"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="23"/>
<source>OK</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="24"/>
<source>Color Picker</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="25"/>
<source>Edit Color</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="26"/>
<source>Red</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="27"/>
<source>Green</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="28"/>
<source>Blue</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="29"/>
<source>Opacity</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_ComboBox</name>
@ -1361,26 +1298,49 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
<context>
<name>T_Home</name>
<message>
<location filename="qml/page/T_Home.qml" line="23"/>
<location filename="qml/page/T_Home.qml" line="19"/>
<source>FluentUI GitHub</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Home.qml" line="24"/>
<location filename="qml/page/T_Home.qml" line="20"/>
<source>The latest FluentUI controls and styles for your applications.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Home.qml" line="32"/>
<location filename="qml/page/T_Home.qml" line="28"/>
<source>FluentUI Initializr</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Home.qml" line="33"/>
<location filename="qml/page/T_Home.qml" line="29"/>
<source>FluentUI Initializr is a Tool that helps you create and customize Fluent UI projects with various options.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_Icons</name>
<message>
<location filename="qml/page/T_Icons.qml" line="9"/>
<source>Icons</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Icons.qml" line="13"/>
<source>Please enter a keyword</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Icons.qml" line="20"/>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Icons.qml" line="60"/>
<source>You Copied </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_Image</name>
<message>
@ -1621,6 +1581,14 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_OpenGL</name>
<message>
<location filename="qml/page/T_OpenGL.qml" line="11"/>
<source>OpenGL</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_Pagination</name>
<message>
@ -1957,26 +1925,6 @@ Some contents...</source>
<source>StatusLayout</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_StatusLayout.qml" line="63"/>
<source>Loading...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_StatusLayout.qml" line="64"/>
<source>Empty</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_StatusLayout.qml" line="65"/>
<source>The page went wrong...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_StatusLayout.qml" line="66"/>
<source>Reload</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_TabView</name>
@ -2177,6 +2125,11 @@ Some contents...</source>
<source>Open Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Theme.qml" line="123"/>
<source>Open Blur Window</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_TimePicker</name>
@ -2376,13 +2329,23 @@ Some contents...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TreeView.qml" line="44"/>
<source>Total %1 data, %2 data currently displayed</source>
<location filename="qml/page/T_TreeView.qml" line="183"/>
<source>Title</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TreeView.qml" line="48"/>
<source>A total of %1 data items are selected</source>
<location filename="qml/page/T_TreeView.qml" line="187"/>
<source>Name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TreeView.qml" line="191"/>
<source>Avatar</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TreeView.qml" line="195"/>
<source>Address</source>
<translation type="unfinished"></translation>
</message>
</context>

View File

@ -87,22 +87,22 @@
<context>
<name>InitializrHelper</name>
<message>
<location filename="src/helper/InitializrHelper.cpp" line="77"/>
<location filename="src/helper/InitializrHelper.cpp" line="69"/>
<source>The name cannot be empty</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/helper/InitializrHelper.cpp" line="81"/>
<location filename="src/helper/InitializrHelper.cpp" line="73"/>
<source>The creation path cannot be empty</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/helper/InitializrHelper.cpp" line="86"/>
<location filename="src/helper/InitializrHelper.cpp" line="78"/>
<source>The path does not exist</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/helper/InitializrHelper.cpp" line="92"/>
<location filename="src/helper/InitializrHelper.cpp" line="84"/>
<source>%1 folder already exists</source>
<translation type="unfinished">%1 </translation>
</message>
@ -425,7 +425,7 @@
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="367"/>
<source>Awesome</source>
<source>Icons</source>
<translation type="unfinished"></translation>
</message>
<message>
@ -475,43 +475,47 @@
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="430"/>
<source>OpenGL</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="436"/>
<source>QRCode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="436"/>
<location filename="qml/global/ItemsOriginal.qml" line="442"/>
<source>Tour</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="442"/>
<location filename="qml/global/ItemsOriginal.qml" line="448"/>
<source>Timeline</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="448"/>
<location filename="qml/global/ItemsOriginal.qml" line="454"/>
<source>Captcha</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="454"/>
<location filename="qml/global/ItemsOriginal.qml" line="460"/>
<source>Network</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="461"/>
<location filename="qml/global/ItemsOriginal.qml" line="467"/>
<source>Remote Loader</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="475"/>
<location filename="qml/global/ItemsOriginal.qml" line="481"/>
<source>Hot Loader</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="481"/>
<source>3D</source>
<translation type="unfinished">3D</translation>
<translation type="obsolete">3D</translation>
</message>
<message>
<location filename="qml/global/ItemsOriginal.qml" line="487"/>
@ -546,104 +550,104 @@
<context>
<name>MainWindow</name>
<message>
<location filename="qml/window/MainWindow.qml" line="307"/>
<location filename="qml/window/MainWindow.qml" line="311"/>
<source>Dark Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="83"/>
<location filename="qml/window/MainWindow.qml" line="91"/>
<location filename="qml/window/MainWindow.qml" line="87"/>
<location filename="qml/window/MainWindow.qml" line="95"/>
<source>Quit</source>
<translation type="unfinished">退</translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="84"/>
<location filename="qml/window/MainWindow.qml" line="88"/>
<source>Are you sure you want to exit the program?</source>
<translation type="unfinished">退</translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="85"/>
<location filename="qml/window/MainWindow.qml" line="89"/>
<source>Minimize</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="88"/>
<location filename="qml/window/MainWindow.qml" line="92"/>
<source>Friendly Reminder</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="88"/>
<location filename="qml/window/MainWindow.qml" line="92"/>
<source>FluentUI is hidden from the tray, click on the tray to activate the window again</source>
<translation type="unfinished">FluentUI </translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="92"/>
<location filename="qml/window/MainWindow.qml" line="336"/>
<location filename="qml/window/MainWindow.qml" line="96"/>
<location filename="qml/window/MainWindow.qml" line="340"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="103"/>
<location filename="qml/window/MainWindow.qml" line="107"/>
<source>Open in Separate Window</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="200"/>
<location filename="qml/window/MainWindow.qml" line="204"/>
<source>Click Time</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="210"/>
<location filename="qml/window/MainWindow.qml" line="214"/>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="301"/>
<location filename="qml/window/MainWindow.qml" line="305"/>
<source>Finish</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="302"/>
<location filename="qml/window/MainWindow.qml" line="306"/>
<source>Next</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="303"/>
<location filename="qml/window/MainWindow.qml" line="307"/>
<source>Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="307"/>
<location filename="qml/window/MainWindow.qml" line="311"/>
<source>Here you can switch to night mode.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="309"/>
<location filename="qml/window/MainWindow.qml" line="313"/>
<source>Hide Easter eggs</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="309"/>
<location filename="qml/window/MainWindow.qml" line="313"/>
<source>Try a few more clicks!!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="333"/>
<location filename="qml/window/MainWindow.qml" line="337"/>
<source>Upgrade Tips</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="334"/>
<location filename="qml/window/MainWindow.qml" line="338"/>
<source>FluentUI is currently up to date </source>
<translation type="unfinished">FluentUI </translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="334"/>
<location filename="qml/window/MainWindow.qml" line="338"/>
<source> -- The current app version</source>
<translation type="unfinished"> -- </translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="334"/>
<location filename="qml/window/MainWindow.qml" line="338"/>
<source>
Now go and download the new version
@ -656,17 +660,17 @@ Updated content:
</translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="337"/>
<location filename="qml/window/MainWindow.qml" line="341"/>
<source>OK</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="364"/>
<location filename="qml/window/MainWindow.qml" line="368"/>
<source>The current version is already the latest</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="371"/>
<location filename="qml/window/MainWindow.qml" line="375"/>
<source>The network is abnormal</source>
<translation type="unfinished"></translation>
</message>
@ -776,24 +780,20 @@ Updated content:
<context>
<name>T_Awesome</name>
<message>
<location filename="qml/page/T_Awesome.qml" line="9"/>
<source>Awesome</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
<message>
<location filename="qml/page/T_Awesome.qml" line="13"/>
<source>Please enter a keyword</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
<message>
<location filename="qml/page/T_Awesome.qml" line="20"/>
<source>Search</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
<message>
<location filename="qml/page/T_Awesome.qml" line="55"/>
<source>You Copied </source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
</context>
<context>
@ -1112,44 +1112,36 @@ Updated content:
<translation type="unfinished"> - &gt;</translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="22"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="23"/>
<source>OK</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="24"/>
<source>Color Picker</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="25"/>
<source>Edit Color</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="26"/>
<source>Red</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="27"/>
<source>Green</source>
<translation type="unfinished">绿</translation>
<translation type="obsolete">绿</translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="28"/>
<source>Blue</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
<message>
<location filename="qml/page/T_ColorPicker.qml" line="29"/>
<source>Opacity</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
</context>
<context>
@ -1392,26 +1384,49 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
<context>
<name>T_Home</name>
<message>
<location filename="qml/page/T_Home.qml" line="23"/>
<location filename="qml/page/T_Home.qml" line="19"/>
<source>FluentUI GitHub</source>
<translation type="unfinished">FluentUI GitHub</translation>
</message>
<message>
<location filename="qml/page/T_Home.qml" line="24"/>
<location filename="qml/page/T_Home.qml" line="20"/>
<source>The latest FluentUI controls and styles for your applications.</source>
<translation type="unfinished"> FluentUI </translation>
</message>
<message>
<location filename="qml/page/T_Home.qml" line="32"/>
<location filename="qml/page/T_Home.qml" line="28"/>
<source>FluentUI Initializr</source>
<translation type="unfinished">FluentUI脚手架</translation>
</message>
<message>
<location filename="qml/page/T_Home.qml" line="33"/>
<location filename="qml/page/T_Home.qml" line="29"/>
<source>FluentUI Initializr is a Tool that helps you create and customize Fluent UI projects with various options.</source>
<translation type="unfinished">FluentUI Fluent UI </translation>
</message>
</context>
<context>
<name>T_Icons</name>
<message>
<location filename="qml/page/T_Icons.qml" line="9"/>
<source>Icons</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Icons.qml" line="13"/>
<source>Please enter a keyword</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Icons.qml" line="20"/>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Icons.qml" line="60"/>
<source>You Copied </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_Image</name>
<message>
@ -1660,6 +1675,14 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_OpenGL</name>
<message>
<location filename="qml/page/T_OpenGL.qml" line="11"/>
<source>OpenGL</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_Pagination</name>
<message>
@ -2029,24 +2052,20 @@ Some contents...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_StatusLayout.qml" line="63"/>
<source>Loading...</source>
<translation type="unfinished">...</translation>
<translation type="obsolete">...</translation>
</message>
<message>
<location filename="qml/page/T_StatusLayout.qml" line="64"/>
<source>Empty</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
<message>
<location filename="qml/page/T_StatusLayout.qml" line="65"/>
<source>The page went wrong...</source>
<translation type="unfinished">...</translation>
<translation type="obsolete">...</translation>
</message>
<message>
<location filename="qml/page/T_StatusLayout.qml" line="66"/>
<source>Reload</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
</context>
<context>
@ -2248,6 +2267,11 @@ Some contents...</source>
<source>Open Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Theme.qml" line="123"/>
<source>Open Blur Window</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_TimePicker</name>
@ -2459,14 +2483,32 @@ Some contents...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TreeView.qml" line="44"/>
<source>Total %1 data, %2 data currently displayed</source>
<translation type="unfinished">%1%2</translation>
<translation type="obsolete">%1%2</translation>
</message>
<message>
<location filename="qml/page/T_TreeView.qml" line="48"/>
<source>A total of %1 data items are selected</source>
<translation type="unfinished">%1</translation>
<translation type="obsolete">%1</translation>
</message>
<message>
<location filename="qml/page/T_TreeView.qml" line="183"/>
<source>Title</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TreeView.qml" line="195"/>
<source>Address</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TreeView.qml" line="191"/>
<source>Avatar</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TreeView.qml" line="187"/>
<source>Name</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>

View File

@ -364,9 +364,9 @@ FluObject{
onTap: { navigationView.push(url) }
}
FluPaneItem{
title: qsTr("Awesome")
title: qsTr("Icons")
menuDelegate: paneItemMenu
url: "qrc:/example/qml/page/T_Awesome.qml"
url: "qrc:/example/qml/page/T_Icons.qml"
onTap: { navigationView.push(url) }
}
}
@ -426,6 +426,12 @@ FluObject{
FluPaneItemExpander{
title: qsTr("Other")
icon: FluentIcons.Shop
FluPaneItem{
title: qsTr("OpenGL")
menuDelegate: paneItemMenu
url: "qrc:/example/qml/page/T_OpenGL.qml"
onTap: { navigationView.push(url) }
}
FluPaneItem{
title: qsTr("QRCode")
menuDelegate: paneItemMenu
@ -477,12 +483,6 @@ FluObject{
FluRouter.navigate("/hotload")
}
}
FluPaneItem{
title: qsTr("3D")
menuDelegate: paneItemMenu
url: "qrc:/example/qml/page/T_3D.qml"
onTap: { navigationView.push(url) }
}
FluPaneItem{
title: qsTr("Test Crash")
onTapListener: function(){

View File

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

View File

@ -18,16 +18,7 @@ FluScrollablePage{
text: qsTr("Click to Select a Color - >")
Layout.alignment: Qt.AlignVCenter
}
FluColorPicker{
cancelText: qsTr("Cancel")
okText: qsTr("OK")
titleText: qsTr("Color Picker")
editText: qsTr("Edit Color")
redText: qsTr("Red")
greenText: qsTr("Green")
blueText: qsTr("Blue")
opacityText: qsTr("Opacity")
}
FluColorPicker{}
}
}
CodeExpander{

View File

@ -12,10 +12,6 @@ FluScrollablePage{
animationEnabled: false
header: Item{}
FluentInitializrWindow{
id:fluent_Initializr
}
ListModel{
id: model_header
ListElement{

View File

@ -6,7 +6,7 @@ import FluentUI 1.0
FluContentPage {
title: qsTr("Awesome")
title: qsTr("Icons")
FluTextBox{
id: text_box
@ -24,16 +24,16 @@ FluContentPage {
leftMargin: 14
}
onClicked: {
grid_view.model = FluTheme.awesomeList(text_box.text)
grid_view.model = FluApp.iconDatas(text_box.text)
}
}
GridView{
id: grid_view
cellWidth: 80
cellHeight: 80
cellWidth: 110
cellHeight: 110
clip: true
boundsBehavior: GridView.StopAtBounds
model:FluTheme.awesomeList()
model: FluApp.iconDatas()
ScrollBar.vertical: FluScrollBar {}
anchors{
topMargin: 10
@ -43,28 +43,30 @@ FluContentPage {
bottom: parent.bottom
}
delegate: Item {
width: 68
height: 80
width: 100
height: 100
FluIconButton{
id:item_icon
iconSource: modelData.icon
anchors.horizontalCenter: parent.horizontalCenter
iconSize: 30
padding: 0
verticalPadding: 0
horizontalPadding: 0
bottomPadding: 30
anchors.fill: parent
onClicked: {
var text ="FluentIcons."+modelData.name;
FluTools.clipText(text)
showSuccess(qsTr("You Copied ")+text)
}
}
FluText{
id:item_name
font.pixelSize: 10
font.family: FluTextStyle.family
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: item_icon.bottom
width: parent.width
horizontalAlignment: Qt.AlignHCenter
wrapMode: Text.WrapAnywhere
text: modelData.name
horizontalAlignment: Text.AlignHCenter
anchors.top: parent.top
anchors.topMargin: 60
}
}
}
}

View File

@ -0,0 +1,26 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import example 1.0
import "../component"
FluContentPage{
title: qsTr("OpenGL")
FluFrame{
anchors.fill: parent
OpenGLItem{
anchors.fill: parent
SequentialAnimation on t {
NumberAnimation { to: 1; duration: 2500; easing.type: Easing.InQuad }
NumberAnimation { to: 0; duration: 2500; easing.type: Easing.OutQuad }
loops: Animation.Infinite
running: true
}
}
}
}

View File

@ -60,12 +60,8 @@ FluScrollablePage{
FluStatusLayout{
id:status_view
anchors.fill: parent
loadingText: qsTr("Loading...")
emptyText: qsTr("Empty")
errorText: qsTr("The page went wrong...")
errorButtonText: qsTr("Reload")
onErrorClicked:{
showError("Click Reload")
status_view.statusMode = FluStatusLayoutType.Loading
}
Rectangle {
anchors.fill: parent

View File

@ -13,7 +13,7 @@ FluScrollablePage{
FluFrame{
Layout.fillWidth: true
Layout.preferredHeight: 340
Layout.preferredHeight: 408
padding: 10
ColumnLayout{
@ -119,6 +119,17 @@ FluScrollablePage{
FluTheme.animationEnabled = !FluTheme.animationEnabled
}
}
FluText{
text: qsTr("Open Blur Window")
Layout.topMargin: 20
}
FluToggleSwitch{
Layout.topMargin: 5
checked: FluTheme.blurBehindWindowEnabled
onClicked: {
FluTheme.blurBehindWindowEnabled = !FluTheme.blurBehindWindowEnabled
}
}
}
}
CodeExpander{

View File

@ -9,14 +9,33 @@ FluContentPage {
title: qsTr("TreeView")
function treeData(){
const dig = (path = '0', level = 4) => {
const names = ["孙悟空", "猪八戒", "沙和尚", "唐僧","白骨夫人","金角大王","熊山君","黄风怪","银角大王"]
function getRandomName(){
var randomIndex = Math.floor(Math.random() * names.length)
return names[randomIndex]
}
const addresses = ["傲来国界花果山水帘洞","傲来国界坎源山脏水洞","大唐国界黑风山黑风洞","大唐国界黄风岭黄风洞","大唐国界骷髅山白骨洞","宝象国界碗子山波月洞","宝象国界平顶山莲花洞","宝象国界压龙山压龙洞","乌鸡国界号山枯松涧火云洞","乌鸡国界衡阳峪黑水河河神府"]
function getRandomAddresses(){
var randomIndex = Math.floor(Math.random() * addresses.length)
return addresses[randomIndex]
}
const avatars = ["qrc:/example/res/svg/avatar_1.svg", "qrc:/example/res/svg/avatar_2.svg", "qrc:/example/res/svg/avatar_3.svg", "qrc:/example/res/svg/avatar_4.svg","qrc:/example/res/svg/avatar_5.svg","qrc:/example/res/svg/avatar_6.svg","qrc:/example/res/svg/avatar_7.svg","qrc:/example/res/svg/avatar_8.svg","qrc:/example/res/svg/avatar_9.svg","qrc:/example/res/svg/avatar_10.svg","qrc:/example/res/svg/avatar_11.svg","qrc:/example/res/svg/avatar_12.svg"]
function getRandomAvatar(){
var randomIndex = Math.floor(Math.random() * avatars.length);
return avatars[randomIndex];
}
const dig = (path = '0', level = 5) => {
const list = [];
for (let i = 0; i < 6; i += 1) {
for (let i = 0; i < 4; i += 1) {
const key = `${path}-${i}`;
const treeNode = {
title: key,
key,
_key: key,
name: getRandomName(),
avatar:tree_view.customItem(com_avatar,{avatar:getRandomAvatar()}),
address: getRandomAddresses()
};
if (level > 0) {
treeNode.children = dig(key, level - 1);
@ -28,26 +47,46 @@ FluContentPage {
return dig();
}
Column{
id: layout_column
spacing: 12
width: 300
Component{
id:com_avatar
Item{
FluClip{
anchors.centerIn: parent
width: height
height: parent.height/3*2
radius: [height/2,height/2,height/2,height/2]
Image{
anchors.fill: parent
source: {
if(options && options.avatar){
return options.avatar
}
return ""
}
sourceSize: Qt.size(80,80)
}
}
}
}
FluFrame{
id:layout_controls
anchors{
left: parent.left
right: parent.right
top: parent.top
topMargin: 10
}
height: 80
clip: true
Row{
spacing: 12
anchors{
left: parent.left
leftMargin: 10
bottom:parent.bottom
bottomMargin: 20
verticalCenter: parent.verticalCenter
}
FluText{
text: qsTr("Total %1 data, %2 data currently displayed").arg(tree_view.count()).arg(tree_view.visibleCount())
}
FluText{
text: qsTr("A total of %1 data items are selected").arg(tree_view.selectionModel().length)
}
Column{
anchors.verticalCenter: parent.verticalCenter
RowLayout{
spacing: 10
FluText{
@ -56,8 +95,8 @@ FluContentPage {
}
FluSlider{
id: slider_cell_height
value: 30
from: 30
value: 38
from: 38
to:100
}
}
@ -69,26 +108,29 @@ FluContentPage {
}
FluSlider{
id: slider_depth_padding
value: 30
from: 30
value: 15
from: 15
to:100
}
}
}
Column{
spacing: 8
anchors.verticalCenter: parent.verticalCenter
FluToggleSwitch{
id: switch_showline
text:"showLine"
checked: false
}
FluToggleSwitch{
id: switch_draggable
text:"draggable"
checked: false
}
FluToggleSwitch{
id: switch_checkable
text:"checkable"
checked: false
}
}
Column{
spacing: 8
anchors.verticalCenter: parent.verticalCenter
FluButton{
text: "all expand"
onClicked: {
@ -102,29 +144,62 @@ FluContentPage {
}
}
}
FluFrame{
anchors{
left: layout_column.right
top: parent.top
bottom: parent.bottom
right: parent.right
rightMargin: 5
topMargin: 5
bottomMargin: 5
FluButton{
text: "print selection model"
onClicked: {
var printData = []
var data = tree_view.selectionModel();
console.debug(data.length)
for(var i = 0; i <= data.length-1 ; i++){
const newObj = Object.assign({}, data[i].data);
delete newObj["__parent"];
delete newObj["children"];
printData.push(newObj)
}
FluShadow{}
console.debug(JSON.stringify(printData))
}
}
}
}
FluTreeView{
id:tree_view
anchors.fill: parent
anchors{
left: parent.left
top: layout_controls.bottom
topMargin: 10
bottom: parent.bottom
right: parent.right
}
cellHeight: slider_cell_height.value
draggable:switch_draggable.checked
showLine: switch_showline.checked
checkable:switch_checkable.checked
depthPadding: slider_depth_padding.value
onCurrentChanged: {
showInfo(current.data.title)
}
columnSource:[
{
title: qsTr("Title"),
dataIndex: 'title',
width: 300
},{
title: qsTr("Name"),
dataIndex: 'name',
width: 100
},{
title: qsTr("Avatar"),
dataIndex: 'avatar',
width: 100
},{
title: qsTr("Address"),
dataIndex: 'address',
width: 200
},
]
Component.onCompleted: {
var data = treeData()
dataSource = data
}
}
}
}

View File

@ -20,7 +20,7 @@ FluWindowDialog {
showError(message)
}
function onSuccess(path){
FluTools.showFileInFolder(path+"/CMakeLists.txt")
FluTools.showFileInFolder(path)
window.close()
}
}

View File

@ -15,7 +15,7 @@ FluWindow {
title: "FluentUI"
width: 1000
height: 680
minimumWidth: 520
minimumWidth: 1000
minimumHeight: 200
launchMode: FluWindowType.SingleTask
fitsAppBarWindows: true
@ -28,6 +28,10 @@ FluWindow {
z:7
}
FluentInitializrWindow{
id:fluent_Initializr
}
FluEvent{
name: "checkUpdate"
onTriggered: {

View File

@ -1,17 +1,15 @@
#include "AppInfo.h"
#include <QQmlContext>
#include <QDebug>
#include <QGuiApplication>
#include "Version.h"
AppInfo::AppInfo(QObject *parent)
: QObject{parent}
{
: QObject{parent} {
version(APPLICATION_VERSION);
}
void AppInfo::testCrash(){
[[maybe_unused]] void AppInfo::testCrash() {
auto *crash = reinterpret_cast<volatile int *>(0);
*crash = 0;
}

View File

@ -1,20 +1,18 @@
#ifndef APPINFO_H
#define APPINFO_H
#pragma once
#include <QObject>
#include <QQmlApplicationEngine>
#include "stdafx.h"
#include "singleton.h"
class AppInfo : public QObject
{
class AppInfo : public QObject {
Q_OBJECT
Q_PROPERTY_AUTO(QString, version)
private:
explicit AppInfo(QObject *parent = nullptr);
public:
SINGLETON(AppInfo)
Q_INVOKABLE void testCrash();
};
#endif // APPINFO_H
[[maybe_unused]] Q_INVOKABLE void testCrash();
};

View File

@ -1,5 +1,4 @@
#ifndef APP_DUMP_H
#define APP_DUMP_H
#pragma once
#include <Windows.h>
#include <DbgHelp.h>
@ -12,22 +11,22 @@
#pragma comment(lib, "Dbghelp.lib")
static void miniDumpWriteDump(HANDLE hProcess,DWORD ProcessId,HANDLE hFile,MINIDUMP_TYPE DumpType,CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam){
typedef HRESULT (WINAPI* MiniDumpWriteDumpPtr)(HANDLE hProcess,DWORD ProcessId,HANDLE hFile,MINIDUMP_TYPE DumpType,CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
static void
miniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam) {
typedef HRESULT (WINAPI *MiniDumpWriteDumpPtr)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
HMODULE module = LoadLibraryW(L"Dbghelp.dll");
if (module)
{
if (module) {
MiniDumpWriteDumpPtr mini_dump_write_dump;
mini_dump_write_dump = reinterpret_cast<MiniDumpWriteDumpPtr>(GetProcAddress(module, "MiniDumpWriteDump"));
if (mini_dump_write_dump)
{
mini_dump_write_dump(hProcess,ProcessId,hFile,DumpType,ExceptionParam,UserStreamParam,CallbackParam);
if (mini_dump_write_dump) {
mini_dump_write_dump(hProcess, ProcessId, hFile, static_cast<MINIDUMP_TYPE>(80), ExceptionParam, nullptr, CallbackParam);
}
}
}
BOOL CALLBACK MyMiniDumpCallback(PVOID, const PMINIDUMP_CALLBACK_INPUT input, PMINIDUMP_CALLBACK_OUTPUT output) {
if (input == NULL || output == NULL)
if (input == nullptr || output == nullptr)
return FALSE;
BOOL ret = FALSE;
@ -43,7 +42,8 @@ BOOL CALLBACK MyMiniDumpCallback(PVOID, const PMINIDUMP_CALLBACK_INPUT input, PM
output->ModuleWriteFlags &= ~ModuleWriteModule;
}
ret = TRUE;
} break;
}
break;
default:
break;
}
@ -51,16 +51,15 @@ BOOL CALLBACK MyMiniDumpCallback(PVOID, const PMINIDUMP_CALLBACK_INPUT input, PM
}
void WriteDump(EXCEPTION_POINTERS *exp, const std::wstring &path) {
HANDLE h = ::CreateFileW(path.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE h = ::CreateFileW(path.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
MINIDUMP_EXCEPTION_INFORMATION info;
info.ThreadId = ::GetCurrentThreadId();
info.ExceptionPointers = exp;
info.ClientPointers = FALSE;
MINIDUMP_CALLBACK_INFORMATION mci;
mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE) MyMiniDumpCallback;
mci.CallbackParam = 0;
MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory);
miniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), h, mdt, &info, NULL, &mci);
mci.CallbackParam = nullptr;
miniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), h, &info, &mci);
::CloseHandle(h);
}
@ -75,8 +74,6 @@ LONG WINAPI MyUnhandledExceptionFilter(EXCEPTION_POINTERS* exp) {
WriteDump(exp, dumpFilePath.toStdWString());
QStringList arguments;
arguments << "-crashed=" + dumpFilePath;
QProcess::startDetached(qApp->applicationFilePath(), arguments);
QProcess::startDetached(QGuiApplication::applicationFilePath(), arguments);
return EXCEPTION_EXECUTE_HANDLER;
}
#endif // APP_DUMP_H

View File

@ -3,12 +3,13 @@
#include <QQuickItemGrabResult>
#include <QPainterPath>
CircularReveal::CircularReveal(QQuickItem* parent) : QQuickPaintedItem(parent)
{
CircularReveal::CircularReveal(QQuickItem *parent) : QQuickPaintedItem(parent) {
_target = nullptr;
_radius = 0;
_anim = new QPropertyAnimation(this, "radius", this);
setVisible(false);
_anim->setDuration(333);
_anim->setEasingCurve(QEasingCurve::OutCubic);
setVisible(false);
connect(_anim, &QPropertyAnimation::finished, this, [=]() {
update();
setVisible(false);
@ -19,8 +20,7 @@ CircularReveal::CircularReveal(QQuickItem* parent) : QQuickPaintedItem(parent)
});
}
void CircularReveal::paint(QPainter* painter)
{
void CircularReveal::paint(QPainter *painter) {
painter->save();
painter->drawImage(QRect(0, 0, static_cast<int>(width()), static_cast<int>(height())), _source);
QPainterPath path;
@ -31,7 +31,7 @@ void CircularReveal::paint(QPainter* painter)
painter->restore();
}
void CircularReveal::start(int w,int h,const QPoint& center,int radius){
[[maybe_unused]] void CircularReveal::start(int w, int h, const QPoint &center, int radius) {
_anim->setStartValue(0);
_anim->setEndValue(radius);
_center = center;

View File

@ -1,5 +1,4 @@
#ifndef CIRCULARREVEAL_H
#define CIRCULARREVEAL_H
#pragma once
#include <QQuickItem>
#include <QQuickPaintedItem>
@ -7,23 +6,26 @@
#include <QPropertyAnimation>
#include "src/stdafx.h"
class CircularReveal : public QQuickPaintedItem
{
class CircularReveal : public QQuickPaintedItem {
Q_OBJECT
Q_PROPERTY_AUTO(QQuickItem*,target)
Q_PROPERTY_AUTO_P(QQuickItem*, target)
Q_PROPERTY_AUTO(int, radius)
public:
CircularReveal(QQuickItem* parent = nullptr);
explicit CircularReveal(QQuickItem *parent = nullptr);
void paint(QPainter *painter) override;
Q_INVOKABLE void start(int w,int h,const QPoint& center,int radius);
Q_INVOKABLE [[maybe_unused]] void start(int w, int h, const QPoint &center, int radius);
Q_SIGNAL void imageChanged();
Q_SIGNAL void animationFinished();
Q_SLOT void handleGrabResult();
private:
QPropertyAnimation *_anim = nullptr;
QImage _source;
QPoint _center;
QSharedPointer<QQuickItemGrabResult> _grabResult;
};
#endif // CIRCULARREVEAL_H

View File

@ -1,8 +1,6 @@
#include "FileWatcher.h"
FileWatcher::FileWatcher(QObject *parent)
: QObject{parent}
{
FileWatcher::FileWatcher(QObject *parent) : QObject{parent} {
connect(&_watcher, &QFileSystemWatcher::fileChanged, this, [=](const QString &path) {
Q_EMIT fileChanged();
clean();
@ -18,7 +16,8 @@ FileWatcher::FileWatcher(QObject *parent)
}
void FileWatcher::clean() {
foreach (const QString &item, _watcher.files()) {
for (int i = 0; i <= _watcher.files().size() - 1; ++i) {
auto item = _watcher.files().at(i);
_watcher.removePath(item);
}
}

View File

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

View File

@ -3,9 +3,9 @@
#include <QTimer>
#include <QQuickWindow>
FpsItem::FpsItem()
{
QTimer *timer = new QTimer(this);
FpsItem::FpsItem() {
_fps = 0;
auto *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, [this] {
fps(_frameCount);
_frameCount = 0;

View File

@ -1,11 +1,9 @@
#ifndef FPSITEM_H
#define FPSITEM_H
#pragma once
#include <QQuickItem>
#include "src/stdafx.h"
class FpsItem : public QQuickItem
{
class FpsItem : public QQuickItem {
Q_OBJECT
Q_PROPERTY_AUTO(int, fps)
public:
@ -15,5 +13,3 @@ private:
int _frameCount = 0;
};
#endif // FPSITEM_H

View File

@ -0,0 +1,93 @@
#include "OpenGLItem.h"
#include <QOpenGLFramebufferObjectFormat>
#include <QOpenGLShaderProgram>
class FBORenderer : public QQuickFramebufferObject::Renderer, protected QOpenGLFunctions {
public:
explicit FBORenderer(const OpenGLItem *item);
void render() override;
QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override;
QOpenGLShaderProgram program;
const OpenGLItem *item = nullptr;
};
FBORenderer::FBORenderer(const OpenGLItem *item) {
this->item = item;
initializeOpenGLFunctions();
program.addCacheableShaderFromSourceCode(QOpenGLShader::Vertex,
"attribute highp vec4 vertices;"
"varying highp vec2 coords;"
"void main() {"
" gl_Position = vertices;"
" coords = vertices.xy;"
"}");
program.addCacheableShaderFromSourceCode(QOpenGLShader::Fragment,
"uniform lowp float t;"
"varying highp vec2 coords;"
"void main() {"
" lowp float i = 1. - (pow(abs(coords.x), 4.) + pow(abs(coords.y), 4.));"
" i = smoothstep(t - 0.8, t + 0.8, i);"
" i = floor(i * 20.) / 20.;"
" gl_FragColor = vec4(coords * .5 + .5, i, i);"
"}");
program.bindAttributeLocation("vertices", 0);
program.link();
}
QOpenGLFramebufferObject *FBORenderer::createFramebufferObject(const QSize &size) {
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setSamples(4);
return new QOpenGLFramebufferObject(size, format);
}
void FBORenderer::render() {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
program.bind();
program.enableAttributeArray(0);
float values[] = {
-1, -1,
1, -1,
-1, 1,
1, 1
};
glBindBuffer(GL_ARRAY_BUFFER, 0);
program.setAttributeArray(0, GL_FLOAT, values, 2);
program.setUniformValue("t", (float) item->t());
glViewport(0, 0, qRound(item->width()), qRound(item->height()));
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
program.disableAttributeArray(0);
program.release();
}
OpenGLItem::OpenGLItem(QQuickItem *parent) : QQuickFramebufferObject(parent) {
setMirrorVertically(true);
startTimer(1);
}
void OpenGLItem::timerEvent(QTimerEvent *) {
update();
}
void OpenGLItem::setT(qreal t) {
if (t == m_t)
return;
m_t = t;
emit tChanged();
}
QQuickFramebufferObject::Renderer *OpenGLItem::createRenderer() const {
return new FBORenderer(this);
}

View File

@ -0,0 +1,29 @@
#pragma once
#include <QtQuick/QQuickItem>
#include <QOpenGLFunctions>
#include <QQuickFramebufferObject>
class FBORenderer;
class OpenGLItem : public QQuickFramebufferObject, protected QOpenGLFunctions {
Q_OBJECT
Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged)
public:
explicit OpenGLItem(QQuickItem *parent = nullptr);
[[nodiscard]] QQuickFramebufferObject::Renderer *createRenderer() const override;
void timerEvent(QTimerEvent *) override;
[[nodiscard]] qreal t() const { return m_t; }
void setT(qreal t);
signals:
void tChanged();
private:
qreal m_t{};
};

View File

@ -3,39 +3,31 @@
#include <QDir>
#include <QGuiApplication>
InitializrHelper::InitializrHelper(QObject *parent) : QObject(parent)
{
[[maybe_unused]] InitializrHelper::InitializrHelper(QObject *parent) : QObject(parent) {
}
InitializrHelper::~InitializrHelper() = default;
bool InitializrHelper::copyDir(const QDir &fromDir, const QDir &toDir, bool coverIfFileExists) {
QDir _formDir = fromDir;
const QDir &_formDir = fromDir;
QDir _toDir = toDir;
if(!_toDir.exists())
{
if (!_toDir.exists()) {
if (!_toDir.mkdir(toDir.absolutePath()))
return false;
}
QFileInfoList fileInfoList = _formDir.entryInfoList();
foreach(QFileInfo fileInfo, fileInfoList)
{
foreach(QFileInfo fileInfo, fileInfoList) {
if (fileInfo.fileName() == "." || fileInfo.fileName() == "..")
continue;
if(fileInfo.isDir())
{
if (fileInfo.isDir()) {
if (!copyDir(fileInfo.filePath(), _toDir.filePath(fileInfo.fileName()), true))
return false;
}
else
{
if(coverIfFileExists && _toDir.exists(fileInfo.fileName()))
{
} else {
if (coverIfFileExists && _toDir.exists(fileInfo.fileName())) {
_toDir.remove(fileInfo.fileName());
}
if(!QFile::copy(fileInfo.filePath(), _toDir.filePath(fileInfo.fileName())))
{
if (!QFile::copy(fileInfo.filePath(), _toDir.filePath(fileInfo.fileName()))) {
return false;
}
}
@ -72,7 +64,7 @@ void InitializrHelper::copyFile(const QString& source,const QString& dest){
QFile::setPermissions(dest, QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther);
}
void InitializrHelper::generate(const QString& name,const QString& path){
[[maybe_unused]] void InitializrHelper::generate(const QString &name, const QString &path) {
if (name.isEmpty()) {
error(tr("The name cannot be empty"));
return;
@ -105,5 +97,5 @@ void InitializrHelper::generate(const QString& name,const QString& path){
copyFile(":/example/res/template/src/qml.qrc.in", projectDir.filePath("src/qml.qrc"));
copyFile(":/example/res/template/src/logo.ico.in", projectDir.filePath("src/logo.ico"));
copyFile(":/example/res/template/src/README.md.in", projectDir.filePath("src/README.md"));
return this->success(projectPath);
return this->success(projectPath+"/CMakeLists.txt");
}

View File

@ -1,26 +1,30 @@
#ifndef INITIALIZRHELPER_H
#define INITIALIZRHELPER_H
#pragma once
#include <QObject>
#include <QtQml/qqml.h>
#include <QDir>
#include "src/singleton.h"
class InitializrHelper : public QObject
{
class InitializrHelper : public QObject {
Q_OBJECT
private:
explicit InitializrHelper(QObject* parent = nullptr);
[[maybe_unused]] explicit InitializrHelper(QObject *parent = nullptr);
bool copyDir(const QDir &fromDir, const QDir &toDir, bool coverIfFileExists = true);
void copyFile(const QString& source,const QString& dest);
static void copyFile(const QString &source, const QString &dest);
template<typename...Args>
void templateToFile(const QString &source, const QString &dest, Args &&...args);
public:
SINGLETON(InitializrHelper)
~InitializrHelper() override;
Q_INVOKABLE void generate(const QString& name,const QString& path);
Q_INVOKABLE [[maybe_unused]] void generate(const QString &name, const QString &path);
Q_SIGNAL void error(const QString &message);
Q_SIGNAL void success(const QString &path);
};
#endif // INITIALIZRHELPER_H

View File

@ -11,8 +11,11 @@
#include <QSettings>
#include <QRegularExpression>
#include "Version.h"
#ifdef WIN32
#include <process.h>
#else
#include <unistd.h>
#endif
@ -42,8 +45,7 @@ std::map<QtMsgType, int> logLevelMap = {
{QtDebugMsg, 4}
};
QString Log::prettyProductInfoWrapper()
{
QString Log::prettyProductInfoWrapper() {
auto productName = QSysInfo::prettyProductName();
#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
#if defined(Q_OS_MACOS)
@ -70,20 +72,17 @@ QString Log::prettyProductInfoWrapper()
#endif
#endif
#if defined(Q_OS_WIN)
QSettings regKey {QString::fromUtf8("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), QSettings::NativeFormat};
QSettings regKey{QString::fromUtf8(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion)"), QSettings::NativeFormat};
if (regKey.contains(QString::fromUtf8("CurrentBuildNumber"))) {
auto buildNumber = regKey.value(QString::fromUtf8("CurrentBuildNumber")).toInt();
if (buildNumber > 0) {
if (buildNumber < 9200) {
productName = QString::fromUtf8("Windows 7 build %1").arg(buildNumber);
}
else if (buildNumber < 10240) {
} else if (buildNumber < 10240) {
productName = QString::fromUtf8("Windows 8 build %1").arg(buildNumber);
}
else if (buildNumber < 22000) {
} else if (buildNumber < 22000) {
productName = QString::fromUtf8("Windows 10 build %1").arg(buildNumber);
}
else {
} else {
productName = QString::fromUtf8("Windows 11 build %1").arg(buildNumber);
}
}
@ -92,8 +91,7 @@ QString Log::prettyProductInfoWrapper()
return productName;
}
static inline void messageHandler(const QtMsgType type, const QMessageLogContext &context, const QString &message)
{
static inline void messageHandler(const QtMsgType type, const QMessageLogContext &context, const QString &message) {
if (message == "Could not get the INetworkConnection instance for the adapter GUID.") {
return;
}
@ -168,8 +166,7 @@ static inline void messageHandler(const QtMsgType type, const QMessageLogContext
}
}
void Log::setup(char *argv[],const QString &app,int level)
{
void Log::setup(char *argv[], const QString &app, int level) {
Q_ASSERT(!app.isEmpty());
if (app.isEmpty()) {
return;

View File

@ -1,11 +1,9 @@
#ifndef LOG_H
#define LOG_H
#pragma once
#include <QtCore/qstring.h>
namespace Log
{
namespace Log {
QString prettyProductInfoWrapper();
void setup(char *argv[], const QString &app, int level = 4);
}
#endif // LOG_H

View File

@ -17,12 +17,14 @@
#include <QCryptographicHash>
#include <QEventLoop>
#include <QGuiApplication>
#include <utility>
NetworkCallable::NetworkCallable(QObject *parent) : QObject{parent} {
}
QString NetworkParams::method2String(){
QString NetworkParams::method2String() const {
switch (_method) {
case METHOD_GET:
return "GET";
@ -41,21 +43,21 @@ QString NetworkParams::method2String(){
}
}
int NetworkParams::getTimeout(){
int NetworkParams::getTimeout() const {
if (_timeout != -1) {
return _timeout;
}
return Network::getInstance()->timeout();
}
int NetworkParams::getRetry(){
int NetworkParams::getRetry() const {
if (_retry != -1) {
return _retry;
}
return Network::getInstance()->retry();
}
bool NetworkParams::getOpenLog(){
bool NetworkParams::getOpenLog() const {
if (!_openLog.isNull()) {
return _openLog.toBool();
}
@ -63,52 +65,49 @@ bool NetworkParams::getOpenLog(){
}
FluDownloadParam::FluDownloadParam(QObject *parent)
: QObject{parent}
{
: QObject{parent} {
}
FluDownloadParam::FluDownloadParam(QString destPath, bool append, QObject *parent)
: QObject{parent}
{
this->_destPath = destPath;
: QObject{parent} {
this->_destPath = std::move(destPath);
this->_append = append;
}
NetworkParams::NetworkParams(QObject *parent)
: QObject{parent}
{
NetworkParams::NetworkParams(QObject *parent) : QObject{parent} {
_method = NetworkParams::Method::METHOD_GET;
_type = NetworkParams::Type::TYPE_BODY;
}
NetworkParams::NetworkParams(QString url, Type type, Method method, QObject *parent)
: QObject{parent}
{
: QObject{parent} {
this->_method = method;
this->_url = url;
this->_url = std::move(url);
this->_type = type;
}
NetworkParams* NetworkParams::add(QString key,QVariant val){
NetworkParams *NetworkParams::add(const QString &key, const QVariant &val) {
_paramMap.insert(key, val);
return this;
}
NetworkParams* NetworkParams::addFile(QString key,QVariant val){
NetworkParams *NetworkParams::addFile(const QString &key, const QVariant &val) {
_fileMap.insert(key, val);
return this;
}
NetworkParams* NetworkParams::addHeader(QString key,QVariant val){
NetworkParams *NetworkParams::addHeader(const QString &key, const QVariant &val) {
_headerMap.insert(key, val);
return this;
}
NetworkParams* NetworkParams::addQuery(QString key,QVariant val){
NetworkParams *NetworkParams::addQuery(const QString &key, const QVariant &val) {
_queryMap.insert(key, val);
return this;
}
NetworkParams *NetworkParams::setBody(QString val) {
_body = val;
_body = std::move(val);
return this;
}
@ -128,7 +127,7 @@ NetworkParams* NetworkParams::setCacheMode(int val){
}
NetworkParams *NetworkParams::toDownload(QString destPath, bool append) {
_downloadParam = new FluDownloadParam(destPath,append,this);
_downloadParam = new FluDownloadParam(std::move(destPath), append, this);
return this;
}
@ -138,11 +137,11 @@ NetworkParams* NetworkParams::bind(QObject* target){
}
NetworkParams *NetworkParams::openLog(QVariant val) {
_openLog = val;
_openLog = std::move(val);
return this;
}
QString NetworkParams::buildCacheKey(){
QString NetworkParams::buildCacheKey() const {
QJsonObject obj;
obj.insert("url", _url);
obj.insert("method", method2String());
@ -196,19 +195,19 @@ void Network::handle(NetworkParams* params,NetworkCallable* c){
manager.setTransferTimeout(params->getTimeout());
QEventLoop loop;
connect(&manager, &QNetworkAccessManager::finished, &manager, [&loop](QNetworkReply *reply) { loop.quit(); });
for (int i = 0; i < params->getRetry(); ++i) {
for (int i = 0; i <= params->getRetry() - 1; ++i) {
QUrl url(params->_url);
addQueryParam(&url, params->_queryMap);
QNetworkRequest request(url);
addHeaders(&request, params->_headerMap);
QNetworkReply *reply;
sendRequest(&manager, request, params, reply, i == 0, callable);
if(!QPointer<QGuiApplication>(qApp)){
if (!QPointer<QCoreApplication>(QGuiApplication::instance())) {
reply->deleteLater();
reply = nullptr;
return;
}
auto abortCallable = [&loop,reply,&i,params]{
auto abortCallable = [reply, &i, params] {
if (reply) {
i = params->getRetry();
reply->abort();
@ -219,7 +218,7 @@ void Network::handle(NetworkParams* params,NetworkCallable* c){
if (params->_target) {
conn_destroyed = connect(params->_target, &QObject::destroyed, &manager, abortCallable);
}
conn_quit = connect(qApp,&QGuiApplication::aboutToQuit,&manager, abortCallable);
conn_quit = connect(QGuiApplication::instance(), &QGuiApplication::aboutToQuit, &manager, abortCallable);
loop.exec();
if (conn_destroyed) {
disconnect(conn_destroyed);
@ -282,14 +281,14 @@ void Network::handleDownload(NetworkParams* params,NetworkCallable* c){
addHeaders(&request, params->_headerMap);
QString cachePath = getCacheFilePath(cacheKey);
QString destPath = params->_downloadParam->_destPath;
QFile* destFile = new QFile(destPath);
QFile* cacheFile = new QFile(cachePath);
bool isOpen = false;
qint64 seek = 0;
auto *destFile = new QFile(destPath);
auto *cacheFile = new QFile(cachePath);
bool isOpen;
qint64 seek;
if (cacheFile->exists() && destFile->exists() && params->_downloadParam->_append) {
QJsonObject cacheInfo = QJsonDocument::fromJson(readCache(cacheKey).toUtf8()).object();
qint64 fileSize = cacheInfo.value("fileSize").toDouble();
qint64 contentLength = cacheInfo.value("contentLength").toDouble();
qint64 fileSize = qRound(cacheInfo.value("fileSize").toDouble());
qint64 contentLength = qRound(cacheInfo.value("contentLength").toDouble());
if (fileSize == contentLength && destFile->size() == contentLength) {
if (!callable.isNull()) {
callable->downloadProgress(fileSize, contentLength);
@ -316,8 +315,7 @@ void Network::handleDownload(NetworkParams* params,NetworkCallable* c){
return;
}
if (params->_downloadParam->_append) {
if (!cacheFile->open(QIODevice::WriteOnly|QIODevice::Truncate))
{
if (!cacheFile->open(QIODevice::WriteOnly | QIODevice::Truncate)) {
if (!callable.isNull()) {
callable->error(-1, "cache file device not open", "");
callable->finish();
@ -329,22 +327,21 @@ void Network::handleDownload(NetworkParams* params,NetworkCallable* c){
QNetworkReply *reply = manager.get(request);
destFile->setParent(reply);
cacheFile->setParent(reply);
auto abortCallable = [&loop,reply,params]{
auto abortCallable = [reply] {
if (reply) {
reply->abort();
}
};
connect(&manager, &QNetworkAccessManager::finished, &manager, [&loop](QNetworkReply *reply) { loop.quit(); });
connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();});
connect(QGuiApplication::instance(), &QGuiApplication::aboutToQuit, &manager, [&loop, reply]() { reply->abort(), loop.quit(); });
QMetaObject::Connection conn_destroyed = {};
QMetaObject::Connection conn_quit = {};
if (params->_target) {
conn_destroyed = connect(params->_target, &QObject::destroyed, &manager, abortCallable);
}
conn_quit = connect(qApp,&QGuiApplication::aboutToQuit,&manager, abortCallable);
conn_quit = connect(QGuiApplication::instance(), &QGuiApplication::aboutToQuit, &manager, abortCallable);
connect(reply, &QNetworkReply::readyRead, reply, [reply, seek, destFile, cacheFile, callable] {
if (!reply || !destFile || reply->error() != QNetworkReply::NoError)
{
if (!reply || !destFile || reply->error() != QNetworkReply::NoError) {
return;
}
QMap<QString, QVariant> downInfo;
@ -433,31 +430,29 @@ QString Network::map2String(const QMap<QString, QVariant>& map){
return parameters.join(" ");
}
void Network::sendRequest(QNetworkAccessManager* manager,QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,bool isFirst,QPointer<NetworkCallable> callable){
void Network::sendRequest(QNetworkAccessManager *manager, QNetworkRequest request, NetworkParams *params, QNetworkReply *&reply, bool isFirst, const QPointer<NetworkCallable> &callable) {
QByteArray verb = params->method2String().toUtf8();
switch (params->_type) {
case NetworkParams::TYPE_FORM: {
bool isFormData = !params->_fileMap.isEmpty();
if (isFormData) {
QHttpMultiPart *multiPart = new QHttpMultiPart();
auto *multiPart = new QHttpMultiPart();
multiPart->setContentType(QHttpMultiPart::FormDataType);
for (const auto& each : params->_paramMap.toStdMap())
{
for (const auto &each: params->_paramMap.toStdMap()) {
QHttpPart part;
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"").arg(each.first));
part.setBody(each.second.toByteArray());
multiPart->append(part);
}
for (const auto& each : params->_fileMap.toStdMap())
{
for (const auto &each: params->_fileMap.toStdMap()) {
QString filePath = each.second.toString();
QString name = each.first;
QFile *file = new QFile(filePath);
auto *file = new QFile(filePath);
QString fileName = QFileInfo(filePath).fileName();
file->open(QIODevice::ReadOnly);
file->setParent(multiPart);
QHttpPart part;
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"; filename=\"%2\"").arg(name,fileName));
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString(R"(form-data; name="%1"; filename="%2")").arg(name, fileName));
part.setBodyDevice(file);
multiPart->append(part);
}
@ -471,8 +466,7 @@ void Network::sendRequest(QNetworkAccessManager* manager,QNetworkRequest request
} else {
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/x-www-form-urlencoded"));
QString value;
for (const auto& each : params->_paramMap.toStdMap())
{
for (const auto &each: params->_paramMap.toStdMap()) {
value += QString("%1=%2").arg(each.first, each.second.toString());
value += "&";
}
@ -487,8 +481,7 @@ void Network::sendRequest(QNetworkAccessManager* manager,QNetworkRequest request
case NetworkParams::TYPE_JSON: {
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/json;charset=utf-8"));
QJsonObject json;
for (const auto& each : params->_paramMap.toStdMap())
{
for (const auto &each: params->_paramMap.toStdMap()) {
json.insert(each.first, each.second.toJsonValue());
}
QByteArray data = QJsonDocument(json).toJson(QJsonDocument::Compact);
@ -498,8 +491,7 @@ void Network::sendRequest(QNetworkAccessManager* manager,QNetworkRequest request
case NetworkParams::TYPE_JSONARRAY: {
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/json;charset=utf-8"));
QJsonArray jsonArray;
for (const auto& each : params->_paramMap.toStdMap())
{
for (const auto &each: params->_paramMap.toStdMap()) {
QJsonObject json;
json.insert(each.first, each.second.toJsonValue());
jsonArray.append(json);
@ -523,7 +515,7 @@ void Network::sendRequest(QNetworkAccessManager* manager,QNetworkRequest request
}
}
void Network::printRequestStartLog(QNetworkRequest request,NetworkParams* params){
void Network::printRequestStartLog(const QNetworkRequest &request, NetworkParams *params) {
if (!params->getOpenLog()) {
return;
}
@ -551,7 +543,7 @@ void Network::printRequestStartLog(QNetworkRequest request,NetworkParams* params
}
}
void Network::printRequestEndLog(QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,const QString& response){
void Network::printRequestEndLog(const QNetworkRequest &request, NetworkParams *params, QNetworkReply *&reply, const QString &response) {
if (!params->getOpenLog()) {
return;
}
@ -560,11 +552,10 @@ void Network::printRequestEndLog(QNetworkRequest request,NetworkParams* params,Q
qDebug() << "<Result>" << qUtf8Printable(response);
}
void Network::saveResponse(QString key,QString response){
void Network::saveResponse(const QString &key, const QString &response) {
QSharedPointer<QFile> file(new QFile(getCacheFilePath(key)));
QIODevice::OpenMode mode = QIODevice::WriteOnly | QIODevice::Truncate;
if (!file->open(mode))
{
if (!file->open(mode)) {
return;
}
file->write(response.toUtf8().toBase64());
@ -573,8 +564,7 @@ void Network::saveResponse(QString key,QString response){
void Network::addHeaders(QNetworkRequest *request, const QMap<QString, QVariant> &headers) {
request->setHeader(QNetworkRequest::UserAgentHeader, QString::fromStdString("Mozilla/5.0 %1/%2").arg(QGuiApplication::applicationName(), QGuiApplication::applicationVersion()));
QMapIterator<QString, QVariant> iter(headers);
while (iter.hasNext())
{
while (iter.hasNext()) {
iter.next();
request->setRawHeader(iter.key().toUtf8(), iter.value().toString().toUtf8());
}
@ -583,20 +573,18 @@ void Network::addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>&
void Network::addQueryParam(QUrl *url, const QMap<QString, QVariant> &params) {
QMapIterator<QString, QVariant> iter(params);
QUrlQuery urlQuery(*url);
while (iter.hasNext())
{
while (iter.hasNext()) {
iter.next();
urlQuery.addQueryItem(iter.key(), iter.value().toString());
}
url->setQuery(urlQuery);
}
Network::Network(QObject *parent): QObject{parent}
{
timeout(5000);
retry(3);
openLog(false);
cacheDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation).append(QDir::separator()).append("network"));
Network::Network(QObject *parent) : QObject{parent} {
_timeout = 5000;
_retry = 3;
_openLog = false;
_cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation).append(QDir::separator()).append("network");
}
NetworkParams *Network::get(const QString &url) {
@ -672,5 +660,5 @@ NetworkParams* Network::deleteJsonArray(const QString& url){
}
void Network::setInterceptor(QJSValue interceptor) {
this->_interceptor = interceptor;
this->_interceptor = std::move(interceptor);
}

View File

@ -1,5 +1,4 @@
#ifndef NETWORK_H
#define NETWORK_H
#pragma once
#include <QObject>
#include <QtQml/qqml.h>
@ -19,7 +18,9 @@ enum CacheMode {
IfNoneCacheRequest = 0x0002,
FirstCacheThenRequest = 0x0004,
};
Q_ENUM_NS(CacheMode)
QML_NAMED_ELEMENT(NetworkType)
}
@ -31,12 +32,19 @@ class NetworkCallable : public QObject{
QML_NAMED_ELEMENT(NetworkCallable)
public:
explicit NetworkCallable(QObject *parent = nullptr);
Q_SIGNAL void start();
Q_SIGNAL void finish();
Q_SIGNAL void error(int status, QString errorString, QString result);
Q_SIGNAL void success(QString result);
Q_SIGNAL void cache(QString result);
Q_SIGNAL void uploadProgress(qint64 sent, qint64 total);
Q_SIGNAL void downloadProgress(qint64 recv, qint64 total);
};
@ -47,17 +55,18 @@ class FluDownloadParam : public QObject{
Q_OBJECT
public:
explicit FluDownloadParam(QObject *parent = nullptr);
FluDownloadParam(QString destPath, bool append, QObject *parent = nullptr);
public:
QString _destPath;
bool _append;
bool _append{};
};
/**
* @brief The NetworkParams class
*/
class NetworkParams : public QObject
{
class NetworkParams : public QObject {
Q_OBJECT
QML_NAMED_ELEMENT(NetworkParams)
public:
@ -76,25 +85,45 @@ public:
TYPE_JSONARRAY,
TYPE_BODY
};
explicit NetworkParams(QObject *parent = nullptr);
NetworkParams(QString url, Type type, Method method, QObject *parent = nullptr);
Q_INVOKABLE NetworkParams* addQuery(QString key,QVariant val);
Q_INVOKABLE NetworkParams* addHeader(QString key,QVariant val);
Q_INVOKABLE NetworkParams* add(QString key,QVariant val);
Q_INVOKABLE NetworkParams* addFile(QString key,QVariant val);
Q_INVOKABLE NetworkParams *addQuery(const QString &key, const QVariant &val);
Q_INVOKABLE NetworkParams *addHeader(const QString &key, const QVariant &val);
Q_INVOKABLE NetworkParams *add(const QString &key, const QVariant &val);
Q_INVOKABLE NetworkParams *addFile(const QString &key, const QVariant &val);
Q_INVOKABLE NetworkParams *setBody(QString val);
Q_INVOKABLE NetworkParams *setTimeout(int val);
Q_INVOKABLE NetworkParams *setRetry(int val);
Q_INVOKABLE NetworkParams *setCacheMode(int val);
Q_INVOKABLE NetworkParams *toDownload(QString destPath, bool append = false);
Q_INVOKABLE NetworkParams *bind(QObject *target);
Q_INVOKABLE NetworkParams *openLog(QVariant val);
Q_INVOKABLE void go(NetworkCallable *result);
QString buildCacheKey();
QString method2String();
int getTimeout();
int getRetry();
bool getOpenLog();
QString buildCacheKey() const;
QString method2String() const;
int getTimeout() const;
int getRetry() const;
bool getOpenLog() const;
public:
FluDownloadParam *_downloadParam = nullptr;
QObject *_target = nullptr;
@ -115,8 +144,7 @@ public:
/**
* @brief The Network class
*/
class Network : public QObject
{
class Network : public QObject {
Q_OBJECT
Q_PROPERTY_AUTO(int, timeout)
Q_PROPERTY_AUTO(int, retry)
@ -124,46 +152,80 @@ class Network : public QObject
Q_PROPERTY_AUTO(bool, openLog)
QML_NAMED_ELEMENT(Network)
QML_SINGLETON
private:
explicit Network(QObject *parent = nullptr);
public:
SINGLETON(Network)
static Network *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine) { return getInstance(); }
Q_INVOKABLE NetworkParams *get(const QString &url);
Q_INVOKABLE NetworkParams *head(const QString &url);
Q_INVOKABLE NetworkParams *postBody(const QString &url);
Q_INVOKABLE NetworkParams *putBody(const QString &url);
Q_INVOKABLE NetworkParams *patchBody(const QString &url);
Q_INVOKABLE NetworkParams *deleteBody(const QString &url);
Q_INVOKABLE NetworkParams *postForm(const QString &url);
Q_INVOKABLE NetworkParams *putForm(const QString &url);
Q_INVOKABLE NetworkParams *patchForm(const QString &url);
Q_INVOKABLE NetworkParams *deleteForm(const QString &url);
Q_INVOKABLE NetworkParams *postJson(const QString &url);
Q_INVOKABLE NetworkParams *putJson(const QString &url);
Q_INVOKABLE NetworkParams *patchJson(const QString &url);
Q_INVOKABLE NetworkParams *deleteJson(const QString &url);
Q_INVOKABLE NetworkParams *postJsonArray(const QString &url);
Q_INVOKABLE NetworkParams *putJsonArray(const QString &url);
Q_INVOKABLE NetworkParams *patchJsonArray(const QString &url);
Q_INVOKABLE NetworkParams *deleteJsonArray(const QString &url);
Q_INVOKABLE void setInterceptor(QJSValue interceptor);
void handle(NetworkParams *params, NetworkCallable *result);
void handleDownload(NetworkParams *params, NetworkCallable *result);
private:
void sendRequest(QNetworkAccessManager* manager,QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,bool isFirst,QPointer<NetworkCallable> callable);
void addQueryParam(QUrl* url,const QMap<QString, QVariant>& params);
void addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& headers);
void saveResponse(QString key,QString response);
static void sendRequest(QNetworkAccessManager *manager, QNetworkRequest request, NetworkParams *params, QNetworkReply *&reply, bool isFirst, const QPointer<NetworkCallable> &callable);
static void addQueryParam(QUrl *url, const QMap<QString, QVariant> &params);
static void addHeaders(QNetworkRequest *request, const QMap<QString, QVariant> &headers);
void saveResponse(const QString &key, const QString &response);
QString readCache(const QString &key);
bool cacheExists(const QString &key);
QString getCacheFilePath(const QString &key);
QString map2String(const QMap<QString, QVariant>& map);
QString headerList2String(const QList<QNetworkReply::RawHeaderPair>& data);
void printRequestStartLog(QNetworkRequest request,NetworkParams* params);
void printRequestEndLog(QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,const QString& response);
static QString headerList2String(const QList<QNetworkReply::RawHeaderPair> &data);
static void printRequestStartLog(const QNetworkRequest &request, NetworkParams *params);
static void printRequestEndLog(const QNetworkRequest &request, NetworkParams *params, QNetworkReply *&reply, const QString &response);
static QString map2String(const QMap<QString, QVariant> &map);
public:
QJSValue _interceptor;
};
#endif // Network_H

View File

@ -3,15 +3,13 @@
#include <QDataStream>
#include <QStandardPaths>
SettingsHelper::SettingsHelper(QObject *parent) : QObject(parent)
{
SettingsHelper::SettingsHelper(QObject *parent) : QObject(parent) {
}
SettingsHelper::~SettingsHelper() = default;
void SettingsHelper::save(const QString& key,QVariant val)
{
void SettingsHelper::save(const QString &key, QVariant val) {
m_settings->setValue(key, val);
}

View File

@ -1,5 +1,4 @@
#ifndef SETTINGSHELPER_H
#define SETTINGSHELPER_H
#pragma once
#include <QtCore/qobject.h>
#include <QtQml/qqml.h>
@ -10,26 +9,35 @@
#include <QDir>
#include "src/singleton.h"
class SettingsHelper : public QObject
{
class SettingsHelper : public QObject {
Q_OBJECT
private:
explicit SettingsHelper(QObject *parent = nullptr);
public:
SINGLETON(SettingsHelper)
~SettingsHelper() override;
void init(char *argv[]);
Q_INVOKABLE void saveDarkMode(int darkModel) { save("darkMode", darkModel); }
Q_INVOKABLE int getDarkMode() { return get("darkMode", QVariant(0)).toInt(); }
Q_INVOKABLE void saveUseSystemAppBar(bool useSystemAppBar) { save("useSystemAppBar", useSystemAppBar); }
Q_INVOKABLE bool getUseSystemAppBar() { return get("useSystemAppBar", QVariant(false)).toBool(); }
Q_INVOKABLE void saveLanguage(QString language){save("language",language);}
Q_INVOKABLE void saveLanguage(const QString &language) { save("language", language); }
Q_INVOKABLE QString getLanguage() { return get("language", QVariant("en_US")).toString(); }
private:
void save(const QString &key, QVariant val);
QVariant get(const QString &key, QVariant def = {});
private:
QScopedPointer<QSettings> m_settings;
};
#endif // SETTINGSHELPER_H

View File

@ -5,8 +5,7 @@
#include "SettingsHelper.h"
TranslateHelper::TranslateHelper(QObject *parent) : QObject(parent)
{
[[maybe_unused]] TranslateHelper::TranslateHelper(QObject *parent) : QObject(parent) {
_languages << "en_US";
_languages << "zh_CN";
_current = SettingsHelper::getInstance()->getLanguage();
@ -17,7 +16,7 @@ TranslateHelper::~TranslateHelper() = default;
void TranslateHelper::init(QQmlEngine *engine) {
_engine = engine;
_translator = new QTranslator(this);
qApp->installTranslator(_translator);
QGuiApplication::installTranslator(_translator);
QString translatorPath = QGuiApplication::applicationDirPath() + "/i18n";
if (_translator->load(QString::fromStdString("%1/example_%2.qm").arg(translatorPath, _current))) {
_engine->retranslate();

View File

@ -1,5 +1,4 @@
#ifndef TRANSLATEHELPER_H
#define TRANSLATEHELPER_H
#pragma once
#include <QObject>
#include <QtQml/qqml.h>
@ -7,20 +6,21 @@
#include "src/singleton.h"
#include "src/stdafx.h"
class TranslateHelper : public QObject
{
class TranslateHelper : public QObject {
Q_OBJECT
Q_PROPERTY_AUTO(QString, current)
Q_PROPERTY_READONLY_AUTO(QStringList, languages)
private:
explicit TranslateHelper(QObject* parent = nullptr);
[[maybe_unused]] explicit TranslateHelper(QObject *parent = nullptr);
public:
SINGLETON(TranslateHelper)
~TranslateHelper() override;
void init(QQmlEngine *engine);
private:
QQmlEngine *_engine = nullptr;
QTranslator *_translator = nullptr;
};
#endif // TRANSLATEHELPER_H

View File

@ -14,6 +14,7 @@
#include "src/component/CircularReveal.h"
#include "src/component/FileWatcher.h"
#include "src/component/FpsItem.h"
#include "src/component/OpenGLItem.h"
#include "src/helper/SettingsHelper.h"
#include "src/helper/InitializrHelper.h"
#include "src/helper/TranslateHelper.h"
@ -53,7 +54,7 @@ int main(int argc, char *argv[])
QGuiApplication::setOrganizationName("ZhuZiChu");
QGuiApplication::setOrganizationDomain("https://zhuzichu520.github.io");
QGuiApplication::setApplicationName("FluentUI");
QGuiApplication::setApplicationDisplayName("FluentUI Exmaple");
QGuiApplication::setApplicationDisplayName("FluentUI Example");
QGuiApplication::setApplicationVersion(APPLICATION_VERSION);
QGuiApplication::setQuitOnLastWindowClosed(false);
SettingsHelper::getInstance()->init(argv);
@ -75,6 +76,9 @@ int main(int argc, char *argv[])
qmlRegisterType<FpsItem>(uri, major, minor, "FpsItem");
qmlRegisterType<NetworkCallable>(uri,major,minor,"NetworkCallable");
qmlRegisterType<NetworkParams>(uri,major,minor,"NetworkParams");
qmlRegisterType<OpenGLItem>(uri,major,minor,"OpenGLItem");
qmlRegisterUncreatableMetaObject(NetworkType::staticMetaObject, uri, major, minor, "NetworkType", "Access to enums & flags only");
QQmlApplicationEngine engine;
TranslateHelper::getInstance()->init(&engine);
engine.rootContext()->setContextProperty("AppInfo",AppInfo::getInstance());

View File

@ -1,5 +1,4 @@
#ifndef SINGLETON_H
#define SINGLETON_H
#pragma once
/**
* @brief The Singleton class
@ -23,5 +22,3 @@ private: \
static Class* getInstance() { \
return Singleton<Class>::getInstance(); \
}
#endif // SINGLETON_H

View File

@ -1,7 +1,6 @@
#ifndef STDAFX_H
#define STDAFX_H
#pragma once
#define Q_PROPERTY_AUTO(TYPE, M) \
#define Q_PROPERTY_AUTO_P(TYPE, M) \
Q_PROPERTY(TYPE M MEMBER _##M NOTIFY M##Changed) \
public: \
Q_SIGNAL void M##Changed(); \
@ -15,14 +14,13 @@ Q_PROPERTY(TYPE M MEMBER _##M NOTIFY M##Changed)
return _##M; \
} \
private: \
TYPE _##M; \
TYPE _##M;
#define Q_PROPERTY_READONLY_AUTO(TYPE, M) \
Q_PROPERTY(TYPE M READ M NOTIFY M##Changed FINAL) \
#define Q_PROPERTY_AUTO(TYPE, M) \
Q_PROPERTY(TYPE M MEMBER _##M NOTIFY M##Changed) \
public: \
Q_SIGNAL void M##Changed(); \
void M(TYPE in_##M) \
void M(const TYPE& in_##M) \
{ \
_##M = in_##M; \
Q_EMIT M##Changed(); \
@ -32,6 +30,21 @@ Q_PROPERTY(TYPE M READ M NOTIFY M##Changed FINAL)
return _##M; \
} \
private: \
TYPE _##M; \
TYPE _##M;
#endif // STDAFX_H
#define Q_PROPERTY_READONLY_AUTO(TYPE, M) \
Q_PROPERTY(TYPE M READ M NOTIFY M##Changed FINAL) \
public: \
Q_SIGNAL void M##Changed(); \
void M(const TYPE& in_##M) \
{ \
_##M = in_##M; \
Q_EMIT M##Changed(); \
} \
TYPE M() \
{ \
return _##M; \
} \
private: \
TYPE _##M;

View File

@ -13,7 +13,7 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#
add_definitions(-DFLUENTUI_VERSION=1,7,4,0)
add_definitions(-DFLUENTUI_VERSION=1,7,5,0)
if (FLUENTUI_BUILD_STATIC_LIB)
add_definitions(-DFLUENTUI_BUILD_STATIC_LIB)
@ -24,7 +24,7 @@ option(FLUENTUI_BUILD_STATIC_LIB "Build static library." OFF)
#Qt
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Quick Qml)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick Qml)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick)
set(QT_SDK_DIR "${Qt${QT_VERSION_MAJOR}_DIR}/../../..")
cmake_path(SET QT_SDK_DIR NORMALIZE ${QT_SDK_DIR})
@ -59,7 +59,7 @@ file(GLOB QM_FILE_PATHS ${CMAKE_CURRENT_LIST_DIR}/ *.qm)
file(COPY ${QM_FILE_PATHS} DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/Qt${QT_VERSION_MAJOR}/imports/FluentUI/i18n")
#Cpp
file(GLOB_RECURSE CPP_FILES *.cpp *.h)
file(GLOB_RECURSE CPP_FILES *.cpp *.h *.cxx)
foreach (filepath ${CPP_FILES})
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
list(APPEND sources_files ${filename})
@ -143,11 +143,7 @@ if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
RESOURCE_PREFIX "/qt/qml"
)
else ()
#qrc
set(QRC_FILE Qt5/imports/fluentui.qrc)
qt_add_big_resources(QRC_RESOURCES ${QRC_FILE})
list(APPEND QRC_RESOURCES ${QRC_FILE})
set_property(SOURCE ${QRC_FILE} PROPERTY SKIP_AUTORCC ON)
qt_add_resources(QRC_RESOURCES Qt5/imports/fluentui.qrc)
#Qt6.2使add_qmlplugin.cmake/QmlPlugin.cmake
include(QmlPlugin)
add_qmlplugin(${PROJECT_NAME}

View File

@ -1 +0,0 @@
#include "Def.h"

1444
src/Def.h

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
#include "FluAccentColor.h"
FluAccentColor::FluAccentColor(QObject *parent) : QObject{parent} {
}

View File

@ -1,5 +1,4 @@
#ifndef FLUACCENTCOLOR_H
#define FLUACCENTCOLOR_H
#pragma once
#include <QObject>
#include <QtQml/qqml.h>
@ -9,9 +8,9 @@
/**
* @brief The FluAccentColor class
*/
class FluAccentColor : public QObject
{
class FluAccentColor : public QObject {
Q_OBJECT
Q_PROPERTY_AUTO(QColor, darkest)
Q_PROPERTY_AUTO(QColor, darker)
Q_PROPERTY_AUTO(QColor, dark)
@ -23,5 +22,3 @@ class FluAccentColor : public QObject
public:
explicit FluAccentColor(QObject *parent = nullptr);
};
#endif // FLUACCENTCOLOR_H

View File

@ -2,26 +2,26 @@
#include <QQmlEngine>
#include <QGuiApplication>
#include <QQmlContext>
#include <QQuickItem>
#include <QTimer>
#include <QUuid>
#include <QFontDatabase>
#include <QClipboard>
#include <QTranslator>
#include <utility>
#include "FluentIconDef.h"
FluApp::FluApp(QObject *parent) : QObject{parent} {
useSystemAppBar(false);
_useSystemAppBar = false;
}
FluApp::~FluApp(){
}
FluApp::~FluApp() = default;
void FluApp::init(QObject *target, QLocale locale) {
_locale = locale;
_locale = std::move(locale);
_engine = qmlEngine(target);
_translator = new QTranslator(this);
qApp->installTranslator(_translator);
QGuiApplication::installTranslator(_translator);
const QStringList uiLanguages = _locale.uiLanguages();
for (const QString &name: uiLanguages) {
const QString baseName = "fluentui_" + QLocale(name).name();
@ -31,3 +31,19 @@ void FluApp::init(QObject *target,QLocale locale){
}
}
}
[[maybe_unused]] QJsonArray FluApp::iconDatas(const QString &keyword) {
QJsonArray arr;
QMetaEnum enumType = Fluent_Icons::staticMetaObject.enumerator(Fluent_Icons::staticMetaObject.indexOfEnumerator("Fluent_IconType"));
for (int i = 0; i <= enumType.keyCount() - 1; ++i) {
QString name = enumType.key(i);
int icon = enumType.value(i);
if (keyword.isEmpty() || name.contains(keyword)) {
QJsonObject obj;
obj.insert("name", name);
obj.insert("icon", icon);
arr.append(obj);
}
}
return arr;
}

View File

@ -1,5 +1,4 @@
#ifndef FLUAPP_H
#define FLUAPP_H
#pragma once
#include <QObject>
#include <QWindow>
@ -9,30 +8,37 @@
#include <QQmlEngine>
#include <QTranslator>
#include <QQuickWindow>
#include <QJsonArray>
#include "stdafx.h"
#include "singleton.h"
/**
* @brief The FluApp class
*/
class FluApp : public QObject
{
class FluApp : public QObject {
Q_OBJECT
Q_PROPERTY_AUTO(bool,useSystemAppBar);
Q_PROPERTY_AUTO(QString,windowIcon);
Q_PROPERTY_AUTO(QLocale,locale);
Q_PROPERTY_AUTO(bool, useSystemAppBar)
Q_PROPERTY_AUTO(QString, windowIcon)
Q_PROPERTY_AUTO(QLocale, locale)
QML_NAMED_ELEMENT(FluApp)
QML_SINGLETON
private:
explicit FluApp(QObject *parent = nullptr);
~FluApp();
~FluApp() override;
public:
SINGLETON(FluApp)
static FluApp *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
static FluApp *create(QQmlEngine *, QJSEngine *) { return getInstance(); }
Q_INVOKABLE void init(QObject *target, QLocale locale = QLocale::system());
[[maybe_unused]] Q_INVOKABLE static QJsonArray iconDatas(const QString &keyword = "");
private:
QQmlEngine *_engine;
QQmlEngine *_engine{};
QTranslator *_translator = nullptr;
};
#endif // FLUAPP_H

View File

@ -3,14 +3,20 @@
#include <QChar>
#include <QPainter>
#include <QRandomGenerator>
#include <qmath.h>
int generaNumber(int number) {
return QRandomGenerator::global()->bounded(0, number);
}
FluCaptcha::FluCaptcha(QQuickItem *parent) : QQuickPaintedItem(parent) {
ignoreCase(true);
QFont fontStype;
fontStype.setPixelSize(28);
fontStype.setBold(true);
font(fontStype);
_ignoreCase = false;
QFont fontStyle;
#ifdef Q_OS_WIN
fontStyle.setFamily("微软雅黑");
#endif
fontStyle.setPixelSize(28);
fontStyle.setBold(true);
font(fontStyle);
setWidth(180);
setHeight(80);
refresh();
@ -21,55 +27,42 @@ void FluCaptcha::paint(QPainter* painter){
painter->fillRect(boundingRect().toRect(), QColor(255, 255, 255, 255));
QPen pen;
painter->setFont(_font);
for(int i=0;i<100;i++)
{
pen = QPen(QColor(_generaNumber(256),_generaNumber(256),_generaNumber(256)));
for (int i = 0; i < 100; i++) {
pen = QPen(QColor(generaNumber(256), generaNumber(256), generaNumber(256)));
painter->setPen(pen);
painter->drawPoint(_generaNumber(180),_generaNumber(80));
painter->drawPoint(generaNumber(180), generaNumber(80));
}
for(int i=0;i<5;i++)
{
pen = QPen(QColor(_generaNumber(256),_generaNumber(256),_generaNumber(256)));
for (int i = 0; i < 5; i++) {
pen = QPen(QColor(generaNumber(256), generaNumber(256), generaNumber(256)));
painter->setPen(pen);
painter->drawLine(_generaNumber(180),_generaNumber(80),_generaNumber(180),_generaNumber(80));
painter->drawLine(generaNumber(180), generaNumber(80), generaNumber(180), generaNumber(80));
}
for(int i=0;i<4;i++)
{
pen = QPen(QColor(_generaNumber(255),_generaNumber(255),_generaNumber(255)));
for (int i = 0; i < 4; i++) {
pen = QPen(QColor(generaNumber(255), generaNumber(255), generaNumber(255)));
painter->setPen(pen);
painter->drawText(15+35*i,10+_generaNumber(15),30,40,Qt::AlignCenter, QString(_code[i]));
painter->drawText(15 + 35 * i, 10 + generaNumber(15), 30, 40, Qt::AlignCenter, QString(_code[i]));
}
painter->restore();
}
int FluCaptcha::_generaNumber(int number){
return QRandomGenerator::global()->bounded(0,number);
}
void FluCaptcha::refresh() {
this->_code.clear();
for(int i = 0;i < 4;++i)
{
int num = _generaNumber(3);
if(num == 0)
{
this->_code += QString::number(_generaNumber(10));
}
else if(num == 1)
{
for (int i = 0; i < 4; ++i) {
int num = generaNumber(3);
if (num == 0) {
this->_code += QString::number(generaNumber(10));
} else if (num == 1) {
int temp = 'A';
this->_code += static_cast<QChar>(temp + _generaNumber(26));
}
else if(num == 2)
{
this->_code += static_cast<QChar>(temp + generaNumber(26));
} else if (num == 2) {
int temp = 'a';
this->_code += static_cast<QChar>(temp + _generaNumber(26));
this->_code += static_cast<QChar>(temp + generaNumber(26));
}
}
update();
}
bool FluCaptcha::verify(const QString& code){
[[maybe_unused]] bool FluCaptcha::verify(const QString &code) {
if (_ignoreCase) {
return this->_code.toUpper() == code.toUpper();
}

View File

@ -1,5 +1,4 @@
#ifndef FLUCAPTCHA_H
#define FLUCAPTCHA_H
#pragma once
#include <QQuickItem>
#include <QQuickPaintedItem>
@ -9,21 +8,22 @@
/**
* @brief The FluCaptcha class
*/
class FluCaptcha : public QQuickPaintedItem
{
class FluCaptcha : public QQuickPaintedItem {
Q_OBJECT
Q_PROPERTY_AUTO(QFont, font);
Q_PROPERTY_AUTO(bool, ignoreCase);
QML_NAMED_ELEMENT(FluCaptcha)
private:
int _generaNumber(int number);
public:
explicit FluCaptcha(QQuickItem *parent = nullptr);
void paint(QPainter *painter) override;
Q_INVOKABLE void refresh();
Q_INVOKABLE bool verify(const QString& code);
[[maybe_unused]] Q_INVOKABLE bool verify(const QString &code);
private:
QString _code;
};
#endif // FLUCAPTCHA_H

View File

@ -2,34 +2,33 @@
#include "FluTools.h"
FluColors::FluColors(QObject *parent) : QObject{parent} {
Transparent(QColor(0, 0, 0, 0));
Black(QColor(0, 0, 0));
White(QColor(255, 255, 255));
Grey10(QColor(250, 249, 248));
Grey20(QColor(243, 242, 241));
Grey30(QColor(237, 235, 233));
Grey40(QColor(225, 223, 221));
Grey50(QColor(210, 208, 206));
Grey60(QColor(200, 198, 196));
Grey70(QColor(190, 185, 184));
Grey80(QColor(179, 176, 173));
Grey90(QColor(161, 159, 157));
Grey100(QColor(151, 149, 146));
Grey110(QColor(138, 136, 134));
Grey120(QColor(121, 119, 117));
Grey130(QColor(96, 94, 92));
Grey140(QColor(72, 70, 68));
Grey150(QColor(59, 58, 57));
Grey160(QColor(50, 49, 48));
Grey170(QColor(41, 40, 39));
Grey180(QColor(37, 36, 35));
Grey190(QColor(32, 31, 30));
Grey200(QColor(27, 26, 25));
Grey210(QColor(22, 21, 20));
Grey220(QColor(17, 16, 15));
_Transparent = QColor(0, 0, 0, 0);
_Black = QColor(0, 0, 0);
_White = QColor(255, 255, 255);
_Grey10 = QColor(250, 249, 248);
_Grey20 = QColor(243, 242, 241);
_Grey30 = QColor(237, 235, 233);
_Grey40 = QColor(225, 223, 221);
_Grey50 = QColor(210, 208, 206);
_Grey60 = QColor(200, 198, 196);
_Grey70 = QColor(190, 185, 184);
_Grey80 = QColor(179, 176, 173);
_Grey90 = QColor(161, 159, 157);
_Grey100 = QColor(151, 149, 146);
_Grey110 = QColor(138, 136, 134);
_Grey120 = QColor(121, 119, 117);
_Grey130 = QColor(96, 94, 92);
_Grey140 = QColor(72, 70, 68);
_Grey150 = QColor(59, 58, 57);
_Grey160 = QColor(50, 49, 48);
_Grey170 = QColor(41, 40, 39);
_Grey180 = QColor(37, 36, 35);
_Grey190 = QColor(32, 31, 30);
_Grey200 = QColor(27, 26, 25);
_Grey210 = QColor(22, 21, 20);
_Grey220 = QColor(17, 16, 15);
FluAccentColor *yellow = new FluAccentColor(this);
auto yellow = new FluAccentColor(this);
yellow->darkest(QColor(249, 168, 37));
yellow->darker(QColor(251, 192, 45));
yellow->dark(QColor(253, 212, 53));
@ -37,9 +36,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
yellow->light(QColor(255, 238, 88));
yellow->lighter(QColor(255, 241, 118));
yellow->lightest(QColor(255, 245, 155));
Yellow(yellow);
_Yellow = yellow;
FluAccentColor *orange = new FluAccentColor(this);
auto orange = new FluAccentColor(this);
orange->darkest(QColor(153, 61, 7));
orange->darker(QColor(172, 68, 8));
orange->dark(QColor(209, 88, 10));
@ -47,9 +46,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
orange->light(QColor(248, 122, 48));
orange->lighter(QColor(249, 145, 84));
orange->lightest(QColor(250, 192, 106));
Orange(orange);
_Orange = orange;
FluAccentColor *red = new FluAccentColor(this);
auto red = new FluAccentColor(this);
red->darkest(QColor(143, 10, 21));
red->darker(QColor(162, 11, 24));
red->dark(QColor(185, 13, 28));
@ -57,9 +56,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
red->light(QColor(236, 64, 79));
red->lighter(QColor(238, 88, 101));
red->lightest(QColor(240, 107, 118));
Red(red);
_Red = red;
FluAccentColor *magenta = new FluAccentColor(this);
auto magenta = new FluAccentColor(this);
magenta->darkest(QColor(111, 0, 79));
magenta->darker(QColor(160, 7, 108));
magenta->dark(QColor(181, 13, 125));
@ -67,9 +66,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
magenta->light(QColor(234, 77, 168));
magenta->lighter(QColor(238, 110, 193));
magenta->lightest(QColor(241, 140, 213));
Magenta(magenta);
_Magenta = magenta;
FluAccentColor *purple = new FluAccentColor(this);
auto purple = new FluAccentColor(this);
purple->darkest(QColor(44, 15, 118));
purple->darker(QColor(61, 15, 153));
purple->dark(QColor(78, 17, 174));
@ -77,9 +76,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
purple->light(QColor(123, 76, 157));
purple->lighter(QColor(141, 110, 189));
purple->lightest(QColor(158, 142, 217));
Purple(purple);
_Purple = purple;
FluAccentColor *blue = new FluAccentColor(this);
auto blue = new FluAccentColor(this);
blue->darkest(QColor(0, 74, 131));
blue->darker(QColor(0, 84, 148));
blue->dark(QColor(0, 102, 180));
@ -87,9 +86,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
blue->light(QColor(38, 140, 220));
blue->lighter(QColor(76, 160, 224));
blue->lightest(QColor(96, 171, 228));
Blue(blue);
_Blue = blue;
FluAccentColor *teal = new FluAccentColor(this);
auto teal = new FluAccentColor(this);
teal->darkest(QColor(0, 110, 91));
teal->darker(QColor(0, 124, 103));
teal->dark(QColor(0, 151, 125));
@ -97,9 +96,9 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
teal->light(QColor(38, 189, 164));
teal->lighter(QColor(77, 201, 180));
teal->lightest(QColor(96, 207, 188));
Teal(teal);
_Teal = teal;
FluAccentColor *green = new FluAccentColor(this);
auto green = new FluAccentColor(this);
green->darkest(QColor(9, 76, 9));
green->darker(QColor(12, 93, 12));
green->dark(QColor(14, 111, 14));
@ -107,17 +106,17 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
green->light(QColor(39, 137, 57));
green->lighter(QColor(76, 156, 76));
green->lightest(QColor(106, 173, 106));
Green(green);
_Green = green;
}
FluAccentColor* FluColors::createAccentColor(QColor primaryColor){
FluAccentColor *accentColor = new FluAccentColor(this);
accentColor->darkest(FluTools::getInstance()->withOpacity(primaryColor,0.7));
accentColor->darker(FluTools::getInstance()->withOpacity(primaryColor,0.8));
accentColor->dark(FluTools::getInstance()->withOpacity(primaryColor,0.9));
[[maybe_unused]] FluAccentColor *FluColors::createAccentColor(const QColor& primaryColor) {
auto accentColor = new FluAccentColor(this);
accentColor->normal(primaryColor);
accentColor->dark(FluTools::getInstance()->withOpacity(primaryColor, 0.9));
accentColor->light(FluTools::getInstance()->withOpacity(primaryColor, 0.9));
accentColor->lighter(FluTools::getInstance()->withOpacity(primaryColor,0.8));
accentColor->lightest(FluTools::getInstance()->withOpacity(primaryColor,0.7));
accentColor->darker(FluTools::getInstance()->withOpacity(accentColor->dark(), 0.8));
accentColor->lighter(FluTools::getInstance()->withOpacity(accentColor->light(), 0.8));
accentColor->darkest(FluTools::getInstance()->withOpacity(accentColor->darker(), 0.7));
accentColor->lightest(FluTools::getInstance()->withOpacity(accentColor->lighter(), 0.7));
return accentColor;
}

View File

@ -1,5 +1,4 @@
#ifndef FLUCOLORS_H
#define FLUCOLORS_H
#pragma once
#include <QObject>
#include <QtQml/qqml.h>
@ -11,9 +10,9 @@
/**
* @brief The FluColors class
*/
class FluColors : public QObject
{
class FluColors : public QObject {
Q_OBJECT
Q_PROPERTY_AUTO(QColor, Transparent);
Q_PROPERTY_AUTO(QColor, Black);
Q_PROPERTY_AUTO(QColor, White);
@ -39,22 +38,24 @@ class FluColors : public QObject
Q_PROPERTY_AUTO(QColor, Grey200);
Q_PROPERTY_AUTO(QColor, Grey210);
Q_PROPERTY_AUTO(QColor, Grey220);
Q_PROPERTY_AUTO(FluAccentColor*,Yellow);
Q_PROPERTY_AUTO(FluAccentColor*,Orange);
Q_PROPERTY_AUTO(FluAccentColor*,Red);
Q_PROPERTY_AUTO(FluAccentColor*,Magenta);
Q_PROPERTY_AUTO(FluAccentColor*,Purple);
Q_PROPERTY_AUTO(FluAccentColor*,Blue);
Q_PROPERTY_AUTO(FluAccentColor*,Teal);
Q_PROPERTY_AUTO(FluAccentColor*,Green);
Q_PROPERTY_AUTO_P(FluAccentColor*, Yellow);
Q_PROPERTY_AUTO_P(FluAccentColor*, Orange);
Q_PROPERTY_AUTO_P(FluAccentColor*, Red);
Q_PROPERTY_AUTO_P(FluAccentColor*, Magenta);
Q_PROPERTY_AUTO_P(FluAccentColor*, Purple);
Q_PROPERTY_AUTO_P(FluAccentColor*, Blue);
Q_PROPERTY_AUTO_P(FluAccentColor*, Teal);
Q_PROPERTY_AUTO_P(FluAccentColor*, Green);
QML_NAMED_ELEMENT(FluColors)
QML_SINGLETON
private:
explicit FluColors(QObject *parent = nullptr);
public:
SINGLETON(FluColors)
Q_INVOKABLE FluAccentColor* createAccentColor(QColor primaryColor);
static FluColors *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
};
#endif // FLUCOLORS_H
[[maybe_unused]] Q_INVOKABLE FluAccentColor *createAccentColor(const QColor& primaryColor);
static FluColors *create(QQmlEngine *, QJSEngine *) { return getInstance(); }
};

View File

@ -4,58 +4,74 @@
#include <QGuiApplication>
#include <QScreen>
#include <QDateTime>
#include "FluTools.h"
#ifdef Q_OS_WIN
#pragma comment (lib, "user32.lib")
#pragma comment (lib, "dwmapi.lib")
#include <windows.h>
#include <windowsx.h>
#include <dwmapi.h>
static inline QByteArray qtNativeEventType()
{
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");
if (module)
{
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)
{
if (dwm_is_composition_enabled) {
dwm_is_composition_enabled(&composition_enabled);
}
return composition_enabled;
}
return false;
}
#endif
FluFrameless::FluFrameless(QQuickItem *parent)
: QQuickItem{parent}
{
appbar(nullptr);
maximizeButton(nullptr);
minimizedButton(nullptr);
closeButton(nullptr);
topmost(false);
disabled(false);
bool containsCursorToItem(QQuickItem *item) {
if (!item || !item->isVisible()) {
return false;
}
auto point = QCursor::pos();
auto rect = QRectF(item->mapToGlobal(QPoint(0, 0)), item->size());
if (point.x() > rect.x() && point.x() < (rect.x() + rect.width()) && point.y() > rect.y() && point.y() < (rect.y() + rect.height())) {
return true;
}
return false;
}
FluFrameless::~FluFrameless(){
FluFrameless::FluFrameless(QQuickItem *parent) : QQuickItem{parent} {
_fixSize = false;
_appbar = nullptr;
_maximizeButton = nullptr;
_minimizedButton = nullptr;
_closeButton = nullptr;
_topmost = false;
_disabled = false;
_isWindows11OrGreater = FluTools::getInstance()->isWindows11OrGreater();
}
void FluFrameless::onDestruction(){
qApp->removeNativeEventFilter(this);
FluFrameless::~FluFrameless() = default;
[[maybe_unused]] void FluFrameless::onDestruction() {
QGuiApplication::instance()->removeNativeEventFilter(this);
}
void FluFrameless::componentComplete() {
if (_disabled) {
return;
}
int w = window()->width();
int h = window()->height();
_current = window()->winId();
window()->setFlags((window()->flags()) | Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::FramelessWindowHint);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
@ -67,7 +83,7 @@ void FluFrameless::componentComplete(){
window()->setFlag(Qt::WindowMaximizeButtonHint);
}
window()->installEventFilter(this);
qApp->installNativeEventFilter(this);
QGuiApplication::instance()->installNativeEventFilter(this);
if (_maximizeButton) {
setHitTestVisible(_maximizeButton);
}
@ -82,8 +98,8 @@ void FluFrameless::componentComplete(){
DWORD style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
if (_fixSize) {
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME);
for (int i = 0; i < qApp->screens().count(); ++i) {
connect( qApp->screens().at(i),&QScreen::logicalDotsPerInchChanged,this,[=]{
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);
});
}
@ -92,38 +108,43 @@ void FluFrameless::componentComplete(){
}
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,0,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
::RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
::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);
});
#endif
h = h + _appbar->height();
if (_fixSize) {
window()->setMaximumSize(QSize(w, h));
window()->setMinimumSize(QSize(w, h));
}
window()->resize(QSize(w, h));
connect(this, &FluFrameless::topmostChanged, this, [this] {
_setWindowTopmost(topmost());
});
_setWindowTopmost(topmost());
}
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;
}
const auto msg = static_cast<const MSG *>(message);
const HWND hwnd = msg->hwnd;
if (!hwnd || !msg) {
auto hwnd = msg->hwnd;
if (!hwnd) {
return false;
}
const qint64 wid = reinterpret_cast<qint64>(hwnd);
const quint64 wid = reinterpret_cast<qint64>(hwnd);
if (wid != _current) {
return false;
}
const UINT uMsg = msg->message;
const WPARAM wParam = msg->wParam;
const LPARAM lParam = msg->lParam;
const auto uMsg = msg->message;
const auto wParam = msg->wParam;
const auto lParam = msg->lParam;
static QPoint offsetXY;
if (uMsg == WM_WINDOWPOSCHANGING) {
WINDOWPOS* wp = reinterpret_cast<WINDOWPOS*>(lParam);
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0)
{
auto *wp = reinterpret_cast<WINDOWPOS *>(lParam);
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0) {
wp->flags |= SWP_NOCOPYBITS;
*result = ::DefWindowProcW(hwnd, uMsg, wParam, lParam);
return true;
@ -140,9 +161,12 @@ bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message,
*result = hitTestResult;
return true;
}
int offsetSize = 0;
int offsetSize;
bool isMaximum = ::IsZoomed(hwnd);
offsetXY = QPoint(abs(clientRect->left - originalLeft),abs(clientRect->top - originalTop));
auto _offsetXY = QPoint(abs(clientRect->left - originalLeft), abs(clientRect->top - originalTop));
if (_offsetXY.x() != 0) {
offsetXY = _offsetXY;
}
if (isMaximum || _isFullScreen()) {
offsetSize = 0;
} else {
@ -161,6 +185,7 @@ bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message,
*result = WVR_REDRAW;
return true;
} else if (uMsg == WM_NCHITTEST) {
if (_isWindows11OrGreater) {
if (_hitMaximizeButton()) {
if (*result == HTNOWHERE) {
*result = HTZOOM;
@ -170,6 +195,7 @@ bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message,
}
_setMaximizeHovered(false);
_setMaximizePressed(false);
}
*result = 0;
POINT nativeGlobalPos{GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
POINT nativeLocalPos = nativeGlobalPos;
@ -211,14 +237,14 @@ bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message,
}
*result = HTCLIENT;
return true;
}else if(uMsg == WM_NCLBUTTONDBLCLK || uMsg == WM_NCLBUTTONDOWN){
} else if (_isWindows11OrGreater && (uMsg == WM_NCLBUTTONDBLCLK || uMsg == WM_NCLBUTTONDOWN)) {
if (_hitMaximizeButton()) {
QMouseEvent event = QMouseEvent(QEvent::MouseButtonPress, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QGuiApplication::sendEvent(_maximizeButton, &event);
_setMaximizePressed(true);
return true;
}
}else if(uMsg == WM_NCLBUTTONUP || uMsg == WM_NCRBUTTONUP){
} else if (_isWindows11OrGreater && (uMsg == WM_NCLBUTTONUP || uMsg == WM_NCRBUTTONUP)) {
if (_hitMaximizeButton()) {
QMouseEvent event = QMouseEvent(QEvent::MouseButtonRelease, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QGuiApplication::sendEvent(_maximizeButton, &event);
@ -232,16 +258,28 @@ bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message,
*result = ::DefWindowProcW(hwnd, WM_NCACTIVATE, wParam, -1);
return true;
} else if (uMsg == WM_GETMINMAXINFO) {
MINMAXINFO* minmaxInfo = reinterpret_cast<MINMAXINFO *>(lParam);
auto *minmaxInfo = reinterpret_cast<MINMAXINFO *>(lParam);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
minmaxInfo->ptMaxPosition.x = 0;
minmaxInfo->ptMaxPosition.y = 0;
minmaxInfo->ptMaxSize.x = 0;
minmaxInfo->ptMaxSize.y = 0;
return false;
#else
auto pixelRatio = window()->devicePixelRatio();
auto geometry = window()->screen()->availableGeometry();
RECT rect;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
if(!_fixSize){
minmaxInfo->ptMinTrackSize.x = window()->minimumWidth() * pixelRatio + offsetXY.x();
minmaxInfo->ptMinTrackSize.y = window()->minimumHeight() * pixelRatio + offsetXY.y() + _appbar->height() * pixelRatio;
}
minmaxInfo->ptMaxPosition.x = rect.left - offsetXY.x();
minmaxInfo->ptMaxPosition.y = rect.top - offsetXY.x();
minmaxInfo->ptMaxSize.x = geometry.width()*pixelRatio + offsetXY.x() * 2;
minmaxInfo->ptMaxSize.y = geometry.height()*pixelRatio + offsetXY.y() * 2;
return false;
minmaxInfo->ptMaxSize.x = qRound(geometry.width() * pixelRatio) + offsetXY.x() * 2;
minmaxInfo->ptMaxSize.y = qRound(geometry.height() * pixelRatio) + offsetXY.y() * 2;
return true;
#endif
} else if (uMsg == WM_NCRBUTTONDOWN) {
if (wParam == HTCAPTION) {
_showSystemMenu(QCursor::pos());
@ -251,22 +289,25 @@ bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message,
const bool spacePressed = ((wParam == VK_SPACE) || (::GetKeyState(VK_SPACE) < 0));
if (altPressed && spacePressed) {
auto pos = window()->position();
_showSystemMenu(QPoint(pos.x(),pos.y()+_appbar->height()));
_showSystemMenu(QPoint(pos.x(), qRound(pos.y() + _appbar->height())));
}
} else if (uMsg == WM_SYSCOMMAND) {
if (wParam == SC_MINIMIZE) {
if (window()->transientParent()) {
window()->transientParent()->showMinimized();
HWND hwnd = reinterpret_cast<HWND>(window()->transientParent()->winId());
::ShowWindow(hwnd, 2);
} else {
window()->showMinimized();
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
::ShowWindow(hwnd, 2);
}
return true;
}
return false;
}
return false;
#endif
#else
return false;
#endif
}
bool FluFrameless::_isMaximized() {
@ -282,7 +323,7 @@ void FluFrameless::_showSystemMenu(QPoint point){
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
DWORD style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_SYSMENU);
const HMENU hMenu = ::GetSystemMenu(hwnd, FALSE);
auto hMenu = ::GetSystemMenu(hwnd, FALSE);
if (_isMaximized() || _isFullScreen()) {
::EnableMenuItem(hMenu, SC_MOVE, MFS_DISABLED);
::EnableMenuItem(hMenu, SC_RESTORE, MFS_ENABLED);
@ -297,7 +338,8 @@ 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)), point.x()*window()->devicePixelRatio(), point.y()*window()->devicePixelRatio(), 0, hwnd, nullptr);
const int result = ::TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), qRound(point.x() * window()->devicePixelRatio()),
qRound(point.y() * window()->devicePixelRatio()), 0, hwnd, nullptr);
if (result != FALSE) {
::PostMessageW(hwnd, WM_SYSCOMMAND, result, 0);
}
@ -305,32 +347,21 @@ void FluFrameless::_showSystemMenu(QPoint point){
#endif
}
bool FluFrameless::_containsCursorToItem(QQuickItem* item){
if(!item || !item->isVisible()){
return false;
}
auto point = QCursor::pos();
auto rect = QRectF(item->mapToGlobal(QPoint(0,0)),item->size());
if(point.x()>rect.x() && point.x()<(rect.x()+rect.width()) && point.y()>rect.y() && point.y()<(rect.y()+rect.height())){
return true;
}
return false;
}
bool FluFrameless::_hitAppBar() {
foreach (auto item, _hitTestList) {
if(_containsCursorToItem(item)){
for (int i = 0; i <= _hitTestList.size() - 1; ++i) {
auto item = _hitTestList.at(i);
if (containsCursorToItem(item)) {
return false;
}
}
if(_containsCursorToItem(_appbar)){
if (containsCursorToItem(_appbar)) {
return true;
}
return false;
}
bool FluFrameless::_hitMaximizeButton() {
if(_containsCursorToItem(_maximizeButton)){
if (containsCursorToItem(_maximizeButton)) {
return true;
}
return false;
@ -365,10 +396,12 @@ void FluFrameless::_updateCursor(int edges){
case Qt::LeftEdge | Qt::BottomEdge:
window()->setCursor(Qt::SizeBDiagCursor);
break;
default:
break;
}
}
void FluFrameless::showFullScreen(){
[[maybe_unused]] void FluFrameless::showFullScreen() {
window()->showFullScreen();
}
@ -377,16 +410,21 @@ void FluFrameless::showMaximized(){
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
::ShowWindow(hwnd, 3);
#else
window()->showMaximized();
window()->setVisibility(QQuickWindow::Maximized);
#endif
}
void FluFrameless::showMinimized(){
window()->showMinimized();
[[maybe_unused]] void FluFrameless::showMinimized() {
#ifdef Q_OS_WIN
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
::ShowWindow(hwnd, 2);
#else
window()->setVisibility(QQuickWindow::Minimized);
#endif
}
void FluFrameless::showNormal() {
window()->showNormal();
window()->setVisibility(QQuickWindow::Windowed);
}
void FluFrameless::setHitTestVisible(QQuickItem *val) {
@ -395,7 +433,6 @@ void FluFrameless::setHitTestVisible(QQuickItem* val){
}
}
void FluFrameless::_setWindowTopmost(bool topmost) {
#ifdef Q_OS_WIN
HWND hwnd = reinterpret_cast<HWND>(window()->winId());

View File

@ -1,9 +1,9 @@
#ifndef FLUFRAMELESS_H
#define FLUFRAMELESS_H
#pragma once
#include <QObject>
#include <QQuickItem>
#include <QAbstractNativeEventFilter>
#include <QQmlProperty>
#include "stdafx.h"
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
@ -15,47 +15,64 @@ using QT_ENTER_EVENT_TYPE = QEvent;
#endif
class FluFrameless : public QQuickItem,QAbstractNativeEventFilter
{
class FluFrameless : public QQuickItem, QAbstractNativeEventFilter {
Q_OBJECT
Q_PROPERTY_AUTO(QQuickItem*,appbar)
Q_PROPERTY_AUTO_P(QQuickItem*, appbar)
Q_PROPERTY_AUTO_P(QQuickItem*, maximizeButton)
Q_PROPERTY_AUTO_P(QQuickItem*, minimizedButton)
Q_PROPERTY_AUTO_P(QQuickItem*, closeButton)
Q_PROPERTY_AUTO(bool, topmost)
Q_PROPERTY_AUTO(QQuickItem*,maximizeButton)
Q_PROPERTY_AUTO(QQuickItem*,minimizedButton)
Q_PROPERTY_AUTO(QQuickItem*,closeButton)
Q_PROPERTY_AUTO(bool, disabled)
Q_PROPERTY_AUTO(bool, fixSize)
QML_NAMED_ELEMENT(FluFrameless)
public:
explicit FluFrameless(QQuickItem *parent = nullptr);
~FluFrameless();
~FluFrameless() override;
void componentComplete() override;
bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
Q_INVOKABLE void showFullScreen();
[[maybe_unused]] bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
[[maybe_unused]] Q_INVOKABLE void showFullScreen();
Q_INVOKABLE void showMaximized();
Q_INVOKABLE void showMinimized();
[[maybe_unused]] Q_INVOKABLE void showMinimized();
Q_INVOKABLE void showNormal();
Q_INVOKABLE void setHitTestVisible(QQuickItem *);
Q_INVOKABLE void onDestruction();
[[maybe_unused]] Q_INVOKABLE void onDestruction();
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
private:
bool _isFullScreen();
bool _isMaximized();
void _updateCursor(int edges);
void _setWindowTopmost(bool topmost);
void _showSystemMenu(QPoint point);
bool _containsCursorToItem(QQuickItem* item);
bool _hitAppBar();
bool _hitMaximizeButton();
void _setMaximizePressed(bool val);
void _setMaximizeHovered(bool val);
private:
qint64 _current;
quint64 _current = 0;
int _edges = 0;
int _margins = 8;
qint64 _clickTimer = 0;
quint64 _clickTimer = 0;
bool _isWindows11OrGreater = false;
QList<QPointer<QQuickItem>> _hitTestList;
};
#endif // FLUFRAMELESS_H

View File

@ -3,9 +3,9 @@
#include "qrcode/qrencode.h"
FluQrCodeItem::FluQrCodeItem(QQuickItem *parent) : QQuickPaintedItem(parent) {
color(QColor(0,0,0,255));
bgColor(QColor(255,255,255,255));
size(100);
_color = QColor(0, 0, 0, 255);
_bgColor = QColor(255, 255, 255, 255);
_size = 100;
setWidth(_size);
setHeight(_size);
connect(this, &FluQrCodeItem::textChanged, this, [=] { update(); });
@ -18,7 +18,6 @@ FluQrCodeItem::FluQrCodeItem(QQuickItem* parent):QQuickPaintedItem(parent){
});
}
void FluQrCodeItem::paint(QPainter *painter) {
if (_text.isEmpty()) {
return;
@ -28,8 +27,8 @@ void FluQrCodeItem::paint(QPainter* painter){
}
painter->save();
QRcode *qrcode = QRcode_encodeString(_text.toUtf8().constData(), 2, QR_ECLEVEL_Q, QR_MODE_8, 1);
qint32 w = width();
qint32 h = height();
auto w = qint32(width());
auto h = qint32(height());
qint32 qrcodeW = qrcode->width > 0 ? qrcode->width : 1;
double scaleX = (double) w / (double) qrcodeW;
double scaleY = (double) h / (double) qrcodeW;
@ -39,13 +38,10 @@ void FluQrCodeItem::paint(QPainter* painter){
p.setPen(Qt::NoPen);
p.drawRect(0, 0, w, h);
p.setBrush(_color);
for (qint32 y = 0; y < qrcodeW; y++)
{
for (qint32 x = 0; x < qrcodeW; x++)
{
for (qint32 y = 0; y < qrcodeW; y++) {
for (qint32 x = 0; x < qrcodeW; x++) {
unsigned char b = qrcode->data[y * qrcodeW + x];
if (b & 0x01)
{
if (b & 0x01) {
QRectF r(x * scaleX, y * scaleY, scaleX, scaleY);
p.drawRects(&r, 1);
}

View File

@ -1,5 +1,4 @@
#ifndef FLUQRCODEITEM_H
#define FLUQRCODEITEM_H
#pragma once
#include <QQuickItem>
#include <QQuickPaintedItem>
@ -9,9 +8,9 @@
/**
* @brief The FluQrCodeItem class
*/
class FluQrCodeItem : public QQuickPaintedItem
{
class FluQrCodeItem : public QQuickPaintedItem {
Q_OBJECT
Q_PROPERTY_AUTO(QString, text)
Q_PROPERTY_AUTO(QColor, color)
Q_PROPERTY_AUTO(QColor, bgColor)
@ -19,7 +18,6 @@ class FluQrCodeItem : public QQuickPaintedItem
QML_NAMED_ELEMENT(FluQrCodeItem)
public:
explicit FluQrCodeItem(QQuickItem *parent = nullptr);
void paint(QPainter *painter) override;
};
#endif // FLUQRCODEITEM_H

View File

@ -1,5 +1,4 @@
#ifndef FLURECTANGLE_H
#define FLURECTANGLE_H
#pragma once
#include <QQuickItem>
#include <QQuickPaintedItem>
@ -9,15 +8,13 @@
/**
* @brief The FluRectangle class
*/
class FluRectangle : public QQuickPaintedItem
{
class FluRectangle : public QQuickPaintedItem {
Q_OBJECT
Q_PROPERTY_AUTO(QColor, color)
Q_PROPERTY_AUTO(QList<int>, radius)
QML_NAMED_ELEMENT(FluRectangle)
public:
explicit FluRectangle(QQuickItem *parent = nullptr);
void paint(QPainter *painter) override;
};
#endif // FLURECTANGLE_H

View File

@ -2,9 +2,7 @@
#include <QJSValueList>
FluTableSortProxyModel::FluTableSortProxyModel(QSortFilterProxyModel *parent)
: QSortFilterProxyModel {parent}
{
FluTableSortProxyModel::FluTableSortProxyModel(QSortFilterProxyModel *parent) : QSortFilterProxyModel{parent} {
_model = nullptr;
connect(this, &FluTableSortProxyModel::modelChanged, this, [=] {
setSourceModel(this->model());
@ -41,7 +39,7 @@ bool FluTableSortProxyModel::lessThan(const QModelIndex &source_left, const QMod
}
}
void FluTableSortProxyModel::setComparator(QJSValue comparator){
[[maybe_unused]] void FluTableSortProxyModel::setComparator(const QJSValue &comparator) {
int column = 0;
if (comparator.isUndefined()) {
column = -1;
@ -54,22 +52,22 @@ void FluTableSortProxyModel::setComparator(QJSValue comparator){
}
}
void FluTableSortProxyModel::setFilter(QJSValue filter){
[[maybe_unused]] void FluTableSortProxyModel::setFilter(const QJSValue &filter) {
this->_filter = filter;
invalidateFilter();
}
QVariant FluTableSortProxyModel::getRow(int rowIndex){
[[maybe_unused]] QVariant FluTableSortProxyModel::getRow(int rowIndex) {
QVariant result;
QMetaObject::invokeMethod(_model, "getRow", Q_RETURN_ARG(QVariant, result), Q_ARG(int, mapToSource(index(rowIndex, 0)).row()));
return result;
}
void FluTableSortProxyModel::setRow(int rowIndex,QVariant val){
[[maybe_unused]] void FluTableSortProxyModel::setRow(int rowIndex, const QVariant &val) {
QMetaObject::invokeMethod(_model, "setRow", Q_ARG(int, mapToSource(index(rowIndex, 0)).row()), Q_ARG(QVariant, val));
}
void FluTableSortProxyModel::removeRow(int rowIndex,int rows){
[[maybe_unused]] void FluTableSortProxyModel::removeRow(int rowIndex, int rows) {
QMetaObject::invokeMethod(_model, "removeRow", Q_ARG(int, mapToSource(index(rowIndex, 0)).row()), Q_ARG(int, rows));
}

View File

@ -1,5 +1,4 @@
#ifndef FLUTABLESORTPROXYMODEL_H
#define FLUTABLESORTPROXYMODEL_H
#pragma once
#include <QSortFilterProxyModel>
#include <QAbstractTableModel>
@ -7,24 +6,30 @@
#include <QJSValue>
#include "stdafx.h"
class FluTableSortProxyModel : public QSortFilterProxyModel
{
class FluTableSortProxyModel : public QSortFilterProxyModel {
Q_OBJECT
Q_PROPERTY_AUTO(QAbstractTableModel*,model)
Q_PROPERTY_AUTO_P(QAbstractTableModel*, model)
QML_NAMED_ELEMENT(FluTableSortProxyModel)
public:
explicit FluTableSortProxyModel(QSortFilterProxyModel *parent = nullptr);
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
bool filterAcceptsColumn(int sourceColumn, const QModelIndex &sourceParent) const override;
bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override;
Q_INVOKABLE QVariant getRow(int rowIndex);
Q_INVOKABLE void setRow(int rowIndex,QVariant val);
Q_INVOKABLE void removeRow(int rowIndex,int rows);
Q_INVOKABLE void setComparator(QJSValue comparator);
Q_INVOKABLE void setFilter(QJSValue filter);
[[maybe_unused]] Q_INVOKABLE QVariant getRow(int rowIndex);
[[maybe_unused]] Q_INVOKABLE void setRow(int rowIndex, const QVariant &val);
[[maybe_unused]] Q_INVOKABLE void removeRow(int rowIndex, int rows);
[[maybe_unused]] Q_INVOKABLE void setComparator(const QJSValue &comparator);
[[maybe_unused]] Q_INVOKABLE void setFilter(const QJSValue &filter);
private:
QJSValue _filter;
QJSValue _comparator;
};
#endif // FLUTABLESORTPROXYMODEL_H

View File

@ -1,5 +1,4 @@
#ifndef FLUTEXTSTYLE_H
#define FLUTEXTSTYLE_H
#pragma once
#include <QObject>
#include <QtQml/qqml.h>
@ -10,8 +9,7 @@
/**
* @brief The FluTextStyle class
*/
class FluTextStyle : public QObject
{
class FluTextStyle : public QObject {
Q_OBJECT
public:
Q_PROPERTY_AUTO(QString, family)
@ -24,11 +22,12 @@ public:
Q_PROPERTY_AUTO(QFont, Display);
QML_NAMED_ELEMENT(FluTextStyle)
QML_SINGLETON
private:
explicit FluTextStyle(QObject *parent = nullptr);
public:
SINGLETON(FluTextStyle)
static FluTextStyle *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
};
#endif // FLUTEXTSTYLE_H
static FluTextStyle *create(QQmlEngine *, QJSEngine *) { return getInstance(); }
};

View File

@ -2,21 +2,38 @@
#include <QGuiApplication>
#include <QPalette>
#include <QImage>
#include <QThreadPool>
#include "Def.h"
#include "FluColors.h"
#include "FluTools.h"
bool systemDark() {
QPalette palette = QGuiApplication::palette();
QColor color = palette.color(QPalette::Window).rgb();
return color.red() * 0.2126 + color.green() * 0.7152 + color.blue() * 0.0722 <= 255.0f / 2;
}
FluTheme::FluTheme(QObject *parent) : QObject{parent} {
_accentColor = FluColors::getInstance()->Blue();
_darkMode = FluThemeType::DarkMode::Light;
_nativeText = false;
_animationEnabled = true;
_systemDark = systemDark();
_desktopImagePath = "";
_blurBehindWindowEnabled = false;
QGuiApplication::instance()->installEventFilter(this);
refreshColors();
connect(this, &FluTheme::darkModeChanged, this, [=] {
Q_EMIT darkChanged();
});
connect(this, &FluTheme::darkChanged, this, [=] { refreshColors(); });
connect(this, &FluTheme::accentColorChanged, this, [=] { refreshColors(); });
accentColor(FluColors::getInstance()->Blue());
darkMode(FluThemeType::DarkMode::Light);
nativeText(false);
animationEnabled(true);
_systemDark = systemDark();
qApp->installEventFilter(this);
connect(&_watcher, &QFileSystemWatcher::fileChanged, this, [=](const QString &path){
Q_EMIT desktopImagePathChanged();
});
connect(this, &FluTheme::blurBehindWindowEnabledChanged, this, [=] {checkUpdateDesktopImage();});
startTimer(1000);
}
void FluTheme::refreshColors() {
@ -30,15 +47,15 @@ void FluTheme::refreshColors(){
fontSecondaryColor(isDark ? QColor(222, 222, 222, 255) : QColor(102, 102, 102, 255));
fontTertiaryColor(isDark ? QColor(200, 200, 200, 255) : QColor(153, 153, 153, 255));
itemNormalColor(isDark ? QColor(255, 255, 255, 0) : QColor(0, 0, 0, 0));
itemHoverColor(isDark ? QColor(255,255,255,255*0.06) : QColor(0,0,0,255*0.03));
itemPressColor(isDark ? QColor(255,255,255,255*0.09) : QColor(0,0,0,255*0.06));
itemCheckColor(isDark ? QColor(255,255,255,255*0.12) : QColor(0,0,0,255*0.09));
frameColor(isDark ? QColor(56, 56, 56, qRound(255 * 0.8)) : QColor(233, 233, 233, qRound(255 * 0.8)));
frameActiveColor(isDark ? QColor(48, 48, 48, qRound(255 * 0.8)) : QColor(255, 255, 255, qRound(255 * 0.8)));
itemHoverColor(isDark ? QColor(255, 255, 255, qRound(255 * 0.06)) : QColor(0, 0, 0, qRound(255 * 0.03)));
itemPressColor(isDark ? QColor(255, 255, 255, qRound(255 * 0.09)) : QColor(0, 0, 0, qRound(255 * 0.06)));
itemCheckColor(isDark ? QColor(255, 255, 255, qRound(255 * 0.12)) : QColor(0, 0, 0, qRound(255 * 0.09)));
}
bool FluTheme::eventFilter(QObject *obj, QEvent *event){
Q_UNUSED(obj);
if (event->type() == QEvent::ApplicationPaletteChange || event->type() == QEvent::ThemeChange)
{
bool FluTheme::eventFilter(QObject *, QEvent *event) {
if (event->type() == QEvent::ApplicationPaletteChange || event->type() == QEvent::ThemeChange) {
_systemDark = systemDark();
Q_EMIT darkChanged();
event->accept();
@ -47,36 +64,35 @@ bool FluTheme::eventFilter(QObject *obj, QEvent *event){
return false;
}
QJsonArray FluTheme::awesomeList(const QString& keyword){
QJsonArray arr;
QMetaEnum enumType = Fluent_Awesome::staticMetaObject.enumerator(Fluent_Awesome::staticMetaObject.indexOfEnumerator("Fluent_AwesomeType"));
for(int i=0; i < enumType.keyCount(); ++i){
QString name = enumType.key(i);
int icon = enumType.value(i);
if(keyword.isEmpty() || name.contains(keyword)){
QJsonObject obj;
obj.insert("name",name);
obj.insert("icon",icon);
arr.append(obj);
}
}
return arr;
}
bool FluTheme::systemDark(){
QPalette palette = qApp->palette();
QColor color = palette.color(QPalette::Window).rgb();
return !(color.red() * 0.2126 + color.green() * 0.7152 + color.blue() * 0.0722 > 255 / 2);
}
bool FluTheme::dark(){
bool FluTheme::dark() const {
if (_darkMode == FluThemeType::DarkMode::Dark) {
return true;
}else if(_darkMode == FluThemeType::DarkMode::Light){
return false;
} else if (_darkMode == FluThemeType::DarkMode::System) {
return _systemDark;
} else {
return false;
}
}
void FluTheme::checkUpdateDesktopImage(){
if(!_blurBehindWindowEnabled){
return;
}
QThreadPool::globalInstance()->start([=]() {
_mutex.lock();
auto path = FluTools::getInstance()->getWallpaperFilePath();
if(_desktopImagePath != path){
if(!_desktopImagePath.isEmpty()){
_watcher.removePath(_desktopImagePath);
}
desktopImagePath(path);
_watcher.addPath(path);
}
_mutex.unlock();
});
}
void FluTheme::timerEvent(QTimerEvent *event)
{
checkUpdateDesktopImage();
}

View File

@ -6,6 +6,9 @@
#include <QJsonArray>
#include <QJsonObject>
#include <QColor>
#include <QTimer>
#include <QFileSystemWatcher>
#include <QMutex>
#include "FluAccentColor.h"
#include "stdafx.h"
#include "singleton.h"
@ -13,11 +16,10 @@
/**
* @brief The FluTheme class
*/
class FluTheme : public QObject
{
class FluTheme : public QObject {
Q_OBJECT
Q_PROPERTY(bool dark READ dark NOTIFY darkChanged)
Q_PROPERTY_AUTO(FluAccentColor*,accentColor);
Q_PROPERTY_AUTO_P(FluAccentColor*, accentColor);
Q_PROPERTY_AUTO(QColor, primaryColor);
Q_PROPERTY_AUTO(QColor, backgroundColor);
Q_PROPERTY_AUTO(QColor, dividerColor);
@ -27,27 +29,47 @@ class FluTheme : public QObject
Q_PROPERTY_AUTO(QColor, fontSecondaryColor);
Q_PROPERTY_AUTO(QColor, fontTertiaryColor);
Q_PROPERTY_AUTO(QColor, itemNormalColor);
Q_PROPERTY_AUTO(QColor, frameColor);
Q_PROPERTY_AUTO(QColor, frameActiveColor);
Q_PROPERTY_AUTO(QColor, itemHoverColor);
Q_PROPERTY_AUTO(QColor, itemPressColor);
Q_PROPERTY_AUTO(QColor, itemCheckColor);
Q_PROPERTY_AUTO(QString, desktopImagePath);
Q_PROPERTY_AUTO(int, darkMode);
Q_PROPERTY_AUTO(bool, nativeText);
Q_PROPERTY_AUTO(bool, animationEnabled);
Q_PROPERTY_AUTO(bool, blurBehindWindowEnabled);
QML_NAMED_ELEMENT(FluTheme)
QML_SINGLETON
private:
explicit FluTheme(QObject *parent = nullptr);
bool eventFilter(QObject *obj, QEvent *event);
bool systemDark();
bool eventFilter(QObject *obj, QEvent *event) override;
void refreshColors();
void updateBackgroundMainColor();
protected:
void timerEvent(QTimerEvent *event) override;
void checkUpdateDesktopImage();
public:
SINGLETON(FluTheme)
Q_INVOKABLE QJsonArray awesomeList(const QString& keyword = "");
Q_SIGNAL void darkChanged();
static FluTheme *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
bool dark();
static FluTheme *create(QQmlEngine *, QJSEngine *) { return getInstance(); }
bool dark() const;
private:
bool _systemDark;
QFileSystemWatcher _watcher;
QMutex _mutex;
};
#endif // FLUTHEME_H

View File

@ -16,6 +16,14 @@
#include <QDateTime>
#include <QSettings>
#ifdef Q_OS_WIN
#pragma comment (lib, "user32.lib")
#include <windows.h>
#include <windowsx.h>
#endif
FluTools::FluTools(QObject *parent) : QObject{parent} {
}
@ -75,21 +83,20 @@ int FluTools::qtMinor(){
}
void FluTools::setQuitOnLastWindowClosed(bool val) {
qApp->setQuitOnLastWindowClosed(val);
QGuiApplication::setQuitOnLastWindowClosed(val);
}
void FluTools::setOverrideCursor(Qt::CursorShape shape) {
qApp->setOverrideCursor(QCursor(shape));
QGuiApplication::setOverrideCursor(QCursor(shape));
}
void FluTools::restoreOverrideCursor() {
qApp->restoreOverrideCursor();
QGuiApplication::restoreOverrideCursor();
}
void FluTools::deleteLater(QObject *p) {
if (p) {
p->deleteLater();
p = nullptr;
}
}
@ -108,11 +115,11 @@ QString FluTools::html2PlantText(const QString& html){
}
QRect FluTools::getVirtualGeometry() {
return qApp->primaryScreen()->virtualGeometry();
return QGuiApplication::primaryScreen()->virtualGeometry();
}
QString FluTools::getApplicationDirPath() {
return qApp->applicationDirPath();
return QGuiApplication::applicationDirPath();
}
QUrl FluTools::getUrlByFilePath(const QString &path) {
@ -124,33 +131,33 @@ QColor FluTools::withOpacity(const QColor& color,qreal opacity){
return QColor::fromRgba((alpha << 24) | (color.rgba() & 0xffffff));
}
QString FluTools::md5(QString text){
QString FluTools::md5(const QString &text) {
return QCryptographicHash::hash(text.toUtf8(), QCryptographicHash::Md5).toHex();
}
QString FluTools::toBase64(QString text){
QString FluTools::toBase64(const QString &text) {
return text.toUtf8().toBase64();
}
QString FluTools::fromBase64(QString text){
QString FluTools::fromBase64(const QString &text) {
return QByteArray::fromBase64(text.toUtf8());
}
bool FluTools::removeDir(QString dirPath){
bool FluTools::removeDir(const QString &dirPath) {
QDir qDir(dirPath);
return qDir.removeRecursively();
}
bool FluTools::removeFile(QString filePath){
bool FluTools::removeFile(const QString &filePath) {
QFile file(filePath);
return file.remove();
}
QString FluTools::sha256(QString text){
QString FluTools::sha256(const QString &text) {
return QCryptographicHash::hash(text.toUtf8(), QCryptographicHash::Sha256).toHex();
}
void FluTools::showFileInFolder(QString path){
void FluTools::showFileInFolder(const QString &path) {
#if defined(Q_OS_WIN)
QProcess::startDetached("explorer.exe", {"/select,", QDir::toNativeSeparators(path)});
#endif
@ -184,11 +191,11 @@ QIcon FluTools::windowIcon(){
int FluTools::cursorScreenIndex() {
int screenIndex = 0;
int screenCount = qApp->screens().count();
int screenCount = QGuiApplication::screens().count();
if (screenCount > 1) {
QPoint pos = QCursor::pos();
for (int i = 0; i < screenCount; ++i) {
if (qApp->screens().at(i)->geometry().contains(pos)) {
for (int i = 0; i <= screenCount - 1; ++i) {
if (QGuiApplication::screens().at(i)->geometry().contains(pos)) {
screenIndex = i;
break;
}
@ -199,7 +206,7 @@ int FluTools::cursorScreenIndex(){
int FluTools::windowBuildNumber() {
#if defined(Q_OS_WIN)
QSettings regKey {QString::fromUtf8("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), QSettings::NativeFormat};
QSettings regKey{QString::fromUtf8(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion)"), QSettings::NativeFormat};
if (regKey.contains(QString::fromUtf8("CurrentBuildNumber"))) {
auto buildNumber = regKey.value(QString::fromUtf8("CurrentBuildNumber")).toInt();
return buildNumber;
@ -245,3 +252,66 @@ bool FluTools::isWindows10OrGreater(){
QRect FluTools::desktopAvailableGeometry(QQuickWindow *window) {
return window->screen()->availableGeometry();
}
QString FluTools::getWallpaperFilePath() {
#if defined(Q_OS_WIN)
wchar_t path[MAX_PATH] = {};
if (::SystemParametersInfoW(SPI_GETDESKWALLPAPER, MAX_PATH, path, FALSE) == FALSE) {
return {};
}
return QString::fromWCharArray(path);
#elif defined(Q_OS_LINUX)
auto type = QSysInfo::productType();
if (type == "uos") {
QProcess process;
QStringList args;
args << "--session";
args << "--type=method_call";
args << "--print-reply";
args << "--dest=com.deepin.wm";
args << "/com/deepin/wm";
args << "com.deepin.wm.GetCurrentWorkspaceBackgroundForMonitor";
args << QString("string:'%1'").arg(currentTimestamp());
process.start("dbus-send", args);
process.waitForFinished();
QByteArray result = process.readAllStandardOutput().trimmed();
int startIndex = result.indexOf("file:///");
if (startIndex != -1) {
auto path = result.mid(startIndex + 7, result.length() - startIndex - 8);
return path;
}
}
#elif defined(Q_OS_MACOS)
QProcess process;
QStringList args;
args << "-e";
args << R"(tell application "Finder" to get POSIX path of (desktop picture as alias))";
process.start("osascript", args);
process.waitForFinished();
QByteArray result = process.readAllStandardOutput().trimmed();
if(result.isEmpty()){
return "/System/Library/CoreServices/DefaultDesktop.heic";
}
return result;
#else
return {};
#endif
}
QColor FluTools::imageMainColor(const QImage &image, double bright) {
int step = 20;
int t = 0;
int r = 0, g = 0, b = 0;
for (int i = 0; i < image.width(); i += step) {
for (int j = 0; j < image.height(); j += step) {
if (image.valid(i, j)) {
t++;
QColor c = image.pixel(i, j);
r += c.red();
b += c.blue();
g += c.green();
}
}
}
return QColor(int(bright * r / t) > 255 ? 255 : int(bright * r / t), int(bright * g / t) > 255 ? 255 : int(bright * g / t), int(bright * b / t) > 255 ? 255 : int(bright * b / t));
}

View File

@ -1,5 +1,4 @@
#ifndef FLUTOOLS_H
#define FLUTOOLS_H
#pragma once
#include <QObject>
#include <QFile>
@ -11,51 +10,90 @@
/**
* @brief The FluTools class
*/
class FluTools : public QObject
{
class FluTools : public QObject {
Q_OBJECT
QML_NAMED_ELEMENT(FluTools)
QML_SINGLETON
private:
explicit FluTools(QObject *parent = nullptr);
public:
SINGLETON(FluTools)
static FluTools *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
Q_INVOKABLE int qtMajor();
Q_INVOKABLE int qtMinor();
Q_INVOKABLE bool isMacos();
Q_INVOKABLE bool isLinux();
Q_INVOKABLE bool isWin();
Q_INVOKABLE void clipText(const QString& text);
Q_INVOKABLE QString uuid();
Q_INVOKABLE QString readFile(const QString& fileName);
Q_INVOKABLE void setQuitOnLastWindowClosed(bool val);
Q_INVOKABLE void setOverrideCursor(Qt::CursorShape shape);
Q_INVOKABLE void restoreOverrideCursor();
Q_INVOKABLE QString html2PlantText(const QString& html);
Q_INVOKABLE QString toLocalPath(const QUrl& url);
Q_INVOKABLE void deleteLater(QObject *p);
Q_INVOKABLE QString getFileNameByUrl(const QUrl& url);
Q_INVOKABLE QRect getVirtualGeometry();
Q_INVOKABLE QString getApplicationDirPath();
Q_INVOKABLE QUrl getUrlByFilePath(const QString& path);
Q_INVOKABLE QColor withOpacity(const QColor&,qreal alpha);
Q_INVOKABLE QString md5(QString text);
Q_INVOKABLE QString sha256(QString text);
Q_INVOKABLE QString toBase64(QString text);
Q_INVOKABLE QString fromBase64(QString text);
Q_INVOKABLE bool removeDir(QString dirPath);
Q_INVOKABLE bool removeFile(QString filePath);
Q_INVOKABLE void showFileInFolder(QString path);
Q_INVOKABLE bool isSoftware();
Q_INVOKABLE qint64 currentTimestamp();
Q_INVOKABLE QPoint cursorPos();
Q_INVOKABLE QIcon windowIcon();
Q_INVOKABLE int cursorScreenIndex();
Q_INVOKABLE int windowBuildNumber();
Q_INVOKABLE bool isWindows11OrGreater();
Q_INVOKABLE bool isWindows10OrGreater();
Q_INVOKABLE QRect desktopAvailableGeometry(QQuickWindow* window);
};
#endif // FLUTOOLS_H
static FluTools *create(QQmlEngine *, QJSEngine *) { return getInstance(); }
Q_INVOKABLE int qtMajor();
Q_INVOKABLE int qtMinor();
Q_INVOKABLE bool isMacos();
Q_INVOKABLE bool isLinux();
Q_INVOKABLE bool isWin();
Q_INVOKABLE void clipText(const QString &text);
Q_INVOKABLE QString uuid();
Q_INVOKABLE QString readFile(const QString &fileName);
Q_INVOKABLE void setQuitOnLastWindowClosed(bool val);
Q_INVOKABLE void setOverrideCursor(Qt::CursorShape shape);
Q_INVOKABLE void restoreOverrideCursor();
Q_INVOKABLE QString html2PlantText(const QString &html);
Q_INVOKABLE QString toLocalPath(const QUrl &url);
Q_INVOKABLE void deleteLater(QObject *p);
Q_INVOKABLE QString getFileNameByUrl(const QUrl &url);
Q_INVOKABLE QRect getVirtualGeometry();
Q_INVOKABLE QString getApplicationDirPath();
Q_INVOKABLE QUrl getUrlByFilePath(const QString &path);
Q_INVOKABLE QColor withOpacity(const QColor &, qreal alpha);
Q_INVOKABLE QString md5(const QString &text);
Q_INVOKABLE QString sha256(const QString &text);
Q_INVOKABLE QString toBase64(const QString &text);
Q_INVOKABLE QString fromBase64(const QString &text);
Q_INVOKABLE bool removeDir(const QString &dirPath);
Q_INVOKABLE bool removeFile(const QString &filePath);
Q_INVOKABLE void showFileInFolder(const QString &path);
Q_INVOKABLE bool isSoftware();
Q_INVOKABLE qint64 currentTimestamp();
Q_INVOKABLE QPoint cursorPos();
Q_INVOKABLE QIcon windowIcon();
Q_INVOKABLE int cursorScreenIndex();
Q_INVOKABLE int windowBuildNumber();
Q_INVOKABLE bool isWindows11OrGreater();
Q_INVOKABLE bool isWindows10OrGreater();
Q_INVOKABLE QRect desktopAvailableGeometry(QQuickWindow *window);
Q_INVOKABLE QString getWallpaperFilePath();
Q_INVOKABLE QColor imageMainColor(const QImage& image, double bright = 1);
};

View File

@ -1,49 +1,55 @@
#include "FluTreeModel.h"
#include <QMetaEnum>
#include <utility>
FluTreeNode::FluTreeNode(QObject *parent) : QObject{parent} {
}
FluTreeModel::FluTreeModel(QObject *parent) : QAbstractItemModel{parent} {
dataSourceSize(0);
_dataSourceSize = 0;
}
QModelIndex FluTreeModel::parent(const QModelIndex &child) const {
return QModelIndex();
return {};
}
QModelIndex FluTreeModel::index(int row, int column, const QModelIndex &parent) const {
if (!hasIndex(row, column, parent) || parent.isValid())
return QModelIndex();
return {};
return createIndex(row, column, _rows.at(row));
}
int FluTreeModel::rowCount(const QModelIndex &parent) const {
return _rows.count();
};
}
int FluTreeModel::columnCount(const QModelIndex &parent) const {
return 1;;
};
return this->_columnSource.size();
}
QVariant FluTreeModel::data(const QModelIndex &index, int role) const {
switch (role) {
case Qt::DisplayRole:
case TreeModelRoles::RowModel:
return QVariant::fromValue(_rows.at(index.row()));
case TreeModelRoles::ColumnModel:
return QVariant::fromValue(_columnSource.at(index.column()));
default:
break;
}
return QVariant();
};
return {};
}
QHash<int, QByteArray> FluTreeModel::roleNames() const {
return { {Qt::DisplayRole, "dataModel"} };
return {
{TreeModelRoles::RowModel, "rowModel"},
{TreeModelRoles::ColumnModel, "columnModel"}
};
}
void FluTreeModel::setData(QList<FluTreeNode *> data) {
beginResetModel();
_rows = data;
_rows = std::move(data);
endResetModel();
}
@ -59,9 +65,9 @@ void FluTreeModel::removeRows(int row,int count){
endRemoveRows();
}
void FluTreeModel::insertRows(int row,QList<FluTreeNode*> data){
if (row < 0 || row > _rows.size() || data.size() == 0)
return;;
void FluTreeModel::insertRows(int row, const QList<FluTreeNode *> &data) {
if (row < 0 || row > _rows.size() || data.empty())
return;
beginInsertRows(QModelIndex(), row, row + data.size() - 1);
QList<FluTreeNode *> firstPart = _rows.mid(0, row);
QList<FluTreeNode *> secondPart = _rows.mid(row);
@ -76,6 +82,11 @@ QObject* FluTreeModel::getRow(int row){
return _rows.at(row);
}
void FluTreeModel::setRow(int row, QVariantMap data) {
_rows.at(row)->_data = std::move(data);
Q_EMIT dataChanged(index(row, 0), index(row, columnCount() - 1));
}
void FluTreeModel::checkRow(int row, bool checked) {
auto itemData = _rows.at(row);
if (itemData->hasChildren()) {
@ -102,15 +113,7 @@ void FluTreeModel::checkRow(int row,bool checked){
itemData->_checked = checked;
}
Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, 0));
QList<FluTreeNode*> data;
foreach (auto item, _dataSource) {
if(!item->hasChildren()){
if(item->_checked){
data.append(item);
}
}
}
selectionModel(data);
}
void FluTreeModel::setDataSource(QList<QMap<QString, QVariant>> data) {
@ -124,11 +127,10 @@ void FluTreeModel::setDataSource(QList<QMap<QString,QVariant>> data){
while (data.count() > 0) {
auto item = data.at(data.count() - 1);
data.pop_back();
FluTreeNode* node = new FluTreeNode(this);
node->_title = item.value("title").toString();
node->_key = item.value("key").toString();
auto *node = new FluTreeNode(this);
node->_depth = item.value("__depth").toInt();
node->_parent = item.value("__parent").value<FluTreeNode *>();
node->_data = item;
node->_isExpanded = true;
if (node->_parent) {
node->_parent->_children.append(node);
@ -141,9 +143,9 @@ void FluTreeModel::setDataSource(QList<QMap<QString,QVariant>> data){
QList<QVariant> children = item.value("children").toList();
if (!children.isEmpty()) {
std::reverse(children.begin(), children.end());
for (int i = 0; i < children.count(); ++i) {
for (int i = 0; i <= children.count() - 1; ++i) {
auto child = children.at(i).toMap();
child.insert("__depth",item.value("__depth").toInt(0)+1);
child.insert("__depth", item.value("__depth").toInt(nullptr) + 1);
child.insert("__parent", QVariant::fromValue(node));
data.append(child);
}
@ -201,110 +203,6 @@ void FluTreeModel::expand(int row){
insertRows(row + 1, insertData);
}
void FluTreeModel::dragAndDrop(int dragIndex,int dropIndex,bool isDropTopArea){
if(dropIndex>_rows.count() || dropIndex<0){
return;
}
auto dragItem = _rows[dragIndex];
auto dropItem = _rows[dropIndex];
int targetIndex;
if(dropIndex > dragIndex){
if(isDropTopArea){
targetIndex = dropIndex;
}else{
targetIndex = dropIndex+1;
}
}else{
if(isDropTopArea){
targetIndex = dropIndex;
}else{
targetIndex = dropIndex+1;
}
}
if (!beginMoveRows(QModelIndex(), dragIndex, dragIndex, QModelIndex(), targetIndex)) {
return;
}
if(dropIndex > dragIndex){
if(isDropTopArea){
targetIndex = dropIndex-1;
}else{
targetIndex = dropIndex;
}
}else{
if(isDropTopArea){
targetIndex = dropIndex;
}else{
targetIndex = dropIndex+1;
}
}
_rows.move(dragIndex,targetIndex);
endMoveRows();
Q_EMIT layoutAboutToBeChanged();
if(dragItem->_parent == dropItem->_parent){
QList<FluTreeNode*>* children = &(dragItem->_parent->_children);
int srcIndex = children->indexOf(dragItem);
int destIndex = children->indexOf(dropItem);
if(dropIndex > dragIndex){
if(isDropTopArea){
targetIndex = destIndex-1;
}else{
targetIndex = destIndex;
}
}else{
if(isDropTopArea){
targetIndex = destIndex;
}else{
targetIndex = destIndex+1;
}
}
children->move(srcIndex,targetIndex);
}else{
QList<FluTreeNode*>* srcChildren = &(dragItem->_parent->_children);
QList<FluTreeNode*>* destChildren = &(dropItem->_parent->_children);
int srcIndex = srcChildren->indexOf(dragItem);
int destIndex = destChildren->indexOf(dropItem);
dragItem->_depth = dropItem->_depth;
dragItem->_parent = dropItem->_parent;
if(dragItem->hasChildren()){
QList<FluTreeNode*> stack = dragItem->_children;
foreach (auto node, stack) {
node->_depth = dragItem->_depth+1;
}
std::reverse(stack.begin(), stack.end());
while (stack.count() > 0) {
auto item = stack.at(stack.count()-1);
stack.pop_back();
QList<FluTreeNode*> children = item->_children;
if(!children.isEmpty()){
std::reverse(children.begin(), children.end());
foreach (auto c, children) {
c->_depth = item->_depth+1;
stack.append(c);
}
}
}
}
srcChildren->removeAt(srcIndex);
if(dropIndex > dragIndex){
if(isDropTopArea){
targetIndex = destIndex;
}else{
targetIndex = destIndex + 1;
}
}else{
if(isDropTopArea){
targetIndex = destIndex;
}else{
targetIndex = destIndex + 1;
}
}
destChildren->insert(targetIndex,dragItem);
}
changePersistentIndex(index(qMin(dragIndex,dropIndex),0),index(qMax(dragIndex,dropIndex),0));
Q_EMIT dataChanged(index(0,0),index(rowCount()-1,0));
}
bool FluTreeModel::hitHasChildrenExpanded(int row) {
auto itemData = _rows.at(row);
if (itemData->hasChildren() && itemData->_isExpanded) {
@ -315,7 +213,7 @@ bool FluTreeModel::hitHasChildrenExpanded(int row){
void FluTreeModel::refreshNode(int row) {
Q_EMIT dataChanged(index(row, 0), index(row, 0));
};
}
FluTreeNode *FluTreeModel::getNode(int row) {
return _rows.at(row);
@ -344,6 +242,7 @@ void FluTreeModel::allExpand(){
_rows = data;
endResetModel();
}
void FluTreeModel::allCollapse() {
beginResetModel();
QList<FluTreeNode *> stack = _root->_children;
@ -365,3 +264,13 @@ void FluTreeModel::allCollapse(){
_rows = _root->_children;
endResetModel();
}
QVariant FluTreeModel::selectionModel(){
QList<FluTreeNode *> data;
foreach (auto item, _dataSource) {
if (item->checked()) {
data.append(item);
}
}
return QVariant::fromValue(data);
}

View File

@ -1,9 +1,9 @@
#ifndef FLUTREEMODEL_H
#define FLUTREEMODEL_H
#pragma once
#include <QObject>
#include <QAbstractTableModel>
#include <QJsonArray>
#include <QVariant>
#include <QtQml/qqml.h>
#include "stdafx.h"
@ -12,21 +12,24 @@
*/
class FluTreeNode : public QObject {
Q_OBJECT
Q_PROPERTY(QString key READ key CONSTANT)
Q_PROPERTY(QString title READ title CONSTANT)
Q_PROPERTY(QVariantMap data READ data CONSTANT)
Q_PROPERTY(int depth READ depth CONSTANT)
Q_PROPERTY(bool isExpanded READ isExpanded CONSTANT)
Q_PROPERTY(bool checked READ checked CONSTANT)
public:
explicit FluTreeNode(QObject *parent = nullptr);
Q_INVOKABLE QString key(){return _key;};
Q_INVOKABLE QString title(){return _title;};
Q_INVOKABLE int depth(){return _depth;};
Q_INVOKABLE bool isExpanded(){return _isExpanded;};
Q_INVOKABLE bool hasChildren(){ return !_children.isEmpty();};
[[nodiscard]] Q_INVOKABLE int depth() const { return _depth; };
[[nodiscard]] Q_INVOKABLE bool isExpanded() const { return _isExpanded; };
[[nodiscard]] Q_INVOKABLE QVariantMap data() const { return _data; };
[[nodiscard]] Q_INVOKABLE bool hasChildren() const { return !_children.isEmpty(); };
Q_INVOKABLE bool hasNextNodeByIndex(int index) {
FluTreeNode *p = this;
for(int i=0;i<(_depth - index -1);i++){
for (int i = 0; i <= _depth - index - 1; i++) {
p = p->_parent;
}
if (p->_parent->_children.indexOf(p) == p->_parent->_children.count() - 1) {
@ -34,18 +37,20 @@ public:
}
return true;
}
Q_INVOKABLE bool checked(){
[[nodiscard]] Q_INVOKABLE bool checked() const {
if (!hasChildren()) {
return _checked;
}
foreach (auto item, _children) {
for (int i = 0; i <= _children.size() - 1; ++i) {
auto item = _children.at(i);
if (!item->checked()) {
return false;
}
}
return true;
};
Q_INVOKABLE bool hideLineFooter() {
if (_parent) {
auto childIndex = _parent->_children.indexOf(this);
@ -59,7 +64,8 @@ public:
}
return false;
};
bool isShown(){
[[nodiscard]] bool isShown() const {
auto p = _parent;
while (p) {
if (!p->_isExpanded) {
@ -69,50 +75,75 @@ public:
}
return true;
}
public:
QString _key="";
QString _title = "";
int _depth = 0;
bool _checked = false;
bool _isExpanded = true;
QVariantMap _data;
QList<FluTreeNode *> _children;
FluTreeNode *_parent = nullptr;
};
class FluTreeModel : public QAbstractItemModel
{
class FluTreeModel : public QAbstractItemModel {
Q_OBJECT
Q_PROPERTY_AUTO(int, dataSourceSize)
Q_PROPERTY_AUTO(QList<FluTreeNode*>,selectionModel)
Q_PROPERTY_AUTO(QList<QVariantMap>, columnSource)
QML_NAMED_ELEMENT(FluTreeModel)
QML_ADDED_IN_MINOR_VERSION(1)
public:
enum TreeModelRoles {
RowModel = 0x0101,
ColumnModel = 0x0102
};
explicit FluTreeModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
QModelIndex parent(const QModelIndex &child) const override;
QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const override;
[[nodiscard]] int rowCount(const QModelIndex &parent = {}) const override;
[[nodiscard]] int columnCount(const QModelIndex &parent = {}) const override;
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
[[nodiscard]] QModelIndex parent(const QModelIndex &child) const override;
[[nodiscard]] QModelIndex index(int row, int column, const QModelIndex &parent = {}) const override;
Q_INVOKABLE void removeRows(int row, int count);
Q_INVOKABLE void insertRows(int row,QList<FluTreeNode*> data);
Q_INVOKABLE void insertRows(int row, const QList<FluTreeNode *> &data);
Q_INVOKABLE QObject *getRow(int row);
Q_INVOKABLE void setRow(int row, QVariantMap data);
Q_INVOKABLE void setData(QList<FluTreeNode *> data);
Q_INVOKABLE void setDataSource(QList<QMap<QString, QVariant>> data);
Q_INVOKABLE void collapse(int row);
Q_INVOKABLE void expand(int row);
Q_INVOKABLE void dragAndDrop(int dragIndex,int dropIndex,bool isDropTopArea);
Q_INVOKABLE FluTreeNode *getNode(int row);
Q_INVOKABLE void refreshNode(int row);
Q_INVOKABLE void checkRow(int row, bool checked);
Q_INVOKABLE bool hitHasChildrenExpanded(int row);
Q_INVOKABLE void allExpand();
Q_INVOKABLE void allCollapse();
Q_INVOKABLE QVariant selectionModel();
private:
QList<FluTreeNode *> _rows;
QList<FluTreeNode *> _dataSource;
FluTreeNode *_root = nullptr;
};
#endif // FLUTREEMODEL_H

View File

@ -1,12 +1,14 @@
#include "FluWatermark.h"
#include "FluTextStyle.h"
FluWatermark::FluWatermark(QQuickItem *parent) : QQuickPaintedItem(parent) {
gap(QPoint(100,100));
offset(QPoint(_gap.x()/2,_gap.y()/2));
rotate(22);
_gap = QPoint(100, 100);
_offset = QPoint(_gap.x() / 2, _gap.y() / 2);
_rotate = 22;
_textColor = QColor(222, 222, 222, 222);
_textSize = 16;
setZ(9999);
textColor(QColor(222,222,222,222));
textSize(16);
connect(this, &FluWatermark::textColorChanged, this, [=] { update(); });
connect(this, &FluWatermark::gapChanged, this, [=] { update(); });
connect(this, &FluWatermark::offsetChanged, this, [=] { update(); });
@ -17,20 +19,19 @@ FluWatermark::FluWatermark(QQuickItem* parent) : QQuickPaintedItem(parent){
void FluWatermark::paint(QPainter *painter) {
QFont font;
font.setFamily(FluTextStyle::getInstance()->family());
font.setPixelSize(_textSize);
painter->setFont(font);
painter->setPen(_textColor);
QFontMetricsF fontMetrics(font);
qreal fontWidth = fontMetrics.horizontalAdvance(_text);
qreal fontHeight = fontMetrics.height();
int stepX = fontWidth + _gap.x();
int stepY = fontHeight + _gap.y();
int rowCount = width() / stepX+1;
int colCount = height() / stepY+1;
for (int r = 0; r < rowCount; r++)
{
for (int c = 0; c < colCount; c++)
{
int stepX = qRound(fontWidth + _gap.x());
int stepY = qRound(fontHeight + _gap.y());
int rowCount = qRound(width() / stepX + 1);
int colCount = qRound(height() / stepY + 1);
for (int r = 0; r < rowCount; r++) {
for (int c = 0; c < colCount; c++) {
qreal centerX = stepX * r + _offset.x() + fontWidth / 2.0;
qreal centerY = stepY * c + _offset.y() + fontHeight / 2.0;
painter->save();

View File

@ -1,5 +1,4 @@
#ifndef FLUWATERMARK_H
#define FLUWATERMARK_H
#pragma once
#include <QQuickItem>
#include <QQuickPaintedItem>
@ -9,8 +8,7 @@
/**
* @brief The FluWatermark class
*/
class FluWatermark : public QQuickPaintedItem
{
class FluWatermark : public QQuickPaintedItem {
Q_OBJECT
Q_PROPERTY_AUTO(QString, text)
Q_PROPERTY_AUTO(QPoint, gap)
@ -21,7 +19,6 @@ class FluWatermark : public QQuickPaintedItem
QML_NAMED_ELEMENT(FluWatermark)
public:
explicit FluWatermark(QQuickItem *parent = nullptr);
void paint(QPainter *painter) override;
};
#endif // FLUWATERMARK_H

1417
src/FluentIconDef.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
#include <QGuiApplication>
#include "Def.h"
#include "FluentIconDef.h"
#include "FluApp.h"
#include "FluColors.h"
#include "FluTheme.h"
@ -16,14 +17,15 @@
#include "FluFrameless.h"
void FluentUI::registerTypes(QQmlEngine *engine) {
initializeEngine(engine,uri);
registerTypes(uri);
initializeEngine(engine, _uri);
registerTypes(_uri);
}
void FluentUI::registerTypes(const char *uri){
void FluentUI::registerTypes(const char *uri) const {
#if (QT_VERSION < QT_VERSION_CHECK(6, 2, 0))
Q_INIT_RESOURCE(fluentui);
int major = _major;
int minor = _minor;
//@uri FluentUI
qmlRegisterType<FluQrCodeItem>(uri, major, minor, "FluQrCodeItem");
qmlRegisterType<FluCaptcha>(uri, major, minor, "FluCaptcha");
@ -130,7 +132,7 @@ void FluentUI::registerTypes(const char *uri){
qmlRegisterSingletonType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRouter.qml"), uri, major, minor, "FluRouter");
qmlRegisterSingletonType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluEventBus.qml"), uri, major, minor, "FluEventBus");
qmlRegisterUncreatableMetaObject(Fluent_Awesome::staticMetaObject, uri,major,minor,"FluentIcons", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(Fluent_Icons::staticMetaObject, uri, major, minor, "FluentIcons", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluThemeType::staticMetaObject, uri, major, minor, "FluThemeType", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluPageType::staticMetaObject, uri, major, minor, "FluPageType", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluWindowType::staticMetaObject, uri, major, minor, "FluWindowType", "Access to enums & flags only");
@ -148,7 +150,7 @@ void FluentUI::registerTypes(const char *uri){
#endif
}
void FluentUI::initializeEngine(QQmlEngine *engine, const char *uri){
void FluentUI::initializeEngine(QQmlEngine *engine, [[maybe_unused]] const char *uri) {
engine->rootContext()->setContextProperty("FluApp", FluApp::getInstance());
engine->rootContext()->setContextProperty("FluColors", FluColors::getInstance());
engine->rootContext()->setContextProperty("FluTheme", FluTheme::getInstance());

View File

@ -1,5 +1,4 @@
#ifndef FLUENTUI_H
#define FLUENTUI_H
#pragma once
#include <QObject>
#include <QQmlEngine>
@ -8,18 +7,20 @@
/**
* @brief The FluentUI class
*/
class FluentUI : public QObject
{
class FluentUI : public QObject {
Q_OBJECT
public:
SINGLETON(FluentUI)
Q_DECL_EXPORT void registerTypes(QQmlEngine *engine);
void registerTypes(const char *uri);
void initializeEngine(QQmlEngine *engine, const char *uri);
private:
const int major = 1;
const int minor = 0;
const char *uri = "FluentUI";
};
#endif // FLUENTUI_H
Q_DECL_EXPORT void registerTypes(QQmlEngine *engine);
void registerTypes(const char *uri) const;
void initializeEngine(QQmlEngine *engine, [[maybe_unused]] const char *uri);
private:
const int _major = 1;
const int _minor = 0;
const char *_uri = "FluentUI";
};

View File

@ -10,8 +10,7 @@ Item {
property real noiseOpacity: 0.02
property alias target : effect_source.sourceItem
property int blurRadius: 32
property rect targetRect: Qt.rect(control.x, control.y, control.width,
control.height)
property rect targetRect: Qt.rect(control.x, control.y, control.width,control.height)
ShaderEffectSource {
id: effect_source
anchors.fill: parent
@ -34,7 +33,7 @@ Item {
}
Image {
anchors.fill: parent
source: "../Image/noise.png"
source: "qrc:/qt/qml/FluentUI/Image/noise.png"
fillMode: Image.Tile
opacity: control.noiseOpacity
}

View File

@ -14,7 +14,7 @@ Rectangle{
property string closeText : qsTr("Close")
property string stayTopText : qsTr("Sticky on Top")
property string stayTopCancelText : qsTr("Sticky on Top cancelled")
property color textColor: FluTheme.dark ? "#FFFFFF" : "#000000"
property color textColor: FluTheme.fontPrimaryColor
property color minimizeNormalColor: FluTheme.itemNormalColor
property color minimizeHoverColor: FluTheme.itemHoverColor
property color minimizePressColor: FluTheme.itemPressColor

View File

@ -59,12 +59,8 @@ FluTextBox{
duration: FluTheme.animationEnabled ? 83 : 0
}
}
contentItem: FluRectangle{
radius: [4,4,4,4]
FluShadow{
radius: 4
}
color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)
contentItem: FluClip{
radius: [5,5,5,5]
ListView{
id:list_view
anchors.fill: parent
@ -97,10 +93,13 @@ FluTextBox{
radius:4
}
color: {
if(hovered){
return FluTheme.dark ? Qt.rgba(63/255,60/255,61/255,1) : Qt.rgba(237/255,237/255,242/255,1)
if(pressed){
return FluTheme.itemPressColor
}
return FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(0,0,0,0)
if(hovered){
return FluTheme.itemHoverColor
}
return FluTheme.itemNormalColor
}
}
contentItem: FluText{
@ -112,22 +111,28 @@ FluTextBox{
}
}
}
background: Item{
id:container
background:Rectangle{
id: rect_background
implicitWidth: control.width
implicitHeight: 38*Math.min(Math.max(list_view.count,1),8)
radius: 5
color: FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(1,1,1,1)
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
FluShadow{
radius: 5
}
}
}
onTextChanged: {
d.loadData()
if(d.flagVisible){
var pos = control.mapToItem(null, 0, 0)
if(d.window.height>pos.y+control.height+container.implicitHeight){
if(d.window.height>pos.y+control.height+rect_background.implicitHeight){
control_popup.y = control.height
} else if(pos.y>container.implicitHeight){
control_popup.y = -container.implicitHeight
} else if(pos.y>rect_background.implicitHeight){
control_popup.y = -rect_background.implicitHeight
} else {
control_popup.y = d.window.height-(pos.y+container.implicitHeight)
control_popup.y = d.window.height-(pos.y+rect_background.implicitHeight) - 1
}
control_popup.visible = true
}

View File

@ -57,12 +57,12 @@ Item {
Layout.alignment: Qt.AlignVCenter
color: {
if(item_mouse.pressed){
return FluTheme.dark ? Qt.rgba(150/255,150/255,150/235,1) : Qt.rgba(134/255,134/255,134/235,1)
return FluTheme.dark ? Qt.rgba(150/255,150/255,150/255,1) : Qt.rgba(134/255,134/255,134/255,1)
}
if(item_mouse.containsMouse){
return FluTheme.dark ? Qt.rgba(204/255,204/255,204/235,1) : Qt.rgba(92/255,92/255,92/235,1)
return FluTheme.dark ? Qt.rgba(204/255,204/255,204/255,1) : Qt.rgba(92/255,92/255,92/255,1)
}
return FluTheme.dark ? Qt.rgba(255/255,255/255,255/235,1) : Qt.rgba(26/255,26/255,26/235,1)
return FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(26/255,26/255,26/255,1)
}
MouseArea{
id:item_mouse

View File

@ -53,8 +53,6 @@ FluButton {
}
Menu{
id:popup
height: container.height
width: container.width
modal: true
Overlay.modal: Item {}
enter: Transition {
@ -75,11 +73,9 @@ FluButton {
}
}
contentItem: Item{
clip: true
FluFrame{
id:container
width: 300
height: 360
implicitWidth: 300
implicitHeight: 360
ColumnLayout {
anchors.fill: parent
spacing: 0
@ -609,8 +605,10 @@ FluButton {
}
}
}
}
background: Item{
background:Rectangle{
radius: 5
color: FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(1,1,1,1)
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
FluShadow{
radius: 5
}
@ -618,13 +616,12 @@ FluButton {
function showPopup() {
var pos = control.mapToItem(null, 0, 0)
if(d.window.height>pos.y+control.height+container.height){
popup.y = control.height
popup.y = control.height - 1
} else if(pos.y>container.height){
popup.y = -container.height
} else {
popup.y = d.window.height-(pos.y+container.height)
}
popup.x = -(popup.width-control.width)/2
popup.open()
}
}

View File

@ -13,16 +13,15 @@ Button{
property color current : Qt.rgba(1,1,1,1)
signal accepted()
property int colorHandleRadius: 8
property string cancelText: "取消"
property string okText: "确定"
property string titleText: "颜色选择器"
property string editText: "编辑颜色"
property string redText: "红色"
property string greenText: "绿色"
property string blueText: "蓝色"
property string opacityText: "透明度"
background:
Rectangle{
property string cancelText: qsTr("Cancel")
property string okText: qsTr("OK")
property string titleText: qsTr("Color Picker")
property string editText: qsTr("Edit Color")
property string redText: qsTr("Red")
property string greenText: qsTr("Green")
property string blueText: qsTr("Blue")
property string opacityText: qsTr("Opacity")
background: Rectangle{
id:layout_color
radius: 5
color:"#00000000"

View File

@ -134,10 +134,9 @@ T.ComboBox {
}
}
background:Rectangle{
color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(249/255,249/255,249/255,1)
border.color: FluTheme.dark ? Window.active ? Qt.rgba(55/255,55/255,55/255,1):Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
border.width: 1
radius: 5
color: FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(1,1,1,1)
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
FluShadow{
radius: 5
}

View File

@ -4,7 +4,6 @@ import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import FluentUI 1.0
FluButton {
property bool showYear: true
property var current
@ -96,8 +95,6 @@ FluButton {
Menu{
id:popup
modal: true
width: container.width
height: container.height
Overlay.modal: Item {}
enter: Transition {
reversible: true
@ -116,30 +113,26 @@ FluButton {
duration: FluTheme.animationEnabled ? 83 : 0
}
}
background:Item{
background:Rectangle{
radius: 5
color: FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(1,1,1,1)
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
FluShadow{
radius: 4
radius: 5
}
}
contentItem: Item{
clip: true
Rectangle{
id:container
radius: 4
width: 300
height: 340
color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)
implicitHeight: 340
implicitWidth: 300
MouseArea{
anchors.fill: parent
}
FluShadow{
radius: 4
}
RowLayout{
id:layout_content
spacing: 0
width: parent.width
height: 300
height: 280
Component{
id:list_delegate
Item{
@ -166,7 +159,7 @@ FluButton {
if(item_mouse.containsMouse){
return FluTheme.dark ? Qt.rgba(63/255,60/255,61/255,1) : Qt.rgba(237/255,237/255,242/255,1)
}
return FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(0,0,0,0)
return Qt.rgba(0,0,0,0)
}
radius: 3
MouseArea{
@ -214,8 +207,9 @@ FluButton {
}
ListView{
id:list_view_1
width: 100
height: parent.height
Layout.preferredWidth: 100
Layout.preferredHeight: parent.height - 2
Layout.alignment: Qt.AlignVCenter
boundsBehavior:Flickable.StopAtBounds
ScrollBar.vertical: FluScrollBar {}
model: generateYearArray(1924,2048)
@ -232,14 +226,16 @@ FluButton {
}
}
Rectangle{
width: 1
height: parent.height
Layout.preferredWidth: 1
Layout.preferredHeight: parent.height
color: control.dividerColor
visible: showYear
}
ListView{
id:list_view_2
width: showYear ? 100 : 150
height: parent.height
Layout.preferredWidth: showYear ? 99 : 150
Layout.preferredHeight: parent.height - 2
Layout.alignment: Qt.AlignVCenter
clip: true
ScrollBar.vertical: FluScrollBar {}
preferredHighlightBegin: 0
@ -254,20 +250,20 @@ FluButton {
}
}
Rectangle{
width: 1
height: parent.height
Layout.preferredWidth: 1
Layout.preferredHeight: parent.height
color: control.dividerColor
}
ListView{
id:list_view_3
width: showYear ? 100 : 150
height: parent.height
Layout.preferredWidth: showYear ? 99 : 150
Layout.preferredHeight: parent.height - 2
Layout.alignment: Qt.AlignVCenter
clip: true
preferredHighlightBegin: 0
preferredHighlightEnd: 0
highlightMoveDuration: 0
ScrollBar.vertical: FluScrollBar {}
Layout.alignment: Qt.AlignVCenter
boundsBehavior:Flickable.StopAtBounds
delegate: FluLoader{
property var model: modelData
@ -277,17 +273,12 @@ FluButton {
}
}
}
Rectangle{
width: parent.width
height: 1
anchors.top: layout_content.bottom
color: control.dividerColor
}
Rectangle{
id:layout_actions
height: 40
radius: 5
height: 60
color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
radius: 5
anchors{
bottom:parent.bottom
left: parent.left
@ -340,7 +331,6 @@ FluButton {
}
}
}
}
y:35
function showPopup() {
d.changeFlag = true
@ -361,7 +351,7 @@ FluButton {
text_day.text = day
var pos = control.mapToItem(null, 0, 0)
if(d.window.height>pos.y+control.height+container.height){
popup.y = control.height
popup.y = control.height-1
} else if(pos.y>container.height){
popup.y = -container.height
} else {

View File

@ -19,16 +19,20 @@ FluButton {
}
iconColor:control.textColor
}
Item{
id: d
property var window: Window.window
}
onClicked: {
if(menu.count !==0){
var pos = control.mapToItem(null, 0, 0)
var containerHeight = menu.count*36
if(window.height>pos.y+control.height+containerHeight){
if(d.window.height>pos.y+control.height+containerHeight){
menu.y = control.height
}else if(pos.y>containerHeight){
menu.y = -containerHeight
}else{
menu.y = window.height-(pos.y+containerHeight)
menu.y = d.window.height-(pos.y+containerHeight)
}
menu.open()
}

View File

@ -27,7 +27,12 @@ Item {
height: 45
radius: 4
border.color: FluTheme.dividerColor
color: FluTheme.dark ? Window.active ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
color: {
if(Window.active){
return FluTheme.frameActiveColor
}
return FluTheme.frameColor
}
MouseArea{
id:control_mouse
anchors.fill: parent
@ -84,12 +89,18 @@ Item {
height: contentHeight+container.anchors.topMargin
width: parent.width
z:-999
clip: true
Rectangle{
id:container
anchors.fill: parent
radius: 4
clip: true
color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
color: {
if(Window.active){
return FluTheme.frameActiveColor
}
return FluTheme.frameColor
}
border.color: FluTheme.dividerColor
anchors.topMargin: -contentHeight
states: [

View File

@ -19,6 +19,11 @@ T.Frame {
id:d
radius: 4
border.color: FluTheme.dividerColor
color: FluTheme.dark ? Window.active ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(251/255,251/255,253/255,1)
color: {
if(Window.active){
return FluTheme.frameActiveColor
}
return FluTheme.frameColor
}
}
}

View File

@ -8,8 +8,13 @@ import FluentUI 1.0
T.GroupBox {
id: control
property int borderWidth : 1
property color borderColor : FluTheme.dark ? Window.active ? Qt.rgba(55/255,55/255,55/255,1):Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
property color color: FluTheme.dark ? Window.active ? Qt.rgba(38/255,44/255,54/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
property color borderColor : FluTheme.dividerColor
property color color: {
if(Window.active){
return FluTheme.frameActiveColor
}
return FluTheme.frameColor
}
property int radius: 4
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
contentWidth + leftPadding + rightPadding,

View File

@ -7,13 +7,15 @@ Text {
property int iconSize: 20
property color iconColor: FluTheme.dark ? "#FFFFFF" : "#000000"
id:control
font.family: "Segoe Fluent Icons"
font.family: font_loader.name
font.pixelSize: iconSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: iconColor
text: (String.fromCharCode(iconSource).toString(16))
opacity: iconSource>0
FontLoader{
source: "../Font/Segoe_Fluent_Icons.ttf"
id: font_loader
source: "qrc:/qt/qml/FluentUI/Font/FluentIcons.ttf"
}
}

View File

@ -44,8 +44,8 @@ T.Menu {
background: Rectangle {
implicitWidth: 150
implicitHeight: 36
color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(240/255,240/255,240/255,1)
border.color: FluTheme.dark ? Window.active ? Qt.rgba(55/255,55/255,55/255,1):Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(252/255,252/255,252/255,1)
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
border.width: 1
radius: 5
FluShadow{}

View File

@ -21,6 +21,7 @@ T.SpinBox {
bottom: Math.min(control.from, control.to)
top: Math.max(control.from, control.to)
}
font: FluTextStyle.Body
contentItem: TextInput {
property color normalColor: FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1)

View File

@ -8,11 +8,11 @@ Item{
id:control
default property alias content: container.data
property int statusMode: FluStatusLayoutType.Loading
property string loadingText:"正在加载..."
property string emptyText: "空空如也"
property string errorText: "页面出错了.."
property string errorButtonText: "重新加载"
property color color: FluTheme.dark ? Window.active ? Qt.rgba(38/255,44/255,54/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
property string loadingText: qsTr("Loading...")
property string emptyText: qsTr("Empty")
property string errorText: qsTr("Error")
property string errorButtonText: qsTr("Reload")
property color color: Qt.rgba(0,0,0,0)
signal errorClicked
property Component loadingItem : com_loading
property Component emptyItem : com_empty

View File

@ -1,4 +1,5 @@
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import Qt.labs.qmlmodels 1.0
@ -17,7 +18,12 @@ Rectangle {
property color selectedBorderColor: FluTheme.primaryColor
property color selectedColor: FluTools.withOpacity(FluTheme.primaryColor,0.3)
id:control
color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
color: {
if(Window.active){
return FluTheme.frameActiveColor
}
return FluTheme.frameColor
}
onColumnSourceChanged: {
if(columnSource.length!==0){
var columns= []
@ -90,7 +96,7 @@ Rectangle {
if(!readOnly){
editTextChaged(text_box.text)
}
tableView.closeEditor()
control.closeEditor()
}
}
}
@ -119,7 +125,7 @@ Rectangle {
if(!readOnly){
editTextChaged(text_box.text)
}
tableView.closeEditor()
control.closeEditor()
}
}
}
@ -258,7 +264,7 @@ Rectangle {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onPressed:{
closeEditor()
control.closeEditor()
}
onCanceled: {
}
@ -275,7 +281,7 @@ Rectangle {
onClicked:
(event)=>{
d.current = rowObject
closeEditor()
control.closeEditor()
event.accepted = true
}
}
@ -381,6 +387,7 @@ Rectangle {
clip: true
onRowsChanged: {
control.closeEditor()
table_view.flick(0,1)
}
delegate: com_table_delegate
FluLoader{
@ -771,9 +778,9 @@ Rectangle {
timer_vertical_force_layout.restart()
}
Connections{
target: table_model
function onRowCountChanged(){
header_row_model.rows = Array.from({length: table_model.rows.length}, (_, i) => ({rowIndex:i+1}))
target: table_view
function onRowsChanged(){
header_row_model.rows = Array.from({length: table_view.rows}, (_, i) => ({rowIndex:i+1}))
}
}
Timer{

View File

@ -23,16 +23,27 @@ FluControlBackground{
GradientStop { position: 1 - d.offsetSize/control.height; color: d.startColor }
GradientStop { position: 1.0; color: d.endColor }
}
bottomMargin: inputItem && inputItem.activeFocus ? 2 : 1
bottomMargin: 1
QtObject{
id:d
property int offsetSize : inputItem && inputItem.activeFocus ? 2 : 3
property int offsetSize : 3
property color startColor : FluTheme.dark ? Qt.rgba(66/255,66/255,66/255,1) : Qt.rgba(232/255,232/255,232/255,1)
property color endColor: {
if(!control.enabled){
return d.startColor
}
return inputItem && inputItem.activeFocus ? FluTheme.primaryColor : FluTheme.dark ? Qt.rgba(123/255,123/255,123/255,1) : Qt.rgba(132/255,132/255,132/255,1)
return FluTheme.dark ? Qt.rgba(123/255,123/255,123/255,1) : Qt.rgba(132/255,132/255,132/255,1)
}
}
FluClip{
anchors.fill: parent
radius: [control.radius,control.radius,control.radius,control.radius]
visible: inputItem && inputItem.activeFocus
Rectangle{
width: parent.width
height: 2
anchors.bottom: parent.bottom
color: FluTheme.primaryColor
}
}
}

View File

@ -111,8 +111,6 @@ FluButton {
}
Menu{
id:popup
width: container.width
height: container.height
modal: true
Overlay.modal: Item {}
enter: Transition {
@ -132,19 +130,18 @@ FluButton {
duration: FluTheme.animationEnabled ? 83 : 0
}
}
background:Item{
background:Rectangle{
radius: 5
color: FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(1,1,1,1)
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
FluShadow{
radius: 4
radius: 5
}
}
contentItem: Item{
clip: true
Rectangle{
id:container
height: 340
width: 300
radius: 4
color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)
implicitHeight: 340
implicitWidth: 300
MouseArea{
anchors.fill: parent
}
@ -152,7 +149,7 @@ FluButton {
id:layout_content
spacing: 0
width: parent.width
height: 300
height: 280
Component{
id:list_delegate
Item{
@ -179,7 +176,7 @@ FluButton {
if(item_mouse.containsMouse){
return FluTheme.dark ? Qt.rgba(63/255,60/255,61/255,1) : Qt.rgba(237/255,237/255,242/255,1)
}
return FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(0,0,0,0)
return Qt.rgba(0,0,0,0)
}
radius: 3
MouseArea{
@ -219,8 +216,9 @@ FluButton {
}
ListView{
id:list_view_1
width: isH ? 100 : 150
height: parent.height
Layout.preferredWidth: isH ? 100 : 150
Layout.preferredHeight: parent.height-2
Layout.alignment: Qt.AlignVCenter
boundsBehavior:Flickable.StopAtBounds
ScrollBar.vertical: FluScrollBar {}
preferredHighlightBegin: 0
@ -236,14 +234,15 @@ FluButton {
}
}
Rectangle{
width: 1
height: parent.height
Layout.preferredWidth: 1
Layout.preferredHeight: parent.height
color: control.dividerColor
}
ListView{
id:list_view_2
width: isH ? 100 : 150
height: parent.height
Layout.preferredWidth: isH ? 99 : 150
Layout.preferredHeight: parent.height-2
Layout.alignment: Qt.AlignVCenter
model: generateArray(0,59)
clip: true
preferredHighlightBegin: 0
@ -266,8 +265,8 @@ FluButton {
}
ListView{
id:list_view_3
width: 100
height: 76
Layout.preferredWidth: 100
Layout.preferredHeight: 76
model: [control.amText,control.pmText]
clip: true
visible: isH
@ -285,17 +284,12 @@ FluButton {
}
}
}
Rectangle{
width: parent.width
height: 1
anchors.top: layout_content.bottom
color: control.dividerColor
}
Rectangle{
id:layout_actions
height: 40
radius: 5
height: 60
color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1)
radius: 5
anchors{
bottom:parent.bottom
left: parent.left
@ -353,7 +347,6 @@ FluButton {
}
}
}
}
y:35
function showPopup() {
d.changeFlag = true
@ -387,7 +380,7 @@ FluButton {
}
var pos = control.mapToItem(null, 0, 0)
if(d.window.height>pos.y+control.height+container.height){
popup.y = control.height
popup.y = control.height-1
} else if(pos.y>container.height){
popup.y = -container.height
} else {

File diff suppressed because it is too large Load Diff

View File

@ -109,9 +109,56 @@ Window {
}
Component{
id:com_background
Item{
Rectangle{
anchors.fill: parent
color: window.backgroundColor
}
Image{
id:img_back
visible: false
cache: false
fillMode: Image.PreserveAspectCrop
asynchronous: true
Component.onCompleted: {
var geometry = FluTools.desktopAvailableGeometry(window)
width = geometry.width
height = geometry.height
sourceSize = Qt.size(width,height)
source = FluTools.getUrlByFilePath(FluTheme.desktopImagePath)
}
Connections{
target: FluTheme
function onDesktopImagePathChanged(){
timer_update_image.restart()
}
function onBlurBehindWindowEnabledChanged(){
if(FluTheme.blurBehindWindowEnabled){
img_back.source = FluTools.getUrlByFilePath(FluTheme.desktopImagePath)
}else{
img_back.source = ""
}
}
}
Timer{
id:timer_update_image
interval: 500
onTriggered: {
img_back.source = ""
img_back.source = FluTools.getUrlByFilePath(FluTheme.desktopImagePath)
}
}
}
FluAcrylic{
anchors.fill: parent
target: img_back
tintOpacity: FluTheme.dark ? 0.80 : 0.75
blurRadius: 64
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.y,window.width,window.height)
}
}
}
Component{
id:com_app_bar
@ -283,6 +330,12 @@ Window {
function showMaximized(){
frameless.showMaximized()
}
function showMinimized(){
frameless.showMinimized()
}
function showNormal(){
frameless.showNormal()
}
function showLoading(text = "",cancel = true){
if(text===""){
text = qsTr("Loading...")

View File

@ -32,9 +32,9 @@ FluWindow {
}
}
}
function showDialog(){
var x = transientParent.x + (transientParent.width - width)/2
var y = transientParent.y + (transientParent.height - height)/2
function showDialog(offsetX=0,offsetY=0){
var x = transientParent.x + (transientParent.width - width)/2 + offsetX
var y = transientParent.y + (transientParent.height - height)/2 + offsetY
control.stayTop = Qt.binding(function(){return transientParent.stayTop})
control.setGeometry(x,y,width,height)
control.visibility = Window.Windowed

View File

@ -21,6 +21,30 @@ Module {
Property { name: "lighter"; type: "QColor" }
Property { name: "lightest"; type: "QColor" }
}
Component {
name: "FluApp"
prototype: "QObject"
exports: ["FluentUI/FluApp 1.0"]
exportMetaObjectRevisions: [0]
Property { name: "useSystemAppBar"; type: "bool" }
Property { name: "windowIcon"; type: "string" }
Property { name: "locale"; type: "QLocale" }
Method {
name: "init"
Parameter { name: "target"; type: "QObject"; isPointer: true }
Parameter { name: "locale"; type: "QLocale" }
}
Method {
name: "init"
Parameter { name: "target"; type: "QObject"; isPointer: true }
}
Method {
name: "iconDatas"
type: "QJsonArray"
Parameter { name: "keyword"; type: "string" }
}
Method { name: "iconDatas"; type: "QJsonArray" }
}
Component {
name: "FluCalendarViewType"
exports: ["FluentUI/FluCalendarViewType 1.0"]
@ -50,6 +74,50 @@ Module {
Parameter { name: "code"; type: "string" }
}
}
Component {
name: "FluColors"
prototype: "QObject"
exports: ["FluentUI/FluColors 1.0"]
exportMetaObjectRevisions: [0]
Property { name: "Transparent"; type: "QColor" }
Property { name: "Black"; type: "QColor" }
Property { name: "White"; type: "QColor" }
Property { name: "Grey10"; type: "QColor" }
Property { name: "Grey20"; type: "QColor" }
Property { name: "Grey30"; type: "QColor" }
Property { name: "Grey40"; type: "QColor" }
Property { name: "Grey50"; type: "QColor" }
Property { name: "Grey60"; type: "QColor" }
Property { name: "Grey70"; type: "QColor" }
Property { name: "Grey80"; type: "QColor" }
Property { name: "Grey90"; type: "QColor" }
Property { name: "Grey100"; type: "QColor" }
Property { name: "Grey110"; type: "QColor" }
Property { name: "Grey120"; type: "QColor" }
Property { name: "Grey130"; type: "QColor" }
Property { name: "Grey140"; type: "QColor" }
Property { name: "Grey150"; type: "QColor" }
Property { name: "Grey160"; type: "QColor" }
Property { name: "Grey170"; type: "QColor" }
Property { name: "Grey180"; type: "QColor" }
Property { name: "Grey190"; type: "QColor" }
Property { name: "Grey200"; type: "QColor" }
Property { name: "Grey210"; type: "QColor" }
Property { name: "Grey220"; type: "QColor" }
Property { name: "Yellow"; type: "FluAccentColor"; isPointer: true }
Property { name: "Orange"; type: "FluAccentColor"; isPointer: true }
Property { name: "Red"; type: "FluAccentColor"; isPointer: true }
Property { name: "Magenta"; type: "FluAccentColor"; isPointer: true }
Property { name: "Purple"; type: "FluAccentColor"; isPointer: true }
Property { name: "Blue"; type: "FluAccentColor"; isPointer: true }
Property { name: "Teal"; type: "FluAccentColor"; isPointer: true }
Property { name: "Green"; type: "FluAccentColor"; isPointer: true }
Method {
name: "createAccentColor"
type: "FluAccentColor*"
Parameter { name: "primaryColor"; type: "QColor" }
}
}
Component {
name: "FluContentDialogType"
exports: ["FluentUI/FluContentDialogType 1.0"]
@ -71,10 +139,10 @@ Module {
exports: ["FluentUI/FluFrameless 1.0"]
exportMetaObjectRevisions: [0]
Property { name: "appbar"; type: "QQuickItem"; isPointer: true }
Property { name: "topmost"; type: "bool" }
Property { name: "maximizeButton"; type: "QQuickItem"; isPointer: true }
Property { name: "minimizedButton"; type: "QQuickItem"; isPointer: true }
Property { name: "closeButton"; type: "QQuickItem"; isPointer: true }
Property { name: "topmost"; type: "bool" }
Property { name: "disabled"; type: "bool" }
Property { name: "fixSize"; type: "bool" }
Method { name: "showFullScreen" }
@ -226,6 +294,47 @@ Module {
Parameter { name: "filter"; type: "QJSValue" }
}
}
Component {
name: "FluTextStyle"
prototype: "QObject"
exports: ["FluentUI/FluTextStyle 1.0"]
exportMetaObjectRevisions: [0]
Property { name: "family"; type: "string" }
Property { name: "Caption"; type: "QFont" }
Property { name: "Body"; type: "QFont" }
Property { name: "BodyStrong"; type: "QFont" }
Property { name: "Subtitle"; type: "QFont" }
Property { name: "Title"; type: "QFont" }
Property { name: "TitleLarge"; type: "QFont" }
Property { name: "Display"; type: "QFont" }
}
Component {
name: "FluTheme"
prototype: "QObject"
exports: ["FluentUI/FluTheme 1.0"]
exportMetaObjectRevisions: [0]
Property { name: "dark"; type: "bool"; isReadonly: true }
Property { name: "accentColor"; type: "FluAccentColor"; isPointer: true }
Property { name: "primaryColor"; type: "QColor" }
Property { name: "backgroundColor"; type: "QColor" }
Property { name: "dividerColor"; type: "QColor" }
Property { name: "windowBackgroundColor"; type: "QColor" }
Property { name: "windowActiveBackgroundColor"; type: "QColor" }
Property { name: "fontPrimaryColor"; type: "QColor" }
Property { name: "fontSecondaryColor"; type: "QColor" }
Property { name: "fontTertiaryColor"; type: "QColor" }
Property { name: "itemNormalColor"; type: "QColor" }
Property { name: "frameColor"; type: "QColor" }
Property { name: "frameActiveColor"; type: "QColor" }
Property { name: "itemHoverColor"; type: "QColor" }
Property { name: "itemPressColor"; type: "QColor" }
Property { name: "itemCheckColor"; type: "QColor" }
Property { name: "desktopImagePath"; type: "string" }
Property { name: "darkMode"; type: "int" }
Property { name: "nativeText"; type: "bool" }
Property { name: "animationEnabled"; type: "bool" }
Property { name: "blurBehindWindowEnabled"; type: "bool" }
}
Component {
name: "FluThemeType"
exports: ["FluentUI/FluThemeType 1.0"]
@ -267,13 +376,134 @@ Module {
}
}
}
Component {
name: "FluTools"
prototype: "QObject"
exports: ["FluentUI/FluTools 1.0"]
exportMetaObjectRevisions: [0]
Method { name: "qtMajor"; type: "int" }
Method { name: "qtMinor"; type: "int" }
Method { name: "isMacos"; type: "bool" }
Method { name: "isLinux"; type: "bool" }
Method { name: "isWin"; type: "bool" }
Method {
name: "clipText"
Parameter { name: "text"; type: "string" }
}
Method { name: "uuid"; type: "string" }
Method {
name: "readFile"
type: "string"
Parameter { name: "fileName"; type: "string" }
}
Method {
name: "setQuitOnLastWindowClosed"
Parameter { name: "val"; type: "bool" }
}
Method {
name: "setOverrideCursor"
Parameter { name: "shape"; type: "Qt::CursorShape" }
}
Method { name: "restoreOverrideCursor" }
Method {
name: "html2PlantText"
type: "string"
Parameter { name: "html"; type: "string" }
}
Method {
name: "toLocalPath"
type: "string"
Parameter { name: "url"; type: "QUrl" }
}
Method {
name: "deleteLater"
Parameter { name: "p"; type: "QObject"; isPointer: true }
}
Method {
name: "getFileNameByUrl"
type: "string"
Parameter { name: "url"; type: "QUrl" }
}
Method { name: "getVirtualGeometry"; type: "QRect" }
Method { name: "getApplicationDirPath"; type: "string" }
Method {
name: "getUrlByFilePath"
type: "QUrl"
Parameter { name: "path"; type: "string" }
}
Method {
name: "withOpacity"
type: "QColor"
Parameter { type: "QColor" }
Parameter { name: "alpha"; type: "double" }
}
Method {
name: "md5"
type: "string"
Parameter { name: "text"; type: "string" }
}
Method {
name: "sha256"
type: "string"
Parameter { name: "text"; type: "string" }
}
Method {
name: "toBase64"
type: "string"
Parameter { name: "text"; type: "string" }
}
Method {
name: "fromBase64"
type: "string"
Parameter { name: "text"; type: "string" }
}
Method {
name: "removeDir"
type: "bool"
Parameter { name: "dirPath"; type: "string" }
}
Method {
name: "removeFile"
type: "bool"
Parameter { name: "filePath"; type: "string" }
}
Method {
name: "showFileInFolder"
Parameter { name: "path"; type: "string" }
}
Method { name: "isSoftware"; type: "bool" }
Method { name: "currentTimestamp"; type: "qlonglong" }
Method { name: "cursorPos"; type: "QPoint" }
Method { name: "windowIcon"; type: "QIcon" }
Method { name: "cursorScreenIndex"; type: "int" }
Method { name: "windowBuildNumber"; type: "int" }
Method { name: "isWindows11OrGreater"; type: "bool" }
Method { name: "isWindows10OrGreater"; type: "bool" }
Method {
name: "desktopAvailableGeometry"
type: "QRect"
Parameter { name: "window"; type: "QQuickWindow"; isPointer: true }
}
Method { name: "getWallpaperFilePath"; type: "string" }
Method {
name: "imageMainColor"
type: "QColor"
Parameter { name: "image"; type: "QImage" }
Parameter { name: "bright"; type: "double" }
}
Method {
name: "imageMainColor"
type: "QColor"
Parameter { name: "image"; type: "QImage" }
}
}
Component {
name: "FluTreeModel"
prototype: "QAbstractItemModel"
exports: ["FluentUI/FluTreeModel 1.0"]
exportMetaObjectRevisions: [0]
Property { name: "dataSourceSize"; type: "int" }
Property { name: "selectionModel"; type: "QList<FluTreeNode*>" }
Property { name: "columnSource"; type: "QList<QVariantMap>" }
Method {
name: "removeRows"
Parameter { name: "row"; type: "int" }
@ -289,6 +519,11 @@ Module {
type: "QObject*"
Parameter { name: "row"; type: "int" }
}
Method {
name: "setRow"
Parameter { name: "row"; type: "int" }
Parameter { name: "data"; type: "QVariantMap" }
}
Method {
name: "setData"
Parameter { name: "data"; type: "QList<FluTreeNode*>" }
@ -305,12 +540,6 @@ Module {
name: "expand"
Parameter { name: "row"; type: "int" }
}
Method {
name: "dragAndDrop"
Parameter { name: "dragIndex"; type: "int" }
Parameter { name: "dropIndex"; type: "int" }
Parameter { name: "isDropTopArea"; type: "bool" }
}
Method {
name: "getNode"
type: "FluTreeNode*"
@ -332,6 +561,7 @@ Module {
}
Method { name: "allExpand" }
Method { name: "allCollapse" }
Method { name: "selectionModel"; type: "QVariant" }
}
Component {
name: "FluTreeViewType"
@ -375,12 +605,12 @@ Module {
}
}
Component {
name: "Fluent_Awesome"
name: "Fluent_Icons"
exports: ["FluentUI/FluentIcons 1.0"]
isCreatable: false
exportMetaObjectRevisions: [0]
Enum {
name: "Fluent_AwesomeType"
name: "Fluent_IconType"
values: {
"GlobalNavButton": 59136,
"Wifi": 59137,
@ -2212,37 +2442,37 @@ Module {
Property { name: "darkClickListener"; type: "QVariant" }
Property {
name: "buttonStayTop"
type: "FluIconButton_QMLTYPE_19"
type: "FluIconButton_QMLTYPE_20"
isReadonly: true
isPointer: true
}
Property {
name: "buttonMinimize"
type: "FluIconButton_QMLTYPE_19"
type: "FluIconButton_QMLTYPE_20"
isReadonly: true
isPointer: true
}
Property {
name: "buttonMaximize"
type: "FluIconButton_QMLTYPE_19"
type: "FluIconButton_QMLTYPE_20"
isReadonly: true
isPointer: true
}
Property {
name: "buttonClose"
type: "FluIconButton_QMLTYPE_19"
type: "FluIconButton_QMLTYPE_20"
isReadonly: true
isPointer: true
}
Property {
name: "buttonDark"
type: "FluIconButton_QMLTYPE_19"
type: "FluIconButton_QMLTYPE_20"
isReadonly: true
isPointer: true
}
Property {
name: "layoutMacosButtons"
type: "FluLoader_QMLTYPE_13"
type: "FluLoader_QMLTYPE_14"
isReadonly: true
isPointer: true
}
@ -2932,15 +3162,15 @@ Module {
defaultProperty: "data"
Property { name: "logo"; type: "QUrl" }
Property { name: "title"; type: "string" }
Property { name: "items"; type: "FluObject_QMLTYPE_137"; isPointer: true }
Property { name: "footerItems"; type: "FluObject_QMLTYPE_137"; isPointer: true }
Property { name: "items"; type: "FluObject_QMLTYPE_172"; isPointer: true }
Property { name: "footerItems"; type: "FluObject_QMLTYPE_172"; 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_38"; isPointer: true }
Property { name: "navItemExpanderRightMenu"; type: "FluMenu_QMLTYPE_38"; isPointer: true }
Property { name: "navItemRightMenu"; type: "FluMenu_QMLTYPE_33"; isPointer: true }
Property { name: "navItemExpanderRightMenu"; type: "FluMenu_QMLTYPE_33"; isPointer: true }
Property { name: "navCompactWidth"; type: "int" }
Property { name: "navTopMargin"; type: "int" }
Property { name: "cellHeight"; type: "int" }
@ -2948,13 +3178,13 @@ Module {
Property { name: "hideNavAppBar"; type: "bool" }
Property {
name: "buttonMenu"
type: "FluIconButton_QMLTYPE_19"
type: "FluIconButton_QMLTYPE_20"
isReadonly: true
isPointer: true
}
Property {
name: "buttonBack"
type: "FluIconButton_QMLTYPE_19"
type: "FluIconButton_QMLTYPE_20"
isReadonly: true
isPointer: true
}
@ -3766,21 +3996,23 @@ Module {
Property { name: "previousText"; type: "string" }
}
Component {
prototype: "QQuickItem"
prototype: "QQuickRectangle"
name: "FluentUI/FluTreeView 1.0"
exports: ["FluentUI/FluTreeView 1.0"]
exportMetaObjectRevisions: [0]
isComposite: true
defaultProperty: "data"
Property { name: "currentIndex"; type: "int" }
Property { name: "dataSource"; type: "QVariant" }
Property { name: "columnSource"; type: "QVariant" }
Property { name: "showLine"; type: "bool" }
Property { name: "draggable"; type: "bool" }
Property { name: "cellHeight"; type: "int" }
Property { name: "depthPadding"; type: "int" }
Property { name: "checkable"; type: "bool" }
Property { name: "lineColor"; type: "QColor" }
Method { name: "selectionModel"; type: "QVariant" }
Property { name: "borderColor"; type: "QColor" }
Property { name: "selectedBorderColor"; type: "QColor" }
Property { name: "selectedColor"; type: "QColor" }
Property { name: "current"; type: "QVariant"; isReadonly: true }
Method { name: "count"; type: "QVariant" }
Method { name: "visibleCount"; type: "QVariant" }
Method {
@ -3795,6 +4027,14 @@ Module {
}
Method { name: "allExpand"; type: "QVariant" }
Method { name: "allCollapse"; type: "QVariant" }
Method {
name: "customItem"
type: "QVariant"
Parameter { name: "comId"; type: "QVariant" }
Parameter { name: "options"; type: "QVariant" }
}
Method { name: "closeEditor"; type: "QVariant" }
Method { name: "selectionModel"; type: "QVariant" }
}
Component {
prototype: "QQuickWindowQmlImpl"

View File

@ -2,7 +2,6 @@
<qresource prefix="/qt/qml">
<file>FluentUI/JS/Chart.js</file>
<file>FluentUI/Image/noise.png</file>
<file>FluentUI/Font/Segoe_Fluent_Icons.ttf</file>
<file>FluentUI/Controls/FluAcrylic.qml</file>
<file>FluentUI/Controls/FluAppBar.qml</file>
<file>FluentUI/Controls/FluAutoSuggestBox.qml</file>
@ -110,5 +109,6 @@
<file>FluentUI/Controls/FluSheet.qml</file>
<file>FluentUI/Controls/FluGroupBox.qml</file>
<file>FluentUI/Controls/FluControlBackground.qml</file>
<file>FluentUI/Font/FluentIcons.ttf</file>
</qresource>
</RCC>

View File

@ -8,15 +8,15 @@ Item {
property real tintOpacity: 0.65
property real luminosity: 0.01
property real noiseOpacity: 0.02
property alias target: effect_source.sourceItem
property var target
property int blurRadius: 32
property rect targetRect: Qt.rect(control.x, control.y, control.width,
control.height)
property rect targetRect: Qt.rect(control.x, control.y, control.width,control.height)
ShaderEffectSource {
id: effect_source
anchors.fill: parent
visible: false
sourceRect: control.targetRect
sourceItem: control.target
}
FastBlur {
id: fast_blur
@ -34,7 +34,7 @@ Item {
}
Image {
anchors.fill: parent
source: "../Image/noise.png"
source: "qrc:/qt/qml/FluentUI/Image/noise.png"
fillMode: Image.Tile
opacity: control.noiseOpacity
}

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