树形结构体
class YjProjectModelData
{
public:
explicit YjProjectModelData(YjProjectModelData *parentItem = 0){m_parentItem = parentItem;}
~YjProjectModelData(){}
YjProjectModelData *child(int row){ return children.at(row);}
int childCount() const{ return children.count();}
QVariant data(int column) const;
int row() const{
if (m_parentItem)
return m_parentItem->children.indexOf(const_cast<YjProjectModelData*>(this));
return 0;
}
YjProjectModelData *parentItem(){
return m_parentItem;
}
public:
qint64 dataId;
QString dataName;
QString labelIds;
qint64 parentId;
QVector<YjProjectModelData*> children;
QString cTime;
QString lastUpdateTime;
QVector<YjProjectLabel>labelList;
Qt::CheckState checked = Qt::Unchecked;
YjProjectModelData &operator=(const YjProjectModelData &data)
{
this->dataId = data.dataId;
this->dataName = data.dataName;
this->labelIds = data.labelIds;
this->parentId = data.parentId;
this->children = data.children;
this->cTime = data.cTime;
this->lastUpdateTime = data.lastUpdateTime;
this->labelList = data.labelList;
return *this;
}
private:
YjProjectModelData *m_parentItem;
};
树形model.h:
#ifndef YJPROJECTTREEMODEL_H
#define YJPROJECTTREEMODEL_H
#include <QAbstractItemModel>
#include <QIcon>
#include "YjTreeItem.h"
#include "YjModelProject.h"
enum ColumnIndex{
Name,
category,
createDate,
lastModifyDate
};
class YjProjectTreeModel : public QAbstractItemModel
{
Q_OBJECT
public:
YjProjectTreeModel(QObject *parent, YjProjectModelData* rootItem);
~YjProjectTreeModel();
QVariant data(const QModelIndex &index, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &index) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role);
YjProjectModelData *rootItem() const;
public slots:
void onUpdataTree();
private:
void setAllchildandParentcheackState(YjProjectModelData *currentItem); //设置关联的父子选中状态级联改变
/////////////////////////////////////////////////////////////////////////
/// 函数名称:
/// 函数功能:递归设置所有的子项目为全选或全不选状态item
/// 返回值:
/// 函数参数:item 当前项目 check true时为全选,false时全不选
/////////////////////////////////////////////////////////////////////////
void treeItem_checkAllChild(YjProjectModelData * item, bool check);
void treeItem_checkAllChild_recursion(YjProjectModelData * item,bool check);
////////////////////////////////////////////////////////////////////////
/// 函数名称: treeItem_CheckChildChanged
/// 函数功能: 根据子节点的改变,更改父节点的选择情况
////////////////////////////////////////////////////////////////////////
void treeItem_CheckChildChanged(YjProjectModelData * item);
////////////////////////////////////////////////////////////////////////
/// 函数功能: 测量兄弟节点的情况,如果都选中返回Qt::Checked,都不选中Qt::Unchecked,不完全选中返回Qt::PartiallyChecked
/// 返回值: 如果都选中返回Qt::Checked,都不选中Qt::Unchecked,不完全选中返回Qt::PartiallyChecked
////////////////////////////////////////////////////////////////////////
Qt::CheckState checkSibling(YjProjectModelData * item);
YjProjectModelData* m_rootItem;
QIcon m_icon;
};
#endif // YJPROJECTTREEMODEL_H
model.cpp
#include "YjProjectTreeModel.h"
#include <QDebug>
const int columnNum = 4;
YjProjectTreeModel::YjProjectTreeModel(QObject *parent, YjProjectModelData *rootItem):QAbstractItemModel(parent)
{
m_rootItem = rootItem;
m_icon = QIcon(":/YjHealthePlus/image/dir.png");
}
YjProjectTreeModel::~YjProjectTreeModel()
{
if(m_rootItem != NULL){
delete m_rootItem;
}
}
QVariant YjProjectTreeModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
// if (role != Qt::DisplayRole)
// return QVariant();
YjProjectModelData *item = static_cast<YjProjectModelData*>(index.internalPointer());
if(role == Qt::UserRole +1){
return item->dataName;
}
if(role == Qt::UserRole +11){
return item->checked;
}
if(role == Qt::DisplayRole && index.column() == category){
QString m_category = "";
for(auto obj:item->labelList)
{
m_category += obj.m_labelName;
m_category += ",";
}
if(m_category == ""){
return QStringLiteral("未指定诊断类别");
}else{
m_category.chop(1);
return m_category;
}
}
if(role == Qt::DisplayRole && index.column() == createDate){
return item->cTime;
}
if( role == Qt::DisplayRole && index.column() == lastModifyDate){
return item->lastUpdateTime;
}
return QVariant();
}
Qt::ItemFlags YjProjectTreeModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags theFlags = QAbstractItemModel::flags(index);
if (index.isValid()) {
theFlags |= Qt::ItemIsSelectable|Qt::ItemIsEnabled;
if (index.column() == Name)
theFlags |= Qt::ItemIsUserCheckable;
}
return theFlags;
}
QVariant YjProjectTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
if (section == Name)
return QStringLiteral("数据名称");
else if (section == category)
return QStringLiteral("指定诊断类别");
else if (section == createDate)
return QStringLiteral("创建日期");
else if (section == lastModifyDate)
return QStringLiteral("最后操作日期");
}
return QVariant();
}
QModelIndex YjProjectTreeModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
YjProjectModelData *parentItem;
if (!parent.isValid())
parentItem = m_rootItem;
else
parentItem = static_cast<YjProjectModelData*>(parent.internalPointer());
YjProjectModelData *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
else
return QModelIndex();
}
QModelIndex YjProjectTreeModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
YjProjectModelData *childItem = static_cast<YjProjectModelData*>(index.internalPointer());
YjProjectModelData *parentItem = childItem->parentItem();
if (parentItem == m_rootItem)
return QModelIndex();
return createIndex(parentItem->row(), 0, parentItem);
}
int YjProjectTreeModel::rowCount(const QModelIndex &parent) const
{
YjProjectModelData *parentItem;
if (parent.column() > 0)
return 0;
if (!parent.isValid())
parentItem = m_rootItem;
else
parentItem = static_cast<YjProjectModelData*>(parent.internalPointer());
return parentItem->childCount();
}
int YjProjectTreeModel::columnCount(const QModelIndex &parent) const
{
return columnNum;
}
bool YjProjectTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(role == Qt::CheckStateRole){
YjProjectModelData *item = static_cast<YjProjectModelData*>(index.internalPointer());
// item->checked = item->checked;
if(item->checked == Qt::Checked)
{
item->checked = Qt::Unchecked;
}else{
item->checked = Qt::Checked;
}
setAllchildandParentcheackState(item);
qDebug()<<"TreeitemState:"<<item->checked<<" item:" <<item->dataName;
onUpdataTree();
return true;
}
return QAbstractItemModel::setData(index,value,role);
}
void YjProjectTreeModel::onUpdataTree()
{
layoutAboutToBeChanged();
// inspectChecked();
layoutChanged();
}
void YjProjectTreeModel::setAllchildandParentcheackState(YjProjectModelData *currentItem)
{
if ( currentItem == nullptr )
return ;
Qt::CheckState state = currentItem -> checked; //获取当前的选择状态
treeItem_CheckChildChanged ( currentItem );
if ( state != Qt :: PartiallyChecked )
{
//当前是选中状态,需要对其子项目进行全选
treeItem_checkAllChild ( currentItem , state == Qt :: Checked ? true : false );
}
}
void YjProjectTreeModel::treeItem_checkAllChild(YjProjectModelData *item, bool check)
{
if(item == nullptr)
return;
int rowCount = item->childCount();
for(int i=0;i<rowCount;++i)
{
YjProjectModelData* childItems = item->child(i);
treeItem_checkAllChild_recursion(childItems,check);
}
item->checked = (check ? Qt::Checked : Qt::Unchecked);
}
void YjProjectTreeModel::treeItem_checkAllChild_recursion(YjProjectModelData *item, bool check)
{
if(item == nullptr)
return;
int rowCount = item->childCount();
for(int i=0;i<rowCount;++i)
{
YjProjectModelData* childItems = item->child(i);
treeItem_checkAllChild_recursion(childItems,check);
}
item->checked = (check ? Qt::Checked : Qt::Unchecked);
}
void YjProjectTreeModel::treeItem_CheckChildChanged(YjProjectModelData *item)
{
if(nullptr == item)
return;
Qt::CheckState siblingState = checkSibling(item);
qDebug()<<siblingState;
YjProjectModelData * parentItem = item->parentItem();
if(nullptr == parentItem)
return;
if(Qt::PartiallyChecked == siblingState)
{
parentItem->checked = Qt::PartiallyChecked;
}
else if(Qt::Checked == siblingState)
{
parentItem->checked = Qt::Checked;
}
else
{
parentItem->checked = Qt::Unchecked;
}
treeItem_CheckChildChanged(parentItem);
}
Qt::CheckState YjProjectTreeModel::checkSibling(YjProjectModelData *item)
{
YjProjectModelData *parent = item->parentItem();
if(nullptr == parent)
return (Qt::CheckState) item->checked;
int brotherCount = parent->childCount();
int checkedCount(0),unCheckedCount(0);
Qt::CheckState state;
for(int i=0;i<brotherCount;++i){
YjProjectModelData* siblingItem = parent->child(i);
state = (Qt::CheckState)siblingItem->checked;
if(Qt::PartiallyChecked == state)
return Qt::PartiallyChecked;
else if(Qt::Unchecked == state)
++unCheckedCount;
else
++checkedCount;
if(checkedCount>0 && unCheckedCount>0)
return Qt::PartiallyChecked;
}
if(unCheckedCount>0)
return Qt::Unchecked;
return Qt::Checked;
}
YjProjectModelData *YjProjectTreeModel::rootItem() const
{
return m_rootItem;
}
代理类:
YjAddStructItemDelegate.h
#ifndef YJADDSTRUCTITEMDELEGATE_H
#define YJADDSTRUCTITEMDELEGATE_H
#include <QStyledItemDelegate>
#include <QPushButton>
#include <QTableView>
#include <QIcon>
class YjTableView;
class YjStructParaSelectitem;
class YjAddStructItemDelegate: public QStyledItemDelegate
{
Q_OBJECT
public:
YjAddStructItemDelegate(QObject *parent);
~YjAddStructItemDelegate();
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setEditorData(QWidget *editor,const QModelIndex &index);
void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const Q_DECL_OVERRIDE;
void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
void setSelectRowClear();
YjTableView* m_tableView;
signals:
void deleteData(const QModelIndex& index);
private:
QPoint m_mousePoint; // 鼠标位置
QScopedPointer<QPushButton> m_pButton;
int m_nSpacing; // 按钮之间的间距
int m_nWidth; // 按钮宽度
int m_nHeight; // 按钮高度
int m_nType; // 按钮状态-1:划过 2:按下
int m_moveRow;
int m_pressedRow;
QIcon m_deleteICon;
};
#endif // YJADDSTRUCTITEMDELEGATE_H
#include <QPainter>
#include <QEvent>
#include <QMouseEvent>
#include <QLineEdit>
#include "YjAddStructItemDelegate.h"
#include "yjaddstructitemmodel.h"
#include "YjModelProject.h"
#include "YjTipConverDialog.h"
#include "YjTableView.h"
#include <QDebug>
YjAddStructItemDelegate::YjAddStructItemDelegate(QObject *parent): QStyledItemDelegate(parent),
m_pButton(new QPushButton()),
m_nSpacing(5),
m_nWidth(30),
m_nHeight(30)
{
m_moveRow = -1;
m_pressedRow = -1;
m_pButton->setStyleSheet("QPushButton {border: none; "> transparent; color:rgb(245,87,62);} \
QPushButton:hover {color:rgb(0, 255, 0);} \
QPushButton:pressed {color:rgb(0, 255, 0);}");
m_deleteICon = QIcon("./data/image/delete.png");
}
YjAddStructItemDelegate::~YjAddStructItemDelegate()
{
}
QWidget *YjAddStructItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.column() == 0){
QLineEdit *editor = new QLineEdit(parent);
editor->setPlaceholderText(QStringLiteral("请输入数字"));
QRegExp regExp("[0-9]{0,10}");
editor->setValidator(new QRegExpValidator(regExp, parent));
return editor;
}
if(index.column() == 1)
{
QLineEdit *editor = new QLineEdit(parent);
editor->setPlaceholderText(QStringLiteral("请输入"));
return editor;
}
if(index.column() == 2)
{
return QStyledItemDelegate::createEditor(parent,option,index);
}
}
void YjAddStructItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index)
{
if(index.column() != 2)
{
QString text = index.model()->data(index, Qt::EditRole).toString();
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
lineEdit->setText(text);
}else{
return QStyledItemDelegate::setEditorData(editor,index);
}
}
void YjAddStructItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
QString text = lineEdit->text();
model->setData(index, text, Qt::EditRole);
}
void YjAddStructItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}
void YjAddStructItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem viewOption(option);
initStyleOption(&viewOption, index);
if (option.state.testFlag(QStyle::State_HasFocus))
viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
bool l_flag = false;
const QAbstractItemModel * model = index.model();
if (index.column() == 0)
{
QString l_paralValue = model->data(index, Qt::UserRole + 1).toString();
//绘制文本
painter->drawText(option.rect, Qt::AlignHCenter | Qt::AlignVCenter, l_paralValue);
}
else if (index.column() == 1)
{
QString l_paralName = model->data(index, Qt::UserRole + 2).toString();
//绘制文本
painter->drawText(option.rect, Qt::AlignHCenter | Qt::AlignVCenter, l_paralName);
}
else if (index.column() == 2)
{
// const QAbstractItemModel * model = index.model();
// int l_labelType = model->data(index, Qt::UserRole+1).toInt();
int nCount = 1;
int nHalf = (option.rect.width() - m_nWidth * nCount - m_nSpacing * (nCount - 1)) / 2;
int nTop = (option.rect.height() - m_nHeight) / 2;
QStyleOptionButton delBtn;
delBtn.icon = m_deleteICon;
delBtn.iconSize = QSize(28, 28);
delBtn.rect = QRect(option.rect.left() + nHalf + m_nWidth * 0 + m_nSpacing * 0,
option.rect.top() + nTop, m_nWidth, m_nHeight);
delBtn.state |= QStyle::State_Enabled;
if (delBtn.rect.contains(m_mousePoint))
{
if (m_nType == 0)
{
delBtn.state |= QStyle::State_MouseOver;
}
else if (m_nType == 1)
{
delBtn.state |= QStyle::State_Sunken;
}
}
m_pButton->style()->drawControl(QStyle::CE_PushButton, &delBtn, painter, m_pButton.data());
}
}
bool YjAddStructItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
m_nType = -1;
m_moveRow = -1;
m_pressedRow = -1;
bool bRepaint = false;
QMouseEvent *pEvent = static_cast<QMouseEvent *> (event);
m_mousePoint = pEvent->pos();
bool l_bPressed = false;
if (event->type() == QEvent::MouseMove)
{
m_moveRow = index.row();
}
else if (QEvent::MouseButtonPress)
{
m_moveRow = index.row();
m_pressedRow = index.row();
}
if (index.column() == 2)
{
const QAbstractItemModel * model = index.model();
int nCount = 1;
int nHalf = (option.rect.width() - m_nWidth * nCount - m_nSpacing * (nCount - 1)) / 2;
int nTop = (option.rect.height() - m_nHeight) / 2;
QRect l_rect = QRect(option.rect.left() + nHalf + m_nWidth * 0 + m_nSpacing * 0,
option.rect.top() + nTop, m_nWidth, m_nHeight);
bRepaint = true;
if (l_rect.contains(m_mousePoint))
{
bRepaint = true;
switch (event->type())
{
// 鼠标滑过
case QEvent::MouseMove:
{
m_nType = 0;
break;
}
// 鼠标按下
case QEvent::MouseButtonPress:
{
m_nType = 1;
break;
}
// 鼠标释放
case QEvent::MouseButtonRelease:
{
YjTipConverDialog l_tipDialog;
l_tipDialog.setTipMes(QStringLiteral("是否确认删除!"));
l_tipDialog.exec();
if (!l_tipDialog.getIsConfirm())
{
break;
}
m_moveRow = index.row();
m_pressedRow = index.row();
m_tableView->clearSelection();
emit deleteData(index);
((YjAddStructItemModel*)model)->removeSelItemRow(index.row());
((YjAddStructItemModel*)model)->onUpdataTable();
break;
}
default:
break;
}
}
}else
{
switch (event->type())
{
// 鼠标滑过
case QEvent::MouseMove:
{
m_nType = 0;
if(index.row() == ((YjAddStructItemModel*)model)->getSelItem().size() -1 && model->data(index) != "")
{
((YjAddStructItemModel*)model)->addoneNewRow();
}
break;
}
// 鼠标按下
case QEvent::MouseButtonPress:
{
m_nType = 1;
break;
}
// 鼠标释放
case QEvent::MouseButtonRelease:
{
bRepaint = true;
m_moveRow = index.row();
m_pressedRow = index.row();
m_tableView->clearSelection();
((YjAddStructItemModel*)model)->onUpdataTable();
break;
}
default:
break;
}
}
// }
((YjAddStructItemModel*)model)->onUpdataTable();
if (bRepaint)
{
return bRepaint;
}
else
{
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
}
void YjAddStructItemDelegate::setSelectRowClear()
{
m_mousePoint = QPoint(-1, -1);
m_pressedRow = -1;
m_moveRow = -1;
}