diff --git a/example/qml-Qt6/page/T_TableView.qml b/example/qml-Qt6/page/T_TableView.qml index 464b1ad5..c64f676a 100644 --- a/example/qml-Qt6/page/T_TableView.qml +++ b/example/qml-Qt6/page/T_TableView.qml @@ -14,6 +14,16 @@ FluContentPage{ property var dataSource : [] property int sortType: 0 property bool seletedAll: true + property string nameKeyword: "" + + onNameKeywordChanged: { + table_view.filter(function(item){ + if(item.name.includes(nameKeyword)){ + return true + } + return false + }) + } Component.onCompleted: { loadData(1,1000) @@ -34,23 +44,25 @@ FluContentPage{ if(sortType === 0){ table_view.sort() }else if(sortType === 1){ - table_view.sort((l, r) =>{ - var lage = Number(l.age) - var rage = Number(r.age) - if(lage === rage){ - return l._key>r._key - } - return lage>rage - }); + table_view.sort( + (l, r) =>{ + var lage = Number(l.age) + var rage = Number(r.age) + if(lage === rage){ + return l._key>r._key + } + return lage>rage + }); }else if(sortType === 2){ - table_view.sort((l, r) => { - var lage = Number(l.age) - var rage = Number(r.age) - if(lage === rage){ - return l._key>r._key - } - return lage { + var lage = Number(l.age) + var rage = Number(r.age) + if(lage === rage){ + return l._key>r._key + } + return lage item._key === sourceItem._key) + if (!foundItem) { + data.push(sourceItem); } } table_view.dataSource = data @@ -370,7 +475,7 @@ FluContentPage{ width:100 }, { - title: '姓名', + title: table_view.customItem(com_column_filter_name,{title:'姓名'}), dataIndex: 'name', readOnly:true }, diff --git a/example/qml/page/T_TableView.qml b/example/qml/page/T_TableView.qml index 093a1483..e5e89597 100644 --- a/example/qml/page/T_TableView.qml +++ b/example/qml/page/T_TableView.qml @@ -14,6 +14,16 @@ FluContentPage{ property var dataSource : [] property int sortType: 0 property bool seletedAll: true + property string nameKeyword: "" + + onNameKeywordChanged: { + table_view.filter(function(item){ + if(item.name.includes(nameKeyword)){ + return true + } + return false + }) + } Component.onCompleted: { loadData(1,1000) @@ -34,23 +44,25 @@ FluContentPage{ if(sortType === 0){ table_view.sort() }else if(sortType === 1){ - table_view.sort((l, r) =>{ - var lage = Number(l.age) - var rage = Number(r.age) - if(lage === rage){ - return l._key>r._key - } - return lage>rage - }); + table_view.sort( + (l, r) =>{ + var lage = Number(l.age) + var rage = Number(r.age) + if(lage === rage){ + return l._key>r._key + } + return lage>rage + }); }else if(sortType === 2){ - table_view.sort((l, r) => { - var lage = Number(l.age) - var rage = Number(r.age) - if(lage === rage){ - return l._key>r._key - } - return lage { + var lage = Number(l.age) + var rage = Number(r.age) + if(lage === rage){ + return l._key>r._key + } + return lage item._key === sourceItem._key) + if (!foundItem) { + data.push(sourceItem); } } table_view.dataSource = data @@ -370,7 +475,7 @@ FluContentPage{ width:100 }, { - title: '姓名', + title: table_view.customItem(com_column_filter_name,{title:'姓名'}), dataIndex: 'name', readOnly:true }, diff --git a/src/FluTableSortProxyModel.cpp b/src/FluTableSortProxyModel.cpp index 7a9344d0..4101b630 100644 --- a/src/FluTableSortProxyModel.cpp +++ b/src/FluTableSortProxyModel.cpp @@ -8,12 +8,17 @@ FluTableSortProxyModel::FluTableSortProxyModel(QSortFilterProxyModel *parent) _model = nullptr; connect(this,&FluTableSortProxyModel::modelChanged,this,[=]{ setSourceModel(this->model()); - sort(0,Qt::AscendingOrder); }); } bool FluTableSortProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const{ - return true; + QJSValue filter = _filter; + if(filter.isUndefined()){ + return true; + } + QJSValueList data; + data<_comparator = comparator; if(sortOrder()==Qt::AscendingOrder){ - sort(0,Qt::DescendingOrder); + sort(column,Qt::DescendingOrder); }else{ - sort(0,Qt::AscendingOrder); + sort(column,Qt::AscendingOrder); } } + +void FluTableSortProxyModel::setFilter(QJSValue filter){ + this->_filter = filter; + invalidateFilter(); +} + QVariant FluTableSortProxyModel::getRow(int rowIndex){ QVariant result; QMetaObject::invokeMethod(_model, "getRow",Q_RETURN_ARG(QVariant, result),Q_ARG(int, mapToSource(index(rowIndex,0)).row())); diff --git a/src/FluTableSortProxyModel.h b/src/FluTableSortProxyModel.h index c470f780..baa1b84c 100644 --- a/src/FluTableSortProxyModel.h +++ b/src/FluTableSortProxyModel.h @@ -17,11 +17,13 @@ public: bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; bool filterAcceptsColumn(int sourceColumn, const QModelIndex &sourceParent) const override; bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override; - Q_INVOKABLE void setSortComparator(QJSValue comparator); Q_INVOKABLE QVariant getRow(int rowIndex); Q_INVOKABLE void setRow(int rowIndex,QVariant val); Q_INVOKABLE void removeRow(int rowIndex,int rows); + Q_INVOKABLE void setComparator(QJSValue comparator); + Q_INVOKABLE void setFilter(QJSValue filter); private: + QJSValue _filter; QJSValue _comparator; }; diff --git a/src/Qt5/imports/FluentUI/Controls/FluTableView.qml b/src/Qt5/imports/FluentUI/Controls/FluTableView.qml index 4b939deb..541756df 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluTableView.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluTableView.qml @@ -12,6 +12,9 @@ Rectangle { property alias columns: table_view.columns property bool horizonalHeaderVisible: true property bool verticalHeaderVisible: true + property color selectedBorderColor: FluTheme.primaryColor + property color selectedColor: FluTools.colorAlpha(FluTheme.primaryColor,0.3) + property alias sourceModel: table_model id:control color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1) onColumnSourceChanged: { @@ -44,7 +47,7 @@ Rectangle { item_loader_layout.cellItem = cellItem item_loader_layout.x = table_view.contentX + cellPosition.x item_loader_layout.y = table_view.contentY + cellPosition.y - item_loader_layout.width = table_view.columnWidthProvider(column) + item_loader_layout.width = header_horizontal.columnWidthProvider(column) item_loader_layout.height = table_view.rowHeightProvider(row) item_loader.display = display var obj =columnSource[column].editDelegate @@ -198,25 +201,8 @@ Rectangle { ScrollBar.vertical: FluScrollBar{ id:scroll_bar_v } - columnWidthProvider: function(column) { - var w = columnSource[column].width - if(!w){ - w = columnSource[column].minimumWidth - } - if(!w){ - w = d.defaultItemWidth - } - if(item_loader_layout.cellItem){ - if(column === item_loader.column){ - item_loader_layout.width = w - } - if(column === item_loader.column-1){ - let cellPosition = item_loader_layout.cellItem.mapToItem(scroll_table, 0, 0) - item_loader_layout.x = table_view.contentX + cellPosition.x - } - } - return w - } + syncView: header_horizontal + syncDirection: Qt.Horizontal rowHeightProvider: function(row) { if(row>=table_view.rows){ return 0 @@ -240,7 +226,7 @@ Rectangle { } return h } - model: table_model + model: table_sort_model clip: true onRowsChanged: { closeEditor() @@ -276,23 +262,14 @@ Rectangle { return false } color:{ + if(item_table.isRowSelected){ + return control.selectedColor + } if(d.rowHoverIndex === row || item_table.isRowSelected){ return FluTheme.dark ? Qt.rgba(1,1,1,0.06) : Qt.rgba(0,0,0,0.06) } return (row%2!==0) ? control.color : (FluTheme.dark ? Qt.rgba(1,1,1,0.015) : Qt.rgba(0,0,0,0.015)) } - Rectangle{ - height: 18 - radius: 1.5 - color: FluTheme.primaryColor - width: 3 - visible: item_table.isRowSelected && column === 0 - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - leftMargin: 3 - } - } MouseArea{ anchors.fill: parent acceptedButtons: Qt.LeftButton @@ -335,6 +312,36 @@ Rectangle { return com_text } } + Item{ + anchors.fill: parent + visible: item_table.isRowSelected + Rectangle{ + width: 1 + height: parent.height + anchors.left: parent.left + color: control.selectedBorderColor + visible: column === 0 + } + Rectangle{ + width: 1 + height: parent.height + anchors.right: parent.right + color: control.selectedBorderColor + visible: column === control.columns-1 + } + Rectangle{ + width: parent.width + height: 1 + anchors.top: parent.top + color: control.selectedBorderColor + } + Rectangle{ + width: parent.width + height: 1 + anchors.bottom: parent.bottom + color: control.selectedBorderColor + } + } } } } @@ -397,11 +404,29 @@ Rectangle { anchors.left: scroll_table.left anchors.top: parent.top visible: control.horizonalHeaderVisible - implicitWidth: syncView ? syncView.width : 0 + implicitWidth: table_view.width implicitHeight: visible ? Math.max(1, contentHeight) : 0 - syncView: table_view boundsBehavior: Flickable.StopAtBounds clip: true + columnWidthProvider: function(column) { + var w = columnSource[column].width + if(!w){ + w = columnSource[column].minimumWidth + } + if(!w){ + w = d.defaultItemWidth + } + if(item_loader_layout.cellItem){ + if(column === item_loader.column){ + item_loader_layout.width = w + } + if(column === item_loader.column-1){ + let cellPosition = item_loader_layout.cellItem.mapToItem(scroll_table, 0, 0) + item_loader_layout.x = table_view.contentX + cellPosition.x + } + } + return w + } delegate: Rectangle { id:column_item_control readonly property real cellPadding: 8 @@ -524,7 +549,7 @@ Rectangle { maximumWidth = 65535 } columnObject.width = Math.min(Math.max(minimumWidth, w + delta.x),maximumWidth) - table_view.forceLayout() + header_horizontal.forceLayout() } } } @@ -687,14 +712,22 @@ Rectangle { o.options = options return o } - function sort(order){ - if(order === undefined){ - table_view.model = table_model - }else{ - table_view.model = table_sort_model - table_sort_model.setSortComparator(function(left,right){ - return order(table_model.getRow(left),table_model.getRow(right)) + function sort(callback=undefined){ + if(callback){ + table_sort_model.setComparator(function(left,right){ + return callback(table_model.getRow(left),table_model.getRow(right)) }) + }else{ + table_sort_model.setComparator(undefined) + } + } + function filter(callback=undefined){ + if(callback){ + table_sort_model.setFilter(function(index){ + return callback(table_model.getRow(index)) + }) + }else{ + table_sort_model.setFilter(undefined) } } function setRow(rowIndex,obj){ diff --git a/src/Qt6/imports/FluentUI/Controls/FluTableView.qml b/src/Qt6/imports/FluentUI/Controls/FluTableView.qml index 0af24ab4..223d9631 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluTableView.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluTableView.qml @@ -13,6 +13,9 @@ Rectangle { property alias columns: table_view.columns property bool horizonalHeaderVisible: true property bool verticalHeaderVisible: true + property color selectedBorderColor: FluTheme.primaryColor + property color selectedColor: FluTools.colorAlpha(FluTheme.primaryColor,0.3) + property alias sourceModel: table_model id:control color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1) onColumnSourceChanged: { @@ -45,7 +48,7 @@ Rectangle { item_loader_layout.cellItem = cellItem item_loader_layout.x = table_view.contentX + cellPosition.x item_loader_layout.y = table_view.contentY + cellPosition.y - item_loader_layout.width = table_view.columnWidthProvider(column) + item_loader_layout.width = header_horizontal.columnWidthProvider(column) item_loader_layout.height = table_view.rowHeightProvider(row) item_loader.display = display var obj =columnSource[column].editDelegate @@ -199,25 +202,8 @@ Rectangle { ScrollBar.vertical: FluScrollBar{ id:scroll_bar_v } - columnWidthProvider: function(column) { - var w = columnSource[column].width - if(!w){ - w = columnSource[column].minimumWidth - } - if(!w){ - w = d.defaultItemWidth - } - if(item_loader_layout.cellItem){ - if(column === item_loader.column){ - item_loader_layout.width = w - } - if(column === item_loader.column-1){ - let cellPosition = item_loader_layout.cellItem.mapToItem(scroll_table, 0, 0) - item_loader_layout.x = table_view.contentX + cellPosition.x - } - } - return w - } + syncView: header_horizontal + syncDirection: Qt.Horizontal rowHeightProvider: function(row) { if(row>=table_view.rows){ return 0 @@ -241,7 +227,7 @@ Rectangle { } return h } - model: table_model + model: table_sort_model clip: true onRowsChanged: { closeEditor() @@ -277,23 +263,14 @@ Rectangle { return false } color:{ + if(item_table.isRowSelected){ + return control.selectedColor + } if(d.rowHoverIndex === row || item_table.isRowSelected){ return FluTheme.dark ? Qt.rgba(1,1,1,0.06) : Qt.rgba(0,0,0,0.06) } return (row%2!==0) ? control.color : (FluTheme.dark ? Qt.rgba(1,1,1,0.015) : Qt.rgba(0,0,0,0.015)) } - Rectangle{ - height: 18 - radius: 1.5 - color: FluTheme.primaryColor - width: 3 - visible: item_table.isRowSelected && column === 0 - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - leftMargin: 3 - } - } MouseArea{ anchors.fill: parent acceptedButtons: Qt.LeftButton @@ -336,6 +313,36 @@ Rectangle { return com_text } } + Item{ + anchors.fill: parent + visible: item_table.isRowSelected + Rectangle{ + width: 1 + height: parent.height + anchors.left: parent.left + color: control.selectedBorderColor + visible: column === 0 + } + Rectangle{ + width: 1 + height: parent.height + anchors.right: parent.right + color: control.selectedBorderColor + visible: column === control.columns-1 + } + Rectangle{ + width: parent.width + height: 1 + anchors.top: parent.top + color: control.selectedBorderColor + } + Rectangle{ + width: parent.width + height: 1 + anchors.bottom: parent.bottom + color: control.selectedBorderColor + } + } } } } @@ -398,11 +405,29 @@ Rectangle { anchors.left: scroll_table.left anchors.top: parent.top visible: control.horizonalHeaderVisible - implicitWidth: syncView ? syncView.width : 0 + implicitWidth: table_view.width implicitHeight: visible ? Math.max(1, contentHeight) : 0 - syncView: table_view boundsBehavior: Flickable.StopAtBounds clip: true + columnWidthProvider: function(column) { + var w = columnSource[column].width + if(!w){ + w = columnSource[column].minimumWidth + } + if(!w){ + w = d.defaultItemWidth + } + if(item_loader_layout.cellItem){ + if(column === item_loader.column){ + item_loader_layout.width = w + } + if(column === item_loader.column-1){ + let cellPosition = item_loader_layout.cellItem.mapToItem(scroll_table, 0, 0) + item_loader_layout.x = table_view.contentX + cellPosition.x + } + } + return w + } delegate: Rectangle { id:column_item_control readonly property real cellPadding: 8 @@ -525,7 +550,7 @@ Rectangle { maximumWidth = 65535 } columnObject.width = Math.min(Math.max(minimumWidth, w + delta.x),maximumWidth) - table_view.forceLayout() + header_horizontal.forceLayout() } } } @@ -688,14 +713,22 @@ Rectangle { o.options = options return o } - function sort(order){ - if(order === undefined){ - table_view.model = table_model - }else{ - table_view.model = table_sort_model - table_sort_model.setSortComparator(function(left,right){ - return order(table_model.getRow(left),table_model.getRow(right)) + function sort(callback=undefined){ + if(callback){ + table_sort_model.setComparator(function(left,right){ + return callback(table_model.getRow(left),table_model.getRow(right)) }) + }else{ + table_sort_model.setComparator(undefined) + } + } + function filter(callback=undefined){ + if(callback){ + table_sort_model.setFilter(function(index){ + return callback(table_model.getRow(index)) + }) + }else{ + table_sort_model.setFilter(undefined) } } function setRow(rowIndex,obj){