예제 #1
0
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();
}
예제 #2
0
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();
}
예제 #3
0
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 &currentRange = 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;
}