diff --git a/example/example_en_US.ts b/example/example_en_US.ts index 01b97f79..e853567d 100644 --- a/example/example_en_US.ts +++ b/example/example_en_US.ts @@ -70,17 +70,17 @@ - + We apologize for the inconvenience caused by an unexpected error - + Report Logs - + Restart Program @@ -2368,7 +2368,7 @@ Some contents... - + Name @@ -2418,37 +2418,37 @@ Some contents... - + Avatar - + Address - + Nickname - + Long String - + Options - + <Previous - + Next> @@ -2487,8 +2487,8 @@ Some contents... - - + + Disabled @@ -2507,6 +2507,11 @@ Some contents... AutoSuggestBox + + + Show suggest when pressed + + T_Theme @@ -2727,49 +2732,60 @@ Some contents... T_Tour + Upload File + Put your files here. - - + + + Save + Save your changes. + Other Actions + Click to see other actions. - + Begin Tour - - + + Begin Tour with custom indicator + + + + + Upload - + More diff --git a/example/example_zh_CN.ts b/example/example_zh_CN.ts index 3cead65e..ae385d80 100644 --- a/example/example_zh_CN.ts +++ b/example/example_zh_CN.ts @@ -70,17 +70,17 @@ 友情提示 - + We apologize for the inconvenience caused by an unexpected error 对于意外错误给您带来的不便,我们深表歉意 - + Report Logs 上报日志 - + Restart Program 重启程序 @@ -552,7 +552,7 @@ Tour - 游览 + 漫游式引导 @@ -2557,7 +2557,7 @@ Some contents... - + Name 名称 @@ -2597,37 +2597,37 @@ Some contents... 焦点未获取:请点击表格中的任意一项,作为插入的靶点! - + Avatar 头像 - + Address 地址 - + Nickname 昵称 - + Long String 长字符串 - + Options 操作 - + <Previous <上一页 - + Next> 下一页> @@ -2676,8 +2676,8 @@ Some contents... - - + + Disabled 禁用 @@ -2696,6 +2696,11 @@ Some contents... AutoSuggestBox 自动建议框 + + + Show suggest when pressed + 按下时显示建议 + T_Theme @@ -2928,56 +2933,67 @@ Some contents... + Upload File 上传文件 + Put your files here. 把你的文件放在这里 - - + + + Save 保存 + Save your changes. 保存更改 + Other Actions 其他操作 + Click to see other actions. 点击查看其他操作 - + Begin Tour - 开始游览 + 开始导览 - - + + Begin Tour with custom indicator + 以自定义指示器开始导览 + + + + Upload 上传 - + More 更多 Tour - 游览 + 漫游式引导 diff --git a/example/qml/page/T_Badge.qml b/example/qml/page/T_Badge.qml index 6a2db9c5..941fc241 100644 --- a/example/qml/page/T_Badge.qml +++ b/example/qml/page/T_Badge.qml @@ -26,7 +26,8 @@ FluScrollablePage{ width: parent.width text: qsTr("It usually appears in the upper right corner of the notification icon or avatar to display the number of messages that need to be processed") } - Row{ + Flow{ + width: parent.width spacing: 20 Rectangle{ width: 40 @@ -34,7 +35,7 @@ FluScrollablePage{ radius: 8 color: Qt.rgba(191/255,191/255,191/255,1) FluBadge{ - topRight: true + position: "topRight" showZero: true count:0 } @@ -46,7 +47,7 @@ FluScrollablePage{ radius: 8 color: Qt.rgba(191/255,191/255,191/255,1) FluBadge{ - topRight: true + position: "topRight" showZero: true count:5 } @@ -57,7 +58,7 @@ FluScrollablePage{ radius: 8 color: Qt.rgba(191/255,191/255,191/255,1) FluBadge{ - topRight: true + position: "topRight" showZero: true count:50 } @@ -68,9 +69,10 @@ FluScrollablePage{ radius: 8 color: Qt.rgba(191/255,191/255,191/255,1) FluBadge{ - topRight: true + position: "topRight" showZero: true - count:100 + count:1000 + max: 999 } } Rectangle{ @@ -79,7 +81,7 @@ FluScrollablePage{ radius: 8 color: Qt.rgba(191/255,191/255,191/255,1) FluBadge{ - topRight: true + position: "topRight" showZero: true isDot:true } @@ -90,7 +92,7 @@ FluScrollablePage{ radius: 8 color: Qt.rgba(191/255,191/255,191/255,1) FluBadge{ - topRight: true + position: "topRight" showZero: true count:99 color: Qt.rgba(250/255,173/255,20/255,1) @@ -102,12 +104,71 @@ FluScrollablePage{ radius: 8 color: Qt.rgba(191/255,191/255,191/255,1) FluBadge{ - topRight: true + position: "topRight" showZero: true count:99 color: Qt.rgba(82/255,196/255,26/255,1) } } + Rectangle{ + width: 40 + height: 40 + radius: 8 + color: Qt.rgba(191/255,191/255,191/255,1) + FluBadge{ + position: "topRight" + showZero: true + count:100 + color: Qt.rgba(84/255,169/255,1,1) + } + } + Rectangle{ + width: 40 + height: 40 + radius: 8 + color: Qt.rgba(191/255,191/255,191/255,1) + FluBadge{ + position: "bottomLeft" + showZero: true + count:100 + color: Qt.rgba(84/255,169/255,1,1) + } + } + Rectangle{ + width: 40 + height: 40 + radius: 8 + color: Qt.rgba(191/255,191/255,191/255,1) + FluBadge{ + position: "topLeft" + showZero: true + count:100 + color: Qt.rgba(84/255,169/255,1,1) + } + } + Rectangle{ + width: 40 + height: 40 + radius: 8 + color: Qt.rgba(191/255,191/255,191/255,1) + FluBadge{ + position: "bottomRight" + showZero: true + count:100 + color: Qt.rgba(84/255,169/255,1,1) + } + } + Rectangle{ + width: 40 + height: 40 + radius: 8 + color: Qt.rgba(191/255,191/255,191/255,1) + FluBadge{ + position: "topRight" + count: "NEW" + color: Qt.rgba(84/255,169/255,1,1) + } + } } } } @@ -120,7 +181,9 @@ FluScrollablePage{ radius: 8 color: Qt.rgba(191/255,191/255,191/255,1) FluBadge{ + position: "topRight" count: 100 + max: 99 isDot: false color: Qt.rgba(82/255,196/255,26/255,1) } diff --git a/example/qml/page/T_Rectangle.qml b/example/qml/page/T_Rectangle.qml index edd8d153..12cd429b 100644 --- a/example/qml/page/T_Rectangle.qml +++ b/example/qml/page/T_Rectangle.qml @@ -11,53 +11,71 @@ FluScrollablePage{ FluFrame{ Layout.fillWidth: true - Layout.preferredHeight: 80 padding: 10 - Column{ + Flow{ + width: parent.width spacing: 15 - anchors{ - left: parent.left - verticalCenter: parent.verticalCenter + FluRectangle{ + width: 50 + height: 50 + color:"#0078d4" + radius:[0,0,0,0] } - RowLayout{ - Layout.topMargin: 20 - FluRectangle{ - width: 50 - height: 50 - color:"#0078d4" - radius:[0,0,0,0] - } - FluRectangle{ - width: 50 - height: 50 - color:"#744da9" - radius:[15,15,15,15] - } - FluRectangle{ - width: 50 - height: 50 - color:"#ffeb3b" - radius:[15,0,0,0] - } - FluRectangle{ - width: 50 - height: 50 - color:"#f7630c" - radius:[0,15,0,0] - } - FluRectangle{ - width: 50 - height: 50 - color:"#e71123" - radius:[0,0,15,0] - } - FluRectangle{ - width: 50 - height: 50 - color:"#b4009e" - radius:[0,0,0,15] - } + FluRectangle{ + width: 50 + height: 50 + color:"#744da9" + radius:[15,15,15,15] + } + FluRectangle{ + width: 50 + height: 50 + color:"#ffeb3b" + radius:[15,0,0,0] + } + FluRectangle{ + width: 50 + height: 50 + color:"#f7630c" + radius:[0,15,0,0] + } + FluRectangle{ + width: 50 + height: 50 + color:"#e71123" + radius:[0,0,15,0] + } + FluRectangle{ + width: 50 + height: 50 + color:"#b4009e" + radius:[0,0,0,15] + } + FluRectangle{ + width: 50 + height: 50 + color:"#a8d5ba" + radius:[15,15,15,15] + borderWidth: 3 + borderColor: "#5b8a72" + } + FluRectangle{ + width: 50 + height: 50 + color:"#dbe2ef" + radius:[15,0,0,0] + borderWidth: 2 + borderColor: "#3f72af" + } + FluRectangle{ + width: 50 + height: 50 + color:"#dbe2ef" + borderWidth: 2 + borderColor: "#3f72af" + borderStyle: Qt.DashLine + dashPattern: [4,2] } } } @@ -66,6 +84,10 @@ FluScrollablePage{ Layout.topMargin: -6 code:'FluRectangle{ radius: [25,25,25,25] + borderWidth: 2 + borderColor: "#000000" + borderStyle: Qt.DashLine + dashPattern: [4,2] width: 50 height: 50 }' diff --git a/example/qml/page/T_TableView.qml b/example/qml/page/T_TableView.qml index 242fdb4b..e9681387 100644 --- a/example/qml/page/T_TableView.qml +++ b/example/qml/page/T_TableView.qml @@ -493,6 +493,7 @@ FluContentPage{ onRowsChanged: { root.checkBoxChanged() } + startRowIndex: (gagination.pageCurrent - 1) * gagination.__itemPerPage + 1 columnSource:[ { title: table_view.customItem(com_column_checbox,{checked:true}), diff --git a/example/qml/page/T_TextBox.qml b/example/qml/page/T_TextBox.qml index 357720d2..ab722ba5 100644 --- a/example/qml/page/T_TextBox.qml +++ b/example/qml/page/T_TextBox.qml @@ -114,18 +114,26 @@ FluScrollablePage{ placeholderText: qsTr("AutoSuggestBox") items: generateRandomNames(100) disabled: text_box_suggest_switch.checked + itemRows: 12 + showSuggestWhenPressed: text_box_show_suggest_switch.checked anchors{ verticalCenter: parent.verticalCenter left: parent.left } } - FluToggleSwitch{ - id:text_box_suggest_switch + RowLayout{ anchors{ verticalCenter: parent.verticalCenter right: parent.right } - text: qsTr("Disabled") + FluToggleSwitch{ + id:text_box_show_suggest_switch + text: qsTr("Show suggest when pressed") + } + FluToggleSwitch{ + id:text_box_suggest_switch + text: qsTr("Disabled") + } } } CodeExpander{ @@ -133,6 +141,9 @@ FluScrollablePage{ Layout.topMargin: -6 code:'FluAutoSuggestBox{ placeholderText: qsTr("AutoSuggestBox") + itemRows: 12 + itemHeight: 38 + showSuggestWhenPressed: false }' } diff --git a/example/qml/page/T_Tour.qml b/example/qml/page/T_Tour.qml index e87e5827..f7ce16df 100644 --- a/example/qml/page/T_Tour.qml +++ b/example/qml/page/T_Tour.qml @@ -17,20 +17,42 @@ FluScrollablePage{ {title:qsTr("Other Actions"),description: qsTr("Click to see other actions."),target:()=>btn_more} ] } + FluTour{ + id:tour_custom_indicator + steps:[ + {title:qsTr("Upload File"),description: qsTr("Put your files here."),target:()=>btn_upload}, + {title:qsTr("Save"),description: qsTr("Save your changes."),target:()=>btn_save}, + {title:qsTr("Other Actions"),description: qsTr("Click to see other actions."),target:()=>btn_more} + ] + indicator: Component{ + FluText { + text: "%1 / %2".arg(current + 1).arg(total) + } + } + } FluFrame{ Layout.fillWidth: true Layout.preferredHeight: 130 padding: 10 - FluFilledButton{ + Row{ anchors{ top: parent.top topMargin: 14 } - text: qsTr("Begin Tour") - onClicked: { - tour.open() + spacing: 20 + FluFilledButton{ + text: qsTr("Begin Tour") + onClicked: { + tour.open() + } + } + FluFilledButton{ + text: qsTr("Begin Tour with custom indicator") + onClicked: { + tour_custom_indicator.open() + } } } diff --git a/example/qml/window/CrashWindow.qml b/example/qml/window/CrashWindow.qml index b70fa0d5..4451816b 100644 --- a/example/qml/window/CrashWindow.qml +++ b/example/qml/window/CrashWindow.qml @@ -19,6 +19,9 @@ FluWindow { Component.onCompleted: { window.stayTop = true } + Component.onDestruction: { + FluRouter.exit() + } onInitArgument: (argument)=>{ diff --git a/src/FluRectangle.cpp b/src/FluRectangle.cpp index 00890a76..f682eae1 100644 --- a/src/FluRectangle.cpp +++ b/src/FluRectangle.cpp @@ -2,33 +2,69 @@ #include FluRectangle::FluRectangle(QQuickItem *parent) : QQuickPaintedItem(parent) { - color(QColor(255, 255, 255, 255)); + color(Qt::white); radius({0, 0, 0, 0}); + borderWidth(0); + borderColor(Qt::black); + borderStyle(Qt::SolidLine); + dashPattern({}); connect(this, &FluRectangle::colorChanged, this, [=] { update(); }); connect(this, &FluRectangle::radiusChanged, this, [=] { update(); }); + connect(this, &FluRectangle::borderWidthChanged, this, [=] { update(); }); + connect(this, &FluRectangle::borderColorChanged, this, [=] { update(); }); + connect(this, &FluRectangle::borderStyleChanged, this, [=] { update(); }); + connect(this, &FluRectangle::dashPatternChanged, this, [=] { update(); }); } +bool FluRectangle::borderValid() const { + return qRound(_borderWidth) >= 1 && _color.isValid() && _color.alpha() > 0; +} 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.bottomRight() - 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); + bool drawBorder = borderValid(); + if (drawBorder) { + // 绘制边框时画笔的宽度从路径向两侧扩充 + // 因此实际绘制的矩形应向内侧收缩边框宽度的一半,避免边框裁剪导致不完整 + qreal halfBorderWidth = _borderWidth / 2.0; + rect.adjust(halfBorderWidth, halfBorderWidth, -halfBorderWidth, -halfBorderWidth); + } + + QPainterPath path; + QList r = _radius; + + while (r.size() < 4) { + r.append(0); + } + + // 从右下角开始逆时针绘制圆角矩形路径 + path.moveTo(rect.bottomRight() - QPointF(0, r[2])); + path.lineTo(rect.topRight() + QPointF(0, r[1])); + path.arcTo(QRectF(QPointF(rect.topRight() - QPointF(r[1] * 2, 0)), QSize(r[1] * 2, r[1] * 2)), 0, 90); + + path.lineTo(rect.topLeft() + QPointF(r[0], 0)); + path.arcTo(QRectF(QPointF(rect.topLeft()), QSize(r[0] * 2, r[0] * 2)), 90, 90); + + path.lineTo(rect.bottomLeft() - QPointF(0, r[3])); + path.arcTo(QRectF(QPointF(rect.bottomLeft() - QPointF(0, r[3] * 2)), QSize(r[3] * 2, r[3] * 2)), 180, 90); + + path.lineTo(rect.bottomRight() - QPointF(r[2], 0)); + path.arcTo(QRectF(QPointF(rect.bottomRight() - QPointF(r[2] * 2, r[2] * 2)), QSize(r[2] * 2, r[2] * 2)), 270, 90); + + // 填充背景 painter->fillPath(path, _color); + + // 绘制边框 + if (drawBorder) { + QPen pen(_borderColor, _borderWidth, _borderStyle); + if (_borderStyle == Qt::DashLine || _borderStyle == Qt::CustomDashLine) { + pen.setDashPattern(_dashPattern); + } + painter->strokePath(path, pen); + } + painter->restore(); } diff --git a/src/FluRectangle.h b/src/FluRectangle.h index 4690ff39..53556cc1 100644 --- a/src/FluRectangle.h +++ b/src/FluRectangle.h @@ -12,9 +12,15 @@ class FluRectangle : public QQuickPaintedItem { Q_OBJECT Q_PROPERTY_AUTO(QColor, color) Q_PROPERTY_AUTO(QList, radius) + Q_PROPERTY_AUTO(qreal, borderWidth) + Q_PROPERTY_AUTO(QColor, borderColor) + Q_PROPERTY_AUTO(Qt::PenStyle, borderStyle) + Q_PROPERTY_AUTO(QVector, dashPattern) QML_NAMED_ELEMENT(FluRectangle) public: explicit FluRectangle(QQuickItem *parent = nullptr); + bool borderValid() const; + void paint(QPainter *painter) override; }; diff --git a/src/Qt5/imports/FluentUI/Controls/FluAutoSuggestBox.qml b/src/Qt5/imports/FluentUI/Controls/FluAutoSuggestBox.qml index 4cf102ed..9f28175c 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluAutoSuggestBox.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluAutoSuggestBox.qml @@ -7,9 +7,12 @@ FluTextBox{ property var items:[] property string emptyText: qsTr("No results found") property int autoSuggestBoxReplacement: FluentIcons.Search + property int itemHeight: 38 + property int itemRows: 8 + property bool showSuggestWhenPressed: false property string textRole: "title" property var filter: function(item){ - if(item.title.indexOf(control.text)!==-1){ + if(item[textRole].indexOf(control.text)!==-1){ return true } return false @@ -29,17 +32,11 @@ FluTextBox{ control.updateText(modelData[textRole]) } function loadData(){ - var result = [] if(items==null){ - list_view.model = result + list_view.model = [] return } - items.map(function(item){ - if(control.filter(item)){ - result.push(item) - } - }) - list_view.model = result + list_view.model = items.filter(item => control.filter(item)) } } onActiveFocusChanged: { @@ -69,7 +66,7 @@ FluTextBox{ ScrollBar.vertical: FluScrollBar {} header: Item{ width: control.width - height: visible ? 38 : 0 + height: visible ? control.itemHeight : 0 visible: list_view.count === 0 FluText{ text: emptyText @@ -82,7 +79,7 @@ FluTextBox{ } delegate:FluControl{ id: item_control - height: 38 + height: control.itemHeight width: control.width onClicked: { d.handleClick(modelData) @@ -114,7 +111,7 @@ FluTextBox{ background:Rectangle{ id: rect_background implicitWidth: control.width - implicitHeight: 38*Math.min(Math.max(list_view.count,1),8) + implicitHeight: control.itemHeight*Math.min(Math.max(list_view.count,1),control.itemRows) radius: 5 color: FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(1,1,1,1) border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1) @@ -124,6 +121,14 @@ FluTextBox{ } } onTextChanged: { + control.showSuggest() + } + onPressed: { + if(control.showSuggestWhenPressed){ + control.showSuggest() + } + } + function showSuggest(){ d.loadData() if(d.flagVisible){ var pos = control.mapToItem(null, 0, 0) diff --git a/src/Qt5/imports/FluentUI/Controls/FluBadge.qml b/src/Qt5/imports/FluentUI/Controls/FluBadge.qml index 32fe084c..22086a7d 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluBadge.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluBadge.qml @@ -5,19 +5,15 @@ import FluentUI 1.0 Rectangle{ property bool isDot: false property bool showZero: false - property int count: 0 - property bool topRight: false + property var count: 0 + property int max: 99 + property string position: "" // topLeft, topRight, bottomLeft, bottomRight id:control color:Qt.rgba(255/255,77/255,79/255,1) width: { if(isDot) return 10 - if(count<10){ - return 20 - }else if(count<100){ - return 30 - } - return 40 + return content_text.implicitWidth + 12 } height: { if(isDot) @@ -31,49 +27,74 @@ Rectangle{ } border.width: 1 border.color: Qt.rgba(1,1,1,1) - anchors{ + anchors { + left: { + if(!parent){ + return undefined + } + return (position === "topLeft" || position === "bottomLeft") ? parent.left : undefined + } right: { - if(parent && topRight) - return parent.right - return undefined + if(!parent){ + return undefined + } + return (position === "topRight" || position === "bottomRight") ? parent.right : undefined } top: { - if(parent && topRight) - return parent.top - return undefined + if(!parent){ + return undefined + } + return (position === "topLeft" || position === "topRight") ? parent.top : undefined + } + bottom: { + if(!parent){ + return undefined + } + return (position === "bottomLeft" || position === "bottomRight") ? parent.bottom : undefined + } + leftMargin: { + if(!parent){ + return 0 + } + return (position === "topLeft" || position === "bottomLeft") ? (isDot ? -2.5 : -(width / 2)) : 0 } rightMargin: { - if(parent && topRight){ - if(isDot){ - return -2.5 - } - return -(control.width/2) + if(!parent){ + return 0 } - return 0 + return (position === "topRight" || position === "bottomRight") ? (isDot ? -2.5 : -(width / 2)) : 0 } topMargin: { - if(parent && topRight){ - if(isDot){ - return -2.5 - } - return -10 + if(!parent){ + return 0 } - return 0 + return (position === "topLeft" || position === "topRight") ? (isDot ? -2.5 : -10) : 0 + } + bottomMargin: { + if(!parent){ + return 0 + } + return (position === "bottomLeft" || position === "bottomRight") ? (isDot ? -2.5 : -10) : 0 } } visible: { - if(showZero) - return true - return count!==0 + if(typeof(count) === "number"){ + return showZero ? true : count !== 0 + } + return true } FluText{ + id: content_text anchors.centerIn: parent color: Qt.rgba(1,1,1,1) visible: !isDot text:{ - if(count<100) + if(typeof(count) === "string"){ return count - return "100+" + }else if(typeof(count) === "number"){ + return count <= max ? count.toString() : "%1+".arg(max.toString()) + } + return "" } } } diff --git a/src/Qt5/imports/FluentUI/Controls/FluComboBox.qml b/src/Qt5/imports/FluentUI/Controls/FluComboBox.qml index 3000cc7c..1792f911 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluComboBox.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluComboBox.qml @@ -55,7 +55,7 @@ T.ComboBox { font:control.font readOnly: control.down color: { - if(control.disabled) { + if(!control.enabled) { return FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) } return FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1) @@ -97,7 +97,7 @@ T.ComboBox { anchors.margins: -2 } color:{ - if(disabled){ + if(!enabled){ return disableColor } return hovered ? hoverColor :normalColor diff --git a/src/Qt5/imports/FluentUI/Controls/FluDatePicker.qml b/src/Qt5/imports/FluentUI/Controls/FluDatePicker.qml index 1ba43afa..b2f4e96d 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluDatePicker.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluDatePicker.qml @@ -178,7 +178,12 @@ FluButton { } if(type === 1){ text_month.text = model + let day = list_view_3.model[list_view_3.currentIndex] list_view_3.model = generateMonthDaysArray(list_view_1.model[list_view_1.currentIndex],list_view_2.model[list_view_2.currentIndex]) + if(list_view_3.model.indexOf(day) === -1){ + day = list_view_3.model[list_view_3.model.length - 1] + } + list_view_3.currentIndex = list_view_3.model.indexOf(day) text_day.text = list_view_3.model[list_view_3.currentIndex] } diff --git a/src/Qt5/imports/FluentUI/Controls/FluMenuBarItem.qml b/src/Qt5/imports/FluentUI/Controls/FluMenuBarItem.qml index e772314f..4d366fcf 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluMenuBarItem.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluMenuBarItem.qml @@ -6,7 +6,7 @@ T.MenuBarItem { property bool disabled: false property color textColor: { if(FluTheme.dark){ - if(disabled){ + if(!enabled){ return Qt.rgba(131/255,131/255,131/255,1) } if(pressed){ @@ -14,7 +14,7 @@ T.MenuBarItem { } return Qt.rgba(1,1,1,1) }else{ - if(disabled){ + if(!enabled){ return Qt.rgba(160/255,160/255,160/255,1) } if(pressed){ diff --git a/src/Qt5/imports/FluentUI/Controls/FluSpinBox.qml b/src/Qt5/imports/FluentUI/Controls/FluSpinBox.qml index 2f562e35..bd3ab1aa 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluSpinBox.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluSpinBox.qml @@ -139,13 +139,13 @@ T.SpinBox { radius: 4 border.width: 1 border.color: { - if(contentItem.disabled){ + if(!contentItem.enabled){ 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) } color: { - if(contentItem.disabled){ + if(!contentItem.enabled){ return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) } if(contentItem.activeFocus){ diff --git a/src/Qt5/imports/FluentUI/Controls/FluTableView.qml b/src/Qt5/imports/FluentUI/Controls/FluTableView.qml index 681200aa..c1beabbe 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluTableView.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluTableView.qml @@ -17,6 +17,7 @@ Rectangle { property color borderColor: FluTheme.dark ? Qt.rgba(37/255,37/255,37/255,1) : Qt.rgba(228/255,228/255,228/255,1) property bool horizonalHeaderVisible: true property bool verticalHeaderVisible: true + property int startRowIndex: 1 property color selectedBorderColor: FluTheme.primaryColor property color selectedColor: FluTools.withOpacity(FluTheme.primaryColor,0.3) property alias view: table_view @@ -266,30 +267,18 @@ Rectangle { d.rowHoverIndex = row } onWidthChanged: { - if(editVisible){ - updateEditPosition() - } - if(isMainTable){ - updateTableItem() - } + updatePosition() } onHeightChanged: { - if(editVisible){ - updateEditPosition() - } - if(isMainTable){ - updateTableItem() - } + updatePosition() } onXChanged: { - if(editVisible){ - updateEditPosition() - } - if(isMainTable){ - updateTableItem() - } + updatePosition() } onYChanged: { + updatePosition() + } + function updatePosition(){ if(editVisible){ updateEditPosition() } @@ -310,9 +299,11 @@ Rectangle { } function updateTableItem(){ var columnModel = control.columnSource[column] - columnModel.x = item_table_mouse.x - columnModel.y = item_table_mouse.y - d.tableItemLayout(column) + if(columnModel.x !== item_table_mouse.x || columnModel.y !== item_table_mouse.y){ + columnModel.x = item_table_mouse.x + columnModel.y = item_table_mouse.y + d.tableItemLayout(column) + } } Rectangle{ anchors.fill: parent @@ -352,6 +343,7 @@ Rectangle { } FluLoader{ id: item_table_loader + property var tableView: control property var model: item_table_mouse._model property var display: rowModel[columnModel.dataIndex] property var rowModel : model.rowModel @@ -445,10 +437,6 @@ Rectangle { } } - onWidthChanged:{ - table_view.forceLayout() - } - MouseArea{ id:layout_mouse_table hoverEnabled: true @@ -479,6 +467,9 @@ Rectangle { table_view.flick(0,1) } delegate: com_table_delegate + onWidthChanged: { + Qt.callLater(forceLayout) + } } } @@ -851,7 +842,13 @@ Rectangle { Connections{ target: table_view function onRowsChanged(){ - header_row_model.rows = Array.from({length: table_view.rows}, (_, i) => ({rowIndex:i+1})) + header_vertical.updateRowIndex() + } + } + Connections { + target: control + function onStartRowIndexChanged(){ + header_vertical.updateRowIndex() } } Timer{ @@ -861,6 +858,9 @@ Rectangle { header_vertical.forceLayout() } } + function updateRowIndex(){ + header_row_model.rows = Array.from({length: table_view.rows}, (_, i) => ({rowIndex:i+control.startRowIndex})) + } } Item{ anchors{ @@ -955,18 +955,18 @@ Rectangle { target: d function onTableItemLayout(column){ if(item_layout_frozen._index === column){ - updateLayout() + Qt.callLater(updateLayout) } } } Connections{ target: table_view function onContentXChanged(){ - updateLayout() + Qt.callLater(updateLayout) } } function updateLayout(){ - width = table_view.columnWidthProvider(_index) + width = Qt.binding(() => table_view.columnWidthProvider(_index)) x = Qt.binding(function(){ var minX = 0 var maxX = table_view.width-width diff --git a/src/Qt5/imports/FluentUI/Controls/FluTextBoxBackground.qml b/src/Qt5/imports/FluentUI/Controls/FluTextBoxBackground.qml index ef82bd13..3467a621 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluTextBoxBackground.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluTextBoxBackground.qml @@ -6,7 +6,7 @@ FluControlBackground{ property Item inputItem id:control color: { - if(inputItem && inputItem.disabled){ + if(inputItem && !inputItem.enabled){ return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) } if(inputItem && inputItem.activeFocus){ diff --git a/src/Qt5/imports/FluentUI/Controls/FluTour.qml b/src/Qt5/imports/FluentUI/Controls/FluTour.qml index d8ff7027..b73b4853 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluTour.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluTour.qml @@ -7,8 +7,10 @@ import FluentUI 1.0 Popup{ property var steps : [] property int targetMargins: 5 + property int targetRadius: 2 property Component nextButton: com_next_button property Component prevButton: com_prev_button + property Component indicator: com_indicator property int index : 0 property string finishText: qsTr("Finish") property string nextText: qsTr("Next") @@ -22,12 +24,12 @@ Popup{ contentItem: Item{} onVisibleChanged: { if(visible){ + d.animationEnabled = false control.index = 0 + d.updatePos() + d.animationEnabled = true } } - onIndexChanged: { - canvas.requestPaint() - } Component{ id: com_next_button FluFilledButton{ @@ -50,10 +52,32 @@ Popup{ } } } + Component{ + id: com_indicator + Row{ + spacing: 10 + Repeater{ + model: total + delegate: Rectangle{ + width: 8 + height: 8 + radius: 4 + scale: current === index ? 1.2 : 1 + color:{ + if(current === index){ + return FluTheme.primaryColor + } + return FluTheme.dark ? Qt.rgba(99/255,99/255,99/255,1) : Qt.rgba(214/255,214/255,214/255,1) + } + } + } + } + } Item{ id:d property var window: Window.window property point pos: Qt.point(0,0) + property bool animationEnabled: true property var step: steps[index] property var target: { if(steps[index]){ @@ -73,15 +97,22 @@ Popup{ } return control.width } + function updatePos(){ + if(d.target && d.window){ + d.pos = d.target.mapToGlobal(0,0) + d.pos = Qt.point(d.pos.x-d.window.x,d.pos.y-d.window.y) + } + } + onTargetChanged: { + updatePos() + } } Connections{ target: d.window function onWidthChanged(){ - canvas.requestPaint() timer_delay.restart() } function onHeightChanged(){ - canvas.requestPaint() timer_delay.restart() } } @@ -89,39 +120,128 @@ Popup{ id: timer_delay interval: 200 onTriggered: { - canvas.requestPaint() + d.updatePos() } } - Canvas{ - id: canvas - anchors.fill: parent - onPaint: { - d.pos = d.target.mapToGlobal(0,0) - d.pos = Qt.point(d.pos.x-d.window.x,d.pos.y-d.window.y) - var ctx = canvas.getContext("2d") - ctx.clearRect(0, 0, canvasSize.width, canvasSize.height) - ctx.save() - ctx.fillStyle = "#88000000" - ctx.fillRect(0, 0, canvasSize.width, canvasSize.height) - ctx.globalCompositeOperation = 'destination-out' - ctx.fillStyle = 'black' - var rect = Qt.rect(d.pos.x-control.targetMargins,d.pos.y-control.targetMargins, d.target.width+control.targetMargins*2, d.target.height+control.targetMargins*2) - drawRoundedRect(rect,2,ctx) - ctx.restore() + Item{ + id: targetRect + x: d.pos.x - control.targetMargins + y: d.pos.y - control.targetMargins + width: d.target ? d.target.width + control.targetMargins * 2 : 0 + height: d.target ? d.target.height + control.targetMargins * 2 : 0 + Behavior on x { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } } - function drawRoundedRect(rect, r, ctx) { - ctx.beginPath(); - ctx.moveTo(rect.x + r, rect.y); - ctx.lineTo(rect.x + rect.width - r, rect.y); - ctx.arcTo(rect.x + rect.width, rect.y, rect.x + rect.width, rect.y + r, r); - ctx.lineTo(rect.x + rect.width, rect.y + rect.height - r); - ctx.arcTo(rect.x + rect.width, rect.y + rect.height, rect.x + rect.width - r, rect.y + rect.height, r); - ctx.lineTo(rect.x + r, rect.y + rect.height); - ctx.arcTo(rect.x, rect.y + rect.height, rect.x, rect.y + rect.height - r, r); - ctx.lineTo(rect.x, rect.y + r); - ctx.arcTo(rect.x, rect.y, rect.x + r, rect.y, r); - ctx.closePath(); - ctx.fill() + Behavior on y { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } + Behavior on width { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } + Behavior on height { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } + } + Shape { + anchors.fill: parent + layer.enabled: true + layer.samples: 4 + layer.smooth: true + ShapePath { + fillColor: "#88000000" + strokeWidth: 0 + strokeColor: "transparent" + + // draw background + PathMove { + x: 0 + y: 0 + } + PathLine { + x: control.width + y: 0 + } + PathLine { + x: control.width + y: control.height + } + PathLine { + x: 0 + y: control.height + } + PathLine { + x: 0 + y: 0 + } + + // draw highlight + PathMove { + x: targetRect.x + control.targetRadius + y: targetRect.y + } + PathLine { + x: targetRect.x + targetRect.width - control.targetRadius + y: targetRect.y + } + PathArc { + x: targetRect.x + targetRect.width + y: targetRect.y + control.targetRadius + radiusX: control.targetRadius + radiusY: control.targetRadius + useLargeArc: false + direction: PathArc.Clockwise + } + + PathLine { + x: targetRect.x + targetRect.width + y: targetRect.y + targetRect.height - control.targetRadius + } + PathArc { + x: targetRect.x + targetRect.width - control.targetRadius + y: targetRect.y + targetRect.height + radiusX: control.targetRadius + radiusY: control.targetRadius + useLargeArc: false + direction: PathArc.Clockwise + } + + PathLine { + x: targetRect.x + control.targetRadius + y: targetRect.y + targetRect.height + } + PathArc { + x: targetRect.x + y: targetRect.y + targetRect.height - control.targetRadius + radiusX: control.targetRadius + radiusY: control.targetRadius + useLargeArc: false + direction: PathArc.Clockwise + } + + PathLine { + x: targetRect.x + y: targetRect.y + control.targetRadius + } + PathArc { + x: targetRect.x + control.targetRadius + y: targetRect.y + radiusX: control.targetRadius + radiusY: control.targetRadius + useLargeArc: false + direction: PathArc.Clockwise + } } } FluFrame{ @@ -151,6 +271,18 @@ Popup{ return 0 } border.width: 0 + Behavior on x { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } + Behavior on y { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } FluShadow{ radius: 5 } @@ -193,10 +325,21 @@ Popup{ leftMargin: 15 } } + FluLoader{ + readonly property int total: steps.length + readonly property int current: control.index + sourceComponent: control.indicator + anchors{ + bottom: parent.bottom + left: parent.left + bottomMargin: 15 + leftMargin: 15 + } + } FluLoader{ id: loader_next property bool isEnd: control.index === steps.length-1 - sourceComponent: com_next_button + sourceComponent: control.nextButton anchors{ top: text_desc.bottom topMargin: 10 @@ -207,7 +350,7 @@ Popup{ FluLoader{ id: loader_prev visible: control.index !== 0 - sourceComponent: com_prev_button + sourceComponent: control.prevButton anchors{ right: loader_next.left top: loader_next.top @@ -246,5 +389,17 @@ Popup{ } return 0 } + Behavior on x { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } + Behavior on y { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } } } diff --git a/src/Qt5/imports/FluentUI/plugins.qmltypes b/src/Qt5/imports/FluentUI/plugins.qmltypes index 26d694db..5790dc12 100644 --- a/src/Qt5/imports/FluentUI/plugins.qmltypes +++ b/src/Qt5/imports/FluentUI/plugins.qmltypes @@ -231,6 +231,10 @@ Module { exportMetaObjectRevisions: [0] Property { name: "color"; type: "QColor" } Property { name: "radius"; type: "QList" } + Property { name: "borderWidth"; type: "double" } + Property { name: "borderColor"; type: "QColor" } + Property { name: "borderStyle"; type: "Qt::PenStyle" } + Property { name: "dashPattern"; type: "QVector" } } Component { name: "FluSheetType" @@ -2776,7 +2780,7 @@ Module { } Property { name: "layoutMacosButtons" - type: "FluLoader_QMLTYPE_14" + type: "FluLoader_QMLTYPE_12" isReadonly: true isPointer: true } @@ -2797,12 +2801,16 @@ Module { Property { name: "items"; type: "QVariant" } Property { name: "emptyText"; type: "string" } Property { name: "autoSuggestBoxReplacement"; type: "int" } + Property { name: "itemHeight"; type: "int" } + Property { name: "itemRows"; type: "int" } + Property { name: "showSuggestWhenPressed"; type: "bool" } Property { name: "textRole"; type: "string" } Property { name: "filter"; type: "QVariant" } Signal { name: "itemClicked" Parameter { name: "data"; type: "QVariant" } } + Method { name: "showSuggest"; type: "QVariant" } Method { name: "updateText" type: "QVariant" @@ -2830,8 +2838,9 @@ Module { defaultProperty: "data" Property { name: "isDot"; type: "bool" } Property { name: "showZero"; type: "bool" } - Property { name: "count"; type: "int" } - Property { name: "topRight"; type: "bool" } + Property { name: "count"; type: "QVariant" } + Property { name: "max"; type: "int" } + Property { name: "position"; type: "string" } } Component { prototype: "QQuickItem" @@ -3479,8 +3488,8 @@ Module { Property { name: "actionItem"; type: "QQmlComponent"; isPointer: true } Property { name: "topPadding"; type: "int" } Property { name: "pageMode"; type: "int" } - Property { name: "navItemRightMenu"; type: "FluMenu_QMLTYPE_47"; isPointer: true } - Property { name: "navItemExpanderRightMenu"; type: "FluMenu_QMLTYPE_47"; isPointer: true } + Property { name: "navItemRightMenu"; type: "FluMenu_QMLTYPE_49"; isPointer: true } + Property { name: "navItemExpanderRightMenu"; type: "FluMenu_QMLTYPE_49"; isPointer: true } Property { name: "navCompactWidth"; type: "int" } Property { name: "navTopMargin"; type: "int" } Property { name: "cellHeight"; type: "int" } @@ -4085,6 +4094,7 @@ Module { Property { name: "borderColor"; type: "QColor" } Property { name: "horizonalHeaderVisible"; type: "bool" } Property { name: "verticalHeaderVisible"; type: "bool" } + Property { name: "startRowIndex"; type: "int" } Property { name: "selectedBorderColor"; type: "QColor" } Property { name: "selectedColor"; type: "QColor" } Property { name: "columnWidthProvider"; type: "QVariant" } @@ -4320,8 +4330,10 @@ Module { defaultProperty: "contentData" Property { name: "steps"; type: "QVariant" } Property { name: "targetMargins"; type: "int" } + Property { name: "targetRadius"; type: "int" } Property { name: "nextButton"; type: "QQmlComponent"; isPointer: true } Property { name: "prevButton"; type: "QQmlComponent"; isPointer: true } + Property { name: "indicator"; type: "QQmlComponent"; isPointer: true } Property { name: "index"; type: "int" } Property { name: "finishText"; type: "string" } Property { name: "nextText"; type: "string" } diff --git a/src/Qt6/imports/FluentUI/Controls/FluAutoSuggestBox.qml b/src/Qt6/imports/FluentUI/Controls/FluAutoSuggestBox.qml index 18119013..93697196 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluAutoSuggestBox.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluAutoSuggestBox.qml @@ -6,9 +6,12 @@ FluTextBox{ property var items:[] property string emptyText: qsTr("No results found") property int autoSuggestBoxReplacement: FluentIcons.Search + property int itemHeight: 38 + property int itemRows: 8 + property bool showSuggestWhenPressed: false property string textRole: "title" property var filter: function(item){ - if(item.title.indexOf(control.text)!==-1){ + if(item[textRole].indexOf(control.text)!==-1){ return true } return false @@ -28,17 +31,11 @@ FluTextBox{ control.updateText(modelData[textRole]) } function loadData(){ - var result = [] if(items==null){ - list_view.model = result + list_view.model = [] return } - items.map(function(item){ - if(control.filter(item)){ - result.push(item) - } - }) - list_view.model = result + list_view.model = items.filter(item => control.filter(item)) } } onActiveFocusChanged: { @@ -68,7 +65,7 @@ FluTextBox{ ScrollBar.vertical: FluScrollBar {} header: Item{ width: control.width - height: visible ? 38 : 0 + height: visible ? control.itemHeight : 0 visible: list_view.count === 0 FluText{ text: emptyText @@ -81,7 +78,7 @@ FluTextBox{ } delegate:FluControl{ id: item_control - height: 38 + height: control.itemHeight width: control.width onClicked: { d.handleClick(modelData) @@ -113,7 +110,7 @@ FluTextBox{ background:Rectangle{ id: rect_background implicitWidth: control.width - implicitHeight: 38*Math.min(Math.max(list_view.count,1),8) + implicitHeight: control.itemHeight*Math.min(Math.max(list_view.count,1),control.itemRows) radius: 5 color: FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(1,1,1,1) border.color: FluTheme.dark ? Qt.rgba(26/255,26/255,26/255,1) : Qt.rgba(191/255,191/255,191/255,1) @@ -123,6 +120,14 @@ FluTextBox{ } } onTextChanged: { + control.showSuggest() + } + onPressed: { + if(control.showSuggestWhenPressed){ + control.showSuggest() + } + } + function showSuggest(){ d.loadData() if(d.flagVisible){ var pos = control.mapToItem(null, 0, 0) diff --git a/src/Qt6/imports/FluentUI/Controls/FluBadge.qml b/src/Qt6/imports/FluentUI/Controls/FluBadge.qml index 2e88c728..2c390c48 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluBadge.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluBadge.qml @@ -5,19 +5,15 @@ import FluentUI Rectangle{ property bool isDot: false property bool showZero: false - property int count: 0 - property bool topRight: false + property var count: 0 + property int max: 99 + property string position: "" // topLeft, topRight, bottomLeft, bottomRight id:control color:Qt.rgba(255/255,77/255,79/255,1) width: { if(isDot) return 10 - if(count<10){ - return 20 - }else if(count<100){ - return 30 - } - return 40 + return content_text.implicitWidth + 12 } height: { if(isDot) @@ -31,49 +27,74 @@ Rectangle{ } border.width: 1 border.color: Qt.rgba(1,1,1,1) - anchors{ + anchors { + left: { + if(!parent){ + return undefined + } + return (position === "topLeft" || position === "bottomLeft") ? parent.left : undefined + } right: { - if(parent && topRight) - return parent.right - return undefined + if(!parent){ + return undefined + } + return (position === "topRight" || position === "bottomRight") ? parent.right : undefined } top: { - if(parent && topRight) - return parent.top - return undefined + if(!parent){ + return undefined + } + return (position === "topLeft" || position === "topRight") ? parent.top : undefined + } + bottom: { + if(!parent){ + return undefined + } + return (position === "bottomLeft" || position === "bottomRight") ? parent.bottom : undefined + } + leftMargin: { + if(!parent){ + return 0 + } + return (position === "topLeft" || position === "bottomLeft") ? (isDot ? -2.5 : -(width / 2)) : 0 } rightMargin: { - if(parent && topRight){ - if(isDot){ - return -2.5 - } - return -(control.width/2) + if(!parent){ + return 0 } - return 0 + return (position === "topRight" || position === "bottomRight") ? (isDot ? -2.5 : -(width / 2)) : 0 } topMargin: { - if(parent && topRight){ - if(isDot){ - return -2.5 - } - return -10 + if(!parent){ + return 0 } - return 0 + return (position === "topLeft" || position === "topRight") ? (isDot ? -2.5 : -10) : 0 + } + bottomMargin: { + if(!parent){ + return 0 + } + return (position === "bottomLeft" || position === "bottomRight") ? (isDot ? -2.5 : -10) : 0 } } visible: { - if(showZero) - return true - return count!==0 + if(typeof(count) === "number"){ + return showZero ? true : count !== 0 + } + return true } FluText{ + id: content_text anchors.centerIn: parent color: Qt.rgba(1,1,1,1) visible: !isDot text:{ - if(count<100) + if(typeof(count) === "string"){ return count - return "100+" + }else if(typeof(count) === "number"){ + return count <= max ? count.toString() : "%1+".arg(max.toString()) + } + return "" } } } diff --git a/src/Qt6/imports/FluentUI/Controls/FluComboBox.qml b/src/Qt6/imports/FluentUI/Controls/FluComboBox.qml index 6dc161b1..6a8662c4 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluComboBox.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluComboBox.qml @@ -55,7 +55,7 @@ T.ComboBox { font:control.font readOnly: control.down color: { - if(control.disabled) { + if(!control.enabled) { return FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) } return FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1) @@ -97,7 +97,7 @@ T.ComboBox { anchors.margins: -2 } color:{ - if(disabled){ + if(!enabled){ return disableColor } return hovered ? hoverColor :normalColor diff --git a/src/Qt6/imports/FluentUI/Controls/FluDatePicker.qml b/src/Qt6/imports/FluentUI/Controls/FluDatePicker.qml index 7afd1ca3..3c3a2ac5 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluDatePicker.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluDatePicker.qml @@ -178,7 +178,12 @@ FluButton { } if(type === 1){ text_month.text = model + let day = list_view_3.model[list_view_3.currentIndex] list_view_3.model = generateMonthDaysArray(list_view_1.model[list_view_1.currentIndex],list_view_2.model[list_view_2.currentIndex]) + if(list_view_3.model.indexOf(day) === -1){ + day = list_view_3.model[list_view_3.model.length - 1] + } + list_view_3.currentIndex = list_view_3.model.indexOf(day) text_day.text = list_view_3.model[list_view_3.currentIndex] } diff --git a/src/Qt6/imports/FluentUI/Controls/FluMenuBarItem.qml b/src/Qt6/imports/FluentUI/Controls/FluMenuBarItem.qml index 03e06cf0..9e0c6891 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluMenuBarItem.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluMenuBarItem.qml @@ -7,7 +7,7 @@ T.MenuBarItem { property bool disabled: false property color textColor: { if(FluTheme.dark){ - if(disabled){ + if(!enabled){ return Qt.rgba(131/255,131/255,131/255,1) } if(pressed){ @@ -15,7 +15,7 @@ T.MenuBarItem { } return Qt.rgba(1,1,1,1) }else{ - if(disabled){ + if(!enabled){ return Qt.rgba(160/255,160/255,160/255,1) } if(pressed){ diff --git a/src/Qt6/imports/FluentUI/Controls/FluSpinBox.qml b/src/Qt6/imports/FluentUI/Controls/FluSpinBox.qml index 7dcc6294..335d73eb 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluSpinBox.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluSpinBox.qml @@ -140,13 +140,13 @@ T.SpinBox { radius: 4 border.width: 1 border.color: { - if(contentItem.disabled){ + if(!contentItem.enabled){ 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) } color: { - if(contentItem.disabled){ + if(!contentItem.enabled){ return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) } if(contentItem.activeFocus){ diff --git a/src/Qt6/imports/FluentUI/Controls/FluTableView.qml b/src/Qt6/imports/FluentUI/Controls/FluTableView.qml index 7efea849..ebb50392 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluTableView.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluTableView.qml @@ -17,6 +17,7 @@ Rectangle { property color borderColor: FluTheme.dark ? Qt.rgba(37/255,37/255,37/255,1) : Qt.rgba(228/255,228/255,228/255,1) property bool horizonalHeaderVisible: true property bool verticalHeaderVisible: true + property int startRowIndex: 1 property color selectedBorderColor: FluTheme.primaryColor property color selectedColor: FluTools.withOpacity(FluTheme.primaryColor,0.3) property alias view: table_view @@ -266,30 +267,18 @@ Rectangle { d.rowHoverIndex = row } onWidthChanged: { - if(editVisible){ - updateEditPosition() - } - if(isMainTable){ - updateTableItem() - } + updatePosition() } onHeightChanged: { - if(editVisible){ - updateEditPosition() - } - if(isMainTable){ - updateTableItem() - } + updatePosition() } onXChanged: { - if(editVisible){ - updateEditPosition() - } - if(isMainTable){ - updateTableItem() - } + updatePosition() } onYChanged: { + updatePosition() + } + function updatePosition(){ if(editVisible){ updateEditPosition() } @@ -310,9 +299,11 @@ Rectangle { } function updateTableItem(){ var columnModel = control.columnSource[column] - columnModel.x = item_table_mouse.x - columnModel.y = item_table_mouse.y - d.tableItemLayout(column) + if(columnModel.x !== item_table_mouse.x || columnModel.y !== item_table_mouse.y){ + columnModel.x = item_table_mouse.x + columnModel.y = item_table_mouse.y + d.tableItemLayout(column) + } } Rectangle{ anchors.fill: parent @@ -352,6 +343,7 @@ Rectangle { } FluLoader{ id: item_table_loader + property var tableView: control property var model: item_table_mouse._model property var display: rowModel[columnModel.dataIndex] property var rowModel : model.rowModel @@ -445,10 +437,6 @@ Rectangle { } } - onWidthChanged:{ - table_view.forceLayout() - } - MouseArea{ id:layout_mouse_table hoverEnabled: true @@ -479,6 +467,9 @@ Rectangle { table_view.flick(0,1) } delegate: com_table_delegate + onWidthChanged: { + Qt.callLater(forceLayout) + } } } @@ -851,7 +842,13 @@ Rectangle { Connections{ target: table_view function onRowsChanged(){ - header_row_model.rows = Array.from({length: table_view.rows}, (_, i) => ({rowIndex:i+1})) + header_vertical.updateRowIndex() + } + } + Connections { + target: control + function onStartRowIndexChanged(){ + header_vertical.updateRowIndex() } } Timer{ @@ -861,6 +858,9 @@ Rectangle { header_vertical.forceLayout() } } + function updateRowIndex(){ + header_row_model.rows = Array.from({length: table_view.rows}, (_, i) => ({rowIndex:i+control.startRowIndex})) + } } Item{ anchors{ @@ -955,18 +955,18 @@ Rectangle { target: d function onTableItemLayout(column){ if(item_layout_frozen._index === column){ - updateLayout() + Qt.callLater(updateLayout) } } } Connections{ target: table_view function onContentXChanged(){ - updateLayout() + Qt.callLater(updateLayout) } } function updateLayout(){ - width = table_view.columnWidthProvider(_index) + width = Qt.binding(() => table_view.columnWidthProvider(_index)) x = Qt.binding(function(){ var minX = 0 var maxX = table_view.width-width diff --git a/src/Qt6/imports/FluentUI/Controls/FluTextBoxBackground.qml b/src/Qt6/imports/FluentUI/Controls/FluTextBoxBackground.qml index a57cff5a..44a4604e 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluTextBoxBackground.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluTextBoxBackground.qml @@ -6,7 +6,7 @@ FluControlBackground{ property Item inputItem id:control color: { - if(inputItem && inputItem.disabled){ + if(inputItem && !inputItem.enabled){ return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) } if(inputItem && inputItem.activeFocus){ diff --git a/src/Qt6/imports/FluentUI/Controls/FluTour.qml b/src/Qt6/imports/FluentUI/Controls/FluTour.qml index fea6368b..5049c9cc 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluTour.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluTour.qml @@ -7,8 +7,10 @@ import FluentUI Popup{ property var steps : [] property int targetMargins: 5 + property int targetRadius: 2 property Component nextButton: com_next_button property Component prevButton: com_prev_button + property Component indicator: com_indicator property int index : 0 property string finishText: qsTr("Finish") property string nextText: qsTr("Next") @@ -22,12 +24,12 @@ Popup{ contentItem: Item{} onVisibleChanged: { if(visible){ + d.animationEnabled = false control.index = 0 + d.updatePos() + d.animationEnabled = true } } - onIndexChanged: { - canvas.requestPaint() - } Component{ id: com_next_button FluFilledButton{ @@ -50,10 +52,32 @@ Popup{ } } } + Component{ + id: com_indicator + Row{ + spacing: 10 + Repeater{ + model: total + delegate: Rectangle{ + width: 8 + height: 8 + radius: 4 + scale: current === index ? 1.2 : 1 + color:{ + if(current === index){ + return FluTheme.primaryColor + } + return FluTheme.dark ? Qt.rgba(99/255,99/255,99/255,1) : Qt.rgba(214/255,214/255,214/255,1) + } + } + } + } + } Item{ id:d property var window: Window.window property point pos: Qt.point(0,0) + property bool animationEnabled: true property var step: steps[index] property var target: { if(steps[index]){ @@ -73,15 +97,22 @@ Popup{ } return control.width } + function updatePos(){ + if(d.target && d.window){ + d.pos = d.target.mapToGlobal(0,0) + d.pos = Qt.point(d.pos.x-d.window.x,d.pos.y-d.window.y) + } + } + onTargetChanged: { + updatePos() + } } Connections{ target: d.window function onWidthChanged(){ - canvas.requestPaint() timer_delay.restart() } function onHeightChanged(){ - canvas.requestPaint() timer_delay.restart() } } @@ -89,39 +120,128 @@ Popup{ id: timer_delay interval: 200 onTriggered: { - canvas.requestPaint() + d.updatePos() } } - Canvas{ - id: canvas - anchors.fill: parent - onPaint: { - d.pos = d.target.mapToGlobal(0,0) - d.pos = Qt.point(d.pos.x-d.window.x,d.pos.y-d.window.y) - var ctx = canvas.getContext("2d") - ctx.clearRect(0, 0, canvasSize.width, canvasSize.height) - ctx.save() - ctx.fillStyle = "#88000000" - ctx.fillRect(0, 0, canvasSize.width, canvasSize.height) - ctx.globalCompositeOperation = 'destination-out' - ctx.fillStyle = 'black' - var rect = Qt.rect(d.pos.x-control.targetMargins,d.pos.y-control.targetMargins, d.target.width+control.targetMargins*2, d.target.height+control.targetMargins*2) - drawRoundedRect(rect,2,ctx) - ctx.restore() + Item{ + id: targetRect + x: d.pos.x - control.targetMargins + y: d.pos.y - control.targetMargins + width: d.target ? d.target.width + control.targetMargins * 2 : 0 + height: d.target ? d.target.height + control.targetMargins * 2 : 0 + Behavior on x { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } } - function drawRoundedRect(rect, r, ctx) { - ctx.beginPath(); - ctx.moveTo(rect.x + r, rect.y); - ctx.lineTo(rect.x + rect.width - r, rect.y); - ctx.arcTo(rect.x + rect.width, rect.y, rect.x + rect.width, rect.y + r, r); - ctx.lineTo(rect.x + rect.width, rect.y + rect.height - r); - ctx.arcTo(rect.x + rect.width, rect.y + rect.height, rect.x + rect.width - r, rect.y + rect.height, r); - ctx.lineTo(rect.x + r, rect.y + rect.height); - ctx.arcTo(rect.x, rect.y + rect.height, rect.x, rect.y + rect.height - r, r); - ctx.lineTo(rect.x, rect.y + r); - ctx.arcTo(rect.x, rect.y, rect.x + r, rect.y, r); - ctx.closePath(); - ctx.fill() + Behavior on y { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } + Behavior on width { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } + Behavior on height { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } + } + Shape { + anchors.fill: parent + layer.enabled: true + layer.samples: 4 + layer.smooth: true + ShapePath { + fillColor: "#88000000" + strokeWidth: 0 + strokeColor: "transparent" + + // draw background + PathMove { + x: 0 + y: 0 + } + PathLine { + x: control.width + y: 0 + } + PathLine { + x: control.width + y: control.height + } + PathLine { + x: 0 + y: control.height + } + PathLine { + x: 0 + y: 0 + } + + // draw highlight + PathMove { + x: targetRect.x + control.targetRadius + y: targetRect.y + } + PathLine { + x: targetRect.x + targetRect.width - control.targetRadius + y: targetRect.y + } + PathArc { + x: targetRect.x + targetRect.width + y: targetRect.y + control.targetRadius + radiusX: control.targetRadius + radiusY: control.targetRadius + useLargeArc: false + direction: PathArc.Clockwise + } + + PathLine { + x: targetRect.x + targetRect.width + y: targetRect.y + targetRect.height - control.targetRadius + } + PathArc { + x: targetRect.x + targetRect.width - control.targetRadius + y: targetRect.y + targetRect.height + radiusX: control.targetRadius + radiusY: control.targetRadius + useLargeArc: false + direction: PathArc.Clockwise + } + + PathLine { + x: targetRect.x + control.targetRadius + y: targetRect.y + targetRect.height + } + PathArc { + x: targetRect.x + y: targetRect.y + targetRect.height - control.targetRadius + radiusX: control.targetRadius + radiusY: control.targetRadius + useLargeArc: false + direction: PathArc.Clockwise + } + + PathLine { + x: targetRect.x + y: targetRect.y + control.targetRadius + } + PathArc { + x: targetRect.x + control.targetRadius + y: targetRect.y + radiusX: control.targetRadius + radiusY: control.targetRadius + useLargeArc: false + direction: PathArc.Clockwise + } } } FluFrame{ @@ -151,6 +271,18 @@ Popup{ return 0 } border.width: 0 + Behavior on x { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } + Behavior on y { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } FluShadow{ radius: 5 } @@ -193,10 +325,21 @@ Popup{ leftMargin: 15 } } + FluLoader{ + readonly property int total: steps.length + readonly property int current: control.index + sourceComponent: control.indicator + anchors{ + bottom: parent.bottom + left: parent.left + bottomMargin: 15 + leftMargin: 15 + } + } FluLoader{ id: loader_next property bool isEnd: control.index === steps.length-1 - sourceComponent: com_next_button + sourceComponent: control.nextButton anchors{ top: text_desc.bottom topMargin: 10 @@ -207,7 +350,7 @@ Popup{ FluLoader{ id: loader_prev visible: control.index !== 0 - sourceComponent: com_prev_button + sourceComponent: control.prevButton anchors{ right: loader_next.left top: loader_next.top @@ -246,5 +389,17 @@ Popup{ } return 0 } + Behavior on x { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } + Behavior on y { + enabled: d.animationEnabled && FluTheme.animationEnabled + NumberAnimation { + duration: 167 + } + } } }