+Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid()) {
+ return rootItem->flags() & Qt::ItemIsDropEnabled;
+ }
+ else {
+ auto *item = static_cast<AbstractTreeItem *>(index.internalPointer());
+ return item->flags();
+ }
+}
+
+
+QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
+ return rootItem->data(section, role);
+ else
+ return QVariant();
+}
+
+
+void TreeModel::itemDataChanged(int column)
+{
+ auto *item = qobject_cast<AbstractTreeItem *>(sender());
+ QModelIndex leftIndex, rightIndex;
+
+ if (item == rootItem)
+ return;
+
+ if (column == -1) {
+ leftIndex = createIndex(item->row(), 0, item);
+ rightIndex = createIndex(item->row(), item->columnCount() - 1, item);
+ }
+ else {
+ leftIndex = createIndex(item->row(), column, item);
+ rightIndex = leftIndex;
+ }
+
+ emit dataChanged(leftIndex, rightIndex);
+}
+
+
+void TreeModel::connectItem(AbstractTreeItem *item)
+{
+ connect(item, &AbstractTreeItem::dataChanged,
+ this, &TreeModel::itemDataChanged);
+
+ connect(item, &AbstractTreeItem::beginAppendChilds,
+ this, &TreeModel::beginAppendChilds);
+ connect(item, &AbstractTreeItem::endAppendChilds,
+ this, &TreeModel::endAppendChilds);
+
+ connect(item, &AbstractTreeItem::beginRemoveChilds,
+ this, &TreeModel::beginRemoveChilds);
+ connect(item, &AbstractTreeItem::endRemoveChilds,
+ this, &TreeModel::endRemoveChilds);
+}
+
+
+void TreeModel::beginAppendChilds(int firstRow, int lastRow)
+{
+ auto *parentItem = qobject_cast<AbstractTreeItem *>(sender());
+ if (!parentItem) {
+ qWarning() << "TreeModel::beginAppendChilds(): cannot append Children to unknown parent";
+ return;
+ }
+
+ QModelIndex parent = indexByItem(parentItem);
+ Q_ASSERT(!_aboutToRemoveOrInsert);
+
+ _aboutToRemoveOrInsert = true;
+ _childStatus = ChildStatus(parent, rowCount(parent), firstRow, lastRow);
+ beginInsertRows(parent, firstRow, lastRow);