From c21be9d2206e4a33d2021cdaddba245009240d6a Mon Sep 17 00:00:00 2001 From: Wang Zichong Date: Thu, 23 Jul 2026 10:15:17 +0800 Subject: [PATCH] fix: section sort no longer works MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修正分组排序的顺序不再正确的问题. Log: --- qml/windowed/AppListView.qml | 2 +- src/models/categorizedsortproxymodel.cpp | 26 ++++++++++++++++-------- src/models/categorizedsortproxymodel.h | 6 +++++- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/qml/windowed/AppListView.qml b/qml/windowed/AppListView.qml index 4896c1b1..c4dcef0a 100644 --- a/qml/windowed/AppListView.qml +++ b/qml/windowed/AppListView.qml @@ -377,7 +377,7 @@ FocusScope { } } - section.property: CategorizedSortProxyModel.sortRoleName // "transliterated" // "category" + section.property: CategorizedSortProxyModel.sectionRoleName // "transliterated" // "category" section.criteria: section.property === "transliterated" ? ViewSection.FirstCharacter : ViewSection.FullString section.delegate: sectionHeading section.labelPositioning: ViewSection.InlineLabels // | ViewSection.CurrentLabelAtStart diff --git a/src/models/categorizedsortproxymodel.cpp b/src/models/categorizedsortproxymodel.cpp index 9838c659..20a4f528 100644 --- a/src/models/categorizedsortproxymodel.cpp +++ b/src/models/categorizedsortproxymodel.cpp @@ -20,7 +20,7 @@ void CategorizedSortProxyModel::setCategoryType(CategoryType categoryType) CategoryType oldCategoryType = this->categoryType(); // Temporarily disable dynamic sort to prevent setSortRole from triggering - // a redundant sort. We trigger a single sort below via setDynamicSortFilter, + // a redundant sort. We trigger a single sort below via sort(0), // which uses layoutAboutToBeChanged/layoutChanged instead of modelReset, // preserving delegates. const bool wasDynamic = dynamicSortFilter(); @@ -42,14 +42,22 @@ void CategorizedSortProxyModel::setCategoryType(CategoryType categoryType) config->setValue("categoryType", categoryType); } - // Re-enable dynamic sort filter to trigger a single d->sort() internally, - // then restore the original setting. d->sort() emits - // layoutAboutToBeChanged/layoutChanged (not modelReset), so the view moves - // existing delegates instead of destroying and recreating them. - setDynamicSortFilter(true); - if (!wasDynamic) { - setDynamicSortFilter(false); - } + // Use sort(0) instead of setDynamicSortFilter(true) because the latter + // calls d->sort() without setting proxy_sort_column, leaving it at -1 + // (the Qt 6 default). When source_sort_column is -1, + // QSortFilterProxyModelPrivate::sort_source_rows falls through to + // std::less{} (a no-op), so no sorting actually occurs. + // sort(0) properly sets proxy_sort_column = 0 and calls + // update_source_sort_column(), then d->sort() emits + // layoutAboutToBeChanged/layoutChanged so the view moves existing + // delegates instead of destroying and recreating them. + sort(0); + setDynamicSortFilter(wasDynamic); + + // Must update sectionRoleName after the sort so that the QML ListView + // evaluates section structure with the correct (already sorted) item order. + m_sectionRoleName = sortRoleName(); + emit sectionRoleNameChanged(); qCInfo(logModels) << "Category type changed to:" << categoryType; emit categoryTypeChanged(); diff --git a/src/models/categorizedsortproxymodel.h b/src/models/categorizedsortproxymodel.h index 9b9e0239..2d7b78dd 100644 --- a/src/models/categorizedsortproxymodel.h +++ b/src/models/categorizedsortproxymodel.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -13,6 +13,7 @@ class CategorizedSortProxyModel : public QSortFilterProxyModel Q_PROPERTY(CategoryType categoryType READ categoryType WRITE setCategoryType NOTIFY categoryTypeChanged) Q_PROPERTY(QString sortRoleName READ sortRoleName NOTIFY categoryTypeChanged) + Q_PROPERTY(QString sectionRoleName READ sectionRoleName NOTIFY sectionRoleNameChanged) QML_NAMED_ELEMENT(CategorizedSortProxyModel) QML_SINGLETON @@ -42,17 +43,20 @@ class CategorizedSortProxyModel : public QSortFilterProxyModel enum CategoryType categoryType() const; QString sortRoleName() const; + QString sectionRoleName() const { return m_sectionRoleName; } Q_INVOKABLE QList alphabetarySections() const; Q_INVOKABLE QList DDECategorySections() const; signals: void categoryTypeChanged(); + void sectionRoleNameChanged(); protected: bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override; private: bool isFreeSort; + QString m_sectionRoleName; explicit CategorizedSortProxyModel(QObject *parent = nullptr); };