This commit is contained in:
zhuzichu 2023-09-11 18:10:50 +08:00
parent 0297445218
commit 05040ec4a9
18 changed files with 2055 additions and 27 deletions

View File

@ -139,7 +139,8 @@ FluExpander{
"FluChart", "FluChart",
"FluRangeSlider", "FluRangeSlider",
"FluStaggeredView", "FluStaggeredView",
"FluProgressButton" "FluProgressButton",
"FluLoadingButton"
]; ];
code = code.replace(/\n/g, "<br>"); code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;"); code = code.replace(/ /g, "&nbsp;");

View File

@ -213,6 +213,45 @@ FluScrollablePage{
}' }'
} }
FluArea{
Layout.fillWidth: true
height: 68
Layout.topMargin: 20
paddings: 10
FluLoadingButton{
id:btn_loading
loading:loading_button_switch.checked
text:"Loading Button"
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
onClicked: {
}
}
FluToggleSwitch{
id:loading_button_switch
checked: true
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
}
text:"Loading"
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluLoadingButton{
text:"Loading Button"
onClicked: {
}
}'
}
FluArea{ FluArea{
Layout.fillWidth: true Layout.fillWidth: true

View File

@ -10,6 +10,49 @@ FluScrollablePage{
title:"Settings" title:"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
height: 60
paddings: 10
Row{
spacing: 20
anchors.verticalCenter: parent.verticalCenter
FluText{
text:"当前版本 v%1".arg(appInfo.version)
font: FluTextStyle.Body
anchors.verticalCenter: parent.verticalCenter
}
FluLoadingButton{
id:btn_checkupdate
text:"检查更新"
anchors.verticalCenter: parent.verticalCenter
onClicked: {
loading = true
FluEventBus.post("checkUpdate")
}
}
}
}
FluArea{ FluArea{
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20

View File

@ -25,10 +25,23 @@ CustomWindow {
event.accepted = false event.accepted = false
} }
FluEvent{
id:event_checkupdate
name: "checkUpdate"
onTriggered: {
checkUpdate(false)
}
}
Component.onCompleted: { Component.onCompleted: {
FluTools.setQuitOnLastWindowClosed(false) FluTools.setQuitOnLastWindowClosed(false)
tour.open() tour.open()
checkUpdate() checkUpdate(true)
FluEventBus.registerEvent(event_checkupdate)
}
Component.onDestruction: {
FluEventBus.unRegisterEvent(event_checkupdate)
} }
SystemTrayIcon { SystemTrayIcon {
@ -311,11 +324,13 @@ CustomWindow {
HttpCallable{ HttpCallable{
id:callable id:callable
property bool silent: true
onStart: { onStart: {
console.debug("satrt check update...") console.debug("satrt check update...")
} }
onFinish: { onFinish: {
console.debug("check update finish") console.debug("check update finish")
FluEventBus.post("checkUpdateFinish");
} }
onSuccess: onSuccess:
(result)=>{ (result)=>{
@ -326,15 +341,23 @@ CustomWindow {
dialog_update.newVerson = data.tag_name dialog_update.newVerson = data.tag_name
dialog_update.body = data.body dialog_update.body = data.body
dialog_update.open() dialog_update.open()
}else{
if(!silent){
showInfo("当前版本已经是最新版")
}
} }
} }
onError: onError:
(status,errorString)=>{ (status,errorString)=>{
if(!silent){
showError("网络异常!")
}
console.debug(status+";"+errorString) console.debug(status+";"+errorString)
} }
} }
function checkUpdate(){ function checkUpdate(silent){
callable.silent = silent
var request = http.newRequest("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest") var request = http.newRequest("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
http.get(request,callable); http.get(request,callable);
} }

View File

@ -139,7 +139,8 @@ FluExpander{
"FluChart", "FluChart",
"FluRangeSlider", "FluRangeSlider",
"FluStaggeredView", "FluStaggeredView",
"FluProgressButton" "FluProgressButton",
"FluLoadingButton"
]; ];
code = code.replace(/\n/g, "<br>"); code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;"); code = code.replace(/ /g, "&nbsp;");

View File

@ -213,6 +213,45 @@ FluScrollablePage{
}' }'
} }
FluArea{
Layout.fillWidth: true
height: 68
Layout.topMargin: 20
paddings: 10
FluLoadingButton{
id:btn_loading
loading:loading_button_switch.checked
text:"Loading Button"
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
onClicked: {
}
}
FluToggleSwitch{
id:loading_button_switch
checked: true
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
}
text:"Loading"
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluLoadingButton{
text:"Loading Button"
onClicked: {
}
}'
}
FluArea{ FluArea{
Layout.fillWidth: true Layout.fillWidth: true

View File

@ -11,6 +11,49 @@ FluScrollablePage{
title:"Settings" title:"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
height: 60
paddings: 10
Row{
spacing: 20
anchors.verticalCenter: parent.verticalCenter
FluText{
text:"当前版本 v%1".arg(appInfo.version)
font: FluTextStyle.Body
anchors.verticalCenter: parent.verticalCenter
}
FluLoadingButton{
id:btn_checkupdate
text:"检查更新"
anchors.verticalCenter: parent.verticalCenter
onClicked: {
loading = true
FluEventBus.post("checkUpdate")
}
}
}
}
FluArea{ FluArea{
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20
@ -107,3 +150,4 @@ FluScrollablePage{
} }
} }

View File

@ -26,10 +26,23 @@ CustomWindow {
event.accepted = false event.accepted = false
} }
FluEvent{
id:event_checkupdate
name: "checkUpdate"
onTriggered: {
checkUpdate(false)
}
}
Component.onCompleted: { Component.onCompleted: {
FluTools.setQuitOnLastWindowClosed(false) FluTools.setQuitOnLastWindowClosed(false)
tour.open() tour.open()
checkUpdate() checkUpdate(true)
FluEventBus.registerEvent(event_checkupdate)
}
Component.onDestruction: {
FluEventBus.unRegisterEvent(event_checkupdate)
} }
SystemTrayIcon { SystemTrayIcon {
@ -312,11 +325,13 @@ CustomWindow {
HttpCallable{ HttpCallable{
id:callable id:callable
property bool silent: true
onStart: { onStart: {
console.debug("satrt check update...") console.debug("satrt check update...")
} }
onFinish: { onFinish: {
console.debug("check update finish") console.debug("check update finish")
FluEventBus.post("checkUpdateFinish");
} }
onSuccess: onSuccess:
(result)=>{ (result)=>{
@ -327,15 +342,23 @@ CustomWindow {
dialog_update.newVerson = data.tag_name dialog_update.newVerson = data.tag_name
dialog_update.body = data.body dialog_update.body = data.body
dialog_update.open() dialog_update.open()
}else{
if(!silent){
showInfo("当前版本已经是最新版")
}
} }
} }
onError: onError:
(status,errorString)=>{ (status,errorString)=>{
if(!silent){
showError("网络异常!")
}
console.debug(status+";"+errorString) console.debug(status+";"+errorString)
} }
} }
function checkUpdate(){ function checkUpdate(silent){
callable.silent = silent
var request = http.newRequest("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest") var request = http.newRequest("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
http.get(request,callable); http.get(request,callable);
} }

40
src/FluEventBus.cpp Normal file
View File

@ -0,0 +1,40 @@
#include "FluEventBus.h"
FluEventBus* FluEventBus::m_instance = nullptr;
FluEvent::FluEvent(QObject *parent)
: QObject{parent}
{
}
FluEventBus *FluEventBus::getInstance()
{
if(FluEventBus::m_instance == nullptr){
FluEventBus::m_instance = new FluEventBus;
}
return FluEventBus::m_instance;
}
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);
}
}
}

38
src/FluEventBus.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef FLUEVENTBUS_H
#define FLUEVENTBUS_H
#include <QObject>
#include <QtQml/qqml.h>
#include "stdafx.h"
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);
};
class FluEventBus : public QObject
{
Q_OBJECT
QML_NAMED_ELEMENT(FluEventBus)
QML_SINGLETON
private:
static FluEventBus* m_instance;
explicit FluEventBus(QObject *parent = nullptr);
public:
static FluEventBus *getInstance();
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

View File

@ -12,6 +12,7 @@
#include "FluHttpInterceptor.h" #include "FluHttpInterceptor.h"
#include "FluWatermark.h" #include "FluWatermark.h"
#include "FluCaptcha.h" #include "FluCaptcha.h"
#include "FluEventBus.h"
#include "Screenshot.h" #include "Screenshot.h"
#include "QRCode.h" #include "QRCode.h"
@ -49,6 +50,7 @@ void FluentUI::registerTypes(const char *uri){
qmlRegisterType<FluHttp>(uri,major,minor,"FluHttp"); qmlRegisterType<FluHttp>(uri,major,minor,"FluHttp");
qmlRegisterType<HttpCallable>(uri,major,minor,"HttpCallable"); qmlRegisterType<HttpCallable>(uri,major,minor,"HttpCallable");
qmlRegisterType<HttpRequest>(uri,major,minor,"HttpRequest"); qmlRegisterType<HttpRequest>(uri,major,minor,"HttpRequest");
qmlRegisterType<FluEvent>(uri,major,minor,"FluEvent");
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/ColorPicker/ColorPicker.qml"),uri,major,minor,"ColorPicker"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/ColorPicker/ColorPicker.qml"),uri,major,minor,"ColorPicker");
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/ColorPicker/Content/Checkerboard.qml"),uri,major,minor,"Checkerboard"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/ColorPicker/Content/Checkerboard.qml"),uri,major,minor,"Checkerboard");
@ -143,6 +145,7 @@ void FluentUI::registerTypes(const char *uri){
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRangeSlider.qml"),uri,major,minor,"FluRangeSlider"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRangeSlider.qml"),uri,major,minor,"FluRangeSlider");
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluStaggeredView.qml"),uri,major,minor,"FluStaggeredView"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluStaggeredView.qml"),uri,major,minor,"FluStaggeredView");
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluProgressButton.qml"),uri,major,minor,"FluProgressButton"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluProgressButton.qml"),uri,major,minor,"FluProgressButton");
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluLoadingButton.qml"),uri,major,minor,"FluLoadingButton");
qmlRegisterUncreatableMetaObject(Fluent_Awesome::staticMetaObject, uri,major,minor,"FluentIcons", "Access to enums & flags only"); qmlRegisterUncreatableMetaObject(Fluent_Awesome::staticMetaObject, uri,major,minor,"FluentIcons", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluHttpType::staticMetaObject, uri,major,minor,"FluHttpType", "Access to enums & flags only"); qmlRegisterUncreatableMetaObject(FluHttpType::staticMetaObject, uri,major,minor,"FluHttpType", "Access to enums & flags only");
@ -178,5 +181,7 @@ void FluentUI::initializeEngine(QQmlEngine *engine, const char *uri){
engine->rootContext()->setContextProperty("FluTools",tools); engine->rootContext()->setContextProperty("FluTools",tools);
FluTextStyle* textStyle = FluTextStyle::getInstance(); FluTextStyle* textStyle = FluTextStyle::getInstance();
engine->rootContext()->setContextProperty("FluTextStyle",textStyle); engine->rootContext()->setContextProperty("FluTextStyle",textStyle);
FluEventBus* eventBus = FluEventBus::getInstance();
engine->rootContext()->setContextProperty("FluEventBus",eventBus);
engine->addImportPath("qrc:/qt/qml"); engine->addImportPath("qrc:/qt/qml");
} }

