QModelIndex FlatProxyModel::mapToSource(const QModelIndex &proxyIndex) const { if (!proxyIndex.isValid()) return QModelIndex(); Q_ASSERT(proxyIndex.model() == this); Q_ASSERT(_rootSourceItem); int row = proxyIndex.row(); QModelIndex sourceParent; SourceItem *sourceItem = _rootSourceItem->findChild(row); while (sourceItem) { if (sourceItem->pos() == row) { return sourceModel()->index(sourceItem->sourceRow(), proxyIndex.column(), sourceParent); } else { sourceParent = sourceModel()->index(sourceItem->sourceRow(), 0, sourceParent); sourceItem = sourceItem->findChild(row); } } qWarning() << "FlatProxyModel::mapToSource(): couldn't find source index for" << proxyIndex; Q_ASSERT(false); return QModelIndex(); // make compilers happy :) }
QModelIndex FlatProxyModel::mapFromSource(const QModelIndex &sourceIndex) const { if (!sourceIndex.isValid()) return QModelIndex(); SourceItem *sourceItem = sourceToInternal(sourceIndex); Q_ASSERT(sourceItem); return createIndex(sourceItem->pos(), sourceIndex.column(), sourceItem); }
void FlatProxyModel::insertSubTree(const QModelIndex &source_idx, bool emitInsert) { SourceItem *newSubTree = new SourceItem(source_idx.row(), sourceToInternal(sourceModel()->parent(source_idx))); if (newSubTree->parent()) { newSubTree->setPos(newSubTree->parent()->pos() + source_idx.row() + 1); } SourceItem *lastItem = insertSubTreeHelper(newSubTree, newSubTree, source_idx); Q_ASSERT(lastItem); Q_ASSERT(lastItem->next() == 0); if (emitInsert) beginInsertRows(QModelIndex(), newSubTree->pos(), lastItem->pos()); if (newSubTree->parent()) { if (newSubTree->parent()->childCount() > source_idx.row()) { SourceItem *next = newSubTree->parent()->child(source_idx.row()); lastItem->setNext(next); int nextPos = lastItem->pos() + 1; while (next) { next->setPos(nextPos); next = next->next(); nextPos++; } } if (source_idx.row() > 0) { SourceItem *previous = newSubTree->parent()->child(source_idx.row() - 1); while (previous->childCount() > 0) { previous = previous->child(previous->childCount() - 1); } previous->setNext(newSubTree); } else { newSubTree->parent()->setNext(newSubTree); } } else { _rootSourceItem = newSubTree; } if (emitInsert) endInsertRows(); }
QItemSelection FlatProxyModel::mapSelectionToSource(const QItemSelection& proxySelection) const { QItemSelection sourceSelection; for (int i = 0; i < proxySelection.count(); i++) { const QItemSelectionRange& range = proxySelection[i]; SourceItem* topLeftItem = nullptr; SourceItem* bottomRightItem = nullptr; auto* currentItem = static_cast<SourceItem*>(range.topLeft().internalPointer()); int row = range.topLeft().row(); int left = range.topLeft().column(); int right = range.bottomRight().column(); while (currentItem && row <= range.bottomRight().row()) { Q_ASSERT(currentItem->pos() == row); if (!topLeftItem) topLeftItem = currentItem; if (currentItem->parent() == topLeftItem->parent()) { bottomRightItem = currentItem; } else { Q_ASSERT(topLeftItem && bottomRightItem); sourceSelection << QItemSelectionRange(mapToSource(createIndex(topLeftItem->pos(), left, topLeftItem)), mapToSource(createIndex(bottomRightItem->pos(), right, bottomRightItem))); topLeftItem = nullptr; bottomRightItem = nullptr; } // update loop vars currentItem = currentItem->next(); row++; } if (topLeftItem && bottomRightItem) { // there should be one range left. sourceSelection << QItemSelectionRange(mapToSource(createIndex(topLeftItem->pos(), left, topLeftItem)), mapToSource(createIndex(bottomRightItem->pos(), right, bottomRightItem))); } } return sourceSelection; }
void FlatProxyModel::removeSubTree(const QModelIndex &source_idx, bool emitRemove) { SourceItem *sourceItem = sourceToInternal(source_idx); if (!sourceItem) return; SourceItem *prevItem = sourceItem->parent(); if (sourceItem->sourceRow() > 0) { prevItem = prevItem->child(sourceItem->sourceRow() - 1); while (prevItem->childCount() > 0) { prevItem = prevItem->child(prevItem->childCount() - 1); } } SourceItem *lastItem = sourceItem; while (lastItem->childCount() > 0) { lastItem = lastItem->child(lastItem->childCount() - 1); } if (emitRemove) beginRemoveRows(QModelIndex(), sourceItem->pos(), lastItem->pos()); int nextPos = 0; if (prevItem) { prevItem->setNext(lastItem->next()); nextPos = prevItem->pos() + 1; } SourceItem *nextItem = lastItem->next(); while (nextItem) { nextItem->setPos(nextPos); nextPos++; nextItem = nextItem->next(); } sourceItem->parent()->removeChild(sourceItem); delete sourceItem; if (emitRemove) endRemoveRows(); }
FlatProxyModel::SourceItem *FlatProxyModel::insertSubTreeHelper(SourceItem *parentItem, SourceItem *lastItem_, const QModelIndex &source_idx) { SourceItem *lastItem = lastItem_; SourceItem *newItem = 0; for (int row = 0; row < sourceModel()->rowCount(source_idx); row++) { newItem = new SourceItem(row, parentItem); newItem->setPos(lastItem->pos() + 1); lastItem->setNext(newItem); lastItem = insertSubTreeHelper(newItem, newItem, sourceModel()->index(row, 0, source_idx)); } return lastItem; }
QModelIndex FlatProxyModel::index(int row, int column, const QModelIndex &parent) const { if (parent.isValid()) { qWarning() << "FlatProxyModel::index() called with valid parent:" << parent; return QModelIndex(); } if (!_rootSourceItem) { qWarning() << "FlatProxyModel::index() while model has no root Item"; return QModelIndex(); } SourceItem *item = _rootSourceItem; while (item->pos() != row) { item = item->findChild(row); if (!item) { qWarning() << "FlatProxyModel::index() no such row:" << row; return QModelIndex(); } } Q_ASSERT(item->pos() == row); return createIndex(row, column, item); }