From b2cb38214ec403dfc68e5231e0006fe59833515a Mon Sep 17 00:00:00 2001 From: Peter Penz Date: Fri, 23 Dec 2011 23:05:08 +0100 Subject: [PATCH] Introduce "isExpandable" role The role is used to determine whether a directory can be expanded at all. This is e.g. not the case if a directory has 0 items or the target-URL is different from the item-URL. The expansion toggle will get hidden if a directory is not expandable. CCBUG: 288521 --- src/kitemviews/kfileitemlistview.cpp | 1 + src/kitemviews/kfileitemlistwidget.cpp | 8 ++--- src/kitemviews/kfileitemlistwidget.h | 2 +- src/kitemviews/kfileitemmodel.cpp | 14 +++++--- src/kitemviews/kfileitemmodel.h | 1 + src/kitemviews/kfileitemmodelrolesupdater.cpp | 33 +++++++++++++------ src/kitemviews/kfileitemmodelrolesupdater.h | 2 +- src/tests/kfileitemmodeltest.cpp | 2 +- 8 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/kitemviews/kfileitemlistview.cpp b/src/kitemviews/kfileitemlistview.cpp index 89fec9d0f..86db28d3d 100644 --- a/src/kitemviews/kfileitemlistview.cpp +++ b/src/kitemviews/kfileitemlistview.cpp @@ -586,6 +586,7 @@ void KFileItemListView::applyRolesToModel() roles.insert("isDir"); if (m_itemLayout == DetailsLayout) { roles.insert("isExpanded"); + roles.insert("isExpandable"); roles.insert("expansionLevel"); } diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp index 7a36214b6..d3e792ea0 100644 --- a/src/kitemviews/kfileitemlistwidget.cpp +++ b/src/kitemviews/kfileitemlistwidget.cpp @@ -44,7 +44,7 @@ KFileItemListWidget::KFileItemListWidget(QGraphicsItem* parent) : KItemListWidget(parent), m_isCut(false), m_isHidden(false), - m_isDir(false), + m_isExpandable(false), m_dirtyLayout(true), m_dirtyContent(true), m_dirtyContentRoles(), @@ -95,7 +95,7 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte KItemListWidget::paint(painter, option, widget); // Draw expansion toggle '>' or 'V' - if (m_isDir && !m_expansionArea.isEmpty()) { + if (m_isExpandable) { QStyleOption arrowOption; arrowOption.rect = m_expansionArea.toRect(); const QStyle::PrimitiveElement arrow = data()["isExpanded"].toBool() @@ -169,7 +169,7 @@ QRectF KFileItemListWidget::textRect() const QRectF KFileItemListWidget::expansionToggleRect() const { const_cast(this)->triggerCacheRefreshing(); - return m_isDir ? m_expansionArea : QRectF(); + return m_isExpandable ? m_expansionArea : QRectF(); } QRectF KFileItemListWidget::selectionToggleRect() const @@ -405,7 +405,7 @@ void KFileItemListWidget::triggerCacheRefreshing() refreshCache(); const QHash values = data(); - m_isDir = values["isDir"].toBool(); + m_isExpandable = values["isExpandable"].toBool(); m_isHidden = values["name"].toString().startsWith(QLatin1Char('.')); updateExpansionArea(); diff --git a/src/kitemviews/kfileitemlistwidget.h b/src/kitemviews/kfileitemlistwidget.h index 8f7397b75..91f00fe73 100644 --- a/src/kitemviews/kfileitemlistwidget.h +++ b/src/kitemviews/kfileitemlistwidget.h @@ -128,7 +128,7 @@ private: private: bool m_isCut; bool m_isHidden; - bool m_isDir; + bool m_isExpandable; bool m_dirtyLayout; bool m_dirtyContent; diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index b40865f8f..baf168ddf 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -358,8 +358,8 @@ void KFileItemModel::setRoles(const QSet& roles) m_roles = roles; if (count() > 0) { - const bool supportedExpanding = m_requestRole[IsExpandedRole] && m_requestRole[ExpansionLevelRole]; - const bool willSupportExpanding = roles.contains("isExpanded") && roles.contains("expansionLevel"); + const bool supportedExpanding = m_requestRole[ExpansionLevelRole]; + const bool willSupportExpanding = roles.contains("expansionLevel"); if (supportedExpanding && !willSupportExpanding) { // No expanding is supported anymore. Take care to delete all items that have an expansion level // that is not 0 (and hence are part of an expanded item). @@ -394,7 +394,7 @@ QSet KFileItemModel::roles() const bool KFileItemModel::setExpanded(int index, bool expanded) { - if (isExpanded(index) == expanded || index < 0 || index >= count()) { + if (!isExpandable(index) || isExpanded(index) == expanded) { return false; } @@ -445,7 +445,7 @@ bool KFileItemModel::isExpanded(int index) const bool KFileItemModel::isExpandable(int index) const { if (index >= 0 && index < count()) { - return m_itemData.at(index)->item.isDir(); + return m_itemData.at(index)->values.value("isExpandable").toBool(); } return false; } @@ -462,7 +462,6 @@ void KFileItemModel::restoreExpandedUrls(const QSet& urls) void KFileItemModel::setExpanded(const QSet& urls) { - const KDirLister* dirLister = m_dirLister.data(); if (!dirLister) { return; @@ -1097,6 +1096,7 @@ KFileItemModel::Role KFileItemModel::roleIndex(const QByteArray& role) const rolesHash.insert("rating", RatingRole); rolesHash.insert("isDir", IsDirRole); rolesHash.insert("isExpanded", IsExpandedRole); + rolesHash.insert("isExpandable", IsExpandableRole); rolesHash.insert("expansionLevel", ExpansionLevelRole); } return rolesHash.value(role, NoRole); @@ -1169,6 +1169,10 @@ QHash KFileItemModel::retrieveData(const KFileItem& item) data.insert("isExpanded", false); } + if (m_requestRole[IsExpandableRole]) { + data.insert("isExpandable", item.isDir() && item.url() == item.targetUrl()); + } + if (m_requestRole[ExpansionLevelRole]) { if (m_rootExpansionLevel == UninitializedRootExpansionLevel && m_dirLister.data()) { const KUrl rootUrl = m_dirLister.data()->url(); diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h index 2992de065..07634655c 100644 --- a/src/kitemviews/kfileitemmodel.h +++ b/src/kitemviews/kfileitemmodel.h @@ -199,6 +199,7 @@ private: RatingRole, IsDirRole, IsExpandedRole, + IsExpandableRole, ExpansionLevelRole, RolesCount // Mandatory last entry }; diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp index 671352cac..0ecc0e973 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.cpp +++ b/src/kitemviews/kfileitemmodelrolesupdater.cpp @@ -356,7 +356,8 @@ void KFileItemModelRolesUpdater::resolvePendingRoles() const bool hasSlowRoles = m_previewShown || m_roles.contains("size") - || m_roles.contains("type"); + || m_roles.contains("type") + || m_roles.contains("isExpandable"); const ResolveHint resolveHint = hasSlowRoles ? ResolveFast : ResolveAll; // Resolving the MIME type can be expensive. Assure that not more than MaxBlockTimeout ms are @@ -715,13 +716,19 @@ QHash KFileItemModelRolesUpdater::rolesData(const KFileIte { QHash data; - if (m_roles.contains("size")) { - if (item.isDir() && item.isLocalFile()) { - const QString path = item.localPath(); - const int count = subDirectoriesCount(path); - if (count >= 0) { + const bool getSizeRole = m_roles.contains("size"); + const bool getIsExpandableRole = m_roles.contains("isExpandable"); + + if ((getSizeRole || getIsExpandableRole) && item.isDir() && item.isLocalFile()) { + const QString path = item.localPath(); + const int count = subDirectoriesCount(path); + if (count >= 0) { + if (getSizeRole) { data.insert("size", KIO::filesize_t(count)); } + if (getIsExpandableRole) { + data.insert("isExpandable", count > 0); + } } } @@ -770,11 +777,17 @@ KFileItemList KFileItemModelRolesUpdater::sortedItems(const QSet& ite return itemList; } -int KFileItemModelRolesUpdater::subDirectoriesCount(const QString& path) +int KFileItemModelRolesUpdater::subDirectoriesCount(const QString& path) const { + const bool countHiddenFiles = m_model->showHiddenFiles(); + #ifdef Q_WS_WIN QDir dir(path); - return dir.entryList(QDir::AllEntries|QDir::NoDotAndDotDot|QDir::System).count(); + QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::System; + if (countHiddenFiles) { + filters |= QDir::Hidden; + } + return dir.entryList(filters).count(); #else // Taken from kdelibs/kio/kio/kdirmodel.cpp // Copyright (C) 2006 David Faure @@ -786,8 +799,8 @@ int KFileItemModelRolesUpdater::subDirectoriesCount(const QString& path) struct dirent *dirEntry = 0; while ((dirEntry = ::readdir(dir))) { // krazy:exclude=syscalls if (dirEntry->d_name[0] == '.') { - if (dirEntry->d_name[1] == '\0') { - // Skip "." + if (dirEntry->d_name[1] == '\0' || !countHiddenFiles) { + // Skip "." or hidden files continue; } if (dirEntry->d_name[1] == '.' && dirEntry->d_name[2] == '\0') { diff --git a/src/kitemviews/kfileitemmodelrolesupdater.h b/src/kitemviews/kfileitemmodelrolesupdater.h index 065f069c8..b7d8ceab0 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.h +++ b/src/kitemviews/kfileitemmodelrolesupdater.h @@ -157,7 +157,7 @@ private: KFileItemList sortedItems(const QSet& items) const; - static int subDirectoriesCount(const QString& path); + int subDirectoriesCount(const QString& path) const; private: // Property for setPaused()/isPaused(). diff --git a/src/tests/kfileitemmodeltest.cpp b/src/tests/kfileitemmodeltest.cpp index ac0c59952..86a2c04a4 100644 --- a/src/tests/kfileitemmodeltest.cpp +++ b/src/tests/kfileitemmodeltest.cpp @@ -372,7 +372,7 @@ void KFileItemModelTest::testExpandItems() // yields the correct result for "a/a/1" and "a/a-1/", whis is non-trivial because they share the // first three characters. QSet modelRoles = m_model->roles(); - modelRoles << "isExpanded" << "expansionLevel"; + modelRoles << "isExpanded" << "isExpandable" << "expansionLevel"; m_model->setRoles(modelRoles); QStringList files; -- 2.47.3