mirror of
https://github.com/zhuzichu520/FluentUI.git
synced 2024-11-23 11:17:15 +08:00
update
This commit is contained in:
parent
67ef7f13aa
commit
f88b330f8e
@ -302,7 +302,7 @@ FluObject{
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
FluPaneItem{
|
||||
title:"TreeView(Todo)"
|
||||
title:"TreeView"
|
||||
url:"qrc:/example/qml/page/T_TreeView.qml"
|
||||
onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) }
|
||||
onTap:{ navigationView.push(url) }
|
||||
|
@ -12,7 +12,7 @@ FluContentPage {
|
||||
function treeData(){
|
||||
const dig = (path = '0', level = 4) => {
|
||||
const list = [];
|
||||
for (let i = 0; i < 9; i += 1) {
|
||||
for (let i = 0; i < 6; i += 1) {
|
||||
const key = `${path}-${i}`;
|
||||
const treeNode = {
|
||||
title: key,
|
||||
@ -45,6 +45,10 @@ FluContentPage {
|
||||
text:"共计%1条数据,当前显示的%2条数据".arg(tree_view.count()).arg(tree_view.visibleCount())
|
||||
}
|
||||
|
||||
FluText{
|
||||
text:"共计选中%1条数据".arg(tree_view.selectionModel().length)
|
||||
}
|
||||
|
||||
RowLayout{
|
||||
spacing: 10
|
||||
FluText{
|
||||
@ -74,12 +78,17 @@ FluContentPage {
|
||||
FluToggleSwitch{
|
||||
id:switch_showline
|
||||
text:"showLine"
|
||||
checked: true
|
||||
checked: false
|
||||
}
|
||||
FluToggleSwitch{
|
||||
id:switch_draggable
|
||||
text:"draggable"
|
||||
checked: true
|
||||
checked: false
|
||||
}
|
||||
FluToggleSwitch{
|
||||
id:switch_checkable
|
||||
text:"checkable"
|
||||
checked: false
|
||||
}
|
||||
FluButton{
|
||||
text:"all expand"
|
||||
@ -111,6 +120,7 @@ FluContentPage {
|
||||
cellHeight: slider_cell_height.value
|
||||
draggable:switch_draggable.checked
|
||||
showLine: switch_showline.checked
|
||||
checkable:switch_checkable.checked
|
||||
depthPadding: slider_depth_padding.value
|
||||
Component.onCompleted: {
|
||||
var data = treeData()
|
||||
|
@ -302,7 +302,7 @@ FluObject{
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
FluPaneItem{
|
||||
title:"TreeView(Todo)"
|
||||
title:"TreeView"
|
||||
url:"qrc:/example/qml/page/T_TreeView.qml"
|
||||
onDropped:{ FluApp.navigate("/pageWindow",{title:title,url:url}) }
|
||||
onTap:{ navigationView.push(url) }
|
||||
|
@ -13,7 +13,7 @@ FluContentPage {
|
||||
function treeData(){
|
||||
const dig = (path = '0', level = 4) => {
|
||||
const list = [];
|
||||
for (let i = 0; i < 9; i += 1) {
|
||||
for (let i = 0; i < 6; i += 1) {
|
||||
const key = `${path}-${i}`;
|
||||
const treeNode = {
|
||||
title: key,
|
||||
@ -46,6 +46,10 @@ FluContentPage {
|
||||
text:"共计%1条数据,当前显示的%2条数据".arg(tree_view.count()).arg(tree_view.visibleCount())
|
||||
}
|
||||
|
||||
FluText{
|
||||
text:"共计选中%1条数据".arg(tree_view.selectionModel().length)
|
||||
}
|
||||
|
||||
RowLayout{
|
||||
spacing: 10
|
||||
FluText{
|
||||
@ -75,12 +79,17 @@ FluContentPage {
|
||||
FluToggleSwitch{
|
||||
id:switch_showline
|
||||
text:"showLine"
|
||||
checked: true
|
||||
checked: false
|
||||
}
|
||||
FluToggleSwitch{
|
||||
id:switch_draggable
|
||||
text:"draggable"
|
||||
checked: true
|
||||
checked: false
|
||||
}
|
||||
FluToggleSwitch{
|
||||
id:switch_checkable
|
||||
text:"checkable"
|
||||
checked: false
|
||||
}
|
||||
FluButton{
|
||||
text:"all expand"
|
||||
@ -112,6 +121,7 @@ FluContentPage {
|
||||
cellHeight: slider_cell_height.value
|
||||
draggable:switch_draggable.checked
|
||||
showLine: switch_showline.checked
|
||||
checkable:switch_checkable.checked
|
||||
depthPadding: slider_depth_padding.value
|
||||
Component.onCompleted: {
|
||||
var data = treeData()
|
||||
|
@ -1,8 +1,5 @@
|
||||
#include "FluRectangle.h"
|
||||
|
||||
#include <QPainterPath>
|
||||
#include <QSGClipNode>
|
||||
#include <QQuickWindow>
|
||||
|
||||
FluRectangle::FluRectangle(QQuickItem* parent) : QQuickPaintedItem(parent){
|
||||
setFlag(ItemHasContents, true);
|
||||
@ -24,7 +21,7 @@ void FluRectangle::paint(QPainter* painter){
|
||||
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.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);
|
||||
painter->fillPath(path,_color);
|
||||
painter->restore();
|
||||
|
@ -76,6 +76,43 @@ QObject* FluTreeModel::getRow(int row){
|
||||
return _rows.at(row);
|
||||
}
|
||||
|
||||
void FluTreeModel::checkRow(int row,bool chekced){
|
||||
auto itemData = _rows.at(row);
|
||||
if(itemData->hasChildren()){
|
||||
QList<Node*> stack = itemData->_children;
|
||||
std::reverse(stack.begin(), stack.end());
|
||||
while (stack.count() > 0) {
|
||||
auto item = stack.at(stack.count()-1);
|
||||
stack.pop_back();
|
||||
if(!item->hasChildren()){
|
||||
item->_checked = chekced;
|
||||
}
|
||||
QList<Node*> children = item->_children;
|
||||
if(!children.isEmpty()){
|
||||
std::reverse(children.begin(), children.end());
|
||||
foreach (auto c, children) {
|
||||
stack.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(itemData->_checked == chekced){
|
||||
return;
|
||||
}
|
||||
itemData->_checked = chekced;
|
||||
}
|
||||
Q_EMIT layoutChanged(QList<QPersistentModelIndex>(),QAbstractItemModel::VerticalSortHint);
|
||||
QList<Node*> data;
|
||||
foreach (auto item, _dataSource) {
|
||||
if(!item->hasChildren()){
|
||||
if(item->_checked){
|
||||
data.append(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
selectionModel(data);
|
||||
}
|
||||
|
||||
void FluTreeModel::setDataSource(QList<QMap<QString,QVariant>> data){
|
||||
_dataSource.clear();
|
||||
if(_root){
|
||||
@ -84,7 +121,6 @@ void FluTreeModel::setDataSource(QList<QMap<QString,QVariant>> data){
|
||||
}
|
||||
_root = new Node(this);
|
||||
std::reverse(data.begin(), data.end());
|
||||
auto startTime = QDateTime::currentMSecsSinceEpoch();
|
||||
while (data.count() > 0) {
|
||||
auto item = data.at(data.count()-1);
|
||||
data.pop_back();
|
||||
@ -114,7 +150,6 @@ void FluTreeModel::setDataSource(QList<QMap<QString,QVariant>> data){
|
||||
}
|
||||
}
|
||||
}
|
||||
auto endTime = QDateTime::currentMSecsSinceEpoch();
|
||||
beginResetModel();
|
||||
_rows = _dataSource;
|
||||
endResetModel();
|
||||
@ -204,6 +239,7 @@ void FluTreeModel::dragAnddrop(int dragIndex,int dropIndex,bool isDropTopArea){
|
||||
}
|
||||
_rows.move(dragIndex,targetIndex);
|
||||
endMoveRows();
|
||||
|
||||
Q_EMIT layoutAboutToBeChanged();
|
||||
if(dragItem->_parent == dropItem->_parent){
|
||||
QList<Node*>* children = &(dragItem->_parent->_children);
|
||||
|
@ -13,6 +13,7 @@ class Node : public QObject{
|
||||
Q_PROPERTY(QString title READ title CONSTANT)
|
||||
Q_PROPERTY(int depth READ depth CONSTANT)
|
||||
Q_PROPERTY(bool isExpanded READ isExpanded CONSTANT)
|
||||
Q_PROPERTY(bool checked READ checked CONSTANT)
|
||||
public:
|
||||
explicit Node(QObject *parent = nullptr);
|
||||
Q_INVOKABLE QString key(){return _key;};
|
||||
@ -30,6 +31,18 @@ public:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Q_INVOKABLE bool checked(){
|
||||
if(!hasChildren()){
|
||||
return _checked;
|
||||
}
|
||||
foreach (auto item, _children) {
|
||||
if(!item->checked()){
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
Q_INVOKABLE bool hideLineFooter(){
|
||||
if(_parent){
|
||||
auto childIndex = _parent->_children.indexOf(this);
|
||||
@ -57,6 +70,7 @@ public:
|
||||
QString _key="";
|
||||
QString _title="";
|
||||
int _depth=0;
|
||||
bool _checked = false;
|
||||
bool _isExpanded=true;
|
||||
QList<Node*> _children;
|
||||
Node* _parent = nullptr;
|
||||
@ -66,6 +80,7 @@ class FluTreeModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(int,dataSourceSize)
|
||||
Q_PROPERTY_AUTO(QList<Node*>,selectionModel)
|
||||
QML_NAMED_ELEMENT(FluTreeModel)
|
||||
QML_ADDED_IN_MINOR_VERSION(1)
|
||||
public:
|
||||
@ -87,6 +102,7 @@ public:
|
||||
Q_INVOKABLE void dragAnddrop(int dragIndex,int dropIndex,bool isDropTopArea);
|
||||
Q_INVOKABLE Node* getNode(int row);
|
||||
Q_INVOKABLE void refreshNode(int row);
|
||||
Q_INVOKABLE void checkRow(int row,bool chekced);
|
||||
Q_INVOKABLE bool hitHasChildrenExpanded(int row);
|
||||
Q_INVOKABLE void allExpand();
|
||||
Q_INVOKABLE void allCollapse();
|
||||
|
@ -22,6 +22,7 @@ Button {
|
||||
property alias textColor: btn_text.textColor
|
||||
property bool textRight: true
|
||||
property real textSpacing: 6
|
||||
property bool enableAnimation: FluTheme.enableAnimation
|
||||
property var clickListener : function(){
|
||||
checked = !checked
|
||||
}
|
||||
@ -39,8 +40,9 @@ Button {
|
||||
visible: control.activeFocus
|
||||
}
|
||||
}
|
||||
horizontalPadding:2
|
||||
verticalPadding: 2
|
||||
horizontalPadding:0
|
||||
verticalPadding: 0
|
||||
padding: 0
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: control.text
|
||||
Accessible.description: contentDescription
|
||||
@ -91,7 +93,7 @@ Button {
|
||||
return normalColor
|
||||
}
|
||||
Behavior on color {
|
||||
enabled: FluTheme.enableAnimation
|
||||
enabled: control.enableAnimation
|
||||
ColorAnimation{
|
||||
duration: 83
|
||||
}
|
||||
@ -103,7 +105,7 @@ Button {
|
||||
visible: checked
|
||||
iconColor: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1)
|
||||
Behavior on visible {
|
||||
enabled: FluTheme.enableAnimation
|
||||
enabled: control.enableAnimation
|
||||
NumberAnimation{
|
||||
duration: 83
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ Item {
|
||||
property bool draggable: false
|
||||
property int cellHeight: 30
|
||||
property int depthPadding: 30
|
||||
property bool checkable: 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 {
|
||||
@ -50,7 +51,7 @@ Item {
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "opacity"
|
||||
duration: 300
|
||||
duration: 88
|
||||
from: 0
|
||||
to: 1
|
||||
}
|
||||
@ -69,7 +70,7 @@ Item {
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "opacity"
|
||||
duration: 300
|
||||
duration: 88
|
||||
from: 0
|
||||
to: 1
|
||||
}
|
||||
@ -197,6 +198,11 @@ Item {
|
||||
var viewPos = table_view.mapToGlobal(0,0)
|
||||
var y = table_view.contentY + pos.y-viewPos.y
|
||||
var index = Math.floor(y/control.cellHeight)
|
||||
if(index<0 || index>table_view.count-1){
|
||||
d.dropIndex = -1
|
||||
return
|
||||
}
|
||||
console.debug(index)
|
||||
if(tree_model.hitHasChildrenExpanded(index) && y>index*control.cellHeight+control.cellHeight/2){
|
||||
d.dropIndex = index + 1
|
||||
d.isDropTopArea = true
|
||||
@ -321,7 +327,10 @@ Item {
|
||||
if(isCurrent){
|
||||
return Qt.rgba(1,1,1,0.06)
|
||||
}
|
||||
if(item_mouse.containsMouse){
|
||||
if(item_mouse.containsMouse || item_check_box.hovered){
|
||||
return Qt.rgba(1,1,1,0.03)
|
||||
}
|
||||
if(item_loader_expand.item && item_loader_expand.item.hovered){
|
||||
return Qt.rgba(1,1,1,0.03)
|
||||
}
|
||||
return Qt.rgba(0,0,0,0)
|
||||
@ -329,7 +338,10 @@ Item {
|
||||
if(isCurrent){
|
||||
return Qt.rgba(0,0,0,0.06)
|
||||
}
|
||||
if(item_mouse.containsMouse){
|
||||
if(item_mouse.containsMouse || item_check_box.hovered){
|
||||
return Qt.rgba(0,0,0,0.03)
|
||||
}
|
||||
if(item_loader_expand.item && item_loader_expand.item.hovered){
|
||||
return Qt.rgba(0,0,0,0.03)
|
||||
}
|
||||
return Qt.rgba(0,0,0,0)
|
||||
@ -341,6 +353,7 @@ Item {
|
||||
height: parent.height
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
spacing: 0
|
||||
anchors.leftMargin: 14 + control.depthPadding*itemModel.depth
|
||||
Component{
|
||||
id:com_icon_btn
|
||||
@ -357,16 +370,36 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader{
|
||||
id:item_loader_expand
|
||||
Layout.preferredWidth: 20
|
||||
Layout.preferredHeight: 20
|
||||
sourceComponent: itemModel.hasChildren() ? com_icon_btn : undefined
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
FluCheckBox{
|
||||
id:item_check_box
|
||||
Layout.preferredWidth: 18
|
||||
Layout.preferredHeight: 18
|
||||
Layout.leftMargin: 5
|
||||
horizontalPadding:0
|
||||
verticalPadding: 0
|
||||
checked: itemModel.checked
|
||||
enableAnimation:false
|
||||
visible: control.checkable
|
||||
padding: 0
|
||||
clickListener: function(){
|
||||
tree_model.checkRow(rowIndex,!itemModel.checked)
|
||||
}
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
Loader{
|
||||
property var modelData: itemModel
|
||||
property var itemMouse: item_mouse
|
||||
id:item_loader_cell
|
||||
Layout.leftMargin: 10
|
||||
Layout.preferredWidth: {
|
||||
if(item){
|
||||
return item.width
|
||||
@ -397,6 +430,9 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
function selectionModel(){
|
||||
return tree_model.selectionModel
|
||||
}
|
||||
function count(){
|
||||
return tree_model.dataSourceSize
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ Button {
|
||||
property alias textColor: btn_text.textColor
|
||||
property bool textRight: true
|
||||
property real textSpacing: 6
|
||||
property bool enableAnimation: FluTheme.enableAnimation
|
||||
property var clickListener : function(){
|
||||
checked = !checked
|
||||
}
|
||||
@ -35,8 +36,9 @@ Button {
|
||||
visible: control.activeFocus
|
||||
}
|
||||
}
|
||||
horizontalPadding:2
|
||||
verticalPadding: 2
|
||||
horizontalPadding:0
|
||||
verticalPadding: 0
|
||||
padding: 0
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: control.text
|
||||
Accessible.description: contentDescription
|
||||
@ -87,7 +89,7 @@ Button {
|
||||
return normalColor
|
||||
}
|
||||
Behavior on color {
|
||||
enabled: FluTheme.enableAnimation
|
||||
enabled: control.enableAnimation
|
||||
ColorAnimation{
|
||||
duration: 83
|
||||
}
|
||||
@ -99,7 +101,7 @@ Button {
|
||||
visible: checked
|
||||
iconColor: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1)
|
||||
Behavior on visible {
|
||||
enabled: FluTheme.enableAnimation
|
||||
enabled: control.enableAnimation
|
||||
NumberAnimation{
|
||||
duration: 83
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ Item {
|
||||
property bool draggable: false
|
||||
property int cellHeight: 30
|
||||
property int depthPadding: 30
|
||||
property bool checkable: 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 {
|
||||
@ -50,7 +51,7 @@ Item {
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "opacity"
|
||||
duration: 300
|
||||
duration: 88
|
||||
from: 0
|
||||
to: 1
|
||||
}
|
||||
@ -69,7 +70,7 @@ Item {
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "opacity"
|
||||
duration: 300
|
||||
duration: 88
|
||||
from: 0
|
||||
to: 1
|
||||
}
|
||||
@ -197,6 +198,11 @@ Item {
|
||||
var viewPos = table_view.mapToGlobal(0,0)
|
||||
var y = table_view.contentY + pos.y-viewPos.y
|
||||
var index = Math.floor(y/control.cellHeight)
|
||||
if(index<0 || index>table_view.count-1){
|
||||
d.dropIndex = -1
|
||||
return
|
||||
}
|
||||
console.debug(index)
|
||||
if(tree_model.hitHasChildrenExpanded(index) && y>index*control.cellHeight+control.cellHeight/2){
|
||||
d.dropIndex = index + 1
|
||||
d.isDropTopArea = true
|
||||
@ -321,7 +327,10 @@ Item {
|
||||
if(isCurrent){
|
||||
return Qt.rgba(1,1,1,0.06)
|
||||
}
|
||||
if(item_mouse.containsMouse){
|
||||
if(item_mouse.containsMouse || item_check_box.hovered){
|
||||
return Qt.rgba(1,1,1,0.03)
|
||||
}
|
||||
if(item_loader_expand.item && item_loader_expand.item.hovered){
|
||||
return Qt.rgba(1,1,1,0.03)
|
||||
}
|
||||
return Qt.rgba(0,0,0,0)
|
||||
@ -329,7 +338,10 @@ Item {
|
||||
if(isCurrent){
|
||||
return Qt.rgba(0,0,0,0.06)
|
||||
}
|
||||
if(item_mouse.containsMouse){
|
||||
if(item_mouse.containsMouse || item_check_box.hovered){
|
||||
return Qt.rgba(0,0,0,0.03)
|
||||
}
|
||||
if(item_loader_expand.item && item_loader_expand.item.hovered){
|
||||
return Qt.rgba(0,0,0,0.03)
|
||||
}
|
||||
return Qt.rgba(0,0,0,0)
|
||||
@ -341,6 +353,7 @@ Item {
|
||||
height: parent.height
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
spacing: 0
|
||||
anchors.leftMargin: 14 + control.depthPadding*itemModel.depth
|
||||
Component{
|
||||
id:com_icon_btn
|
||||
@ -357,16 +370,36 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader{
|
||||
id:item_loader_expand
|
||||
Layout.preferredWidth: 20
|
||||
Layout.preferredHeight: 20
|
||||
sourceComponent: itemModel.hasChildren() ? com_icon_btn : undefined
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
FluCheckBox{
|
||||
id:item_check_box
|
||||
Layout.preferredWidth: 18
|
||||
Layout.preferredHeight: 18
|
||||
Layout.leftMargin: 5
|
||||
horizontalPadding:0
|
||||
verticalPadding: 0
|
||||
checked: itemModel.checked
|
||||
enableAnimation:false
|
||||
visible: control.checkable
|
||||
padding: 0
|
||||
clickListener: function(){
|
||||
tree_model.checkRow(rowIndex,!itemModel.checked)
|
||||
}
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
Loader{
|
||||
property var modelData: itemModel
|
||||
property var itemMouse: item_mouse
|
||||
id:item_loader_cell
|
||||
Layout.leftMargin: 10
|
||||
Layout.preferredWidth: {
|
||||
if(item){
|
||||
return item.width
|
||||
@ -397,6 +430,9 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
function selectionModel(){
|
||||
return tree_model.selectionModel
|
||||
}
|
||||
function count(){
|
||||
return tree_model.dataSourceSize
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user