Compare commits

...

24 Commits

Author SHA1 Message Date
5fd934b5f5 update 2024-03-29 00:51:55 +08:00
b7fde5f79c update 2024-03-29 00:48:58 +08:00
41cbeef3fd update 2024-03-28 19:18:56 +08:00
f616a2da6a update 2024-03-27 14:13:36 +08:00
b6c3f0eda9 update 2024-03-27 10:52:47 +08:00
06aa16c0eb update 2024-03-27 10:25:58 +08:00
c52439ac39 update 2024-03-27 09:45:56 +08:00
e81a2cc849 update 2024-03-27 00:36:56 +08:00
485bcc8acc update 2024-03-25 22:17:05 +08:00
07fedb43a8 update 2024-03-25 21:01:47 +08:00
d6c0492665 update 2024-03-25 14:43:23 +08:00
9d06c6d1e9 update 2024-03-24 22:12:20 +08:00
0ca486dfa1 fix bug 2024-03-24 12:45:34 +08:00
3257f59c68 update 2024-03-24 10:50:01 +08:00
ff68491baf update 2024-03-24 10:27:16 +08:00
247b8db7c4 update 2024-03-24 10:20:50 +08:00
07a43825d1 update 2024-03-24 10:17:20 +08:00
e0254f2f80 fix bug 2024-03-23 22:28:14 +08:00
37101c97c5 update 2024-03-23 22:17:03 +08:00
7e1490f8f4 update 2024-03-22 12:59:39 +08:00
98770cb907 update 2024-03-21 13:33:35 +08:00
bd942659df update 2024-03-21 11:30:17 +08:00
796be2a8f2 update FluWindowDialog 2024-03-21 11:29:49 +08:00
d655dc0141 update 2024-03-20 23:35:15 +08:00
198 changed files with 1977 additions and 38407 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20)
project(example VERSION 1.0 LANGUAGES CXX)
project(example VERSION 1.0)
#配置通用编译
set(CMAKE_CXX_STANDARD 17)
@ -166,7 +166,7 @@ if (CMAKE_BUILD_TYPE MATCHES "Release")
add_custom_target(Script-DeployRelease
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/dist
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/dist
COMMAND ${QT_DEPLOY_QT} ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME}.exe -qmldir=${CMAKE_CURRENT_LIST_DIR}
COMMAND ${QT_DEPLOY_QT} --qmldir=${CMAKE_CURRENT_LIST_DIR} --plugindir ${CMAKE_SOURCE_DIR}/dist/plugins --no-translations --compiler-runtime ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME}.exe
COMMENT "Windows Deploying Qt Dependencies After Build........."
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}

View File

@ -181,8 +181,6 @@
<file>res/image/image_1.jpg</file>
<file>qml/window/PageWindow.qml</file>
<file>qml/page/T_StaggeredLayout.qml</file>
<file>qml/viewmodel/SettingsViewModel.qml</file>
<file>qml/viewmodel/TextBoxViewModel.qml</file>
<file>qml/page/T_Clip.qml</file>
<file>qml/page/T_3D.qml</file>
<file>qml/page/T_Network.qml</file>
@ -208,5 +206,6 @@
<file>res/template/src/qml.qrc.in</file>
<file>res/template/src/zh_CN.ts.in</file>
<file>res/template/src/README.md.in</file>
<file>qml/global/GlobalModel.qml</file>
</qresource>
</RCC>

View File

@ -535,104 +535,104 @@
<context>
<name>MainWindow</name>
<message>
<location filename="qml/window/MainWindow.qml" line="322"/>
<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="98"/>
<location filename="qml/window/MainWindow.qml" line="106"/>
<location filename="qml/window/MainWindow.qml" line="83"/>
<location filename="qml/window/MainWindow.qml" line="91"/>
<source>Quit</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="99"/>
<location filename="qml/window/MainWindow.qml" line="84"/>
<source>Are you sure you want to exit the program?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="100"/>
<location filename="qml/window/MainWindow.qml" line="85"/>
<source>Minimize</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="103"/>
<location filename="qml/window/MainWindow.qml" line="88"/>
<source>Friendly Reminder</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="103"/>
<location filename="qml/window/MainWindow.qml" line="88"/>
<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="107"/>
<location filename="qml/window/MainWindow.qml" line="351"/>
<location filename="qml/window/MainWindow.qml" line="92"/>
<location filename="qml/window/MainWindow.qml" line="336"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="118"/>
<location filename="qml/window/MainWindow.qml" line="103"/>
<source>Open in Separate Window</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="215"/>
<location filename="qml/window/MainWindow.qml" line="200"/>
<source>Click Time</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="225"/>
<location filename="qml/window/MainWindow.qml" line="210"/>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="316"/>
<location filename="qml/window/MainWindow.qml" line="301"/>
<source>Finish</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="317"/>
<location filename="qml/window/MainWindow.qml" line="302"/>
<source>Next</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="318"/>
<location filename="qml/window/MainWindow.qml" line="303"/>
<source>Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="322"/>
<location filename="qml/window/MainWindow.qml" line="307"/>
<source>Here you can switch to night mode.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="324"/>
<location filename="qml/window/MainWindow.qml" line="309"/>
<source>Hide Easter eggs</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="324"/>
<location filename="qml/window/MainWindow.qml" line="309"/>
<source>Try a few more clicks!!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="348"/>
<location filename="qml/window/MainWindow.qml" line="333"/>
<source>Upgrade Tips</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="349"/>
<location filename="qml/window/MainWindow.qml" line="334"/>
<source>FluentUI is currently up to date </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="349"/>
<location filename="qml/window/MainWindow.qml" line="334"/>
<source> -- The current app version</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="349"/>
<location filename="qml/window/MainWindow.qml" line="334"/>
<source>
Now go and download the new version
@ -641,17 +641,17 @@ Updated content:
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="352"/>
<location filename="qml/window/MainWindow.qml" line="337"/>
<source>OK</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="379"/>
<location filename="qml/window/MainWindow.qml" line="364"/>
<source>The current version is already the latest</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="386"/>
<location filename="qml/window/MainWindow.qml" line="371"/>
<source>The network is abnormal</source>
<translation type="unfinished"></translation>
</message>
@ -1149,7 +1149,8 @@ Updated content:
<name>T_DatePicker</name>
<message>
<location filename="qml/page/T_DatePicker.qml" line="10"/>
<source>TimePicker</source>
<source>DatePicker</source>
<oldsource>TimePicker</oldsource>
<translation type="unfinished"></translation>
</message>
<message>
@ -1521,46 +1522,46 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
<context>
<name>T_MultiWindow</name>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="13"/>
<location filename="qml/page/T_MultiWindow.qml" line="12"/>
<source>MultiWindow</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="35"/>
<location filename="qml/page/T_MultiWindow.qml" line="36"/>
<source>&lt;font color=&apos;red&apos;&gt;Standard&lt;/font&gt; mode windowa new window is created every time</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="38"/>
<location filename="qml/page/T_MultiWindow.qml" line="62"/>
<location filename="qml/page/T_MultiWindow.qml" line="85"/>
<location filename="qml/page/T_MultiWindow.qml" line="119"/>
<location filename="qml/page/T_MultiWindow.qml" line="154"/>
<location filename="qml/page/T_MultiWindow.qml" line="39"/>
<location filename="qml/page/T_MultiWindow.qml" line="63"/>
<location filename="qml/page/T_MultiWindow.qml" line="86"/>
<location filename="qml/page/T_MultiWindow.qml" line="120"/>
<location filename="qml/page/T_MultiWindow.qml" line="155"/>
<source>Create Window</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="58"/>
<location filename="qml/page/T_MultiWindow.qml" line="59"/>
<source>&lt;font color=&apos;red&apos;&gt;SingleTask&lt;/font&gt; mode windowIf a window exists, this activates the window</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="82"/>
<location filename="qml/page/T_MultiWindow.qml" line="83"/>
<source>&lt;font color=&apos;red&apos;&gt;SingleInstance&lt;/font&gt; mode windowIf the window exists, destroy the window and create a new window</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="116"/>
<location filename="qml/page/T_MultiWindow.qml" line="117"/>
<source>Create the window without carrying any parameters</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="151"/>
<location filename="qml/page/T_MultiWindow.qml" line="152"/>
<source>Create a window with the parameter username: zhuzichu</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="160"/>
<location filename="qml/page/T_MultiWindow.qml" line="161"/>
<source>Login Window Returned Password - &gt;</source>
<translation type="unfinished"></translation>
</message>
@ -1568,7 +1569,7 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
<context>
<name>T_Network</name>
<message>
<location filename="qml/page/T_Network.qml" line="12"/>
<location filename="qml/page/T_Network.qml" line="13"/>
<source>Network</source>
<translation type="unfinished"></translation>
</message>
@ -1735,97 +1736,97 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
<context>
<name>T_Settings</name>
<message>
<location filename="qml/page/T_Settings.qml" line="12"/>
<location filename="qml/page/T_Settings.qml" line="11"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="43"/>
<location filename="qml/page/T_Settings.qml" line="29"/>
<source>Current Version</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="49"/>
<location filename="qml/page/T_Settings.qml" line="35"/>
<source>Check for Updates</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="65"/>
<location filename="qml/page/T_Settings.qml" line="51"/>
<source>Use System AppBar</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="81"/>
<location filename="qml/page/T_Settings.qml" line="67"/>
<source>Fits AppBar Windows</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="92"/>
<location filename="qml/page/T_Settings.qml" line="78"/>
<source>Friendly Reminder</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="93"/>
<location filename="qml/page/T_Settings.qml" line="79"/>
<source>This action requires a restart of the program to take effect, is it restarted?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="95"/>
<location filename="qml/page/T_Settings.qml" line="81"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="96"/>
<location filename="qml/page/T_Settings.qml" line="82"/>
<source>OK</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="115"/>
<location filename="qml/page/T_Settings.qml" line="101"/>
<source>Dark Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="120"/>
<location filename="qml/page/T_Settings.qml" line="106"/>
<source>System</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="120"/>
<location filename="qml/page/T_Settings.qml" line="106"/>
<source>Light</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="120"/>
<location filename="qml/page/T_Settings.qml" line="106"/>
<source>Dark</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="145"/>
<location filename="qml/page/T_Settings.qml" line="131"/>
<source>Navigation View Display Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="150"/>
<location filename="qml/page/T_Settings.qml" line="136"/>
<source>Open</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="150"/>
<location filename="qml/page/T_Settings.qml" line="136"/>
<source>Compact</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="150"/>
<location filename="qml/page/T_Settings.qml" line="136"/>
<source>Minimal</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="150"/>
<location filename="qml/page/T_Settings.qml" line="136"/>
<source>Auto</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="185"/>
<location filename="qml/page/T_Settings.qml" line="171"/>
<source>Language</source>
<translation type="unfinished"></translation>
</message>
@ -2023,36 +2024,36 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
<context>
<name>T_TextBox</name>
<message>
<location filename="qml/page/T_TextBox.qml" line="11"/>
<location filename="qml/page/T_TextBox.qml" line="10"/>
<source>TextBox</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TextBox.qml" line="24"/>
<location filename="qml/page/T_TextBox.qml" line="19"/>
<source>Single-line Input Box</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TextBox.qml" line="43"/>
<location filename="qml/page/T_TextBox.qml" line="74"/>
<location filename="qml/page/T_TextBox.qml" line="112"/>
<location filename="qml/page/T_TextBox.qml" line="143"/>
<location filename="qml/page/T_TextBox.qml" line="172"/>
<location filename="qml/page/T_TextBox.qml" line="34"/>
<location filename="qml/page/T_TextBox.qml" line="65"/>
<location filename="qml/page/T_TextBox.qml" line="98"/>
<location filename="qml/page/T_TextBox.qml" line="129"/>
<location filename="qml/page/T_TextBox.qml" line="158"/>
<source>Disabled</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TextBox.qml" line="61"/>
<location filename="qml/page/T_TextBox.qml" line="52"/>
<source>Please enter your password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TextBox.qml" line="94"/>
<location filename="qml/page/T_TextBox.qml" line="84"/>
<source>Multi-line Input Box</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_TextBox.qml" line="129"/>
<location filename="qml/page/T_TextBox.qml" line="115"/>
<source>AutoSuggestBox</source>
<translation type="unfinished"></translation>
</message>

View File

@ -535,104 +535,104 @@
<context>
<name>MainWindow</name>
<message>
<location filename="qml/window/MainWindow.qml" line="322"/>
<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="98"/>
<location filename="qml/window/MainWindow.qml" line="106"/>
<location filename="qml/window/MainWindow.qml" line="83"/>
<location filename="qml/window/MainWindow.qml" line="91"/>
<source>Quit</source>
<translation type="unfinished">退</translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="99"/>
<location filename="qml/window/MainWindow.qml" line="84"/>
<source>Are you sure you want to exit the program?</source>
<translation type="unfinished">退</translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="100"/>
<location filename="qml/window/MainWindow.qml" line="85"/>
<source>Minimize</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="103"/>
<location filename="qml/window/MainWindow.qml" line="88"/>
<source>Friendly Reminder</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="103"/>
<location filename="qml/window/MainWindow.qml" line="88"/>
<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="107"/>
<location filename="qml/window/MainWindow.qml" line="351"/>
<location filename="qml/window/MainWindow.qml" line="92"/>
<location filename="qml/window/MainWindow.qml" line="336"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="118"/>
<location filename="qml/window/MainWindow.qml" line="103"/>
<source>Open in Separate Window</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="215"/>
<location filename="qml/window/MainWindow.qml" line="200"/>
<source>Click Time</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="225"/>
<location filename="qml/window/MainWindow.qml" line="210"/>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="316"/>
<location filename="qml/window/MainWindow.qml" line="301"/>
<source>Finish</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="317"/>
<location filename="qml/window/MainWindow.qml" line="302"/>
<source>Next</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="318"/>
<location filename="qml/window/MainWindow.qml" line="303"/>
<source>Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="322"/>
<location filename="qml/window/MainWindow.qml" line="307"/>
<source>Here you can switch to night mode.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="324"/>
<location filename="qml/window/MainWindow.qml" line="309"/>
<source>Hide Easter eggs</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="324"/>
<location filename="qml/window/MainWindow.qml" line="309"/>
<source>Try a few more clicks!!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="348"/>
<location filename="qml/window/MainWindow.qml" line="333"/>
<source>Upgrade Tips</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="349"/>
<location filename="qml/window/MainWindow.qml" line="334"/>
<source>FluentUI is currently up to date </source>
<translation type="unfinished">FluentUI </translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="349"/>
<location filename="qml/window/MainWindow.qml" line="334"/>
<source> -- The current app version</source>
<translation type="unfinished"> -- </translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="349"/>
<location filename="qml/window/MainWindow.qml" line="334"/>
<source>
Now go and download the new version
@ -645,17 +645,17 @@ Updated content:
</translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="352"/>
<location filename="qml/window/MainWindow.qml" line="337"/>
<source>OK</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="379"/>
<location filename="qml/window/MainWindow.qml" line="364"/>
<source>The current version is already the latest</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/window/MainWindow.qml" line="386"/>
<location filename="qml/window/MainWindow.qml" line="371"/>
<source>The network is abnormal</source>
<translation type="unfinished"></translation>
</message>
@ -1153,8 +1153,8 @@ Updated content:
<name>T_DatePicker</name>
<message>
<location filename="qml/page/T_DatePicker.qml" line="10"/>
<source>TimePicker</source>
<translation type="unfinished"></translation>
<source>DatePicker</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_DatePicker.qml" line="23"/>
@ -1561,46 +1561,46 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
<context>
<name>T_MultiWindow</name>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="13"/>
<location filename="qml/page/T_MultiWindow.qml" line="12"/>
<source>MultiWindow</source>
<translation type="unfinished">多窗口</translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="35"/>
<location filename="qml/page/T_MultiWindow.qml" line="36"/>
<source>&lt;font color=&apos;red&apos;&gt;Standard&lt;/font&gt; mode windowa new window is created every time</source>
<translation type="unfinished">&lt;font color=&apos;red&apos;&gt;Standard&lt;/font&gt; 模式窗口,每次都会创建新窗口</translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="38"/>
<location filename="qml/page/T_MultiWindow.qml" line="62"/>
<location filename="qml/page/T_MultiWindow.qml" line="85"/>
<location filename="qml/page/T_MultiWindow.qml" line="119"/>
<location filename="qml/page/T_MultiWindow.qml" line="154"/>
<location filename="qml/page/T_MultiWindow.qml" line="39"/>
<location filename="qml/page/T_MultiWindow.qml" line="63"/>
<location filename="qml/page/T_MultiWindow.qml" line="86"/>
<location filename="qml/page/T_MultiWindow.qml" line="120"/>
<location filename="qml/page/T_MultiWindow.qml" line="155"/>
<source>Create Window</source>
<translation type="unfinished">创建窗口</translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="58"/>
<location filename="qml/page/T_MultiWindow.qml" line="59"/>
<source>&lt;font color=&apos;red&apos;&gt;SingleTask&lt;/font&gt; mode windowIf a window exists, this activates the window</source>
<translation type="unfinished">&lt;font color=&apos;red&apos;&gt;SingleTask&lt;/font&gt; 模式窗口,如果窗口存在,这激活该窗口</translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="82"/>
<location filename="qml/page/T_MultiWindow.qml" line="83"/>
<source>&lt;font color=&apos;red&apos;&gt;SingleInstance&lt;/font&gt; mode windowIf the window exists, destroy the window and create a new window</source>
<translation type="unfinished">&lt;font color=&apos;red&apos;&gt;SingleInstance&lt;/font&gt; 模式窗口,如果窗口存在,则销毁窗口,然后新建窗口</translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="116"/>
<location filename="qml/page/T_MultiWindow.qml" line="117"/>
<source>Create the window without carrying any parameters</source>
<translation type="unfinished">创建一个窗口,不携带任何参数</translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="151"/>
<location filename="qml/page/T_MultiWindow.qml" line="152"/>
<source>Create a window with the parameter username: zhuzichu</source>
<translation type="unfinished">创建一个窗口并携带参数用户名zhuzichu</translation>
</message>
<message>
<location filename="qml/page/T_MultiWindow.qml" line="160"/>
<location filename="qml/page/T_MultiWindow.qml" line="161"/>
<source>Login Window Returned Password - &gt;</source>
<translation type="unfinished">登录窗口返回过来的密码 - &gt;</translation>
</message>
@ -1608,7 +1608,7 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
<context>
<name>T_Network</name>
<message>
<location filename="qml/page/T_Network.qml" line="12"/>
<location filename="qml/page/T_Network.qml" line="13"/>
<source>Network</source>
<translation type="unfinished">网络</translation>
</message>
@ -1785,97 +1785,97 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
<context>
<name>T_Settings</name>
<message>
<location filename="qml/page/T_Settings.qml" line="12"/>
<location filename="qml/page/T_Settings.qml" line="11"/>
<source>Settings</source>
<translation type="unfinished">设置</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="43"/>
<location filename="qml/page/T_Settings.qml" line="29"/>
<source>Current Version</source>
<translation type="unfinished">当前版本</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="49"/>
<location filename="qml/page/T_Settings.qml" line="35"/>
<source>Check for Updates</source>
<translation type="unfinished">检查更新</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="65"/>
<location filename="qml/page/T_Settings.qml" line="51"/>
<source>Use System AppBar</source>
<translation type="unfinished">使用系统应用栏</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="81"/>
<location filename="qml/page/T_Settings.qml" line="67"/>
<source>Fits AppBar Windows</source>
<translation type="unfinished">沉浸式应用栏</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="92"/>
<location filename="qml/page/T_Settings.qml" line="78"/>
<source>Friendly Reminder</source>
<translation type="unfinished">友情提示</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="93"/>
<location filename="qml/page/T_Settings.qml" line="79"/>
<source>This action requires a restart of the program to take effect, is it restarted?</source>
<translation type="unfinished">此操作需要重启程序才能生效,是否重新启动?</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="95"/>
<location filename="qml/page/T_Settings.qml" line="81"/>
<source>Cancel</source>
<translation type="unfinished">取消</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="96"/>
<location filename="qml/page/T_Settings.qml" line="82"/>
<source>OK</source>
<translation type="unfinished">确定</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="115"/>
<location filename="qml/page/T_Settings.qml" line="101"/>
<source>Dark Mode</source>
<translation type="unfinished">夜间模式</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="120"/>
<location filename="qml/page/T_Settings.qml" line="106"/>
<source>System</source>
<translation type="unfinished">跟随系统</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="120"/>
<location filename="qml/page/T_Settings.qml" line="106"/>
<source>Light</source>
<translation type="unfinished">浅色</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="120"/>
<location filename="qml/page/T_Settings.qml" line="106"/>
<source>Dark</source>
<translation type="unfinished">深色</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="145"/>
<location filename="qml/page/T_Settings.qml" line="131"/>
<source>Navigation View Display Mode</source>
<translation type="unfinished">导航视图</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="150"/>
<location filename="qml/page/T_Settings.qml" line="136"/>
<source>Open</source>
<translation type="unfinished">开放</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="150"/>
<location filename="qml/page/T_Settings.qml" line="136"/>
<source>Compact</source>
<translation type="unfinished">紧凑</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="150"/>
<location filename="qml/page/T_Settings.qml" line="136"/>
<source>Minimal</source>
<translation type="unfinished">极简</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="150"/>
<location filename="qml/page/T_Settings.qml" line="136"/>
<source>Auto</source>
<translation type="unfinished">自动</translation>
</message>
<message>
<location filename="qml/page/T_Settings.qml" line="185"/>
<location filename="qml/page/T_Settings.qml" line="171"/>
<source>Language</source>
<translation type="unfinished">语言</translation>
</message>
@ -2093,36 +2093,36 @@ My only desire is to be permitted to drive out the traitors and restore the Han.
<context>
<name>T_TextBox</name>
<message>
<location filename="qml/page/T_TextBox.qml" line="11"/>
<location filename="qml/page/T_TextBox.qml" line="10"/>
<source>TextBox</source>
<translation type="unfinished">文本框</translation>
</message>
<message>
<location filename="qml/page/T_TextBox.qml" line="24"/>
<location filename="qml/page/T_TextBox.qml" line="19"/>
<source>Single-line Input Box</source>
<translation type="unfinished">单行输入框</translation>
</message>
<message>
<location filename="qml/page/T_TextBox.qml" line="43"/>
<location filename="qml/page/T_TextBox.qml" line="74"/>
<location filename="qml/page/T_TextBox.qml" line="112"/>
<location filename="qml/page/T_TextBox.qml" line="143"/>
<location filename="qml/page/T_TextBox.qml" line="172"/>
<location filename="qml/page/T_TextBox.qml" line="34"/>
<location filename="qml/page/T_TextBox.qml" line="65"/>
<location filename="qml/page/T_TextBox.qml" line="98"/>
<location filename="qml/page/T_TextBox.qml" line="129"/>
<location filename="qml/page/T_TextBox.qml" line="158"/>
<source>Disabled</source>
<translation type="unfinished">禁用</translation>
</message>
<message>
<location filename="qml/page/T_TextBox.qml" line="61"/>
<location filename="qml/page/T_TextBox.qml" line="52"/>
<source>Please enter your password</source>
<translation type="unfinished">请输入您的密码</translation>
</message>
<message>
<location filename="qml/page/T_TextBox.qml" line="94"/>
<location filename="qml/page/T_TextBox.qml" line="84"/>
<source>Multi-line Input Box</source>
<translation type="unfinished">多行输入框</translation>
</message>
<message>
<location filename="qml/page/T_TextBox.qml" line="129"/>
<location filename="qml/page/T_TextBox.qml" line="115"/>
<source>AutoSuggestBox</source>
<translation type="unfinished">自动建议框</translation>
</message>

View File

