Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 21 additions & 27 deletions qml/windowed/AppList.qml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

Expand All @@ -18,50 +18,45 @@ ColumnLayout {

signal freeSortViewFolderClicked(string folderId, string folderName, point triggerPosition)

property Item keyTabTarget: loader.item
property bool isFreeSort: CategorizedSortProxyModel.categoryType === CategorizedSortProxyModel.FreeCategory
property Item keyTabTarget: isFreeSort ? freeSortView.keyTabTarget : categoryView.keyTabTarget
property Item nextKeyTabTarget

onFocusChanged: () => {
loader.item.focus = true
(isFreeSort ? freeSortView : categoryView).focus = true
}

function resetViewState() {
loader.item.resetViewState()
onIsFreeSortChanged: {
(isFreeSort ? freeSortView : categoryView).resetViewState()
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
}

function switchToFreeSort(freeSort) {
if (freeSort) {
loader.sourceComponent = freeSortListView
} else {
loader.sourceComponent = categoryListView
}
// 切换排序模式后立即重置视图到顶部,无动画
if (loader.item) {
loader.item.resetViewState()
}
function resetViewState() {
(isFreeSort ? freeSortView : categoryView).resetViewState()
}

Loader {
id: loader
sourceComponent: CategorizedSortProxyModel.categoryType === CategorizedSortProxyModel.FreeCategory ? freeSortListView : categoryListView
// Both views are always instantiated; switching is done via `visible`
// to avoid the costly Loader component destruction/creation (~120ms -> ~0ms).
// The hidden view's ListView retains its delegates because it keeps a valid
// size from anchors.fill, so re-showing is instant.
// Extra memory: ~60-80KB for hidden view delegates (measured).
Item {
id: viewContainer
Layout.fillWidth: true
Layout.fillHeight: true
}

Component {
id: categoryListView
AppListView {
id: appCategoryListView
id: categoryView
anchors.fill: viewContainer
visible: !isFreeSort

MouseAreaCom {}
KeyNavigation.tab: nextKeyTabTarget
}
}

Component {
id: freeSortListView
FreeSortListView {
id: appFreeSortListView
id: freeSortView
anchors.fill: viewContainer
visible: isFreeSort

onFolderClicked: {
freeSortViewFolderClicked(folderId, folderName, triggerPosition)
Expand All @@ -84,4 +79,3 @@ ColumnLayout {
}
}
}

7 changes: 0 additions & 7 deletions qml/windowed/WindowedFrame.qml
Original file line number Diff line number Diff line change
Expand Up @@ -325,13 +325,6 @@ InputEventItem {
}
}

Connections {
target: sideBar
function onSwitchToFreeSort(isFreeSort) {
appList.switchToFreeSort(isFreeSort)
}
}

Connections {
target: appList
function onFreeSortViewFolderClicked(folderId, folderName, triggerPosition) {
Expand Down
21 changes: 16 additions & 5 deletions src/models/categorizedsortproxymodel.cpp
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -18,8 +18,13 @@ DCORE_USE_NAMESPACE
void CategorizedSortProxyModel::setCategoryType(CategoryType categoryType)
{
CategoryType oldCategoryType = this->categoryType();

beginResetModel();

// Temporarily disable dynamic sort to prevent setSortRole from triggering
// a redundant sort. We trigger a single sort below via setDynamicSortFilter,
// which uses layoutAboutToBeChanged/layoutChanged instead of modelReset,
// preserving delegates.
const bool wasDynamic = dynamicSortFilter();
setDynamicSortFilter(false);
isFreeSort = (categoryType == FreeCategory);
switch (categoryType) {
case Alphabetary:
Expand All @@ -37,8 +42,14 @@ void CategorizedSortProxyModel::setCategoryType(CategoryType categoryType)
config->setValue("categoryType", categoryType);
}

sort(0);
endResetModel();
// 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);
}

qCInfo(logModels) << "Category type changed to:" << categoryType;
emit categoryTypeChanged();
Expand Down
Loading