00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "krecursivefilterproxymodel.h"
00021
00022 #include <kdebug.h>
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 class KRecursiveFilterProxyModelPrivate
00035 {
00036 Q_DECLARE_PUBLIC(KRecursiveFilterProxyModel)
00037 KRecursiveFilterProxyModel *q_ptr;
00038 public:
00039 KRecursiveFilterProxyModelPrivate(KRecursiveFilterProxyModel *model)
00040 : q_ptr(model),
00041 ignoreRemove(false),
00042 completeInsert(false),
00043 completeRemove(false)
00044 {
00045 qRegisterMetaType<QModelIndex>( "QModelIndex" );
00046 }
00047
00048
00049
00050 inline void invokeDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
00051 {
00052 Q_Q(KRecursiveFilterProxyModel);
00053 bool success = QMetaObject::invokeMethod(q, "_q_sourceDataChanged", Qt::DirectConnection,
00054 Q_ARG(QModelIndex, topLeft),
00055 Q_ARG(QModelIndex, bottomRight));
00056 Q_UNUSED(success);
00057 Q_ASSERT(success);
00058 }
00059
00060 inline void invokeRowsInserted(const QModelIndex &source_parent, int start, int end)
00061 {
00062 Q_Q(KRecursiveFilterProxyModel);
00063 bool success = QMetaObject::invokeMethod(q, "_q_sourceRowsInserted", Qt::DirectConnection,
00064 Q_ARG(QModelIndex, source_parent),
00065 Q_ARG(int, start),
00066 Q_ARG(int, end));
00067 Q_UNUSED(success);
00068 Q_ASSERT(success);
00069 }
00070
00071 inline void invokeRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end)
00072 {
00073 Q_Q(KRecursiveFilterProxyModel);
00074 bool success = QMetaObject::invokeMethod(q, "_q_sourceRowsAboutToBeInserted", Qt::DirectConnection,
00075 Q_ARG(QModelIndex, source_parent),
00076 Q_ARG(int, start),
00077 Q_ARG(int, end));
00078 Q_UNUSED(success);
00079 Q_ASSERT(success);
00080 }
00081
00082 inline void invokeRowsRemoved(const QModelIndex &source_parent, int start, int end)
00083 {
00084 Q_Q(KRecursiveFilterProxyModel);
00085 bool success = QMetaObject::invokeMethod(q, "_q_sourceRowsRemoved", Qt::DirectConnection,
00086 Q_ARG(QModelIndex, source_parent),
00087 Q_ARG(int, start),
00088 Q_ARG(int, end));
00089 Q_UNUSED(success);
00090 Q_ASSERT(success);
00091 }
00092
00093 inline void invokeRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end)
00094 {
00095 Q_Q(KRecursiveFilterProxyModel);
00096 bool success = QMetaObject::invokeMethod(q, "_q_sourceRowsAboutToBeRemoved", Qt::DirectConnection,
00097 Q_ARG(QModelIndex, source_parent),
00098 Q_ARG(int, start),
00099 Q_ARG(int, end));
00100 Q_UNUSED(success);
00101 Q_ASSERT(success);
00102 }
00103
00104 void sourceDataChanged(const QModelIndex &source_top_left, const QModelIndex &source_bottom_right);
00105 void sourceRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end);
00106 void sourceRowsInserted(const QModelIndex &source_parent, int start, int end);
00107 void sourceRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end);
00108 void sourceRowsRemoved(const QModelIndex &source_parent, int start, int end);
00109
00116 void refreshAscendantMapping(const QModelIndex &index, bool refreshAll = false);
00117
00118 bool ignoreRemove;
00119 bool completeInsert;
00120 bool completeRemove;
00121 };
00122
00123 void KRecursiveFilterProxyModelPrivate::sourceDataChanged(const QModelIndex &source_top_left, const QModelIndex &source_bottom_right)
00124 {
00125 Q_Q(KRecursiveFilterProxyModel);
00126
00127 QModelIndex source_parent = source_top_left.parent();
00128
00129 if (!source_parent.isValid() || q->filterAcceptsRow(source_parent.row(), source_parent.parent()))
00130 {
00131 invokeDataChanged(source_top_left, source_bottom_right);
00132 return;
00133 }
00134
00135 bool requireRow = false;
00136 for (int row = source_top_left.row(); row <= source_bottom_right.row(); ++row)
00137 if (q->filterAcceptsRow(row, source_parent))
00138 {
00139 requireRow = true;
00140 break;
00141 }
00142
00143 if (!requireRow)
00144 return;
00145
00146 refreshAscendantMapping(source_parent);
00147 }
00148
00149 void KRecursiveFilterProxyModelPrivate::refreshAscendantMapping(const QModelIndex &index, bool refreshAll)
00150 {
00151 Q_Q(KRecursiveFilterProxyModel);
00152
00153 Q_ASSERT(index.isValid());
00154 QModelIndex lastAscendant = index;
00155 QModelIndex sourceAscendant = index.parent();
00156
00157
00158
00159 while(sourceAscendant.isValid() && !q->acceptRow(sourceAscendant.row(), sourceAscendant.parent()))
00160 {
00161 if (refreshAll)
00162 invokeDataChanged(sourceAscendant, sourceAscendant);
00163
00164 lastAscendant = sourceAscendant;
00165 sourceAscendant = sourceAscendant.parent();
00166 }
00167
00168
00169 invokeDataChanged(lastAscendant, lastAscendant);
00170 }
00171
00172 void KRecursiveFilterProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end)
00173 {
00174 Q_Q(KRecursiveFilterProxyModel);
00175
00176 if (!source_parent.isValid() || q->filterAcceptsRow(source_parent.row(), source_parent.parent()))
00177 {
00178 invokeRowsAboutToBeInserted(source_parent, start, end);
00179 completeInsert = true;
00180 }
00181 }
00182
00183 void KRecursiveFilterProxyModelPrivate::sourceRowsInserted(const QModelIndex &source_parent, int start, int end)
00184 {
00185 Q_Q(KRecursiveFilterProxyModel);
00186
00187 if (completeInsert)
00188 {
00189 completeInsert = false;
00190 invokeRowsInserted(source_parent, start, end);
00191
00192 return;
00193 }
00194
00195 bool requireRow = false;
00196 for (int row = start; row <= end; ++row)
00197 {
00198 if (q->filterAcceptsRow(row, source_parent))
00199 {
00200 requireRow = true;
00201 break;
00202 }
00203 }
00204
00205 if (!requireRow)
00206 {
00207
00208 return;
00209 }
00210
00211 refreshAscendantMapping(source_parent);
00212 }
00213
00214 void KRecursiveFilterProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end)
00215 {
00216 Q_Q(KRecursiveFilterProxyModel);
00217
00218 if (source_parent.isValid() && q->filterAcceptsRow(source_parent.row(), source_parent.parent()))
00219 {
00220 invokeRowsAboutToBeRemoved(source_parent, start, end);
00221 completeRemove = true;
00222 return;
00223 }
00224
00225 bool accepted = false;
00226 for (int row = start; row <= end; ++row)
00227 {
00228 if (q->filterAcceptsRow(row, source_parent))
00229 {
00230 accepted = true;
00231 break;
00232 }
00233 }
00234 if (!accepted)
00235 {
00236
00237 ignoreRemove = true;
00238 return;
00239 }
00240 completeRemove = true;
00241 invokeRowsAboutToBeRemoved(source_parent, start, end);
00242 }
00243
00244 void KRecursiveFilterProxyModelPrivate::sourceRowsRemoved(const QModelIndex &source_parent, int start, int end)
00245 {
00246 if (completeRemove)
00247 {
00248 completeRemove = false;
00249
00250 invokeRowsRemoved(source_parent, start, end);
00251
00252 }
00253
00254 if (ignoreRemove)
00255 {
00256 ignoreRemove = false;
00257 return;
00258 }
00259
00260
00261
00262
00263 if (source_parent.isValid())
00264 refreshAscendantMapping(source_parent, true);
00265 }
00266
00267 KRecursiveFilterProxyModel::KRecursiveFilterProxyModel(QObject* parent)
00268 : QSortFilterProxyModel(parent), d_ptr(new KRecursiveFilterProxyModelPrivate(this))
00269 {
00270 setDynamicSortFilter(true);
00271 }
00272
00273 KRecursiveFilterProxyModel::~KRecursiveFilterProxyModel()
00274 {
00275 delete d_ptr;
00276 }
00277
00278 bool KRecursiveFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
00279 {
00280
00281
00282 if (acceptRow(sourceRow, sourceParent))
00283 return true;
00284
00285 QModelIndex source_index = sourceModel()->index(sourceRow, 0, sourceParent);
00286 Q_ASSERT(source_index.isValid());
00287 bool accepted = false;
00288
00289 for (int row = 0 ; row < sourceModel()->rowCount(source_index); ++row)
00290 if (filterAcceptsRow(row, source_index))
00291 accepted = true;
00292
00293 return accepted;
00294 }
00295
00296 bool KRecursiveFilterProxyModel::acceptRow(int sourceRow, const QModelIndex& sourceParent) const
00297 {
00298 return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
00299 }
00300
00301 void KRecursiveFilterProxyModel::setSourceModel(QAbstractItemModel* model)
00302 {
00303
00304 disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
00305 this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));
00306
00307 disconnect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
00308 this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)));
00309
00310 disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
00311 this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
00312
00313 disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
00314 this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
00315
00316 disconnect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
00317 this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
00318
00319 QSortFilterProxyModel::setSourceModel(model);
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
00386 this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex)));
00387
00388 disconnect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
00389 this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int)));
00390
00391 disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
00392 this, SLOT(_q_sourceRowsInserted(QModelIndex,int,int)));
00393
00394 disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
00395 this, SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
00396
00397 disconnect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
00398 this, SLOT(_q_sourceRowsRemoved(QModelIndex,int,int)));
00399
00400
00401 connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
00402 this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));
00403
00404 connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
00405 this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)));
00406
00407 connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
00408 this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
00409
00410 connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
00411 this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
00412
00413 connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
00414 this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
00415
00416 }
00417
00418 #include "krecursivefilterproxymodel.moc"