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(); }
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::mapSelectionFromSource(const QItemSelection &sourceSelection) const { QList<_RangeRect> newRanges; QHash<QModelIndex, SourceItem *> itemLookup; // basics steps of the loop: // 1. convert each source ItemSelectionRange to a mapped Range (internal one for easier post processing) // 2. insert it into the list of previously mapped Ranges sorted by top location for (int i = 0; i < sourceSelection.count(); i++) { const QItemSelectionRange ¤tRange = sourceSelection[i]; QModelIndex currentParent = currentRange.topLeft().parent(); Q_ASSERT(currentParent == currentRange.bottomRight().parent()); SourceItem *parentItem = 0; if (!itemLookup.contains(currentParent)) { parentItem = sourceToInternal(currentParent); itemLookup[currentParent] = parentItem; } else { parentItem = itemLookup[currentParent]; } _RangeRect newRange = { currentRange.topLeft().column(), currentRange.bottomRight().column(), currentRange.topLeft().row(), currentRange.bottomRight().row(), parentItem->child(currentRange.topLeft().row()), parentItem->child(currentRange.bottomRight().row()) }; if (newRanges.isEmpty()) { newRanges << newRange; continue; } _RangeRect &first = newRanges[0]; if (newRange < first) { newRanges.prepend(newRange); continue; } bool inserted = false; for (int j = 0; j < newRanges.count() - 1; j++) { _RangeRect &a = newRanges[j]; _RangeRect &b = newRanges[j + 1]; if (a < newRange && newRange < b) { newRanges[j + 1] = newRange; inserted = true; break; } } if (inserted) continue; _RangeRect &last = newRanges[newRanges.count() - 1]; if (last < newRange) { newRanges.append(newRange); continue; } Q_ASSERT(false); } // we've got a sorted list of ranges now. so we can easily check if there is a possibility to merge for (int i = newRanges.count() - 1; i > 0; i--) { _RangeRect &a = newRanges[i - 1]; _RangeRect &b = newRanges[i]; if (a.left != b.left || a.right != b.right) continue; if (a.bottom < b.top - 1) { continue; } // all merge checks passed! if (b.bottom > a.bottom) { a.bottom = b.bottom; a.bottomItem = b.bottomItem; } // otherwise b is totally enclosed in a -> nothing to do but drop b. newRanges.removeAt(i); } QItemSelection proxySelection; for (int i = 0; i < newRanges.count(); i++) { _RangeRect &r = newRanges[i]; proxySelection << QItemSelectionRange(createIndex(r.top, r.left, r.topItem), createIndex(r.bottom, r.right, r.bottomItem)); } return proxySelection; }