From 8fc74fe43b3d9c5b360860d085271c77d2096735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E5=AD=90=E6=A5=9A=5Czhuzi?= Date: Sun, 17 Sep 2023 20:36:33 +0800 Subject: [PATCH] update --- example/qml-Qt6/App.qml | 9 +- example/qml-Qt6/component/CodeExpander.qml | 1 - example/qml-Qt6/global/ItemsOriginal.qml | 3 + example/qml-Qt6/page/T_Acrylic.qml | 2 +- example/qml-Qt6/page/T_Carousel.qml | 2 - example/qml-Qt6/page/T_Home.qml | 68 +-- example/qml-Qt6/page/T_InfoBar.qml | 2 +- example/qml-Qt6/page/T_QRCode.qml | 1 - example/qml-Qt6/page/T_Rectangle.qml | 10 +- example/qml-Qt6/page/T_Settings.qml | 38 +- example/qml-Qt6/page/T_TreeView.qml | 16 +- example/qml-Qt6/window/AboutWindow.qml | 2 +- example/qml-Qt6/window/MainWindow.qml | 6 +- example/qml/App.qml | 9 +- example/qml/component/CodeExpander.qml | 1 - example/qml/global/ItemsOriginal.qml | 3 + example/qml/page/T_Acrylic.qml | 2 +- example/qml/page/T_Carousel.qml | 2 - example/qml/page/T_Home.qml | 68 +-- example/qml/page/T_InfoBar.qml | 2 +- example/qml/page/T_QRCode.qml | 1 - example/qml/page/T_Rectangle.qml | 10 +- example/qml/page/T_Settings.qml | 38 +- example/qml/page/T_TreeView.qml | 16 +- example/qml/window/AboutWindow.qml | 2 +- example/qml/window/MainWindow.qml | 6 +- example/src/AppInfo.cpp | 6 +- example/src/AppInfo.h | 6 +- example/src/helper/SettingsHelper.cpp | 40 ++ example/src/helper/SettingsHelper.h | 33 ++ example/src/main.cpp | 23 +- example/src/singleton.h | 47 ++ src/FluRectangle.cpp | 31 ++ src/FluRectangle.h | 20 + src/FluTools.cpp | 9 + src/FluTools.h | 1 + src/FluTreeModel.cpp | 155 ++++++- src/FluTreeModel.h | 60 ++- src/FluViewModel.cpp | 3 +- src/FluViewModel.h | 6 +- src/FluentUI.cpp | 6 +- .../imports/FluentUI/Controls/FluAcrylic.qml | 2 +- .../imports/FluentUI/Controls/FluCarousel.qml | 2 +- src/Qt5/imports/FluentUI/Controls/FluClip.qml | 17 + .../imports/FluentUI/Controls/FluComboBox.qml | 2 +- .../imports/FluentUI/Controls/FluDivider.qml | 10 +- .../imports/FluentUI/Controls/FluExpander.qml | 3 +- src/Qt5/imports/FluentUI/Controls/FluItem.qml | 57 --- .../FluentUI/Controls/FluNavigationView.qml | 61 ++- .../FluentUI/Controls/FluProgressBar.qml | 2 +- .../FluentUI/Controls/FluProgressButton.qml | 2 +- .../FluentUI/Controls/FluRectangle.qml | 71 --- .../imports/FluentUI/Controls/FluSlider.qml | 24 +- .../imports/FluentUI/Controls/FluSpinBox.qml | 4 +- .../imports/FluentUI/Controls/FluTabView.qml | 6 +- .../FluentUI/Controls/FluTableView.qml | 12 +- .../Controls/FluTextBoxBackground.qml | 52 ++- .../FluentUI/Controls/FluToggleSwitch.qml | 13 +- .../imports/FluentUI/Controls/FluTreeItem.qml | 22 - .../imports/FluentUI/Controls/FluTreeView.qml | 395 ++++++++++------- src/Qt5/imports/FluentUI/qmldir | 4 +- src/Qt5/imports/fluentui.qrc | 4 +- .../imports/FluentUI/Controls/FluAcrylic.qml | 2 +- .../imports/FluentUI/Controls/FluCarousel.qml | 2 +- src/Qt6/imports/FluentUI/Controls/FluClip.qml | 19 + .../imports/FluentUI/Controls/FluComboBox.qml | 2 +- .../imports/FluentUI/Controls/FluDivider.qml | 10 +- .../imports/FluentUI/Controls/FluExpander.qml | 1 + src/Qt6/imports/FluentUI/Controls/FluItem.qml | 57 --- .../FluentUI/Controls/FluNavigationView.qml | 61 ++- .../FluentUI/Controls/FluProgressBar.qml | 2 +- .../FluentUI/Controls/FluProgressButton.qml | 2 +- .../FluentUI/Controls/FluRectangle.qml | 71 --- .../imports/FluentUI/Controls/FluSlider.qml | 24 +- .../imports/FluentUI/Controls/FluSpinBox.qml | 4 +- .../imports/FluentUI/Controls/FluTabView.qml | 6 +- .../FluentUI/Controls/FluTableView.qml | 12 +- .../Controls/FluTextBoxBackground.qml | 52 ++- .../FluentUI/Controls/FluToggleSwitch.qml | 13 +- .../imports/FluentUI/Controls/FluTreeItem.qml | 22 - .../imports/FluentUI/Controls/FluTreeView.qml | 405 +++++++++++------- 81 files changed, 1368 insertions(+), 930 deletions(-) create mode 100644 example/src/helper/SettingsHelper.cpp create mode 100644 example/src/helper/SettingsHelper.h create mode 100644 example/src/singleton.h create mode 100644 src/FluRectangle.cpp create mode 100644 src/FluRectangle.h create mode 100644 src/Qt5/imports/FluentUI/Controls/FluClip.qml delete mode 100644 src/Qt5/imports/FluentUI/Controls/FluItem.qml delete mode 100644 src/Qt5/imports/FluentUI/Controls/FluRectangle.qml delete mode 100644 src/Qt5/imports/FluentUI/Controls/FluTreeItem.qml create mode 100644 src/Qt6/imports/FluentUI/Controls/FluClip.qml delete mode 100644 src/Qt6/imports/FluentUI/Controls/FluItem.qml delete mode 100644 src/Qt6/imports/FluentUI/Controls/FluRectangle.qml delete mode 100644 src/Qt6/imports/FluentUI/Controls/FluTreeItem.qml diff --git a/example/qml-Qt6/App.qml b/example/qml-Qt6/App.qml index 70bc1c7a..71d27b45 100644 --- a/example/qml-Qt6/App.qml +++ b/example/qml-Qt6/App.qml @@ -8,6 +8,13 @@ Window { id: app flags: Qt.SplashScreen + Connections{ + target: FluTheme + function onDarkModeChanged(){ + SettingsHelper.saveDarkMode(FluTheme.darkMode) + } + } + FluHttpInterceptor{ id:interceptor function onIntercept(request){ @@ -26,7 +33,7 @@ Window { Component.onCompleted: { FluApp.init(app) - FluTheme.darkMode = FluThemeType.System + FluTheme.darkMode = SettingsHelper.getDarkMode() FluTheme.enableAnimation = true FluApp.routes = { "/":"qrc:/example/qml/window/MainWindow.qml", diff --git a/example/qml-Qt6/component/CodeExpander.qml b/example/qml-Qt6/component/CodeExpander.qml index 11d80eb7..0f54225b 100644 --- a/example/qml-Qt6/component/CodeExpander.qml +++ b/example/qml-Qt6/component/CodeExpander.qml @@ -80,7 +80,6 @@ FluExpander{ "FluIcon", "FluIconButton", "FluInfoBar", - "FluItem", "FluMediaPlayer", "FluMenu", "FluMenuItem", diff --git a/example/qml-Qt6/global/ItemsOriginal.qml b/example/qml-Qt6/global/ItemsOriginal.qml index 92f5ee53..b2d9afa5 100644 --- a/example/qml-Qt6/global/ItemsOriginal.qml +++ b/example/qml-Qt6/global/ItemsOriginal.qml @@ -477,6 +477,9 @@ FluObject{ } function getSearchData(){ + if(!navigationView){ + return + } var arr = [] var items = navigationView.getItems(); for(var i=0;i { + const dig = (path = '0', level = 3) => { const list = []; - for (let i = 0; i < 10; i += 1) { + for (let i = 0; i < 8; i += 1) { const key = `${path}-${i}`; const treeNode = { title: key, @@ -48,7 +48,7 @@ FluScrollablePage { Layout.fillWidth: true Layout.topMargin: 10 paddings: 10 - height: 400 + height: 640 Item{ anchors.fill: tree_view FluShadow{} @@ -61,6 +61,7 @@ FluScrollablePage { left:parent.left bottom:parent.bottom } + draggable:switch_draggable.checked showLine: switch_showline.checked Component.onCompleted: { var data = treeData() @@ -68,6 +69,7 @@ FluScrollablePage { } } Column{ + spacing: 15 anchors{ top:parent.top topMargin: 10 @@ -86,7 +88,7 @@ FluScrollablePage { id:slider_width value: 200 from: 160 - to:320 + to:460 } } @@ -95,6 +97,12 @@ FluScrollablePage { text:"showLine" checked: true } + + FluToggleSwitch{ + id:switch_draggable + text:"draggable" + checked: false + } } } CodeExpander{ diff --git a/example/qml-Qt6/window/AboutWindow.qml b/example/qml-Qt6/window/AboutWindow.qml index 862923dd..a812e5f0 100644 --- a/example/qml-Qt6/window/AboutWindow.qml +++ b/example/qml-Qt6/window/AboutWindow.qml @@ -35,7 +35,7 @@ CustomWindow { } } FluText{ - text:"v%1".arg(appInfo.version) + text:"v%1".arg(AppInfo.version) font: FluTextStyle.Body Layout.alignment: Qt.AlignBottom } diff --git a/example/qml-Qt6/window/MainWindow.qml b/example/qml-Qt6/window/MainWindow.qml index 2159be8c..d264fb99 100644 --- a/example/qml-Qt6/window/MainWindow.qml +++ b/example/qml-Qt6/window/MainWindow.qml @@ -318,7 +318,7 @@ CustomWindow { property string body id:dialog_update title:"升级提示" - message:"FluentUI目前最新版本 "+ newVerson +" -- 当前应用版本 "+appInfo.version+" \n现在是否去下载新版本?\n\n更新内容:\n"+body + message:"FluentUI目前最新版本 "+ newVerson +" -- 当前应用版本 "+AppInfo.version+" \n现在是否去下载新版本?\n\n更新内容:\n"+body buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton negativeText: "取消" positiveText:"确定" @@ -340,9 +340,9 @@ CustomWindow { onSuccess: (result)=>{ var data = JSON.parse(result) - console.debug("current version "+appInfo.version) + console.debug("current version "+AppInfo.version) console.debug("new version "+data.tag_name) - if(data.tag_name !== appInfo.version){ + if(data.tag_name !== AppInfo.version){ dialog_update.newVerson = data.tag_name dialog_update.body = data.body dialog_update.open() diff --git a/example/qml/App.qml b/example/qml/App.qml index 0060ec77..f9d979d9 100644 --- a/example/qml/App.qml +++ b/example/qml/App.qml @@ -8,6 +8,13 @@ Window { id: app flags: Qt.SplashScreen + Connections{ + target: FluTheme + function onDarkModeChanged(){ + SettingsHelper.saveDarkMode(FluTheme.darkMode) + } + } + FluHttpInterceptor{ id:interceptor function onIntercept(request){ @@ -26,7 +33,7 @@ Window { Component.onCompleted: { FluApp.init(app) - FluTheme.darkMode = FluThemeType.System + FluTheme.darkMode = SettingsHelper.getDarkMode() FluTheme.enableAnimation = true FluApp.routes = { "/":"qrc:/example/qml/window/MainWindow.qml", diff --git a/example/qml/component/CodeExpander.qml b/example/qml/component/CodeExpander.qml index 331f5889..0227fa10 100644 --- a/example/qml/component/CodeExpander.qml +++ b/example/qml/component/CodeExpander.qml @@ -80,7 +80,6 @@ FluExpander{ "FluIcon", "FluIconButton", "FluInfoBar", - "FluItem", "FluMediaPlayer", "FluMenu", "FluMenuItem", diff --git a/example/qml/global/ItemsOriginal.qml b/example/qml/global/ItemsOriginal.qml index f5e6d534..884fb44a 100644 --- a/example/qml/global/ItemsOriginal.qml +++ b/example/qml/global/ItemsOriginal.qml @@ -477,6 +477,9 @@ FluObject{ } function getSearchData(){ + if(!navigationView){ + return + } var arr = [] var items = navigationView.getItems(); for(var i=0;i { + const dig = (path = '0', level = 3) => { const list = []; - for (let i = 0; i < 10; i += 1) { + for (let i = 0; i < 8; i += 1) { const key = `${path}-${i}`; const treeNode = { title: key, @@ -49,7 +49,7 @@ FluScrollablePage { Layout.fillWidth: true Layout.topMargin: 10 paddings: 10 - height: 400 + height: 420 Item{ anchors.fill: tree_view FluShadow{} @@ -62,6 +62,7 @@ FluScrollablePage { left:parent.left bottom:parent.bottom } + draggable:switch_draggable.checked showLine: switch_showline.checked Component.onCompleted: { var data = treeData() @@ -69,6 +70,7 @@ FluScrollablePage { } } Column{ + spacing: 15 anchors{ top:parent.top topMargin: 10 @@ -87,7 +89,7 @@ FluScrollablePage { id:slider_width value: 200 from: 160 - to:320 + to:460 } } @@ -96,6 +98,12 @@ FluScrollablePage { text:"showLine" checked: true } + + FluToggleSwitch{ + id:switch_draggable + text:"draggable" + checked: false + } } } CodeExpander{ diff --git a/example/qml/window/AboutWindow.qml b/example/qml/window/AboutWindow.qml index aff6de8c..ccef8216 100644 --- a/example/qml/window/AboutWindow.qml +++ b/example/qml/window/AboutWindow.qml @@ -36,7 +36,7 @@ CustomWindow { } } FluText{ - text:"v%1".arg(appInfo.version) + text:"v%1".arg(AppInfo.version) font: FluTextStyle.Body Layout.alignment: Qt.AlignBottom } diff --git a/example/qml/window/MainWindow.qml b/example/qml/window/MainWindow.qml index e60dc23b..5b8d6f68 100644 --- a/example/qml/window/MainWindow.qml +++ b/example/qml/window/MainWindow.qml @@ -321,7 +321,7 @@ CustomWindow { property string body id:dialog_update title:"升级提示" - message:"FluentUI目前最新版本 "+ newVerson +" -- 当前应用版本 "+appInfo.version+" \n现在是否去下载新版本?\n\n更新内容:\n"+body + message:"FluentUI目前最新版本 "+ newVerson +" -- 当前应用版本 "+AppInfo.version+" \n现在是否去下载新版本?\n\n更新内容:\n"+body buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton negativeText: "取消" positiveText:"确定" @@ -343,9 +343,9 @@ CustomWindow { onSuccess: (result)=>{ var data = JSON.parse(result) - console.debug("current version "+appInfo.version) + console.debug("current version "+AppInfo.version) console.debug("new version "+data.tag_name) - if(data.tag_name !== appInfo.version){ + if(data.tag_name !== AppInfo.version){ dialog_update.newVerson = data.tag_name dialog_update.body = data.body dialog_update.open() diff --git a/example/src/AppInfo.cpp b/example/src/AppInfo.cpp index 7eb78036..2cafc4ef 100644 --- a/example/src/AppInfo.cpp +++ b/example/src/AppInfo.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "lang/En.h" #include "lang/Zh.h" #include "Version.h" @@ -20,7 +21,6 @@ void AppInfo::init(QQmlApplicationEngine *engine){ QObject::connect(this,&AppInfo::langChanged,this,[=]{ context->setContextProperty("lang",this->lang()); }); - context->setContextProperty("appInfo",this); } void AppInfo::changeLang(const QString& locale){ @@ -35,3 +35,7 @@ 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 3372a0e5..a4a8812b 100644 --- a/example/src/AppInfo.h +++ b/example/src/AppInfo.h @@ -5,16 +5,20 @@ #include #include "lang/Lang.h" #include "stdafx.h" +#include "singleton.h" class AppInfo : public QObject { Q_OBJECT Q_PROPERTY_AUTO(QString,version) Q_PROPERTY_AUTO(Lang*,lang) -public: +private: explicit AppInfo(QObject *parent = nullptr); +public: + SINGLETONG(AppInfo) void init(QQmlApplicationEngine *engine); Q_INVOKABLE void changeLang(const QString& locale); + Q_INVOKABLE void restart(); }; #endif // APPINFO_H diff --git a/example/src/helper/SettingsHelper.cpp b/example/src/helper/SettingsHelper.cpp new file mode 100644 index 00000000..eea152ba --- /dev/null +++ b/example/src/helper/SettingsHelper.cpp @@ -0,0 +1,40 @@ +#include "SettingsHelper.h" + +#include + +SettingsHelper::SettingsHelper(QObject *parent) : QObject(parent) +{ + +} + +SettingsHelper::~SettingsHelper() = default; + +void SettingsHelper::save(const QString& key,QVariant val) +{ + QByteArray data = {}; + QDataStream stream(&data, QIODevice::WriteOnly); + stream.setVersion(QDataStream::Qt_5_6); + stream << val; + m_settings->setValue(key, data); +} + +QVariant SettingsHelper::get(const QString& key){ + const QByteArray data = m_settings->value(key).toByteArray(); + if (data.isEmpty()) { + return {}; + } + QDataStream stream(data); + stream.setVersion(QDataStream::Qt_5_6); + QVariant val; + stream >> val; + return val; +} + +void SettingsHelper::init(char *argv[]){ + auto applicationPath = QString::fromStdString(argv[0]); + const QFileInfo fileInfo(applicationPath); + const QString iniFileName = fileInfo.completeBaseName() + ".ini"; + const QString iniFilePath = fileInfo.dir().path() + "/" + iniFileName; + qDebug()< +#include +#include +#include +#include +#include +#include +#include "src/singleton.h" + +class SettingsHelper : public QObject +{ + Q_OBJECT +private: + explicit SettingsHelper(QObject* parent = nullptr); +public: + SINGLETONG(SettingsHelper) + ~SettingsHelper() override; + void init(char *argv[]); + Q_INVOKABLE void saveRender(const QString& render){save("render",render);} + Q_INVOKABLE QString getReander(){return get("render").toString();} + Q_INVOKABLE void saveDarkMode(int darkModel){save("darkMode",darkModel);} + Q_INVOKABLE int getDarkMode(){return get("darkMode").toInt(0);} +private: + void save(const QString& key,QVariant val); + QVariant get(const QString& key); +private: + QScopedPointer m_settings; +}; + +#endif // SETTINGSHELPER_H diff --git a/example/src/main.cpp b/example/src/main.cpp index e8e04832..1a5ca868 100644 --- a/example/src/main.cpp +++ b/example/src/main.cpp @@ -13,6 +13,8 @@ #include "src/component/CircularReveal.h" #include "src/component/FileWatcher.h" #include "src/component/FpsItem.h" +#include "src/helper/SettingsHelper.h" + #ifdef FLUENTUI_BUILD_STATIC_LIB #if (QT_VERSION > QT_VERSION_CHECK(6, 2, 0)) Q_IMPORT_QML_PLUGIN(FluentUIPlugin) @@ -22,8 +24,9 @@ Q_IMPORT_QML_PLUGIN(FluentUIPlugin) FRAMELESSHELPER_USE_NAMESPACE - int main(int argc, char *argv[]) +int main(int argc, char *argv[]) { + SettingsHelper::getInstance()->init(argv); #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); @@ -36,6 +39,13 @@ FRAMELESSHELPER_USE_NAMESPACE QGuiApplication::setOrganizationName("ZhuZiChu"); QGuiApplication::setOrganizationDomain("https://zhuzichu520.github.io"); QGuiApplication::setApplicationName("FluentUI"); + if(SettingsHelper::getInstance()->getReander()=="software"){ +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + QQuickWindow::setGraphicsApi(QSGRendererInterface::Software); +#elif (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software); +#endif + } QGuiApplication app(argc, argv); FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial); FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow); @@ -48,8 +58,10 @@ FRAMELESSHELPER_USE_NAMESPACE #ifdef Q_OS_MACOS FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur,false); #endif - AppInfo* appInfo = new AppInfo(); QQmlApplicationEngine engine; + AppInfo::getInstance()->init(&engine); + engine.rootContext()->setContextProperty("AppInfo",AppInfo::getInstance()); + engine.rootContext()->setContextProperty("SettingsHelper",SettingsHelper::getInstance()); FramelessHelper::Quick::registerTypes(&engine); #ifdef FLUENTUI_BUILD_STATIC_LIB FluentUI::getInstance()->registerTypes(&engine); @@ -58,7 +70,6 @@ FRAMELESSHELPER_USE_NAMESPACE qmlRegisterType("example", 1, 0, "CircularReveal"); qmlRegisterType("example", 1, 0, "FileWatcher"); qmlRegisterType("example", 1, 0, "FpsItem"); - appInfo->init(&engine); const QUrl url(QStringLiteral("qrc:/example/qml/App.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { @@ -66,5 +77,9 @@ FRAMELESSHELPER_USE_NAMESPACE QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); - return app.exec(); + const int exec = QGuiApplication::exec(); + if (exec == 931) { + QProcess::startDetached(qApp->applicationFilePath(), QStringList()); + } + return exec; } diff --git a/example/src/singleton.h b/example/src/singleton.h new file mode 100644 index 00000000..ef685f96 --- /dev/null +++ b/example/src/singleton.h @@ -0,0 +1,47 @@ +#ifndef SINGLETON_H +#define SINGLETON_H + +#include +#include +#include +#include + +template +class Singleton { +public: + static T* getInstance(); + + Singleton(const Singleton& other) = delete; + Singleton& operator=(const Singleton& other) = delete; + +private: + static std::mutex mutex; + static T* instance; +}; + +template +std::mutex Singleton::mutex; +template +T* Singleton::instance; +template +T* Singleton::getInstance() { + if (instance == nullptr) { + std::lock_guard locker(mutex); + if (instance == nullptr) { + instance = new T(); + } + } + return instance; +} + +#define SINGLETONG(Class) \ +private: \ + friend class Singleton; \ + friend struct QScopedPointerDeleter; \ + \ + public: \ + static Class* getInstance() { \ + return Singleton::getInstance(); \ +} + +#endif // SINGLETON_H diff --git a/src/FluRectangle.cpp b/src/FluRectangle.cpp new file mode 100644 index 00000000..9eb07684 --- /dev/null +++ b/src/FluRectangle.cpp @@ -0,0 +1,31 @@ +#include "FluRectangle.h" + +#include +#include +#include + +FluRectangle::FluRectangle(QQuickItem* parent) : QQuickPaintedItem(parent){ + setFlag(ItemHasContents, true); + color(QColor(255,255,255,255)); + radius({0,0,0,0}); + connect(this,&FluRectangle::colorChanged,this,[=]{update();}); + connect(this,&FluRectangle::radiusChanged,this,[=]{update();}); +} + +void FluRectangle::paint(QPainter* painter){ + painter->save(); + painter->setRenderHint(QPainter::Antialiasing); + QPainterPath path; + QRectF rect = boundingRect(); + path.moveTo(rect.bottomRight() - QPointF(0, _radius[2])); + path.lineTo(rect.topRight() + QPointF(0, _radius[1])); + path.arcTo(QRectF(QPointF(rect.topRight() - QPointF(_radius[1] * 2, 0)), QSize(_radius[1] * 2, _radius[1] * 2)), 0, 90); + path.lineTo(rect.topLeft() + QPointF(_radius[0], 0)); + path.arcTo(QRectF(QPointF(rect.topLeft()), QSize(_radius[0] * 2, _radius[0] * 2)), 90, 90); + path.lineTo(rect.bottomLeft() - QPointF(0, _radius[3])); + path.arcTo(QRectF(QPointF(rect.bottomLeft() - QPointF(0, _radius[3] * 2)), QSize(_radius[3] * 2, _radius[3] * 2)), 180, 90); + path.lineTo(rect.bottomLeft() + QPointF(_radius[2], 0)); + path.arcTo(QRectF(QPointF(rect.bottomRight() - QPointF(_radius[2] * 2, _radius[2] * 2)), QSize(_radius[2] * 2, _radius[2] * 2)), 270, 90); + painter->fillPath(path,_color); + painter->restore(); +} diff --git a/src/FluRectangle.h b/src/FluRectangle.h new file mode 100644 index 00000000..51e87ebe --- /dev/null +++ b/src/FluRectangle.h @@ -0,0 +1,20 @@ +#ifndef FLURECTANGLE_H +#define FLURECTANGLE_H + +#include +#include +#include +#include "stdafx.h" + +class FluRectangle : public QQuickPaintedItem +{ + Q_OBJECT + Q_PROPERTY_AUTO(QColor,color) + Q_PROPERTY_AUTO(QList,radius) + QML_NAMED_ELEMENT(FluRectangle) +public: + explicit FluRectangle(QQuickItem *parent = nullptr); + void paint(QPainter* painter) override; +}; + +#endif // FLURECTANGLE_H diff --git a/src/FluTools.cpp b/src/FluTools.cpp index 4f742f03..573732be 100644 --- a/src/FluTools.cpp +++ b/src/FluTools.cpp @@ -9,10 +9,15 @@ #include #include #include +#include #include #include +#include +#include + FluTools::FluTools(QObject *parent):QObject{parent}{ + } void FluTools::clipText(const QString& text){ @@ -159,3 +164,7 @@ void FluTools::showFileInFolder(QString path){ QProcess::execute("/usr/bin/osascript", {"-e", "tell application \"Finder\" to activate"}); #endif } + +bool FluTools::isSoftware(){ + return QQuickWindow::sceneGraphBackend() == "software"; +} diff --git a/src/FluTools.h b/src/FluTools.h index ad370f29..a1101feb 100644 --- a/src/FluTools.h +++ b/src/FluTools.h @@ -46,6 +46,7 @@ public: Q_INVOKABLE bool removeDir(QString dirPath); Q_INVOKABLE bool removeFile(QString filePath); Q_INVOKABLE void showFileInFolder(QString path); + Q_INVOKABLE bool isSoftware(); }; #endif // FLUTOOLS_H diff --git a/src/FluTreeModel.cpp b/src/FluTreeModel.cpp index 933f97ec..d73b5f10 100644 --- a/src/FluTreeModel.cpp +++ b/src/FluTreeModel.cpp @@ -2,10 +2,16 @@ #include +Node::Node(QObject *parent) + : QObject{parent} +{ + +} + FluTreeModel::FluTreeModel(QObject *parent) : QAbstractTableModel{parent} { - + dataSourceSize(0); } int FluTreeModel::rowCount(const QModelIndex &parent) const { @@ -27,35 +33,162 @@ QVariant FluTreeModel::data(const QModelIndex &index, int role) const { }; QHash FluTreeModel::roleNames() const { - return { {Qt::DisplayRole, "display"} }; + return { {Qt::DisplayRole, "modelData"} }; }; -void FluTreeModel::setData(QList data){ +void FluTreeModel::setData(QList data){ beginResetModel(); _rows = data; endResetModel(); } void FluTreeModel::removeRows(int row,int count){ - if (row < 0 || row + count > _rows.size()) + if (row < 0 || row + count > _rows.size() || count==0) return; - beginRemoveRows(QModelIndex(),row, row + count - 1); +// beginRemoveRows(QModelIndex(),row, row + count - 1); for (int i = 0; i < count; ++i) { _rows.removeAt(row); } - endRemoveRows(); +// endRemoveRows(); } -void FluTreeModel::insertRows(int row,QList data){ - if (row < 0 || row > _rows.size()) - return; - beginInsertRows(QModelIndex(), row, row + data.size() - 1); +void FluTreeModel::insertRows(int row,QList data){ + if (row < 0 || row > _rows.size() || data.size() == 0) + return;; +// beginInsertRows(QModelIndex(), row, row + data.size() - 1); for (const auto& item : data) { _rows.insert(row++, item); } - endInsertRows(); +// endInsertRows(); } QObject* FluTreeModel::getRow(int row){ return _rows.at(row); } + +void FluTreeModel::setDataSource(QList> data){ + _dataSource.clear(); + if(_root){ + delete _root; + _root = nullptr; + } + _root = new Node(this); + std::reverse(data.begin(), data.end()); + while (data.count() > 0) { + auto item = data.at(data.count()-1); + data.pop_back(); + Node* node = new Node(this); + node->_title = item.value("title").toString(); + node->_key = item.value("key").toString(); + node->_depth = item.value("__depth").toInt(); + node->_parent = item.value("__parent").value(); + node->_isExpanded = true; + if(node->_parent){ + node->_parent->_children.append(node); + }else{ + node->_parent = _root; + _root->_children.append(node); + } + _dataSource.append(node); + if (item.contains("children")) { + QList children = item.value("children").toList(); + if(!children.isEmpty()){ + std::reverse(children.begin(), children.end()); + foreach (auto c, children) { + auto child = c.toMap(); + child.insert("__depth",item.value("__depth").toInt(0)+1); + child.insert("__parent",QVariant::fromValue(node)); + data.append(child); + } + } + } + } + beginResetModel(); + _rows = _dataSource; + endResetModel(); + dataSourceSize(_dataSource.size()); +} + +void FluTreeModel::collapse(int row){ + if(!_rows.at(row)->_isExpanded){ + return; + } + _rows.at(row)->_isExpanded = false; + Q_EMIT dataChanged(index(row,0),index(row,0)); + auto modelData = _rows.at(row); + int removeCount = 0; + for(int i=row+1;i<_rows.count();i++){ + auto obj = _rows[i]; + if(obj->_depth<=modelData->_depth){ + break; + } + removeCount = removeCount + 1; + } + removeRows(row+1,removeCount); + Q_EMIT dataChanged(index(row+1,0),index(row+1+removeCount,0)); +} + +void FluTreeModel::expand(int row){ + if(_rows.at(row)->_isExpanded){ + return; + } + _rows.at(row)->_isExpanded = true; + Q_EMIT dataChanged(index(row,0),index(row,0)); + auto modelData = _rows.at(row); + QList insertData; + QList stack = modelData->_children; + std::reverse(stack.begin(), stack.end()); + while (stack.count() > 0) { + auto item = stack.at(stack.count()-1); + stack.pop_back(); + if(item->isShown()){ + insertData.append(item); + } + QList children = item->_children; + if(!children.isEmpty()){ + std::reverse(children.begin(), children.end()); + foreach (auto c, children) { + stack.append(c); + } + } + } + insertRows(row+1,insertData); + Q_EMIT dataChanged(index(row+1,0),index(row+1+insertData.count(),0)); +} + +void FluTreeModel::dragAnddrop(int dragIndex,int dropIndex){ + if(dragIndex == dropIndex+1){ + return; + } + auto dragItem = _rows[dragIndex]; + auto dropItem = _rows[dropIndex]; + if (!beginMoveRows(QModelIndex(), dragIndex, dragIndex, QModelIndex(), dropIndex > dragIndex ? dropIndex+1 : dropIndex)) { + return; + } + if(dragItem->_parent == dropItem->_parent){ + if(dragItem->hasChildren()){ + + }else{ + QList* children = &(dragItem->_parent->_children); + int srcIndex = children->indexOf(dragItem); + int destIndex = children->indexOf(dropItem); + children->move(srcIndex,destIndex>srcIndex? destIndex : destIndex +1); + _rows.move(dragIndex,dropIndex>dragIndex? dropIndex : dropIndex+1); + } + }else{ + if(dragItem->hasChildren()){ + + }else{ + QList* srcChildren = &(dragItem->_parent->_children); + QList* destChildren = &(dropItem->_parent->_children); + int srcIndex = srcChildren->indexOf(dragItem); + int destIndex = destChildren->indexOf(dropItem); + dragItem->_depth = dropItem->_depth; + dragItem->_parent = dropItem->_parent; + srcChildren->removeAt(srcIndex); + destChildren->insert(destIndex+1,dragItem); + _rows.move(dragIndex,dropIndex>dragIndex? dropIndex : dropIndex+1); + } + } + endMoveRows(); +} diff --git a/src/FluTreeModel.h b/src/FluTreeModel.h index 2d1c307e..e28ef6f3 100644 --- a/src/FluTreeModel.h +++ b/src/FluTreeModel.h @@ -3,11 +3,59 @@ #include #include +#include #include +#include "stdafx.h" + +class Node : public QObject{ + Q_OBJECT + Q_PROPERTY(QString key READ key CONSTANT) + Q_PROPERTY(QString title READ title CONSTANT) + Q_PROPERTY(int depth READ depth CONSTANT) + Q_PROPERTY(bool isExpanded READ isExpanded CONSTANT) +public: + explicit Node(QObject *parent = nullptr); + Q_INVOKABLE QString key(){return _key;}; + Q_INVOKABLE QString title(){return _title;}; + Q_INVOKABLE int depth(){return _depth;}; + Q_INVOKABLE bool isExpanded(){return _isExpanded;}; + Q_INVOKABLE bool hasChildren(){ return !_children.isEmpty();}; + Q_INVOKABLE bool hideLineFooter(){ + if(_parent){ + auto childIndex = _parent->_children.indexOf(this); + if(childIndex==_parent->_children.count()-1){ + return true; + } + if(_parent->_children.at(childIndex+1)->hasChildren()){ + return true; + } + return false; + } + return false; + }; + bool isShown(){ + auto p = _parent; + while (p) { + if(!p->_isExpanded){ + return false; + } + p = p->_parent; + } + return true; + } +public: + QString _key=""; + QString _title=""; + int _depth=0; + bool _isExpanded=true; + QList _children; + Node* _parent = nullptr; +}; class FluTreeModel : public QAbstractTableModel { Q_OBJECT + Q_PROPERTY_AUTO(int,dataSourceSize) QML_NAMED_ELEMENT(FluTreeModel) QML_ADDED_IN_MINOR_VERSION(1) public: @@ -17,11 +65,17 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QHash roleNames() const override; Q_INVOKABLE void removeRows(int row,int count); - Q_INVOKABLE void insertRows(int row,QList data); + Q_INVOKABLE void insertRows(int row,QList data); Q_INVOKABLE QObject* getRow(int row); - Q_INVOKABLE void setData(QList data); + Q_INVOKABLE void setData(QList data); + Q_INVOKABLE void setDataSource(QList> data); + Q_INVOKABLE void collapse(int row); + Q_INVOKABLE void expand(int row); + Q_INVOKABLE void dragAnddrop(int dragIndex,int dropIndex); private: - QList _rows; + QList _rows; + QList _dataSource; + Node* _root = nullptr; }; #endif // FLUTREEMODEL_H diff --git a/src/FluViewModel.cpp b/src/FluViewModel.cpp index d578992d..abb6dc1f 100644 --- a/src/FluViewModel.cpp +++ b/src/FluViewModel.cpp @@ -57,8 +57,9 @@ void PropertyObserver::_propertyChange(){ } FluViewModel::FluViewModel(QObject *parent):QObject{parent}{ - ViewModelManager::getInstance()->insertViewModel(this); scope(FluViewModelType::Scope::Window); + target(nullptr); + ViewModelManager::getInstance()->insertViewModel(this); } FluViewModel::~FluViewModel(){ diff --git a/src/FluViewModel.h b/src/FluViewModel.h index e440d031..924372d1 100644 --- a/src/FluViewModel.h +++ b/src/FluViewModel.h @@ -31,7 +31,7 @@ public: QString getKey(); private: QObject* _window = nullptr; - QString _key; + QString _key = ""; }; class PropertyObserver: public QObject{ @@ -42,9 +42,9 @@ public: private: Q_SLOT void _propertyChange(); private: - QString _name; + QString _name = ""; QQmlProperty _property; - QObject* _model; + QObject* _model = nullptr; }; diff --git a/src/FluentUI.cpp b/src/FluentUI.cpp index 0efeaf75..7d9536c7 100644 --- a/src/FluentUI.cpp +++ b/src/FluentUI.cpp @@ -16,6 +16,7 @@ #include "FluTreeModel.h" #include "FluViewModel.h" #include "Screenshot.h" +#include "FluRectangle.h" #include "QRCode.h" int major = 1; @@ -55,6 +56,7 @@ void FluentUI::registerTypes(const char *uri){ qmlRegisterType(uri,major,minor,"FluEvent"); qmlRegisterType(uri,major,minor,"FluViewModel"); qmlRegisterType(uri,major,minor,"FluTreeModel"); + qmlRegisterType(uri,major,minor,"FluRectangle"); 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"); @@ -93,7 +95,6 @@ void FluentUI::registerTypes(const char *uri){ qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluIconButton.qml"),uri,major,minor,"FluIconButton"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluImage.qml"),uri,major,minor,"FluImage"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluInfoBar.qml"),uri,major,minor,"FluInfoBar"); - qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluItem.qml"),uri,major,minor,"FluItem"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluItemDelegate.qml"),uri,major,minor,"FluItemDelegate"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMenu.qml"),uri,major,minor,"FluMenu"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluMenuBar.qml"),uri,major,minor,"FluMenuBar"); @@ -120,7 +121,6 @@ void FluentUI::registerTypes(const char *uri){ qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRadioButton.qml"),uri,major,minor,"FluRadioButton"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRadioButtons.qml"),uri,major,minor,"FluRadioButtons"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRatingControl.qml"),uri,major,minor,"FluRatingControl"); - qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRectangle.qml"),uri,major,minor,"FluRectangle"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRemoteLoader.qml"),uri,major,minor,"FluRemoteLoader"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluScreenshot.qml"),uri,major,minor,"FluScreenshot"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluScrollBar.qml"),uri,major,minor,"FluScrollBar"); @@ -150,7 +150,7 @@ void FluentUI::registerTypes(const char *uri){ 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/FluLoadingButton.qml"),uri,major,minor,"FluLoadingButton"); - qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTreeItem.qml"),uri,major,minor,"FluTreeItem"); + qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluClip.qml"),uri,major,minor,"FluClip"); 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"); diff --git a/src/Qt5/imports/FluentUI/Controls/FluAcrylic.qml b/src/Qt5/imports/FluentUI/Controls/FluAcrylic.qml index c4100d03..da6af5c6 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluAcrylic.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluAcrylic.qml @@ -2,7 +2,7 @@ import QtQuick 2.15 import QtGraphicalEffects 1.15 import FluentUI 1.0 -FluItem { +Item { id: control property color tintColor: Qt.rgba(1,1,1,1) property real tintOpacity: 0.65 diff --git a/src/Qt5/imports/FluentUI/Controls/FluCarousel.qml b/src/Qt5/imports/FluentUI/Controls/FluCarousel.qml index f4ae4c36..1418f493 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluCarousel.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluCarousel.qml @@ -2,7 +2,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import FluentUI 1.0 -FluItem { +Item { property bool autoPlay: true property int loopTime: 2000 property var model diff --git a/src/Qt5/imports/FluentUI/Controls/FluClip.qml b/src/Qt5/imports/FluentUI/Controls/FluClip.qml new file mode 100644 index 00000000..18920010 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluClip.qml @@ -0,0 +1,17 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtGraphicalEffects 1.0 +import FluentUI 1.0 + +FluRectangle { + id:control + color: "#00000000" + layer.enabled: !FluTools.isSoftware() + layer.effect: OpacityMask{ + maskSource: FluRectangle{ + radius: control.radius + width: control.width + height: control.height + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluComboBox.qml b/src/Qt5/imports/FluentUI/Controls/FluComboBox.qml index bce5ba64..55a76f97 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluComboBox.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluComboBox.qml @@ -62,7 +62,7 @@ ComboBox { bottomInset:1 rightInset:1 background: FluTextBoxBackground{ - border.width: 0 + borderWidth: 0 inputItem: contentItem } Component.onCompleted: { diff --git a/src/Qt5/imports/FluentUI/Controls/FluDivider.qml b/src/Qt5/imports/FluentUI/Controls/FluDivider.qml index 34fe3892..a8e35aba 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluDivider.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluDivider.qml @@ -5,14 +5,14 @@ import FluentUI 1.0 Rectangle { property real spacing property alias separatorHeight:separator.height - - id:root + id:control color:Qt.rgba(0,0,0,0) height: spacing*2+separator.height Rectangle{ id:separator - color: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1) - width:parent.width - anchors.centerIn: parent + clip: true + color: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1) + width:parent.width + anchors.centerIn: parent } } diff --git a/src/Qt5/imports/FluentUI/Controls/FluExpander.qml b/src/Qt5/imports/FluentUI/Controls/FluExpander.qml index d36b81e2..9aa00cde 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluExpander.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluExpander.qml @@ -70,14 +70,15 @@ Item { left: layout_header.left } width: parent.width - clip: true visible: contentHeight+container.y !== 0 height: contentHeight+container.y + clip: true Rectangle{ id:container width: parent.width height: parent.height 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) y: -contentHeight diff --git a/src/Qt5/imports/FluentUI/Controls/FluItem.qml b/src/Qt5/imports/FluentUI/Controls/FluItem.qml deleted file mode 100644 index 51074233..00000000 --- a/src/Qt5/imports/FluentUI/Controls/FluItem.qml +++ /dev/null @@ -1,57 +0,0 @@ -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtGraphicalEffects 1.15 - -Item{ - property var radius:[0,0,0,0] - default property alias contentItem: container.data - id:control - Item{ - id:container - width: control.width - height: control.height - opacity: 0 - } - onWidthChanged: { - canvas.requestPaint() - } - onHeightChanged: { - canvas.requestPaint() - } - onRadiusChanged: { - canvas.requestPaint() - } - Canvas { - id: canvas - anchors.fill: parent - visible: false - onPaint: { - var ctx = getContext("2d"); - var x = 0; - var y = 0; - var w = control.width; - var h = control.height; - ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.save(); - ctx.beginPath(); - ctx.moveTo(x + radius[0], y); - ctx.lineTo(x + w - radius[1], y); - ctx.arcTo(x + w, y, x + w, y + radius[1], radius[1]); - ctx.lineTo(x + w, y + h - radius[2]); - ctx.arcTo(x + w, y + h, x + w - radius[2], y + h, radius[2]); - ctx.lineTo(x + radius[3], y + h); - ctx.arcTo(x, y + h, x, y + h - radius[3], radius[3]); - ctx.lineTo(x, y + radius[0]); - ctx.arcTo(x, y, x + radius[0], y, radius[0]); - ctx.closePath(); - ctx.fillStyle = control.color; - ctx.fill(); - ctx.restore(); - } - } - OpacityMask { - anchors.fill: container - source: container - maskSource: canvas - } -} diff --git a/src/Qt5/imports/FluentUI/Controls/FluNavigationView.qml b/src/Qt5/imports/FluentUI/Controls/FluNavigationView.qml index 0acaab6c..284b1cd2 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluNavigationView.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluNavigationView.qml @@ -112,8 +112,16 @@ Item { id:com_panel_item_separatorr FluDivider{ width: layout_list.width - spacing: model.spacing + spacing: { + if(model){ + return model.spacing + } + return 1 + } separatorHeight: { + if(!model){ + return 1 + } if(model.parent){ return model.parent.isExpand ? model.size : 0 } @@ -200,6 +208,9 @@ Item { verticalCenterOffset: -8 } visible: { + if(!model){ + return false + } if(!model.isExpand){ for(var i=0;i{ - drag.source.modelData.dropped(drag) + if(drag.source.modelData){ + drag.source.modelData.dropped(drag) + } } } Loader{ @@ -938,6 +970,8 @@ Item { property var _idx: index property int type: 0 sourceComponent: { + if(model === null || !model) + return undefined if(modelData instanceof FluPaneItem){ return com_panel_item } @@ -953,6 +987,7 @@ Item { if(modelData instanceof FluPaneItemEmpty){ return com_panel_item_empty } + return undefined } } } diff --git a/src/Qt5/imports/FluentUI/Controls/FluProgressBar.qml b/src/Qt5/imports/FluentUI/Controls/FluProgressBar.qml index 3d325ec3..25f1eeec 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluProgressBar.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluProgressBar.qml @@ -19,7 +19,7 @@ ProgressBar{ color: control.backgroundColor radius: d._radius } - contentItem: FluItem { + contentItem: FluClip { clip: true radius: [d._radius,d._radius,d._radius,d._radius] Rectangle { diff --git a/src/Qt5/imports/FluentUI/Controls/FluProgressButton.qml b/src/Qt5/imports/FluentUI/Controls/FluProgressButton.qml index 2ef5fae4..67fec864 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluProgressButton.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluProgressButton.qml @@ -40,7 +40,7 @@ Button { id: control enabled: !disabled horizontalPadding:12 - background: FluItem{ + background: FluClip{ implicitWidth: 28 implicitHeight: 28 radius: [4,4,4,4] diff --git a/src/Qt5/imports/FluentUI/Controls/FluRectangle.qml b/src/Qt5/imports/FluentUI/Controls/FluRectangle.qml deleted file mode 100644 index 215f8068..00000000 --- a/src/Qt5/imports/FluentUI/Controls/FluRectangle.qml +++ /dev/null @@ -1,71 +0,0 @@ -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtGraphicalEffects 1.15 -import FluentUI 1.0 - -Item{ - property var radius:[0,0,0,0] - property color color : FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1) - property bool shadow: true - default property alias contentItem: container.data - id:control - onWidthChanged: { - canvas.requestPaint() - } - onHeightChanged: { - canvas.requestPaint() - } - onRadiusChanged: { - canvas.requestPaint() - } - FluShadow{ - anchors.fill: container - radius: control.radius[0] - visible: { - if(control.radius[0] === control.radius[1] && control.radius[0] === control.radius[2] && control.radius[0] === control.radius[3] && control.shadow){ - return true - } - return false - } - } - Rectangle{ - id:container - width: control.width - height: control.height - opacity: 0 - color:control.color - } - Canvas { - id: canvas - anchors.fill: parent - visible: false - onPaint: { - var ctx = getContext("2d") - var x = 0 - var y = 0 - var w = control.width - var h = control.height - ctx.clearRect(0, 0, canvas.width, canvas.height) - ctx.save() - ctx.beginPath(); - ctx.moveTo(x + radius[0], y) - ctx.lineTo(x + w - radius[1], y) - ctx.arcTo(x + w, y, x + w, y + radius[1], radius[1]) - ctx.lineTo(x + w, y + h - radius[2]) - ctx.arcTo(x + w, y + h, x + w - radius[2], y + h, radius[2]) - ctx.lineTo(x + radius[3], y + h) - ctx.arcTo(x, y + h, x, y + h - radius[3], radius[3]) - ctx.lineTo(x, y + radius[0]) - ctx.arcTo(x, y, x + radius[0], y, radius[0]) - ctx.closePath() - ctx.fillStyle = "#000000" - ctx.fill() - ctx.restore() - } - } - OpacityMask { - anchors.fill: container - source: container - maskSource: canvas - } -} diff --git a/src/Qt5/imports/FluentUI/Controls/FluSlider.qml b/src/Qt5/imports/FluentUI/Controls/FluSlider.qml index 6d38d2b7..642ad8be 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluSlider.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluSlider.qml @@ -23,24 +23,16 @@ T.Slider { radius: 12 } Rectangle{ - width: 24 - height: 24 - radius: 12 + width: radius*2 + height: radius*2 + radius:{ + if(control.pressed){ + return 5 + } + return control.hovered ? 7 : 6 + } color:FluTheme.dark ? FluTheme.primaryColor.lighter :FluTheme.primaryColor.dark anchors.centerIn: parent - scale: { - if(control.pressed){ - return 4/10 - } - return control.hovered ? 6/10 : 5/10 - } - Behavior on scale { - enabled: FluTheme.enableAnimation - NumberAnimation{ - duration: 167 - easing.type: Easing.OutCubic - } - } } } background: Item { diff --git a/src/Qt5/imports/FluentUI/Controls/FluSpinBox.qml b/src/Qt5/imports/FluentUI/Controls/FluSpinBox.qml index 171875d9..253cc6a5 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluSpinBox.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluSpinBox.qml @@ -68,7 +68,7 @@ T.SpinBox { } } - up.indicator: FluItem { + up.indicator: FluRectangle { x: control.mirrored ? 0 : control.width - width height: control.height implicitWidth: 32 @@ -103,7 +103,7 @@ T.SpinBox { } - down.indicator: FluItem { + down.indicator: FluRectangle { x: control.mirrored ? parent.width - width : 0 height: control.height implicitWidth: 32 diff --git a/src/Qt5/imports/FluentUI/Controls/FluTabView.qml b/src/Qt5/imports/FluentUI/Controls/FluTabView.qml index 7554a390..898c0c08 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluTabView.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluTabView.qml @@ -76,7 +76,7 @@ Item { id:item_layout width: item_container.width height: item_container.height - FluItem{ + Item{ id:item_container property real timestamp: new Date().getTime() height: tab_nav.height @@ -92,7 +92,6 @@ Item { } return Math.max(Math.min(d.maxEqualWidth,tab_nav.width/tab_nav.count),41 + item_btn_close.width) } - radius: [6,6,0,0] Behavior on x { enabled: d.dragBehavior; NumberAnimation { duration: 200 } } Behavior on y { enabled: d.dragBehavior; NumberAnimation { duration: 200 } } MouseArea{ @@ -186,8 +185,9 @@ Item { } } } - Rectangle{ + FluRectangle{ anchors.fill: parent + radius: [6,6,0,0] color: { if(FluTheme.dark){ if(item_mouse_hove.containsMouse || item_btn_close.hovered){ diff --git a/src/Qt5/imports/FluentUI/Controls/FluTableView.qml b/src/Qt5/imports/FluentUI/Controls/FluTableView.qml index 3a192a60..f4398f07 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluTableView.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluTableView.qml @@ -141,13 +141,15 @@ Rectangle { FluText { id:item_text text: itemData - anchors.fill: parent - leftPadding: 11 - rightPadding: 11 - topPadding: 6 - bottomPadding: 6 elide: Text.ElideRight wrapMode: Text.WrapAnywhere + anchors{ + fill: parent + leftMargin: 11 + rightMargin: 11 + topMargin: 6 + bottomMargin: 6 + } verticalAlignment: Text.AlignVCenter HoverHandler{ id: hover_handler diff --git a/src/Qt5/imports/FluentUI/Controls/FluTextBoxBackground.qml b/src/Qt5/imports/FluentUI/Controls/FluTextBoxBackground.qml index a7a96221..eda41756 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluTextBoxBackground.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluTextBoxBackground.qml @@ -1,38 +1,34 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 -import QtGraphicalEffects 1.15 import FluentUI 1.0 -Rectangle{ +FluClip{ property Item inputItem - id:content - radius: 4 - layer.enabled: true - color: { - if(inputItem.disabled){ - return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) + property int borderWidth: 1 + id:control + radius: [4,4,4,4] + Rectangle{ + radius: 4 + anchors.fill: parent + color: { + if(inputItem.disabled){ + return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) + } + if(inputItem.activeFocus){ + return FluTheme.dark ? Qt.rgba(36/255,36/255,36/255,1) : Qt.rgba(1,1,1,1) + } + if(inputItem.hovered){ + return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) + } + return FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(1,1,1,1) } - if(inputItem.activeFocus){ - return FluTheme.dark ? Qt.rgba(36/255,36/255,36/255,1) : Qt.rgba(1,1,1,1) + border.width: control.borderWidth + border.color: { + if(inputItem.disabled){ + return FluTheme.dark ? Qt.rgba(73/255,73/255,73/255,1) : Qt.rgba(237/255,237/255,237/255,1) + } + return FluTheme.dark ? Qt.rgba(76/255,76/255,76/255,1) : Qt.rgba(240/255,240/255,240/255,1) } - if(inputItem.hovered){ - return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) - } - return FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(1,1,1,1) - } - layer.effect:OpacityMask { - maskSource: Rectangle { - width: content.width - height: content.height - radius: 4 - } - } - border.width: 1 - border.color: { - if(inputItem.disabled){ - return FluTheme.dark ? Qt.rgba(73/255,73/255,73/255,1) : Qt.rgba(237/255,237/255,237/255,1) - } - return FluTheme.dark ? Qt.rgba(76/255,76/255,76/255,1) : Qt.rgba(240/255,240/255,240/255,1) } Rectangle{ width: parent.width diff --git a/src/Qt5/imports/FluentUI/Controls/FluToggleSwitch.qml b/src/Qt5/imports/FluentUI/Controls/FluToggleSwitch.qml index 986d8b97..87128be1 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluToggleSwitch.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluToggleSwitch.qml @@ -75,12 +75,12 @@ Button { } return borderNormalColor } - Rectangle { + FluIcon { width: parent.height x:checked ? control_backgound.width-width : 0 - height: width - radius: width/2 scale: hovered&enabled ? 7/10 : 6/10 + iconSource: FluentIcons.FullCircleMask + iconSize: 20 color: { if(!enabled){ return dotDisableColor @@ -91,14 +91,9 @@ Button { return dotNormalColor } Behavior on x { - enabled: FluTheme.enableAnimation - NumberAnimation { - easing.type: Easing.OutCubic - } - } - Behavior on scale { enabled: FluTheme.enableAnimation NumberAnimation { + duration: 167 easing.type: Easing.OutCubic } } diff --git a/src/Qt5/imports/FluentUI/Controls/FluTreeItem.qml b/src/Qt5/imports/FluentUI/Controls/FluTreeItem.qml deleted file mode 100644 index ca6f5f86..00000000 --- a/src/Qt5/imports/FluentUI/Controls/FluTreeItem.qml +++ /dev/null @@ -1,22 +0,0 @@ -import QtQuick 2.15 - -QtObject { - property string key - property string title - property var children: [] - property int depth: 0 - property bool isExpanded: true - property var __parent - property int __childIndex: 0 - property bool __expanded:{ - var p = __parent; - while (p) { - if(!p.isExpanded){ - return false - } - p = p.__parent; - } - return true - } - property int index: 0 -} diff --git a/src/Qt5/imports/FluentUI/Controls/FluTreeView.qml b/src/Qt5/imports/FluentUI/Controls/FluTreeView.qml index a8eb4304..e761cb2c 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluTreeView.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluTreeView.qml @@ -9,55 +9,19 @@ Item { property int currentIndex : -1 property var dataSource property bool showLine: true + property bool draggable: false property color lineColor: FluTheme.dark ? Qt.rgba(111/255,111/255,111/255,1) : Qt.rgba(217/255,217/255,217/255,1) id:control QtObject { id:d - property var rowData: [] - function handleTree(treeData) { - var comItem = Qt.createComponent("FluTreeItem.qml"); - if (comItem.status !== Component.Ready) { - return - } - var stack = [] - var rawData = [] - for (var item of treeData) { - stack.push({node:item,depth:0,isExpanded:true,__parent:undefined,__childIndex:0}) - } - stack = stack.reverse() - var index =0 - while (stack.length > 0) { - const { node, depth,isExpanded,__parent,__childIndex} = stack.pop(); - node.depth = depth; - node.isExpanded = isExpanded; - node.__parent = __parent; - node.__childIndex = __childIndex; - var objItem = comItem.createObject(table_view); - objItem.title = node.title - objItem.key = node.key - objItem.depth = node.depth - objItem.isExpanded = node.isExpanded - objItem.__parent = node.__parent - objItem.children = node.children - objItem.__childIndex = node.__childIndex - objItem.index = index - index = index + 1; - rawData.push(objItem) - if (node.children && node.children.length > 0) { - const children = node.children.reverse(); - var childIndex = children.length-1 - for (const child of children) { - stack.push({ node: child, depth: depth + 1,isExpanded:true,__parent:objItem,__childIndex:childIndex}); - childIndex=childIndex-1; - } - } - } - return rawData - } + property var current + property int dropIndex: -1 + property int dragIndex: -1 + property color hitColor: FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark + } onDataSourceChanged: { - d.rowData = d.handleTree(dataSource) - tree_model.setData(d.rowData) + tree_model.setDataSource(dataSource) } FluTreeModel{ id:tree_model @@ -69,65 +33,205 @@ Item { table_view.forceLayout() } } - TableView{ - id:table_view - ScrollBar.horizontal: FluScrollBar{} - ScrollBar.vertical: FluScrollBar{} - boundsBehavior: Flickable.StopAtBounds - model: tree_model - clip: true - anchors.fill: parent - onContentYChanged:{ - timer_refresh.restart() - } - reuseItems: false - delegate: Item { - property bool hasChildren: { - if(display.children){ - return true - } - return false + Component{ + id:com_item_container + Item{ + signal reused + signal pooled + + onReused: { + console.debug("----->onReused") } - property var itemData: display - property bool vlineVisible: display.depth !== 0 && control.showLine - property bool hlineVisible: display.depth !== 0 && control.showLine && !hasChildren - property bool isLastIndex : { - if(display.__parent && display.__parent.children){ - return display.__childIndex === display.__parent.children.length-1 - } - return false + onPooled: { + console.debug("----->onPooled") + } + + property bool isCurrent: d.current === itemModel + id:item_container + width: { + var w = 46 + item_layout_text.width + 30*itemModel.depth + if(control.width>w){ + return control.width + } + return w + } + height: 30 + function toggle(){ + if(itemModel.isExpanded){ + tree_model.collapse(rowIndex) + }else{ + tree_model.expand(rowIndex) + } + } + Rectangle{ + anchors.fill: parent + radius: 4 + anchors.leftMargin: 6 + anchors.rightMargin: 6 + border.color: d.hitColor + border.width: d.dragIndex === rowIndex ? 1 : 0 + color: { + if(FluTheme.dark){ + if(isCurrent){ + return Qt.rgba(1,1,1,0.03) + } + if(item_mouse.containsMouse){ + return Qt.rgba(1,1,1,0.03) + } + return Qt.rgba(0,0,0,0) + }else{ + if(isCurrent){ + return Qt.rgba(0,0,0,0.06) + } + if(item_mouse.containsMouse){ + return Qt.rgba(0,0,0,0.03) + } + return Qt.rgba(0,0,0,0) + } + } + } + Rectangle{ + width: 3 + height: 18 + radius: 1.5 + color: FluTheme.primaryColor.dark + visible: isCurrent + anchors{ + left: parent.left + leftMargin: 6 + verticalCenter: parent.verticalCenter + } + } + MouseArea{ + id:item_mouse + anchors.fill: parent + drag.target:control.draggable ? loader_container : undefined + hoverEnabled: true + drag.onActiveChanged: { + if(drag.active){ + if(itemModel.isExpanded && itemModel.hasChildren()){ + tree_model.collapse(rowIndex) + } + d.dragIndex = rowIndex + loader_container.sourceComponent = com_item_container + } + } + onPressed: { + loader_container.itemControl = itemControl + loader_container.itemModel = itemModel + var cellPosition = item_container.mapToItem(table_view, 0, 0) + loader_container.width = item_container.width + loader_container.height = item_container.height + loader_container.x = table_view.contentX + cellPosition.x + loader_container.y = table_view.contentY + cellPosition.y + + } + onClicked: { + d.current = itemModel + } + onDoubleClicked: { + if(itemModel.hasChildren()){ + item_container.toggle() + } + } + onPositionChanged: + (mouse)=> { + if(!drag.active){ + return + } + var cellPosition = item_container.mapToItem(table_view, 0, 0) + if(mouse.y+cellPosition.y<0 || mouse.y+cellPosition.y>table_view.height){ + d.dropIndex = -1 + return + } + if((mouse.x-table_view.contentX)>table_view.width || (mouse.x-table_view.contentX)<0){ + d.dropIndex = -1 + return + } + var y = loader_container.y + var index = Math.round(y/30) + if(index !== d.dragIndex){ + d.dropIndex = index + }else{ + d.dropIndex = -1 + } + } + onCanceled: { + loader_container.sourceComponent = undefined + d.dropIndex = -1 + d.dragIndex = -1 + } + onReleased: { + loader_container.sourceComponent = undefined + if(d.dropIndex !== -1){ + tree_model.dragAnddrop(d.dragIndex,d.dropIndex) + } + d.dropIndex = -1 + d.dragIndex = -1 + } + } + Drag.active: item_mouse.drag.active + Rectangle{ + anchors{ + left: parent.left + leftMargin: { + if(itemModel.hasChildren()){ + return 30*(itemModel.depth+1) - 8 + } + return 30*(itemModel.depth+1) + 18 + } + right: parent.right + rightMargin: 10 + bottom: parent.bottom + } + height: 3 + radius: 1.5 + color: d.hitColor + visible: d.dropIndex === rowIndex + Rectangle{ + width: 10 + height: 10 + radius: 5 + border.width: 3 + border.color: d.hitColor + color: FluTheme.dark ? FluColors.Black : FluColors.White + anchors{ + top: parent.top + left: parent.left + topMargin: -3 + leftMargin: -5 + } + } } - property bool isCurrent: control.currentIndex === row - implicitWidth: 46 + item_layout_text.width + 30*display.depth - implicitHeight: 30 Rectangle{ width: 1 color: control.lineColor - visible: hlineVisible - height: isLastIndex ? parent.height/2 : parent.height + visible: itemModel.depth !== 0 && control.showLine && !itemModel.hasChildren() + height: itemModel.hideLineFooter() ? parent.height/2 : parent.height anchors{ top: parent.top right: layout_row.left + rightMargin: -9 } } Rectangle{ height: 1 color: control.lineColor - visible: hlineVisible + visible: itemModel.depth !== 0 && control.showLine && !itemModel.hasChildren() width: 18 anchors{ right: layout_row.left - rightMargin: -18 + rightMargin: -27 verticalCenter: parent.verticalCenter } } Repeater{ - model: Math.max(display.depth-1,0) + model: Math.max(itemModel.depth-1,0) delegate: Rectangle{ required property int index width: 1 color: control.lineColor - visible: vlineVisible + visible: itemModel.depth !== 0 && control.showLine anchors{ top:parent.top bottom: parent.bottom @@ -140,101 +244,32 @@ Item { id:layout_row anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left - anchors.leftMargin: 14 + 30*display.depth + anchors.leftMargin: 14 + 30*itemModel.depth FluIconButton{ Layout.preferredWidth: 20 Layout.preferredHeight: 20 enabled: opacity - opacity: hasChildren + opacity: itemModel.hasChildren() contentItem: FluIcon{ - rotation: itemData.isExpanded?0:-90 + rotation: itemModel.isExpanded?0:-90 iconSource:FluentIcons.ChevronDown iconSize: 16 - Behavior on rotation{ - NumberAnimation{ - duration: FluTheme.enableAnimation ? 167 : 0 - easing.type: Easing.OutCubic - } - } } onClicked: { - var isExpanded = !itemData.isExpanded - itemData.isExpanded = isExpanded - var i,obj - if(isExpanded){ - for( i=0;iFluentUI/Controls/FluIconButton.qml FluentUI/Controls/FluImage.qml FluentUI/Controls/FluInfoBar.qml - FluentUI/Controls/FluItem.qml FluentUI/Controls/FluItemDelegate.qml FluentUI/Controls/FluMenu.qml FluentUI/Controls/FluMenuBar.qml @@ -62,7 +61,6 @@ FluentUI/Controls/FluRadioButtons.qml FluentUI/Controls/FluRangeSlider.qml FluentUI/Controls/FluRatingControl.qml - FluentUI/Controls/FluRectangle.qml FluentUI/Controls/FluRemoteLoader.qml FluentUI/Controls/FluScreenshot.qml FluentUI/Controls/FluScrollablePage.qml @@ -96,6 +94,6 @@ FluentUI/Controls/ColorPicker/Content/PanelBorder.qml FluentUI/Controls/ColorPicker/Content/SBPicker.qml FluentUI/Controls/FluLoadingButton.qml - FluentUI/Controls/FluTreeItem.qml + FluentUI/Controls/FluClip.qml diff --git a/src/Qt6/imports/FluentUI/Controls/FluAcrylic.qml b/src/Qt6/imports/FluentUI/Controls/FluAcrylic.qml index 810e3057..0073fef1 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluAcrylic.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluAcrylic.qml @@ -2,7 +2,7 @@ import QtQuick import Qt5Compat.GraphicalEffects import FluentUI -FluItem { +Item { id: control property color tintColor: Qt.rgba(1,1,1,1) property real tintOpacity: 0.65 diff --git a/src/Qt6/imports/FluentUI/Controls/FluCarousel.qml b/src/Qt6/imports/FluentUI/Controls/FluCarousel.qml index 98ba5540..2e6fdcee 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluCarousel.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluCarousel.qml @@ -2,7 +2,7 @@ import QtQuick import QtQuick.Controls import FluentUI -FluItem { +Item { property bool autoPlay: true property int loopTime: 2000 property var model diff --git a/src/Qt6/imports/FluentUI/Controls/FluClip.qml b/src/Qt6/imports/FluentUI/Controls/FluClip.qml new file mode 100644 index 00000000..6c2f4bde --- /dev/null +++ b/src/Qt6/imports/FluentUI/Controls/FluClip.qml @@ -0,0 +1,19 @@ +import QtQuick +import QtQuick.Controls +import Qt5Compat.GraphicalEffects +import FluentUI + +FluRectangle { + id:control + color: "#00000000" + layer.enabled: !FluTools.isSoftware() + layer.effect: OpacityMask{ + maskSource: ShaderEffectSource{ + sourceItem: FluRectangle{ + radius: control.radius + width: control.width + height: control.height + } + } + } +} diff --git a/src/Qt6/imports/FluentUI/Controls/FluComboBox.qml b/src/Qt6/imports/FluentUI/Controls/FluComboBox.qml index 7b2ebada..e8430d02 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluComboBox.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluComboBox.qml @@ -62,7 +62,7 @@ ComboBox { bottomInset:1 rightInset:1 background: FluTextBoxBackground{ - border.width: 0 + borderWidth: 0 inputItem: contentItem } Component.onCompleted: { diff --git a/src/Qt6/imports/FluentUI/Controls/FluDivider.qml b/src/Qt6/imports/FluentUI/Controls/FluDivider.qml index 57710126..996b7a12 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluDivider.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluDivider.qml @@ -5,14 +5,14 @@ import FluentUI Rectangle { property real spacing property alias separatorHeight:separator.height - - id:root + id:control color:Qt.rgba(0,0,0,0) height: spacing*2+separator.height Rectangle{ id:separator - color: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1) - width:parent.width - anchors.centerIn: parent + clip: true + color: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1) + width:parent.width + anchors.centerIn: parent } } diff --git a/src/Qt6/imports/FluentUI/Controls/FluExpander.qml b/src/Qt6/imports/FluentUI/Controls/FluExpander.qml index 3c165514..bc8d4738 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluExpander.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluExpander.qml @@ -78,6 +78,7 @@ Item { width: parent.width height: parent.height 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) y: -contentHeight diff --git a/src/Qt6/imports/FluentUI/Controls/FluItem.qml b/src/Qt6/imports/FluentUI/Controls/FluItem.qml deleted file mode 100644 index 7fc12d8b..00000000 --- a/src/Qt6/imports/FluentUI/Controls/FluItem.qml +++ /dev/null @@ -1,57 +0,0 @@ -import QtQuick -import QtQuick.Controls -import Qt5Compat.GraphicalEffects - -Item{ - property var radius:[0,0,0,0] - default property alias contentItem: container.data - id:control - Item{ - id:container - width: control.width - height: control.height - opacity: 0 - } - onWidthChanged: { - canvas.requestPaint() - } - onHeightChanged: { - canvas.requestPaint() - } - onRadiusChanged: { - canvas.requestPaint() - } - Canvas { - id: canvas - anchors.fill: parent - visible: false - onPaint: { - var ctx = getContext("2d"); - var x = 0; - var y = 0; - var w = control.width; - var h = control.height; - ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.save(); - ctx.beginPath(); - ctx.moveTo(x + radius[0], y); - ctx.lineTo(x + w - radius[1], y); - ctx.arcTo(x + w, y, x + w, y + radius[1], radius[1]); - ctx.lineTo(x + w, y + h - radius[2]); - ctx.arcTo(x + w, y + h, x + w - radius[2], y + h, radius[2]); - ctx.lineTo(x + radius[3], y + h); - ctx.arcTo(x, y + h, x, y + h - radius[3], radius[3]); - ctx.lineTo(x, y + radius[0]); - ctx.arcTo(x, y, x + radius[0], y, radius[0]); - ctx.closePath(); - ctx.fillStyle = control.color; - ctx.fill(); - ctx.restore(); - } - } - OpacityMask { - anchors.fill: container - source: container - maskSource: canvas - } -} diff --git a/src/Qt6/imports/FluentUI/Controls/FluNavigationView.qml b/src/Qt6/imports/FluentUI/Controls/FluNavigationView.qml index 9bf45b19..68c3e583 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluNavigationView.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluNavigationView.qml @@ -113,8 +113,16 @@ Item { id:com_panel_item_separatorr FluDivider{ width: layout_list.width - spacing: model.spacing + spacing: { + if(model){ + return model.spacing + } + return 1 + } separatorHeight: { + if(!model){ + return 1 + } if(model.parent){ return model.parent.isExpand ? model.size : 0 } @@ -201,6 +209,9 @@ Item { verticalCenterOffset: -8 } visible: { + if(!model){ + return false + } if(!model.isExpand){ for(var i=0;i{ - drag.source.modelData.dropped(drag) + if(drag.source.modelData){ + drag.source.modelData.dropped(drag) + } } } Loader{ @@ -939,6 +971,8 @@ Item { property var _idx: index property int type: 0 sourceComponent: { + if(model === null || !model) + return undefined if(modelData instanceof FluPaneItem){ return com_panel_item } @@ -954,6 +988,7 @@ Item { if(modelData instanceof FluPaneItemEmpty){ return com_panel_item_empty } + return undefined } } } diff --git a/src/Qt6/imports/FluentUI/Controls/FluProgressBar.qml b/src/Qt6/imports/FluentUI/Controls/FluProgressBar.qml index f84e131f..421e9e47 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluProgressBar.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluProgressBar.qml @@ -19,7 +19,7 @@ ProgressBar{ color: control.backgroundColor radius: d._radius } - contentItem: FluItem { + contentItem: FluClip { clip: true radius: [d._radius,d._radius,d._radius,d._radius] Rectangle { diff --git a/src/Qt6/imports/FluentUI/Controls/FluProgressButton.qml b/src/Qt6/imports/FluentUI/Controls/FluProgressButton.qml index cf4d5027..869cefdc 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluProgressButton.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluProgressButton.qml @@ -41,7 +41,7 @@ Button { id: control enabled: !disabled horizontalPadding:12 - background: FluItem{ + background: FluClip{ implicitWidth: 28 implicitHeight: 28 radius: [4,4,4,4] diff --git a/src/Qt6/imports/FluentUI/Controls/FluRectangle.qml b/src/Qt6/imports/FluentUI/Controls/FluRectangle.qml deleted file mode 100644 index 9882a2e3..00000000 --- a/src/Qt6/imports/FluentUI/Controls/FluRectangle.qml +++ /dev/null @@ -1,71 +0,0 @@ -import QtQuick -import QtQuick.Controls -import Qt5Compat.GraphicalEffects -import FluentUI - -Item{ - property var radius:[0,0,0,0] - property color color : FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1) - property bool shadow: true - default property alias contentItem: container.data - id:control - onWidthChanged: { - canvas.requestPaint() - } - onHeightChanged: { - canvas.requestPaint() - } - onRadiusChanged: { - canvas.requestPaint() - } - FluShadow{ - anchors.fill: container - radius: control.radius[0] - visible: { - if(control.radius[0] === control.radius[1] && control.radius[0] === control.radius[2] && control.radius[0] === control.radius[3] && control.shadow){ - return true - } - return false - } - } - Rectangle{ - id:container - width: control.width - height: control.height - opacity: 0 - color:control.color - } - Canvas { - id: canvas - anchors.fill: parent - visible: false - onPaint: { - var ctx = getContext("2d") - var x = 0 - var y = 0 - var w = control.width - var h = control.height - ctx.clearRect(0, 0, canvas.width, canvas.height) - ctx.save() - ctx.beginPath(); - ctx.moveTo(x + radius[0], y) - ctx.lineTo(x + w - radius[1], y) - ctx.arcTo(x + w, y, x + w, y + radius[1], radius[1]) - ctx.lineTo(x + w, y + h - radius[2]) - ctx.arcTo(x + w, y + h, x + w - radius[2], y + h, radius[2]) - ctx.lineTo(x + radius[3], y + h) - ctx.arcTo(x, y + h, x, y + h - radius[3], radius[3]) - ctx.lineTo(x, y + radius[0]) - ctx.arcTo(x, y, x + radius[0], y, radius[0]) - ctx.closePath() - ctx.fillStyle = "#000000" - ctx.fill() - ctx.restore() - } - } - OpacityMask { - anchors.fill: container - source: container - maskSource: canvas - } -} diff --git a/src/Qt6/imports/FluentUI/Controls/FluSlider.qml b/src/Qt6/imports/FluentUI/Controls/FluSlider.qml index cfbd5765..c642d30e 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluSlider.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluSlider.qml @@ -24,24 +24,16 @@ T.Slider { radius: 12 } Rectangle{ - width: 24 - height: 24 - radius: 12 + width: radius*2 + height: radius*2 + radius:{ + if(control.pressed){ + return 5 + } + return control.hovered ? 7 : 6 + } color:FluTheme.dark ? FluTheme.primaryColor.lighter :FluTheme.primaryColor.dark anchors.centerIn: parent - scale: { - if(control.pressed){ - return 4/10 - } - return control.hovered ? 6/10 : 5/10 - } - Behavior on scale { - enabled: FluTheme.enableAnimation - NumberAnimation{ - duration: 167 - easing.type: Easing.OutCubic - } - } } } background: Item { diff --git a/src/Qt6/imports/FluentUI/Controls/FluSpinBox.qml b/src/Qt6/imports/FluentUI/Controls/FluSpinBox.qml index 96f80fa2..4cf99c06 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluSpinBox.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluSpinBox.qml @@ -69,7 +69,7 @@ T.SpinBox { } } - up.indicator: FluItem { + up.indicator: FluRectangle { x: control.mirrored ? 0 : control.width - width height: control.height implicitWidth: 32 @@ -104,7 +104,7 @@ T.SpinBox { } - down.indicator: FluItem { + down.indicator: FluRectangle { x: control.mirrored ? parent.width - width : 0 height: control.height implicitWidth: 32 diff --git a/src/Qt6/imports/FluentUI/Controls/FluTabView.qml b/src/Qt6/imports/FluentUI/Controls/FluTabView.qml index 9cc21371..f0532028 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluTabView.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluTabView.qml @@ -76,7 +76,7 @@ Item { id:item_layout width: item_container.width height: item_container.height - FluItem{ + Item{ id:item_container property real timestamp: new Date().getTime() height: tab_nav.height @@ -92,7 +92,6 @@ Item { } return Math.max(Math.min(d.maxEqualWidth,tab_nav.width/tab_nav.count),41 + item_btn_close.width) } - radius: [6,6,0,0] Behavior on x { enabled: d.dragBehavior; NumberAnimation { duration: 200 } } Behavior on y { enabled: d.dragBehavior; NumberAnimation { duration: 200 } } MouseArea{ @@ -186,8 +185,9 @@ Item { } } } - Rectangle{ + FluRectangle{ anchors.fill: parent + radius: [6,6,0,0] color: { if(FluTheme.dark){ if(item_mouse_hove.containsMouse || item_btn_close.hovered){ diff --git a/src/Qt6/imports/FluentUI/Controls/FluTableView.qml b/src/Qt6/imports/FluentUI/Controls/FluTableView.qml index 171f2897..7497d96a 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluTableView.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluTableView.qml @@ -143,13 +143,15 @@ Rectangle { FluText { id:item_text text: itemData - anchors.fill: parent elide: Text.ElideRight wrapMode: Text.WrapAnywhere - leftPadding: 11 - rightPadding: 11 - topPadding: 6 - bottomPadding: 6 + anchors{ + fill: parent + leftMargin: 11 + rightMargin: 11 + topMargin: 6 + bottomMargin: 6 + } verticalAlignment: Text.AlignVCenter HoverHandler{ id: hover_handler diff --git a/src/Qt6/imports/FluentUI/Controls/FluTextBoxBackground.qml b/src/Qt6/imports/FluentUI/Controls/FluTextBoxBackground.qml index dcbf94bb..f81ed2bd 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluTextBoxBackground.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluTextBoxBackground.qml @@ -1,38 +1,34 @@ import QtQuick import QtQuick.Controls -import Qt5Compat.GraphicalEffects import FluentUI -Rectangle{ +FluClip{ property Item inputItem - id:content - radius: 4 - layer.enabled: true - color: { - if(inputItem.disabled){ - return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) + property int borderWidth: 1 + id:control + radius: [4,4,4,4] + Rectangle{ + radius: 4 + anchors.fill: parent + color: { + if(inputItem.disabled){ + return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) + } + if(inputItem.activeFocus){ + return FluTheme.dark ? Qt.rgba(36/255,36/255,36/255,1) : Qt.rgba(1,1,1,1) + } + if(inputItem.hovered){ + return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) + } + return FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(1,1,1,1) } - if(inputItem.activeFocus){ - return FluTheme.dark ? Qt.rgba(36/255,36/255,36/255,1) : Qt.rgba(1,1,1,1) + border.width: control.borderWidth + border.color: { + if(inputItem.disabled){ + return FluTheme.dark ? Qt.rgba(73/255,73/255,73/255,1) : Qt.rgba(237/255,237/255,237/255,1) + } + return FluTheme.dark ? Qt.rgba(76/255,76/255,76/255,1) : Qt.rgba(240/255,240/255,240/255,1) } - if(inputItem.hovered){ - return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) - } - return FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(1,1,1,1) - } - layer.effect:OpacityMask { - maskSource: Rectangle { - width: content.width - height: content.height - radius: 4 - } - } - border.width: 1 - border.color: { - if(inputItem.disabled){ - return FluTheme.dark ? Qt.rgba(73/255,73/255,73/255,1) : Qt.rgba(237/255,237/255,237/255,1) - } - return FluTheme.dark ? Qt.rgba(76/255,76/255,76/255,1) : Qt.rgba(240/255,240/255,240/255,1) } Rectangle{ width: parent.width diff --git a/src/Qt6/imports/FluentUI/Controls/FluToggleSwitch.qml b/src/Qt6/imports/FluentUI/Controls/FluToggleSwitch.qml index 3110c649..277fe75d 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluToggleSwitch.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluToggleSwitch.qml @@ -76,12 +76,12 @@ Button { } return borderNormalColor } - Rectangle { + FluIcon { width: parent.height x:checked ? control_backgound.width-width : 0 - height: width - radius: width/2 scale: hovered&enabled ? 7/10 : 6/10 + iconSource: FluentIcons.FullCircleMask + iconSize: 20 color: { if(!enabled){ return dotDisableColor @@ -92,14 +92,9 @@ Button { return dotNormalColor } Behavior on x { - enabled: FluTheme.enableAnimation - NumberAnimation { - easing.type: Easing.OutCubic - } - } - Behavior on scale { enabled: FluTheme.enableAnimation NumberAnimation { + duration: 167 easing.type: Easing.OutCubic } } diff --git a/src/Qt6/imports/FluentUI/Controls/FluTreeItem.qml b/src/Qt6/imports/FluentUI/Controls/FluTreeItem.qml deleted file mode 100644 index 2539f11a..00000000 --- a/src/Qt6/imports/FluentUI/Controls/FluTreeItem.qml +++ /dev/null @@ -1,22 +0,0 @@ -import QtQuick - -QtObject { - property string key - property string title - property var children: [] - property int depth: 0 - property bool isExpanded: true - property var __parent - property int __childIndex: 0 - property bool __expanded:{ - var p = __parent; - while (p) { - if(!p.isExpanded){ - return false - } - p = p.__parent; - } - return true - } - property int index: 0 -} diff --git a/src/Qt6/imports/FluentUI/Controls/FluTreeView.qml b/src/Qt6/imports/FluentUI/Controls/FluTreeView.qml index 88df62b3..f7a741df 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluTreeView.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluTreeView.qml @@ -9,55 +9,19 @@ Item { property int currentIndex : -1 property var dataSource property bool showLine: true + property bool draggable: false property color lineColor: FluTheme.dark ? Qt.rgba(111/255,111/255,111/255,1) : Qt.rgba(217/255,217/255,217/255,1) id:control QtObject { id:d - property var rowData: [] - function handleTree(treeData) { - var comItem = Qt.createComponent("FluTreeItem.qml"); - if (comItem.status !== Component.Ready) { - return - } - var stack = [] - var rawData = [] - for (var item of treeData) { - stack.push({node:item,depth:0,isExpanded:true,__parent:undefined,__childIndex:0}) - } - stack = stack.reverse() - var index =0 - while (stack.length > 0) { - const { node, depth,isExpanded,__parent,__childIndex} = stack.pop(); - node.depth = depth; - node.isExpanded = isExpanded; - node.__parent = __parent; - node.__childIndex = __childIndex; - var objItem = comItem.createObject(table_view); - objItem.title = node.title - objItem.key = node.key - objItem.depth = node.depth - objItem.isExpanded = node.isExpanded - objItem.__parent = node.__parent - objItem.children = node.children - objItem.__childIndex = node.__childIndex - objItem.index = index - index = index + 1; - rawData.push(objItem) - if (node.children && node.children.length > 0) { - const children = node.children.reverse(); - var childIndex = children.length-1 - for (const child of children) { - stack.push({ node: child, depth: depth + 1,isExpanded:true,__parent:objItem,__childIndex:childIndex}); - childIndex=childIndex-1; - } - } - } - return rawData - } + property var current + property int dropIndex: -1 + property int dragIndex: -1 + property color hitColor: FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark + } onDataSourceChanged: { - d.rowData = d.handleTree(dataSource) - tree_model.setData(d.rowData) + tree_model.setDataSource(dataSource) } FluTreeModel{ id:tree_model @@ -69,65 +33,205 @@ Item { table_view.forceLayout() } } - TableView{ - id:table_view - ScrollBar.horizontal: FluScrollBar{} - ScrollBar.vertical: FluScrollBar{} - boundsBehavior: Flickable.StopAtBounds - model: tree_model - clip: true - anchors.fill: parent - onContentYChanged:{ - timer_refresh.restart() - } - reuseItems: false - delegate: Item { - property bool hasChildren: { - if(display.children){ - return true - } - return false + Component{ + id:com_item_container + Item{ + signal reused + signal pooled + + onReused: { + console.debug("----->onReused") } - property var itemData: display - property bool vlineVisible: display.depth !== 0 && control.showLine - property bool hlineVisible: display.depth !== 0 && control.showLine && !hasChildren - property bool isLastIndex : { - if(display.__parent && display.__parent.children){ - return display.__childIndex === display.__parent.children.length-1 - } - return false + onPooled: { + console.debug("----->onPooled") + } + + property bool isCurrent: d.current === itemModel + id:item_container + width: { + var w = 46 + item_layout_text.width + 30*itemModel.depth + if(control.width>w){ + return control.width + } + return w + } + height: 30 + function toggle(){ + if(itemModel.isExpanded){ + tree_model.collapse(rowIndex) + }else{ + tree_model.expand(rowIndex) + } + } + Rectangle{ + anchors.fill: parent + radius: 4 + anchors.leftMargin: 6 + anchors.rightMargin: 6 + border.color: d.hitColor + border.width: d.dragIndex === rowIndex ? 1 : 0 + color: { + if(FluTheme.dark){ + if(isCurrent){ + return Qt.rgba(1,1,1,0.03) + } + if(item_mouse.containsMouse){ + return Qt.rgba(1,1,1,0.03) + } + return Qt.rgba(0,0,0,0) + }else{ + if(isCurrent){ + return Qt.rgba(0,0,0,0.06) + } + if(item_mouse.containsMouse){ + return Qt.rgba(0,0,0,0.03) + } + return Qt.rgba(0,0,0,0) + } + } + } + Rectangle{ + width: 3 + height: 18 + radius: 1.5 + color: FluTheme.primaryColor.dark + visible: isCurrent + anchors{ + left: parent.left + leftMargin: 6 + verticalCenter: parent.verticalCenter + } + } + MouseArea{ + id:item_mouse + anchors.fill: parent + drag.target:control.draggable ? loader_container : undefined + hoverEnabled: true + drag.onActiveChanged: { + if(drag.active){ + if(itemModel.isExpanded && itemModel.hasChildren()){ + tree_model.collapse(rowIndex) + } + d.dragIndex = rowIndex + loader_container.sourceComponent = com_item_container + } + } + onPressed: { + loader_container.itemControl = itemControl + loader_container.itemModel = itemModel + var cellPosition = item_container.mapToItem(table_view, 0, 0) + loader_container.width = item_container.width + loader_container.height = item_container.height + loader_container.x = table_view.contentX + cellPosition.x + loader_container.y = table_view.contentY + cellPosition.y + + } + onClicked: { + d.current = itemModel + } + onDoubleClicked: { + if(itemModel.hasChildren()){ + item_container.toggle() + } + } + onPositionChanged: + (mouse)=> { + if(!drag.active){ + return + } + var cellPosition = item_container.mapToItem(table_view, 0, 0) + if(mouse.y+cellPosition.y<0 || mouse.y+cellPosition.y>table_view.height){ + d.dropIndex = -1 + return + } + if((mouse.x-table_view.contentX)>table_view.width || (mouse.x-table_view.contentX)<0){ + d.dropIndex = -1 + return + } + var y = loader_container.y + var index = Math.round(y/30) + if(index !== d.dragIndex){ + d.dropIndex = index + }else{ + d.dropIndex = -1 + } + } + onCanceled: { + loader_container.sourceComponent = undefined + d.dropIndex = -1 + d.dragIndex = -1 + } + onReleased: { + loader_container.sourceComponent = undefined + if(d.dropIndex !== -1){ + tree_model.dragAnddrop(d.dragIndex,d.dropIndex) + } + d.dropIndex = -1 + d.dragIndex = -1 + } + } + Drag.active: item_mouse.drag.active + Rectangle{ + anchors{ + left: parent.left + leftMargin: { + if(itemModel.hasChildren()){ + return 30*(itemModel.depth+1) - 8 + } + return 30*(itemModel.depth+1) + 18 + } + right: parent.right + rightMargin: 10 + bottom: parent.bottom + } + height: 3 + radius: 1.5 + color: d.hitColor + visible: d.dropIndex === rowIndex + Rectangle{ + width: 10 + height: 10 + radius: 5 + border.width: 3 + border.color: d.hitColor + color: FluTheme.dark ? FluColors.Black : FluColors.White + anchors{ + top: parent.top + left: parent.left + topMargin: -3 + leftMargin: -5 + } + } } - property bool isCurrent: control.currentIndex === row - implicitWidth: 46 + item_layout_text.width + 30*display.depth - implicitHeight: 30 Rectangle{ width: 1 color: control.lineColor - visible: hlineVisible - height: isLastIndex ? parent.height/2 : parent.height + visible: itemModel.depth !== 0 && control.showLine && !itemModel.hasChildren() + height: itemModel.hideLineFooter() ? parent.height/2 : parent.height anchors{ top: parent.top right: layout_row.left + rightMargin: -9 } } Rectangle{ height: 1 color: control.lineColor - visible: hlineVisible + visible: itemModel.depth !== 0 && control.showLine && !itemModel.hasChildren() width: 18 anchors{ right: layout_row.left - rightMargin: -18 + rightMargin: -27 verticalCenter: parent.verticalCenter } } Repeater{ - model: Math.max(display.depth-1,0) + model: Math.max(itemModel.depth-1,0) delegate: Rectangle{ required property int index width: 1 color: control.lineColor - visible: vlineVisible + visible: itemModel.depth !== 0 && control.showLine anchors{ top:parent.top bottom: parent.bottom @@ -140,101 +244,32 @@ Item { id:layout_row anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left - anchors.leftMargin: 14 + 30*display.depth + anchors.leftMargin: 14 + 30*itemModel.depth FluIconButton{ Layout.preferredWidth: 20 Layout.preferredHeight: 20 enabled: opacity - opacity: hasChildren + opacity: itemModel.hasChildren() contentItem: FluIcon{ - rotation: itemData.isExpanded?0:-90 + rotation: itemModel.isExpanded?0:-90 iconSource:FluentIcons.ChevronDown iconSize: 16 - Behavior on rotation{ - NumberAnimation{ - duration: FluTheme.enableAnimation ? 167 : 0 - easing.type: Easing.OutCubic - } - } } onClicked: { - var isExpanded = !itemData.isExpanded - itemData.isExpanded = isExpanded - var i,obj - if(isExpanded){ - for( i=0;i