Skip to content
Open
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
59 changes: 56 additions & 3 deletions panels/dock/taskmanager/dockglobalelementmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ DockGlobalElementModel::DockGlobalElementModel(QAbstractItemModel *appsModel, Do
, m_activeAppModel(activeAppModel)
{
connect(TaskManagerSettings::instance(), &TaskManagerSettings::dockedElementsChanged, this, &DockGlobalElementModel::loadDockedElements);
connect(TaskManagerSettings::instance(), &TaskManagerSettings::windowSplitChanged, this, &DockGlobalElementModel::groupItemsByApp);

connect(
m_appsModel,
&QAbstractItemModel::rowsRemoved,
Expand Down Expand Up @@ -96,10 +98,13 @@ DockGlobalElementModel::DockGlobalElementModel(QAbstractItemModel *appsModel, Do
}

// There are already windows for this app: insert the new window
// right after the last existing one so that all windows stay together.
// right after the last (rightmost) existing one.
// Search the entire list since windows may not be consecutive after drag reorder.
auto lastIt = firstIt;
while (lastIt + 1 != m_data.end() && std::get<0>(*(lastIt + 1)) == desktopId) {
++lastIt;
for (auto it = firstIt + 1; it != m_data.end(); ++it) {
if (std::get<0>(*it) == desktopId) {
lastIt = it;
}
}

auto insertRow = (lastIt - m_data.begin()) + 1;
Expand Down Expand Up @@ -487,4 +492,52 @@ void DockGlobalElementModel::requestWindowsView(const QModelIndexList &indexes)
{
Q_UNUSED(indexes)
}

void DockGlobalElementModel::moveItem(int from, int to)
{
if (from < 0 || from >= m_data.size() || to < 0 || to >= m_data.size() || from == to)
return;

int destRow = from < to ? to + 1 : to;

if (!beginMoveRows(QModelIndex(), from, from, QModelIndex(), destRow))
return;

m_data.move(from, to);
endMoveRows();
}

void DockGlobalElementModel::groupItemsByApp()
{
if (m_data.isEmpty())
return;

if (TaskManagerSettings::instance()->isWindowSplit())
return;

for (int i = 0; i < m_data.size(); ++i) {
const QString currentId = std::get<0>(m_data.at(i));

int insertPos = i + 1;

while (insertPos < m_data.size() && std::get<0>(m_data.at(insertPos)) == currentId) {
++insertPos;
}

for (int j = insertPos; j < m_data.size(); ++j) {
if (std::get<0>(m_data.at(j)) != currentId)
continue;

int destRow = insertPos < j ? insertPos : insertPos + 1;
if (!beginMoveRows(QModelIndex(), j, j, QModelIndex(), destRow))
continue;
m_data.move(j, insertPos);
endMoveRows();

++insertPos;
}

i = insertPos - 1;
}
}
}
5 changes: 4 additions & 1 deletion panels/dock/taskmanager/dockglobalelementmodel.h
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
#pragma once
Expand Down Expand Up @@ -36,12 +36,15 @@ class DockGlobalElementModel : public QAbstractListModel, public AbstractTaskMan

void requestWindowsView(const QModelIndexList &indexes) const override;

void moveItem(int from, int to);

public slots:
void initDockedElements(bool unused);

private:
void loadDockedElements();
QString getMenus(const QModelIndex &index) const;
void groupItemsByApp();

private:
// id, model, and pos
Expand Down
7 changes: 7 additions & 0 deletions panels/dock/taskmanager/dockitemmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ void DockItemModel::setSourceModel(QAbstractItemModel *model)
auto last = bottomRight.row();
Q_EMIT dataChanged(index(first, 0), index(last, 0), roles);
});
connect(sourceModel(), &QAbstractItemModel::rowsMoved, this, [this](const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row) {
Q_UNUSED(destination)
if (parent.isValid() || m_isUpdating)
return;
beginMoveRows(QModelIndex(), start, end, QModelIndex(), row);
endMoveRows();
Comment on lines +82 to +87
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rowsMoved handler’s lambda takes a destination parameter that is never used. If the project builds with -Werror=unused-parameter, this will fail compilation. Either remove the unused parameter from the lambda signature or mark it unused (e.g., via Q_UNUSED(destination)).

Copilot uses AI. Check for mistakes.
});

auto bottomRight = this->index(std::min(currentCount, newCount), 0);
Q_EMIT dataChanged(index(0, 0), bottomRight);
Expand Down
12 changes: 10 additions & 2 deletions panels/dock/taskmanager/package/TaskManager.qml
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,11 @@ ContainmentItem {
let appId = taskmanager.Applet.desktopIdToAppId(launcherDndDesktopId)
let currentIndex = taskmanager.Applet.windowSplit ? taskmanager.findAppIndexByWindow(appId, launcherDndWinId) : taskmanager.findAppIndex(appId)
if (currentIndex !== -1 && targetIndex !== -1 && currentIndex !== targetIndex) {
visualModel.items.move(currentIndex, targetIndex)
if (taskmanager.Applet.windowSplit) {
taskmanager.Applet.moveItem(currentIndex, targetIndex)
} else {
visualModel.items.move(currentIndex, targetIndex)
}
}
}

Expand All @@ -273,7 +277,11 @@ ContainmentItem {
let appId = taskmanager.Applet.desktopIdToAppId(launcherDndDesktopId)
let currentIndex = taskmanager.Applet.windowSplit ? taskmanager.findAppIndexByWindow(appId, launcherDndWinId) : taskmanager.findAppIndex(appId)
if (currentIndex !== -1 && targetIndex !== -1 && currentIndex !== targetIndex) {
visualModel.items.move(currentIndex, targetIndex)
if (taskmanager.Applet.windowSplit) {
taskmanager.Applet.moveItem(currentIndex, targetIndex)
} else {
visualModel.items.move(currentIndex, targetIndex)
}
}
let appIds = []
for (let i = 0; i < visualModel.items.count; i++) {
Expand Down
8 changes: 7 additions & 1 deletion panels/dock/taskmanager/taskmanager.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 Down Expand Up @@ -484,6 +484,12 @@ void TaskManager::saveDockElementsOrder(const QStringList &appIds)
TaskManagerSettings::instance()->setDockedElements(newDockedElements);
}

void TaskManager::moveItem(int from, int to)
{
if (m_dockGlobalElementModel)
m_dockGlobalElementModel->moveItem(from, to);
}

QString TaskManager::getTrashTipText()
{
const auto count = queryTrashCount();
Expand Down
3 changes: 2 additions & 1 deletion panels/dock/taskmanager/taskmanager.h
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 Down Expand Up @@ -100,6 +100,7 @@ class TaskManager : public DS_NAMESPACE::DContainment, public AbstractTaskManage

Q_INVOKABLE void activateWindow(uint32_t windowID);
Q_INVOKABLE void saveDockElementsOrder(const QStringList &appIds);
Q_INVOKABLE void moveItem(int from, int to);
Q_INVOKABLE QString getTrashTipText();

Q_INVOKABLE bool isTrashEmpty() const;
Expand Down