@ -4,33 +4,29 @@ import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import FluentUI 1.0
Item {
FluLauncher {
id: app
Connections{
target: FluTheme
function onDarkModeChanged(){
SettingsHelper.saveDarkMode(FluTheme.darkMode)
}
}
Connections{
target: FluApp
function onUseSystemAppBarChanged(){
SettingsHelper.saveUseSystemAppBar(FluApp.useSystemAppBar)
}
}
Connections{
target: TranslateHelper
function onCurrentChanged(){
SettingsHelper.saveLanguage(TranslateHelper.current)
}
}
Component.onCompleted: {
FluNetwork.openLog = false
FluNetwork.setInterceptor(function(param){
Network.openLog = false
Network.setInterceptor(function(param){
param.addHeader("Token","000000000000000000000")
})
FluApp.init(app,Qt.locale(TranslateHelper.current))
@ -38,7 +34,7 @@ Item {
FluApp.useSystemAppBar = SettingsHelper.getUseSystemAppBar()
FluTheme.darkMode = SettingsHelper.getDarkMode()
FluTheme.enableAnimation = true
FluApp.routes = {
FluRouter.routes = {
"/":"qrc:/example/qml/window/MainWindow.qml",
"/about":"qrc:/example/qml/window/AboutWindow.qml",
"/login":"qrc:/example/qml/window/LoginWindow.qml",
@ -51,9 +47,9 @@ Item {
}
var args = Qt.application.arguments
if(args.length>=2 && args[1].startsWith("-crashed=")){
FluApp.navigate("/crash",{crashFilePath:args[1].replace("-crashed=","")})
FluRouter.navigate("/crash",{crashFilePath:args[1].replace("-crashed=","")})
}else{
FluApp.navigate("/")
FluRouter.navigate("/")
}
}
}

View File

@ -135,7 +135,9 @@ FluExpander{
"FluLoadingButton",
"FluClip",
"FluNetwork",
"FluShortcutPicker"
"FluShortcutPicker",
"FluWindowResultLauncher",
"FluRouter"
];
code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;");

View File

@ -0,0 +1,10 @@
pragma Singleton
import QtQuick 2.15
import FluentUI 1.0
QtObject{
property int displayMode: FluNavigationViewType.Auto
}

View File

@ -16,7 +16,7 @@ FluObject{
title:qsTr("About")
icon:FluentIcons.Contact
onTapListener:function(){
FluApp.navigate("/about")
FluRouter.navigate("/about")
}
}

View File

@ -462,7 +462,7 @@ FluObject{
FluPaneItem{
title: qsTr("Hot Loader")
onTapListener: function(){
FluApp.navigate("/hotload")
FluRouter.navigate("/hotload")
}
}
FluPaneItem{

View File

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

View File

@ -7,7 +7,7 @@ import "../component"
FluScrollablePage{
title: qsTr("TimePicker")
title: qsTr("DatePicker")
FluArea{
Layout.fillWidth: true

View File

@ -8,16 +8,17 @@ import "../component"
FluScrollablePage{
property string password: ""
property var loginPageRegister: registerForWindowResult("/login")
title: qsTr("MultiWindow")
Connections{
target: loginPageRegister
function onResult(data)
{
password = data.password
}
FluWindowResultLauncher{
id:loginResultLauncher
path: "/login"
onResult:
(data)=>{
password = data.password
}
}
FluArea{
@ -37,7 +38,7 @@ FluScrollablePage{
FluButton{
text: qsTr("Create Window")
onClicked: {
FluApp.navigate("/standardWindow")
FluRouter.navigate("/standardWindow")
}
}
}
@ -61,7 +62,7 @@ FluScrollablePage{
FluButton{
text: qsTr("Create Window")
onClicked: {
FluApp.navigate("/singleTaskWindow")
FluRouter.navigate("/singleTaskWindow")
}
}
}
@ -84,7 +85,7 @@ FluScrollablePage{
FluButton{
text: qsTr("Create Window")
onClicked: {
FluApp.navigate("/singleInstanceWindow")
FluRouter.navigate("/singleInstanceWindow")
}
}
}
@ -118,7 +119,7 @@ FluScrollablePage{
FluButton{
text: qsTr("Create Window")
onClicked: {
FluApp.navigate("/about")
FluRouter.navigate("/about")
}
}
}
@ -129,7 +130,7 @@ FluScrollablePage{
code:'FluButton{
text: qsTr("Create Window")
onClicked: {
FluApp.navigate("/about")
FluRouter.navigate("/about")
}
}
'
@ -153,7 +154,7 @@ FluScrollablePage{
FluButton{
text: qsTr("Create Window")
onClicked: {
loginPageRegister.launch({username:"zhuzichu"})
loginResultLauncher.launch({username:"zhuzichu"})
}
}
FluText{
@ -164,20 +165,19 @@ FluScrollablePage{
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'property var loginPageRegister: registerForWindowResult("/login")
Connections{
target: loginPageRegister
function onResult(data)
{
password = data.password
}
code:'FluWindowResultLauncher{
id:loginResultLauncher
path: "/login"
onResult:
(data)=>{
password = data.password
}
}
FluButton{
text: qsTr("Create Window")
onClicked: {
loginPageRegister.launch({username:"zhuzichu"})
loginResultLauncher.launch({username:"zhuzichu"})
}
}
'

View File

@ -4,6 +4,7 @@ import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import Qt.labs.platform 1.0
import example 1.0
import "../component"
FluContentPage{
@ -11,7 +12,7 @@ FluContentPage{
id:root
title: qsTr("Network")
FluNetworkCallable{
NetworkCallable{
id:callable
onStart: {
showLoading()
@ -56,7 +57,7 @@ FluContentPage{
text: "Get"
onClicked: {
text_info.text = ""
FluNetwork.get("https://httpbingo.org/get")
Network.get("https://httpbingo.org/get")
.addQuery("name","孙悟空")
.addQuery("age",500)
.addQuery("address","花果山水帘洞")
@ -70,7 +71,7 @@ FluContentPage{
text: "Head"
onClicked: {
text_info.text = ""
FluNetwork.head("https://httpbingo.org/head")
Network.head("https://httpbingo.org/head")
.addQuery("name","孙悟空")
.addQuery("age",500)
.addQuery("address","花果山水帘洞")
@ -84,7 +85,7 @@ FluContentPage{
text: "Post Body"
onClicked: {
text_info.text = ""
FluNetwork.postBody("https://httpbingo.org/post")
Network.postBody("https://httpbingo.org/post")
.setBody("花果山水帘洞美猴王齐天大圣孙悟空")
.bind(root)
.go(callable)
@ -96,7 +97,7 @@ FluContentPage{
text: "Post Form"
onClicked: {
text_info.text = ""
FluNetwork.postForm("https://httpbingo.org/post")
Network.postForm("https://httpbingo.org/post")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -110,7 +111,7 @@ FluContentPage{
text: "Post JSON"
onClicked: {
text_info.text = ""
FluNetwork.postJson("https://httpbingo.org/post")
Network.postJson("https://httpbingo.org/post")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -124,7 +125,7 @@ FluContentPage{
text: "Post JSON Array"
onClicked: {
text_info.text = ""
FluNetwork.postJsonArray("https://httpbingo.org/post")
Network.postJsonArray("https://httpbingo.org/post")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -138,7 +139,7 @@ FluContentPage{
text: "Put Body"
onClicked: {
text_info.text = ""
FluNetwork.putBody("https://httpbingo.org/put")
Network.putBody("https://httpbingo.org/put")
.setBody("花果山水帘洞美猴王齐天大圣孙悟空")
.bind(root)
.go(callable)
@ -150,7 +151,7 @@ FluContentPage{
text: "Put Form"
onClicked: {
text_info.text = ""
FluNetwork.putForm("https://httpbingo.org/put")
Network.putForm("https://httpbingo.org/put")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -164,7 +165,7 @@ FluContentPage{
text: "Put JSON"
onClicked: {
text_info.text = ""
FluNetwork.putJson("https://httpbingo.org/put")
Network.putJson("https://httpbingo.org/put")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -178,7 +179,7 @@ FluContentPage{
text: "Put JSON Array"
onClicked: {
text_info.text = ""
FluNetwork.putJsonArray("https://httpbingo.org/put")
Network.putJsonArray("https://httpbingo.org/put")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -192,7 +193,7 @@ FluContentPage{
text: "Patch Body"
onClicked: {
text_info.text = ""
FluNetwork.patchBody("https://httpbingo.org/patch")
Network.patchBody("https://httpbingo.org/patch")
.setBody("花果山水帘洞美猴王齐天大圣孙悟空")
.bind(root)
.go(callable)
@ -204,7 +205,7 @@ FluContentPage{
text: "Patch Form"
onClicked: {
text_info.text = ""
FluNetwork.patchForm("https://httpbingo.org/patch")
Network.patchForm("https://httpbingo.org/patch")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -218,7 +219,7 @@ FluContentPage{
text: "Patch JSON"
onClicked: {
text_info.text = ""
FluNetwork.patchJson("https://httpbingo.org/patch")
Network.patchJson("https://httpbingo.org/patch")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -232,7 +233,7 @@ FluContentPage{
text: "Patch JSON Array"
onClicked: {
text_info.text = ""
FluNetwork.patchJsonArray("https://httpbingo.org/patch")
Network.patchJsonArray("https://httpbingo.org/patch")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -246,7 +247,7 @@ FluContentPage{
text: "Delete Body"
onClicked: {
text_info.text = ""
FluNetwork.deleteBody("https://httpbingo.org/delete")
Network.deleteBody("https://httpbingo.org/delete")
.setBody("花果山水帘洞美猴王齐天大圣孙悟空")
.bind(root)
.go(callable)
@ -258,7 +259,7 @@ FluContentPage{
text: "Delete Form"
onClicked: {
text_info.text = ""
FluNetwork.deleteForm("https://httpbingo.org/delete")
Network.deleteForm("https://httpbingo.org/delete")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -272,7 +273,7 @@ FluContentPage{
text: "Delete JSON"
onClicked: {
text_info.text = ""
FluNetwork.deleteJson("https://httpbingo.org/delete")
Network.deleteJson("https://httpbingo.org/delete")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -286,7 +287,7 @@ FluContentPage{
text: "Delete JSON Array"
onClicked: {
text_info.text = ""
FluNetwork.deleteJsonArray("https://httpbingo.org/delete")
Network.deleteJsonArray("https://httpbingo.org/delete")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -300,7 +301,7 @@ FluContentPage{
text: "Open Log"
onClicked: {
text_info.text = ""
FluNetwork.postJson("https://httpbingo.org/post")
Network.postJson("https://httpbingo.org/post")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -315,7 +316,7 @@ FluContentPage{
text: "Custom Header"
onClicked: {
text_info.text = ""
FluNetwork.postJson("https://httpbingo.org/post")
Network.postJson("https://httpbingo.org/post")
.addHeader("os","PC")
.addHeader("version","1.0.0")
.add("name","孙悟空")
@ -331,8 +332,8 @@ FluContentPage{
text: "RequestFailedReadCache"
onClicked: {
text_info.text = ""
FluNetwork.postJson("https://httpbingo.org/post")
.setCacheMode(FluNetworkType.RequestFailedReadCache)
Network.postJson("https://httpbingo.org/post")
.setCacheMode(NetworkType.RequestFailedReadCache)
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -347,8 +348,8 @@ FluContentPage{
text: "IfNoneCacheRequest"
onClicked: {
text_info.text = ""
FluNetwork.postJson("https://httpbingo.org/post")
.setCacheMode(FluNetworkType.IfNoneCacheRequest)
Network.postJson("https://httpbingo.org/post")
.setCacheMode(NetworkType.IfNoneCacheRequest)
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -363,8 +364,8 @@ FluContentPage{
text: "FirstCacheThenRequest"
onClicked: {
text_info.text = ""
FluNetwork.postJson("https://httpbingo.org/post")
.setCacheMode(FluNetworkType.FirstCacheThenRequest)
Network.postJson("https://httpbingo.org/post")
.setCacheMode(NetworkType.FirstCacheThenRequest)
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
@ -379,7 +380,7 @@ FluContentPage{
text: "Timeout And Retry"
onClicked: {
text_info.text = ""
FluNetwork.postJson("https://httpbingo.org/post")
Network.postJson("https://httpbingo.org/post")
.setTimeout(5000)
.setRetry(3)
.add("name","孙悟空")
@ -407,7 +408,7 @@ FluContentPage{
text: "Download File"
onClicked: {
folder_dialog.showDialog(function(path){
FluNetwork.get("http://vjs.zencdn.net/v/oceans.mp4")
Network.get("http://vjs.zencdn.net/v/oceans.mp4")
.toDownload(path)
.bind(root)
.go(callable_download_file)
@ -421,7 +422,7 @@ FluContentPage{
text: "Breakpoint Download File"
onClicked: {
folder_dialog.showDialog(function(path){
FluNetwork.get("http://vjs.zencdn.net/v/oceans.mp4")
Network.get("http://vjs.zencdn.net/v/oceans.mp4")
.toDownload(path,true)
.bind(root)
.go(callable_breakpoint_download_file)
@ -431,7 +432,7 @@ FluContentPage{
}
}
FluNetworkCallable{
NetworkCallable{
id:callable_upload_file
onStart: {
btn_upload.disabled = true
@ -455,7 +456,7 @@ FluContentPage{
}
}
FluNetworkCallable{
NetworkCallable{
id:callable_download_file
onStart: {
btn_download.progress = 0
@ -480,7 +481,7 @@ FluContentPage{
}
}
FluNetworkCallable{
NetworkCallable{
id:callable_breakpoint_download_file
onStart: {
btn_download_breakpoint.progress = 0
@ -508,7 +509,7 @@ FluContentPage{
FileDialog {
id: file_dialog
onAccepted: {
FluNetwork.postForm("https://httpbingo.org/post")
Network.postForm("https://httpbingo.org/post")
.setRetry(1)//只请求一次
.add("accessToken","12345678")
.addFile("file",FluTools.toLocalPath(file_dialog.currentFile))

View File

@ -4,33 +4,19 @@ import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import "../component"
import "../viewmodel"
import "../global"
FluScrollablePage{
title: qsTr("Settings")
SettingsViewModel{
id:viewmodel_settings
}
FluEvent{
id:event_checkupdate_finish
name: "checkUpdateFinish"
onTriggered: {
btn_checkupdate.loading = false
}
}
Component.onCompleted: {
FluEventBus.registerEvent(event_checkupdate_finish)
}
Component.onDestruction: {
FluEventBus.unRegisterEvent(event_checkupdate_finish)
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
@ -95,7 +81,7 @@ FluScrollablePage{
negativeText: qsTr("Cancel")
positiveText: qsTr("OK")
onPositiveClicked: {
FluApp.exit(931)
FluRouter.exit(931)
}
}
@ -149,10 +135,10 @@ FluScrollablePage{
Repeater{
model: [{title:qsTr("Open"),mode:FluNavigationViewType.Open},{title:qsTr("Compact"),mode:FluNavigationViewType.Compact},{title:qsTr("Minimal"),mode:FluNavigationViewType.Minimal},{title:qsTr("Auto"),mode:FluNavigationViewType.Auto}]
delegate: FluRadioButton{
checked : viewmodel_settings.displayMode===modelData.mode
text:modelData.title
text: modelData.title
checked: GlobalModel.displayMode === modelData.mode
clickListener:function(){
viewmodel_settings.displayMode = modelData.mode
GlobalModel.displayMode = modelData.mode
}
}
}

View File

@ -4,16 +4,11 @@ import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import FluentUI 1.0
import "../component"
import "../viewmodel"
FluScrollablePage{
title: qsTr("TextBox")
TextBoxViewModel{
id:viewModel
}
FluArea{
Layout.fillWidth: true
height: 68
@ -24,10 +19,6 @@ FluScrollablePage{
placeholderText: qsTr("Single-line Input Box")
disabled: text_box_switch.checked
cleanEnabled: true
text: viewModel.text1
onTextChanged: {
viewModel.text1 = text
}
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
@ -82,7 +73,6 @@ FluScrollablePage{
}'
}
FluArea{
Layout.fillWidth: true
height: 36+multiine_textbox.height
@ -92,10 +82,6 @@ FluScrollablePage{
FluMultilineTextBox{
id: multiine_textbox
placeholderText: qsTr("Multi-line Input Box")
text:viewModel.text2
onTextChanged: {
viewModel.text2 = text
}
disabled: text_box_multi_switch.checked
anchors{
verticalCenter: parent.verticalCenter

View File

@ -1,14 +0,0 @@
import QtQuick 2.15
import FluentUI 1.0
FluViewModel{
objectName: "SettingsViewModel"
scope: FluViewModelType.Application
property int displayMode
onInitData: {
displayMode = FluNavigationViewType.Auto
}
}

View File

@ -1,8 +0,0 @@
import QtQuick 2.15
import FluentUI 1.0
FluViewModel {
objectName: "TextBoxView"
property string text1
property string text2
}

View File

@ -31,7 +31,7 @@ FluWindow {
MouseArea{
anchors.fill: parent
onClicked: {
FluApp.navigate("/")
FluRouter.navigate("/")
}
}
}

View File

@ -71,7 +71,7 @@ FluWindow {
FluFilledButton{
text: qsTr("Restart Program")
onClicked: {
FluApp.exit(931)
FluRouter.exit(931)
}
}
}

View File

@ -51,7 +51,7 @@ FluWindow {
showError(qsTr("Please feel free to enter a password"))
return
}
onResult({password:textbox_password.text})
setResult({password:textbox_password.text})
window.close()
}
}

View File

@ -7,7 +7,6 @@ import Qt.labs.platform 1.1
import FluentUI 1.0
import example 1.0
import "../component"
import "../viewmodel"
import "../global"
FluWindow {
@ -29,37 +28,23 @@ FluWindow {
z:7
}
SettingsViewModel{
id:viewmodel_settings
}
FluEvent{
id:event_checkupdate
name: "checkUpdate"
onTriggered: {
checkUpdate(false)
}
}
onFirstVisible: {
timer_tour_delay.restart()
}
Timer{
id:timer_tour_delay
interval: 200
onTriggered: {
tour.open()
}
onLazyLoad: {
tour.open()
}
Component.onCompleted: {
checkUpdate(true)
FluEventBus.registerEvent(event_checkupdate)
}
Component.onDestruction: {
FluEventBus.unRegisterEvent(event_checkupdate)
FluRouter.exit()
}
SystemTrayIcon {
@ -71,7 +56,7 @@ FluWindow {
MenuItem {
text: "退出"
onTriggered: {
FluApp.exit()
FluRouter.exit()
}
}
}
@ -106,7 +91,7 @@ FluWindow {
positiveText: qsTr("Quit")
neutralText: qsTr("Cancel")
onPositiveClicked:{
FluApp.exit(0)
FluRouter.exit(0)
}
}
@ -118,7 +103,7 @@ FluWindow {
text: qsTr("Open in Separate Window")
font.pixelSize: 12
onClicked: {
FluApp.navigate("/pageWindow",{title:modelData.title,url:modelData.url})
FluRouter.navigate("/pageWindow",{title:modelData.title,url:modelData.url})
}
}
}
@ -175,14 +160,14 @@ FluWindow {
}
}
Component.onCompleted: {
appBar.setHitTestVisible(layout_back_buttons)
window.setHitTestVisible(layout_back_buttons)
}
}
FluRemoteLoader{
id:loader
lazy: true
anchors.fill: parent
source: "https://zhu-zichu.gitee.io/Qt_168_LieflatPage.qml"
source: "https://zhu-zichu.gitee.io/Qt_174_LieflatPage.qml"
}
}
front: Item{
@ -197,7 +182,7 @@ FluWindow {
z:999
//Stack模式每次切换都会将页面压入栈中随着栈的页面增多消耗的内存也越多内存消耗多就会卡顿这时候就需要按返回将页面pop掉释放内存。该模式可以配合FluPage中的launchMode属性设置页面的启动模式
// pageMode: FluNavigationViewType.Stack
//NoStack模式每次切换都会销毁之前的页面然后创建一个新的页面只需消耗少量内存可以配合FluViewModel保存页面数据推荐
//NoStack模式每次切换都会销毁之前的页面然后创建一个新的页面只需消耗少量内存
pageMode: FluNavigationViewType.NoStack
items: ItemsOriginal
footerItems:ItemsFooter
@ -207,7 +192,7 @@ FluWindow {
}
return FluTools.isMacos() ? 20 : 0
}
displayMode:viewmodel_settings.displayMode
displayMode: GlobalModel.displayMode
logo: "qrc:/example/res/image/favicon.ico"
title:"FluentUI"
onLogoClicked:{
@ -233,9 +218,9 @@ FluWindow {
ItemsOriginal.paneItemMenu = nav_item_right_menu
ItemsFooter.navigationView = nav_view
ItemsFooter.paneItemMenu = nav_item_right_menu
appBar.setHitTestVisible(nav_view.buttonMenu)
appBar.setHitTestVisible(nav_view.buttonBack)
appBar.setHitTestVisible(nav_view.imageLogo)
window.setHitTestVisible(nav_view.buttonMenu)
window.setHitTestVisible(nav_view.buttonBack)
window.setHitTestVisible(nav_view.imageLogo)
setCurrentIndex(0)
}
}
@ -355,7 +340,7 @@ FluWindow {
}
}
FluNetworkCallable{
NetworkCallable{
id:callable
property bool silent: true
onStart: {
@ -391,7 +376,7 @@ FluWindow {
function checkUpdate(silent){
callable.silent = silent
FluNetwork.get("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
Network.get("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
.go(callable)
}
}

View File

@ -4,14 +4,14 @@ import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import FluentUI 1.0
Item {
FluLauncher {
id: app
Component.onCompleted: {
FluApp.init(app)
FluApp.windowIcon = "qrc:/logo.ico"
FluApp.routes = {
FluRouter.routes = {
"/":"qrc:/main.qml",
}
FluApp.navigate("/")
FluRouter.navigate("/")
}
}

View File

@ -98,7 +98,7 @@ if (CMAKE_BUILD_TYPE MATCHES "Release")
add_custom_target(Script-DeployRelease
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/dist
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/dist
COMMAND ${QT_DEPLOY_QT} ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME}.exe -qmldir=${CMAKE_CURRENT_LIST_DIR}
COMMAND ${QT_DEPLOY_QT} --qmldir=${CMAKE_CURRENT_LIST_DIR} --plugindir ${CMAKE_SOURCE_DIR}/dist/plugins --no-translations --compiler-runtime ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME}.exe
COMMENT "Windows Deploying Qt Dependencies After Build........."
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}

View File

@ -1,4 +1,4 @@
#include "FluNetwork.h"
#include "Network.h"
#include <QUrlQuery>
#include <QBuffer>
@ -18,11 +18,11 @@
#include <QEventLoop>
#include <QGuiApplication>
FluNetworkCallable::FluNetworkCallable(QObject *parent):QObject{parent}{
NetworkCallable::NetworkCallable(QObject *parent):QObject{parent}{
}
QString FluNetworkParams::method2String(){
QString NetworkParams::method2String(){
switch (_method) {
case METHOD_GET:
return "GET";
@ -41,25 +41,25 @@ QString FluNetworkParams::method2String(){
}
}
int FluNetworkParams::getTimeout(){
int NetworkParams::getTimeout(){
if(_timeout != -1){
return _timeout;
}
return FluNetwork::getInstance()->timeout();
return Network::getInstance()->timeout();
}
int FluNetworkParams::getRetry(){
int NetworkParams::getRetry(){
if(_retry != -1){
return _retry;
}
return FluNetwork::getInstance()->retry();
return Network::getInstance()->retry();
}
bool FluNetworkParams::getOpenLog(){
bool NetworkParams::getOpenLog(){
if(!_openLog.isNull()){
return _openLog.toBool();
}
return FluNetwork::getInstance()->openLog();
return Network::getInstance()->openLog();
}
FluDownloadParam::FluDownloadParam(QObject *parent)
@ -74,12 +74,12 @@ FluDownloadParam::FluDownloadParam(QString destPath,bool append,QObject *parent)
this->_append = append;
}
FluNetworkParams::FluNetworkParams(QObject *parent)
NetworkParams::NetworkParams(QObject *parent)
: QObject{parent}
{
}
FluNetworkParams::FluNetworkParams(QString url,Type type,Method method,QObject *parent)
NetworkParams::NetworkParams(QString url,Type type,Method method,QObject *parent)
: QObject{parent}
{
this->_method = method;
@ -87,62 +87,62 @@ FluNetworkParams::FluNetworkParams(QString url,Type type,Method method,QObject *
this->_type = type;
}
FluNetworkParams* FluNetworkParams::add(QString key,QVariant val){
NetworkParams* NetworkParams::add(QString key,QVariant val){
_paramMap.insert(key,val);
return this;
}
FluNetworkParams* FluNetworkParams::addFile(QString key,QVariant val){
NetworkParams* NetworkParams::addFile(QString key,QVariant val){
_fileMap.insert(key,val);
return this;
}
FluNetworkParams* FluNetworkParams::addHeader(QString key,QVariant val){
NetworkParams* NetworkParams::addHeader(QString key,QVariant val){
_headerMap.insert(key,val);
return this;
}
FluNetworkParams* FluNetworkParams::addQuery(QString key,QVariant val){
NetworkParams* NetworkParams::addQuery(QString key,QVariant val){
_queryMap.insert(key,val);
return this;
}
FluNetworkParams* FluNetworkParams::setBody(QString val){
NetworkParams* NetworkParams::setBody(QString val){
_body = val;
return this;
}
FluNetworkParams* FluNetworkParams::setTimeout(int val){
NetworkParams* NetworkParams::setTimeout(int val){
_timeout = val;
return this;
}
FluNetworkParams* FluNetworkParams::setRetry(int val){
NetworkParams* NetworkParams::setRetry(int val){
_retry = val;
return this;
}
FluNetworkParams* FluNetworkParams::setCacheMode(int val){
NetworkParams* NetworkParams::setCacheMode(int val){
_cacheMode = val;
return this;
}
FluNetworkParams* FluNetworkParams::toDownload(QString destPath,bool append){
NetworkParams* NetworkParams::toDownload(QString destPath,bool append){
_downloadParam = new FluDownloadParam(destPath,append,this);
return this;
}
FluNetworkParams* FluNetworkParams::bind(QObject* target){
NetworkParams* NetworkParams::bind(QObject* target){
_target = target;
return this;
}
FluNetworkParams* FluNetworkParams::openLog(QVariant val){
NetworkParams* NetworkParams::openLog(QVariant val){
_openLog = val;
return this;
}
QString FluNetworkParams::buildCacheKey(){
QString NetworkParams::buildCacheKey(){
QJsonObject obj;
obj.insert("url",_url);
obj.insert("method",method2String());
@ -161,30 +161,30 @@ QString FluNetworkParams::buildCacheKey(){
return QCryptographicHash::hash(data, QCryptographicHash::Sha256).toHex();
}
void FluNetworkParams::go(FluNetworkCallable* callable){
void NetworkParams::go(NetworkCallable* callable){
QJSValueList data;
data<<qjsEngine(callable)->newQObject(this);
FluNetwork::getInstance()->_interceptor.call(data);
Network::getInstance()->_interceptor.call(data);
if(_downloadParam){
FluNetwork::getInstance()->handleDownload(this,callable);
Network::getInstance()->handleDownload(this,callable);
}else{
FluNetwork::getInstance()->handle(this,callable);
Network::getInstance()->handle(this,callable);
}
}
void FluNetwork::handle(FluNetworkParams* params,FluNetworkCallable* c){
QPointer<FluNetworkCallable> callable(c);
void Network::handle(NetworkParams* params,NetworkCallable* c){
QPointer<NetworkCallable> callable(c);
QThreadPool::globalInstance()->start([=](){
if(!callable.isNull()){
callable->start();
}
QString cacheKey = params->buildCacheKey();
if(params->_cacheMode == FluNetworkType::CacheMode::FirstCacheThenRequest && cacheExists(cacheKey)){
if(params->_cacheMode == NetworkType::CacheMode::FirstCacheThenRequest && cacheExists(cacheKey)){
if(!callable.isNull()){
callable->cache(readCache(cacheKey));
}
}
if(params->_cacheMode == FluNetworkType::CacheMode::IfNoneCacheRequest && cacheExists(cacheKey)){
if(params->_cacheMode == NetworkType::CacheMode::IfNoneCacheRequest && cacheExists(cacheKey)){
if(!callable.isNull()){
callable->cache(readCache(cacheKey));
callable->finish();
@ -214,21 +214,21 @@ void FluNetwork::handle(FluNetworkParams* params,FluNetworkCallable* c){
reply->abort();
}
};
QMetaObject::Connection conn_destoryed = {};
QMetaObject::Connection conn_destroyed = {};
QMetaObject::Connection conn_quit = {};
if(params->_target){
conn_destoryed = connect(params->_target,&QObject::destroyed,&manager,abortCallable);
conn_destroyed = connect(params->_target,&QObject::destroyed,&manager,abortCallable);
}
conn_quit = connect(qApp,&QGuiApplication::aboutToQuit,&manager, abortCallable);
loop.exec();
if(conn_destoryed){
disconnect(conn_destoryed);
if(conn_destroyed){
disconnect(conn_destroyed);
}
if(conn_quit){
disconnect(conn_quit);
}
QString response;
if(params->_method == FluNetworkParams::METHOD_HEAD){
if(params->_method == NetworkParams::METHOD_HEAD){
response = headerList2String(reply->rawHeaderPairs());
}else{
if(reply->isOpen()){
@ -238,7 +238,7 @@ void FluNetwork::handle(FluNetworkParams* params,FluNetworkCallable* c){
int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if(httpStatus == 200){
if(!callable.isNull()){
if(params->_cacheMode != FluNetworkType::CacheMode::NoCache){
if(params->_cacheMode != NetworkType::CacheMode::NoCache){
saveResponse(cacheKey,response);
}
callable->success(response);
@ -248,7 +248,7 @@ void FluNetwork::handle(FluNetworkParams* params,FluNetworkCallable* c){
}else{
if(i == params->getRetry()-1){
if(!callable.isNull()){
if(params->_cacheMode == FluNetworkType::CacheMode::RequestFailedReadCache && cacheExists(cacheKey)){
if(params->_cacheMode == NetworkType::CacheMode::RequestFailedReadCache && cacheExists(cacheKey)){
if(!callable.isNull()){
callable->cache(readCache(cacheKey));
}
@ -267,8 +267,8 @@ void FluNetwork::handle(FluNetworkParams* params,FluNetworkCallable* c){
});
}
void FluNetwork::handleDownload(FluNetworkParams* params,FluNetworkCallable* c){
QPointer<FluNetworkCallable> callable(c);
void Network::handleDownload(NetworkParams* params,NetworkCallable* c){
QPointer<NetworkCallable> callable(c);
QThreadPool::globalInstance()->start([=](){
if(!callable.isNull()){
callable->start();
@ -336,10 +336,10 @@ void FluNetwork::handleDownload(FluNetworkParams* params,FluNetworkCallable* c){
};
connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();});
connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();});
QMetaObject::Connection conn_destoryed = {};
QMetaObject::Connection conn_destroyed = {};
QMetaObject::Connection conn_quit = {};
if(params->_target){
conn_destoryed = connect(params->_target,&QObject::destroyed,&manager,abortCallable);
conn_destroyed = connect(params->_target,&QObject::destroyed,&manager,abortCallable);
}
conn_quit = connect(qApp,&QGuiApplication::aboutToQuit,&manager, abortCallable);
connect(reply,&QNetworkReply::readyRead,reply,[reply,seek,destFile,cacheFile,callable]{
@ -377,8 +377,8 @@ void FluNetwork::handleDownload(FluNetworkParams* params,FluNetworkCallable* c){
}
printRequestEndLog(request,params,reply,destPath);
}
if(conn_destoryed){
disconnect(conn_destoryed);
if(conn_destroyed){
disconnect(conn_destroyed);
}
if(conn_quit){
disconnect(conn_quit);
@ -391,7 +391,7 @@ void FluNetwork::handleDownload(FluNetworkParams* params,FluNetworkCallable* c){
});
}
QString FluNetwork::readCache(const QString& key){
QString Network::readCache(const QString& key){
auto filePath = getCacheFilePath(key);
QString result;
QFile file(filePath);
@ -405,11 +405,11 @@ QString FluNetwork::readCache(const QString& key){
return result;
}
bool FluNetwork::cacheExists(const QString& key){
bool Network::cacheExists(const QString& key){
return QFile(getCacheFilePath(key)).exists();
}
QString FluNetwork::getCacheFilePath(const QString& key){
QString Network::getCacheFilePath(const QString& key){
QDir cacheDir(_cacheDir);
if(!cacheDir.exists()){
cacheDir.mkpath(_cacheDir);
@ -417,7 +417,7 @@ QString FluNetwork::getCacheFilePath(const QString& key){
return cacheDir.absoluteFilePath(key);
}
QString FluNetwork::headerList2String(const QList<QNetworkReply::RawHeaderPair>& data){
QString Network::headerList2String(const QList<QNetworkReply::RawHeaderPair>& data){
QJsonObject object;
for (auto it = data.constBegin(); it != data.constEnd(); ++it) {
object.insert(QString(it->first),QString(it->second));
@ -425,7 +425,7 @@ QString FluNetwork::headerList2String(const QList<QNetworkReply::RawHeaderPair>&
return QJsonDocument(object).toJson(QJsonDocument::Compact);
}
QString FluNetwork::map2String(const QMap<QString, QVariant>& map){
QString Network::map2String(const QMap<QString, QVariant>& map){
QStringList parameters;
for (auto it = map.constBegin(); it != map.constEnd(); ++it) {
parameters << QString("%1=%2").arg(it.key(), it.value().toString());
@ -433,10 +433,10 @@ QString FluNetwork::map2String(const QMap<QString, QVariant>& map){
return parameters.join(" ");
}
void FluNetwork::sendRequest(QNetworkAccessManager* manager,QNetworkRequest request,FluNetworkParams* params,QNetworkReply*& reply,bool isFirst,QPointer<FluNetworkCallable> callable){
void Network::sendRequest(QNetworkAccessManager* manager,QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,bool isFirst,QPointer<NetworkCallable> callable){
QByteArray verb = params->method2String().toUtf8();
switch (params->_type) {
case FluNetworkParams::TYPE_FORM:{
case NetworkParams::TYPE_FORM:{
bool isFormData = !params->_fileMap.isEmpty();
if(isFormData){
QHttpMultiPart *multiPart = new QHttpMultiPart();
@ -484,7 +484,7 @@ void FluNetwork::sendRequest(QNetworkAccessManager* manager,QNetworkRequest requ
}
break;
}
case FluNetworkParams::TYPE_JSON:{
case NetworkParams::TYPE_JSON:{
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/json;charset=utf-8"));
QJsonObject json;
for (const auto& each : params->_paramMap.toStdMap())
@ -495,7 +495,7 @@ void FluNetwork::sendRequest(QNetworkAccessManager* manager,QNetworkRequest requ
reply = manager->sendCustomRequest(request,verb,data);
break;
}
case FluNetworkParams::TYPE_JSONARRAY:{
case NetworkParams::TYPE_JSONARRAY:{
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/json;charset=utf-8"));
QJsonArray jsonArray;
for (const auto& each : params->_paramMap.toStdMap())
@ -508,7 +508,7 @@ void FluNetwork::sendRequest(QNetworkAccessManager* manager,QNetworkRequest requ
reply = manager->sendCustomRequest(request,params->method2String().toUtf8(),data);
break;
}
case FluNetworkParams::TYPE_BODY:{
case NetworkParams::TYPE_BODY:{
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("text/plain;charset=utf-8"));
QByteArray data = params->_body.toUtf8();
reply = manager->sendCustomRequest(request,verb,data);
@ -523,7 +523,7 @@ void FluNetwork::sendRequest(QNetworkAccessManager* manager,QNetworkRequest requ
}
}
void FluNetwork::printRequestStartLog(QNetworkRequest request,FluNetworkParams* params){
void Network::printRequestStartLog(QNetworkRequest request,NetworkParams* params){
if(!params->getOpenLog()){
return;
}
@ -551,7 +551,7 @@ void FluNetwork::printRequestStartLog(QNetworkRequest request,FluNetworkParams*
}
}
void FluNetwork::printRequestEndLog(QNetworkRequest request,FluNetworkParams* params,QNetworkReply*& reply,const QString& response){
void Network::printRequestEndLog(QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,const QString& response){
if(!params->getOpenLog()){
return;
}
@ -560,7 +560,7 @@ void FluNetwork::printRequestEndLog(QNetworkRequest request,FluNetworkParams* pa
qDebug()<<"<Result>"<<qUtf8Printable(response);
}
void FluNetwork::saveResponse(QString key,QString response){
void Network::saveResponse(QString key,QString response){
QSharedPointer<QFile> file(new QFile(getCacheFilePath(key)));
QIODevice::OpenMode mode = QIODevice::WriteOnly|QIODevice::Truncate;
if (!file->open(mode))
@ -570,7 +570,7 @@ void FluNetwork::saveResponse(QString key,QString response){
file->write(response.toUtf8().toBase64());
}
void FluNetwork::addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& headers){
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())
@ -580,7 +580,7 @@ void FluNetwork::addHeaders(QNetworkRequest* request,const QMap<QString, QVarian
}
}
void FluNetwork::addQueryParam(QUrl* url,const QMap<QString, QVariant>& params){
void Network::addQueryParam(QUrl* url,const QMap<QString, QVariant>& params){
QMapIterator<QString, QVariant> iter(params);
QUrlQuery urlQuery(*url);
while (iter.hasNext())
@ -591,7 +591,7 @@ void FluNetwork::addQueryParam(QUrl* url,const QMap<QString, QVariant>& params){
url->setQuery(urlQuery);
}
FluNetwork::FluNetwork(QObject *parent): QObject{parent}
Network::Network(QObject *parent): QObject{parent}
{
timeout(5000);
retry(3);
@ -599,78 +599,78 @@ FluNetwork::FluNetwork(QObject *parent): QObject{parent}
cacheDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation).append(QDir::separator()).append("network"));
}
FluNetworkParams* FluNetwork::get(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_NONE,FluNetworkParams::METHOD_GET,this);
NetworkParams* Network::get(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_NONE,NetworkParams::METHOD_GET,this);
}
FluNetworkParams* FluNetwork::head(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_NONE,FluNetworkParams::METHOD_HEAD,this);
NetworkParams* Network::head(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_NONE,NetworkParams::METHOD_HEAD,this);
}
FluNetworkParams* FluNetwork::postBody(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_BODY,FluNetworkParams::METHOD_POST,this);
NetworkParams* Network::postBody(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_POST,this);
}
FluNetworkParams* FluNetwork::putBody(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_BODY,FluNetworkParams::METHOD_PUT,this);
NetworkParams* Network::putBody(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_PUT,this);
}
FluNetworkParams* FluNetwork::patchBody(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_BODY,FluNetworkParams::METHOD_PATCH,this);
NetworkParams* Network::patchBody(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_PATCH,this);
}
FluNetworkParams* FluNetwork::deleteBody(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_BODY,FluNetworkParams::METHOD_DELETE,this);
NetworkParams* Network::deleteBody(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_DELETE,this);
}
FluNetworkParams* FluNetwork::postForm(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_FORM,FluNetworkParams::METHOD_POST,this);
NetworkParams* Network::postForm(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_POST,this);
}
FluNetworkParams* FluNetwork::putForm(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_FORM,FluNetworkParams::METHOD_PUT,this);
NetworkParams* Network::putForm(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_PUT,this);
}
FluNetworkParams* FluNetwork::patchForm(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_FORM,FluNetworkParams::METHOD_PATCH,this);
NetworkParams* Network::patchForm(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_PATCH,this);
}
FluNetworkParams* FluNetwork::deleteForm(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_FORM,FluNetworkParams::METHOD_DELETE,this);
NetworkParams* Network::deleteForm(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_DELETE,this);
}
FluNetworkParams* FluNetwork::postJson(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_JSON,FluNetworkParams::METHOD_POST,this);
NetworkParams* Network::postJson(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_POST,this);
}
FluNetworkParams* FluNetwork::putJson(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_JSON,FluNetworkParams::METHOD_PUT,this);
NetworkParams* Network::putJson(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_PUT,this);
}
FluNetworkParams* FluNetwork::patchJson(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_JSON,FluNetworkParams::METHOD_PATCH,this);
NetworkParams* Network::patchJson(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_PATCH,this);
}
FluNetworkParams* FluNetwork::deleteJson(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_JSON,FluNetworkParams::METHOD_DELETE,this);
NetworkParams* Network::deleteJson(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_DELETE,this);
}
FluNetworkParams* FluNetwork::postJsonArray(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_JSONARRAY,FluNetworkParams::METHOD_POST,this);
NetworkParams* Network::postJsonArray(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_POST,this);
}
FluNetworkParams* FluNetwork::putJsonArray(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_JSONARRAY,FluNetworkParams::METHOD_PUT,this);
NetworkParams* Network::putJsonArray(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_PUT,this);
}
FluNetworkParams* FluNetwork::patchJsonArray(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_JSONARRAY,FluNetworkParams::METHOD_PATCH,this);
NetworkParams* Network::patchJsonArray(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_PATCH,this);
}
FluNetworkParams* FluNetwork::deleteJsonArray(const QString& url){
return new FluNetworkParams(url,FluNetworkParams::TYPE_JSONARRAY,FluNetworkParams::METHOD_DELETE,this);
NetworkParams* Network::deleteJsonArray(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_DELETE,this);
}
void FluNetwork::setInterceptor(QJSValue interceptor){
void Network::setInterceptor(QJSValue interceptor){
this->_interceptor = interceptor;
}

View File

@ -0,0 +1,169 @@
#ifndef NETWORK_H
#define NETWORK_H
#include <QObject>
#include <QtQml/qqml.h>
#include <QFile>
#include <QJsonValue>
#include <QJSValue>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include "src/stdafx.h"
#include "src/singleton.h"
namespace NetworkType {
Q_NAMESPACE
enum CacheMode {
NoCache = 0x0000,
RequestFailedReadCache = 0x0001,
IfNoneCacheRequest = 0x0002,
FirstCacheThenRequest = 0x0004,
};
Q_ENUM_NS(CacheMode)
QML_NAMED_ELEMENT(NetworkType)
}
/**
* @brief The NetworkCallable class
*/
class NetworkCallable : public QObject{
Q_OBJECT
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);
};
/**
* @brief The FluDownloadParam class
*/
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;
};
/**
* @brief The NetworkParams class
*/
class NetworkParams : public QObject
{
Q_OBJECT
QML_NAMED_ELEMENT(NetworkParams)
public:
enum Method{
METHOD_GET,
METHOD_HEAD,
METHOD_POST,
METHOD_PUT,
METHOD_PATCH,
METHOD_DELETE
};
enum Type{
TYPE_NONE,
TYPE_FORM,
TYPE_JSON,
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* 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();
public:
FluDownloadParam* _downloadParam = nullptr;
QObject* _target = nullptr;
Method _method;
Type _type;
QString _url;
QString _body;
QMap<QString, QVariant> _queryMap;
QMap<QString, QVariant> _headerMap;
QMap<QString, QVariant> _paramMap;
QMap<QString, QVariant> _fileMap;
int _timeout = -1;
int _retry = -1;
QVariant _openLog;
int _cacheMode = NetworkType::CacheMode::NoCache;
};
/**
* @brief The Network class
*/
class Network : public QObject
{
Q_OBJECT
Q_PROPERTY_AUTO(int,timeout)
Q_PROPERTY_AUTO(int,retry)
Q_PROPERTY_AUTO(QString,cacheDir)
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);
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);
public:
QJSValue _interceptor;
};
#endif // Network_H

View File

@ -24,7 +24,7 @@ public:
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 QString getLanguage(){return get("language",QVariant("en")).toString();}
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={});

View File

@ -17,6 +17,7 @@
#include "src/helper/SettingsHelper.h"
#include "src/helper/InitalizrHelper.h"
#include "src/helper/TranslateHelper.h"
#include "src/helper/Network.h"
#ifdef FLUENTUI_BUILD_STATIC_LIB
#if (QT_VERSION > QT_VERSION_CHECK(6, 2, 0))
@ -51,6 +52,7 @@ int main(int argc, char *argv[])
QGuiApplication::setApplicationName("FluentUI");
QGuiApplication::setApplicationDisplayName("FluentUI Exmaple");
QGuiApplication::setApplicationVersion(APPLICATION_VERSION);
QGuiApplication::setQuitOnLastWindowClosed(false);
SettingsHelper::getInstance()->init(argv);
Log::setup(argv,"example");
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
@ -64,18 +66,25 @@ int main(int argc, char *argv[])
#endif
#endif
QGuiApplication app(argc, argv);
const char *uri = "example";
int major = 1;
int minor = 0;
//@uri example
qmlRegisterType<CircularReveal>(uri, major, minor, "CircularReveal");
qmlRegisterType<FileWatcher>(uri, major, minor, "FileWatcher");
qmlRegisterType<FpsItem>(uri, major, minor, "FpsItem");
qmlRegisterType<NetworkCallable>(uri,major,minor,"NetworkCallable");
qmlRegisterType<NetworkParams>(uri,major,minor,"NetworkParams");
QQmlApplicationEngine engine;
TranslateHelper::getInstance()->init(&engine);
engine.rootContext()->setContextProperty("AppInfo",AppInfo::getInstance());
engine.rootContext()->setContextProperty("SettingsHelper",SettingsHelper::getInstance());
engine.rootContext()->setContextProperty("InitalizrHelper",InitalizrHelper::getInstance());
engine.rootContext()->setContextProperty("TranslateHelper",TranslateHelper::getInstance());
engine.rootContext()->setContextProperty("Network",Network::getInstance());
#ifdef FLUENTUI_BUILD_STATIC_LIB
FluentUI::getInstance()->registerTypes(&engine);
#endif
qmlRegisterType<CircularReveal>("example", 1, 0, "CircularReveal");
qmlRegisterType<FileWatcher>("example", 1, 0, "FileWatcher");
qmlRegisterType<FpsItem>("example", 1, 0, "FpsItem");
const QUrl url(QStringLiteral("qrc:/example/qml/App.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {

View File

@ -13,7 +13,7 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#设置版本号
add_definitions(-DFLUENTUI_VERSION=1,7,3,0)
add_definitions(-DFLUENTUI_VERSION=1,7,4,0)
if (FLUENTUI_BUILD_STATIC_LIB)
add_definitions(-DFLUENTUI_BUILD_STATIC_LIB)
@ -46,13 +46,13 @@ endif()
#国际化
find_program(QT_LUPDATE NAMES lupdate)
find_program(QT_LRELEASE NAMES lrelease)
if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}_en_US.qm)
execute_process(COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts ${PROJECT_NAME}_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
execute_process(COMMAND ${QT_LRELEASE} ${PROJECT_NAME}_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/fluentui_en_US.qm)
execute_process(COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts fluentui_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
execute_process(COMMAND ${QT_LRELEASE} fluentui_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
endif ()
if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}_zh_CN.qm)
execute_process(COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts ${PROJECT_NAME}_zh_CN.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
execute_process(COMMAND ${QT_LRELEASE} ${PROJECT_NAME}_zh_CN.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/fluentui_zh_CN.qm)
execute_process(COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts fluentui_zh_CN.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
execute_process(COMMAND ${QT_LRELEASE} fluentui_zh_CN.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
endif ()
file(GLOB QM_FILE_PATHS ${CMAKE_CURRENT_LIST_DIR}/ *.qm)
@ -73,11 +73,15 @@ if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
endif()
#遍历所有qml文件
file(GLOB_RECURSE QML_PATHS *.qml)
file(GLOB_RECURSE QML_PATHS *.qml qmldir)
foreach(filepath ${QML_PATHS})
if(${filepath} MATCHES "Qt${QT_VERSION_MAJOR}/")
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
list(APPEND qml_files ${filename})
if(${filename} MATCHES "qmldir")
list(APPEND resource_files ${filename})
else()
list(APPEND qml_files ${filename})
endif()
endif()
endforeach(filepath)

View File

@ -4,27 +4,6 @@
#include <QObject>
#include <QtQml/qqml.h>
namespace FluViewModelType {
Q_NAMESPACE
enum Scope {
Window = 0x0000,
Application = 0x0001
};
Q_ENUM_NS(Scope)
QML_NAMED_ELEMENT(FluViewModelType)
}
namespace FluNetworkType {
Q_NAMESPACE
enum CacheMode {
NoCache = 0x0000,
RequestFailedReadCache = 0x0001,
IfNoneCacheRequest = 0x0002,
FirstCacheThenRequest = 0x0004,
};
Q_ENUM_NS(CacheMode)
QML_NAMED_ELEMENT(FluNetworkType)
}
namespace FluThemeType {
Q_NAMESPACE

View File

@ -24,83 +24,10 @@ void FluApp::init(QObject *target,QLocale locale){
qApp->installTranslator(_translator);
const QStringList uiLanguages = _locale.uiLanguages();
for (const QString &name : uiLanguages) {
const QString baseName = "fluentuiplugin_" + QLocale(name).name();
const QString baseName = "fluentui_" + QLocale(name).name();
if (_translator->load(":/qt/qml/FluentUI/i18n/"+ baseName)) {
_engine->retranslate();
break;
}
}
}
void FluApp::run(){
navigate(initialRoute());
}
void FluApp::navigate(const QString& route,const QJsonObject& argument,FluWindowRegister* windowRegister){
if(!routes().contains(route)){
qCritical()<<"Not Found Route "<<route;
return;
}
QQmlComponent component(_engine, routes().value(route).toString());
if (component.isError()) {
qCritical() << component.errors();
return;
}
QVariantMap properties;
properties.insert("_route",route);
if(windowRegister){
properties.insert("_windowRegister",QVariant::fromValue(windowRegister));
}
properties.insert("argument",argument);
QQuickWindow *win=nullptr;
for (const auto& pair : _windows.toStdMap()) {
QString r = pair.second->property("_route").toString();
if(r == route){
win = pair.second;
break;
}
}
if(win){
int launchMode = win->property("launchMode").toInt();
if(launchMode == 1){
win->setProperty("argument",argument);
win->show();
win->raise();
win->requestActivate();
return;
}else if(launchMode == 2){
win->close();
}
}
win = qobject_cast<QQuickWindow*>(component.createWithInitialProperties(properties));
if(windowRegister){
windowRegister->to(win);
}
}
void FluApp::exit(int retCode){
for (const auto& pair : _windows.toStdMap()) {
pair.second->close();
removeWindow(pair.second);
}
qApp->exit(retCode);
}
void FluApp::addWindow(QQuickWindow* window){
_windows.insert(window->winId(),window);
}
void FluApp::removeWindow(QQuickWindow* window){
if(window){
_windows.remove(window->winId());
window->deleteLater();
window = nullptr;
}
}
QVariant FluApp::createWindowRegister(QQuickWindow* window,const QString& path){
FluWindowRegister *p = new FluWindowRegister(window);
p->from(window);
p->path(path);
return QVariant::fromValue(p);
}

View File

@ -4,12 +4,11 @@
#include <QObject>
#include <QWindow>
#include <QtQml/qqml.h>
#include <QJsonArray>
#include <QQmlContext>
#include <QJsonObject>
#include <QQmlEngine>
#include <QTranslator>
#include "FluWindowRegister.h"
#include <QQuickWindow>
#include "stdafx.h"
#include "singleton.h"
@ -19,8 +18,6 @@
class FluApp : public QObject
{
Q_OBJECT
Q_PROPERTY_AUTO(QString,initialRoute);
Q_PROPERTY_AUTO(QJsonObject,routes);
Q_PROPERTY_AUTO(bool,useSystemAppBar);
Q_PROPERTY_AUTO(QString,windowIcon);
Q_PROPERTY_AUTO(QLocale,locale);
@ -32,15 +29,8 @@ private:
public:
SINGLETON(FluApp)
static FluApp *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
Q_INVOKABLE void run();
Q_INVOKABLE void navigate(const QString& route,const QJsonObject& argument = {},FluWindowRegister* windowRegister = nullptr);
Q_INVOKABLE void init(QObject *target,QLocale locale = QLocale::system());
Q_INVOKABLE void exit(int retCode = 0);
Q_INVOKABLE QVariant createWindowRegister(QQuickWindow* window,const QString& path);
void addWindow(QQuickWindow* window);
void removeWindow(QQuickWindow* window);
private:
QMap<quint64, QQuickWindow*> _windows;
QQmlEngine *_engine;
QTranslator* _translator = nullptr;
};

View File

@ -1,23 +0,0 @@
#include "FluEventBus.h"
FluEvent::FluEvent(QObject *parent):QObject{parent}{
}
FluEventBus::FluEventBus(QObject *parent):QObject{parent}{
}
void FluEventBus::registerEvent(FluEvent* event){
_eventData.append(event);
}
void FluEventBus::unRegisterEvent(FluEvent* event){
_eventData.removeOne(event);
}
void FluEventBus::post(const QString& name,const QMap<QString, QVariant>& data){
foreach (auto event, _eventData) {
if(event->name()==name){
Q_EMIT event->triggered(data);
}
}
}

View File

@ -1,41 +0,0 @@
#ifndef FLUEVENTBUS_H
#define FLUEVENTBUS_H
#include <QObject>
#include <QtQml/qqml.h>
#include "stdafx.h"
#include "singleton.h"
/**
* @brief The FluEvent class
*/
class FluEvent : public QObject{
Q_OBJECT
Q_PROPERTY_AUTO(QString,name);
QML_NAMED_ELEMENT(FluEvent)
public:
explicit FluEvent(QObject *parent = nullptr);
Q_SIGNAL void triggered(QMap<QString, QVariant> data);
};
/**
* @brief The FluEventBus class
*/
class FluEventBus : public QObject
{
Q_OBJECT
QML_NAMED_ELEMENT(FluEventBus)
QML_SINGLETON
private:
explicit FluEventBus(QObject *parent = nullptr);
public:
SINGLETON(FluEventBus)
static FluEventBus *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
Q_INVOKABLE void registerEvent(FluEvent* event);
Q_INVOKABLE void unRegisterEvent(FluEvent* event);
Q_INVOKABLE void post(const QString& name,const QMap<QString, QVariant>& params = {});
private:
QList<FluEvent*> _eventData;
};
#endif // FLUEVENTBUS_H

458
src/FluFrameless.cpp Normal file
View File

@ -0,0 +1,458 @@
#include "FluFrameless.h"
#include <QQuickWindow>
#include <QGuiApplication>
#include <QScreen>
#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 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)
{
BOOL composition_enabled = false;
DwmIsCompositionEnabledPtr dwm_is_composition_enabled;
dwm_is_composition_enabled= reinterpret_cast<DwmIsCompositionEnabledPtr>(::GetProcAddress(module, "DwmIsCompositionEnabled"));
if (dwm_is_composition_enabled)
{
dwm_is_composition_enabled(&composition_enabled);
}
return composition_enabled;
}
return false;
}
#endif
FluFrameless::FluFrameless(QQuickItem *parent)
: QQuickItem{parent}
{
appbar(nullptr);
maximizeButton(nullptr);
minimizedButton(nullptr);
closeButton(nullptr);
topmost(false);
disabled(false);
}
FluFrameless::~FluFrameless(){
qApp->removeNativeEventFilter(this);
}
void FluFrameless::componentComplete(){
if(_disabled){
return;
}
_current = window()->winId();
window()->setFlags(( window()->flags()) | Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::FramelessWindowHint);
if(!_fixSize){
window()->setFlag(Qt::WindowMaximizeButtonHint);
}
window()->installEventFilter(this);
qApp->installNativeEventFilter(this);
if(_appbar){
_appbar->installEventFilter(this);
}
if(_maximizeButton){
setHitTestVisible(_maximizeButton);
}
if(_minimizedButton){
setHitTestVisible(_minimizedButton);
}
if(_closeButton){
setHitTestVisible(_closeButton);
}
#ifdef Q_OS_WIN
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
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,[=]{
SetWindowPos(hwnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_FRAMECHANGED);
});
}
}else{
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME);
}
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);
});
#endif
connect(this,&FluFrameless::topmostChanged,this,[this]{
_setWindowTopmost(topmost());
});
_setWindowTopmost(topmost());
}
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) {
return false;
}
const qint64 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;
static QPoint offsetXY;
if(uMsg == WM_WINDOWPOSCHANGING){
WINDOWPOS* 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;
}
return false;
}else if(uMsg == WM_NCCALCSIZE){
const auto clientRect = ((wParam == FALSE) ? reinterpret_cast<LPRECT>(lParam) : &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0]);
const LONG originalTop = clientRect->top;
const LONG originalLeft = clientRect->left;
const LONG originalRight = clientRect->right;
const LONG originalBottom = clientRect->bottom;
const LRESULT hitTestResult = ::DefWindowProcW(hwnd, WM_NCCALCSIZE, wParam, lParam);
if ((hitTestResult != HTERROR) && (hitTestResult != HTNOWHERE)) {
*result = hitTestResult;
return true;
}
int offsetSize = 0;
bool isMaximum = ::IsZoomed(hwnd);
offsetXY = QPoint(abs(clientRect->left - originalLeft),abs(clientRect->top - originalTop));
if(isMaximum || _isFullScreen()){
offsetSize = 0;
}else{
offsetSize = 1;
}
if(!isCompositionEnabled()){
offsetSize = 0;
}
if (!isMaximum || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) {
clientRect->top = originalTop + offsetSize;
clientRect->bottom = originalBottom - offsetSize;
clientRect->left = originalLeft + offsetSize;
clientRect->right = originalRight - offsetSize;
}
*result = WVR_REDRAW;
return true;
}else if(uMsg == WM_NCHITTEST){
if(_hitMaximizeButton()){
if (*result == HTNOWHERE) {
*result = HTZOOM;
}
return true;
}
*result = 0;
POINT nativeGlobalPos{GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
POINT nativeLocalPos = nativeGlobalPos;
::ScreenToClient(hwnd, &nativeLocalPos);
RECT clientRect{0, 0, 0, 0};
::GetClientRect(hwnd, &clientRect);
auto clientWidth = clientRect.right-clientRect.left;
auto clientHeight = clientRect.bottom-clientRect.top;
bool left = nativeLocalPos.x < _margins;
bool right = nativeLocalPos.x > clientWidth - _margins;
bool top = nativeLocalPos.y < _margins;
bool bottom = nativeLocalPos.y > clientHeight - _margins;
*result = 0;
if (!_fixSize && !_isFullScreen() && !_isMaximized()) {
if (left && top) {
*result = HTTOPLEFT;
} else if (left && bottom) {
*result = HTBOTTOMLEFT;
} else if (right && top) {
*result = HTTOPRIGHT;
} else if (right && bottom) {
*result = HTBOTTOMRIGHT;
} else if (left) {
*result = HTLEFT;
} else if (right) {
*result = HTRIGHT;
} else if (top) {
*result = HTTOP;
} else if (bottom) {
*result = HTBOTTOM;
}
}
if (0 != *result) {
return true;
}
if(_hitAppBar()){
*result = HTCAPTION;
return true;
}
*result = HTCLIENT;
return true;
}else if(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);
return true;
}
}else if(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);
return true;
}
}else if(uMsg == WM_NCPAINT){
*result = FALSE;
return true;
}else if(uMsg == WM_NCACTIVATE){
*result = ::DefWindowProcW(hwnd, WM_NCACTIVATE, wParam, -1);
return true;
}else if(uMsg == WM_GETMINMAXINFO){
MINMAXINFO* 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;
#else
auto pixelRatio = window()->devicePixelRatio();
auto geometry = window()->screen()->availableGeometry();
RECT rect;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
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;
#endif
return false;
}else if(uMsg == WM_NCRBUTTONDOWN){
if (wParam == HTCAPTION) {
_showSystemMenu(QCursor::pos());
}
}else if(uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN){
const bool altPressed = ((wParam == VK_MENU) || (::GetKeyState(VK_MENU) < 0));
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()));
}
}else if(uMsg == WM_SYSCOMMAND){
if(wParam == SC_MINIMIZE){
if(window()->transientParent()){
window()->transientParent()->showMinimized();
}else{
window()->showMinimized();
}
return true;
}
return false;
}
return false;
#endif
return false;
}
bool FluFrameless::_isMaximized(){
return window()->visibility() == QWindow::Maximized;
}
bool FluFrameless::_isFullScreen(){
return window()->visibility() == QWindow::FullScreen;
}
void FluFrameless::_showSystemMenu(QPoint point){
#ifdef Q_OS_WIN
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);
if(_isMaximized() || _isFullScreen()){
::EnableMenuItem(hMenu,SC_MOVE,MFS_DISABLED);
::EnableMenuItem(hMenu,SC_RESTORE,MFS_ENABLED);
}else{
::EnableMenuItem(hMenu,SC_MOVE,MFS_ENABLED);
::EnableMenuItem(hMenu,SC_RESTORE,MFS_DISABLED);
}
if(!_fixSize && !_isMaximized() && !_isFullScreen()){
::EnableMenuItem(hMenu,SC_SIZE,MFS_ENABLED);
::EnableMenuItem(hMenu,SC_MAXIMIZE,MFS_ENABLED);
}else{
::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);
if (result != FALSE) {
::PostMessageW(hwnd, WM_SYSCOMMAND, result, 0);
}
::SetWindowLongPtr(hwnd, GWL_STYLE, style &~ WS_SYSMENU);
#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)){
return false;
}
}
if(_containsCursorToItem(_appbar)){
return true;
}
return false;
}
bool FluFrameless::_hitMaximizeButton(){
if(_containsCursorToItem(_maximizeButton)){
return true;
}
return false;
}
void FluFrameless::_updateCursor(int edges){
switch (edges) {
case 0:
window()->setCursor(Qt::ArrowCursor);
break;
case Qt::LeftEdge:
case Qt::RightEdge:
window()->setCursor(Qt::SizeHorCursor);
break;
case Qt::TopEdge:
case Qt::BottomEdge:
window()->setCursor(Qt::SizeVerCursor);
break;
case Qt::LeftEdge | Qt::TopEdge:
case Qt::RightEdge | Qt::BottomEdge:
window()->setCursor(Qt::SizeFDiagCursor);
break;
case Qt::RightEdge | Qt::TopEdge:
case Qt::LeftEdge | Qt::BottomEdge:
window()->setCursor(Qt::SizeBDiagCursor);
break;
}
}
void FluFrameless::showFullScreen(){
window()->showFullScreen();
}
void FluFrameless::showMaximized(){
#ifdef Q_OS_WIN
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
::ShowWindow(hwnd,3);
#else
window()->showMaximized();
#endif
}
void FluFrameless::showMinimized(){
window()->showMinimized();
}
void FluFrameless::showNormal(){
window()->showNormal();
}
void FluFrameless::setHitTestVisible(QQuickItem* val){
_hitTestList.append(val);
}
void FluFrameless::_setWindowTopmost(bool topmost){
#ifdef Q_OS_WIN
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
if(topmost){
::SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}else{
::SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
#else
window()->setFlag(Qt::WindowStaysOnTopHint,topmost);
#endif
}
bool FluFrameless::eventFilter(QObject *obj, QEvent *ev){
#ifndef Q_OS_WIN
switch (ev->type()) {
case QEvent::MouseButtonPress:
if(_edges!=0){
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
if(event->button() == Qt::LeftButton){
_updateCursor(_edges);
window()->startSystemResize(Qt::Edges(_edges));
}
}else{
if(_hitAppBar()){
window()->startSystemMove();
}
}
break;
case QEvent::MouseButtonRelease:
_edges = 0;
break;
case QEvent::MouseMove: {
if(_isMaximized() || _isFullScreen()){
break;
}
if(_fixSize){
break;
}
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
QPoint p =
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
event->pos();
#else
event->position().toPoint();
#endif
if(p.x() >= _margins && p.x() <= (window()->width() - _margins) && p.y() >= _margins && p.y() <= (window()->height() - _margins)){
if(_edges != 0){
_edges = 0;
_updateCursor(_edges);
}
break;
}
_edges = 0;
if ( p.x() < _margins ) {
_edges |= Qt::LeftEdge;
}
if ( p.x() > (window()->width() - _margins) ) {
_edges |= Qt::RightEdge;
}
if ( p.y() < _margins ) {
_edges |= Qt::TopEdge;
}
if ( p.y() > (window()->height() - _margins) ) {
_edges |= Qt::BottomEdge;
}
_updateCursor(_edges);
break;
}
default:
break;
}
#endif
return QObject::eventFilter(obj, ev);
}

57
src/FluFrameless.h Normal file
View File

@ -0,0 +1,57 @@
#ifndef FLUFRAMELESS_H
#define FLUFRAMELESS_H
#include <QObject>
#include <QQuickItem>
#include <QAbstractNativeEventFilter>
#include "stdafx.h"
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
using QT_NATIVE_EVENT_RESULT_TYPE = qintptr;
using QT_ENTER_EVENT_TYPE = QEnterEvent;
#else
using QT_NATIVE_EVENT_RESULT_TYPE = long;
using QT_ENTER_EVENT_TYPE = QEvent;
#endif
class FluFrameless : public QQuickItem,QAbstractNativeEventFilter
{
Q_OBJECT
Q_PROPERTY_AUTO(QQuickItem*,appbar)
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();
void componentComplete() override;
bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
Q_INVOKABLE void showFullScreen();
Q_INVOKABLE void showMaximized();
Q_INVOKABLE void showMinimized();
Q_INVOKABLE void showNormal();
Q_INVOKABLE void setHitTestVisible(QQuickItem*);
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();
private:
qint64 _current;
int _edges = 0;
int _margins = 8;
QList<QPointer<QQuickItem>> _hitTestList;
};
#endif // FLUFRAMELESS_H

View File

@ -1,500 +0,0 @@
#include "FluFramelessHelper.h"
#include <QGuiApplication>
#include <QScreen>
#include <QQuickItem>
#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 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)
{
BOOL composition_enabled = false;
DwmIsCompositionEnabledPtr dwm_is_composition_enabled;
dwm_is_composition_enabled= reinterpret_cast<DwmIsCompositionEnabledPtr>(::GetProcAddress(module, "DwmIsCompositionEnabled"));
if (dwm_is_composition_enabled)
{
dwm_is_composition_enabled(&composition_enabled);
}
return composition_enabled;
}
return false;
}
#endif
FramelessEventFilter::FramelessEventFilter(FluFramelessHelper* helper){
_helper = helper;
_current = _helper->window->winId();
}
bool FramelessEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result){
#ifdef Q_OS_WIN
if ((eventType != qtNativeEventType()) || !message || _helper.isNull() || _helper->window.isNull()) {
return false;
}
const auto msg = static_cast<const MSG *>(message);
const HWND hwnd = msg->hwnd;
if (!hwnd || !msg) {
return false;
}
const qint64 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;
static QPoint offsetXY;
if(uMsg == WM_WINDOWPOSCHANGING){
WINDOWPOS* 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;
}
return false;
}else if(uMsg == WM_NCCALCSIZE){
const auto clientRect = ((wParam == FALSE) ? reinterpret_cast<LPRECT>(lParam) : &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0]);
const LONG originalTop = clientRect->top;
const LONG originalLeft = clientRect->left;
const LONG originalRight = clientRect->right;
const LONG originalBottom = clientRect->bottom;
const LRESULT hitTestResult = ::DefWindowProcW(hwnd, WM_NCCALCSIZE, wParam, lParam);
if ((hitTestResult != HTERROR) && (hitTestResult != HTNOWHERE)) {
*result = hitTestResult;
return true;
}
int offsetSize = 0;
bool isMaximum = ::IsZoomed(hwnd);
offsetXY = QPoint(abs(clientRect->left - originalLeft),abs(clientRect->top - originalTop));
if(isMaximum || _helper->fullScreen()){
offsetSize = 0;
}else{
offsetSize = 1;
}
if(!isCompositionEnabled()){
offsetSize = 0;
}
if (!isMaximum || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) {
clientRect->top = originalTop + offsetSize;
clientRect->bottom = originalBottom - offsetSize;
clientRect->left = originalLeft + offsetSize;
clientRect->right = originalRight - offsetSize;
}
*result = WVR_REDRAW;
return true;
}if(uMsg == WM_NCHITTEST){
if(FluTools::getInstance()->isWindows11OrGreater() && _helper->hoverMaxBtn() && _helper->resizeable()){
if (*result == HTNOWHERE) {
*result = HTZOOM;
}
return true;
}
*result = 0;
POINT nativeGlobalPos{GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
POINT nativeLocalPos = nativeGlobalPos;
::ScreenToClient(hwnd, &nativeLocalPos);
RECT clientRect{0, 0, 0, 0};
::GetClientRect(hwnd, &clientRect);
auto clientWidth = clientRect.right-clientRect.left;
auto clientHeight = clientRect.bottom-clientRect.top;
int margins = _helper->getMargins();
bool left = nativeLocalPos.x < margins;
bool right = nativeLocalPos.x > clientWidth - margins;
bool top = nativeLocalPos.y < margins;
bool bottom = nativeLocalPos.y > clientHeight - margins;
*result = 0;
if (_helper->resizeable() && !_helper->fullScreen() && !_helper->maximized()) {
if (left && top) {
*result = HTTOPLEFT;
} else if (left && bottom) {
*result = HTBOTTOMLEFT;
} else if (right && top) {
*result = HTTOPRIGHT;
} else if (right && bottom) {
*result = HTBOTTOMRIGHT;
} else if (left) {
*result = HTLEFT;
} else if (right) {
*result = HTRIGHT;
} else if (top) {
*result = HTTOP;
} else if (bottom) {
*result = HTBOTTOM;
}
}
if (0 != *result) {
return true;
}
QVariant appBar = _helper->getAppBar();
if(!appBar.isNull()&& _helper->hoverAppBar()){
*result = HTCAPTION;
return true;
}
*result = HTCLIENT;
return true;
}else if(uMsg == WM_NCLBUTTONDBLCLK || uMsg == WM_NCLBUTTONDOWN){
if(_helper->hoverMaxBtn()){
QMouseEvent event = QMouseEvent(QEvent::MouseButtonPress, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QGuiApplication::sendEvent(_helper->maximizeButton(),&event);
return true;
}
}else if(uMsg == WM_NCLBUTTONUP || uMsg == WM_NCRBUTTONUP){
if(_helper->hoverMaxBtn()){
QMouseEvent event = QMouseEvent(QEvent::MouseButtonRelease, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QGuiApplication::sendEvent(_helper->maximizeButton(),&event);
}
}else if(uMsg == WM_NCPAINT){
*result = FALSE;
return true;
}else if(uMsg == WM_NCACTIVATE){
*result = ::DefWindowProcW(hwnd, WM_NCACTIVATE, wParam, -1);
return true;
}else if(uMsg == WM_GETMINMAXINFO){
MINMAXINFO* 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;
#else
auto pixelRatio = _helper->window->devicePixelRatio();
auto geometry = _helper->window->screen()->availableGeometry();
RECT rect;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
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;
#endif
return false;
}else if(uMsg == WM_NCRBUTTONDOWN){
if (wParam == HTCAPTION) {
_helper->showSystemMenu(QCursor::pos());
}
}else if(uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN){
const bool altPressed = ((wParam == VK_MENU) || (::GetKeyState(VK_MENU) < 0));
const bool spacePressed = ((wParam == VK_SPACE) || (::GetKeyState(VK_SPACE) < 0));
if (altPressed && spacePressed) {
auto pos = _helper->window->position();
_helper->showSystemMenu(QPoint(pos.x(),pos.y()+_helper->getAppBarHeight()));
}
}else if(uMsg == WM_SYSCOMMAND){
if(wParam == SC_MINIMIZE){
if(_helper->window->transientParent()){
_helper->window->transientParent()->showMinimized();
}else{
_helper->window->showMinimized();
}
return true;
}
return false;
}
return false;
#endif
return false;
}
FluFramelessHelper::FluFramelessHelper(QObject *parent)
: QObject{parent}
{
}
void FluFramelessHelper::classBegin(){
}
void FluFramelessHelper::_updateCursor(int edges){
switch (edges) {
case 0:
window->setCursor(Qt::ArrowCursor);
break;
case Qt::LeftEdge:
case Qt::RightEdge:
window->setCursor(Qt::SizeHorCursor);
break;
case Qt::TopEdge:
case Qt::BottomEdge:
window->setCursor(Qt::SizeVerCursor);
break;
case Qt::LeftEdge | Qt::TopEdge:
case Qt::RightEdge | Qt::BottomEdge:
window->setCursor(Qt::SizeFDiagCursor);
break;
case Qt::RightEdge | Qt::TopEdge:
case Qt::LeftEdge | Qt::BottomEdge:
window->setCursor(Qt::SizeBDiagCursor);
break;
}
}
bool FluFramelessHelper::eventFilter(QObject *obj, QEvent *ev){
if (!window.isNull() && window->flags()) {
switch (ev->type()) {
case QEvent::MouseButtonPress:
if(_edges!=0){
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
if(event->button() == Qt::LeftButton){
_updateCursor(_edges);
window->startSystemResize(Qt::Edges(_edges));
}
}
break;
case QEvent::MouseButtonRelease:
_edges = 0;
break;
case QEvent::MouseMove: {
if(maximized() || fullScreen()){
break;
}
if(!resizeable()){
break;
}
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
QPoint p =
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
event->pos();
#else
event->position().toPoint();
#endif
if(p.x() >= _margins && p.x() <= (window->width() - _margins) && p.y() >= _margins && p.y() <= (window->height() - _margins)){
if(_edges != 0){
_edges = 0;
_updateCursor(_edges);
}
break;
}
_edges = 0;
if ( p.x() < _margins ) {
_edges |= Qt::LeftEdge;
}
if ( p.x() > (window->width() - _margins) ) {
_edges |= Qt::RightEdge;
}
if ( p.y() < _margins ) {
_edges |= Qt::TopEdge;
}
if ( p.y() > (window->height() - _margins) ) {
_edges |= Qt::BottomEdge;
}
_updateCursor(_edges);
break;
}
default:
break;
}
}
return QObject::eventFilter(obj, ev);
}
void FluFramelessHelper::componentComplete(){
auto o = parent();
do {
window = qobject_cast<QQuickWindow *>(o);
if (window) {
break;
}
o = o->parent();
} while (nullptr != o);
if(!window.isNull()){
_stayTop = QQmlProperty(window,"stayTop");
_screen = QQmlProperty(window,"screen");
_fixSize = QQmlProperty(window,"fixSize");
_realHeight = QQmlProperty(window,"_realHeight");
_realWidth = QQmlProperty(window,"_realWidth");
_appBarHeight = QQmlProperty(window,"_appBarHeight");
_appBar = window->property("appBar");
#ifdef Q_OS_WIN
if(!_appBar.isNull()){
_appBar.value<QObject*>()->setProperty("systemMoveEnable",false);
}
window->setFlags((window->flags()) | Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::FramelessWindowHint);
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
if(FluTools::getInstance()->isSoftware()){
window->setFlag(Qt::FramelessWindowHint,false);
}
#endif
if(resizeable()){
window->setFlag(Qt::WindowMaximizeButtonHint);
}
_nativeEvent =new FramelessEventFilter(this);
qApp->installNativeEventFilter(_nativeEvent);
HWND hwnd = reinterpret_cast<HWND>(window->winId());
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
if(resizeable()){
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME);
}else{
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME);
for (int i = 0; i < qApp->screens().count(); ++i) {
connect( qApp->screens().at(i),&QScreen::logicalDotsPerInchChanged,this,[=]{
SetWindowPos(hwnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_FRAMECHANGED);
});
}
}
SetWindowPos(hwnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
#else
window->setFlags((window->flags() & (~Qt::WindowMinMaxButtonsHint) & (~Qt::Dialog)) | Qt::FramelessWindowHint | Qt::Window);
window->installEventFilter(this);
#endif
int w = _realWidth.read().toInt();
int h = _realHeight.read().toInt()+_appBarHeight.read().toInt();
if(!resizeable()){
window->setMaximumSize(QSize(w,h));
window->setMinimumSize(QSize(w,h));
}
window->resize(QSize(w,h));
_onStayTopChange();
_stayTop.connectNotifySignal(this,SLOT(_onStayTopChange()));
_screen.connectNotifySignal(this,SLOT(_onScreenChanged()));
Q_EMIT loadCompleted();
}
}
void FluFramelessHelper::_onScreenChanged(){
#ifdef Q_OS_WIN
HWND hwnd = reinterpret_cast<HWND>(window->winId());
::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);
#endif
}
void FluFramelessHelper::showSystemMenu(QPoint point){
#ifdef Q_OS_WIN
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);
if(maximized() || fullScreen()){
::EnableMenuItem(hMenu,SC_MOVE,MFS_DISABLED);
::EnableMenuItem(hMenu,SC_RESTORE,MFS_ENABLED);
}else{
::EnableMenuItem(hMenu,SC_MOVE,MFS_ENABLED);
::EnableMenuItem(hMenu,SC_RESTORE,MFS_DISABLED);
}
if(resizeable() && !maximized() && !fullScreen()){
::EnableMenuItem(hMenu,SC_SIZE,MFS_ENABLED);
::EnableMenuItem(hMenu,SC_MAXIMIZE,MFS_ENABLED);
}else{
::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);
if (result != FALSE) {
::PostMessageW(hwnd, WM_SYSCOMMAND, result, 0);
}
::SetWindowLongPtr(hwnd, GWL_STYLE, style &~ WS_SYSMENU);
#endif
}
void FluFramelessHelper::showMaximized(){
#ifdef Q_OS_WIN
HWND hwnd = reinterpret_cast<HWND>(window->winId());
::ShowWindow(hwnd,3);
#endif
}
void FluFramelessHelper::_onStayTopChange(){
bool isStayTop = _stayTop.read().toBool();
#ifdef Q_OS_WIN
HWND hwnd = reinterpret_cast<HWND>(window->winId());
if(isStayTop){
::SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}else{
::SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
#else
window->setFlag(Qt::WindowStaysOnTopHint,isStayTop);
#endif
}
FluFramelessHelper::~FluFramelessHelper(){
if (!window.isNull()) {
window->setFlags(Qt::Window);
#ifdef Q_OS_WIN
qApp->removeNativeEventFilter(_nativeEvent);
delete _nativeEvent;
#endif
window->removeEventFilter(this);
}
}
bool FluFramelessHelper::hoverMaxBtn(){
if(_appBar.isNull()){
return false;
}
QVariant var;
QMetaObject::invokeMethod(_appBar.value<QObject*>(), "_maximizeButtonHover",Q_RETURN_ARG(QVariant, var));
if(var.isNull()){
return false;
}
return var.toBool();
}
bool FluFramelessHelper::hoverAppBar(){
if(_appBar.isNull()){
return false;
}
QVariant var;
QMetaObject::invokeMethod(_appBar.value<QObject*>(), "_appBarHover",Q_RETURN_ARG(QVariant, var));
if(var.isNull()){
return false;
}
return var.toBool();
}
QVariant FluFramelessHelper::getAppBar(){
return _appBar;
}
int FluFramelessHelper::getAppBarHeight(){
if(_appBar.isNull()){
return 0;
}
QVariant var = _appBar.value<QObject*>()->property("height");
if(var.isNull()){
return 0;
}
return var.toInt();
}
QObject* FluFramelessHelper::maximizeButton(){
if(_appBar.isNull()){
return nullptr;
}
QVariant var = _appBar.value<QObject*>()->property("buttonMaximize");
if(var.isNull()){
return nullptr;
}
return var.value<QObject*>();
}
bool FluFramelessHelper::resizeable(){
return !_fixSize.read().toBool();
}
bool FluFramelessHelper::maximized(){
return window->visibility() == QWindow::Maximized;
}
bool FluFramelessHelper::fullScreen(){
return window->visibility() == QWindow::FullScreen;
}
int FluFramelessHelper::getMargins(){
return _margins;
}

View File

@ -1,80 +0,0 @@
#ifndef FLUFRAMELESSHELPER_H
#define FLUFRAMELESSHELPER_H
#include <QObject>
#include <QQuickWindow>
#include <QtQml/qqml.h>
#include <QAbstractNativeEventFilter>
#include <QQmlProperty>
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
using QT_NATIVE_EVENT_RESULT_TYPE = qintptr;
using QT_ENTER_EVENT_TYPE = QEnterEvent;
#else
using QT_NATIVE_EVENT_RESULT_TYPE = long;
using QT_ENTER_EVENT_TYPE = QEvent;
#endif
class FluFramelessHelper;
/**
* @brief The FramelessEventFilter class
*/
class FramelessEventFilter : public QAbstractNativeEventFilter
{
public:
FramelessEventFilter(FluFramelessHelper* helper);
bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
public:
QPointer<FluFramelessHelper> _helper = nullptr;
qint64 _current = 0;
};
/**
* @brief The FluFramelessHelper class
*/
class FluFramelessHelper : public QObject, public QQmlParserStatus
{
Q_OBJECT
Q_INTERFACES(QQmlParserStatus)
QML_NAMED_ELEMENT(FluFramelessHelper)
public:
explicit FluFramelessHelper(QObject *parent = nullptr);
~FluFramelessHelper();
void classBegin() override;
void componentComplete() override;
bool hoverMaxBtn();
bool hoverAppBar();
bool resizeable();
int getMargins();
bool maximized();
bool fullScreen();
int getAppBarHeight();
QVariant getAppBar();
QObject* maximizeButton();
void setOriginalPos(QVariant pos);
Q_INVOKABLE void showSystemMenu(QPoint point);
Q_INVOKABLE void showMaximized();
Q_SIGNAL void loadCompleted();
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
private:
void _updateCursor(int edges);
Q_SLOT void _onStayTopChange();
Q_SLOT void _onScreenChanged();
public:
QPointer<QQuickWindow> window = nullptr;
private:
FramelessEventFilter* _nativeEvent = nullptr;
QQmlProperty _stayTop;
QQmlProperty _screen;
QQmlProperty _fixSize;
QQmlProperty _realHeight;
QQmlProperty _realWidth;
QQmlProperty _appBarHeight;
QVariant _appBar;
int _edges = 0;
int _margins = 8;
};
#endif // FLUFRAMELESSHELPER_H

View File

@ -1,158 +0,0 @@
#ifndef FLUNETWORK_H
#define FLUNETWORK_H
#include <QObject>
#include <QtQml/qqml.h>
#include <QFile>
#include <QJsonValue>
#include <QJSValue>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include "Def.h"
#include "stdafx.h"
#include "singleton.h"
/**
* @brief The NetworkCallable class
*/
class FluNetworkCallable : public QObject{
Q_OBJECT
QML_NAMED_ELEMENT(FluNetworkCallable)
public:
explicit FluNetworkCallable(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);
};
/**
* @brief The FluDownloadParam class
*/
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;
};
/**
* @brief The FluNetworkParams class
*/
class FluNetworkParams : public QObject
{
Q_OBJECT
QML_NAMED_ELEMENT(FluNetworkParams)
public:
enum Method{
METHOD_GET,
METHOD_HEAD,
METHOD_POST,
METHOD_PUT,
METHOD_PATCH,
METHOD_DELETE
};
enum Type{
TYPE_NONE,
TYPE_FORM,
TYPE_JSON,
TYPE_JSONARRAY,
TYPE_BODY
};
explicit FluNetworkParams(QObject *parent = nullptr);
FluNetworkParams(QString url,Type type,Method method,QObject *parent = nullptr);
Q_INVOKABLE FluNetworkParams* addQuery(QString key,QVariant val);
Q_INVOKABLE FluNetworkParams* addHeader(QString key,QVariant val);
Q_INVOKABLE FluNetworkParams* add(QString key,QVariant val);
Q_INVOKABLE FluNetworkParams* addFile(QString key,QVariant val);
Q_INVOKABLE FluNetworkParams* setBody(QString val);
Q_INVOKABLE FluNetworkParams* setTimeout(int val);
Q_INVOKABLE FluNetworkParams* setRetry(int val);
Q_INVOKABLE FluNetworkParams* setCacheMode(int val);
Q_INVOKABLE FluNetworkParams* toDownload(QString destPath,bool append = false);
Q_INVOKABLE FluNetworkParams* bind(QObject* target);
Q_INVOKABLE FluNetworkParams* openLog(QVariant val);
Q_INVOKABLE void go(FluNetworkCallable* result);
QString buildCacheKey();
QString method2String();
int getTimeout();
int getRetry();
bool getOpenLog();
public:
FluDownloadParam* _downloadParam = nullptr;
QObject* _target = nullptr;
Method _method;
Type _type;
QString _url;
QString _body;
QMap<QString, QVariant> _queryMap;
QMap<QString, QVariant> _headerMap;
QMap<QString, QVariant> _paramMap;
QMap<QString, QVariant> _fileMap;
int _timeout = -1;
int _retry = -1;
QVariant _openLog;
int _cacheMode = FluNetworkType::CacheMode::NoCache;
};
/**
* @brief The FluNetwork class
*/
class FluNetwork : public QObject
{
Q_OBJECT
Q_PROPERTY_AUTO(int,timeout)
Q_PROPERTY_AUTO(int,retry)
Q_PROPERTY_AUTO(QString,cacheDir)
Q_PROPERTY_AUTO(bool,openLog)
QML_NAMED_ELEMENT(FluNetwork)
QML_SINGLETON
private:
explicit FluNetwork(QObject *parent = nullptr);
public:
SINGLETON(FluNetwork)
static FluNetwork *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();}
Q_INVOKABLE FluNetworkParams* get(const QString& url);
Q_INVOKABLE FluNetworkParams* head(const QString& url);
Q_INVOKABLE FluNetworkParams* postBody(const QString& url);
Q_INVOKABLE FluNetworkParams* putBody(const QString& url);
Q_INVOKABLE FluNetworkParams* patchBody(const QString& url);
Q_INVOKABLE FluNetworkParams* deleteBody(const QString& url);
Q_INVOKABLE FluNetworkParams* postForm(const QString& url);
Q_INVOKABLE FluNetworkParams* putForm(const QString& url);
Q_INVOKABLE FluNetworkParams* patchForm(const QString& url);
Q_INVOKABLE FluNetworkParams* deleteForm(const QString& url);
Q_INVOKABLE FluNetworkParams* postJson(const QString& url);
Q_INVOKABLE FluNetworkParams* putJson(const QString& url);
Q_INVOKABLE FluNetworkParams* patchJson(const QString& url);
Q_INVOKABLE FluNetworkParams* deleteJson(const QString& url);
Q_INVOKABLE FluNetworkParams* postJsonArray(const QString& url);
Q_INVOKABLE FluNetworkParams* putJsonArray(const QString& url);
Q_INVOKABLE FluNetworkParams* patchJsonArray(const QString& url);
Q_INVOKABLE FluNetworkParams* deleteJsonArray(const QString& url);
Q_INVOKABLE void setInterceptor(QJSValue interceptor);
void handle(FluNetworkParams* params,FluNetworkCallable* result);
void handleDownload(FluNetworkParams* params,FluNetworkCallable* result);
private:
void sendRequest(QNetworkAccessManager* manager,QNetworkRequest request,FluNetworkParams* params,QNetworkReply*& reply,bool isFirst,QPointer<FluNetworkCallable> 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);
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,FluNetworkParams* params);
void printRequestEndLog(QNetworkRequest request,FluNetworkParams* params,QNetworkReply*& reply,const QString& response);
public:
QJSValue _interceptor;
};
#endif // FLUNETWORK_H

View File

@ -86,9 +86,9 @@ void FluTools::restoreOverrideCursor(){
qApp->restoreOverrideCursor();
}
void FluTools::deleteItem(QObject *p){
void FluTools::deleteLater(QObject *p){
if(p){
delete p;
p->deleteLater();
p = nullptr;
}
}

View File

@ -34,7 +34,7 @@ public:
Q_INVOKABLE void restoreOverrideCursor();
Q_INVOKABLE QString html2PlantText(const QString& html);
Q_INVOKABLE QString toLocalPath(const QUrl& url);
Q_INVOKABLE void deleteItem(QObject *p);
Q_INVOKABLE void deleteLater(QObject *p);
Q_INVOKABLE QString getFileNameByUrl(const QUrl& url);
Q_INVOKABLE QRect getVirtualGeometry();
Q_INVOKABLE QString getApplicationDirPath();

View File

@ -1,113 +0,0 @@
#include "FluViewModel.h"
#include <QQuickItem>
#include "Def.h"
FluViewModelManager::FluViewModelManager(QObject *parent): QObject{parent}{
}
void FluViewModelManager::insertViewModel(FluViewModel* value){
_viewmodel.append(value);
}
void FluViewModelManager::deleteViewModel(FluViewModel* value){
_viewmodel.removeOne(value);
}
QObject* FluViewModelManager::getModel(const QString& key){
return _data.value(key);
}
void FluViewModelManager::insert(const QString& key,QObject* value){
_data.insert(key,value);
}
bool FluViewModelManager::exist(const QString& key){
return _data.contains(key);
}
void FluViewModelManager::refreshViewModel(FluViewModel* viewModel,QString key,QVariant value){
foreach (auto item, _viewmodel) {
if(item->getKey() == viewModel->getKey()){
item->enablePropertyChange = false;
item->setProperty(key.toLatin1().constData(),value);
item->enablePropertyChange = true;
}
}
}
FluPropertyObserver::FluPropertyObserver(QString name,QObject* model,QObject *parent):QObject{parent}{
_name = name;
_model = model;
_property = QQmlProperty(parent,_name);
_property.connectNotifySignal(this,SLOT(_propertyChange()));
}
FluPropertyObserver::~FluPropertyObserver(){
}
void FluPropertyObserver::_propertyChange(){
auto viewModel = (FluViewModel*)parent();
if(viewModel->enablePropertyChange){
auto value = _property.read();
_model->setProperty(_name.toLatin1().constData(),value);
FluViewModelManager::getInstance()->refreshViewModel(viewModel,_name,value);
}
}
FluViewModel::FluViewModel(QObject *parent):QObject{parent}{
scope(FluViewModelType::Scope::Window);
FluViewModelManager::getInstance()->insertViewModel(this);
}
FluViewModel::~FluViewModel(){
FluViewModelManager::getInstance()->deleteViewModel(this);
}
void FluViewModel::classBegin(){
}
void FluViewModel::componentComplete(){
auto o = parent();
while (nullptr != o) {
_window = o;
o = o->parent();
}
const QMetaObject* obj = metaObject();
if(_scope == FluViewModelType::Scope::Window){
_key = property("objectName").toString()+"-"+QString::number(reinterpret_cast<qulonglong>(_window), 16);
}else{
_key = property("objectName").toString();
}
QObject * model;
if(!FluViewModelManager::getInstance()->exist(_key)){
if(_scope == FluViewModelType::Scope::Window){
model = new QObject(_window);
}else{
model = new QObject();
}
Q_EMIT initData();
for (int i = 0; i < obj->propertyCount(); ++i) {
const QMetaProperty property = obj->property(i);
QString propertyName = property.name();
auto value = property.read(this);
model->setProperty(propertyName.toLatin1().constData(),value);
new FluPropertyObserver(propertyName,model,this);
}
FluViewModelManager::getInstance()->insert(_key,model);
}else{
model = FluViewModelManager::getInstance()->getModel(_key);
for (int i = 0; i < obj->propertyCount(); ++i) {
const QMetaProperty property = obj->property(i);
QString propertyName = property.name();
new FluPropertyObserver(propertyName,model,this);
}
}
foreach (auto key, model->dynamicPropertyNames()) {
setProperty(key,model->property(key));
}
}
QString FluViewModel::getKey(){
return _key;
}

View File

@ -1,69 +0,0 @@
#ifndef FLUVIEWMODEL_H
#define FLUVIEWMODEL_H
#include <QQuickItem>
#include <QtQml/qqml.h>
#include <QQuickWindow>
#include <QQmlProperty>
#include "stdafx.h"
#include "singleton.h"
/**
* @brief The FluViewModel class
*/
class FluViewModel : public QObject, public QQmlParserStatus
{
Q_OBJECT
Q_INTERFACES(QQmlParserStatus)
Q_PROPERTY_AUTO(int,scope);
QML_NAMED_ELEMENT(FluViewModel)
public:
explicit FluViewModel(QObject *parent = nullptr);
~FluViewModel();
void classBegin() override;
void componentComplete() override;
Q_SIGNAL void initData();
QString getKey();
bool enablePropertyChange = true;
private:
QObject* _window = nullptr;
QString _key = "";
};
/**
* @brief The FluPropertyObserver class
*/
class FluPropertyObserver: public QObject{
Q_OBJECT
public:
explicit FluPropertyObserver(QString name,QObject* model,QObject *parent = nullptr);
~FluPropertyObserver();
private:
Q_SLOT void _propertyChange();
private:
QString _name = "";
QQmlProperty _property;
QObject* _model = nullptr;
};
/**
* @brief The FluViewModelManager class
*/
class FluViewModelManager:public QObject{
Q_OBJECT
private:
explicit FluViewModelManager(QObject *parent = nullptr);
public:
SINGLETON(FluViewModelManager)
bool exist(const QString& key);
void insert(const QString& key,QObject* value);
QObject* getModel(const QString& key);
void insertViewModel(FluViewModel* value);
void deleteViewModel(FluViewModel* value);
void refreshViewModel(FluViewModel* viewModel,QString key,QVariant value);
private:
QMap<QString,QObject*> _data;
QList<FluViewModel*> _viewmodel;
};
#endif // FLUVIEWMODEL_H

View File

@ -1,28 +0,0 @@
#include "FluWindowLifecycle.h"
#include "FluApp.h"
FluWindowLifecycle::FluWindowLifecycle(QObject *parent):QObject{parent}{
}
void FluWindowLifecycle::onCompleted(QQuickWindow* window){
_window = window;
if(_window && _window->transientParent() == nullptr){
FluApp::getInstance()->addWindow(_window);
}
}
void FluWindowLifecycle::onDestoryOnClose(){
if(_window && _window->transientParent() == nullptr){
FluApp::getInstance()->removeWindow(_window);
_window = nullptr;
}
}
void FluWindowLifecycle::onDestruction(){
}
void FluWindowLifecycle::onVisible(bool visible){
}

View File

@ -1,28 +0,0 @@
#ifndef FLUWINDOWLIFECYCLE_H
#define FLUWINDOWLIFECYCLE_H
#include <QObject>
#include <QQuickWindow>
#include <QtQml/qqml.h>
#include <QQuickItem>
#include <QWindow>
#include <QJsonObject>
/**
* @brief The FluWindowLifecycle class
*/
class FluWindowLifecycle : public QObject
{
Q_OBJECT
QML_NAMED_ELEMENT(FluWindowLifecycle)
public:
explicit FluWindowLifecycle(QObject *parent = nullptr);
Q_INVOKABLE void onCompleted(QQuickWindow* window);
Q_INVOKABLE void onDestruction();
Q_INVOKABLE void onVisible(bool visible);
Q_INVOKABLE void onDestoryOnClose();
private:
QQuickWindow* _window = nullptr;
};
#endif // FLUWINDOWLIFECYCLE_H

View File

@ -1,18 +0,0 @@
#include "FluWindowRegister.h"
#include "FluApp.h"
#include <QCoreApplication>
FluWindowRegister::FluWindowRegister(QObject *parent):QObject{parent}{
from(nullptr);
to(nullptr);
path("");
}
void FluWindowRegister::launch(const QJsonObject& argument){
FluApp::getInstance()->navigate(path(),argument,this);
}
void FluWindowRegister::onResult(const QJsonObject& data){
Q_EMIT result(data);
}

View File

@ -1,25 +0,0 @@
#ifndef FLUWINDOWREGISTER_H
#define FLUWINDOWREGISTER_H
#include <QObject>
#include <QQuickWindow>
#include <QJsonObject>
#include "stdafx.h"
/**
* @brief The FluWindowRegister class
*/
class FluWindowRegister : public QObject
{
Q_OBJECT
Q_PROPERTY_AUTO(QQuickWindow*,from)
Q_PROPERTY_AUTO(QQuickWindow*,to)
Q_PROPERTY_AUTO(QString,path);
public:
explicit FluWindowRegister(QObject *parent = nullptr);
Q_INVOKABLE void launch(const QJsonObject& argument = {});
Q_INVOKABLE void onResult(const QJsonObject& data = {});
Q_SIGNAL void result(const QJsonObject& data);
};
#endif // FLUWINDOWREGISTER_H

View File

@ -1,7 +1,6 @@
#include "FluentUI.h"
#include <QGuiApplication>
#include "FluWindowLifecycle.h"
#include "Def.h"
#include "FluApp.h"
#include "FluColors.h"
@ -10,14 +9,11 @@
#include "FluTextStyle.h"
#include "FluWatermark.h"
#include "FluCaptcha.h"
#include "FluEventBus.h"
#include "FluTreeModel.h"
#include "FluViewModel.h"
#include "FluRectangle.h"
#include "FluNetwork.h"
#include "FluFramelessHelper.h"
#include "FluQrCodeItem.h"
#include "FluTableSortProxyModel.h"
#include "FluFrameless.h"
void FluentUI::registerTypes(QQmlEngine *engine){
initializeEngine(engine,uri);
@ -27,18 +23,15 @@ void FluentUI::registerTypes(QQmlEngine *engine){
void FluentUI::registerTypes(const char *uri){
#if (QT_VERSION < QT_VERSION_CHECK(6, 2, 0))
Q_INIT_RESOURCE(fluentui);
qmlRegisterType<FluWindowLifecycle>(uri,major,minor,"FluWindowLifecycle");
//@uri FluentUI
qmlRegisterType<FluQrCodeItem>(uri,major,minor,"FluQrCodeItem");
qmlRegisterType<FluCaptcha>(uri,major,minor,"FluCaptcha");
qmlRegisterType<FluWatermark>(uri,major,minor,"FluWatermark");
qmlRegisterType<FluAccentColor>(uri,major,minor,"FluAccentColor");
qmlRegisterType<FluEvent>(uri,major,minor,"FluEvent");
qmlRegisterType<FluViewModel>(uri,major,minor,"FluViewModel");
qmlRegisterType<FluTreeModel>(uri,major,minor,"FluTreeModel");
qmlRegisterType<FluRectangle>(uri,major,minor,"FluRectangle");
qmlRegisterType<FluNetworkCallable>(uri,major,minor,"FluNetworkCallable");
qmlRegisterType<FluNetworkParams>(uri,major,minor,"FluNetworkParams");
qmlRegisterType<FluFramelessHelper>(uri,major,minor,"FluFramelessHelper");
qmlRegisterType<FluFrameless>(uri,major,minor,"FluFrameless");
qmlRegisterType<FluTableSortProxyModel>(uri,major,minor,"FluTableSortProxyModel");
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluAcrylic.qml"),uri,major,minor,"FluAcrylic");
@ -128,6 +121,11 @@ void FluentUI::registerTypes(const char *uri){
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluLoader.qml"),uri,major,minor,"FluLoader");
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluShortcutPicker.qml"),uri,major,minor,"FluShortcutPicker");
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluSplitLayout.qml"),uri,major,minor,"FluSplitLayout");
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluWindowResultLauncher.qml"),uri,major,minor,"FluWindowResultLauncher");
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluLauncher.qml"),uri,major,minor,"FluLauncher");
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluEvent.qml"),uri,major,minor,"FluEvent");
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(FluThemeType::staticMetaObject, uri,major,minor,"FluThemeType", "Access to enums & flags only");
@ -141,8 +139,6 @@ void FluentUI::registerTypes(const char *uri){
qmlRegisterUncreatableMetaObject(FluTabViewType::staticMetaObject, uri,major,minor,"FluTabViewType", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluNavigationViewType::staticMetaObject, uri,major,minor,"FluNavigationViewType", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluTimelineType::staticMetaObject, uri,major,minor,"FluTimelineType", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluViewModelType::staticMetaObject, uri,major,minor,"FluViewModelType", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluNetworkType::staticMetaObject, uri,major,minor,"FluNetworkType", "Access to enums & flags only");
qmlRegisterModule(uri,major,minor);
#endif
@ -154,18 +150,9 @@ void FluentUI::initializeEngine(QQmlEngine *engine, const char *uri){
font.setFamily("微软雅黑");
QGuiApplication::setFont(font);
#endif
FluApp* app = FluApp::getInstance();
engine->rootContext()->setContextProperty("FluApp",app);
FluColors* colors = FluColors::getInstance();
engine->rootContext()->setContextProperty("FluColors",colors);
FluTheme* theme = FluTheme::getInstance();
engine->rootContext()->setContextProperty("FluTheme",theme);
FluTools* tools = FluTools::getInstance();
engine->rootContext()->setContextProperty("FluTools",tools);
FluTextStyle* textStyle = FluTextStyle::getInstance();
engine->rootContext()->setContextProperty("FluTextStyle",textStyle);
FluEventBus* eventBus = FluEventBus::getInstance();
engine->rootContext()->setContextProperty("FluEventBus",eventBus);
FluNetwork* network = FluNetwork::getInstance();
engine->rootContext()->setContextProperty("FluNetwork",network);
engine->rootContext()->setContextProperty("FluApp",FluApp::getInstance());
engine->rootContext()->setContextProperty("FluColors",FluColors::getInstance());
engine->rootContext()->setContextProperty("FluTheme",FluTheme::getInstance());
engine->rootContext()->setContextProperty("FluTools",FluTools::getInstance());
engine->rootContext()->setContextProperty("FluTextStyle",FluTextStyle::getInstance());
}

View File

@ -1,41 +0,0 @@
import QtQuick
import Qt5Compat.GraphicalEffects
import FluentUI
Item {
id: control
property color tintColor: Qt.rgba(1, 1, 1, 1)
property real tintOpacity: 0.65
property real luminosity: 0.01
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)
ShaderEffectSource {
id: effect_source
anchors.fill: parent
visible: false
sourceRect: control.targetRect
}
FastBlur {
id: fast_blur
anchors.fill: parent
source: effect_source
radius: control.blurRadius
}
Rectangle {
anchors.fill: parent
color: Qt.rgba(1, 1, 1, luminosity)
}
Rectangle {
anchors.fill: parent
color: Qt.rgba(tintColor.r, tintColor.g, tintColor.b, tintOpacity)
}
Image {
anchors.fill: parent
source: "../Image/noise.png"
fillMode: Image.Tile
opacity: control.noiseOpacity
}
}

View File

@ -1,347 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Window
import QtQuick.Layouts
import FluentUI
Rectangle{
property string title: ""
property string darkText : qsTr("Dark")
property string lightText : qsTr("Light")
property string minimizeText : qsTr("Minimize")
property string restoreText : qsTr("Restore")
property string maximizeText : qsTr("Maximize")
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 minimizeNormalColor: FluTheme.itemNormalColor
property color minimizeHoverColor: FluTheme.itemHoverColor
property color minimizePressColor: FluTheme.itemPressColor
property color maximizeNormalColor: FluTheme.itemNormalColor
property color maximizeHoverColor: FluTheme.itemHoverColor
property color maximizePressColor: FluTheme.itemPressColor
property color closeNormalColor: Qt.rgba(0,0,0,0)
property color closeHoverColor: Qt.rgba(251/255,115/255,115/255,1)
property color closePressColor: Qt.rgba(251/255,115/255,115/255,0.8)
property bool showDark: false
property bool showClose: true
property bool showMinimize: true
property bool showMaximize: true
property bool showStayTop: true
property bool titleVisible: true
property url icon
property int iconSize: 20
property bool isMac: FluTools.isMacos()
property color borerlessColor : FluTheme.primaryColor
property bool systemMoveEnable: true
property var maxClickListener : function(){
if(FluTools.isMacos()){
if (d.win.visibility === Window.FullScreen)
d.win.showNormal()
else
d.win.showFullScreen()
}else{
if (d.win.visibility === Window.Maximized)
d.win.showNormal()
else
d.win.showMaximized()
d.hoverMaxBtn = false
}
}
property var minClickListener: function(){
if(d.win.transientParent != null){
d.win.transientParent.showMinimized()
}else{
d.win.showMinimized()
}
}
property var closeClickListener : function(){
d.win.close()
}
property var stayTopClickListener: function(){
if(d.win instanceof FluWindow){
d.win.stayTop = !d.win.stayTop
}
}
property var darkClickListener: function(){
if(FluTheme.dark){
FluTheme.darkMode = FluThemeType.Light
}else{
FluTheme.darkMode = FluThemeType.Dark
}
}
property var systemMenuListener: function(){
if(d.win instanceof FluWindow){
d.win.showSystemMenu()
}
}
property alias buttonStayTop: btn_stay_top
property alias buttonMinimize: btn_minimize
property alias buttonMaximize: btn_maximize
property alias buttonClose: btn_close
property alias buttonDark: btn_dark
id:control
color: Qt.rgba(0,0,0,0)
height: visible ? 30 : 0
opacity: visible
z: 65535
Item{
id:d
property var hitTestList: []
property bool hoverMaxBtn: false
property var win: Window.window
property bool stayTop: {
if(d.win instanceof FluWindow){
return d.win.stayTop
}
return false
}
property bool isRestore: win && Window.Maximized === win.visibility
property bool resizable: win && !(win.height === win.maximumHeight && win.height === win.minimumHeight && win.width === win.maximumWidth && win.width === win.minimumWidth)
function containsPointToItem(point,item){
var pos = item.mapToGlobal(0,0)
var rect = Qt.rect(pos.x,pos.y,item.width,item.height)
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
}
}
MouseArea{
id:mouse_app_bar
anchors.fill: parent
onPositionChanged:
(mouse)=>{
if(systemMoveEnable){
d.win.startSystemMove()
}
}
onDoubleClicked:
(mouse)=>{
if(systemMoveEnable && d.resizable && Qt.LeftButton){
btn_maximize.clicked()
}
}
acceptedButtons: Qt.LeftButton|Qt.RightButton
onClicked:
(mouse)=>{
if (systemMoveEnable && mouse.button === Qt.RightButton){
control.systemMenuListener()
}
}
}
Row{
anchors{
verticalCenter: parent.verticalCenter
left: isMac ? undefined : parent.left
leftMargin: isMac ? undefined : 10
horizontalCenter: isMac ? parent.horizontalCenter : undefined
}
spacing: 10
Image{
width: control.iconSize
height: control.iconSize
visible: status === Image.Ready ? true : false
source: control.icon
anchors.verticalCenter: parent.verticalCenter
}
FluText {
text: title
visible: control.titleVisible
color:control.textColor
anchors.verticalCenter: parent.verticalCenter
}
}
Component{
id:com_mac_buttons
RowLayout{
FluImageButton{
Layout.preferredHeight: 12
Layout.preferredWidth: 12
normalImage: "../Image/btn_close_normal.png"
hoveredImage: "../Image/btn_close_hovered.png"
pushedImage: "../Image/btn_close_pushed.png"
visible: showClose
onClicked: closeClickListener()
}
FluImageButton{
Layout.preferredHeight: 12
Layout.preferredWidth: 12
normalImage: "../Image/btn_min_normal.png"
hoveredImage: "../Image/btn_min_hovered.png"
pushedImage: "../Image/btn_min_pushed.png"
onClicked: minClickListener()
visible: showMinimize
}
FluImageButton{
Layout.preferredHeight: 12
Layout.preferredWidth: 12
normalImage: "../Image/btn_max_normal.png"
hoveredImage: "../Image/btn_max_hovered.png"
pushedImage: "../Image/btn_max_pushed.png"
onClicked: maxClickListener()
visible: d.resizable && showMaximize
}
}
}
FluLoader{
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 10
}
sourceComponent: isMac ? com_mac_buttons : undefined
}
RowLayout{
id:layout_row
anchors.right: parent.right
height: control.height
spacing: 0
Component.onCompleted: {
setHitTestVisible(layout_row)
}
FluIconButton{
id:btn_dark
Layout.preferredWidth: 40
Layout.preferredHeight: 30
padding: 0
verticalPadding: 0
horizontalPadding: 0
rightPadding: 2
iconSource: FluTheme.dark ? FluentIcons.Brightness : FluentIcons.QuietHours
Layout.alignment: Qt.AlignVCenter
iconSize: 15
visible: showDark
text: FluTheme.dark ? control.lightText : control.darkText
radius: 0
iconColor:control.textColor
onClicked:()=> darkClickListener(btn_dark)
}
FluIconButton{
id:btn_stay_top
Layout.preferredWidth: 40
Layout.preferredHeight: 30
padding: 0
verticalPadding: 0
horizontalPadding: 0
iconSource : FluentIcons.Pinned
Layout.alignment: Qt.AlignVCenter
iconSize: 14
visible: {
if(!(d.win instanceof FluWindow)){
return false
}
return showStayTop
}
text:d.stayTop ? control.stayTopCancelText : control.stayTopText
radius: 0
iconColor: d.stayTop ? FluTheme.primaryColor : control.textColor
onClicked: stayTopClickListener()
}
FluIconButton{
id:btn_minimize
Layout.preferredWidth: 40
Layout.preferredHeight: 30
padding: 0
verticalPadding: 0
horizontalPadding: 0
iconSource : FluentIcons.ChromeMinimize
Layout.alignment: Qt.AlignVCenter
iconSize: 11
text:minimizeText
radius: 0
visible: !isMac && showMinimize
iconColor: control.textColor
color: {
if(pressed){
return minimizePressColor
}
return hovered ? minimizeHoverColor : minimizeNormalColor
}
onClicked: minClickListener()
}
FluIconButton{
id:btn_maximize
Layout.preferredWidth: 40
Layout.preferredHeight: 30
padding: 0
verticalPadding: 0
horizontalPadding: 0
iconSource : d.isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize
color: {
if(down){
return maximizePressColor
}
if(FluTools.isWindows11OrGreater()){
return d.hoverMaxBtn ? maximizeHoverColor : maximizeNormalColor
}
return hovered ? maximizeHoverColor : maximizeNormalColor
}
Layout.alignment: Qt.AlignVCenter
visible: d.resizable && !isMac && showMaximize
radius: 0
iconColor: control.textColor
text:d.isRestore?restoreText:maximizeText
iconSize: 11
onClicked: maxClickListener()
}
FluIconButton{
id:btn_close
Layout.preferredWidth: 40
Layout.preferredHeight: 30
padding: 0
verticalPadding: 0
horizontalPadding: 0
iconSource : FluentIcons.ChromeClose
Layout.alignment: Qt.AlignVCenter
text:closeText
visible: !isMac && showClose
radius: 0
iconSize: 10
iconColor: hovered ? Qt.rgba(1,1,1,1) : control.textColor
color:{
if(pressed){
return closePressColor
}
return hovered ? closeHoverColor : closeNormalColor
}
onClicked: closeClickListener()
}
}
function _maximizeButtonHover(){
var hover = false
if(btn_maximize.visible && FluTools.isWindows11OrGreater() && d.resizable){
if(d.containsPointToItem(FluTools.cursorPos(),btn_maximize)){
hover = true
}else{
if(btn_maximize.down){
btn_maximize.down = false
}
}
}
d.hoverMaxBtn = hover
return hover;
}
function _appBarHover(){
var cursorPos = FluTools.cursorPos()
for(var i =0 ;i< d.hitTestList.length; i++){
var item = d.hitTestList[i]
if(item.visible){
if(d.containsPointToItem(cursorPos,item)){
return false
}
}
}
if(d.containsPointToItem(cursorPos,control)){
return true
}
return false
}
function setHitTestVisible(id){
d.hitTestList.push(id)
}
}

View File

@ -1,28 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Window
import FluentUI
Rectangle {
default property alias contentData : layout_content.data
property int paddings : 0
property int leftPadding : 0
property int rightPadding : 0
property int topPadding : 0
property int bottomPadding : 0
id:control
radius: 4
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)
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
implicitHeight: height
implicitWidth: width
Item {
id: layout_content
anchors.fill: parent
anchors.leftMargin: Math.max(paddings,leftPadding)
anchors.rightMargin: Math.max(paddings,rightPadding)
anchors.topMargin: Math.max(paddings,topPadding)
anchors.bottomMargin: Math.max(paddings,bottomPadding)
}
}

View File

@ -1,139 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
FluTextBox{
property var items:[]
property string emptyText: qsTr("No results found")
property int autoSuggestBoxReplacement: FluentIcons.Search
property var filter: function(item){
if(item.title.indexOf(control.text)!==-1){
return true
}
return false
}
signal itemClicked(var data)
id:control
Component.onCompleted: {
d.loadData()
}
Item{
id:d
property bool flagVisible: true
property var window : Window.window
function handleClick(modelData){
control_popup.visible = false
control.itemClicked(modelData)
d.updateText(modelData.title)
}
function updateText(text){
d.flagVisible = false
control.text = text
d.flagVisible = true
}
function loadData(){
var result = []
if(items==null){
list_view.model = result
return
}
items.map(function(item){
if(control.filter(item)){
result.push(item)
}
})
list_view.model = result
}
}
onActiveFocusChanged: {
if(!activeFocus){
control_popup.visible = false
}
}
Popup{
id:control_popup
y:control.height
focus: false
padding: 0
enter: Transition {
NumberAnimation {
property: "opacity"
from:0
to:1
duration: FluTheme.enableAnimation ? 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)
ListView{
id:list_view
anchors.fill: parent
clip: true
boundsBehavior: ListView.StopAtBounds
ScrollBar.vertical: FluScrollBar {}
header: Item{
width: control.width
height: visible ? 38 : 0
visible: list_view.count === 0
FluText{
text:emptyText
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 10
}
}
}
delegate:FluControl{
id:item_control
height: 38
width: control.width
onClicked:{
d.handleClick(modelData)
}
background: Rectangle{
FluFocusRectangle{
visible: item_control.activeFocus
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)
}
return FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(0,0,0,0)
}
}
contentItem: FluText{
text:modelData.title
leftPadding: 10
rightPadding: 10
verticalAlignment : Qt.AlignVCenter
}
}
}
}
background: Item{
id:container
implicitWidth: control.width
implicitHeight: 38*Math.min(Math.max(list_view.count,1),8)
}
}
onTextChanged: {
d.loadData()
if(d.flagVisible){
var pos = control.mapToItem(null, 0, 0)
if(d.window.height>pos.y+control.height+container.implicitHeight){
control_popup.y = control.height
} else if(pos.y>container.implicitHeight){
control_popup.y = -container.implicitHeight
} else {
control_popup.y = d.window.height-(pos.y+container.implicitHeight)
}
control_popup.visible = true
}
}
}

View File

@ -1,79 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
Rectangle{
property bool isDot: false
property bool showZero: false
property int count: 0
property bool topRight: false
id:control
color:Qt.rgba(255/255,77/255,79/255,1)
width: {
if(isDot)
return 10
if(count<10){
return 20
}else if(count<100){
return 30
}
return 40
}
height: {
if(isDot)
return 10
return 20
}
radius: {
if(isDot)
return 5
return 10
}
border.width: 1
border.color: Qt.rgba(1,1,1,1)
anchors{
right: {
if(parent && topRight)
return parent.right
return undefined
}
top: {
if(parent && topRight)
return parent.top
return undefined
}
rightMargin: {
if(parent && topRight){
if(isDot){
return -2.5
}
return -(control.width/2)
}
return 0
}
topMargin: {
if(parent && topRight){
if(isDot){
return -2.5
}
return -10
}
return 0
}
}
visible: {
if(showZero)
return true
return count!==0
}
FluText{
anchors.centerIn: parent
color: Qt.rgba(1,1,1,1)
visible: !isDot
text:{
if(count<100)
return count
return count+"+"
}
}
}

View File

@ -1,92 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
Item {
property int textSize: 15
property string separator: "/"
property var items: []
property int spacing: 5
signal clickItem(var model)
id:control
implicitWidth: 300
height: 30
onItemsChanged: {
list_model.clear()
list_model.append(items)
}
ListModel{
id:list_model
}
ListView{
id:list_view
width: parent.width
height: 30
orientation: ListView.Horizontal
model: list_model
clip: true
spacing : control.spacing
boundsBehavior: ListView.StopAtBounds
remove: Transition {
NumberAnimation {
properties: "opacity"
from: 1
to: 0
duration: FluTheme.enableAnimation ? 83 : 1
}
}
add: Transition {
NumberAnimation {
properties: "opacity"
from: 0
to: 1
duration: FluTheme.enableAnimation ? 83 : 1
}
}
delegate: Item{
height: item_layout.height
width: item_layout.width
RowLayout{
id:item_layout
spacing: list_view.spacing
height: list_view.height
FluText{
text:model.title
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)
}
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(255/255,255/255,255/235,1) : Qt.rgba(26/255,26/255,26/235,1)
}
MouseArea{
id:item_mouse
anchors.fill: parent
hoverEnabled: true
onClicked: {
control.clickItem(model)
}
}
}
FluText{
text:control.separator
font.pixelSize: control.textSize
visible: list_view.count-1 !== index
Layout.alignment: Qt.AlignVCenter
}
}
}
}
function remove(index,count){
list_model.remove(index,count)
}
function count(){
return list_model.count
}
}

View File

@ -1,65 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import FluentUI
Button {
property bool disabled: false
property string contentDescription: ""
property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1)
property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(246/255,246/255,246/255,1)
property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(244/255,244/255,244/255,1)
property color textColor: {
if(FluTheme.dark){
if(!enabled){
return Qt.rgba(131/255,131/255,131/255,1)
}
if(pressed){
return Qt.rgba(162/255,162/255,162/255,1)
}
return Qt.rgba(1,1,1,1)
}else{
if(!enabled){
return Qt.rgba(160/255,160/255,160/255,1)
}
if(pressed){
return Qt.rgba(96/255,96/255,96/255,1)
}
return Qt.rgba(0,0,0,1)
}
}
Accessible.role: Accessible.Button
Accessible.name: control.text
Accessible.description: contentDescription
Accessible.onPressAction: control.clicked()
id: control
enabled: !disabled
verticalPadding: 0
horizontalPadding:12
font:FluTextStyle.Body
focusPolicy:Qt.TabFocus
background: Rectangle{
implicitWidth: 28
implicitHeight: 28
border.color: FluTheme.dark ? "#505050" : "#DFDFDF"
border.width: 1
radius: 4
color:{
if(!enabled){
return disableColor
}
return hovered ? hoverColor :normalColor
}
FluFocusRectangle{
visible: control.activeFocus
radius:4
}
}
contentItem: FluText {
text: control.text
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font: control.font
color: control.textColor
}
}

View File

@ -1,661 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
Rectangle {
property color dividerColor: FluTheme.dark ? Qt.rgba(77/255,77/255,77/255,1) : Qt.rgba(239/255,239/255,239/255,1)
property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1)
property color normalColor: FluTheme.dark ? Qt.rgba(61/255,61/255,61/255,1) : Qt.rgba(254/255,254/255,254/255,1)
property string text: qsTr("Pick a date")
property date from: new Date(1924, 0, 1)
property date to: new Date(2124, 11, 31)
property var current
signal accepted()
id:control
color: {
if(mouse_area.containsMouse){
return hoverColor
}
return normalColor
}
height: 30
width: 120
radius: 4
border.width: 1
border.color: dividerColor
MouseArea{
id:mouse_area
hoverEnabled: true
anchors.fill: parent
onClicked: {
popup.showPopup()
}
}
CalendarModel {
id:calender_model
from: control.from
to: control.to
}
Item{
id:d
property var window : Window.window
property date displayDate: {
if(control.current){
return control.current
}
return new Date()
}
property date toDay : new Date()
property int pageIndex: 0
signal nextButton
signal previousButton
property point yearRing : Qt.point(0,0)
}
FluText{
id:text_date
anchors{
left: parent.left
right: parent.right
rightMargin: 30
top: parent.top
bottom: parent.bottom
}
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text:{
if(control.current){
return control.current.toLocaleDateString(FluApp.locale,"yyyy/M/d")
}
return control.text
}
}
FluIcon{
iconSource: FluentIcons.Calendar
iconSize: 14
iconColor: text_date.color
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 12
}
}
Menu{
id:popup
height: container.height
width: container.width
modal: true
Overlay.modal: Item {}
enter: Transition {
reversible: true
NumberAnimation {
property: "opacity"
from:0
to:1
duration: FluTheme.enableAnimation ? 83 : 0
}
}
exit:Transition {
NumberAnimation {
property: "opacity"
from:1
to:0
duration: FluTheme.enableAnimation ? 83 : 0
}
}
contentItem: Item{
clip: true
FluArea{
id:container
width: 300
height: 360
ColumnLayout {
anchors.fill: parent
spacing: 0
Item{
Layout.fillWidth: true
Layout.preferredHeight: 50
RowLayout{
anchors.fill: parent
spacing: 10
Item{
Layout.leftMargin: parent.spacing
Layout.fillWidth: true
Layout.fillHeight: true
FluTextButton{
width: parent.width
anchors.centerIn: parent
contentItem: FluText {
text: d.displayDate.toLocaleString(FluApp.locale, "MMMM yyyy")
verticalAlignment: Text.AlignVCenter
}
visible: d.pageIndex === 0
onClicked: {
d.pageIndex = 1
}
}
FluTextButton{
width: parent.width
anchors.centerIn: parent
contentItem: FluText {
text: d.displayDate.toLocaleString(FluApp.locale, "yyyy")
verticalAlignment: Text.AlignVCenter
}
visible: d.pageIndex === 1
onClicked: {
d.pageIndex = 2
}
}
FluTextButton{
width: parent.width
anchors.centerIn: parent
contentItem: FluText {
text: "%1-%2".arg(d.yearRing.x).arg(d.yearRing.y)
verticalAlignment: Text.AlignVCenter
textColor: FluTheme.fontTertiaryColor
}
visible: d.pageIndex === 2
}
}
FluIconButton{
id:icon_up
iconSource: FluentIcons.CaretUpSolid8
iconSize: 10
onClicked: {
d.previousButton()
}
}
FluIconButton{
id:icon_down
iconSource: FluentIcons.CaretDownSolid8
iconSize: 10
Layout.rightMargin: parent.spacing
onClicked: {
d.nextButton()
}
}
}
FluDivider{
width: parent.width
height: 1
anchors.bottom: parent.bottom
}
}
Item{
Layout.fillWidth: true
Layout.fillHeight: true
StackView{
id:stack_view
anchors.fill: parent
initialItem: com_page_one
replaceEnter : Transition{
OpacityAnimator{
from: 0
to: 1
duration: 88
}
ScaleAnimator{
from: 0.5
to: 1
duration: 167
easing.type: Easing.OutCubic
}
}
replaceExit : Transition{
OpacityAnimator{
from: 1
to: 0
duration: 88
}
ScaleAnimator{
from: 1.0
to: 0.5
duration: 167
easing.type: Easing.OutCubic
}
}
}
Connections{
target: d
function onPageIndexChanged(){
if(d.pageIndex === 0){
stack_view.replace(com_page_one)
}
if(d.pageIndex === 1){
stack_view.replace(com_page_two)
}
if(d.pageIndex === 2){
stack_view.replace(com_page_three)
}
}
}
Component{
id:com_page_three
GridView{
id:grid_view
cellHeight: 75
cellWidth: 75
clip: true
boundsBehavior: GridView.StopAtBounds
ScrollBar.vertical: FluScrollBar {}
model: {
var fromYear = calender_model.from.getFullYear()
var toYear = calender_model.to.getFullYear()
return toYear-fromYear+1
}
highlightRangeMode: GridView.StrictlyEnforceRange
onCurrentIndexChanged:{
var year = currentIndex + calender_model.from.getFullYear()
var start = Math.ceil(year / 10) * 10
var end = start+10
d.yearRing = Qt.point(start,end)
}
highlightMoveDuration: 100
Component.onCompleted: {
grid_view.highlightMoveDuration = 0
currentIndex = d.displayDate.getFullYear()-calender_model.from.getFullYear()
timer_delay.restart()
}
Connections{
target: d
function onNextButton(){
grid_view.currentIndex = Math.min(grid_view.currentIndex+16,grid_view.count-1)
}
function onPreviousButton(){
grid_view.currentIndex = Math.max(grid_view.currentIndex-16,0)
}
}
Timer{
id:timer_delay
interval: 100
onTriggered: {
grid_view.highlightMoveDuration = 100
}
}
currentIndex: -1
delegate: Item{
property int year : calender_model.from.getFullYear()+modelData
property bool toYear: year === d.toDay.getFullYear()
implicitHeight: 75
implicitWidth: 75
FluControl{
id:control_delegate
width: 60
height: 60
anchors.centerIn: parent
Rectangle{
width: 48
height: 48
radius: width/2
color: {
if(toYear){
if(control_delegate.pressed){
return FluTheme.dark ? Qt.darker(FluTheme.primaryColor,1.2) : Qt.lighter(FluTheme.primaryColor,1.2)
}
if(control_delegate.hovered){
return FluTheme.dark ? Qt.darker(FluTheme.primaryColor,1.1) : Qt.lighter(FluTheme.primaryColor,1.1)
}
return FluTheme.primaryColor
}else{
if(control_delegate.pressed){
return FluTheme.itemPressColor
}
if(control_delegate.hovered){
return FluTheme.itemHoverColor
}
return FluColors.Transparent
}
}
anchors.centerIn: parent
}
FluText{
text: year
anchors.centerIn: parent
opacity: {
if(year >= d.yearRing.x && year <= d.yearRing.y){
return 1
}
if(control_delegate.hovered){
return 1
}
return 0.3
}
color: {
if(toYear){
return FluColors.White
}
if(control_delegate.pressed){
return FluTheme.dark ? FluColors.Grey100 : FluColors.Grey100
}
if(control_delegate.hovered){
return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120
}
return FluTheme.dark ? FluColors.White : FluColors.Grey220
}
}
onClicked: {
d.displayDate = new Date(year,0,1)
d.pageIndex = 1
}
}
}
}
}
Component{
id:com_page_two
ListView{
id:listview
ScrollBar.vertical: FluScrollBar {}
highlightRangeMode: ListView.StrictlyEnforceRange
clip: true
boundsBehavior: ListView.StopAtBounds
spacing: 0
highlightMoveDuration: 100
model: {
var fromYear = calender_model.from.getFullYear()
var toYear = calender_model.to.getFullYear()
var yearsArray = []
for (var i = fromYear; i <= toYear; i++) {
yearsArray.push(i)
}
return yearsArray
}
currentIndex: -1
onCurrentIndexChanged:{
var year = model[currentIndex]
var month = d.displayDate.getMonth()
d.displayDate = new Date(year,month,1)
}
Connections{
target: d
function onNextButton(){
listview.currentIndex = Math.min(listview.currentIndex+1,listview.count-1)
}
function onPreviousButton(){
listview.currentIndex = Math.max(listview.currentIndex-1,0)
}
}
Component.onCompleted: {
listview.highlightMoveDuration = 0
currentIndex = model.indexOf(d.displayDate.getFullYear())
timer_delay.restart()
}
Timer{
id:timer_delay
interval: 100
onTriggered: {
listview.highlightMoveDuration = 100
}
}
delegate: Item{
id:layout_congrol
property int year : modelData
width: listview.width
height: 75*3
GridView{
anchors.fill: parent
cellHeight: 75
cellWidth: 75
clip: true
interactive: false
boundsBehavior: GridView.StopAtBounds
model: 12
delegate: Item{
property int month : modelData
property bool toMonth: layout_congrol.year === d.toDay.getFullYear() && month === d.toDay.getMonth()
implicitHeight: 75
implicitWidth: 75
FluControl{
id:control_delegate
width: 60
height: 60
anchors.centerIn: parent
Rectangle{
width: 48
height: 48
radius: width/2
color: {
if(toMonth){
if(control_delegate.pressed){
return FluTheme.dark ? Qt.darker(FluTheme.primaryColor,1.2) : Qt.lighter(FluTheme.primaryColor,1.2)
}
if(control_delegate.hovered){
return FluTheme.dark ? Qt.darker(FluTheme.primaryColor,1.1) : Qt.lighter(FluTheme.primaryColor,1.1)
}
return FluTheme.primaryColor
}else{
if(control_delegate.pressed){
return FluTheme.itemPressColor
}
if(control_delegate.hovered){
return FluTheme.itemHoverColor
}
return FluColors.Transparent
}
}
anchors.centerIn: parent
}
FluText{
text: new Date(layout_congrol.year,month).toLocaleString(FluApp.locale, "MMMM")
anchors.centerIn: parent
opacity: {
if(layout_congrol.year === d.displayDate.getFullYear()){
return 1
}
if(control_delegate.hovered){
return 1
}
return 0.3
}
color: {
if(toMonth){
return FluColors.White
}
if(control_delegate.pressed){
return FluTheme.dark ? FluColors.Grey100 : FluColors.Grey100
}
if(control_delegate.hovered){
return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120
}
return FluTheme.dark ? FluColors.White : FluColors.Grey220
}
}
onClicked: {
d.displayDate = new Date(layout_congrol.year,month)
d.pageIndex = 0
}
}
}
}
}
}
}
Component{
id:com_page_one
ColumnLayout {
DayOfWeekRow {
id: dayOfWeekRow
locale: FluApp.locale
font.bold: false
delegate: Label {
text: model.shortName
font: dayOfWeekRow.font
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
Layout.column: 1
Layout.fillWidth: true
}
ListView{
id:listview
property bool isCompleted: false
Layout.fillWidth: true
Layout.fillHeight: true
highlightRangeMode: ListView.StrictlyEnforceRange
clip: true
boundsBehavior: ListView.StopAtBounds
spacing: 0
highlightMoveDuration: 100
currentIndex: -1
ScrollBar.vertical: FluScrollBar {}
onCurrentIndexChanged:{
if(isCompleted){
var month = calender_model.monthAt(currentIndex)
var year = calender_model.yearAt(currentIndex)
d.displayDate = new Date(year,month,1)
}
}
Component.onCompleted: {
listview.model = calender_model
listview.highlightMoveDuration = 0
currentIndex = calender_model.indexOf(d.displayDate)
timer_delay.restart()
isCompleted = true
}
Timer{
id:timer_delay
interval: 100
onTriggered: {
listview.highlightMoveDuration = 100
}
}
Connections{
target: d
function onNextButton(){
listview.currentIndex = Math.min(listview.currentIndex+1,listview.count-1)
}
function onPreviousButton(){
listview.currentIndex = Math.max(listview.currentIndex-1,0)
}
}
delegate: MonthGrid {
id: grid
width: listview.width
height: listview.height
month: model.month
year: model.year
spacing: 0
locale: FluApp.locale
delegate: FluControl {
required property bool today
required property int year
required property int month
required property int day
required property int visibleMonth
id: control_delegate
visibleMonth: grid.month
implicitHeight: 40
implicitWidth: 40
Rectangle{
width: 34
height: 34
radius: width/2
color: {
if(today){
if(control_delegate.pressed){
return FluTheme.dark ? Qt.darker(FluTheme.primaryColor,1.2) : Qt.lighter(FluTheme.primaryColor,1.2)
}
if(control_delegate.hovered){
return FluTheme.dark ? Qt.darker(FluTheme.primaryColor,1.1) : Qt.lighter(FluTheme.primaryColor,1.1)
}
return FluTheme.primaryColor
}else{
if(control_delegate.pressed){
return FluTheme.itemPressColor
}
if(control_delegate.hovered){
return FluTheme.itemHoverColor
}
return FluColors.Transparent
}
}
anchors.centerIn: parent
}
Rectangle{
width: 40
height: 40
border.width: 1
anchors.centerIn: parent
radius: width/2
border.color: FluTheme.primaryColor
color: FluColors.Transparent
visible: {
if(control.current){
var y = control.current.getFullYear()
var m = control.current.getMonth()
var d = control.current.getDate()
if(y === year && m === month && d === day){
return true
}
return false
}
return false
}
}
FluText{
text: day
opacity: {
if(month === grid.month){
return 1
}
if(control_delegate.hovered){
return 1
}
return 0.3
}
anchors.centerIn: parent
color: {
if(today){
return FluColors.White
}
if(control_delegate.pressed){
return FluTheme.dark ? FluColors.Grey100 : FluColors.Grey100
}
if(control_delegate.hovered){
return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120
}
return FluTheme.dark ? FluColors.White : FluColors.Grey220
}
}
onClicked: {
control.current = new Date(year,month,day)
control.accepted()
popup.close()
}
}
background: Item {
x: grid.leftPadding
y: grid.topPadding
width: grid.availableWidth
height: grid.availableHeight
}
}
}
}
}
}
}
}
}
background: Item{
FluShadow{
radius: 5
}
}
function showPopup() {
var pos = control.mapToItem(null, 0, 0)
if(d.window.height>pos.y+control.height+container.height){
popup.y = control.height
} 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

@ -1,206 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
Item {
property bool autoPlay: true
property int loopTime: 2000
property var model
property Component delegate
property bool showIndicator: true
property int indicatorGravity : Qt.AlignBottom | Qt.AlignHCenter
property int indicatorMarginLeft: 0
property int indicatorMarginRight: 0
property int indicatorMarginTop: 0
property int indicatorMarginBottom: 20
property int indicatorSpacing: 10
property alias indicatorAnchors: layout_indicator.anchors
property Component indicatorDelegate : com_indicator
id:control
width: 400
height: 300
ListModel{
id:content_model
}
QtObject{
id:d
property bool flagXChanged: true
property bool isAnimEnable: control.autoPlay && list_view.count>3
function setData(data){
if(!data){
return
}
content_model.clear()
content_model.append(data[data.length-1])
content_model.append(data)
content_model.append(data[0])
list_view.highlightMoveDuration = 0
list_view.currentIndex = 1
list_view.highlightMoveDuration = 250
if(d.isAnimEnable){
timer_run.restart()
}
}
}
ListView{
id:list_view
anchors.fill: parent
snapMode: ListView.SnapOneItem
clip: true
boundsBehavior: ListView.StopAtBounds
model:content_model
maximumFlickVelocity: 4 * (list_view.orientation === Qt.Horizontal ? width : height)
preferredHighlightBegin: 0
preferredHighlightEnd: 0
highlightMoveDuration: 0
Component.onCompleted: {
d.setData(control.model)
}
interactive: list_view.count>3
Connections{
target: control
function onModelChanged(){
d.setData(control.model)
}
}
orientation : ListView.Horizontal
delegate: Item{
id:item_control
width: ListView.view.width
height: ListView.view.height
property int displayIndex: {
if(index === 0)
return content_model.count-3
if(index === content_model.count-1)
return 0
return index-1
}
FluLoader{
property int displayIndex : item_control.displayIndex
property var model: list_view.model.get(index)
anchors.fill: parent
sourceComponent: {
if(model){
return control.delegate
}
return undefined
}
}
}
onMovementEnded:{
currentIndex = list_view.contentX/list_view.width
if(currentIndex === 0){
currentIndex = list_view.count-2
}else if(currentIndex === list_view.count-1){
currentIndex = 1
}
d.flagXChanged = false
timer_run.restart()
}
onMovementStarted: {
d.flagXChanged = true
timer_run.stop()
}
onContentXChanged: {
if(d.flagXChanged){
var maxX = Math.min(list_view.width*(currentIndex+1),list_view.count*list_view.width)
var minY = Math.max(0,(list_view.width*(currentIndex-1)))
if(contentX>=maxX){
contentX = maxX
}
if(contentX<=minY){
contentX = minY
}
}
}
}
Component{
id:com_indicator
Rectangle{
width: 8
height: 8
radius: 4
FluShadow{
radius: 4
}
scale: checked ? 1.2 : 1
color: checked ? FluTheme.primaryColor : Qt.rgba(1,1,1,0.7)
border.width: mouse_item.containsMouse ? 1 : 0
border.color: FluTheme.primaryColor
MouseArea{
id:mouse_item
hoverEnabled: true
anchors.fill: parent
onClicked: {
changedIndex(realIndex)
}
}
}
}
Row{
id:layout_indicator
spacing: control.indicatorSpacing
anchors{
horizontalCenter:(indicatorGravity & Qt.AlignHCenter) ? parent.horizontalCenter : undefined
verticalCenter: (indicatorGravity & Qt.AlignVCenter) ? parent.verticalCenter : undefined
bottom: (indicatorGravity & Qt.AlignBottom) ? parent.bottom : undefined
top: (indicatorGravity & Qt.AlignTop) ? parent.top : undefined
left: (indicatorGravity & Qt.AlignLeft) ? parent.left : undefined
right: (indicatorGravity & Qt.AlignRight) ? parent.right : undefined
bottomMargin: control.indicatorMarginBottom
leftMargin: control.indicatorMarginBottom
rightMargin: control.indicatorMarginBottom
topMargin: control.indicatorMarginBottom
}
visible: showIndicator
Repeater{
id:repeater_indicator
model: list_view.count
FluLoader{
property int displayIndex: {
if(index === 0)
return list_view.count-3
if(index === list_view.count-1)
return 0
return index-1
}
property int realIndex: index
property bool checked: list_view.currentIndex === index
sourceComponent: {
if(index===0 || index===list_view.count-1)
return undefined
return control.indicatorDelegate
}
}
}
}
Timer{
id:timer_anim
interval: 250
onTriggered: {
list_view.highlightMoveDuration = 0
if(list_view.currentIndex === list_view.count-1){
list_view.currentIndex = 1
}
}
}
Timer{
id:timer_run
interval: control.loopTime
repeat: d.isAnimEnable
onTriggered: {
list_view.highlightMoveDuration = 250
list_view.currentIndex = list_view.currentIndex+1
timer_anim.start()
}
}
function changedIndex(index){
d.flagXChanged = true
timer_run.stop()
list_view.currentIndex = index
d.flagXChanged = false
if(d.isAnimEnable){
timer_run.restart()
}
}
}

View File

@ -1,117 +0,0 @@
import QtQuick
import "./../JS/Chart.js" as Chart
Canvas {
id: control
property string chartType
property var chartData
property var chartOptions
property double chartAnimationProgress: 0.1
property int animationEasingType: Easing.InOutExpo
property double animationDuration: 300
property alias animationRunning: chartAnimator.running
signal animationFinished()
function animateToNewData()
{
chartAnimationProgress = 0.1;
d.jsChart.update();
chartAnimator.restart();
}
QtObject{
id:d
property var jsChart: undefined
property var memorizedContext
property var memorizedData
property var memorizedOptions
}
MouseArea {
id: event
anchors.fill: control
hoverEnabled: true
enabled: true
property var handler: undefined
property QtObject mouseEvent: QtObject {
property int left: 0
property int top: 0
property int x: 0
property int y: 0
property int clientX: 0
property int clientY: 0
property string type: ""
property var target
}
function submitEvent(mouse, type) {
mouseEvent.type = type
mouseEvent.clientX = mouse ? mouse.x : 0;
mouseEvent.clientY = mouse ? mouse.y : 0;
mouseEvent.x = mouse ? mouse.x : 0;
mouseEvent.y = mouse ? mouse.y : 0;
mouseEvent.left = 0;
mouseEvent.top = 0;
mouseEvent.target = control;
if(handler) {
handler(mouseEvent);
}
control.requestPaint();
}
onClicked:
(mouse)=> {
submitEvent(mouse, "click");
}
onPositionChanged:
(mouse)=> {
submitEvent(mouse, "mousemove");
}
onExited: {
submitEvent(undefined, "mouseout");
}
onEntered: {
submitEvent(undefined, "mouseenter");
}
onPressed:
(mouse)=> {
submitEvent(mouse, "mousedown");
}
onReleased:
(mouse)=> {
submitEvent(mouse, "mouseup");
}
}
PropertyAnimation {
id: chartAnimator
target: control
property: "chartAnimationProgress"
alwaysRunToEnd: true
to: 1
duration: control.animationDuration
easing.type: control.animationEasingType
onFinished: {
control.animationFinished();
}
}
onChartAnimationProgressChanged: {
control.requestPaint();
}
onPaint: {
if(control.getContext('2d') !== null && d.memorizedContext !== control.getContext('2d') || d.memorizedData !== control.chartData || d.memorizedOptions !== control.chartOptions) {
var ctx = control.getContext('2d');
d.jsChart = Chart.build(ctx, {type: control.chartType,data: control.chartData,options: control.chartOptions});
d.memorizedData = control.chartData ;
d.memorizedContext = control.getContext('2d');
d.memorizedOptions = control.chartOptions;
d.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;});
chartAnimator.start();
}
d.jsChart.draw(chartAnimationProgress);
}
onWidthChanged: {
if(d.jsChart) {
d.jsChart.resize();
}
}
onHeightChanged: {
if(d.jsChart) {
d.jsChart.resize();
}
}
}

View File

@ -1,138 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
Button {
property bool disabled: false
property string contentDescription: ""
property color borderNormalColor: FluTheme.dark ? Qt.rgba(160/255,160/255,160/255,1) : Qt.rgba(136/255,136/255,136/255,1)
property color bordercheckedColor: FluTheme.primaryColor
property color borderHoverColor: FluTheme.dark ? Qt.rgba(167/255,167/255,167/255,1) : Qt.rgba(135/255,135/255,135/255,1)
property color borderDisableColor: FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1)
property color borderPressedColor: FluTheme.dark ? Qt.rgba(90/255,90/255,90/255,1) : Qt.rgba(191/255,191/255,191/255,1)
property color normalColor: FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(247/255,247/255,247/255,1)
property color checkedColor: FluTheme.primaryColor
property color hoverColor: FluTheme.dark ? Qt.rgba(72/255,72/255,72/255,1) : Qt.rgba(236/255,236/255,236/255,1)
property color checkedHoverColor: FluTheme.dark ? Qt.darker(checkedColor,1.15) : Qt.lighter(checkedColor,1.15)
property color checkedPreesedColor: FluTheme.dark ? Qt.darker(checkedColor,1.3) : Qt.lighter(checkedColor,1.3)
property color checkedDisableColor: FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1)
property color disableColor: FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(253/255,253/255,253/255,1)
property real size: 18
property alias textColor: btn_text.textColor
property bool textRight: true
property real textSpacing: 6
property bool enableAnimation: FluTheme.enableAnimation
property var clickListener : function(){
checked = !checked
}
property bool indeterminate : false
id:control
enabled: !disabled
onClicked: clickListener()
onCheckableChanged: {
if(checkable){
checkable = false
}
}
background: Item{
FluFocusRectangle{
radius: 4
visible: control.activeFocus
}
}
horizontalPadding:0
verticalPadding: 0
padding: 0
Accessible.role: Accessible.Button
Accessible.name: control.text
Accessible.description: contentDescription
Accessible.onPressAction: control.clicked()
focusPolicy:Qt.TabFocus
contentItem: RowLayout{
spacing: control.textSpacing
layoutDirection:control.textRight ? Qt.LeftToRight : Qt.RightToLeft
Rectangle{
width: control.size
height: control.size
radius: 4
border.color: {
if(!enabled){
return borderDisableColor
}
if(checked){
return bordercheckedColor
}
if(pressed){
return borderPressedColor
}
if(hovered){
return borderHoverColor
}
return borderNormalColor
}
border.width: 1
color: {
if(checked){
if(!enabled){
return checkedDisableColor
}
if(pressed){
return checkedPreesedColor
}
if(hovered){
return checkedHoverColor
}
return checkedColor
}
if(!enabled){
return disableColor
}
if(hovered){
return hoverColor
}
return normalColor
}
Behavior on color {
enabled: control.enableAnimation
ColorAnimation{
duration: 83
}
}
FluIcon {
anchors.centerIn: parent
iconSource: FluentIcons.CheckboxIndeterminate
iconSize: 14
visible: indeterminate
iconColor: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1)
Behavior on visible {
enabled: control.enableAnimation
NumberAnimation{
duration: 83
}
}
}
FluIcon {
anchors.centerIn: parent
iconSource: FluentIcons.AcceptMedium
iconSize: 14
visible: checked && !indeterminate
iconColor: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1)
Behavior on visible {
enabled: control.enableAnimation
NumberAnimation{
duration: 83
}
}
}
}
FluText{
id:btn_text
text: control.text
Layout.alignment: Qt.AlignVCenter
visible: text !== ""
}
}
}

View File

@ -1,20 +0,0 @@
import QtQuick
import QtQuick.Controls
import Qt5Compat.GraphicalEffects
import FluentUI
FluRectangle {
id:control
color: "#00000000"
layer.enabled: !FluTools.isSoftware()
layer.textureSize: Qt.size(control.width*2*Math.ceil(Screen.devicePixelRatio),control.height*2*Math.ceil(Screen.devicePixelRatio))
layer.effect: OpacityMask{
maskSource: ShaderEffectSource{
sourceItem: FluRectangle{
radius: control.radius
width: control.width
height: control.height
}
}
}
}

View File

@ -1,589 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
Button{
id:control
width: 36
height: 36
implicitWidth: width
implicitHeight: height
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{
id:layout_color
radius: 5
color:"#00000000"
border.color: {
if(hovered)
return FluTheme.primaryColor
return FluTheme.dark ? Qt.rgba(100/255,100/255,100/255,1) : Qt.rgba(200/255,200/255,200/255,1)
}
border.width: 1
Rectangle{
anchors.fill: parent
anchors.margins: 4
radius: 5
color: control.current
}
}
contentItem: Item{}
onClicked: {
color_dialog.open()
}
FluPopup{
id:color_dialog
implicitWidth: 326
implicitHeight: 560
closePolicy: Popup.CloseOnEscape
Rectangle{
id:layout_actions
width: parent.width
height: 60
radius: 5
z:999
anchors.bottom: parent.bottom
color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
RowLayout{
anchors
{
centerIn: parent
margins: spacing
fill: parent
}
spacing: 10
Item{
Layout.fillWidth: true
Layout.fillHeight: true
FluButton{
text: control.cancelText
width: parent.width
anchors.centerIn: parent
onClicked: {
color_dialog.close()
}
}
}
Item{
Layout.fillWidth: true
Layout.fillHeight: true
FluFilledButton{
text: control.okText
width: parent.width
anchors.centerIn: parent
onClicked: {
current = layout_color_hue.colorValue
control.accepted()
color_dialog.close()
}
}
}
}
}
contentItem: Flickable{
implicitWidth: parent.width
implicitHeight: Math.min(layout_content.height,560,color_dialog.height)
boundsBehavior:Flickable.StopAtBounds
contentHeight: layout_content.height + 70
contentWidth: width
clip: true
ScrollBar.vertical: FluScrollBar {}
Item{
id: layout_content
width: parent.width
height: childrenRect.height
FluText{
id: text_titile
font: FluTextStyle.Subtitle
text: control.titleText
anchors{
left: parent.left
top: parent.top
leftMargin: 20
topMargin: 20
}
}
Item{
id: layout_sb
width: 200
height: 200
anchors{
left: parent.left
top: text_titile.bottom
leftMargin: 12
}
FluClip{
id: layout_color_hue
property color colorValue
property real xPercent: pickerCursor.x/width
property real yPercent: pickerCursor.y/height
property real blackPercent: blackCursor.x/(layout_black.width-12)
property real opacityPercent: opacityCursor.x/(layout_opacity.width-12)
property color opacityColor:{
var c = blackColor
c = Qt.rgba(c.r,c.g,c.b,opacityPercent)
return c
}
onOpacityColorChanged: {
layout_color_hue.colorValue = opacityColor
updateColorText(opacityColor)
}
function updateColorText(color){
text_box_r.text = String(Math.floor(color.r*255))
text_box_g.text = String(Math.floor(color.g*255))
text_box_b.text = String(Math.floor(color.b*255))
text_box_a.text = String(Math.floor(color.a*100))
var colorString = color.toString().slice(1)
if(color.a===1){
colorString = "FF"+colorString
}
text_box_color.text = colorString.toUpperCase()
}
property color blackColor: {
var c = whiteColor
c = Qt.rgba(c.r*blackPercent,c.g*blackPercent,c.b*blackPercent,1)
return c
}
property color hueColor: {
var v = 1.0-xPercent
var c
if(0.0 <= v && v < 0.16) {
c = Qt.rgba(1.0, 0.0, v/0.16, 1.0)
} else if(0.16 <= v && v < 0.33) {
c = Qt.rgba(1.0 - (v-0.16)/0.17, 0.0, 1.0, 1.0)
} else if(0.33 <= v && v < 0.5) {
c = Qt.rgba(0.0, ((v-0.33)/0.17), 1.0, 1.0)
} else if(0.5 <= v && v < 0.76) {
c = Qt.rgba(0.0, 1.0, 1.0 - (v-0.5)/0.26, 1.0)
} else if(0.76 <= v && v < 0.85) {
c = Qt.rgba((v-0.76)/0.09, 1.0, 0.0, 1.0)
} else if(0.85 <= v && v <= 1.0) {
c = Qt.rgba(1.0, 1.0 - (v-0.85)/0.15, 0.0, 1.0)
} else {
c = Qt.rgba(1.0,0.0,0.0,1.0)
}
return c
}
property color whiteColor: {
var c = hueColor
c = Qt.rgba((1-c.r)*yPercent+c.r,(1-c.g)*yPercent+c.g,(1-c.b)*yPercent+c.b,1.0)
return c
}
function updateColor(){
var r = Number(text_box_r.text)/255
var g = Number(text_box_g.text)/255
var b = Number(text_box_b.text)/255
var opacityPercent = Number(text_box_a.text)/100
var blackPercent = Math.max(r,g,b)
r = r/blackPercent
g = g/blackPercent
b = b/blackPercent
var yPercent = Math.min(r,g,b)
if(r === g && r === b){
r = 1
b = 1
g = 1
}else{
r = (yPercent-r)/(yPercent-1)
g = (yPercent-g)/(yPercent-1)
b = (yPercent-b)/(yPercent-1)
}
var xPercent
if (r === 1.0 && g === 0.0 && b <= 1.0) {
if(b===0.0){
xPercent = 0
}else{
xPercent = 1.0 - b * 0.16
}
} else if (r <= 1.0 && g === 0.0 && b === 1.0) {
xPercent = 1.0 - (1.0 - r) * 0.17 - 0.16
} else if (r === 0.0 && g <= 1.0 && b === 1.0) {
xPercent = 1.0 - (g * 0.17 + 0.33)
} else if (r === 0.0 && g === 1.0 && b <= 1.0) {
xPercent = 1.0 - (1.0 - b) * 0.26 - 0.5
} else if (r <= 1.0 && g === 1.0 && b === 0.0) {
xPercent = 1.0 - (r * 0.09 + 0.76)
} else if (r === 1.0 && g <= 1.0 && b === 0.0) {
xPercent = 1.0 - (1.0 - g) * 0.15 - 0.85
} else {
xPercent = 0
}
pickerCursor.x = xPercent * width
pickerCursor.y = yPercent * height
blackCursor.x = blackPercent * (layout_black.width-12)
opacityCursor.x = opacityPercent * (layout_opacity.width-12)
}
radius: [4,4,4,4]
x: colorHandleRadius
y: colorHandleRadius
width: parent.width - 2 * colorHandleRadius
height: parent.height - 2 * colorHandleRadius
Rectangle {
anchors.fill: parent
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: "#FF0000" }
GradientStop { position: 0.16; color: "#FFFF00" }
GradientStop { position: 0.33; color: "#00FF00" }
GradientStop { position: 0.5; color: "#00FFFF" }
GradientStop { position: 0.76; color: "#0000FF" }
GradientStop { position: 0.85; color: "#FF00FF" }
GradientStop { position: 1.0; color: "#FF0000" }
}
}
Rectangle {
anchors.fill: parent
gradient: Gradient {
GradientStop { position: 1.0; color: "#FFFFFFFF" }
GradientStop { position: 0.0; color: "#00000000" }
}
}
Rectangle{
radius: 4
anchors.fill: parent
border.width: 1
border.color: FluTheme.dividerColor
color:"#00000000"
}
}
Item {
id: pickerCursor
Rectangle {
width: colorHandleRadius*2; height: colorHandleRadius*2
radius: colorHandleRadius
border.color: "black"; border.width: 2
color: "transparent"
Rectangle {
anchors.fill: parent; anchors.margins: 2;
border.color: "white"; border.width: 2
radius: width/2
color: "transparent"
}
}
}
MouseArea {
anchors.fill: parent
x: colorHandleRadius
y: colorHandleRadius
preventStealing: true
function handleMouse(mouse) {
if (mouse.buttons & Qt.LeftButton) {
pickerCursor.x = Math.max(0,Math.min(mouse.x - colorHandleRadius,width-2*colorHandleRadius));
pickerCursor.y = Math.max(0,Math.min(mouse.y - colorHandleRadius,height-2*colorHandleRadius));
}
}
onPositionChanged:(mouse)=> handleMouse(mouse)
onPressed:(mouse)=> handleMouse(mouse)
}
}
FluClip{
width: 40
height: 200
anchors{
top: layout_sb.top
bottom: layout_sb.bottom
left: layout_sb.right
topMargin: colorHandleRadius
bottomMargin: colorHandleRadius
leftMargin: 4
}
radius: [4,4,4,4]
Grid {
padding: 0
id:target_grid_color
anchors.fill: parent
rows: height/5+1
columns: width/5+1
Repeater {
model: (target_grid_color.columns-1)*(target_grid_color.rows-1)
Rectangle {
width: 6
height: 6
color: (model.index%2 == 0) ? "gray" : "white"
}
}
}
Rectangle{
anchors.fill: parent
color:layout_color_hue.colorValue
radius: 4
border.width: 1
border.color: FluTheme.dividerColor
}
}
Column{
id:layout_slider_bar
spacing: 8
anchors{
left: parent.left
leftMargin: 18
right: parent.right
rightMargin: 18
top: layout_sb.bottom
topMargin: 10
}
Rectangle{
id:layout_black
radius: 6
height: 12
width:parent.width
gradient: Gradient {
orientation:Gradient.Horizontal
GradientStop { position: 0.0; color: "#FF000000" }
GradientStop { position: 1.0; color: layout_color_hue.hueColor }
}
Item {
id:blackCursor
x:layout_black.width-12
Rectangle {
width: 12
height: 12
radius: 6
border.color: "black"
border.width: 2
color: "transparent"
Rectangle {
anchors.fill: parent
anchors.margins: 2
border.color: "white"
border.width: 2
radius: width/2
color: "transparent"
}
}
}
MouseArea {
anchors.fill: parent
preventStealing: true
function handleMouse(mouse) {
if (mouse.buttons & Qt.LeftButton) {
blackCursor.x = Math.max(0,Math.min(mouse.x - 6,width-2*6));
blackCursor.y = 0
}
}
onPositionChanged:(mouse)=> handleMouse(mouse)
onPressed:(mouse)=> handleMouse(mouse)
}
}
FluClip{
id:layout_opacity
height: 12
width:parent.width
radius: [6,6,6,6]
Grid {
id:grid_opacity
anchors.fill: parent
rows: height/4
columns: width/4+1
clip: true
Repeater {
model: grid_opacity.columns*grid_opacity.rows
Rectangle {
width: 4
height: 4
color: (model.index%2 == 0) ? "gray" : "white"
}
}
}
MouseArea{
anchors.fill: parent
onClicked: {
console.debug(grid_opacity.columns,grid_opacity.rows)
}
}
Rectangle{
anchors.fill: parent
gradient: Gradient {
orientation:Gradient.Horizontal
GradientStop { position: 0.0; color: "#00000000" }
GradientStop { position: 1.0; color: layout_color_hue.blackColor }
}
}
Item {
id:opacityCursor
x:layout_opacity.width-12
Rectangle {
width: 12
height: 12
radius: 6
border.color: "black"
border.width: 2
color: "transparent"
Rectangle {
anchors.fill: parent
anchors.margins: 2
border.color: "white"
border.width: 2
radius: width/2
color: "transparent"
}
}
}
MouseArea {
id:mouse_opacity
anchors.fill: parent
preventStealing: true
function handleMouse(mouse) {
if (mouse.buttons & Qt.LeftButton) {
opacityCursor.x = Math.max(0,Math.min(mouse.x - 6,width-2*6));
opacityCursor.y = 0
}
}
onPositionChanged:(mouse)=> handleMouse(mouse)
onPressed:(mouse)=> handleMouse(mouse)
}
}
}
Column{
anchors{
left: parent.left
leftMargin: 20
top: layout_slider_bar.bottom
topMargin: 10
right: parent.right
rightMargin: 20
}
spacing: 5
Item{
width: parent.width
height: text_box_color.height
FluText{
text: control.editText
anchors{
verticalCenter: parent.verticalCenter
left:parent.left
}
}
FluTextBox{
id:text_box_color
width: 136
validator: RegularExpressionValidator {
regularExpression: /^[0-9A-F]{8}$/
}
anchors{
right: parent.right
}
leftPadding: 20
FluText{
text:"#"
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 5
}
}
onTextEdited: {
if(text!==""){
var colorString = text_box_color.text.padStart(8,"0")
var c = Qt.rgba(
parseInt(colorString.substring(2, 4), 16) / 255,
parseInt(colorString.substring(4, 6), 16) / 255,
parseInt(colorString.substring(6, 8), 16) / 255,
parseInt(colorString.substring(0, 2), 16) / 255)
layout_color_hue.colorValue = c
}
}
}
}
Row{
spacing: 10
FluTextBox{
id:text_box_r
width: 120
validator: RegularExpressionValidator {
regularExpression: /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$/
}
onTextEdited: {
if(text!==""){
layout_color_hue.updateColor()
}
}
}
FluText{
text: control.redText
anchors.verticalCenter: parent.verticalCenter
}
}
Row{
spacing: 10
FluTextBox{
id:text_box_g
width: 120
validator: RegularExpressionValidator {
regularExpression: /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$/
}
onTextEdited: {
if(text!==""){
layout_color_hue.updateColor()
}
}
}
FluText{
text: control.greenText
anchors.verticalCenter: parent.verticalCenter
}
}
Row{
spacing: 10
FluTextBox{
id:text_box_b
width: 120
validator: RegularExpressionValidator {
regularExpression: /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$/
}
onTextEdited: {
if(text!==""){
layout_color_hue.updateColor()
}
}
}
FluText{
text: control.blueText
anchors.verticalCenter: parent.verticalCenter
}
}
Row{
spacing: 10
FluTextBox{
id:text_box_a
width: 120
validator: RegularExpressionValidator {
regularExpression: /^(100|[1-9]?\d)$/
}
FluText{
id:text_opacity
text:"%"
anchors.verticalCenter: parent.verticalCenter
x:Math.min(text_box_a.implicitWidth,text_box_a.width)-38
}
onTextEdited: {
if(text!==""){
opacityCursor.x = Number(text)/100 * (layout_opacity.width-12)
}
}
}
FluText{
text: control.opacityText
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
}
}
}

View File

@ -1,146 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import FluentUI
import QtQuick.Templates as T
T.ComboBox {
id: control
signal commit(string text)
property bool disabled: false
property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1)
property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1)
property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1)
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding,
implicitIndicatorHeight + topPadding + bottomPadding)
font: FluTextStyle.Body
leftPadding: padding + (!control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
rightPadding: padding + (control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
enabled: !disabled
delegate: FluItemDelegate {
width: ListView.view.width
text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData
palette.text: control.palette.text
font: control.font
palette.highlightedText: control.palette.highlightedText
highlighted: control.highlightedIndex === index
hoverEnabled: control.hoverEnabled
}
focusPolicy:Qt.TabFocus
indicator: FluIcon {
x: control.mirrored ? control.padding : control.width - width - control.padding
y: control.topPadding + (control.availableHeight - height) / 2
width: 28
iconSource:FluentIcons.ChevronDown
iconSize: 15
opacity: enabled ? 1 : 0.3
}
contentItem: T.TextField {
property bool disabled: !control.editable
leftPadding: !control.mirrored ? 10 : control.editable && activeFocus ? 3 : 1
rightPadding: control.mirrored ? 10 : control.editable && activeFocus ? 3 : 1
topPadding: 6 - control.padding
bottomPadding: 6 - control.padding
renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering
selectionColor: FluTools.colorAlpha(FluTheme.primaryColor,0.5)
selectedTextColor: color
text: control.editable ? control.editText : control.displayText
enabled: control.editable
autoScroll: control.editable
font:control.font
readOnly: control.down
color: {
if(control.disabled) {
return FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1)
}
return FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1)
}
inputMethodHints: control.inputMethodHints
validator: control.validator
selectByMouse: true
verticalAlignment: Text.AlignVCenter
leftInset:1
topInset:1
bottomInset:1
rightInset:1
background: FluTextBoxBackground{
borderWidth: 0
inputItem: contentItem
}
Component.onCompleted: {
forceActiveFocus()
}
Keys.onEnterPressed: (event)=> handleCommit(event)
Keys.onReturnPressed:(event)=> handleCommit(event)
function handleCommit(event){
control.commit(control.editText)
accepted()
}
}
background: Rectangle {
implicitWidth: 140
implicitHeight: 32
border.color: FluTheme.dark ? "#505050" : "#DFDFDF"
border.width: 1
visible: !control.flat || control.down
radius: 4
FluFocusRectangle{
visible: control.visualFocus
radius:4
anchors.margins: -2
}
color:{
if(disabled){
return disableColor
}
return hovered ? hoverColor :normalColor
}
}
popup: T.Popup {
y: control.height
width: control.width
height: Math.min(contentItem.implicitHeight, control.Window.height - topMargin - bottomMargin)
topMargin: 6
bottomMargin: 6
modal: true
contentItem: ListView {
clip: true
implicitHeight: contentHeight
model: control.delegateModel
currentIndex: control.highlightedIndex
highlightMoveDuration: 0
boundsMovement: Flickable.StopAtBounds
T.ScrollIndicator.vertical: ScrollIndicator { }
}
enter: Transition {
NumberAnimation {
property: "opacity"
from:0
to:1
duration: FluTheme.enableAnimation ? 83 : 0
}
}
exit:Transition {
NumberAnimation {
property: "opacity"
from:1
to:0
duration: FluTheme.enableAnimation ? 83 : 0
}
}
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
FluShadow{
radius: 5
}
}
}
}

View File

@ -1,163 +0,0 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Window
import FluentUI
FluPopup {
id: control
property string title: ""
property string message: ""
property string neutralText: qsTr("Close")
property string negativeText: qsTr("Cancel")
property string positiveText: qsTr("OK")
property int messageTextFormart: Text.AutoText
property int delayTime: 100
property int buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
property var contentDelegate: Component{
Item{
}
}
property var onNeutralClickListener
property var onNegativeClickListener
property var onPositiveClickListener
signal neutralClicked
signal negativeClicked
signal positiveClicked
implicitWidth: 400
implicitHeight: layout_content.height
focus: true
Component{
id:com_message
Flickable{
id:sroll_message
contentHeight: text_message.height
contentWidth: width
clip: true
boundsBehavior:Flickable.StopAtBounds
width: parent.width
height: message === "" ? 0 : Math.min(text_message.height,300)
ScrollBar.vertical: FluScrollBar {}
FluText{
id:text_message
font: FluTextStyle.Body
wrapMode: Text.WrapAnywhere
text:message
width: parent.width
topPadding: 4
leftPadding: 20
rightPadding: 20
bottomPadding: 4
}
}
}
Rectangle {
id:layout_content
width: parent.width
height: layout_column.childrenRect.height
color: 'transparent'
radius:5
ColumnLayout{
id:layout_column
width: parent.width
FluText{
id:text_title
font: FluTextStyle.Title
text:title
topPadding: 20
leftPadding: 20
rightPadding: 20
wrapMode: Text.WrapAnywhere
}
FluLoader{
sourceComponent: com_message
Layout.fillWidth: true
Layout.preferredHeight: status===Loader.Ready ? item.height : 0
}
FluLoader{
sourceComponent:control.visible ? control.contentDelegate : undefined
Layout.fillWidth: true
onStatusChanged: {
if(status===Loader.Ready){
Layout.preferredHeight = item.implicitHeight
}else{
Layout.preferredHeight = 0
}
}
}
Rectangle{
id:layout_actions
Layout.fillWidth: true
Layout.preferredHeight: 60
radius: 5
color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
RowLayout{
anchors
{
centerIn: parent
margins: spacing
fill: parent
}
spacing: 10
Item{
Layout.fillWidth: true
Layout.fillHeight: true
FluButton{
id:neutral_btn
visible: control.buttonFlags&FluContentDialogType.NeutralButton
text: neutralText
width: parent.width
anchors.centerIn: parent
onClicked: {
if(control.onNeutralClickListener){
control.onNeutralClickListener()
}else{
neutralClicked()
control.close()
}
}
}
}
Item{
Layout.fillWidth: true
Layout.fillHeight: true
FluButton{
id:negative_btn
visible: control.buttonFlags&FluContentDialogType.NegativeButton
width: parent.width
anchors.centerIn: parent
text: negativeText
onClicked: {
if(control.onNegativeClickListener){
control.onNegativeClickListener()
}else{
negativeClicked()
control.close()
}
}
}
}
Item{
Layout.fillWidth: true
Layout.fillHeight: true
FluFilledButton{
id:positive_btn
visible: control.buttonFlags&FluContentDialogType.PositiveButton
text: positiveText
width: parent.width
anchors.centerIn: parent
onClicked: {
if(control.onPositiveClickListener){
control.onPositiveClickListener()
}else{
positiveClicked()
control.close()
}
}
}
}
}
}
}
}
}

View File

@ -1,60 +0,0 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
FluPage {
property alias title: text_title.text
default property alias content: container.data
property int leftPadding: 10
property int topPadding: 0
property int rightPadding: 10
property int bottomPadding: 10
property alias color: status_view.color
property alias statusMode: status_view.statusMode
property alias loadingText: status_view.loadingText
property alias emptyText:status_view.emptyText
property alias errorText:status_view.errorText
property alias errorButtonText:status_view.errorButtonText
property alias loadingItem :status_view.loadingItem
property alias emptyItem : status_view.emptyItem
property alias errorItem :status_view.errorItem
signal errorClicked
id:control
FluText{
id:text_title
visible: text !== ""
height: visible ? contentHeight : 0
font: FluTextStyle.Title
anchors{
top: parent.top
topMargin: control.topPadding
left: parent.left
right: parent.right
leftMargin: control.leftPadding
rightMargin: control.rightPadding
}
}
FluStatusLayout{
id:status_view
color: "#00000000"
statusMode: FluStatusLayoutType.Success
onErrorClicked: control.errorClicked()
anchors{
left: parent.left
right: parent.right
top: text_title.bottom
bottom: parent.bottom
leftMargin: control.leftPadding
rightMargin: control.rightPadding
bottomMargin: control.bottomPadding
}
Item{
clip: true
id:container
anchors.fill: parent
}
}
}

View File

@ -1,28 +0,0 @@
import QtQuick
import QtQuick.Controls.impl
import FluentUI
import QtQuick.Templates as T
T.Button {
id: control
property string contentDescription: ""
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding)
padding: 0
horizontalPadding: 0
spacing: 0
contentItem: Item{}
focusPolicy:Qt.TabFocus
background: Item{
FluFocusRectangle{
visible: control.activeFocus
radius:8
}
}
Accessible.role: Accessible.Button
Accessible.name: control.text
Accessible.description: contentDescription
Accessible.onPressAction: control.clicked()
}

View File

@ -1,35 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
TextEdit {
property color textColor: FluTheme.dark ? FluColors.White : FluColors.Grey220
id:control
color: textColor
readOnly: true
activeFocusOnTab: false
activeFocusOnPress: false
renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering
padding: 0
leftPadding: 0
rightPadding: 0
topPadding: 0
selectByMouse: true
selectedTextColor: color
bottomPadding: 0
selectionColor: FluTools.colorAlpha(FluTheme.primaryColor,0.5)
font:FluTextStyle.Body
onSelectedTextChanged: {
control.forceActiveFocus()
}
MouseArea{
anchors.fill: parent
cursorShape: Qt.IBeamCursor
acceptedButtons: Qt.RightButton
onClicked: control.echoMode !== TextInput.Password && menu.popup()
}
FluTextBoxMenu{
id:menu
inputItem: control
}
}

View File

@ -1,415 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
Rectangle {
property color dividerColor: FluTheme.dark ? Qt.rgba(77/255,77/255,77/255,1) : Qt.rgba(239/255,239/255,239/255,1)
property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1)
property color normalColor: FluTheme.dark ? Qt.rgba(61/255,61/255,61/255,1) : Qt.rgba(254/255,254/255,254/255,1)
property bool showYear: true
property var current
property string yearText: qsTr("Year")
property string monthText: qsTr("Month")
property string dayText: qsTr("Day")
property string cancelText: qsTr("Cancel")
property string okText: qsTr("OK")
signal accepted()
id:control
color: {
if(mouse_area.containsMouse){
return hoverColor
}
return normalColor
}
height: 30
width: 300
radius: 4
border.width: 1
border.color: dividerColor
Component.onCompleted: {
if(current){
const now = current;
var year = text_year.text === control.yearText? now.getFullYear() : Number(text_year.text);
var month = text_month.text === control.monthText? now.getMonth() + 1 : Number(text_month.text);
var day = text_day.text === control.dayText ? now.getDate() : Number(text_day.text);
text_year.text = year
text_month.text = month
text_day.text = day
}
}
Item{
id:d
property var window: Window.window
property bool changeFlag: true
property var rowData: ["","",""]
visible: false
}
MouseArea{
id:mouse_area
hoverEnabled: true
anchors.fill: parent
onClicked: {
popup.showPopup()
}
}
Rectangle{
id:divider_1
width: 1
x: parent.width/3
height: parent.height
color: dividerColor
visible: showYear
}
Rectangle{
id:divider_2
width: 1
x: showYear ? parent.width*2/3 : parent.width/2
height: parent.height
color: dividerColor
}
FluText{
id:text_year
anchors{
left: parent.left
right: divider_1.left
top: parent.top
bottom: parent.bottom
}
visible: showYear
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text:control.yearText
}
FluText{
id:text_month
anchors{
left: showYear ? divider_1.right : parent.left
right: divider_2.left
top: parent.top
bottom: parent.bottom
}
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text:control.monthText
}
FluText{
id:text_day
anchors{
left: divider_2.right
right: parent.right
top: parent.top
bottom: parent.bottom
}
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text:control.dayText
}
Menu{
id:popup
modal: true
width: container.width
height: container.height
Overlay.modal: Item {}
enter: Transition {
reversible: true
NumberAnimation {
property: "opacity"
from:0
to:1
duration: FluTheme.enableAnimation ? 83 : 0
}
}
exit:Transition {
NumberAnimation {
property: "opacity"
from:1
to:0
duration: FluTheme.enableAnimation ? 83 : 0
}
}
background:Item{
FluShadow{
radius: 4
}
}
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)
MouseArea{
anchors.fill: parent
}
FluShadow{
radius: 4
}
RowLayout{
id:layout_content
spacing: 0
width: parent.width
height: 300
Component{
id:list_delegate
Item{
height:38
width:getListView().width
function getListView(){
if(type === 0)
return list_view_1
if(type === 1)
return list_view_2
if(type === 2)
return list_view_3
}
Rectangle{
anchors.fill: parent
anchors.topMargin: 2
anchors.bottomMargin: 2
anchors.leftMargin: 5
anchors.rightMargin: 5
color: {
if(getListView().currentIndex === position){
return item_mouse.containsMouse ? Qt.lighter(FluTheme.primaryColor,1.1): FluTheme.primaryColor
}
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)
}
radius: 3
MouseArea{
id:item_mouse
anchors.fill: parent
hoverEnabled: true
onClicked: {
getListView().currentIndex = position
if(type === 0){
text_year.text = model
list_view_2.model = generateMonthArray(1,12)
text_month.text = list_view_2.model[list_view_2.currentIndex]
list_view_3.model = generateMonthDaysArray(list_view_1.model[list_view_1.currentIndex],list_view_2.model[list_view_2.currentIndex])
text_day.text = list_view_3.model[list_view_3.currentIndex]
}
if(type === 1){
text_month.text = model
list_view_3.model = generateMonthDaysArray(list_view_1.model[list_view_1.currentIndex],list_view_2.model[list_view_2.currentIndex])
text_day.text = list_view_3.model[list_view_3.currentIndex]
}
if(type === 2){
text_day.text = model
}
}
}
FluText{
text:model
color: {
if(getListView().currentIndex === position){
if(FluTheme.dark){
return Qt.rgba(0,0,0,1)
}else{
return Qt.rgba(1,1,1,1)
}
}else{
return FluTheme.dark ? "#FFFFFF" : "#1A1A1A"
}
}
anchors.centerIn: parent
}
}
}
}
ListView{
id:list_view_1
width: 100
height: parent.height
boundsBehavior:Flickable.StopAtBounds
ScrollBar.vertical: FluScrollBar {}
model: generateYearArray(1924,2048)
clip: true
preferredHighlightBegin: 0
preferredHighlightEnd: 0
highlightMoveDuration: 0
visible: showYear
delegate: FluLoader{
property var model: modelData
property int type:0
property int position:index
sourceComponent: list_delegate
}
}
Rectangle{
width: 1
height: parent.height
color: dividerColor
}
ListView{
id:list_view_2
width: showYear ? 100 : 150
height: parent.height
clip: true
ScrollBar.vertical: FluScrollBar {}
preferredHighlightBegin: 0
preferredHighlightEnd: 0
highlightMoveDuration: 0
boundsBehavior:Flickable.StopAtBounds
delegate: FluLoader{
property var model: modelData
property int type:1
property int position:index
sourceComponent: list_delegate
}
}
Rectangle{
width: 1
height: parent.height
color: dividerColor
}
ListView{
id:list_view_3
width: showYear ? 100 : 150
height: parent.height
clip: true
preferredHighlightBegin: 0
preferredHighlightEnd: 0
highlightMoveDuration: 0
ScrollBar.vertical: FluScrollBar {}
Layout.alignment: Qt.AlignVCenter
boundsBehavior:Flickable.StopAtBounds
delegate: FluLoader{
property var model: modelData
property int type:2
property int position:index
sourceComponent: list_delegate
}
}
}
Rectangle{
width: parent.width
height: 1
anchors.top: layout_content.bottom
color: dividerColor
}
Rectangle{
id:layout_actions
height: 40
radius: 5
color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
anchors{
bottom:parent.bottom
left: parent.left
right: parent.right
}
Item {
id:divider
width: 1
height: parent.height
anchors.centerIn: parent
}
FluButton{
anchors{
left: parent.left
leftMargin: 20
rightMargin: 10
right: divider.left
verticalCenter: parent.verticalCenter
}
text: control.cancelText
onClicked: {
popup.close()
}
}
FluFilledButton{
anchors{
right: parent.right
left: divider.right
rightMargin: 20
leftMargin: 10
verticalCenter: parent.verticalCenter
}
text: control.okText
onClicked: {
d.changeFlag = false
popup.close()
const year = text_year.text
const month = text_month.text
const day = text_day.text
const date = new Date()
date.setFullYear(parseInt(year));
date.setMonth(parseInt(month) - 1);
date.setDate(parseInt(day));
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
current = date
control.accepted()
}
}
}
}
}
y:35
function showPopup() {
d.changeFlag = true
d.rowData[0] = text_year.text
d.rowData[1] = text_month.text
d.rowData[2] = text_day.text
const now = new Date();
var year = text_year.text === control.yearText? now.getFullYear() : Number(text_year.text);
var month = text_month.text === control.monthText? now.getMonth() + 1 : Number(text_month.text);
var day = text_day.text === control.dayText ? now.getDate() : Number(text_day.text);
list_view_1.currentIndex = list_view_1.model.indexOf(year)
text_year.text = year
list_view_2.model = generateMonthArray(1,12)
list_view_2.currentIndex = list_view_2.model.indexOf(month)
text_month.text = month
list_view_3.model = generateMonthDaysArray(year,month)
list_view_3.currentIndex = list_view_3.model.indexOf(day)
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
} else if(pos.y>container.height){
popup.y = -container.height
} else {
popup.y = d.window.height-(pos.y+container.height)
}
popup.open()
}
onClosed: {
if(d.changeFlag){
text_year.text = d.rowData[0]
text_month.text = d.rowData[1]
text_day.text = d.rowData[2]
}
}
}
function generateYearArray(startYear, endYear) {
const yearArray = [];
for (let year = startYear; year <= endYear; year++) {
yearArray.push(year);
}
return yearArray;
}
function generateMonthArray(startMonth, endMonth) {
const monthArray = [];
for (let month = startMonth; month <= endMonth; month++) {
monthArray.push(month);
}
return monthArray;
}
function generateMonthDaysArray(year, month) {
const monthDaysArray = [];
const lastDayOfMonth = new Date(year, month, 0).getDate();
for (let day = 1; day <= lastDayOfMonth; day++) {
monthDaysArray.push(day);
}
return monthDaysArray;
}
}

View File

@ -1,34 +0,0 @@
import QtQuick
import QtQuick.Window
import FluentUI
Item {
id:control
property int orientation: Qt.Horizontal
property int spacing:0
property int size: 1
QtObject{
id:d
property bool isVertical : orientation === Qt.Vertical
property int parentHeight: {
if(control.parent){
return control.parent.height
}
return control.height
}
property int parentWidth: {
if(control.parent){
return control.parent.width
}
return control.width
}
}
width: d.isVertical ? spacing*2+size : d.parentWidth
height: d.isVertical ? d.parentHeight : spacing*2+size
FluRectangle{
color: FluTheme.dividerColor
width: d.isVertical ? size : control.width
height: d.isVertical ? control.height : size
anchors.centerIn: parent
}
}

View File

@ -1,96 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import QtQuick.Window
import FluentUI
Button {
property bool disabled: false
property string contentDescription: ""
property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1)
property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(246/255,246/255,246/255,1)
property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(244/255,244/255,244/255,1)
property color textColor: {
if(FluTheme.dark){
if(!enabled){
return Qt.rgba(131/255,131/255,131/255,1)
}
if(pressed){
return Qt.rgba(162/255,162/255,162/255,1)
}
return Qt.rgba(1,1,1,1)
}else{
if(!enabled){
return Qt.rgba(160/255,160/255,160/255,1)
}
if(pressed){
return Qt.rgba(96/255,96/255,96/255,1)
}
return Qt.rgba(0,0,0,1)
}
}
property var window : Window.window
default property alias contentData: menu.contentData
Accessible.role: Accessible.Button
Accessible.name: control.text
Accessible.description: contentDescription
Accessible.onPressAction: control.clicked()
id: control
rightPadding:35
enabled: !disabled
focusPolicy:Qt.TabFocus
verticalPadding: 0
horizontalPadding:12
background: Rectangle{
implicitWidth: 28
implicitHeight: 28
border.color: FluTheme.dark ? "#505050" : "#DFDFDF"
border.width: 1
radius: 4
FluFocusRectangle{
visible: control.activeFocus
radius:8
}
color:{
if(!enabled){
return disableColor
}
return hovered ? hoverColor :normalColor
}
FluIcon{
iconSource:FluentIcons.ChevronDown
iconSize: 15
anchors{
right: parent.right
rightMargin: 10
verticalCenter: parent.verticalCenter
}
iconColor:title.color
}
}
contentItem: FluText {
id:title
text: control.text
verticalAlignment: Text.AlignVCenter
color: control.textColor
}
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){
menu.y = control.height
}else if(pos.y>containerHeight){
menu.y = -containerHeight
}else{
menu.y = window.height-(pos.y+containerHeight)
}
menu.open()
}
}
FluMenu{
id:menu
modal:true
width: control.width
}
}

View File

@ -1,133 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Window
import FluentUI
Item {
property string headerText: ""
property bool expand: false
property int contentHeight : 300
default property alias content: container.data
id:control
implicitHeight: Math.max((layout_header.height + layout_container.height),layout_header.height)
implicitWidth: 400
QtObject{
id:d
property bool flag: false
function toggle(){
d.flag = true
expand = !expand
d.flag = false
}
}
clip: true
Rectangle{
id:layout_header
width: parent.width
height: 45
radius: 4
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)
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)
MouseArea{
id:control_mouse
anchors.fill: parent
hoverEnabled: true
onClicked: {
d.toggle()
}
}
FluText{
text: headerText
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 15
}
}
FluIconButton{
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 15
}
color:{
if(control_mouse.containsMouse || hovered){
return FluTheme.dark ? Qt.rgba(73/255,73/255,73/255,1) : Qt.rgba(245/255,245/255,245/255,1)
}
return FluTheme.dark ? Qt.rgba(0,0,0,0) : Qt.rgba(0,0,0,0)
}
onClicked: {
d.toggle()
}
contentItem: FluIcon{
rotation: expand?0:180
iconSource:FluentIcons.ChevronUp
iconSize: 15
Behavior on rotation {
enabled: FluTheme.enableAnimation
NumberAnimation{
duration: 167
easing.type: Easing.OutCubic
}
}
}
}
}
Item{
id:layout_container
anchors{
top: layout_header.bottom
topMargin: -1
left: layout_header.left
}
visible: contentHeight+container.anchors.topMargin !== 0
height: contentHeight+container.anchors.topMargin
width: parent.width
z:-999
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)
border.color: FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
anchors.topMargin: -contentHeight
states: [
State{
name:"expand"
when: control.expand
PropertyChanges {
target: container
anchors.topMargin:0
}
},
State{
name:"collapsed"
when: !control.expand
PropertyChanges {
target: container
anchors.topMargin:-contentHeight
}
}
]
transitions: [
Transition {
to:"expand"
NumberAnimation {
properties: "anchors.topMargin"
duration: FluTheme.enableAnimation && d.flag ? 167 : 0
easing.type: Easing.OutCubic
}
},
Transition {
to:"collapsed"
NumberAnimation {
properties: "anchors.topMargin"
duration: FluTheme.enableAnimation && d.flag ? 167 : 0
easing.type: Easing.OutCubic
}
}
]
}
}
}

View File

@ -1,72 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import FluentUI
Button {
property bool disabled: false
property string contentDescription: ""
property color normalColor: FluTheme.primaryColor
property color hoverColor: FluTheme.dark ? Qt.darker(normalColor,1.1) : Qt.lighter(normalColor,1.1)
property color disableColor: FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1)
property color pressedColor: FluTheme.dark ? Qt.darker(normalColor,1.2) : Qt.lighter(normalColor,1.2)
property color textColor: {
if(FluTheme.dark){
if(!enabled){
return Qt.rgba(173/255,173/255,173/255,1)
}
return Qt.rgba(0,0,0,1)
}else{
return Qt.rgba(1,1,1,1)
}
}
Accessible.role: Accessible.Button
Accessible.name: control.text
Accessible.description: contentDescription
Accessible.onPressAction: control.clicked()
id: control
enabled: !disabled
focusPolicy:Qt.TabFocus
font:FluTextStyle.Body
verticalPadding: 0
horizontalPadding:12
background: Rectangle{
implicitWidth: 28
implicitHeight: 28
radius: 4
FluFocusRectangle{
visible: control.visualFocus
radius:4
}
gradient: Gradient {
GradientStop { position: 0.33; color: control.enabled ? control.normalColor : Qt.rgba(0,0,0,0) }
GradientStop { position: 1.0; color: control.enabled ? Qt.darker(control.normalColor,1.3) : Qt.rgba(0,0,0,0) }
}
Rectangle{
radius: parent.radius
anchors{
fill: parent
topMargin: control.enabled ? 0 : 0
leftMargin: control.enabled ? 1 : 0
rightMargin: control.enabled ? 1 : 0
bottomMargin: control.enabled ? 2 : 0
}
color:{
if(!enabled){
return disableColor
}
if(pressed){
return pressedColor
}
return hovered ? hoverColor :normalColor
}
}
}
contentItem: FluText {
text: control.text
font: control.font
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: control.textColor
}
}

View File

@ -1,107 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import FluentUI
Item{
property bool vertical: false
default property alias content : swipe.contentData
property alias currentIndex: swipe.currentIndex
id:control
width: 400
height: 300
implicitWidth: width
implicitHeight: height
QtObject{
id:d
property bool flag: true
}
MouseArea{
anchors.fill: parent
preventStealing: true
onWheel:
(wheel)=>{
if(!d.flag)
return
if (wheel.angleDelta.y > 0){
btn_start.clicked()
}else{
btn_end.clicked()
}
d.flag = false
timer.restart()
}
}
Timer{
id:timer
interval: 250
onTriggered: {
d.flag = true
}
}
SwipeView {
id:swipe
clip: true
interactive: false
orientation:control.vertical ? Qt.Vertical : Qt.Horizontal
anchors.fill: parent
}
Button{
id:btn_start
height: vertical ? 20 : 40
width: vertical ? 40 : 20
anchors{
left: vertical ? undefined : parent.left
leftMargin: vertical ? undefined : 2
verticalCenter: vertical ? undefined : parent.verticalCenter
horizontalCenter: !vertical ? undefined : parent.horizontalCenter
top: !vertical ? undefined :parent.top
topMargin: !vertical ? undefined :2
}
background: Rectangle{
radius: 4
color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,0.97) : Qt.rgba(237/255,237/255,237/255,0.97)
}
contentItem:FluIcon{
iconSource: vertical ? FluentIcons.CaretUpSolid8 : FluentIcons.CaretLeftSolid8
width: 10
height: 10
iconSize: 10
iconColor: btn_start.hovered ? FluColors.Grey220 : FluColors.Grey120
anchors.centerIn: parent
}
visible: swipe.currentIndex !==0
onClicked: {
swipe.currentIndex = Math.max(swipe.currentIndex - 1, 0)
}
}
Button{
id:btn_end
height: vertical ? 20 : 40
width: vertical ? 40 : 20
anchors{
right: vertical ? undefined : parent.right
rightMargin: vertical ? undefined : 2
verticalCenter: vertical ? undefined : parent.verticalCenter
horizontalCenter: !vertical ? undefined : parent.horizontalCenter
bottom: !vertical ? undefined :parent.bottom
bottomMargin: !vertical ? undefined :2
}
background: Rectangle{
radius: 4
color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,0.97) : Qt.rgba(237/255,237/255,237/255,0.97)
}
visible: swipe.currentIndex !== swipe.count - 1
contentItem:FluIcon{
iconSource: vertical ? FluentIcons.CaretDownSolid8 : FluentIcons.CaretRightSolid8
width: 10
height: 10
iconSize: 10
iconColor: btn_end.hovered ? FluColors.Grey220 : FluColors.Grey120
anchors.centerIn: parent
}
onClicked: {
swipe.currentIndex = Math.min(swipe.currentIndex + 1,swipe.count-1)
}
}
}

View File

@ -1,19 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
Item {
property int radius: 4
id:control
anchors.fill: parent
Rectangle{
width: control.width
height: control.height
anchors.centerIn: parent
color: "#00000000"
border.width: 2
radius: control.radius
border.color: FluTheme.dark ? Qt.rgba(1,1,1,1) : Qt.rgba(0,0,0,1)
z: 65535
}
}

View File

@ -1,19 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
Text {
property int iconSource
property int iconSize: 20
property color iconColor: FluTheme.dark ? "#FFFFFF" : "#000000"
id:control
font.family: "Segoe Fluent Icons"
font.pixelSize: iconSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: iconColor
text: (String.fromCharCode(iconSource).toString(16))
FontLoader{
source: "../Font/Segoe_Fluent_Icons.ttf"
}
}

View File

@ -1,130 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Controls.Basic
import FluentUI
Button {
display: Button.IconOnly
property int iconSize: 20
property int iconSource
property bool disabled: false
property int radius:4
property string contentDescription: ""
property color hoverColor: FluTheme.itemHoverColor
property color pressedColor: FluTheme.itemPressColor
property color normalColor: FluTheme.itemNormalColor
property color disableColor: FluTheme.itemNormalColor
property Component iconDelegate: com_icon
property color color: {
if(!enabled){
return disableColor
}
if(pressed){
return pressedColor
}
return hovered ? hoverColor : normalColor
}
property color iconColor: {
if(FluTheme.dark){
if(!enabled){
return Qt.rgba(130/255,130/255,130/255,1)
}
return Qt.rgba(1,1,1,1)
}else{
if(!enabled){
return Qt.rgba(161/255,161/255,161/255,1)
}
return Qt.rgba(0,0,0,1)
}
}
property color textColor: FluTheme.fontPrimaryColor
Accessible.role: Accessible.Button
Accessible.name: control.text
Accessible.description: contentDescription
Accessible.onPressAction: control.clicked()
id:control
focusPolicy:Qt.TabFocus
padding: 0
verticalPadding: 8
horizontalPadding: 8
enabled: !disabled
font:FluTextStyle.Caption
background: Rectangle{
implicitWidth: 30
implicitHeight: 30
radius: control.radius
color:control.color
FluFocusRectangle{
visible: control.activeFocus
}
}
Component{
id:com_icon
FluIcon {
id:text_icon
font.pixelSize: iconSize
iconSize: control.iconSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
iconColor: control.iconColor
iconSource: control.iconSource
}
}
Component{
id:com_row
RowLayout{
FluLoader{
sourceComponent: iconDelegate
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
visible: display !== Button.TextOnly
}
FluText{
text:control.text
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
visible: display !== Button.IconOnly
color: control.textColor
font: control.font
}
}
}
Component{
id:com_column
ColumnLayout{
FluLoader{
sourceComponent: iconDelegate
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
visible: display !== Button.TextOnly
}
FluText{
text:control.text
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
visible: display !== Button.IconOnly
color: control.textColor
font: control.font
}
}
}
contentItem:FluLoader{
sourceComponent: {
if(display === Button.TextUnderIcon){
return com_column
}
return com_row
}
}
FluTooltip{
id:tool_tip
visible: {
if(control.text === ""){
return false
}
if(control.display !== Button.IconOnly){
return false
}
return hovered
}
text:control.text
delay: 1000
}
}

View File

@ -1,48 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
Image {
property string errorButtonText: qsTr("Reload")
property var clickErrorListener : function(){
image.source = ""
image.source = control.source
}
property Component errorItem : com_error
property Component loadingItem: com_loading
id: control
FluLoader{
anchors.fill: parent
sourceComponent: {
if(control.status === Image.Loading){
return com_loading
}else if(control.status == Image.Error){
return com_error
}else{
return undefined
}
}
}
Component{
id:com_loading
Rectangle{
color: FluTheme.itemHoverColor
FluProgressRing{
anchors.centerIn: parent
visible: control.status === Image.Loading
}
}
}
Component{
id:com_error
Rectangle{
color: FluTheme.itemHoverColor
FluFilledButton{
text: control.errorButtonText
anchors.centerIn: parent
visible: control.status === Image.Error
onClicked: clickErrorListener()
}
}
}
}

View File

@ -1,18 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
Button{
id:control
property string normalImage: ""
property string hoveredImage: ""
property string pushedImage: ""
background: Item{
implicitHeight: 12
implicitWidth: 12
BorderImage {
anchors.fill: parent
source: control.hovered ? (control.pressed ? control.pushedImage : control.hoveredImage ) : control.normalImage
}
}
}

View File

@ -1,252 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
FluObject {
property var root;
property int layoutY: 75
id:control
FluObject{
id:mcontrol
property string const_success: "success";
property string const_info: "info";
property string const_warning: "warning";
property string const_error: "error";
property int maxWidth: 300;
property var screenLayout: null;
function create(type,text,duration,moremsg){
if(screenLayout){
var last = screenLayout.getLastloader();
if(last.type === type && last.text === text && moremsg === last.moremsg){
last.restart();
return;
}
}
initScreenLayout();
contentComponent.createObject(screenLayout,{
type:type,
text:text,
duration:duration,
moremsg:moremsg,
});
}
function createCustom(itemcomponent,duration){
initScreenLayout();
if(itemcomponent){
contentComponent.createObject(screenLayout,{itemcomponent:itemcomponent,duration:duration});
}
}
function initScreenLayout(){
if(screenLayout == null){
screenLayout = screenlayoutComponent.createObject(root);
screenLayout.y = control.layoutY;
screenLayout.z = 100000;
}
}
Component{
id:screenlayoutComponent
Column{
parent: Overlay.overlay
z:999
spacing: 20
width: root.width
move: Transition {
NumberAnimation {
properties: "y"
easing.type: Easing.OutCubic
duration: FluTheme.enableAnimation ? 333 : 0
}
}
onChildrenChanged: if(children.length === 0) destroy();
function getLastloader(){
if(children.length > 0){
return children[children.length - 1];
}
return null;
}
}
}
Component{
id:contentComponent
Item{
id:content;
property int duration: 1500
property var itemcomponent
property string type
property string text
property string moremsg
width: parent.width;
height: loader.height;
function close(){
content.destroy();
}
function restart(){
delayTimer.restart();
}
Timer {
id:delayTimer
interval: duration; running: duration > 0; repeat: duration > 0
onTriggered: content.close();
}
FluLoader{
id:loader;
x:(parent.width - width) / 2;
property var _super: content;
scale: item ? 1 : 0;
asynchronous: true
Behavior on scale {
enabled: FluTheme.enableAnimation
NumberAnimation {
easing.type: Easing.OutCubic
duration: 167
}
}
sourceComponent:itemcomponent ? itemcomponent : mcontrol.fluent_sytle;
}
}
}
property Component fluent_sytle: Rectangle{
width: rowlayout.width + (btn_close.visible ? 30 : 48);
height: rowlayout.height + 20;
color: {
if(FluTheme.dark){
switch(_super.type){
case mcontrol.const_success: return Qt.rgba(57/255,61/255,27/255,1);
case mcontrol.const_warning: return Qt.rgba(67/255,53/255,25/255,1);
case mcontrol.const_info: return Qt.rgba(39/255,39/255,39/255,1);
case mcontrol.const_error: return Qt.rgba(68/255,39/255,38/255,1);
}
return Qt.rgba(255,255,255,1)
}else{
switch(_super.type){
case mcontrol.const_success: return "#dff6dd";
case mcontrol.const_warning: return "#fff4ce";
case mcontrol.const_info: return "#f4f4f4";
case mcontrol.const_error: return "#fde7e9";
}
return "#FFFFFF"
}
}
FluShadow{
radius: 4
}
radius: 4
border.width: 1
border.color: {
if(FluTheme.dark){
switch(_super.type){
case mcontrol.const_success: return Qt.rgba(56/255,61/255,27/255,1);
case mcontrol.const_warning: return Qt.rgba(66/255,53/255,25/255,1);
case mcontrol.const_info: return Qt.rgba(38/255,39/255,39/255,1);
case mcontrol.const_error: return Qt.rgba(67/255,39/255,38/255,1);
}
return "#FFFFFF"
}else{
switch(_super.type){
case mcontrol.const_success: return "#d2e8d0";
case mcontrol.const_warning: return "#f0e6c2";
case mcontrol.const_info: return "#e6e6e6";
case mcontrol.const_error: return "#eed9db";
}
return "#FFFFFF"
}
}
Row{
id:rowlayout
x:20;
y:(parent.height - height) / 2;
spacing: 10
FluIcon{
iconSource:{
switch(_super.type){
case mcontrol.const_success: return FluentIcons.CompletedSolid;
case mcontrol.const_warning: return FluentIcons.InfoSolid;
case mcontrol.const_info: return FluentIcons.InfoSolid;
case mcontrol.const_error: return FluentIcons.StatusErrorFull;
}FluentIcons.StatusErrorFull
return FluentIcons.FA_info_circle
}
iconSize:20
iconColor: {
if(FluTheme.dark){
switch(_super.type){
case mcontrol.const_success: return Qt.rgba(108/255,203/255,95/255,1);
case mcontrol.const_warning: return Qt.rgba(252/255,225/255,0/255,1);
case mcontrol.const_info: return FluTheme.primaryColor;
case mcontrol.const_error: return Qt.rgba(255/255,153/255,164/255,1);
}
return "#FFFFFF"
}else{
switch(_super.type){
case mcontrol.const_success: return "#0f7b0f";
case mcontrol.const_warning: return "#9d5d00";
case mcontrol.const_info: return "#0066b4";
case mcontrol.const_error: return "#c42b1c";
}
return "#FFFFFF"
}
}
}
Column{
spacing: 5
FluText{
text:_super.text
wrapMode: Text.WrapAnywhere
width: Math.min(implicitWidth,mcontrol.maxWidth)
}
FluText{
text: _super.moremsg
visible: _super.moremsg
wrapMode : Text.WrapAnywhere
textColor: FluColors.Grey120
width: Math.min(implicitWidth,mcontrol.maxWidth)
}
}
FluIconButton{
id:btn_close
iconSource: FluentIcons.ChromeClose
iconSize: 10
y:5
visible: _super.duration<=0
iconColor: {
if(FluTheme.dark){
switch(_super.type){
case mcontrol.const_success: return Qt.rgba(108/255,203/255,95/255,1);
case mcontrol.const_warning: return Qt.rgba(252/255,225/255,0/255,1);
case mcontrol.const_info: return FluTheme.primaryColor;
case mcontrol.const_error: return Qt.rgba(255/255,153/255,164/255,1);
}
return "#FFFFFF"
}else{
switch(_super.type){
case mcontrol.const_success: return "#0f7b0f";
case mcontrol.const_warning: return "#9d5d00";
case mcontrol.const_info: return "#0066b4";
case mcontrol.const_error: return "#c42b1c";
}
return "#FFFFFF"
}
}
onClicked: _super.close()
}
}
}
}
function showSuccess(text,duration=1000,moremsg){
mcontrol.create(mcontrol.const_success,text,duration,moremsg ? moremsg : "");
}
function showInfo(text,duration=1000,moremsg){
mcontrol.create(mcontrol.const_info,text,duration,moremsg ? moremsg : "");
}
function showWarning(text,duration=1000,moremsg){
mcontrol.create(mcontrol.const_warning,text,duration,moremsg ? moremsg : "");
}
function showError(text,duration=1000,moremsg){
mcontrol.create(mcontrol.const_error,text,duration,moremsg ? moremsg : "");
}
function showCustom(itemcomponent,duration=1000){
mcontrol.createCustom(itemcomponent,duration);
}
}

View File

@ -1,39 +0,0 @@
import QtQuick
import QtQuick.Controls.Basic
import QtQuick.Templates as T
import FluentUI
T.ItemDelegate {
id: control
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding,
implicitIndicatorHeight + topPadding + bottomPadding)
padding: 0
verticalPadding: 8
horizontalPadding: 10
icon.color: control.palette.text
contentItem:FluText {
text: control.text
font: control.font
color:{
if(control.down){
return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120
}
return FluTheme.dark ? FluColors.White : FluColors.Grey220
}
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 30
color:{
if(FluTheme.dark){
return Qt.rgba(1,1,1,0.05)
}else{
return Qt.rgba(0,0,0,0.05)
}
}
visible: control.down || control.highlighted || control.visualFocus
}
}

View File

@ -1,5 +0,0 @@
import QtQuick
Loader {
Component.onDestruction: sourceComponent = undefined
}

View File

@ -1,41 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import FluentUI
FluButton {
property bool loading: false
id: control
disabled: loading
contentItem: Row{
spacing: 6
FluText {
text: control.text
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font: control.font
color: control.textColor
anchors.verticalCenter: parent.verticalCenter
}
Item{
width: control.loading ? 16 : 0
height: 16
anchors.verticalCenter: parent.verticalCenter
visible: Number(width)!==0
clip: true
Behavior on width {
enabled: FluTheme.enableAnimation
NumberAnimation{
duration: 167
easing.type: Easing.OutCubic
}
}
FluProgressRing{
width: 16
height: 16
strokeWidth:3
anchors.centerIn: parent
}
}
}
}

View File

@ -1,59 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.impl
import QtQuick.Templates as T
import FluentUI
T.Menu {
property bool enableAnimation: true
id: control
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
contentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
contentHeight + topPadding + bottomPadding)
margins: 0
overlap: 1
spacing: 0
delegate: FluMenuItem { }
enter: Transition {
NumberAnimation {
property: "opacity"
from:0
to:1
duration: FluTheme.enableAnimation && control.enableAnimation ? 83 : 0
}
}
exit:Transition {
NumberAnimation {
property: "opacity"
from:1
to:0
duration: FluTheme.enableAnimation && control.enableAnimation ? 83 : 0
}
}
contentItem: ListView {
implicitHeight: contentHeight
model: control.contentModel
interactive: Window.window
? contentHeight + control.topPadding + control.bottomPadding > Window.window.height
: false
clip: true
currentIndex: control.currentIndex
ScrollIndicator.vertical: ScrollIndicator {}
}
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)
border.width: 1
radius: 5
FluShadow{}
}
T.Overlay.modal: Rectangle {
color: Color.transparent(control.palette.shadow, 0.5)
}
T.Overlay.modeless: Rectangle {
color: Color.transparent(control.palette.shadow, 0.12)
}
}

View File

@ -1,21 +0,0 @@
import QtQuick
import QtQuick.Templates as T
import QtQuick.Controls.impl
T.MenuBar {
id: control
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
contentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
contentHeight + topPadding + bottomPadding)
delegate: FluMenuBarItem { }
contentItem: Row {
spacing: control.spacing
Repeater {
model: control.contentModel
}
}
background: Item {
implicitHeight: 30
}
}

View File

@ -1,61 +0,0 @@
import QtQuick
import QtQuick.Templates as T
import QtQuick.Controls.impl
import FluentUI
T.MenuBarItem {
property bool disabled: false
property color textColor: {
if(FluTheme.dark){
if(disabled){
return Qt.rgba(131/255,131/255,131/255,1)
}
if(pressed){
return Qt.rgba(162/255,162/255,162/255,1)
}
return Qt.rgba(1,1,1,1)
}else{
if(disabled){
return Qt.rgba(160/255,160/255,160/255,1)
}
if(pressed){
return Qt.rgba(96/255,96/255,96/255,1)
}
return Qt.rgba(0,0,0,1)
}
}
id: control
enabled: !disabled
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding,
implicitIndicatorHeight + topPadding + bottomPadding)
spacing: 6
padding: 6
leftPadding: 12
rightPadding: 16
icon.width: 24
icon.height: 24
icon.color: control.palette.buttonText
contentItem: FluText {
verticalAlignment: Text.AlignVCenter
text: control.text
color:control.textColor
}
background: Rectangle {
implicitWidth: 30
implicitHeight: 30
radius: 3
color: {
if(control.highlighted){
return FluTheme.itemCheckColor
}
if(control.hovered){
return FluTheme.itemHoverColor
}
return FluTheme.itemNormalColor
}
}
}

View File

@ -1,111 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Controls.impl
import QtQuick.Templates as T
import FluentUI
T.MenuItem {
property Component iconDelegate : com_icon
property int iconSpacing: 5
property int iconSource
property int iconSize: 16
property color textColor: {
if(FluTheme.dark){
if(!enabled){
return Qt.rgba(131/255,131/255,131/255,1)
}
if(pressed){
return Qt.rgba(162/255,162/255,162/255,1)
}
return Qt.rgba(1,1,1,1)
}else{
if(!enabled){
return Qt.rgba(160/255,160/255,160/255,1)
}
if(pressed){
return Qt.rgba(96/255,96/255,96/255,1)
}
return Qt.rgba(0,0,0,1)
}
}
id: control
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding,
implicitIndicatorHeight + topPadding + bottomPadding)
padding: 6
spacing: 6
icon.width: 24
icon.height: 24
icon.color: control.palette.windowText
height: visible ? implicitHeight : 0
font:FluTextStyle.Body
Component{
id:com_icon
FluIcon{
id:content_icon
iconSize: control.iconSize
iconSource:control.iconSource
}
}
contentItem: Item{
Row{
spacing: control.iconSpacing
readonly property real arrowPadding: control.subMenu && control.arrow ? control.arrow.width + control.spacing : 0
readonly property real indicatorPadding: control.checkable && control.indicator ? control.indicator.width + control.spacing : 0
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: (!control.mirrored ? indicatorPadding : arrowPadding)+5
right: parent.right
rightMargin: (control.mirrored ? indicatorPadding : arrowPadding)+5
}
FluLoader{
id:loader_icon
sourceComponent: iconDelegate
anchors.verticalCenter: parent.verticalCenter
visible: status === Loader.Ready
}
FluText {
id:content_text
text: control.text
font: control.font
color: control.textColor
anchors.verticalCenter: parent.verticalCenter
}
}
}
indicator: FluIcon {
x: control.mirrored ? control.width - width - control.rightPadding : control.leftPadding
y: control.topPadding + (control.availableHeight - height) / 2
visible: control.checked
iconSource: FluentIcons.CheckMark
}
arrow: FluIcon {
x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding
y: control.topPadding + (control.availableHeight - height) / 2
visible: control.subMenu
iconSource: FluentIcons.ChevronRightMed
}
background: Item {
implicitWidth: 150
implicitHeight: 36
x: 1
y: 1
width: control.width - 2
height: control.height - 2
Rectangle{
anchors.fill: parent
anchors.margins: 3
radius: 4
color:{
if(control.highlighted){
return FluTheme.itemCheckColor
}
return FluTheme.itemNormalColor
}
}
}
}

View File

@ -1,19 +0,0 @@
import QtQuick
import QtQuick.Controls.impl
import QtQuick.Templates as T
import FluentUI
T.MenuSeparator {
id: control
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding)
padding: 0
verticalPadding: 0
contentItem: Rectangle {
implicitWidth: 188
implicitHeight: 1
color: FluTheme.dark ? Qt.rgba(60/255,60/255,60/255,1) : Qt.rgba(210/255,210/255,210/255,1)
}
}

View File

@ -1,82 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import FluentUI
TextArea{
signal commit(string text)
property bool disabled: false
property color normalColor: FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1)
property color disableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1)
property color placeholderNormalColor: FluTheme.dark ? Qt.rgba(210/255,210/255,210/255,1) : Qt.rgba(96/255,96/255,96/255,1)
property color placeholderFocusColor: FluTheme.dark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1)
property color placeholderDisableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1)
property bool isCtrlEnterForNewline: false
id:control
enabled: !disabled
color: {
if(!enabled){
return disableColor
}
return normalColor
}
font:FluTextStyle.Body
wrapMode: Text.WrapAnywhere
padding: 8
leftPadding: padding+4
renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering
selectedTextColor: color
selectionColor: FluTools.colorAlpha(FluTheme.primaryColor,0.5)
placeholderTextColor: {
if(!enabled){
return placeholderDisableColor
}
if(focus){
return placeholderFocusColor
}
return placeholderNormalColor
}
selectByMouse: true
width: 240
background: FluTextBoxBackground{
inputItem: control
}
Keys.onEnterPressed: (event)=> d.handleCommit(event)
Keys.onReturnPressed:(event)=> d.handleCommit(event)
QtObject{
id:d
function handleCommit(event){
if(isCtrlEnterForNewline){
if(event.modifiers & Qt.ControlModifier){
insert(control.cursorPosition, "\n")
return
}
control.commit(control.text)
}else{
if(event.modifiers & Qt.ControlModifier){
control.commit(control.text)
return
}
insert(control.cursorPosition, "\n")
}
}
}
MouseArea{
anchors.fill: parent
cursorShape: Qt.IBeamCursor
acceptedButtons: Qt.RightButton
onClicked: {
if(control.echoMode === TextInput.Password){
return
}
if(control.readOnly && control.text === ""){
return
}
menu.popup()
}
}
FluTextBoxMenu{
id:menu
inputItem: control
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
QtObject {
default property list<QtObject> children
id:control
}

View File

@ -1,43 +0,0 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Window
import FluentUI
Item {
property int launchMode: FluPageType.SingleTop
property bool animDisabled: false
property string url : ""
signal animationEnd()
id: control
opacity: visible
visible: false
StackView.onRemoved: destroy()
Behavior on opacity{
enabled: !animDisabled && FluTheme.enableAnimation
NumberAnimation{
duration: 167
}
}
transform: Translate {
y: control.visible ? 0 : 80
Behavior on y{
enabled: !animDisabled && FluTheme.enableAnimation
NumberAnimation{
duration: 167
easing.type: Easing.OutCubic
}
}
}
Component.onCompleted: {
visible = true
timer.restart()
}
Timer{
id:timer
interval: !animDisabled && FluTheme.enableAnimation ? 200 : 0
onTriggered: {
control.animationEnd()
}
}
}

View File

@ -1,100 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
Item {
signal requestPage(int page,int count)
property string previousText: qsTr("<Previous")
property string nextText: qsTr("Next>")
property int pageCurrent: 0
property int itemCount: 0
property int pageButtonCount: 5
property int pageCount: itemCount>0?Math.ceil(itemCount/__itemPerPage):0
property int __itemPerPage: 10
property int __pageButtonHalf: Math.floor(pageButtonCount/2)+1
id: control
implicitHeight: 40
implicitWidth: content.width
Row{
id: content
height: control.height
spacing: 10
padding: 10
FluToggleButton{
visible: control.pageCount>1
disabled: control.pageCurrent<=1
text:control.previousText
clickListener:function() {
control.calcNewPage(control.pageCurrent-1);
}
}
Row{
spacing: 5
FluToggleButton{
property int pageNumber:1
visible: control.pageCount>0
checked: pageNumber === control.pageCurrent
text:String(pageNumber)
clickListener:function() {
control.calcNewPage(pageNumber);
}
}
FluText{
visible: (control.pageCount>control.pageButtonCount&&
control.pageCurrent>control.__pageButtonHalf)
text: "..."
}
Repeater{
id: button_repeator
model: (control.pageCount<2)?0:(control.pageCount>=control.pageButtonCount)?(control.pageButtonCount-2):(control.pageCount-2)
delegate:FluToggleButton{
property int pageNumber: {
return (control.pageCurrent<=control.__pageButtonHalf)
?(2+index)
:(control.pageCount-control.pageCurrent<=control.pageButtonCount-control.__pageButtonHalf)
?(control.pageCount-button_repeator.count+index)
:(control.pageCurrent+2+index-control.__pageButtonHalf)
}
text:String(pageNumber)
checked: pageNumber === control.pageCurrent
clickListener:function(){
control.calcNewPage(pageNumber);
}
}
}
FluText{
visible: (control.pageCount>control.pageButtonCount&&
control.pageCount-control.pageCurrent>control.pageButtonCount-control.__pageButtonHalf)
text: "..."
}
FluToggleButton{
property int pageNumber:control.pageCount
visible: control.pageCount>1
checked: pageNumber === control.pageCurrent
text:String(pageNumber)
clickListener:function(){
control.calcNewPage(pageNumber);
}
}
}
FluToggleButton{
visible: control.pageCount>1
disabled: control.pageCurrent>=control.pageCount
text:control.nextText
clickListener:function() {
control.calcNewPage(control.pageCurrent+1);
}
}
}
function calcNewPage(page)
{
if(!page)
return
let page_num=Number(page)
if(page_num<1||page_num>control.pageCount||page_num===control.pageCurrent)
return
control.pageCurrent=page_num
control.requestPage(page_num,control.__itemPerPage)
}
}

View File

@ -1,25 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
QtObject {
readonly property string key : FluTools.uuid()
property int _idx
property var _ext
property var _parent
property bool visible: true
property string title
property var url
property bool disabled: false
property int icon
property bool iconVisible: true
property Component infoBadge
property int count: 0
property var onTapListener
property Component iconDelegate
property Component menuDelegate
property Component editDelegate
property var extra
property bool showEdit
signal tap
}

View File

@ -1,11 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
QtObject {
readonly property string key : FluTools.uuid()
property int _idx
property var _ext
property var _parent
property bool visible: true
}

View File

@ -1,18 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
FluObject {
readonly property string key : FluTools.uuid()
property int _idx
property bool visible: true
property string title
property var icon
property bool disabled: false
property bool iconVisible: true
property bool isExpand: false
property bool showEdit
property Component iconDelegate
property Component menuDelegate
property Component editDelegate
}

View File

@ -1,11 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
QtObject {
readonly property string key : FluTools.uuid()
property int _idx
property bool visible: true
property string title
property var parent
}

View File

@ -1,12 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
QtObject {
readonly property string key : FluTools.uuid()
property int _idx
property bool visible: true
property var parent
property real spacing
property int size:1
}

View File

@ -1,73 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import FluentUI
TextField{
signal commit(string text)
property bool disabled: false
property int iconSource: 0
property color normalColor: FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1)
property color disableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1)
property color placeholderNormalColor: FluTheme.dark ? Qt.rgba(210/255,210/255,210/255,1) : Qt.rgba(96/255,96/255,96/255,1)
property color placeholderFocusColor: FluTheme.dark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1)
property color placeholderDisableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1)
id:control
enabled: !disabled
color: {
if(!enabled){
return disableColor
}
return normalColor
}
font:FluTextStyle.Body
padding: 7
rightPadding: 40
leftPadding: padding+4
echoMode:btn_reveal.pressed ? TextField.Normal : TextField.Password
renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering
selectionColor: FluTools.colorAlpha(FluTheme.primaryColor,0.5)
selectedTextColor: color
placeholderTextColor: {
if(!enabled){
return placeholderDisableColor
}
if(focus){
return placeholderFocusColor
}
return placeholderNormalColor
}
selectByMouse: true
width: 240
background: FluTextBoxBackground{
inputItem: control
}
Keys.onEnterPressed: (event)=> d.handleCommit(event)
Keys.onReturnPressed:(event)=> d.handleCommit(event)
QtObject{
id:d
function handleCommit(event){
control.commit(control.text)
}
}
FluIconButton{
id:btn_reveal
iconSource:FluentIcons.RevealPasswordMedium
iconSize: 10
width: 30
height: 20
verticalPadding: 0
horizontalPadding: 0
iconColor: FluTheme.dark ? Qt.rgba(222/255,222/255,222/255,1) : Qt.rgba(97/255,97/255,97/255,1)
visible: control.text !== ""
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 5
}
}
FluTextBoxMenu{
id:menu
inputItem: control
}
}

View File

@ -1,95 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
Page {
default property alias content: d.children
property alias currentIndex: nav_list.currentIndex
property color textNormalColor: FluTheme.dark ? FluColors.Grey120 : FluColors.Grey120
property color textHoverColor: FluTheme.dark ? FluColors.Grey10 : FluColors.Black
property int textSize: 28
property bool textBold: true
property int textSpacing: 10
property int headerSpacing: 20
property int headerHeight: 40
id:control
width: 400
height: 300
implicitHeight: height
implicitWidth: width
FluObject{
id:d
property int tabY: control.headerHeight/2+control.textSize/2 + 3
}
background:Item{}
header:ListView{
id:nav_list
implicitHeight: control.headerHeight
implicitWidth: control.width
model:d.children
spacing: control.headerSpacing
interactive: false
orientation: ListView.Horizontal
highlightMoveDuration: FluTheme.enableAnimation ? 167 : 0
highlight: Item{
clip: true
Rectangle{
height: 3
radius: 1.5
color: FluTheme.primaryColor
width: nav_list.currentItem ? nav_list.currentItem.width : 0
y:d.tabY
Behavior on width {
enabled: FluTheme.enableAnimation
NumberAnimation{
duration: 167
easing.type: Easing.OutCubic
}
}
}
}
delegate: Button{
id:item_button
width: item_title.width
height: nav_list.height
focusPolicy:Qt.TabFocus
background:Item{
FluFocusRectangle{
anchors.margins: -4
visible: item_button.activeFocus
radius:4
}
}
contentItem: Item{
FluText {
id:item_title
text: modelData.title
anchors.centerIn: parent
font.pixelSize: control.textSize
font.bold: control.textBold
color: {
if(item_button.hovered || nav_list.currentIndex === index)
return textHoverColor
return textNormalColor
}
}
}
onClicked: {
nav_list.currentIndex = index
}
}
}
Item{
id:container
anchors.fill: parent
Repeater{
model:d.children
FluLoader{
property var argument: modelData.argument
anchors.fill: parent
sourceComponent: modelData.contentItem
visible: nav_list.currentIndex === index
}
}
}
}

View File

@ -1,9 +0,0 @@
import QtQuick
import QtQuick.Controls
import FluentUI
QtObject {
property string title
property Component contentItem
property var argument
}

View File

@ -1,54 +0,0 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Window
import FluentUI
Popup {
id: control
padding: 0
modal:true
parent: Overlay.overlay
x: Math.round((d.parentWidth - width) / 2)
y: Math.round((d.parentHeight - height) / 2)
closePolicy: Popup.CloseOnEscape
enter: Transition {
NumberAnimation {
property: "opacity"
duration: FluTheme.enableAnimation ? 83 : 0
from:0
to:1
}
}
height:Math.min(implicitHeight,d.parentHeight)
exit:Transition {
NumberAnimation {
property: "opacity"
duration: FluTheme.enableAnimation ? 83 : 0
from:1
to:0
}
}
background: FluRectangle{
radius: [5,5,5,5]
color: FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(1,1,1,1)
FluShadow{
radius: 5
}
}
QtObject{
id:d
property int parentHeight: {
if(control.parent){
return control.parent.height
}
return control.height
}
property int parentWidth: {
if(control.parent){
return control.parent.width
}
return control.width
}
}
}

View File

@ -1,69 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import FluentUI
ProgressBar{
property int duration: 888
property real strokeWidth: 6
property bool progressVisible: false
property color color: FluTheme.primaryColor
property color backgroundColor : FluTheme.dark ? Qt.rgba(99/255,99/255,99/255,1) : Qt.rgba(214/255,214/255,214/255,1)
id:control
indeterminate : true
QtObject{
id:d
property real _radius: strokeWidth/2
}
onIndeterminateChanged:{
if(!indeterminate){
animator_x.duration = 0
rect_progress.x = 0
animator_x.duration = control.duration
}
}
background: Rectangle {
implicitWidth: 150
implicitHeight: control.strokeWidth
color: control.backgroundColor
radius: d._radius
}
contentItem: FluClip {
clip: true
radius: [d._radius,d._radius,d._radius,d._radius]
Rectangle {
id:rect_progress
width: {
if(control.indeterminate){
return 0.5 * parent.width
}
return control.visualPosition * parent.width
}
height: parent.height
radius: d._radius
color: control.color
PropertyAnimation on x {
id:animator_x
running: control.indeterminate && control.visible
from: -rect_progress.width
to:control.width+rect_progress.width
loops: Animation.Infinite
duration: control.duration
}
}
}
FluText{
text:(control.visualPosition * 100).toFixed(0) + "%"
visible: {
if(control.indeterminate){
return false
}
return control.progressVisible
}
anchors{
left: parent.left
leftMargin: control.width+5
verticalCenter: parent.verticalCenter
}
}
}

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