┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/kitemviews
diff options
context:
space:
mode:
Diffstat (limited to 'src/kitemviews')
-rw-r--r--src/kitemviews/kfileitemlistview.cpp14
-rw-r--r--src/kitemviews/kfileitemlistview.h1
-rw-r--r--src/kitemviews/kfileitemmodel.cpp78
-rw-r--r--src/kitemviews/kfileitemmodel.h3
-rw-r--r--src/kitemviews/kfileitemmodelrolesupdater.cpp8
-rw-r--r--src/kitemviews/kitemlistview.cpp18
-rw-r--r--src/kitemviews/kitemlistview.h1
-rw-r--r--src/kitemviews/kitemmodelbase.cpp41
-rw-r--r--src/kitemviews/kitemmodelbase.h9
9 files changed, 156 insertions, 17 deletions
diff --git a/src/kitemviews/kfileitemlistview.cpp b/src/kitemviews/kfileitemlistview.cpp
index 3a02d537d..585a972a6 100644
--- a/src/kitemviews/kfileitemlistview.cpp
+++ b/src/kitemviews/kfileitemlistview.cpp
@@ -354,6 +354,15 @@ void KFileItemListView::slotSortRoleChanged(const QByteArray &current, const QBy
KStandardItemListView::slotSortRoleChanged(current, previous);
}
+void KFileItemListView::slotGroupRoleChanged(const QByteArray &current, const QByteArray &previous)
+{
+ if (!visibleRoles().contains(current)) {
+ applyRolesToModel();
+ }
+
+ KItemListView::slotGroupRoleChanged(current, previous);
+}
+
void KFileItemListView::triggerVisibleIndexRangeUpdate()
{
if (!model()) {
@@ -441,6 +450,11 @@ void KFileItemListView::applyRolesToModel()
// Assure that the role that is used for sorting will be determined
roles.insert(fileItemModel->sortRole());
+ const QByteArray rawGroupRole = fileItemModel->rawGroupRole();
+ if (!rawGroupRole.isEmpty()) {
+ roles.insert(rawGroupRole);
+ }
+
fileItemModel->setRoles(roles);
m_modelRolesUpdater->setRoles(roles);
}
diff --git a/src/kitemviews/kfileitemlistview.h b/src/kitemviews/kfileitemlistview.h
index eae00f1f0..203daca09 100644
--- a/src/kitemviews/kfileitemlistview.h
+++ b/src/kitemviews/kfileitemlistview.h
@@ -93,6 +93,7 @@ protected:
protected Q_SLOTS:
void slotItemsRemoved(const KItemRangeList &itemRanges) override;
void slotSortRoleChanged(const QByteArray &current, const QByteArray &previous) override;
+ void slotGroupRoleChanged(const QByteArray &current, const QByteArray &previous) override;
private Q_SLOTS:
void triggerVisibleIndexRangeUpdate();
diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp
index ba33254c0..f4b51ce72 100644
--- a/src/kitemviews/kfileitemmodel.cpp
+++ b/src/kitemviews/kfileitemmodel.cpp
@@ -639,7 +639,7 @@ QList<QPair<int, QVariant>> KFileItemModel::groups() const
QElapsedTimer timer;
timer.start();
#endif
- switch (typeForRole(sortRole())) {
+ switch (typeForRole(groupRole())) {
case NameRole:
m_groups = nameRoleGroups();
break;
@@ -673,7 +673,7 @@ QList<QPair<int, QVariant>> KFileItemModel::groups() const
m_groups = ratingRoleGroups();
break;
default:
- m_groups = genericStringRoleGroups(sortRole());
+ m_groups = genericStringRoleGroups(groupRole());
break;
}
@@ -1232,6 +1232,24 @@ void KFileItemModel::onGroupedSortingChanged(bool current)
m_groups.clear();
}
+void KFileItemModel::onGroupRoleChanged(const QByteArray &current, const QByteArray &previous, bool resortItems)
+{
+ Q_UNUSED(previous)
+ const RoleType roleType = typeForRole(current);
+
+ if (!m_requestRole[roleType]) {
+ QSet<QByteArray> newRoles = m_roles;
+ newRoles << current;
+ setRoles(newRoles);
+ }
+
+ m_groups.clear();
+
+ if (resortItems) {
+ resortAllItems();
+ }
+}
+
void KFileItemModel::onSortRoleChanged(const QByteArray &current, const QByteArray &previous, bool resortItems)
{
Q_UNUSED(previous)
@@ -1927,7 +1945,7 @@ void KFileItemModel::removeItems(const KItemRangeList &itemRanges, RemoveItemsBe
QList<KFileItemModel::ItemData *> KFileItemModel::createItemDataList(const QUrl &parentUrl, const KFileItemList &items) const
{
- if (m_sortRole == TypeRole) {
+ if (m_sortRole == TypeRole || typeForRole(rawGroupRole()) == TypeRole) {
// Try to resolve the MIME-types synchronously to prevent a reordering of
// the items when sorting by type (per default MIME-types are resolved
// asynchronously by KFileItemModelRolesUpdater).
@@ -1991,6 +2009,17 @@ void KFileItemModel::prepareItemsForSorting(QList<ItemData *> &itemDataList)
// DateRole).
break;
}
+
+ if (typeForRole(rawGroupRole()) == TypeRole && m_sortRole != TypeRole) {
+ for (ItemData *itemData : std::as_const(itemDataList)) {
+ if (itemData->values.isEmpty()) {
+ const KFileItem &item = itemData->item;
+ if (item.isDir() || item.isMimeTypeKnown()) {
+ itemData->values = retrieveData(itemData->item, itemData->parent);
+ }
+ }
+ }
+ }
}
int KFileItemModel::expandedParentsCount(const ItemData *data)
@@ -2046,7 +2075,8 @@ void KFileItemModel::emitItemsChangedAndTriggerResorting(const KItemRangeList &i
// Trigger a resorting if necessary. 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))
- || (changedRoles.contains("count") && sortRole() == "size")) { // "count" is used in the "size" sort role, so this might require a resorting.
+ || (changedRoles.contains("count") && sortRole() == "size") // "count" is used in the "size" sort role, so this might require a resorting.
+ || (groupedSorting() && !rawGroupRole().isEmpty() && changedRoles.contains(groupRole()))) {
for (const KItemRange &range : itemRanges) {
bool needsResorting = false;
@@ -2077,7 +2107,7 @@ void KFileItemModel::emitItemsChangedAndTriggerResorting(const KItemRangeList &i
}
}
- if (groupedSorting() && changedRoles.contains(sortRole())) {
+ if (groupedSorting() && (changedRoles.contains(sortRole()) || (!rawGroupRole().isEmpty() && changedRoles.contains(groupRole())))) {
// 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.
@@ -2307,6 +2337,20 @@ QHash<QByteArray, QVariant> KFileItemModel::retrieveData(const KFileItem &item,
return data;
}
+QString KFileItemModel::groupKeyForItem(const ItemData *item, const QByteArray &role) const
+{
+ switch (typeForRole(role)) {
+ case ModificationTimeRole:
+ case CreationTimeRole:
+ case AccessTimeRole:
+ return QDateTime::fromSecsSinceEpoch(item->values.value(role).toLongLong()).date().toString(Qt::ISODate);
+ case DeletionTimeRole:
+ return item->values.value("deletiontime").toDateTime().date().toString(Qt::ISODate);
+ default:
+ return item->values.value(role).toString();
+ }
+}
+
bool KFileItemModel::lessThan(const ItemData *a, const ItemData *b, const QCollator &collator) const
{
int result = 0;
@@ -2364,6 +2408,17 @@ bool KFileItemModel::lessThan(const ItemData *a, const ItemData *b, const QColla
}
}
+ if (groupedSorting() && !rawGroupRole().isEmpty() && groupRole() != sortRole()) {
+ const QByteArray gRole = groupRole();
+ const QString groupValueA = groupKeyForItem(a, gRole);
+ const QString groupValueB = groupKeyForItem(b, gRole);
+ const int groupResult = stringCompare(groupValueA, groupValueB, collator);
+ if (groupResult != 0) {
+ // Groups are always in ascending order regardless of the sort order setting.
+ return groupResult < 0;
+ }
+ }
+
result = sortRoleCompare(a, b, collator);
return (sortOrder() == Qt::AscendingOrder) ? result < 0 : result > 0;
@@ -2375,15 +2430,16 @@ void KFileItemModel::sort(const QList<KFileItemModel::ItemData *>::iterator &beg
return lessThan(a, b, m_collator);
};
- if (m_sortRole == NameRole || isRoleValueNatural(m_sortRole)) {
- // Sorting by string can be expensive, in particular if natural sorting is
- // enabled. Use all CPU cores to speed up the sorting process.
+ const QByteArray rawRole = rawGroupRole();
+ const bool groupKeyIsString = !rawRole.isEmpty() && groupRole() != sortRole()
+ && isRoleValueNatural(typeForRole(rawRole));
+ // String-based sorts benefit from parallelism; non-string sorts use one thread
+ // to avoid non-reentrant comparison functions (bug 312679).
+ const bool primaryKeyIsString = m_sortRole == NameRole || isRoleValueNatural(m_sortRole) || groupKeyIsString;
+ if (primaryKeyIsString) {
static const int numberOfThreads = QThread::idealThreadCount();
parallelMergeSort(begin, end, lambdaLessThan, numberOfThreads);
} else {
- // Sorting by other roles is quite fast. Use only one thread to prevent
- // problems caused by non-reentrant comparison functions, see
- // https://bugs.kde.org/show_bug.cgi?id=312679
mergeSort(begin, end, lambdaLessThan);
}
}
diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h
index 2a6e710c3..0ac5d9261 100644
--- a/src/kitemviews/kfileitemmodel.h
+++ b/src/kitemviews/kfileitemmodel.h
@@ -293,6 +293,7 @@ protected:
void onGroupedSortingChanged(bool current) override;
void onSortRoleChanged(const QByteArray &current, const QByteArray &previous, bool resortItems = true) override;
void onSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous) override;
+ void onGroupRoleChanged(const QByteArray &current, const QByteArray &previous, bool resortItems = true) override;
private Q_SLOTS:
/**
@@ -447,6 +448,8 @@ private:
*/
bool lessThan(const ItemData *a, const ItemData *b, const QCollator &collator) const;
+ QString groupKeyForItem(const ItemData *item, const QByteArray &role) const;
+
/**
* Sorts the items between \a begin and \a end using the comparison
* function lessThan().
diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp
index 38fa58436..33cf6341c 100644
--- a/src/kitemviews/kfileitemmodelrolesupdater.cpp
+++ b/src/kitemviews/kfileitemmodelrolesupdater.cpp
@@ -281,6 +281,14 @@ void KFileItemModelRolesUpdater::setPaused(bool paused)
void KFileItemModelRolesUpdater::setRoles(const QSet<QByteArray> &roles)
{
if (m_roles != roles) {
+ const QSet<QByteArray> addedRoles = roles - m_roles;
+ for (const QByteArray &role : addedRoles) {
+ if (m_resolvableRoles.contains(role)) {
+ m_finishedItems.clear();
+ break;
+ }
+ }
+
m_roles = roles;
#if HAVE_BALOO
diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp
index b87216d4b..d24c2426d 100644
--- a/src/kitemviews/kitemlistview.cpp
+++ b/src/kitemviews/kitemlistview.cpp
@@ -1477,8 +1477,8 @@ void KItemListView::slotItemsChanged(const KItemRangeList &itemRanges, const QSe
}
}
- if (m_grouped && roles.contains(m_model->sortRole())) {
- // The sort-role has been changed which might result
+ if (m_grouped && roles.contains(m_model->groupRole())) {
+ // The group-role data has been changed which might result
// in modified group headers
updateVisibleGroupHeaders();
doLayout(NoAnimation);
@@ -1543,6 +1543,16 @@ void KItemListView::slotSortRoleChanged(const QByteArray &current, const QByteAr
}
}
+void KItemListView::slotGroupRoleChanged(const QByteArray &current, const QByteArray &previous)
+{
+ Q_UNUSED(current)
+ Q_UNUSED(previous)
+ if (m_grouped) {
+ updateVisibleGroupHeaders();
+ doLayout(NoAnimation);
+ }
+}
+
void KItemListView::slotCurrentChanged(int current, int previous)
{
// In SingleSelection mode (e.g., in the Places Panel), the current item is
@@ -1826,6 +1836,7 @@ void KItemListView::setModel(KItemModelBase *model)
disconnect(m_model, &KItemModelBase::groupedSortingChanged, this, &KItemListView::slotGroupedSortingChanged);
disconnect(m_model, &KItemModelBase::sortOrderChanged, this, &KItemListView::slotSortOrderChanged);
disconnect(m_model, &KItemModelBase::sortRoleChanged, this, &KItemListView::slotSortRoleChanged);
+ disconnect(m_model, &KItemModelBase::groupRoleChanged, this, &KItemListView::slotGroupRoleChanged);
m_sizeHintResolver->itemsRemoved(KItemRangeList() << KItemRange(0, m_model->count()));
}
@@ -1843,6 +1854,7 @@ void KItemListView::setModel(KItemModelBase *model)
connect(m_model, &KItemModelBase::groupedSortingChanged, this, &KItemListView::slotGroupedSortingChanged);
connect(m_model, &KItemModelBase::sortOrderChanged, this, &KItemListView::slotSortOrderChanged);
connect(m_model, &KItemModelBase::sortRoleChanged, this, &KItemListView::slotSortRoleChanged);
+ connect(m_model, &KItemModelBase::groupRoleChanged, this, &KItemListView::slotGroupRoleChanged);
const int itemCount = m_model->count();
if (itemCount > 0) {
@@ -2251,7 +2263,7 @@ void KItemListView::updateGroupHeaderForWidget(KItemListWidget *widget)
const int groupIndex = groupIndexForItem(index);
Q_ASSERT(groupIndex >= 0);
groupHeader->setData(groups.at(groupIndex).second);
- groupHeader->setRole(model()->sortRole());
+ groupHeader->setRole(model()->groupRole());
groupHeader->setStyleOption(m_styleOption);
groupHeader->setScrollOrientation(scrollOrientation());
groupHeader->setItemIndex(index);
diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h
index 8dc83d528..20c34ceea 100644
--- a/src/kitemviews/kitemlistview.h
+++ b/src/kitemviews/kitemlistview.h
@@ -441,6 +441,7 @@ protected Q_SLOTS:
virtual void slotGroupedSortingChanged(bool current);
virtual void slotSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous);
virtual void slotSortRoleChanged(const QByteArray &current, const QByteArray &previous);
+ virtual void slotGroupRoleChanged(const QByteArray &current, const QByteArray &previous);
virtual void slotCurrentChanged(int current, int previous);
virtual void slotSelectionChanged(const KItemSet &current, const KItemSet &previous);
diff --git a/src/kitemviews/kitemmodelbase.cpp b/src/kitemviews/kitemmodelbase.cpp
index 82e491220..a4f7b0890 100644
--- a/src/kitemviews/kitemmodelbase.cpp
+++ b/src/kitemviews/kitemmodelbase.cpp
@@ -50,13 +50,41 @@ bool KItemModelBase::groupedSorting() const
void KItemModelBase::setSortRole(const QByteArray &role, bool resortItems)
{
if (role != m_sortRole) {
- const QByteArray previous = m_sortRole;
+ const QByteArray previousSortRole = m_sortRole;
m_sortRole = role;
- onSortRoleChanged(role, previous, resortItems);
- Q_EMIT sortRoleChanged(role, previous);
+ onSortRoleChanged(role, previousSortRole, resortItems);
+ Q_EMIT sortRoleChanged(role, previousSortRole);
+
+ if (m_groupRole.isEmpty()) {
+ onGroupRoleChanged(role, previousSortRole, false);
+ Q_EMIT groupRoleChanged(role, previousSortRole);
+ }
+ }
+}
+
+void KItemModelBase::setGroupRole(const QByteArray &role)
+{
+ if (role != m_groupRole) {
+ const QByteArray previousEffective = groupRole();
+ m_groupRole = role;
+ const QByteArray currentEffective = groupRole();
+ if (currentEffective != previousEffective) {
+ onGroupRoleChanged(currentEffective, previousEffective);
+ Q_EMIT groupRoleChanged(currentEffective, previousEffective);
+ }
}
}
+QByteArray KItemModelBase::groupRole() const
+{
+ return m_groupRole.isEmpty() ? m_sortRole : m_groupRole;
+}
+
+QByteArray KItemModelBase::rawGroupRole() const
+{
+ return m_groupRole;
+}
+
QByteArray KItemModelBase::sortRole() const
{
return m_sortRole;
@@ -149,6 +177,13 @@ void KItemModelBase::onSortRoleChanged(const QByteArray &current, const QByteArr
Q_UNUSED(resortItems)
}
+void KItemModelBase::onGroupRoleChanged(const QByteArray &current, const QByteArray &previous, bool resortItems)
+{
+ Q_UNUSED(current)
+ Q_UNUSED(previous)
+ Q_UNUSED(resortItems)
+}
+
void KItemModelBase::onSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous)
{
Q_UNUSED(current)
diff --git a/src/kitemviews/kitemmodelbase.h b/src/kitemviews/kitemmodelbase.h
index 42a9c54c9..68d1d5d8a 100644
--- a/src/kitemviews/kitemmodelbase.h
+++ b/src/kitemviews/kitemmodelbase.h
@@ -76,6 +76,10 @@ public:
void setSortRole(const QByteArray &role, bool resortItems = true);
QByteArray sortRole() const;
+ void setGroupRole(const QByteArray &role);
+ QByteArray groupRole() const;
+ QByteArray rawGroupRole() const;
+
/**
* Sets the sort order to \a order. The method KItemModelBase::onSortOrderChanged() will be
* called so that model-implementations can react on the sort order change. Afterwards the
@@ -248,6 +252,8 @@ Q_SIGNALS:
void sortRoleChanged(const QByteArray &current, const QByteArray &previous);
void sortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous);
+ void groupRoleChanged(const QByteArray &current, const QByteArray &previous);
+
protected:
/**
* Is invoked if the grouped sorting has been changed by KItemModelBase::setGroupedSorting(). Allows
@@ -266,6 +272,8 @@ protected:
*/
virtual void onSortRoleChanged(const QByteArray &current, const QByteArray &previous, bool resortItems = true);
+ virtual void onGroupRoleChanged(const QByteArray &current, const QByteArray &previous, bool resortItems = true);
+
/**
* Is invoked if the sort order has been changed by KItemModelBase::setSortOrder(). Allows
* to react on the changed sort order before the signal sortOrderChanged() will be emitted.
@@ -279,6 +287,7 @@ protected:
private:
bool m_groupedSorting;
QByteArray m_sortRole;
+ QByteArray m_groupRole;
Qt::SortOrder m_sortOrder;
};