Projects
Kontact:4.13:Git
kdelibs
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 4
View file
_service:set_version:kdelibs.spec
Changed
@@ -39,7 +39,7 @@ %global _changelog_trimtime %(date +%s -d "1 year ago") Summary: KDE Libraries -Version: 4.14.30.git20141230.42bd1a3 +Version: 4.14.30.git20150124.896b262 Release: 0%{?dist} Name: kdelibs
View file
_service:recompress:tar_scm:kdelibs-4.14.30.git20141230.42bd1a3.tar.gz/kdeui/itemviews/krecursivefilterproxymodel.cpp -> _service:recompress:tar_scm:kdelibs-4.14.30.git20150124.896b262.tar.gz/kdeui/itemviews/krecursivefilterproxymodel.cpp
Changed
@@ -39,8 +39,7 @@ KRecursiveFilterProxyModelPrivate(KRecursiveFilterProxyModel *model) : q_ptr(model), ignoreRemove(false), - completeInsert(false), - completeRemove(false) + completeInsert(false) { qRegisterMetaType<QModelIndex>( "QModelIndex" ); } @@ -108,58 +107,52 @@ void sourceRowsRemoved(const QModelIndex &source_parent, int start, int end); /** - Given that @p index does not match the filter, clear mappings in the QSortFilterProxyModel up to and excluding the - first ascendant that does match, and remake the mappings. - - If @p refreshAll is true, this method also refreshes intermediate mappings. This is significant when removing rows. + Force QSortFilterProxyModel to re-evaluate whether to hide or show index and its parents. */ - void refreshAscendantMapping(const QModelIndex &index, bool refreshAll = false); + void refreshAscendantMapping(const QModelIndex &index); + + QModelIndex lastFilteredOutAscendant(const QModelIndex &index); bool ignoreRemove; bool completeInsert; - bool completeRemove; + + QModelIndex lastHiddenAscendantForInsert; }; void KRecursiveFilterProxyModelPrivate::sourceDataChanged(const QModelIndex &source_top_left, const QModelIndex &source_bottom_right) { - Q_Q(KRecursiveFilterProxyModel); - QModelIndex source_parent = source_top_left.parent(); + Q_ASSERT(source_bottom_right.parent() == source_parent); // don't know how to handle different parents in this code... - if (!source_parent.isValid() || q->acceptRow(source_parent.row(), source_parent.parent())) - { - invokeDataChanged(source_top_left, source_bottom_right); - return; - } - - bool requireRow = false; - for (int row = source_top_left.row(); row <= source_bottom_right.row(); ++row) - if (q->filterAcceptsRow(row, source_parent)) - { - requireRow = true; - break; - } + // Tell the world. + invokeDataChanged(source_top_left, source_bottom_right); - if (!requireRow) // None of the changed rows are now required in the model. - return; + // We can't find out if the change really matters to us or not, for a lack of a dataAboutToBeChanged signal (or a cache). + // TODO: add a set of roles that we care for, so we can at least ignore the rest. - refreshAscendantMapping(source_parent); + // Even if we knew the visibility was just toggled, we also can't find out what + // was the last filtered out ascendant (on show, like sourceRowsAboutToBeInserted does) + // or the last to-be-filtered-out ascendant (on hide, like sourceRowsRemoved does) + // So we have to refresh all parents. + QModelIndex sourceParent = source_parent; + while(sourceParent.isValid()) + { + invokeDataChanged(sourceParent, sourceParent); + sourceParent = sourceParent.parent(); + } } -void KRecursiveFilterProxyModelPrivate::refreshAscendantMapping(const QModelIndex &index, bool refreshAll) +QModelIndex KRecursiveFilterProxyModelPrivate::lastFilteredOutAscendant(const QModelIndex &idx) { - Q_Q(KRecursiveFilterProxyModel); - Q_ASSERT(index.isValid()); - - QModelIndex sourceAscendant = index; - // We got a matching descendant, so find the right place to insert the row. - // We need to tell the QSortFilterProxyModel that the first child between an existing row in the model - // has changed data so that it will get a mapping. - while(sourceAscendant.isValid()) - { - invokeDataChanged(sourceAscendant, sourceAscendant); - sourceAscendant = sourceAscendant.parent(); - } + Q_Q(KRecursiveFilterProxyModel); + QModelIndex last = idx; + QModelIndex index = idx.parent(); + while(index.isValid() && !q->filterAcceptsRow(index.row(), index.parent())) + { + last = index; + index = index.parent(); + } + return last; } void KRecursiveFilterProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end) @@ -168,8 +161,13 @@ if (!source_parent.isValid() || q->filterAcceptsRow(source_parent.row(), source_parent.parent())) { + // If the parent is already in the model (directly or indirectly), we can just pass on the signal. invokeRowsAboutToBeInserted(source_parent, start, end); completeInsert = true; + } else { + // OK, so parent is not in the model. + // Maybe the grand parent neither.. Go up until the first one that is. + lastHiddenAscendantForInsert = lastFilteredOutAscendant(source_parent); } } @@ -179,9 +177,9 @@ if (completeInsert) { + // If the parent is already in the model, we can just pass on the signal. completeInsert = false; invokeRowsInserted(source_parent, start, end); - // If the parent is already in the model, we can just pass on the signal. return; } @@ -197,24 +195,18 @@ if (!requireRow) { - // The row doesn't have descendants that match the filter. Filter it out. + // The new rows doesn't have any descendants that match the filter. Filter them out. return; } - refreshAscendantMapping(source_parent); + // Make QSFPM realize that lastHiddenAscendantForInsert should be shown now + invokeDataChanged(lastHiddenAscendantForInsert, lastHiddenAscendantForInsert); } void KRecursiveFilterProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end) { Q_Q(KRecursiveFilterProxyModel); - if (source_parent.isValid() && q->filterAcceptsRow(source_parent.row(), source_parent.parent())) - { - invokeRowsAboutToBeRemoved(source_parent, start, end); - completeRemove = true; - return; - } - bool accepted = false; for (int row = start; row <= end; ++row) { @@ -230,19 +222,13 @@ ignoreRemove = true; return; } - completeRemove = true; + invokeRowsAboutToBeRemoved(source_parent, start, end); } void KRecursiveFilterProxyModelPrivate::sourceRowsRemoved(const QModelIndex &source_parent, int start, int end) { - if (completeRemove) - { - completeRemove = false; - // Source parent is already in the model. - invokeRowsRemoved(source_parent, start, end); - // fall through. After removing rows, we need to refresh things so that intermediates will be removed too if necessary. - } + Q_Q(KRecursiveFilterProxyModel); if (ignoreRemove) { @@ -250,11 +236,25 @@ return; } - // Refresh intermediate rows too. - // This is needed because QSFPM only invalidates the mapping for the - // index range given to dataChanged, not its children. - if (source_parent.isValid()) - refreshAscendantMapping(source_parent, true); + invokeRowsRemoved(source_parent, start, end); + + // Find out if removing this visible row means that some ascendant + // row can now be hidden. + // We go up until we find a row that should still be visible + // and then make QSFPM re-evaluate the last one we saw before that, to hide it. + + QModelIndex toHide; + QModelIndex sourceAscendant = source_parent; + while(sourceAscendant.isValid()) + { + if (q->filterAcceptsRow(sourceAscendant.row(), sourceAscendant.parent())) { + break; + } + toHide = sourceAscendant; + sourceAscendant = sourceAscendant.parent();
View file
_service:recompress:tar_scm:kdelibs-4.14.30.git20141230.42bd1a3.tar.gz/kdeui/tests/krecursivefilterproxymodeltest.cpp -> _service:recompress:tar_scm:kdelibs-4.14.30.git20150124.896b262.tar.gz/kdeui/tests/krecursivefilterproxymodeltest.cpp
Changed
@@ -23,12 +23,16 @@ #include <krecursivefilterproxymodel.h> #include <QStandardItemModel> +Q_DECLARE_METATYPE(QModelIndex) + class ModelSignalSpy : public QObject { Q_OBJECT public: explicit ModelSignalSpy(QAbstractItemModel &model) { connect(&model, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(onRowsInserted(QModelIndex,int,int))); connect(&model, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(onRowsRemoved(QModelIndex,int,int))); + connect(&model, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)), this, SLOT(onRowsAboutToBeInserted(QModelIndex,int,int))); + connect(&model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), this, SLOT(onRowsAboutToBeRemoved(QModelIndex,int,int))); connect(&model, SIGNAL(rowsMoved(QModelIndex, int, int, QModelIndex, int)), this, SLOT(onRowsMoved(QModelIndex,int,int, QModelIndex, int))); connect(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(onDataChanged(QModelIndex,QModelIndex))); connect(&model, SIGNAL(layoutChanged()), this, SLOT(onLayoutChanged())); @@ -36,28 +40,25 @@ } QStringList mSignals; - QModelIndex parent; - int start; - int end; - -public Q_SLOTS: - void onRowsInserted(QModelIndex p, int s, int e) { - mSignals << QLatin1String("rowsInserted"); - parent = p; - start = s; - end = e; - } - void onRowsRemoved(QModelIndex p, int s, int e) { - mSignals << QLatin1String("rowsRemoved"); - parent = p; - start = s; - end = e; + +private Q_SLOTS: + void onRowsInserted(QModelIndex p, int start, int end) { + mSignals << QLatin1String("rowsInserted(") + textForRowSpy(p, start, end) + ')'; + } + void onRowsRemoved(QModelIndex p, int start, int end) { + mSignals << QLatin1String("rowsRemoved(") + textForRowSpy(p, start, end) + ')'; + } + void onRowsAboutToBeInserted(QModelIndex p, int start, int end) { + mSignals << QLatin1String("rowsAboutToBeInserted(") + textForRowSpy(p, start, end) + ')'; + } + void onRowsAboutToBeRemoved(QModelIndex p, int start, int end) { + mSignals << QLatin1String("rowsAboutToBeRemoved(") + textForRowSpy(p, start, end) + ')'; } void onRowsMoved(QModelIndex,int,int,QModelIndex,int) { mSignals << QLatin1String("rowsMoved"); } - void onDataChanged(QModelIndex,QModelIndex) { - mSignals << QLatin1String("dataChanged"); + void onDataChanged(const QModelIndex &from, const QModelIndex& ) { + mSignals << QString("dataChanged(%1)").arg(from.data().toString()); } void onLayoutChanged() { mSignals << QLatin1String("layoutChanged"); @@ -65,12 +66,28 @@ void onModelReset() { mSignals << QLatin1String("modelReset"); } +private: + QString textForRowSpy(const QModelIndex &parent, int start, int end) + { + QString txt = parent.data().toString(); + if (!txt.isEmpty()) + txt += QLatin1Char('.'); + txt += QString::number(start+1); + if (start != end) + txt += QLatin1Char('-') + QString::number(end+1); + return txt; + } }; class TestModel : public KRecursiveFilterProxyModel { Q_OBJECT public: + TestModel(QAbstractItemModel *sourceModel) + : KRecursiveFilterProxyModel() { + setSourceModel(sourceModel); + } + virtual bool acceptRow(int sourceRow, const QModelIndex &sourceParent) const { // qDebug() << sourceModel()->index(sourceRow, 0, sourceParent).data().toString() << sourceModel()->index(sourceRow, 0, sourceParent).data(Qt::UserRole+1).toBool(); @@ -78,142 +95,511 @@ } }; -static QModelIndex getIndex(char *string, const QAbstractItemModel &model) +// Represents this tree +// - A +// - - B +// - - - C +// - - - D +// - - E +// as a single string, englobing children in brackets, like this: +// [A[B[C D] E]] +// In addition, items that match the filtering (data(UserRole+1) == true) have a * after their value. +static QString treeAsString(const QAbstractItemModel &model, const QModelIndex &parent = QModelIndex()) +{ + QString ret; + const int rowCount = model.rowCount(parent); + if (rowCount > 0) { + ret += QLatin1Char('['); + for (int row = 0 ; row < rowCount; ++row) { + if (row > 0) { + ret += ' '; + } + const QModelIndex child = model.index(row, 0, parent); + ret += child.data().toString(); + if (child.data(Qt::UserRole+1).toBool()) + ret += QLatin1Char('*'); + ret += treeAsString(model, child); + } + ret += QLatin1Char(']'); + } + return ret; +} + +// Fill a tree model based on a string representation (see treeAsString) +static void fillModel(QStandardItemModel &model, const QString &str) { - QModelIndexList list = model.match(model.index(0, 0), Qt::DisplayRole, QString::fromLatin1(string), 1, Qt::MatchRecursive); - if (list.isEmpty()) { - return QModelIndex(); + QCOMPARE(str.count('['), str.count(']')); + QStandardItem *item = 0; + QString data; + for ( int i = 0 ; i < str.length() ; ++i ) { + const QChar ch = str.at(i); + if ((ch == '[' || ch == ']' || ch == ' ') && !data.isEmpty()) { + if (data.endsWith('*')) { + item->setData(true); + data.chop(1); + } + item->setText(data); + data.clear(); + } + if (ch == '[') { + // Create new child + QStandardItem *child = new QStandardItem; + if (item) + item->appendRow(child); + else + model.appendRow(child); + item = child; + } else if (ch == ']') { + // Go up to parent + item = item->parent(); + } else if (ch == ' ') { + // Create new sibling + QStandardItem *child = new QStandardItem; + QStandardItem *parent = item->parent(); + if (parent) + parent->appendRow(child); + else + model.appendRow(child); + item = child; + } else { + data += ch; + } } - return list.first(); } class KRecursiveFilterProxyModelTest : public QObject { Q_OBJECT private: - private slots: - // Requires the acceptRow fix in sourceDataChanged to pass + void testInitialFiltering_data() + { + QTest::addColumn<QString>("sourceStr"); + QTest::addColumn<QString>("proxyStr"); + + QTest::newRow("empty") << "[]" << ""; + QTest::newRow("no") << "[1]" << ""; + QTest::newRow("yes") << "[1*]" << "[1*]"; + QTest::newRow("second") << "[1 2*]" << "[2*]"; + QTest::newRow("child_yes") << "[1 2[2.1*]]" << "[2[2.1*]]"; + QTest::newRow("grandchild_yes") << "[1 2[2.1[2.1.1*]]]" << "[2[2.1[2.1.1*]]]"; + // 1, 3.1 and 4.2.1 match, so their parents are in the model + QTest::newRow("more") << "[1* 2[2.1] 3[3.1*] 4[4.1 4.2[4.2.1*]]]" << "[1* 3[3.1*] 4[4.2[4.2.1*]]]"; + } + + void testInitialFiltering() + { + QFETCH(QString, sourceStr); + QFETCH(QString, proxyStr); + + QStandardItemModel model; + fillModel(model, sourceStr);
View file
_service:set_version:kdelibs.dsc
Changed
@@ -2,7 +2,7 @@ Source: kde4libs Binary: libkdecore5, libkdeui5, libkpty4, libkdesu5, libkjsapi4, libkjsembed4, libkio5, libkntlm4, libsolid4, libkde3support4, libkfile4, libknewstuff2-4, libknewstuff3-4, libkparts4, libkutils4, libthreadweaver4, libkhtml5, libkimproxy4, libkmediaplayer4, libktexteditor4, libknotifyconfig4, libkdnssd4, libkrosscore4, libkrossui4, libnepomuk4, libnepomukutils4, libnepomukquery4a, libplasma3, libkunitconversion4, libkdewebkit5, libkcmutils4, libkemoticons4, libkidletime4, libkprintutils4, libkdeclarative5, kdelibs-bin, kdelibs5-plugins, kdelibs5-data, kdoctools, kdelibs5-dev, kdelibs5-dbg Architecture: any all -Version: 4.14.30.git20141230.42bd1a3 +Version: 4.14.30.git20150124.896b262 Maintainer: Kubuntu Developers <kubuntu-devel@lists.ubuntu.com> Uploaders: Sune Vuorela <sune@debian.org>, Fathi Boudra <fabo@debian.org>, Modestas Vainius <modax@debian.org>, George Kiagiadakis <kiagiadakis.george@gmail.com> Homepage: http://www.kde.org/
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.