diff options
| author | Frank Reininghaus <[email protected]> | 2013-08-15 00:15:51 +0200 |
|---|---|---|
| committer | Frank Reininghaus <[email protected]> | 2013-08-15 00:15:51 +0200 |
| commit | 6bfa0ccfc701df5af5f043fce3168b3840858212 (patch) | |
| tree | a978d69d1afbd237cf5a3f8e8e117fbbab71adb2 /src | |
| parent | 68520f55f0b6b2fc450f646477bf3c535324aa2b (diff) | |
| parent | 7c99a9c2ad4455c65a218c53dfa7f6376f389b66 (diff) | |
Merge remote-tracking branch 'origin/KDE/4.11'
Diffstat (limited to 'src')
| -rw-r--r-- | src/kitemviews/kfileitemmodel.cpp | 53 | ||||
| -rw-r--r-- | src/kitemviews/kfileitemmodelrolesupdater.cpp | 16 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistview.cpp | 6 | ||||
| -rw-r--r-- | src/kitemviews/kstandarditemlistwidget.cpp | 38 | ||||
| -rw-r--r-- | src/kitemviews/kstandarditemlistwidget.h | 2 | ||||
| -rw-r--r-- | src/tests/kfileitemmodeltest.cpp | 25 |
6 files changed, 98 insertions, 42 deletions
diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index c7e1c8600..eb7b16461 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -192,8 +192,30 @@ bool KFileItemModel::setData(int index, const QHash<QByteArray, QVariant>& value emit itemsChanged(KItemRangeList() << KItemRange(index, 1), changedRoles); - if (changedRoles.contains(sortRole())) { - m_resortAllItemsTimer->start(); + // Trigger a resorting if the item's correct position has changed. Note + // that this can happen even if the sort role has not changed at all + // because the file name can be used as a fallback. + if (changedRoles.contains(sortRole()) || changedRoles.contains(roleForType(NameRole))) { + // Compare the changed item with its neighbors to see + // if an expensive resorting is needed at all. + const ItemData* changedItem = m_itemData.at(index); + const ItemData* previousItem = (index == 0) ? 0 : m_itemData.at(index - 1); + const ItemData* nextItem = (index == m_itemData.count() - 1) ? 0 : m_itemData.at(index + 1); + + if ((previousItem && lessThan(changedItem, previousItem)) + || (nextItem && lessThan(nextItem, changedItem))) { + m_resortAllItemsTimer->start(); + } else if (groupedSorting() && changedRoles.contains(sortRole())) { + // The position is still correct, but the groups might have changed + // if the changed item is either the first or the last item in a + // group. + // In principle, we could try to find out if the item really is the + // first or last one in its group and then update the groups + // (possibly with a delayed timer to make sure that we don't + // re-calculate the groups very often if items are updated one by + // one), but starting m_resortAllItemsTimer is easier. + m_resortAllItemsTimer->start(); + } } return true; @@ -1299,25 +1321,20 @@ QHash<QByteArray, QVariant> KFileItemModel::retrieveData(const KFileItem& item, data.insert(sharedValue("url"), item.url()); const bool isDir = item.isDir(); - if (m_requestRole[IsDirRole]) { - data.insert(sharedValue("isDir"), isDir); + if (m_requestRole[IsDirRole] && isDir) { + data.insert(sharedValue("isDir"), true); } - if (m_requestRole[IsLinkRole]) { - const bool isLink = item.isLink(); - data.insert(sharedValue("isLink"), isLink); + if (m_requestRole[IsLinkRole] && item.isLink()) { + data.insert(sharedValue("isLink"), true); } if (m_requestRole[NameRole]) { data.insert(sharedValue("text"), item.text()); } - if (m_requestRole[SizeRole]) { - if (isDir) { - data.insert(sharedValue("size"), QVariant()); - } else { - data.insert(sharedValue("size"), item.size()); - } + if (m_requestRole[SizeRole] && !isDir) { + data.insert(sharedValue("size"), item.size()); } if (m_requestRole[DateRole]) { @@ -1371,17 +1388,15 @@ QHash<QByteArray, QVariant> KFileItemModel::retrieveData(const KFileItem& item, data.insert(sharedValue("path"), path); } - if (m_requestRole[IsExpandableRole]) { - data.insert(sharedValue("isExpandable"), item.isDir()); + if (m_requestRole[IsExpandableRole] && isDir) { + data.insert(sharedValue("isExpandable"), true); } if (m_requestRole[ExpandedParentsCountRole]) { - int level = 0; if (parent) { - level = parent->values["expandedParentsCount"].toInt() + 1; + const int level = parent->values["expandedParentsCount"].toInt() + 1; + data.insert(sharedValue("expandedParentsCount"), level); } - - data.insert(sharedValue("expandedParentsCount"), level); } if (item.isMimeTypeKnown()) { diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp index 698a6c5f0..e9b69566d 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.cpp +++ b/src/kitemviews/kfileitemmodelrolesupdater.cpp @@ -570,6 +570,22 @@ void KFileItemModelRolesUpdater::slotGotPreview(const KFileItem& item, const QPi } QHash<QByteArray, QVariant> data = rolesData(item); + + const QStringList overlays = data["iconOverlays"].toStringList(); + // Strangely KFileItem::overlays() returns empty string-values, so + // we need to check first whether an overlay must be drawn at all. + // It is more efficient to do it here, as KIconLoader::drawOverlays() + // assumes that an overlay will be drawn and has some additional + // setup time. + foreach (const QString& overlay, overlays) { + if (!overlay.isEmpty()) { + // There is at least one overlay, draw all overlays above m_pixmap + // and cancel the check + KIconLoader::global()->drawOverlays(overlays, scaledPixmap, KIconLoader::Desktop); + break; + } + } + data.insert("iconPixmap", scaledPixmap); disconnect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)), diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index 80a4ba7e3..d8edcfc50 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -1244,8 +1244,10 @@ void KItemListView::slotGroupedSortingChanged(bool current) if (m_grouped) { updateGroupHeaderHeight(); } else { - // Clear all visible headers - QMutableHashIterator<KItemListWidget*, KItemListGroupHeader*> it (m_visibleGroups); + // Clear all visible headers. Note that the QHashIterator takes a copy of + // m_visibleGroups. Therefore, it remains valid even if items are removed + // from m_visibleGroups in recycleGroupHeaderForWidget(). + QHashIterator<KItemListWidget*, KItemListGroupHeader*> it(m_visibleGroups); while (it.hasNext()) { it.next(); recycleGroupHeaderForWidget(it.key()); diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index b429211b8..2a89004c6 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -791,7 +791,6 @@ void KStandardItemListWidget::updateExpansionArea() { if (m_supportsItemExpanding) { const QHash<QByteArray, QVariant> values = data(); - Q_ASSERT(values.contains("expandedParentsCount")); const int expandedParentsCount = values.value("expandedParentsCount", 0).toInt(); if (expandedParentsCount >= 0) { const qreal widgetHeight = size().height(); @@ -839,29 +838,14 @@ void KStandardItemListWidget::updatePixmapCache() // use a generic icon as fallback iconName = QLatin1String("unknown"); } - m_pixmap = pixmapForIcon(iconName, maxIconHeight); + const QStringList overlays = values["iconOverlays"].toStringList(); + m_pixmap = pixmapForIcon(iconName, overlays, maxIconHeight); } else if (m_pixmap.width() != maxIconWidth || m_pixmap.height() != maxIconHeight) { // A custom pixmap has been applied. Assure that the pixmap // is scaled to the maximum available size. KPixmapModifier::scale(m_pixmap, QSize(maxIconWidth, maxIconHeight)); } - const QStringList overlays = values["iconOverlays"].toStringList(); - - // Strangely KFileItem::overlays() returns empty string-values, so - // we need to check first whether an overlay must be drawn at all. - // It is more efficient to do it here, as KIconLoader::drawOverlays() - // assumes that an overlay will be drawn and has some additional - // setup time. - foreach (const QString& overlay, overlays) { - if (!overlay.isEmpty()) { - // There is at least one overlay, draw all overlays above m_pixmap - // and cancel the check - KIconLoader::global()->drawOverlays(overlays, m_pixmap, KIconLoader::Desktop); - break; - } - } - if (m_isCut) { KIconEffect* effect = KIconLoader::global()->iconEffect(); m_pixmap = effect->apply(m_pixmap, KIconLoader::Desktop, KIconLoader::DisabledState); @@ -1323,9 +1307,9 @@ void KStandardItemListWidget::closeRoleEditor() m_roleEditor = 0; } -QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, int size) +QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, const QStringList& overlays, int size) { - const QString key = "KStandardItemListWidget:" % name % ":" % QString::number(size); + const QString key = "KStandardItemListWidget:" % name % ":" % overlays.join(":") % ":" % QString::number(size); QPixmap pixmap; if (!QPixmapCache::find(key, pixmap)) { @@ -1355,6 +1339,20 @@ QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, int size) KPixmapModifier::scale(pixmap, QSize(size, size)); } + // Strangely KFileItem::overlays() returns empty string-values, so + // we need to check first whether an overlay must be drawn at all. + // It is more efficient to do it here, as KIconLoader::drawOverlays() + // assumes that an overlay will be drawn and has some additional + // setup time. + foreach (const QString& overlay, overlays) { + if (!overlay.isEmpty()) { + // There is at least one overlay, draw all overlays above m_pixmap + // and cancel the check + KIconLoader::global()->drawOverlays(overlays, pixmap, KIconLoader::Desktop); + break; + } + } + QPixmapCache::insert(key, pixmap); } diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h index ecf3a3b60..4bf6116fd 100644 --- a/src/kitemviews/kstandarditemlistwidget.h +++ b/src/kitemviews/kstandarditemlistwidget.h @@ -186,7 +186,7 @@ private: */ void closeRoleEditor(); - static QPixmap pixmapForIcon(const QString& name, int size); + static QPixmap pixmapForIcon(const QString& name, const QStringList& overlays, int size); /** * @return Preferred size of the rating-image based on the given diff --git a/src/tests/kfileitemmodeltest.cpp b/src/tests/kfileitemmodeltest.cpp index 6d5d4b77c..e55e3eb33 100644 --- a/src/tests/kfileitemmodeltest.cpp +++ b/src/tests/kfileitemmodeltest.cpp @@ -71,6 +71,7 @@ private slots: void testSetDataWithModifiedSortRole_data(); void testSetDataWithModifiedSortRole(); void testChangeSortRole(); + void testResortAfterChangingName(); void testModelConsistencyWhenInsertingItems(); void testItemRangeConsistencyWhenInsertingItems(); void testExpandItems(); @@ -369,6 +370,30 @@ void KFileItemModelTest::testChangeSortRole() QVERIFY(ok1 || ok2); } +void KFileItemModelTest::testResortAfterChangingName() +{ + // We sort by size in a directory where all files have the same size. + // Therefore, the files are sorted by their names. + m_model->setSortRole("size"); + + QStringList files; + files << "a.txt" << "b.txt" << "c.txt"; + m_testDir->createFiles(files); + + m_model->loadDirectory(m_testDir->url()); + QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout)); + QCOMPARE(itemsInModel(), QStringList() << "a.txt" << "b.txt" << "c.txt"); + + // We rename a.txt to d.txt. Even though the size has not changed at all, + // the model must re-sort the items. + QHash<QByteArray, QVariant> data; + data.insert("text", "d.txt"); + m_model->setData(0, data); + + QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsMoved(KItemRange,QList<int>)), DefaultTimeout)); + QCOMPARE(itemsInModel(), QStringList() << "b.txt" << "c.txt" << "d.txt"); +} + void KFileItemModelTest::testModelConsistencyWhenInsertingItems() { //QSKIP("Temporary disabled", SkipSingle); |
