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 class KRecursiveFilterProxyModelPrivate
00025 {
00026 Q_DECLARE_PUBLIC(KRecursiveFilterProxyModel)
00027 KRecursiveFilterProxyModel *q_ptr;
00028 public:
00029 KRecursiveFilterProxyModelPrivate(KRecursiveFilterProxyModel *model)
00030 : q_ptr(model),
00031 ignoreRemove(false),
00032 completeInsert(false),
00033 completeRemove(false)
00034 {
00035 qRegisterMetaType<QModelIndex>("QModelIndex");
00036 }
00037
00038 inline void invokeDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
00039 {
00040 Q_Q(KRecursiveFilterProxyModel);
00041 bool success = QMetaObject::invokeMethod(q, "_q_sourceDataChanged", Qt::DirectConnection,
00042 Q_ARG(QModelIndex, topLeft),
00043 Q_ARG(QModelIndex, bottomRight));
00044 Q_ASSERT(success);
00045 }
00046
00047 inline void invokeRowsInserted(const QModelIndex &source_parent, int start, int end)
00048 {
00049 Q_Q(KRecursiveFilterProxyModel);
00050 bool success = QMetaObject::invokeMethod(q, "_q_sourceRowsInserted", Qt::DirectConnection,
00051 Q_ARG(QModelIndex, source_parent),
00052 Q_ARG(int, start),
00053 Q_ARG(int, end));
00054 Q_ASSERT(success);
00055 }
00056
00057 inline void invokeRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end)
00058 {
00059 Q_Q(KRecursiveFilterProxyModel);
00060 bool success = QMetaObject::invokeMethod(q, "_q_sourceRowsAboutToBeInserted", Qt::DirectConnection,
00061 Q_ARG(QModelIndex, source_parent),
00062 Q_ARG(int, start),
00063 Q_ARG(int, end));
00064 Q_ASSERT(success);
00065 }
00066
00067 inline void invokeRowsRemoved(const QModelIndex &source_parent, int start, int end)
00068 {
00069 Q_Q(KRecursiveFilterProxyModel);
00070 bool success = QMetaObject::invokeMethod(q, "_q_sourceRowsRemoved", Qt::DirectConnection,
00071 Q_ARG(QModelIndex, source_parent),
00072 Q_ARG(int, start),
00073 Q_ARG(int, end));
00074 Q_ASSERT(success);
00075 }
00076
00077 inline void invokeRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end)
00078 {
00079 Q_Q(KRecursiveFilterProxyModel);
00080 bool success = QMetaObject::invokeMethod(q, "_q_sourceRowsAboutToBeRemoved", Qt::DirectConnection,
00081 Q_ARG(QModelIndex, source_parent),
00082 Q_ARG(int, start),
00083 Q_ARG(int, end));
00084 Q_ASSERT(success);
00085 }
00086
00087 void sourceDataChanged(const QModelIndex &source_top_left, const QModelIndex &source_bottom_right);
00088 void sourceRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end);
00089 void sourceRowsInserted(const QModelIndex &source_parent, int start, int end);
00090 void sourceRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end);
00091 void sourceRowsRemoved(const QModelIndex &source_parent, int start, int end);
00092
00099 void refreshAscendantMapping(const QModelIndex &index, bool refreshAll = false);
00100
00101 bool ignoreRemove;
00102 bool completeInsert;
00103 bool completeRemove;
00104 };
00105
00106 void KRecursiveFilterProxyModelPrivate::sourceDataChanged(const QModelIndex &source_top_left, const QModelIndex &source_bottom_right)
00107 {
00108 Q_Q(KRecursiveFilterProxyModel);
00109
00110 QModelIndex source_parent = source_top_left.parent();
00111
00112 if (!source_parent.isValid() || q->filterAcceptsRow(source_parent.row(), source_parent.parent()))
00113 {
00114 invokeDataChanged(source_top_left, source_bottom_right);
00115 return;
00116 }
00117
00118 int start = -1;
00119 int end = -1;
00120 bool requireRow = false;
00121 for (int row = source_top_left.row(); row <= source_bottom_right.row(); ++row)
00122 if (q->filterAcceptsRow(row, source_parent))
00123 {
00124 requireRow = true;
00125 break;
00126 }
00127
00128 if (!requireRow)
00129 return;
00130
00131 refreshAscendantMapping(source_parent);
00132 }
00133
00134 void KRecursiveFilterProxyModelPrivate::refreshAscendantMapping(const QModelIndex &index, bool refreshAll)
00135 {
00136 Q_Q(KRecursiveFilterProxyModel);
00137
00138 Q_ASSERT(index.isValid());
00139 QModelIndex lastAscendant = index;
00140 QModelIndex sourceAscendant = index.parent();
00141 int lastRow;
00142
00143
00144
00145 while(sourceAscendant.isValid() && !q->acceptRow(sourceAscendant.row(), sourceAscendant.parent()))
00146 {
00147 if (refreshAll)
00148 invokeDataChanged(sourceAscendant, sourceAscendant);
00149
00150 lastAscendant = sourceAscendant;
00151 sourceAscendant = sourceAscendant.parent();
00152 }
00153
00154
00155 invokeDataChanged(lastAscendant, lastAscendant);
00156 }
00157
00158 void KRecursiveFilterProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end)
00159 {
00160 Q_Q(KRecursiveFilterProxyModel);
00161
00162 if (!source_parent.isValid() || q->filterAcceptsRow(source_parent.row(), source_parent.parent()))
00163 {
00164 invokeRowsAboutToBeInserted(source_parent, start, end);
00165 completeInsert = true;
00166 }
00167 }
00168
00169 void KRecursiveFilterProxyModelPrivate::sourceRowsInserted(const QModelIndex &source_parent, int start, int end)
00170 {
00171 Q_Q(KRecursiveFilterProxyModel);
00172
00173 if (completeInsert)
00174 {
00175 completeInsert = false;
00176 invokeRowsInserted(source_parent, start, end);
00177
00178 return;
00179 }
00180
00181 bool requireRow = false;
00182 for (int row = start; row <= end; ++row)
00183 {
00184 if (q->filterAcceptsRow(row, source_parent))
00185 {
00186 requireRow = true;
00187 break;
00188 }
00189 }
00190
00191 if (!requireRow)
00192 {
00193
00194 return;
00195 }
00196
00197 refreshAscendantMapping(source_parent);
00198 }
00199
00200 void KRecursiveFilterProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end)
00201 {
00202 Q_Q(KRecursiveFilterProxyModel);
00203
00204 if (q->filterAcceptsRow(source_parent.row(), source_parent.parent()))
00205 {
00206 invokeRowsAboutToBeRemoved(source_parent, start, end);
00207 completeRemove = true;
00208 return;
00209 }
00210
00211 bool accepted = false;
00212 for (int row = start; row < end; ++row)
00213 {
00214 if (q->filterAcceptsRow(row, source_parent))
00215 {
00216 accepted = true;
00217 break;
00218 }
00219 }
00220 if (!accepted)
00221 {
00222
00223 ignoreRemove = true;
00224 }
00225 }
00226
00227 void KRecursiveFilterProxyModelPrivate::sourceRowsRemoved(const QModelIndex &source_parent, int start, int end)
00228 {
00229 Q_Q(KRecursiveFilterProxyModel);
00230
00231 if (completeRemove)
00232 {
00233 completeRemove = false;
00234
00235 invokeRowsRemoved(source_parent, start, end);
00236
00237 }
00238
00239 if (ignoreRemove)
00240 {
00241 ignoreRemove = false;
00242 return;
00243 }
00244
00245
00246
00247
00248 refreshAscendantMapping(source_parent, true);
00249 }
00250
00251 KRecursiveFilterProxyModel::KRecursiveFilterProxyModel(QObject* parent)
00252 : QSortFilterProxyModel(parent), d_ptr(new KRecursiveFilterProxyModelPrivate(this))
00253 {
00254 setDynamicSortFilter(true);
00255 }
00256
00257 KRecursiveFilterProxyModel::~KRecursiveFilterProxyModel()
00258 {
00259
00260 }
00261
00262 bool KRecursiveFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
00263 {
00264 Q_ASSERT(sourceModel()->index(sourceRow, 0, sourceParent).isValid());
00265 QVariant da = sourceModel()->index(sourceRow, 0, sourceParent).data();
00266
00267 if (acceptRow(sourceRow, sourceParent))
00268 return true;
00269
00270 QModelIndex source_index = sourceModel()->index(sourceRow, 0, sourceParent);
00271 Q_ASSERT(source_index.isValid());
00272 bool accepted = false;
00273
00274 for (int row = 0 ; row < sourceModel()->rowCount(source_index); ++row)
00275 if (filterAcceptsRow(row, source_index))
00276 accepted = true;
00277
00278 return accepted;
00279 }
00280
00281 bool KRecursiveFilterProxyModel::acceptRow(int sourceRow, const QModelIndex& sourceParent) const
00282 {
00283 return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
00284 }
00285
00286 void KRecursiveFilterProxyModel::setSourceModel(QAbstractItemModel* model)
00287 {
00288 Q_D(KRecursiveFilterProxyModel);
00289
00290
00291 disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
00292 this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));
00293
00294 disconnect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
00295 this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)));
00296
00297 disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
00298 this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
00299
00300 disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
00301 this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
00302
00303 disconnect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
00304 this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
00305
00306 QSortFilterProxyModel::setSourceModel(model);
00307
00308
00309 disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
00310 this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex)));
00311
00312 disconnect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
00313 this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int)));
00314
00315 disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
00316 this, SLOT(_q_sourceRowsInserted(QModelIndex,int,int)));
00317
00318 disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
00319 this, SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
00320
00321 disconnect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
00322 this, SLOT(_q_sourceRowsRemoved(QModelIndex,int,int)));
00323
00324
00325 connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
00326 this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));
00327
00328 connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
00329 this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)));
00330
00331 connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
00332 this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
00333
00334 connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
00335 this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
00336
00337 connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
00338 this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
00339
00340 }
00341
00342 QModelIndexList KRecursiveFilterProxyModel::match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const
00343 {
00344 if (role < Qt::UserRole)
00345 return QSortFilterProxyModel::match(start, role, value, hits, flags);
00346
00347 QModelIndexList list;
00348 QModelIndex proxyIndex;
00349 foreach(const QModelIndex idx, sourceModel()->match(mapToSource(start), role, value, hits, flags))
00350 {
00351 proxyIndex = mapFromSource(idx);
00352 if (proxyIndex.isValid())
00353 list << proxyIndex;
00354 }
00355 return list;
00356 }
00357
00358
00359 #include "krecursivefilterproxymodel.moc"