FluentUI/src/FluTreeModel.cpp

369 lines
11 KiB
C++
Raw Normal View History

2023-09-15 19:11:55 +08:00
#include "FluTreeModel.h"
#include <QMetaEnum>
2024-04-03 11:19:35 +08:00
FluTreeNode::FluTreeNode(QObject *parent): QObject{parent}{
2023-09-17 20:36:33 +08:00
}
2023-09-22 00:11:58 +08:00
FluTreeModel::FluTreeModel(QObject *parent): QAbstractItemModel{parent}{
2023-09-17 20:36:33 +08:00
dataSourceSize(0);
2023-09-15 19:11:55 +08:00
}
2023-09-19 23:41:56 +08:00
QModelIndex FluTreeModel::parent(const QModelIndex &child) const{
return QModelIndex();
}
QModelIndex FluTreeModel::index(int row, int column,const QModelIndex &parent) const{
if (!hasIndex(row, column, parent) || parent.isValid())
return QModelIndex();
return createIndex(row, column, _rows.at(row));
}
2023-09-15 19:11:55 +08:00
int FluTreeModel::rowCount(const QModelIndex &parent) const {
return _rows.count();
};
int FluTreeModel::columnCount(const QModelIndex &parent) const {
return 1;;
};
QVariant FluTreeModel::data(const QModelIndex &index, int role) const {
switch (role) {
case Qt::DisplayRole:
return QVariant::fromValue(_rows.at(index.row()));
default:
break;
}
return QVariant();
};
QHash<int, QByteArray> FluTreeModel::roleNames() const {
2023-10-15 16:29:50 +08:00
return { {Qt::DisplayRole, "dataModel"} };
2023-09-15 19:11:55 +08:00
};
2024-04-03 11:19:35 +08:00
void FluTreeModel::setData(QList<FluTreeNode*> data){
2023-09-15 19:11:55 +08:00
beginResetModel();
_rows = data;
endResetModel();
}
void FluTreeModel::removeRows(int row,int count){
2023-09-17 20:36:33 +08:00
if (row < 0 || row + count > _rows.size() || count==0)
2023-09-15 19:11:55 +08:00
return;
2023-09-18 00:12:39 +08:00
beginRemoveRows(QModelIndex(),row, row + count - 1);
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*> firstPart = _rows.mid(0,row);
QList<FluTreeNode*> secondPart = _rows.mid(row + count);
2023-09-21 18:29:09 +08:00
_rows.clear();
_rows.append(firstPart);
_rows.append(secondPart);
2023-09-18 00:12:39 +08:00
endRemoveRows();
2023-09-15 19:11:55 +08:00
}
2024-04-03 11:19:35 +08:00
void FluTreeModel::insertRows(int row,QList<FluTreeNode*> data){
2023-09-17 20:36:33 +08:00
if (row < 0 || row > _rows.size() || data.size() == 0)
return;;
2023-09-18 00:12:39 +08:00
beginInsertRows(QModelIndex(), row, row + data.size() - 1);
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*> firstPart = _rows.mid(0, row);
QList<FluTreeNode*> secondPart = _rows.mid(row);
2023-09-21 18:29:09 +08:00
_rows.clear();
_rows.append(firstPart);
_rows.append(data);
_rows.append(secondPart);
2023-09-18 00:12:39 +08:00
endInsertRows();
2023-09-15 19:11:55 +08:00
}
QObject* FluTreeModel::getRow(int row){
return _rows.at(row);
}
2023-09-17 20:36:33 +08:00
2024-03-31 21:52:06 +08:00
void FluTreeModel::checkRow(int row,bool checked){
2023-09-22 17:35:02 +08:00
auto itemData = _rows.at(row);
if(itemData->hasChildren()){
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*> stack = itemData->_children;
2023-09-22 17:35:02 +08:00
std::reverse(stack.begin(), stack.end());
while (stack.count() > 0) {
auto item = stack.at(stack.count()-1);
stack.pop_back();
if(!item->hasChildren()){
2024-03-31 21:52:06 +08:00
item->_checked = checked;
2023-09-22 17:35:02 +08:00
}
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*> children = item->_children;
2023-09-22 17:35:02 +08:00
if(!children.isEmpty()){
std::reverse(children.begin(), children.end());
foreach (auto c, children) {
stack.append(c);
}
}
}
}else{
2024-03-31 21:52:06 +08:00
if(itemData->_checked == checked){
2023-09-22 17:35:02 +08:00
return;
}
2024-03-31 21:52:06 +08:00
itemData->_checked = checked;
2023-09-22 17:35:02 +08:00
}
2024-04-03 11:19:35 +08:00
Q_EMIT layoutChanged();
QList<FluTreeNode*> data;
2023-09-22 17:35:02 +08:00
foreach (auto item, _dataSource) {
if(!item->hasChildren()){
if(item->_checked){
data.append(item);
}
}
}
selectionModel(data);
}
2023-09-17 20:36:33 +08:00
void FluTreeModel::setDataSource(QList<QMap<QString,QVariant>> data){
_dataSource.clear();
if(_root){
delete _root;
_root = nullptr;
}
2024-04-03 11:19:35 +08:00
_root = new FluTreeNode(this);
2023-09-17 20:36:33 +08:00
std::reverse(data.begin(), data.end());
while (data.count() > 0) {
auto item = data.at(data.count()-1);
data.pop_back();
2024-04-03 11:19:35 +08:00
FluTreeNode* node = new FluTreeNode(this);
2023-09-17 20:36:33 +08:00
node->_title = item.value("title").toString();
node->_key = item.value("key").toString();
node->_depth = item.value("__depth").toInt();
2024-04-03 11:19:35 +08:00
node->_parent = item.value("__parent").value<FluTreeNode*>();
2023-09-17 20:36:33 +08:00
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<QVariant> children = item.value("children").toList();
if(!children.isEmpty()){
std::reverse(children.begin(), children.end());
2023-09-21 18:29:09 +08:00
for (int i = 0; i < children.count(); ++i) {
auto child = children.at(i).toMap();
2023-09-17 20:36:33 +08:00
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);
}
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);
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*> insertData;
QList<FluTreeNode*> stack = modelData->_children;
2023-09-17 20:36:33 +08:00
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);
}
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*> children = item->_children;
2023-09-17 20:36:33 +08:00
if(!children.isEmpty()){
std::reverse(children.begin(), children.end());
foreach (auto c, children) {
stack.append(c);
}
}
}
insertRows(row+1,insertData);
}
2024-03-31 21:52:06 +08:00
void FluTreeModel::dragAndDrop(int dragIndex,int dropIndex,bool isDropTopArea){
2023-09-19 00:31:49 +08:00
if(dropIndex>_rows.count() || dropIndex<0){
2023-09-17 20:36:33 +08:00
return;
}
auto dragItem = _rows[dragIndex];
auto dropItem = _rows[dropIndex];
2023-09-21 18:29:09 +08:00
int targetIndex;
if(dropIndex > dragIndex){
if(isDropTopArea){
targetIndex = dropIndex;
}else{
targetIndex = dropIndex+1;
}
}else{
if(isDropTopArea){
targetIndex = dropIndex;
}else{
targetIndex = dropIndex+1;
}
}
if (!beginMoveRows(QModelIndex(), dragIndex, dragIndex, QModelIndex(), targetIndex)) {
2023-09-17 20:36:33 +08:00
return;
}
2023-09-21 18:29:09 +08:00
if(dropIndex > dragIndex){
if(isDropTopArea){
targetIndex = dropIndex-1;
}else{
targetIndex = dropIndex;
}
}else{
if(isDropTopArea){
targetIndex = dropIndex;
}else{
targetIndex = dropIndex+1;
}
}
_rows.move(dragIndex,targetIndex);
endMoveRows();
2023-09-22 17:35:02 +08:00
2023-09-21 18:29:09 +08:00
Q_EMIT layoutAboutToBeChanged();
2023-09-17 20:36:33 +08:00
if(dragItem->_parent == dropItem->_parent){
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*>* children = &(dragItem->_parent->_children);
2023-09-18 18:10:27 +08:00
int srcIndex = children->indexOf(dragItem);
int destIndex = children->indexOf(dropItem);
2023-09-21 18:29:09 +08:00
if(dropIndex > dragIndex){
if(isDropTopArea){
targetIndex = destIndex-1;
}else{
targetIndex = destIndex;
}
}else{
if(isDropTopArea){
targetIndex = destIndex;
}else{
targetIndex = destIndex+1;
}
2023-09-19 00:31:49 +08:00
}
2023-09-21 18:29:09 +08:00
children->move(srcIndex,targetIndex);
2023-09-17 20:36:33 +08:00
}else{
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*>* srcChildren = &(dragItem->_parent->_children);
QList<FluTreeNode*>* destChildren = &(dropItem->_parent->_children);
2023-09-18 18:10:27 +08:00
int srcIndex = srcChildren->indexOf(dragItem);
int destIndex = destChildren->indexOf(dropItem);
dragItem->_depth = dropItem->_depth;
dragItem->_parent = dropItem->_parent;
2023-09-17 20:36:33 +08:00
if(dragItem->hasChildren()){
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*> stack = dragItem->_children;
2023-09-18 18:10:27 +08:00
foreach (auto node, stack) {
node->_depth = dragItem->_depth+1;
}
std::reverse(stack.begin(), stack.end());
while (stack.count() > 0) {
auto item = stack.at(stack.count()-1);
stack.pop_back();
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*> children = item->_children;
2023-09-18 18:10:27 +08:00
if(!children.isEmpty()){
std::reverse(children.begin(), children.end());
foreach (auto c, children) {
c->_depth = item->_depth+1;
stack.append(c);
}
}
}
2023-09-17 20:36:33 +08:00
}
2023-09-18 18:10:27 +08:00
srcChildren->removeAt(srcIndex);
2023-09-21 18:29:09 +08:00
if(dropIndex > dragIndex){
if(isDropTopArea){
targetIndex = destIndex;
}else{
targetIndex = destIndex + 1;
}
}else{
if(isDropTopArea){
targetIndex = destIndex;
}else{
targetIndex = destIndex + 1;
}
2023-09-19 18:31:29 +08:00
}
2023-09-21 18:29:09 +08:00
destChildren->insert(targetIndex,dragItem);
2023-09-17 20:36:33 +08:00
}
2023-09-21 18:29:09 +08:00
changePersistentIndex(index(qMin(dragIndex,dropIndex),0),index(qMax(dragIndex,dropIndex),0));
2024-04-03 11:19:35 +08:00
Q_EMIT layoutChanged();
2023-09-21 18:29:09 +08:00
2023-09-17 20:36:33 +08:00
}
2023-09-18 18:10:27 +08:00
2023-09-19 00:31:49 +08:00
bool FluTreeModel::hitHasChildrenExpanded(int row){
2023-09-22 00:11:58 +08:00
auto itemData = _rows.at(row);
if(itemData->hasChildren() && itemData->_isExpanded){
return true;
}
2023-09-19 00:31:49 +08:00
return false;
}
2023-09-18 18:10:27 +08:00
void FluTreeModel::refreshNode(int row){
Q_EMIT dataChanged(index(row,0),index(row,0));
};
2024-04-03 11:19:35 +08:00
FluTreeNode* FluTreeModel::getNode(int row){
2023-09-18 18:10:27 +08:00
return _rows.at(row);
}
2023-09-19 00:31:49 +08:00
void FluTreeModel::allExpand(){
beginResetModel();
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*> data;
QList<FluTreeNode*> stack = _root->_children;
2023-09-19 00:31:49 +08:00
std::reverse(stack.begin(), stack.end());
while (stack.count() > 0) {
auto item = stack.at(stack.count()-1);
stack.pop_back();
if(item->hasChildren()){
item->_isExpanded = true;
}
data.append(item);
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*> children = item->_children;
2023-09-19 00:31:49 +08:00
if(!children.isEmpty()){
std::reverse(children.begin(), children.end());
foreach (auto c, children) {
stack.append(c);
}
}
}
_rows = data;
endResetModel();
}
void FluTreeModel::allCollapse(){
beginResetModel();
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*> stack = _root->_children;
2023-09-19 00:31:49 +08:00
std::reverse(stack.begin(), stack.end());
while (stack.count() > 0) {
auto item = stack.at(stack.count()-1);
stack.pop_back();
if(item->hasChildren()){
item->_isExpanded = false;
}
2024-04-03 11:19:35 +08:00
QList<FluTreeNode*> children = item->_children;
2023-09-19 00:31:49 +08:00
if(!children.isEmpty()){
std::reverse(children.begin(), children.end());
foreach (auto c, children) {
stack.append(c);
}
}
}
_rows = _root->_children;
endResetModel();
}