View File

@ -0,0 +1,40 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
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: 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

@ -27,28 +27,31 @@ Button {
Accessible.name: control.text Accessible.name: control.text
Accessible.description: contentDescription Accessible.description: contentDescription
Accessible.onPressAction: control.clicked() Accessible.onPressAction: control.clicked()
height: 20
enabled: !disabled enabled: !disabled
implicitHeight: height
focusPolicy:Qt.TabFocus focusPolicy:Qt.TabFocus
onClicked: clickListener() onClicked: clickListener()
padding: 0
horizontalPadding: 0
onCheckableChanged: { onCheckableChanged: {
if(checkable){ if(checkable){
checkable = false checkable = false
} }
} }
contentItem: Item{} background : Item{
background : RowLayout{ implicitHeight: 20
implicitWidth: 40
}
contentItem: RowLayout{
spacing: control.textSpacing spacing: control.textSpacing
layoutDirection:control.textRight ? Qt.LeftToRight : Qt.RightToLeft layoutDirection:control.textRight ? Qt.LeftToRight : Qt.RightToLeft
Rectangle { Rectangle {
id:control_backgound id:control_backgound
width: 40 width: background.width
height: control.height height: background.height
radius: height / 2 radius: height / 2
FluFocusRectangle{ FluFocusRectangle{
visible: control.activeFocus visible: control.activeFocus
radius: 20 radius: parent.radius
} }
color: { color: {
if(!enabled){ if(!enabled){
@ -73,10 +76,10 @@ Button {
return borderNormalColor return borderNormalColor
} }
Rectangle { Rectangle {
width: 20 width: parent.height
x:checked ? control_backgound.width-width : 0 x:checked ? control_backgound.width-width : 0
height: 20 height: width
radius: 10 radius: width/2
scale: hovered&enabled ? 7/10 : 6/10 scale: hovered&enabled ? 7/10 : 6/10
color: { color: {
if(!enabled){ if(!enabled){

File diff suppressed because it is too large Load Diff

View File

@ -95,4 +95,5 @@ FluWindow 1.0 Controls/FluWindow.qml
FluRangeSlider 1.0 Controls/FluRangeSlider.qml FluRangeSlider 1.0 Controls/FluRangeSlider.qml
FluStaggeredView 1.0 Controls/FluStaggeredView.qml FluStaggeredView 1.0 Controls/FluStaggeredView.qml
FluProgressButton 1.0 Controls/FluProgressButton.qml FluProgressButton 1.0 Controls/FluProgressButton.qml
FluLoadingButton 1.0 Controls/FluLoadingButton.qml
plugin fluentuiplugin plugin fluentuiplugin

View File

@ -95,5 +95,6 @@
<file>FluentUI/Controls/ColorPicker/Content/NumberBox.qml</file> <file>FluentUI/Controls/ColorPicker/Content/NumberBox.qml</file>
<file>FluentUI/Controls/ColorPicker/Content/PanelBorder.qml</file> <file>FluentUI/Controls/ColorPicker/Content/PanelBorder.qml</file>
<file>FluentUI/Controls/ColorPicker/Content/SBPicker.qml</file> <file>FluentUI/Controls/ColorPicker/Content/SBPicker.qml</file>
<file>FluentUI/Controls/FluLoadingButton.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -0,0 +1,41 @@
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: 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

@ -28,23 +28,31 @@ Button {
Accessible.name: control.text Accessible.name: control.text
Accessible.description: contentDescription Accessible.description: contentDescription
Accessible.onPressAction: control.clicked() Accessible.onPressAction: control.clicked()
height: 20
enabled: !disabled enabled: !disabled
implicitHeight: height
focusPolicy:Qt.TabFocus focusPolicy:Qt.TabFocus
onClicked: clickListener() onClicked: clickListener()
contentItem: Item{} padding: 0
background : RowLayout{ horizontalPadding: 0
onCheckableChanged: {
if(checkable){
checkable = false
}
}
background : Item{
implicitHeight: 20
implicitWidth: 40
}
contentItem: RowLayout{
spacing: control.textSpacing spacing: control.textSpacing
layoutDirection:control.textRight ? Qt.LeftToRight : Qt.RightToLeft layoutDirection:control.textRight ? Qt.LeftToRight : Qt.RightToLeft
Rectangle { Rectangle {
id:control_backgound id:control_backgound
width: 40 width: background.width
height: control.height height: background.height
radius: height / 2 radius: height / 2
FluFocusRectangle{ FluFocusRectangle{
visible: control.activeFocus visible: control.activeFocus
radius: 20 radius: parent.radius
} }
color: { color: {
if(!enabled){ if(!enabled){
@ -69,10 +77,10 @@ Button {
return borderNormalColor return borderNormalColor
} }
Rectangle { Rectangle {
width: 20 width: parent.height
x:checked ? control_backgound.width-width : 0 x:checked ? control_backgound.width-width : 0
height: 20 height: width
radius: 10 radius: width/2
scale: hovered&enabled ? 7/10 : 6/10 scale: hovered&enabled ? 7/10 : 6/10
color: { color: {
if(!enabled){ if(!enabled){