diff --git a/example/example.qrc b/example/example.qrc index 04ccb1c6..33a311c6 100644 --- a/example/example.qrc +++ b/example/example.qrc @@ -187,5 +187,6 @@ qml/page/T_StaggeredView.qml qml/viewmodel/SettingsViewModel.qml qml/viewmodel/TextBoxViewModel.qml + qml/page/T_Clip.qml diff --git a/example/qml-Qt6/component/CodeExpander.qml b/example/qml-Qt6/component/CodeExpander.qml index 0f54225b..a38d3387 100644 --- a/example/qml-Qt6/component/CodeExpander.qml +++ b/example/qml-Qt6/component/CodeExpander.qml @@ -139,7 +139,8 @@ FluExpander{ "FluRangeSlider", "FluStaggeredView", "FluProgressButton", - "FluLoadingButton" + "FluLoadingButton", + "FluClip" ]; code = code.replace(/\n/g, "
"); code = code.replace(/ /g, " "); diff --git a/example/qml-Qt6/global/ItemsOriginal.qml b/example/qml-Qt6/global/ItemsOriginal.qml index ab88e9dd..760b067c 100644 --- a/example/qml-Qt6/global/ItemsOriginal.qml +++ b/example/qml-Qt6/global/ItemsOriginal.qml @@ -207,6 +207,12 @@ FluObject{ onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) } onTap:{ navigationView.push(url) } } + FluPaneItem{ + title:"Clip" + url:"qrc:/example/qml/page/T_Clip.qml" + onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) } + onTap:{ navigationView.push(url) } + } FluPaneItem{ title:"StatusView" url:"qrc:/example/qml/page/T_StatusView.qml" diff --git a/example/qml-Qt6/page/T_Awesome.qml b/example/qml-Qt6/page/T_Awesome.qml index 182ce910..0d0e9d31 100644 --- a/example/qml-Qt6/page/T_Awesome.qml +++ b/example/qml-Qt6/page/T_Awesome.qml @@ -25,7 +25,7 @@ FluContentPage { leftMargin: 14 } onClicked: { - grid_view.model = FluApp.awesomelist(text_box.text) + grid_view.model = FluTheme.awesomeList(text_box.text) } } GridView{ @@ -34,7 +34,7 @@ FluContentPage { cellHeight: 80 clip: true boundsBehavior: GridView.StopAtBounds - model:FluApp.awesomelist() + model:FluTheme.awesomeList() ScrollBar.vertical: FluScrollBar {} anchors{ topMargin: 10 diff --git a/example/qml-Qt6/page/T_Clip.qml b/example/qml-Qt6/page/T_Clip.qml new file mode 100644 index 00000000..2e8a275f --- /dev/null +++ b/example/qml-Qt6/page/T_Clip.qml @@ -0,0 +1,107 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Clip" + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 380 + paddings: 10 + + Column{ + spacing: 15 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluText{ + text:"配合图片使用(software渲染下该组件将没有效果)" + font: FluTextStyle.Subtitle + Layout.topMargin: 20 + } + RowLayout{ + spacing: 14 + FluClip{ + width: 50 + height: 50 + radius:[25,0,25,25] + Image { + asynchronous: true + anchors.fill: parent + source: "qrc:/example/res/svg/avatar_1.svg" + sourceSize: Qt.size(width,height) + } + } + FluClip{ + width: 50 + height: 50 + radius:[10,10,10,10] + Image { + asynchronous: true + anchors.fill: parent + sourceSize: Qt.size(width,height) + source: "qrc:/example/res/svg/avatar_2.svg" + } + } + FluClip{ + width: 50 + height: 50 + radius:[25,25,25,25] + Image { + asynchronous: true + anchors.fill: parent + sourceSize: Qt.size(width,height) + source: "qrc:/example/res/svg/avatar_3.svg" + } + } + FluClip{ + width: 50 + height: 50 + radius:[0,25,25,25] + Image { + asynchronous: true + anchors.fill: parent + sourceSize: Qt.size(width,height) + source: "qrc:/example/res/svg/avatar_4.svg" + } + } + } + FluClip{ + width: 1920/5 + height: 1200/5 + radius:[8,8,8,8] + Image { + asynchronous: true + source: "qrc:/example/res/image/banner_1.jpg" + anchors.fill: parent + sourceSize: Qt.size(2*width,2*height) + } + Layout.topMargin: 20 + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluClip{ + radius: [25,25,25,25] + width: 50 + height: 50 + Image{ + asynchronous: true + anchors.fill: parent + source: "qrc:/example/res/svg/avatar_4.svg" + sourceSize: Qt.size(width,height) + } +}' + } + + +} diff --git a/example/qml-Qt6/page/T_Rectangle.qml b/example/qml-Qt6/page/T_Rectangle.qml index 5ea40b59..76653492 100644 --- a/example/qml-Qt6/page/T_Rectangle.qml +++ b/example/qml-Qt6/page/T_Rectangle.qml @@ -12,16 +12,15 @@ FluScrollablePage{ FluArea{ Layout.fillWidth: true Layout.topMargin: 20 - height: 460 + height: 80 paddings: 10 Column{ spacing: 15 anchors{ - verticalCenter: parent.verticalCenter left: parent.left + verticalCenter: parent.verticalCenter } - RowLayout{ Layout.topMargin: 20 FluRectangle{ @@ -61,70 +60,6 @@ FluScrollablePage{ radius:[0,0,0,15] } } - FluText{ - text:"配合图片使用" - font: FluTextStyle.Subtitle - Layout.topMargin: 20 - } - RowLayout{ - spacing: 14 - FluClip{ - width: 50 - height: 50 - radius:[25,0,25,25] - Image { - asynchronous: true - anchors.fill: parent - source: "qrc:/example/res/svg/avatar_1.svg" - sourceSize: Qt.size(width,height) - } - } - FluClip{ - width: 50 - height: 50 - radius:[10,10,10,10] - Image { - asynchronous: true - anchors.fill: parent - sourceSize: Qt.size(width,height) - source: "qrc:/example/res/svg/avatar_2.svg" - } - } - FluClip{ - width: 50 - height: 50 - radius:[25,25,25,25] - Image { - asynchronous: true - anchors.fill: parent - sourceSize: Qt.size(width,height) - source: "qrc:/example/res/svg/avatar_3.svg" - } - } - FluClip{ - width: 50 - height: 50 - radius:[0,25,25,25] - Image { - asynchronous: true - anchors.fill: parent - sourceSize: Qt.size(width,height) - source: "qrc:/example/res/svg/avatar_4.svg" - } - } - } - FluClip{ - width: 1920/5 - height: 1200/5 - radius:[8,8,8,8] - Image { - asynchronous: true - source: "qrc:/example/res/image/banner_1.jpg" - anchors.fill: parent - sourceSize: Qt.size(2*width,2*height) - } - Layout.topMargin: 20 - } } } CodeExpander{ @@ -134,14 +69,6 @@ FluScrollablePage{ radius: [25,25,25,25] width: 50 height: 50 - Image{ - asynchronous: true - anchors.fill: parent - source: "qrc:/example/res/svg/avatar_4.svg" - sourceSize: Qt.size(width,height) - } }' } - - } diff --git a/example/qml-Qt6/page/T_Settings.qml b/example/qml-Qt6/page/T_Settings.qml index a1578866..aecef5c2 100644 --- a/example/qml-Qt6/page/T_Settings.qml +++ b/example/qml-Qt6/page/T_Settings.qml @@ -84,8 +84,7 @@ FluScrollablePage{ negativeText: "取消" positiveText:"确定" onPositiveClicked:{ - window.deleteWindow() - AppInfo.restart() + FluApp.exit(931) } } diff --git a/example/qml-Qt6/window/MainWindow.qml b/example/qml-Qt6/window/MainWindow.qml index b03226e6..a39ca6cb 100644 --- a/example/qml-Qt6/window/MainWindow.qml +++ b/example/qml-Qt6/window/MainWindow.qml @@ -25,7 +25,7 @@ CustomWindow { id:viewmodel_settings } - closeFunc:function(event){ + closeListener:function(event){ dialog_close.open() event.accepted = false } @@ -58,8 +58,7 @@ CustomWindow { MenuItem { text: "退出" onTriggered: { - window.deleteWindow() - FluApp.closeApp() + FluApp.exit() } } } @@ -86,8 +85,7 @@ CustomWindow { positiveText:"退出" neutralText:"取消" onPositiveClicked:{ - window.deleteWindow() - FluApp.closeApp() + FluApp.exit() } } diff --git a/example/qml/component/CodeExpander.qml b/example/qml/component/CodeExpander.qml index 0227fa10..43039130 100644 --- a/example/qml/component/CodeExpander.qml +++ b/example/qml/component/CodeExpander.qml @@ -139,7 +139,8 @@ FluExpander{ "FluRangeSlider", "FluStaggeredView", "FluProgressButton", - "FluLoadingButton" + "FluLoadingButton", + "FluClip" ]; code = code.replace(/\n/g, "
"); code = code.replace(/ /g, " "); diff --git a/example/qml/global/ItemsOriginal.qml b/example/qml/global/ItemsOriginal.qml index 9b844f77..63f7a075 100644 --- a/example/qml/global/ItemsOriginal.qml +++ b/example/qml/global/ItemsOriginal.qml @@ -207,6 +207,12 @@ FluObject{ onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) } onTap:{ navigationView.push(url) } } + FluPaneItem{ + title:"Clip" + url:"qrc:/example/qml/page/T_Clip.qml" + onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) } + onTap:{ navigationView.push(url) } + } FluPaneItem{ title:"StatusView" url:"qrc:/example/qml/page/T_StatusView.qml" diff --git a/example/qml/page/T_Awesome.qml b/example/qml/page/T_Awesome.qml index 1804475f..92ab874f 100644 --- a/example/qml/page/T_Awesome.qml +++ b/example/qml/page/T_Awesome.qml @@ -25,7 +25,7 @@ FluContentPage { leftMargin: 14 } onClicked: { - grid_view.model = FluApp.awesomelist(text_box.text) + grid_view.model = FluTheme.awesomeList(text_box.text) } } GridView{ @@ -34,7 +34,7 @@ FluContentPage { cellHeight: 80 clip: true boundsBehavior: GridView.StopAtBounds - model:FluApp.awesomelist() + model:FluTheme.awesomeList() ScrollBar.vertical: FluScrollBar {} anchors{ topMargin: 10 diff --git a/example/qml/page/T_Clip.qml b/example/qml/page/T_Clip.qml new file mode 100644 index 00000000..b4d371fb --- /dev/null +++ b/example/qml/page/T_Clip.qml @@ -0,0 +1,108 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 +import "../component" +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Clip" + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 380 + paddings: 10 + + Column{ + spacing: 15 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluText{ + text:"配合图片使用(software渲染下该组件将没有效果)" + font: FluTextStyle.Subtitle + Layout.topMargin: 20 + } + RowLayout{ + spacing: 14 + FluClip{ + width: 50 + height: 50 + radius:[25,0,25,25] + Image { + asynchronous: true + anchors.fill: parent + source: "qrc:/example/res/svg/avatar_1.svg" + sourceSize: Qt.size(width,height) + } + } + FluClip{ + width: 50 + height: 50 + radius:[10,10,10,10] + Image { + asynchronous: true + anchors.fill: parent + sourceSize: Qt.size(width,height) + source: "qrc:/example/res/svg/avatar_2.svg" + } + } + FluClip{ + width: 50 + height: 50 + radius:[25,25,25,25] + Image { + asynchronous: true + anchors.fill: parent + sourceSize: Qt.size(width,height) + source: "qrc:/example/res/svg/avatar_3.svg" + } + } + FluClip{ + width: 50 + height: 50 + radius:[0,25,25,25] + Image { + asynchronous: true + anchors.fill: parent + sourceSize: Qt.size(width,height) + source: "qrc:/example/res/svg/avatar_4.svg" + } + } + } + FluClip{ + width: 1920/5 + height: 1200/5 + radius:[8,8,8,8] + Image { + asynchronous: true + source: "qrc:/example/res/image/banner_1.jpg" + anchors.fill: parent + sourceSize: Qt.size(2*width,2*height) + } + Layout.topMargin: 20 + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluClip{ + radius: [25,25,25,25] + width: 50 + height: 50 + Image{ + asynchronous: true + anchors.fill: parent + source: "qrc:/example/res/svg/avatar_4.svg" + sourceSize: Qt.size(width,height) + } +}' + } + + +} diff --git a/example/qml/page/T_Rectangle.qml b/example/qml/page/T_Rectangle.qml index 451148d4..b6ffb11c 100644 --- a/example/qml/page/T_Rectangle.qml +++ b/example/qml/page/T_Rectangle.qml @@ -13,16 +13,15 @@ FluScrollablePage{ FluArea{ Layout.fillWidth: true Layout.topMargin: 20 - height: 460 + height: 80 paddings: 10 Column{ spacing: 15 anchors{ - verticalCenter: parent.verticalCenter left: parent.left + verticalCenter: parent.verticalCenter } - RowLayout{ Layout.topMargin: 20 FluRectangle{ @@ -62,70 +61,6 @@ FluScrollablePage{ radius:[0,0,0,15] } } - FluText{ - text:"配合图片使用" - font: FluTextStyle.Subtitle - Layout.topMargin: 20 - } - RowLayout{ - spacing: 14 - FluClip{ - width: 50 - height: 50 - radius:[25,0,25,25] - Image { - asynchronous: true - anchors.fill: parent - source: "qrc:/example/res/svg/avatar_1.svg" - sourceSize: Qt.size(width,height) - } - } - FluClip{ - width: 50 - height: 50 - radius:[10,10,10,10] - Image { - asynchronous: true - anchors.fill: parent - sourceSize: Qt.size(width,height) - source: "qrc:/example/res/svg/avatar_2.svg" - } - } - FluClip{ - width: 50 - height: 50 - radius:[25,25,25,25] - Image { - asynchronous: true - anchors.fill: parent - sourceSize: Qt.size(width,height) - source: "qrc:/example/res/svg/avatar_3.svg" - } - } - FluClip{ - width: 50 - height: 50 - radius:[0,25,25,25] - Image { - asynchronous: true - anchors.fill: parent - sourceSize: Qt.size(width,height) - source: "qrc:/example/res/svg/avatar_4.svg" - } - } - } - FluClip{ - width: 1920/5 - height: 1200/5 - radius:[8,8,8,8] - Image { - asynchronous: true - source: "qrc:/example/res/image/banner_1.jpg" - anchors.fill: parent - sourceSize: Qt.size(2*width,2*height) - } - Layout.topMargin: 20 - } } } CodeExpander{ @@ -135,14 +70,6 @@ FluScrollablePage{ radius: [25,25,25,25] width: 50 height: 50 - Image{ - asynchronous: true - anchors.fill: parent - source: "qrc:/example/res/svg/avatar_4.svg" - sourceSize: Qt.size(width,height) - } }' } - - } diff --git a/example/qml/page/T_Settings.qml b/example/qml/page/T_Settings.qml index 0887e1e0..6d28ff9c 100644 --- a/example/qml/page/T_Settings.qml +++ b/example/qml/page/T_Settings.qml @@ -87,8 +87,7 @@ FluScrollablePage{ negativeText: "取消" positiveText:"确定" onPositiveClicked:{ - window.deleteWindow() - AppInfo.restart() + FluApp.exit(931) } } diff --git a/example/qml/window/MainWindow.qml b/example/qml/window/MainWindow.qml index 0d6b4b2a..c2f336fe 100644 --- a/example/qml/window/MainWindow.qml +++ b/example/qml/window/MainWindow.qml @@ -28,7 +28,7 @@ CustomWindow { id:viewmodel_settings } - closeFunc:function(event){ + closeListener:function(event){ dialog_close.open() event.accepted = false } @@ -61,8 +61,7 @@ CustomWindow { MenuItem { text: "退出" onTriggered: { - window.deleteWindow() - FluApp.closeApp() + FluApp.exit() } } } @@ -89,8 +88,7 @@ CustomWindow { positiveText:"退出" neutralText:"取消" onPositiveClicked:{ - window.deleteWindow() - FluApp.closeApp() + FluApp.exit() } } diff --git a/example/src/AppInfo.cpp b/example/src/AppInfo.cpp index 2cafc4ef..d833609f 100644 --- a/example/src/AppInfo.cpp +++ b/example/src/AppInfo.cpp @@ -35,7 +35,3 @@ void AppInfo::changeLang(const QString& locale){ lang(new En()); } } - -void AppInfo::restart(){ - qApp->exit(931); -} diff --git a/example/src/AppInfo.h b/example/src/AppInfo.h index a4a8812b..647fee8e 100644 --- a/example/src/AppInfo.h +++ b/example/src/AppInfo.h @@ -18,7 +18,6 @@ public: SINGLETONG(AppInfo) void init(QQmlApplicationEngine *engine); Q_INVOKABLE void changeLang(const QString& locale); - Q_INVOKABLE void restart(); }; #endif // APPINFO_H diff --git a/src/FluApp.cpp b/src/FluApp.cpp index b95b78ab..43ae2820 100644 --- a/src/FluApp.cpp +++ b/src/FluApp.cpp @@ -8,7 +8,6 @@ #include #include #include -#include "Def.h" FluApp::FluApp(QObject *parent):QObject{parent}{ httpInterceptor(nullptr); @@ -18,7 +17,7 @@ FluApp::~FluApp(){ } void FluApp::init(QQuickWindow *window){ - this->appWindow = window; + this->_application = window; } void FluApp::run(){ @@ -30,7 +29,7 @@ void FluApp::navigate(const QString& route,const QJsonObject& argument,FluRegist qCritical()<<"No route found "<property("_route").toString(); + QQuickWindow *win=nullptr; + for (const auto& pair : _windows.toStdMap()) { + QString r = pair.second->property("_route").toString(); if(r == route){ - view = pair; + win = pair.second; break; } } - if(view){ - //如果窗口存在,则判断启动模式 - int launchMode = view->property("launchMode").toInt(); + if(win){ + int launchMode = win->property("launchMode").toInt(); if(launchMode == 1){ - view->setProperty("argument",argument); - view->show(); - view->raise(); - view->requestActivate(); + win->setProperty("argument",argument); + win->show(); + win->raise(); + win->requestActivate(); return; }else if(launchMode == 2){ - view->close(); + win->close(); } } - view = qobject_cast(component.createWithInitialProperties(properties)); - wnds.insert(view->winId(),view); + win = qobject_cast(component.createWithInitialProperties(properties)); if(fluRegister){ - fluRegister->to(view); + fluRegister->to(win); } - view->setColor(QColor(Qt::transparent)); + win->setColor(QColor(Qt::transparent)); } -QJsonArray FluApp::awesomelist(const QString& keyword){ - QJsonArray arr; - QMetaEnum enumType = Fluent_Awesome::staticMetaObject.enumerator(Fluent_Awesome::staticMetaObject.indexOfEnumerator("Fluent_AwesomeType")); - for(int i=0; i < enumType.keyCount(); ++i){ - QString name = enumType.key(i); - int icon = enumType.value(i); - if(keyword.isEmpty()){ - QJsonObject obj; - obj.insert("name",name); - obj.insert("icon",icon); - arr.append(obj); - }else{ - if(name.contains(keyword)){ - QJsonObject obj; - obj.insert("name",name); - obj.insert("icon",icon); - arr.append(obj); - } - } +void FluApp::exit(int retCode){ + for (const auto& pair : _windows.toStdMap()) { + removeWindow(pair.second); } - return arr; + qApp->exit(retCode); } -void FluApp::closeApp(){ - qApp->exit(0); +void FluApp::addWindow(QQuickWindow* window){ + _windows.insert(window->winId(),window); } -void FluApp::deleteWindow(QQuickWindow* window){ +void FluApp::removeWindow(QQuickWindow* window){ if(window){ - wnds.remove(window->winId()); + _windows.remove(window->winId()); window->deleteLater(); window = nullptr; } diff --git a/src/FluApp.h b/src/FluApp.h index a5122bcd..ddcaf249 100644 --- a/src/FluApp.h +++ b/src/FluApp.h @@ -33,13 +33,12 @@ public: Q_INVOKABLE void run(); Q_INVOKABLE void navigate(const QString& route,const QJsonObject& argument = {},FluRegister* fluRegister = nullptr); Q_INVOKABLE void init(QQuickWindow *window); - Q_INVOKABLE QJsonArray awesomelist(const QString& keyword = ""); - Q_INVOKABLE void closeApp(); - Q_INVOKABLE void deleteWindow(QQuickWindow* window); -public: - QMap wnds; + Q_INVOKABLE void exit(int retCode = 0); + void addWindow(QQuickWindow* window); + void removeWindow(QQuickWindow* window); private: - QWindow *appWindow; + QMap _windows; + QWindow* _application; }; #endif // FLUAPP_H diff --git a/src/FluHttp.cpp b/src/FluHttp.cpp index 7065551e..a159388e 100644 --- a/src/FluHttp.cpp +++ b/src/FluHttp.cpp @@ -110,11 +110,16 @@ void FluHttp::post(HttpRequest* r,HttpCallable* c){ part.setBody(value.toUtf8()); multiPart.append(part); } - QEventLoop loop; QNetworkReply* reply = manager.post(req,&multiPart); + if(!QPointer(qApp)){ + reply->deleteLater(); + reply = nullptr; + return; + } _cacheReply.append(reply); + QEventLoop loop; connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();}); - connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop](){loop.quit();}); + connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();}); loop.exec(); QString result = QString::fromUtf8(reply->readAll()); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); @@ -169,11 +174,16 @@ void FluHttp::postString(HttpRequest* r,HttpCallable* c){ addHeaders(&req,data["headers"].toMap()); QString contentType = QString("text/plain;charset=utf-8"); req.setHeader(QNetworkRequest::ContentTypeHeader, contentType); - QEventLoop loop; QNetworkReply* reply = manager.post(req,params.toUtf8()); + if(!QPointer(qApp)){ + reply->deleteLater(); + reply = nullptr; + return; + } _cacheReply.append(reply); + QEventLoop loop; connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();}); - connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop](){loop.quit();}); + connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();}); loop.exec(); QString result = QString::fromUtf8(reply->readAll()); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); @@ -227,11 +237,16 @@ void FluHttp::postJson(HttpRequest* r,HttpCallable* c){ addHeaders(&req,data["headers"].toMap()); QString contentType = QString("application/json;charset=utf-8"); req.setHeader(QNetworkRequest::ContentTypeHeader, contentType); - QEventLoop loop; QNetworkReply* reply = manager.post(req,QJsonDocument::fromVariant(data["params"]).toJson()); + if(!QPointer(qApp)){ + reply->deleteLater(); + reply = nullptr; + return; + } _cacheReply.append(reply); + QEventLoop loop; connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();}); - connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop](){loop.quit();}); + connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();}); loop.exec(); QString result = QString::fromUtf8(reply->readAll()); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); @@ -284,11 +299,16 @@ void FluHttp::get(HttpRequest* r,HttpCallable* c){ addQueryParam(&url,data["params"].toMap()); QNetworkRequest req(url); addHeaders(&req,data["headers"].toMap()); - QEventLoop loop; - auto reply = QPointer(manager.get(req)); + QNetworkReply* reply = manager.get(req); + if(!QPointer(qApp)){ + reply->deleteLater(); + reply = nullptr; + return; + } _cacheReply.append(reply); + QEventLoop loop; connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();}); - connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop](){loop.quit();}); + connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();}); loop.exec(); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); QString errorString = reply->errorString(); @@ -337,9 +357,6 @@ void FluHttp::download(HttpRequest* r,HttpCallable* c){ if (!dir.exists(dir.path())){ dir.mkpath(dir.path()); } - QEventLoop loop; - connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();}); - connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop](){loop.quit();}); qint64 seek = 0; auto filePath = getCacheFilePath(httpId); QSharedPointer fileCache(new QFile(filePath)); @@ -364,7 +381,15 @@ void FluHttp::download(HttpRequest* r,HttpCallable* c){ file->open(QIODevice::WriteOnly|QIODevice::Truncate); } QNetworkReply* reply = manager.get(req); + if(!QPointer(qApp)){ + reply->deleteLater(); + reply = nullptr; + return; + } _cacheReply.append(reply); + QEventLoop loop; + connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();}); + connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();}); if (!fileCache->open(QIODevice::WriteOnly|QIODevice::Truncate)) { qDebug()<<"FileCache Error"; @@ -411,7 +436,6 @@ void FluHttp::upload(HttpRequest* request,HttpCallable* callable){ QNetworkRequest req(url); addHeaders(&req,data["headers"].toMap()); QHttpMultiPart multiPart(QHttpMultiPart::FormDataType); - qDebug()<deleteLater(); + reply = nullptr; + return; + } _cacheReply.append(reply); + QEventLoop loop; connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();}); - connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop](){loop.quit();}); + connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();}); connect(reply,&QNetworkReply::uploadProgress,reply,[=](qint64 bytesSent, qint64 bytesTotal){ onUploadProgress(callable,bytesSent,bytesTotal); }); diff --git a/src/FluTheme.cpp b/src/FluTheme.cpp index 2c3ec38c..657604eb 100644 --- a/src/FluTheme.cpp +++ b/src/FluTheme.cpp @@ -36,6 +36,22 @@ bool FluTheme::eventFilter(QObject *obj, QEvent *event){ return false; } +QJsonArray FluTheme::awesomeList(const QString& keyword){ + QJsonArray arr; + QMetaEnum enumType = Fluent_Awesome::staticMetaObject.enumerator(Fluent_Awesome::staticMetaObject.indexOfEnumerator("Fluent_AwesomeType")); + for(int i=0; i < enumType.keyCount(); ++i){ + QString name = enumType.key(i); + int icon = enumType.value(i); + if(keyword.isEmpty() || name.contains(keyword)){ + QJsonObject obj; + obj.insert("name",name); + obj.insert("icon",icon); + arr.append(obj); + } + } + return arr; +} + bool FluTheme::systemDark(){ #if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) return (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark); diff --git a/src/FluTheme.h b/src/FluTheme.h index cef3dfa2..725f45b1 100644 --- a/src/FluTheme.h +++ b/src/FluTheme.h @@ -3,6 +3,8 @@ #include #include +#include +#include #include "FluColorSet.h" #include "stdafx.h" #include "singleton.h" @@ -26,9 +28,10 @@ private: bool systemDark(); public: SINGLETONG(FluTheme) + Q_INVOKABLE QJsonArray awesomeList(const QString& keyword = ""); + Q_SIGNAL void darkChanged(); static FluTheme *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return getInstance();} bool dark(); - Q_SIGNAL void darkChanged(); private: bool _dark; bool _systemDark; diff --git a/src/FluentUI.cpp b/src/FluentUI.cpp index 7d9536c7..266f09b5 100644 --- a/src/FluentUI.cpp +++ b/src/FluentUI.cpp @@ -1,7 +1,7 @@ #include "FluentUI.h" #include -#include "WindowHelper.h" +#include "WindowLifecycle.h" #include "Def.h" #include "FluApp.h" #include "FluColors.h" @@ -42,7 +42,7 @@ void FluentUI::registerTypes(const char *uri){ #if (QT_VERSION < QT_VERSION_CHECK(6, 2, 0)) Q_INIT_RESOURCE(fluentui); #endif - qmlRegisterType(uri,major,minor,"WindowHelper"); + qmlRegisterType(uri,major,minor,"WindowLifecycle"); qmlRegisterType(uri,major,minor,"QRCode"); qmlRegisterType(uri,major,minor,"FluCaptcha"); qmlRegisterType(uri,major,minor,"FluWatermark"); diff --git a/src/Qt5/imports/FluentUI/Controls/FluTreeView.qml b/src/Qt5/imports/FluentUI/Controls/FluTreeView.qml index 49ca0a58..ad89a65e 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluTreeView.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluTreeView.qml @@ -202,7 +202,6 @@ Item { d.dropIndex = -1 return } - console.debug(index) if(tree_model.hitHasChildrenExpanded(index) && y>index*control.cellHeight+control.cellHeight/2){ d.dropIndex = index + 1 d.isDropTopArea = true diff --git a/src/Qt5/imports/FluentUI/Controls/FluWindow.qml b/src/Qt5/imports/FluentUI/Controls/FluWindow.qml index 17f4ca48..00c262d9 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluWindow.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluWindow.qml @@ -19,9 +19,9 @@ Window { } property var _pageRegister property string _route - property var closeFunc: function(event){ + property var closeListener: function(event){ if(closeDestory){ - deleteWindow() + destoryOnClose() }else{ visible = false event.accepted = false @@ -31,12 +31,18 @@ Window { id:window color:"transparent" Component.onCompleted: { - helper.initWindow(window) + lifecycle.onCompleted(window) initArgument(argument) } + Component.onDestruction: { + lifecycle.onDestruction() + } + onVisibleChanged: { + lifecycle.onVisible(visible) + } Connections{ target: window - function onClosing(event){closeFunc(event)} + function onClosing(event){closeListener(event)} } Component{ id:com_background @@ -126,8 +132,11 @@ Window { } } } - WindowHelper{ - id:helper + WindowLifecycle{ + id:lifecycle + } + function destoryOnClose(){ + lifecycle.onDestoryOnClose() } function showLoading(text = "加载中...",cancel = true){ loader_loading.loadingText = text @@ -150,10 +159,7 @@ Window { infoBar.showError(text,duration,moremsg) } function registerForWindowResult(path){ - return helper.createRegister(window,path) - } - function deleteWindow(){ - FluApp.deleteWindow(window) + return lifecycle.createRegister(window,path) } function onResult(data){ if(_pageRegister){ diff --git a/src/Qt5/imports/FluentUI/plugins.qmltypes b/src/Qt5/imports/FluentUI/plugins.qmltypes index f52f82e3..7fe09718 100644 --- a/src/Qt5/imports/FluentUI/plugins.qmltypes +++ b/src/Qt5/imports/FluentUI/plugins.qmltypes @@ -4,7 +4,7 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable FluentUI 1.0 D:\QtProjects\build-FluentUI-Desktop_Qt_5_15_2_MSVC2019_64bit-Release\src' +// 'qmlplugindump -nonrelocatable FluentUI 1.0 D:/QtProjects/build-FluentUI-Desktop_Qt_5_15_2_MSVC2019_64bit-Release/src' Module { dependencies: ["QtQuick 2.0"] @@ -288,10 +288,11 @@ Module { } Component { name: "FluTreeModel" - prototype: "QAbstractTableModel" + prototype: "QAbstractItemModel" exports: ["FluentUI/FluTreeModel 1.0"] exportMetaObjectRevisions: [0] Property { name: "dataSourceSize"; type: "int" } + Property { name: "selectionModel"; type: "QList" } Method { name: "removeRows" Parameter { name: "row"; type: "int" } @@ -327,7 +328,29 @@ Module { name: "dragAnddrop" Parameter { name: "dragIndex"; type: "int" } Parameter { name: "dropIndex"; type: "int" } + Parameter { name: "isDropTopArea"; type: "bool" } } + Method { + name: "getNode" + type: "Node*" + Parameter { name: "row"; type: "int" } + } + Method { + name: "refreshNode" + Parameter { name: "row"; type: "int" } + } + Method { + name: "checkRow" + Parameter { name: "row"; type: "int" } + Parameter { name: "chekced"; type: "bool" } + } + Method { + name: "hitHasChildrenExpanded" + type: "bool" + Parameter { name: "row"; type: "int" } + } + Method { name: "allExpand" } + Method { name: "allCollapse" } } Component { name: "FluTreeViewType" @@ -2123,7 +2146,6 @@ Module { Parameter { name: "value"; type: "QVariant" } } } - Component { name: "QAbstractTableModel"; prototype: "QAbstractItemModel" } Component { name: "QRCode" defaultProperty: "data" @@ -2168,14 +2190,20 @@ Module { } } Component { - name: "WindowHelper" + name: "WindowLifecycle" prototype: "QObject" - exports: ["FluentUI/WindowHelper 1.0"] + exports: ["FluentUI/WindowLifecycle 1.0"] exportMetaObjectRevisions: [0] Method { - name: "initWindow" + name: "onCompleted" Parameter { name: "window"; type: "QQuickWindow"; isPointer: true } } + Method { name: "onDestruction" } + Method { + name: "onVisible" + Parameter { name: "visible"; type: "bool" } + } + Method { name: "onDestoryOnClose" } Method { name: "createRegister" type: "QVariant" @@ -2286,10 +2314,13 @@ Module { Property { name: "textColor"; type: "QColor" } Property { name: "minimizeNormalColor"; type: "QColor" } Property { name: "minimizeHoverColor"; type: "QColor" } + Property { name: "minimizePressColor"; type: "QColor" } Property { name: "maximizeNormalColor"; type: "QColor" } Property { name: "maximizeHoverColor"; type: "QColor" } + Property { name: "maximizePressColor"; type: "QColor" } Property { name: "closeNormalColor"; type: "QColor" } Property { name: "closeHoverColor"; type: "QColor" } + Property { name: "closePressColor"; type: "QColor" } Property { name: "showDark"; type: "bool" } Property { name: "showClose"; type: "bool" } Property { name: "showMinimize"; type: "bool" } @@ -2549,6 +2580,7 @@ Module { Property { name: "size"; type: "double" } Property { name: "textRight"; type: "bool" } Property { name: "textSpacing"; type: "double" } + Property { name: "enableAnimation"; type: "bool" } Property { name: "clickListener"; type: "QVariant" } Property { name: "textColor"; type: "QColor" } } @@ -2959,16 +2991,17 @@ Module { defaultProperty: "data" Property { name: "logo"; type: "QUrl" } Property { name: "title"; type: "string" } - Property { name: "items"; type: "FluObject_QMLTYPE_148"; isPointer: true } - Property { name: "footerItems"; type: "FluObject_QMLTYPE_148"; isPointer: true } + Property { name: "items"; type: "FluObject_QMLTYPE_140"; isPointer: true } + Property { name: "footerItems"; type: "FluObject_QMLTYPE_140"; isPointer: true } Property { name: "displayMode"; type: "int" } Property { name: "autoSuggestBox"; type: "QQmlComponent"; isPointer: true } Property { name: "actionItem"; type: "QQmlComponent"; isPointer: true } Property { name: "topPadding"; type: "int" } - Property { name: "navWidth"; type: "int" } Property { name: "pageMode"; type: "int" } Property { name: "navItemRightMenu"; type: "FluMenu_QMLTYPE_52"; isPointer: true } Property { name: "navItemExpanderRightMenu"; type: "FluMenu_QMLTYPE_52"; isPointer: true } + Property { name: "cellHeight"; type: "int" } + Property { name: "cellWidth"; type: "int" } Signal { name: "logoClicked" } Method { name: "collapseAll"; type: "QVariant" } Method { @@ -3053,6 +3086,7 @@ Module { Property { name: "order"; type: "int" } Property { name: "icon"; type: "int" } Property { name: "url"; type: "QVariant" } + Property { name: "disabled"; type: "bool" } Property { name: "cusIcon"; type: "QQmlComponent"; isPointer: true } Property { name: "infoBadge"; type: "QQmlComponent"; isPointer: true } Property { name: "recentlyAdded"; type: "bool" } @@ -3093,6 +3127,7 @@ Module { Property { name: "_idx"; type: "int" } Property { name: "title"; type: "string" } Property { name: "icon"; type: "QVariant" } + Property { name: "disabled"; type: "bool" } Property { name: "cusIcon"; type: "QQmlComponent"; isPointer: true } Property { name: "isExpand"; type: "bool" } Property { name: "parent"; type: "QVariant" } @@ -3676,9 +3711,25 @@ Module { Property { name: "dataSource"; type: "QVariant" } Property { name: "showLine"; type: "bool" } Property { name: "draggable"; type: "bool" } + Property { name: "cellHeight"; type: "int" } + Property { name: "depthPadding"; type: "int" } + Property { name: "checkable"; type: "bool" } Property { name: "lineColor"; type: "QColor" } + Method { name: "selectionModel"; type: "QVariant" } Method { name: "count"; type: "QVariant" } Method { name: "visibleCount"; type: "QVariant" } + Method { + name: "collapse" + type: "QVariant" + Parameter { name: "rowIndex"; type: "QVariant" } + } + Method { + name: "expand" + type: "QVariant" + Parameter { name: "rowIndex"; type: "QVariant" } + } + Method { name: "allExpand"; type: "QVariant" } + Method { name: "allCollapse"; type: "QVariant" } } Component { prototype: "QQuickWindowQmlImpl" @@ -3695,12 +3746,13 @@ Module { Property { name: "backgroundColor"; type: "QColor" } Property { name: "_pageRegister"; type: "QVariant" } Property { name: "_route"; type: "string" } - Property { name: "closeFunc"; type: "QVariant" } + Property { name: "closeListener"; type: "QVariant" } Property { name: "content"; type: "QObject"; isList: true; isReadonly: true } Signal { name: "initArgument" Parameter { name: "argument"; type: "QVariant" } } + Method { name: "destoryOnClose"; type: "QVariant" } Method { name: "showLoading" type: "QVariant" @@ -3741,7 +3793,6 @@ Module { type: "QVariant" Parameter { name: "path"; type: "QVariant" } } - Method { name: "deleteWindow"; type: "QVariant" } Method { name: "onResult" type: "QVariant" diff --git a/src/Qt6/imports/FluentUI/Controls/FluTreeView.qml b/src/Qt6/imports/FluentUI/Controls/FluTreeView.qml index 4f2160a0..019c98a2 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluTreeView.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluTreeView.qml @@ -202,7 +202,6 @@ Item { d.dropIndex = -1 return } - console.debug(index) if(tree_model.hitHasChildrenExpanded(index) && y>index*control.cellHeight+control.cellHeight/2){ d.dropIndex = index + 1 d.isDropTopArea = true diff --git a/src/Qt6/imports/FluentUI/Controls/FluWindow.qml b/src/Qt6/imports/FluentUI/Controls/FluWindow.qml index 540c2065..e208165b 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluWindow.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluWindow.qml @@ -18,9 +18,9 @@ Window { } property var _pageRegister property string _route - property var closeFunc: function(event){ + property var closeListener: function(event){ if(closeDestory){ - deleteWindow() + destoryOnClose() }else{ visible = false event.accepted = false @@ -30,12 +30,18 @@ Window { id:window color:"transparent" Component.onCompleted: { - helper.initWindow(window) + lifecycle.onCompleted(window) initArgument(argument) } + Component.onDestruction: { + lifecycle.onDestruction() + } + onVisibleChanged: { + lifecycle.onVisible(visible) + } Connections{ target: window - function onClosing(event){closeFunc(event)} + function onClosing(event){closeListener(event)} } Component{ id:com_background @@ -125,8 +131,11 @@ Window { } } } - WindowHelper{ - id:helper + WindowLifecycle{ + id:lifecycle + } + function destoryOnClose(){ + lifecycle.onDestoryOnClose() } function showLoading(text = "加载中...",cancel = true){ loader_loading.loadingText = text @@ -149,10 +158,7 @@ Window { infoBar.showError(text,duration,moremsg) } function registerForWindowResult(path){ - return helper.createRegister(window,path) - } - function deleteWindow(){ - FluApp.deleteWindow(window) + return lifecycle.createRegister(window,path) } function onResult(data){ if(_pageRegister){ diff --git a/src/WindowHelper.cpp b/src/WindowHelper.cpp deleted file mode 100644 index f4b2f6c6..00000000 --- a/src/WindowHelper.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "WindowHelper.h" - -#include "FluRegister.h" - -WindowHelper::WindowHelper(QObject *parent):QObject{parent}{ -} - -void WindowHelper::initWindow(QQuickWindow* window){ - this->window = window; -} - -QVariant WindowHelper::createRegister(QQuickWindow* window,const QString& path){ - FluRegister *p = new FluRegister(window); - p->from(window); - p->path(path); - return QVariant::fromValue(p); -} diff --git a/src/WindowHelper.h b/src/WindowHelper.h deleted file mode 100644 index e169d09d..00000000 --- a/src/WindowHelper.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef WINDOWHELPER_H -#define WINDOWHELPER_H - -#include -#include -#include -#include -#include -#include - -/** - * @brief The WindowHelper class - */ -class WindowHelper : public QObject -{ - Q_OBJECT - QML_NAMED_ELEMENT(WindowHelper) -public: - explicit WindowHelper(QObject *parent = nullptr); - Q_INVOKABLE void initWindow(QQuickWindow* window); - Q_INVOKABLE QVariant createRegister(QQuickWindow* window,const QString& path); -private: - QQuickWindow* window; -}; - -#endif // WINDOWHELPER_H diff --git a/src/WindowLifecycle.cpp b/src/WindowLifecycle.cpp new file mode 100644 index 00000000..91c1e6f7 --- /dev/null +++ b/src/WindowLifecycle.cpp @@ -0,0 +1,29 @@ +#include "WindowLifecycle.h" + +#include "FluApp.h" +#include "FluRegister.h" + +WindowLifecycle::WindowLifecycle(QObject *parent):QObject{parent}{ +} + +void WindowLifecycle::onCompleted(QQuickWindow* window){ + this->_window = window; + FluApp::getInstance()->addWindow(this->_window); +} + +void WindowLifecycle::onDestoryOnClose(){ + FluApp::getInstance()->removeWindow(this->_window); +} + +void WindowLifecycle::onDestruction(){ +} + +void WindowLifecycle::onVisible(bool visible){ +} + +QVariant WindowLifecycle::createRegister(QQuickWindow* window,const QString& path){ + FluRegister *p = new FluRegister(window); + p->from(window); + p->path(path); + return QVariant::fromValue(p); +} diff --git a/src/WindowLifecycle.h b/src/WindowLifecycle.h new file mode 100644 index 00000000..886ff631 --- /dev/null +++ b/src/WindowLifecycle.h @@ -0,0 +1,29 @@ +#ifndef WINDOWLIFECYCLE_H +#define WINDOWLIFECYCLE_H + +#include +#include +#include +#include +#include +#include + +/** + * @brief The WindowLifecycle class + */ +class WindowLifecycle : public QObject +{ + Q_OBJECT + QML_NAMED_ELEMENT(WindowLifecycle) +public: + explicit WindowLifecycle(QObject *parent = nullptr); + Q_INVOKABLE void onCompleted(QQuickWindow* window); + Q_INVOKABLE void onDestruction(); + Q_INVOKABLE void onVisible(bool visible); + Q_INVOKABLE void onDestoryOnClose(); + Q_INVOKABLE QVariant createRegister(QQuickWindow* window,const QString& path); +private: + QQuickWindow* _window; +}; + +#endif // WINDOWLIFECYCLE_H