00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kdescendantsproxymodel_p.h"
00022
00023 #include "kdebug.h"
00024
00025 #include <QtCore/QStringList>
00026
00032 class KDescendantsProxyModelPrivate
00033 {
00034 public:
00035
00036 KDescendantsProxyModelPrivate(KDescendantsProxyModel *model)
00037 : q_ptr(model),
00038 m_displayAncestorData( false ),
00039 m_ancestorSeparator( QLatin1String( " / " ) )
00040 {
00041 }
00042
00043 Q_DECLARE_PUBLIC( KDescendantsProxyModel )
00044 KDescendantsProxyModel *q_ptr;
00065 QModelIndex findSourceIndexForRow( int row, QModelIndex sourceParent) const;
00066
00075 bool isDescended(const QModelIndex &sourceIndex) const;
00076
00099 int descendantCount(const QModelIndex &sourceIndex, int ignoreTerminals=ObserveTerminals) const;
00100
00101 enum TerminalIgnorance
00102 {
00103 ObserveTerminals,
00104 IgnoreTerminals
00105 };
00106
00131 int descendedRow(const QModelIndex &sourceIndex) const;
00132
00133 QModelIndexList matchDescendants(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags, int until, const bool matchAll) const;
00134
00135 enum Operation
00136 {
00137 InsertOperation,
00138 RemoveOperation
00139 };
00140
00141 void insertOrRemoveRows(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, int type);
00142
00143 void sourceRowsAboutToBeInserted(const QModelIndex &, int start, int end);
00144 void sourceRowsInserted(const QModelIndex &, int start, int end);
00145 void sourceRowsAboutToBeRemoved(const QModelIndex &, int start, int end);
00146 void sourceRowsRemoved(const QModelIndex &, int start, int end);
00147 void sourceRowsAboutToBeMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destParent, int destRow);
00148 void sourceRowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destParent, int destRow);
00149 void sourceModelAboutToBeReset();
00150 void sourceModelReset();
00151 void sourceLayoutAboutToBeChanged();
00152 void sourceLayoutChanged();
00153 void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
00154
00155 QPersistentModelIndex m_rootDescendIndex;
00156
00157
00158
00159
00160 mutable QHash<qint64, int> m_descendantsCount;
00161
00162 bool m_displayAncestorData;
00163 QString m_ancestorSeparator;
00164
00165 QList<QPersistentModelIndex> m_terminalIndexes;
00166 void descendNewIndexes();
00167
00168 QList<QPersistentModelIndex> m_layoutChangePersistentIndexes;
00169 QModelIndexList m_proxyIndexes;
00170
00171 };
00172
00173 KDescendantsProxyModel::KDescendantsProxyModel( QObject *parent )
00174 : QAbstractProxyModel( parent ),
00175 d_ptr( new KDescendantsProxyModelPrivate(this) )
00176 {
00177 Q_D(KDescendantsProxyModel);
00178
00179 d->m_rootDescendIndex = QModelIndex();
00180 }
00181
00182 void KDescendantsProxyModel::setRootIndex(const QModelIndex &index)
00183 {
00184 Q_D(KDescendantsProxyModel);
00185
00186 if (index.isValid())
00187 Q_ASSERT(index.model() == sourceModel());
00188
00189 d->m_rootDescendIndex = index;
00190 d->m_descendantsCount.clear();
00191 reset();
00192 }
00193
00194 KDescendantsProxyModel::~KDescendantsProxyModel()
00195 {
00196 Q_D(KDescendantsProxyModel);
00197 d->m_descendantsCount.clear();
00198 delete d_ptr;
00199 }
00200
00201 QModelIndex KDescendantsProxyModelPrivate::findSourceIndexForRow( int row, QModelIndex idx ) const
00202 {
00203 Q_Q( const KDescendantsProxyModel );
00204 int childCount = q->sourceModel()->rowCount(idx);
00205 for (int childRow = 0; childRow < childCount; childRow++)
00206 {
00207 QModelIndex childIndex = q->sourceModel()->index(childRow, 0, idx);
00208 if (row == 0)
00209 {
00210 return childIndex;
00211 }
00212 row--;
00213 if (q->sourceModel()->hasChildren(childIndex))
00214 {
00215 int childDesc = descendantCount(childIndex);
00216 if (childDesc > row)
00217 {
00218 return findSourceIndexForRow(row, childIndex);
00219 }
00220 row -= childDesc;
00221 }
00222 }
00223
00224
00225 return QModelIndex();
00226 }
00227
00228 void KDescendantsProxyModel::setSourceModel(QAbstractItemModel * sourceModel)
00229 {
00230 Q_D(KDescendantsProxyModel);
00231
00232 disconnect( sourceModel, SIGNAL(modelReset()), this, SLOT( sourceModelReset() ) );
00233 disconnect( sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset() ) );
00234 disconnect( sourceModel, SIGNAL(layoutChanged()), this, SLOT(sourceLayoutChanged()) );
00235 disconnect( sourceModel, SIGNAL(layoutAboutToBeChanged()), this, SLOT(sourceLayoutAboutToBeChanged()) );
00236 disconnect( sourceModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
00237 this, SLOT(sourceDataChanged(const QModelIndex &, const QModelIndex & ) ) );
00238 disconnect( sourceModel, SIGNAL(rowsInserted(const QModelIndex, int, int)),
00239 this, SLOT(sourceRowsInserted(const QModelIndex, int, int)) );
00240 disconnect( sourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex, int, int)),
00241 this, SLOT(sourceRowsAboutToBeInserted(const QModelIndex, int, int)) );
00242 disconnect( sourceModel, SIGNAL(rowsRemoved(const QModelIndex, int, int)),
00243 this, SLOT(sourceRowsRemoved(const QModelIndex, int, int)) );
00244 disconnect( sourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex, int, int)),
00245 this, SLOT(sourceRowsAboutToBeRemoved(const QModelIndex, int, int)) );
00246 disconnect( sourceModel, SIGNAL(rowsMoved(const QModelIndex, int, int, const QModelIndex, int)),
00247 this, SLOT(sourceRowsMoved(const QModelIndex, int, int, const QModelIndex, int)) );
00248 disconnect( sourceModel, SIGNAL(rowsAboutToBeMoved(const QModelIndex, int, int, const QModelIndex, int)),
00249 this, SLOT(sourceRowsAboutToBeMoved(const QModelIndex, int, int, const QModelIndex, int) ) );
00250
00251 QAbstractProxyModel::setSourceModel( sourceModel );
00252 connect( sourceModel, SIGNAL(modelReset()), SLOT( sourceModelReset() ) );
00253 connect( sourceModel, SIGNAL(modelAboutToBeReset()), SLOT(sourceModelAboutToBeReset() ) );
00254 connect( sourceModel, SIGNAL(layoutChanged()), SLOT(sourceLayoutChanged()) );
00255 connect( sourceModel, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged()) );
00256 connect( sourceModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
00257 SLOT(sourceDataChanged(const QModelIndex &, const QModelIndex & ) ) );
00258 connect( sourceModel, SIGNAL(rowsInserted(const QModelIndex, int, int)),
00259 SLOT(sourceRowsInserted(const QModelIndex, int, int)) );
00260 connect( sourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex, int, int)),
00261 SLOT(sourceRowsAboutToBeInserted(const QModelIndex, int, int)) );
00262 connect( sourceModel, SIGNAL(rowsRemoved(const QModelIndex, int, int)),
00263 SLOT(sourceRowsRemoved(const QModelIndex, int, int)) );
00264 connect( sourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex, int, int)),
00265 SLOT(sourceRowsAboutToBeRemoved(const QModelIndex, int, int)) );
00266 connect( sourceModel, SIGNAL(rowsMoved(const QModelIndex, int, int, const QModelIndex, int)),
00267 SLOT(sourceRowsMoved(const QModelIndex, int, int, const QModelIndex, int)) );
00268 connect( sourceModel, SIGNAL(rowsAboutToBeMoved(const QModelIndex, int, int, const QModelIndex, int)),
00269 SLOT(sourceRowsAboutToBeMoved(const QModelIndex, int, int, const QModelIndex, int) ) );
00270
00271 d->m_descendantsCount.clear();
00272 reset();
00273 }
00274
00275 bool KDescendantsProxyModelPrivate::isDescended(const QModelIndex &sourceIndex) const
00276 {
00277 Q_Q(const KDescendantsProxyModel);
00278
00279 if (sourceIndex == m_rootDescendIndex)
00280 {
00281 return false;
00282 }
00283
00284 QModelIndex parentIndex = q->sourceModel()->parent(sourceIndex);
00285
00286 if (parentIndex == m_rootDescendIndex)
00287 {
00288 return true;
00289 }
00290 bool found = false;
00291
00292 forever
00293 {
00294 parentIndex = parentIndex.parent();
00295 if (parentIndex == m_rootDescendIndex)
00296 {
00297 found = true;
00298 break;
00299 }
00300 if (!parentIndex.isValid())
00301 break;
00302 }
00303 return found;
00304 }
00305
00306 int KDescendantsProxyModelPrivate::descendedRow(const QModelIndex &sourceIndex) const
00307 {
00308 Q_Q(const KDescendantsProxyModel);
00309 QModelIndex parentIndex = sourceIndex.parent();
00310 int row = sourceIndex.row();
00311
00312 for (int childRow = 0; childRow < sourceIndex.row(); childRow++ )
00313 {
00314 QModelIndex childIndex = q->sourceModel()->index( childRow, sourceIndex.column(), parentIndex );
00315 if (q->sourceModel()->hasChildren(childIndex))
00316 row += descendantCount(childIndex);
00317 }
00318
00319 if (parentIndex == m_rootDescendIndex)
00320 {
00321
00322 if (row < 0)
00323 {
00324 return 0;
00325 }
00326 return row;
00327 }
00328 else if(!parentIndex.isValid())
00329 {
00330
00331
00332 return 0;
00333 }
00334 else {
00335 int dr = descendedRow(parentIndex);
00336 return row + dr + 1;
00337 }
00338 }
00339
00340 QModelIndex KDescendantsProxyModel::mapFromSource(const QModelIndex & sourceIndex) const
00341 {
00342 Q_D(const KDescendantsProxyModel);
00343
00344 if (sourceIndex == d->m_rootDescendIndex)
00345 {
00346 return QModelIndex();
00347 }
00348
00349 if ( d->isDescended( sourceIndex ) )
00350 {
00351 int row = d->descendedRow( sourceIndex );
00352 if (row < 0)
00353 return QModelIndex();
00354 return createIndex( row, sourceIndex.column() );
00355 } else {
00356 return QModelIndex();
00357 }
00358 }
00359
00360 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &sourceParentIndex, int start, int end)
00361 {
00362 insertOrRemoveRows(sourceParentIndex, start, end, InsertOperation);
00363 }
00364
00365 void KDescendantsProxyModelPrivate::insertOrRemoveRows(const QModelIndex &sourceParentIndex, int start, int end, int operationType)
00366 {
00367
00368 Q_Q(KDescendantsProxyModel);
00369
00370 int c = descendedRow(sourceParentIndex);
00371
00372
00373
00374
00375
00376
00377 const int column = 0;
00378 for (int childRow = 0; childRow < start; childRow++)
00379 {
00380 QModelIndex childIndex = q->sourceModel()->index( childRow, column, sourceParentIndex );
00381
00382 if (q->sourceModel()->hasChildren(childIndex))
00383 c += descendantCount(childIndex);
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 int proxy_start = c + start;
00404 int proxy_end = c + end;
00405
00406 if (isDescended(sourceParentIndex))
00407 {
00408 proxy_start++;
00409 proxy_end++;
00410 }
00411
00412 if (operationType == InsertOperation)
00413 q->beginInsertRows(m_rootDescendIndex, proxy_start, proxy_end);
00414 else if (operationType == RemoveOperation)
00415 {
00416
00417 for (int childRow = start; childRow <= end; childRow++)
00418 {
00419 QModelIndex childIndex = q->sourceModel()->index(childRow, column, sourceParentIndex);
00420 if (q->sourceModel()->hasChildren(childIndex))
00421 proxy_end += descendantCount(childIndex);
00422 }
00423 Q_ASSERT( proxy_end <= q->rowCount() );
00424 q->beginRemoveRows(m_rootDescendIndex, proxy_start, proxy_end);
00425 }
00426 }
00427
00428 void KDescendantsProxyModelPrivate::sourceRowsInserted(const QModelIndex &sourceParentIndex, int start, int end)
00429 {
00430 Q_Q(KDescendantsProxyModel);
00431
00432 m_descendantsCount.clear();
00433
00434
00435
00436
00437 const int column = 0;
00438 for (int childRow = start; childRow <= end; childRow++)
00439 {
00440 QModelIndex childIndex = q->sourceModel()->index( childRow, column, sourceParentIndex );
00441 m_terminalIndexes << QPersistentModelIndex(childIndex);
00442 }
00443
00444 q->endInsertRows();
00445 descendNewIndexes();
00446 }
00447
00448 void KDescendantsProxyModelPrivate::descendNewIndexes()
00449 {
00450 Q_Q(KDescendantsProxyModel);
00451
00452 QMutableListIterator<QPersistentModelIndex> i(m_terminalIndexes);
00453 while (i.hasNext())
00454 {
00455 QModelIndex idx = i.next();
00456
00457 int descCount = descendantCount(idx, IgnoreTerminals);
00458
00459 if (descCount <= 0)
00460 {
00461 i.remove();
00462 continue;
00463 }
00464
00465
00466
00467 int proxyStart = descendedRow(idx);
00468
00469 int proxyEnd = proxyStart + descendantCount(idx, IgnoreTerminals);
00470
00471 if (isDescended(idx))
00472 {
00473 proxyStart++;
00474 proxyEnd++;
00475 }
00476 q->beginInsertRows(QModelIndex(), proxyStart, proxyEnd - 1 );
00477 i.remove();
00478 m_descendantsCount.clear();
00479 q->endInsertRows();
00480 }
00481 }
00482
00483
00484 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destParent, int destRow)
00485 {
00486 Q_Q(KDescendantsProxyModel);
00487 int c = descendedRow(parent);
00488 int d = descendedRow(destParent);
00489
00490 bool allowMove = q->beginMoveRows(QModelIndex(), c+1+start, c+1+end, QModelIndex(), d+1+destRow);
00491 Q_ASSERT(allowMove);
00492 }
00493
00494 void KDescendantsProxyModelPrivate::sourceRowsMoved(const QModelIndex &sourceParentIndex, int start, int end, const QModelIndex &destParentIndex, int destRow)
00495 {
00496 Q_Q(KDescendantsProxyModel);
00497 Q_UNUSED(sourceParentIndex);
00498 Q_UNUSED(start);
00499 Q_UNUSED(end);
00500 Q_UNUSED(destParentIndex);
00501 Q_UNUSED(destRow);
00502
00503 m_descendantsCount.clear();
00504
00505 q->endMoveRows();
00506 }
00507
00508
00509 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
00510 {
00511 insertOrRemoveRows(parent, start, end, RemoveOperation);
00512 }
00513
00514 void KDescendantsProxyModelPrivate::sourceRowsRemoved(const QModelIndex &sourceParentIndex, int start, int end)
00515 {
00516 Q_Q(KDescendantsProxyModel);
00517 Q_UNUSED(sourceParentIndex);
00518 Q_UNUSED(start);
00519 Q_UNUSED(end);
00520
00521 m_descendantsCount.clear();
00522 q->endRemoveRows();
00523 }
00524
00525 void KDescendantsProxyModelPrivate::sourceModelAboutToBeReset()
00526 {
00527 Q_Q(KDescendantsProxyModel);
00528 q->beginResetModel();
00529 }
00530
00531 void KDescendantsProxyModelPrivate::sourceModelReset()
00532 {
00533 Q_Q(KDescendantsProxyModel);
00534
00535 m_descendantsCount.clear();
00536 q->endResetModel();
00537 }
00538
00539 void KDescendantsProxyModelPrivate::sourceLayoutAboutToBeChanged()
00540 {
00541 Q_Q(KDescendantsProxyModel);
00542
00543 emit q->layoutAboutToBeChanged();
00544
00545 foreach(const QPersistentModelIndex &proxyPersistentIndex, q->persistentIndexList())
00546 {
00547 m_proxyIndexes << proxyPersistentIndex;
00548 m_layoutChangePersistentIndexes << QPersistentModelIndex(q->mapToSource(proxyPersistentIndex));
00549 }
00550 }
00551
00552 void KDescendantsProxyModelPrivate::sourceLayoutChanged()
00553 {
00554 Q_Q(KDescendantsProxyModel);
00555
00556 for(int i = 0; i < m_proxyIndexes.size(); ++i)
00557 {
00558 q->changePersistentIndex(m_proxyIndexes.at(i), q->mapFromSource(m_layoutChangePersistentIndexes.at(i)));
00559 }
00560
00561 m_layoutChangePersistentIndexes.clear();
00562 m_proxyIndexes.clear();
00563
00564 m_descendantsCount.clear();
00565
00566 emit q->layoutChanged();
00567 }
00568
00569 QModelIndex KDescendantsProxyModel::mapToSource(const QModelIndex &proxyIndex) const
00570 {
00571 Q_D(const KDescendantsProxyModel);
00572
00573 if (!proxyIndex.isValid())
00574 return d->m_rootDescendIndex;
00575
00576 if (proxyIndex.column() >= sourceModel()->columnCount())
00577 return QModelIndex();
00578
00579 QModelIndex idx = d->findSourceIndexForRow( proxyIndex.row(), d->m_rootDescendIndex );
00580
00581 if (proxyIndex.column() > 0)
00582 {
00583 return sourceModel()->index(idx.row(), proxyIndex.column(), idx.parent());
00584 }
00585 return idx;
00586 }
00587
00588 QVariant KDescendantsProxyModel::data(const QModelIndex & index, int role) const
00589 {
00590 Q_D(const KDescendantsProxyModel );
00591
00592 if (!sourceModel())
00593 return QVariant();
00594
00595 if (!index.isValid())
00596 return sourceModel()->data(index, role);
00597
00598 QModelIndex sourceIndex = mapToSource( index );
00599
00600 if ((d->m_displayAncestorData) && ( role == Qt::DisplayRole ) )
00601 {
00602 if (!sourceIndex.isValid())
00603 {
00604 return QVariant();
00605 }
00606 QString displayData = sourceIndex.data().toString();
00607 sourceIndex = sourceIndex.parent();
00608 while (sourceIndex.isValid())
00609 {
00610 displayData.prepend(d->m_ancestorSeparator);
00611 displayData.prepend(sourceIndex.data().toString());
00612 sourceIndex = sourceIndex.parent();
00613 }
00614 return displayData;
00615 } else {
00616 return sourceIndex.data(role);
00617 }
00618
00619 }
00620
00621 QMimeData* KDescendantsProxyModel::mimeData( const QModelIndexList & indexes ) const
00622 {
00623 Q_ASSERT(sourceModel());
00624 QModelIndexList sourceIndexes;
00625 foreach(const QModelIndex& index, indexes)
00626 sourceIndexes << mapToSource(index);
00627 return sourceModel()->mimeData(sourceIndexes);
00628 }
00629
00630 QStringList KDescendantsProxyModel::mimeTypes() const
00631 {
00632 Q_ASSERT(sourceModel());
00633 return sourceModel()->mimeTypes();
00634 }
00635
00636 bool KDescendantsProxyModel::hasChildren ( const QModelIndex & parent ) const
00637 {
00638 return rowCount(parent) > 0;
00639 }
00640
00641 int KDescendantsProxyModel::rowCount(const QModelIndex & proxyIndex) const
00642 {
00643 Q_D(const KDescendantsProxyModel );
00644
00645 if (!sourceModel() || proxyIndex.column() > 0)
00646 return 0;
00647
00648 QModelIndex sourceIndex = mapToSource(proxyIndex);
00649
00650 if (sourceIndex == d->m_rootDescendIndex)
00651 {
00652 int c = d->descendantCount(sourceIndex);
00653 return c;
00654 }
00655 return 0;
00656 }
00657
00658 void KDescendantsProxyModelPrivate::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
00659 {
00660 Q_Q( KDescendantsProxyModel );
00661 int topRow = topLeft.row();
00662 int bottomRow = bottomRight.row();
00663
00664 for(int i = topRow; i <= bottomRow; ++i)
00665 {
00666 QModelIndex sourceTopLeft = q->sourceModel()->index(i, topLeft.column(), topLeft.parent());
00667 QModelIndex proxyTopLeft = q->mapFromSource(sourceTopLeft);
00668
00669
00670 QModelIndex sourceBottomRight = q->sourceModel()->index(i, bottomRight.column(), bottomRight.parent());
00671 QModelIndex proxyBottomRight = q->mapFromSource(sourceBottomRight);
00672 emit q->dataChanged(proxyTopLeft, proxyBottomRight);
00673 }
00674 }
00675
00676 int KDescendantsProxyModelPrivate::descendantCount(const QModelIndex &sourceIndex, int ignoreTerminals) const
00677 {
00678 if (sourceIndex.column() > 0)
00679 return 0;
00680
00681 if (ObserveTerminals == ignoreTerminals)
00682 {
00683 if (m_terminalIndexes.contains(sourceIndex))
00684 {
00685 return 0;
00686 }
00687 }
00688
00689 Q_Q( const KDescendantsProxyModel );
00690 if (m_descendantsCount.contains(sourceIndex.internalId()))
00691 {
00692 return m_descendantsCount.value(sourceIndex.internalId());
00693 }
00694
00695 int sourceIndexRowCount = q->sourceModel()->rowCount(sourceIndex);
00696 if (sourceIndexRowCount == 0)
00697 return 0;
00698 int c = 0;
00699 c += sourceIndexRowCount;
00700
00701 int childRow = 0;
00702 QModelIndex childIndex = q->sourceModel()->index(childRow, 0, sourceIndex);
00703 while (childIndex.isValid())
00704 {
00705 c += descendantCount(childIndex);
00706 childRow++;
00707 childIndex = q->sourceModel()->index(childRow, 0, sourceIndex);
00708 }
00709
00710 m_descendantsCount.insert( sourceIndex.internalId(), c );
00711
00712 return c;
00713 }
00714
00715 QModelIndex KDescendantsProxyModel::index(int r, int c, const QModelIndex& parent) const
00716 {
00717 Q_D(const KDescendantsProxyModel );
00718
00719 if (!sourceModel())
00720 return QModelIndex();
00721
00722
00723 if ( (r < 0) || (c < 0) || (c >= sourceModel()->columnCount() ) )
00724 return QModelIndex();
00725
00726 if ( r >= d->descendantCount(parent) )
00727 return QModelIndex();
00728
00729
00730 if (parent.isValid())
00731 return QModelIndex();
00732
00733 return createIndex(r, c);
00734 }
00735
00736 QModelIndex KDescendantsProxyModel::parent(const QModelIndex& proxyIndex) const
00737 {
00738 Q_UNUSED(proxyIndex);
00739
00740 return QModelIndex();
00741 }
00742
00743 int KDescendantsProxyModel::columnCount(const QModelIndex &index) const
00744 {
00745 if (!sourceModel())
00746 return 0;
00747
00748 return sourceModel()->columnCount();
00749 }
00750
00751 void KDescendantsProxyModel::setDisplayAncestorData( bool display )
00752 {
00753 Q_D(KDescendantsProxyModel);
00754 d->m_displayAncestorData = display;
00755 }
00756
00757 bool KDescendantsProxyModel::displayAncestorData() const
00758 {
00759 Q_D(const KDescendantsProxyModel );
00760 return d->m_displayAncestorData;
00761 }
00762
00763 void KDescendantsProxyModel::setAncestorSeparator( const QString &separator )
00764 {
00765 Q_D(KDescendantsProxyModel);
00766 d->m_ancestorSeparator = separator;
00767 }
00768
00769 QString KDescendantsProxyModel::ancestorSeparator() const
00770 {
00771 Q_D(const KDescendantsProxyModel );
00772 return d->m_ancestorSeparator;
00773 }
00774
00775 Qt::ItemFlags KDescendantsProxyModel::flags( const QModelIndex &index ) const
00776 {
00777
00778
00779 if (!index.isValid())
00780 return 0;
00781 return QAbstractProxyModel::flags(index);
00782 }
00783
00784 QModelIndexList KDescendantsProxyModelPrivate::matchDescendants(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags, int until, const bool matchAll) const
00785 {
00786 Q_Q(const KDescendantsProxyModel);
00787 QModelIndexList matches;
00788
00789 if (!start.isValid())
00790 return matches;
00791
00792 const int column = start.column();
00793 const int firstRow = 0;
00794 QModelIndex idx = start;
00795
00796 while (idx.row() <= until)
00797 {
00798 Q_ASSERT(idx.isValid());
00799
00800 if (q->sourceModel()->hasChildren(idx))
00801 {
00802 QModelIndex firstChild = idx.child(firstRow, column);
00803 matches << q->match(q->mapFromSource(firstChild), role, value, hits, flags);
00804 if (!matchAll && (matches.size() >= hits))
00805 {
00806 return matches.mid(0, hits);
00807 }
00808 }
00809 int row = idx.row();
00810 if (row == until)
00811 {
00812 break;
00813 }
00814 idx = idx.sibling(row + 1, column);
00815 }
00816
00817 return matches;
00818 }
00819
00820 QModelIndexList KDescendantsProxyModel::match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const
00821 {
00822 Q_D(const KDescendantsProxyModel );
00823
00824
00825
00826
00827 QModelIndexList sourceList;
00828 QModelIndexList proxyList;
00829
00830 QModelIndex beginIndex = start;
00831 QModelIndex sourceStart = mapToSource(start);
00832 QModelIndex parent = sourceModel()->parent(sourceStart);
00833
00834 int parentRowCount = sourceModel()->rowCount(sourceModel()->parent(sourceStart));
00835
00836 const bool matchAll = (hits == -1);
00837 const int firstHit = 1;
00838 const int column = start.column();
00839 const int proxyRowCount = rowCount();
00840
00841 Q_ASSERT(sourceStart.column() == start.column());
00842 sourceList = sourceModel()->match(sourceStart, role, value, firstHit, flags);
00843
00844 int lastRow;
00845 if (sourceList.isEmpty())
00846 {
00847 lastRow = parentRowCount - 1;
00848 proxyList = d->matchDescendants(mapToSource(start), role, value, hits, flags, lastRow, matchAll);
00849
00850 if (matchAll)
00851 return proxyList;
00852
00853 return proxyList.mid(0, hits);
00854
00855 } else {
00856 forever
00857 {
00858 QModelIndex firstIndexHit;
00859 if (sourceList.isEmpty())
00860 {
00861 lastRow = parentRowCount - 1;
00862 } else {
00863 firstIndexHit = sourceList.first();
00864
00865 Q_ASSERT(firstIndexHit.column() == start.column());
00866
00867 lastRow = firstIndexHit.row() - 1;
00868 }
00869
00870 proxyList << d->matchDescendants(sourceStart, role, value, hits, flags, lastRow, matchAll);
00871
00872 if (sourceList.isEmpty())
00873 break;
00874
00875 QModelIndex proxyFirst = mapFromSource(firstIndexHit);
00876 proxyList << proxyFirst;
00877
00878 if (!matchAll && ( proxyList.size() >= hits))
00879 {
00880 return proxyList.mid(0, hits);
00881 }
00882
00883 if (proxyFirst.row() == proxyRowCount - 1)
00884 break;
00885
00886 sourceStart = mapToSource(index(proxyFirst.row() + 1, proxyFirst.column()));
00887 Q_ASSERT(sourceStart.isValid());
00888
00889 sourceList = sourceModel()->match(sourceStart, role, value, firstHit, flags);
00890 }
00891 }
00892
00893 QModelIndex nextStart = start.sibling(start.row() + parentRowCount + 1, column);
00894 if (nextStart.isValid())
00895 proxyList << match(nextStart, role, value, hits, flags);
00896
00897 if (matchAll)
00898 return proxyList;
00899
00900 return proxyList.mid(0, hits);
00901 }
00902
00903 Qt::DropActions KDescendantsProxyModel::supportedDropActions() const
00904 {
00905 Q_ASSERT(sourceModel());
00906 return sourceModel()->supportedDropActions();
00907 }
00908
00909 #include "moc_kdescendantsproxymodel_p.cpp"