Вставка элемента в TreeView QT [QAbstractItem]
Пытаюсь реализовать свою модель дерева через QAbstractItem. У меня есть метод SetEmployees, который добавляет элементы с использованием beginInsertRow(). Но, что он есть(beginInsertRow), что нет, элементы все равно добавляются, но не отображаются, пока не потянуть за горизонтальные хэдеры. Хочу реализовать возможность добавления отдельной строки InsertRow (как отдела, так и рабочего), но не получается. Новый элемент не отображается в view. Скорее всего, неправильно описал модель. Буду очень благодарен за любую помощь!
Вот структура элемента
struct infoItem{
QString departmentName;
Person person;
QVector<infoItem *> childrens;
infoItem *parent;
int avgSalary;
int employeeCount;
};
Код модели:
DepartmentModel::DepartmentModel(QObject *parent)
: QAbstractItemModel{parent}
{
rootItem = new infoItem();
rootItem->parent = nullptr;
rootItem->departmentName = tr("Департаменты разработки");
}
QModelIndex DepartmentModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
infoItem *item;
if(!parent.isValid())
item = rootItem;
else
item = static_cast<infoItem* >(parent.internalPointer());
infoItem *child;
child = item->childrens.at(row);
if(child)
return createIndex(row, column, child);
return QModelIndex();
}
QModelIndex DepartmentModel::parent(const QModelIndex &child) const
{
if (!child.isValid())
return QModelIndex();
infoItem *childItem = static_cast<infoItem*>(child.internalPointer());
infoItem *parentItem = childItem->parent;
if (parentItem == rootItem)
return QModelIndex();
int row = parentItem->childrens.indexOf(childItem);
return createIndex(row, 0, parentItem);
}
int DepartmentModel::rowCount(const QModelIndex &parent) const
{
infoItem *item;
if(!parent.isValid())
item = rootItem;
else
item = static_cast<infoItem*>(parent.internalPointer());
return item->childrens.count();
}
int DepartmentModel::columnCount(const QModelIndex &parent) const
{
return 3;
}
QVariant DepartmentModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role == Qt::DisplayRole){
infoItem *item = static_cast<infoItem* >(index.internalPointer());
if(index.column() == 0){
if(item->childrens.count() == 0)
return item->person.surname + " " + item->person.name + " " + item->person.middlename;
return item->departmentName;
}
if(item->childrens.count() != 0){
switch (index.column()) {
case 1:
return item->employeeCount;
break;
case 2:
return item->avgSalary;
break;
}
}
}
return QVariant();
}
QVariant DepartmentModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole){
switch(section){
case 0:
return rootItem->departmentName;
break;
case 1:
return "Количество сотрудников";
break;
case 2:
return "Средняя зарплата";
break;
}
}
return QVariant();
}
void DepartmentModel::SetEmployees(QList<Department> list)
{
QModelIndex index = createIndex(rootItem->childrens.count(), 0, rootItem);
beginInsertRows(index, rootItem->childrens.count(), rootItem->childrens.count() + list.count() - 1);
foreach(auto department, list){
infoItem *new_department = new infoItem();
new_department->parent = rootItem;
new_department->departmentName = department.name;
rootItem->childrens.append(new_department);
double avg = 0;
foreach(auto person, department.employees){
infoItem *child_person = new infoItem();
child_person->parent = new_department;
child_person->person = person;
new_department->childrens.append(child_person);
avg += child_person->person.salary;
}
new_department->employeeCount = new_department->childrens.count();
new_department->avgSalary = avg / new_department->employeeCount;
}
//endInsertRows();
}
void DepartmentModel::InsertRow(const QModelIndex &index)
{
if(!index.isValid()){
QModelIndex newIndex = createIndex(rootItem->childrens.count(), 0, rootItem);
beginInsertRows(newIndex, 0, 1);
infoItem *item = new infoItem();
item->departmentName = "[Новый департамент]";
item->employeeCount = 0;
item->avgSalary = 0;
item->parent = rootItem;
rootItem->childrens.append(item);
endInsertRows();
}
else{
infoItem *parent = static_cast<infoItem *>(index.internalPointer());
QModelIndex newIndex = createIndex(parent->childrens.count(), 0, parent);
beginInsertRows(newIndex, parent->childrens.count(), parent->childrens.count());
infoItem *item = new infoItem();
item->parent = parent;
item->person = Person();
parent->childrens.append(item);
endInsertRows();
}
}
Qt::ItemFlags DepartmentModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags flags = QAbstractItemModel::flags(index);
if(index.isValid())
flags |= Qt::ItemIsSelectable;
infoItem *item = static_cast<infoItem *>(index.internalPointer());
if(item->parent == rootItem)
flags |= Qt::ItemIsEditable;
return flags;
}
bool DepartmentModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(role == Qt::EditRole && index.isValid()){
infoItem *item = static_cast<infoItem *>(index.internalPointer());
if(item->parent == rootItem){
item->departmentName = value.toString();
emit dataChanged(index, index);
return true;
}
infoItem *parent = item->parent;
parent->avgSalary -= item->person.salary / parent->employeeCount;
item->person = unpackPerson(value);
parent->avgSalary += item->person.salary / parent->employeeCount;
emit dataChanged(index.parent(), index);
return true;
}
return false;
}
Ответы (1 шт):
Надо так и делать (немного упрощу код, но суть должна быть ясна).
// Отдел
struct Department {
QList<Person> employee;
QString name;
}
// Список отделов
struct Departments {
QList<Department> deps;
}
class DepModel: public QAbstractItemModel {
Q_OBJECT
private:
Departments root; // Можно и просто QList<Department> root; но, вам виднее
}
Далее, вы хотите иметь возможность добавлять новые отделы:
class DepModel: ... {
public:
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) {
...
}
// Добавим новый отдел в конец списка
void append(const Department& dep) {
// По умолчанию, метод index() должен вернуть QModelIndex,
// соответствующий вашему root (parent = QModelIndex())
QModelIndex idx = this->index(0, 0);
// Получаем текущее количество отделов разработки
int count = root.deps.count();
beginInsertRow(idx, count, count);
root.deps.append(dep);
endInsertRow();
}
}
Добавление сотрудника:
class DepModel: ... {
public:
// Добавление сотрудника в отдел, которому соответствует индекс depIdx
void append(const Person& person, int depIdx) {
// Корневой индекс
QModelIndex rootIndex = this->index(0, 0);
// Индекс отдела
QModelIndex depIndex = this->index(depIdx, 0, rootIndex);
Department& dep = root.deps[depIdx];
beginInsertRow(depIndex, dep.empCount(), dep.empCount());
dep.employee.append(person);
endInsertRow();
}
}
И так далее, и тому подобное.