123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- /*=========================================================================
- Library: CTK
- Copyright (c) Kitware Inc.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0.txt
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- =========================================================================*/
- // QT includes
- #include <QDebug>
- // CTK includes
- #include "ctkFlatProxyModel.h"
- // ----------------------------------------------------------------------------
- class ctkFlatProxyModelPrivate
- {
- Q_DECLARE_PUBLIC(ctkFlatProxyModel);
- protected:
- ctkFlatProxyModel* const q_ptr;
- public:
- ctkFlatProxyModelPrivate(ctkFlatProxyModel& object);
- void init();
- int indexLevel(const QModelIndex& index)const;
- int levelRowCount(const QModelIndex& index)const;
- int nextLevelRowCount(const QModelIndex& index)const;
- int rowCount(const QModelIndex& sourceIndex, int depth = 0)const;
- QModelIndex sourceParent(const QModelIndex& index)const;
- QModelIndex grandChild(const QModelIndex& parent, int& row, int depth)const;
- int StartFlattenLevel;
- int EndFlattenLevel;
- int HideLevel;
- };
- // ----------------------------------------------------------------------------
- // Methods ctkFlatProxyModelPrivate
- // ----------------------------------------------------------------------------
- ctkFlatProxyModelPrivate::ctkFlatProxyModelPrivate(ctkFlatProxyModel &object)
- : q_ptr(&object)
- {
- this->StartFlattenLevel = -1;
- this->EndFlattenLevel = -1;
- this->HideLevel = -1;
- }
- // ----------------------------------------------------------------------------
- void ctkFlatProxyModelPrivate::init()
- {
- }
- // ----------------------------------------------------------------------------
- int ctkFlatProxyModelPrivate::indexLevel(const QModelIndex& index)const
- {
- int level = -1;
- QModelIndex parent = index;
- while (parent.isValid())
- {
- parent = parent.parent();
- ++level;
- }
- return level;
- }
- // ----------------------------------------------------------------------------
- int ctkFlatProxyModelPrivate::levelRowCount(const QModelIndex& sourceIndex)const
- {
- Q_Q(const ctkFlatProxyModel);
- if (!sourceIndex.isValid()
- || this->StartFlattenLevel > this->indexLevel(sourceIndex)
- || this->EndFlattenLevel < this->indexLevel(sourceIndex))
- {
- return 0;
- }
- int previousRows = 0;
- for (int row = 0; row != sourceIndex.row() ; ++row)
- {
- previousRows += q->sourceModel()->rowCount(sourceIndex.sibling(row, sourceIndex.column()));
- }
- return previousRows + this->levelRowCount(sourceIndex.parent());
- }
- // ----------------------------------------------------------------------------
- int ctkFlatProxyModelPrivate::nextLevelRowCount(const QModelIndex& sourceIndex)const
- {
- Q_Q(const ctkFlatProxyModel);
- if (!sourceIndex.isValid()
- || this->StartFlattenLevel > this->indexLevel(sourceIndex)
- || this->EndFlattenLevel < this->indexLevel(sourceIndex))
- {
- return q->sourceModel()->rowCount(sourceIndex);
- }
- int rowCount = 0;
- QModelIndex sibling = sourceIndex.sibling(0, sourceIndex.column());
- for (int row = 0; sibling.isValid() ; ++row)
- {
- sibling = sourceIndex.sibling(row, sourceIndex.column());
- rowCount += q->sourceModel()->rowCount(sibling);
- }
- return rowCount;
- }
- // ----------------------------------------------------------------------------
- int ctkFlatProxyModelPrivate::rowCount(const QModelIndex& sourceIndex, int depth)const
- {
- Q_Q(const ctkFlatProxyModel);
- int rows = 0;
- if (depth < 0)
- {
- rows = 1;
- }
- else
- {
- --depth;
- for (int row = 0; row < q->sourceModel()->rowCount(sourceIndex); ++row)
- {
- QModelIndex child = q->sourceModel()->index(row, 0, sourceIndex);
- rows += this->rowCount(child, depth);
- }
- }
- return rows;
- }
- // ----------------------------------------------------------------------------
- QModelIndex ctkFlatProxyModelPrivate
- ::sourceParent(const QModelIndex& index)const
- {
- Q_Q(const ctkFlatProxyModel);
- QModelIndexList sourceIndexes;
- sourceIndexes << QModelIndex();
- QMap<int, int> rowCountsPerLevel;
- while (!sourceIndexes.isEmpty())
- {
- QModelIndex sourceIndex = sourceIndexes.takeFirst();
- const int rowCount = q->sourceModel()->rowCount(sourceIndex);
- for (int row = 0; row < rowCount; ++row)
- {
- QModelIndex child = q->sourceModel()->index(row, 0, sourceIndex);
- if (child.internalPointer() == index.internalPointer())
- {
- return sourceIndex;
- }
- else
- {
- sourceIndexes << child;
- }
- }
- }
- Q_ASSERT(false);
- return QModelIndex();
- }
- // ----------------------------------------------------------------------------
- QModelIndex ctkFlatProxyModelPrivate
- ::grandChild(const QModelIndex& parent, int& row, int depth)const
- {
- Q_Q(const ctkFlatProxyModel);
- const int rowCount = q->sourceModel()->rowCount(parent);
- if (depth > 0)
- {
- for (int i = 0; i < rowCount; ++i)
- {
- QModelIndex child = q->sourceModel()->index(i, 0, parent);
- QModelIndex found = this->grandChild(child, row, depth - 1);
- if (found.isValid())
- {
- return found;
- }
- }
- }
- else
- {
- if (row < rowCount)
- {
- QModelIndex sourceIndex = q->sourceModel()->index(
- row, 0, parent);
- return sourceIndex;
- }
- else
- {
- row -= rowCount;
- }
- }
- return QModelIndex();
- }
- // ----------------------------------------------------------------------------
- // Methods ctkFlatProxyModel
- // ----------------------------------------------------------------------------
- ctkFlatProxyModel::ctkFlatProxyModel(QObject *parentObject)
- : Superclass(parentObject)
- , d_ptr(new ctkFlatProxyModelPrivate(*this))
- {
- Q_D(ctkFlatProxyModel);
- d->init();
- }
- // ----------------------------------------------------------------------------
- ctkFlatProxyModel::~ctkFlatProxyModel()
- {
- }
- // ----------------------------------------------------------------------------
- int ctkFlatProxyModel::startFlattenLevel() const
- {
- Q_D(const ctkFlatProxyModel);
- return d->StartFlattenLevel;
- }
- // ----------------------------------------------------------------------------
- void ctkFlatProxyModel::setStartFlattenLevel(int level)
- {
- Q_D(ctkFlatProxyModel);
- d->StartFlattenLevel = level;
- Q_ASSERT( d->StartFlattenLevel <= d->EndFlattenLevel);
- }
- // ----------------------------------------------------------------------------
- int ctkFlatProxyModel::endFlattenLevel() const
- {
- Q_D(const ctkFlatProxyModel);
- return d->EndFlattenLevel;
- }
- // ----------------------------------------------------------------------------
- void ctkFlatProxyModel::setEndFlattenLevel(int level)
- {
- Q_D(ctkFlatProxyModel);
- d->EndFlattenLevel = level;
- Q_ASSERT( d->EndFlattenLevel >= d->EndFlattenLevel);
- }
- // ----------------------------------------------------------------------------
- int ctkFlatProxyModel::hideLevel()const
- {
- Q_D(const ctkFlatProxyModel);
- return d->HideLevel;
- }
- // ----------------------------------------------------------------------------
- void ctkFlatProxyModel::setHideLevel(int level)
- {
- Q_D(ctkFlatProxyModel);
- d->HideLevel = level;
- }
- // ----------------------------------------------------------------------------
- QModelIndex ctkFlatProxyModel::mapFromSource( const QModelIndex& sourceIndex ) const
- {
- Q_D(const ctkFlatProxyModel);
- if (!sourceIndex.isValid())
- {
- return QModelIndex();
- }
- int level = d->indexLevel(sourceIndex);
- if (d->HideLevel != -1
- && level >= d->HideLevel)
- {
- return QModelIndex();
- }
- if (d->EndFlattenLevel != -1
- && level <= d->EndFlattenLevel)
- {
- return QModelIndex();
- }
- int row = sourceIndex.row();
- if (d->EndFlattenLevel != -1)
- {
- row += d->levelRowCount(sourceIndex.parent());
- }
- return this->createIndex(row, sourceIndex.column(),
- sourceIndex.internalPointer());
- }
- // ----------------------------------------------------------------------------
- QModelIndex ctkFlatProxyModel::mapToSource( const QModelIndex& proxyIndex ) const
- {
- Q_D(const ctkFlatProxyModel);
- if (!proxyIndex.isValid())
- {
- return QModelIndex();
- }
- QModelIndex sourceParent = d->sourceParent(proxyIndex);
- int level = d->indexLevel(sourceParent);
- int levelRowCount = 0;
- if ((d->StartFlattenLevel != -1 || d->EndFlattenLevel != -1) &&
- (d->StartFlattenLevel != -1 || level >= d->StartFlattenLevel) &&
- (d->EndFlattenLevel != -1 || level <= d->EndFlattenLevel))
- {
- levelRowCount = d->levelRowCount(sourceParent);
- }
- QModelIndex sourceIndex = this->sourceModel()->index(
- proxyIndex.row() - levelRowCount, proxyIndex.column(), sourceParent);
- Q_ASSERT(sourceIndex.isValid());
- return sourceIndex;
- }
- // ----------------------------------------------------------------------------
- QModelIndex ctkFlatProxyModel::index(int row, int column, const QModelIndex &parent) const
- {
- Q_D(const ctkFlatProxyModel);
- if (row < 0 || column < 0)
- {
- return QModelIndex();
- }
- QModelIndex sourceParent = this->mapToSource(parent); // parent is already mapped at this point
- int sourceRow = row;
- QModelIndex sourceGrandChild = d->grandChild(
- sourceParent, sourceRow, qMax(0, d->EndFlattenLevel - d->indexLevel(sourceParent)));
- return this->createIndex(row, column, sourceGrandChild.internalPointer());
- }
- // ----------------------------------------------------------------------------
- QModelIndex ctkFlatProxyModel::parent(const QModelIndex &child) const
- {
- if (!child.isValid())
- {
- return QModelIndex();
- }
- QModelIndex sourceChild = this->mapToSource(child);
- QModelIndex sourceParent = sourceChild.parent();
- QModelIndex proxyParent = this->mapFromSource(sourceParent);
- return proxyParent;
- }
- // ----------------------------------------------------------------------------
- int ctkFlatProxyModel::rowCount(const QModelIndex &parent) const
- {
- Q_D(const ctkFlatProxyModel);
- QModelIndex sourceParent = this->mapToSource(parent);
- int sourceParentLevel = d->indexLevel(sourceParent);
- int depth = 0;
- if (sourceParentLevel >= d->StartFlattenLevel &&
- sourceParentLevel <= d->EndFlattenLevel)
- {
- depth = d->EndFlattenLevel - d->StartFlattenLevel;
- }
- return d->rowCount(sourceParent, depth);
- }
- // ----------------------------------------------------------------------------
- int ctkFlatProxyModel::columnCount(const QModelIndex &parent) const
- {
- QModelIndex proxyChild = this->index(0, 0, parent);
- if (parent.isValid() && !proxyChild.internalPointer())
- {
- Q_ASSERT(!parent.isValid() || proxyChild.internalPointer());
- }
- QModelIndex sourceChild = this->mapToSource(proxyChild);
- QModelIndex sourceParent = sourceChild.parent();
- return this->sourceModel()->columnCount(sourceParent);
- }
|