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
43 changes: 27 additions & 16 deletions panels/dock/tray/package/TrayContainer.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 Down Expand Up @@ -172,7 +172,7 @@ Item {

// 检查当前悬停位置是否是禁止拖拽的插件
let modelIndex = DDT.TraySortOrderModel.getModelIndexByVisualIndex(currentItemIndex)
let sectionType =root.model.data(modelIndex, DDT.TraySortOrderModel.SectionTypeRole)
let sectionType = root.model.data(modelIndex, DDT.TraySortOrderModel.SectionTypeRole)
if (sectionType === "fixed") {
dragEvent.accepted = false
return
Expand All @@ -189,34 +189,45 @@ Item {
}
}

// TODO: If this method is used in the stash area, it will cause the drag state to be terminated when dragging to the tray area
if (!isStash) {
// 根据 ActionShowStashDelegate 的显示状态动态改变条件
let shouldAllowDrop = showStashActionVisible ? (dropHoverIndex !== 0) : (dropHoverIndex !== -1)
if (shouldAllowDrop) {
dropTrayTimer.handleDrop = function() {
if (isDropped || dragExited) return
DDT.TraySortOrderModel.dropToDockTray(surfaceId, Math.floor(currentItemIndex), isBefore)
}
dropTrayTimer.start()
} else if (!surfaceId.startsWith("application-tray")){
dragEvent.accepted = false
// 根据 ActionShowStashDelegate 的显示状态动态改变条件
let shouldAllowDrop = showStashActionVisible ? (dropHoverIndex !== 0) : (dropHoverIndex !== -1)

// 使用暂存机制
if (isStash && shouldAllowDrop) {
// 调用 stageDropPosition 来预览拖放位置,预留空位
DDT.TraySortOrderModel.stageDropPosition(surfaceId, Math.floor(currentItemIndex))
} else if (!isStash && shouldAllowDrop) {
dropTrayTimer.handleDrop = function() {
if (isDropped || dragExited) return
DDT.TraySortOrderModel.dropToDockTray(surfaceId, Math.floor(currentItemIndex), isBefore)
}
dropTrayTimer.start()
} else if (!surfaceId.startsWith("application-tray")){
dragEvent.accepted = false
}
}

onDropped: function (dropEvent) {
isDropped = true
let surfaceId = dropEvent.getDataAsString("text/x-dde-shell-tray-dnd-surfaceId")
let dropIdx = DDT.TrayItemPositionManager.itemIndexByPoint(Qt.point(drag.x, drag.y))
let currentItemIndex = dropIdx.index
let isBefore = dropIdx.isBefore
console.log("dropped", currentItemIndex, isBefore)
DDT.TraySortOrderModel.dropToDockTray(surfaceId, Math.floor(currentItemIndex), isBefore);
let isStash = dropEvent.getDataAsString("text/x-dde-shell-tray-dnd-sectionType") === "stashed"
console.log("dropped", currentItemIndex, isBefore, isStash)

if (isStash) {
// 提交暂存的拖放位置
DDT.TraySortOrderModel.commitStagedDrop()
} else {
DDT.TraySortOrderModel.dropToDockTray(surfaceId, Math.floor(currentItemIndex), isBefore);
}
DDT.TraySortOrderModel.actionsAlwaysVisible = false
}

onExited: function () {
dragExited = true
DDT.TraySortOrderModel.clearStagedDrop()
// dragging from quickPanel, entered trayContainer, but not dropped in this area
if (source !== "" && !isDropped) {
dropTrayTimer.stop()
Expand Down
13 changes: 12 additions & 1 deletion panels/dock/tray/trayitempositionmanager.cpp
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 Down Expand Up @@ -119,6 +119,17 @@ void TrayItemPositionManager::layoutHealthCheck(int delayMs)
qDebug() << "layout health check scheduled!";
}

void TrayItemPositionManager::clearRegisteredSizes()
{
// Avoid emitting signal if there's nothing to clear
if (m_registeredItemsSize.isEmpty()) {
return;
}

m_registeredItemsSize.clear();
emit visualItemSizeChanged();
}

TrayItemPositionManager::TrayItemPositionManager(QObject *parent)
: QObject(parent)
{
Expand Down
3 changes: 2 additions & 1 deletion panels/dock/tray/trayitempositionmanager.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

Expand Down Expand Up @@ -58,6 +58,7 @@ class TrayItemPositionManager : public QObject
Qt::Orientation orientation() const;
int dockHeight() const;
Q_INVOKABLE void layoutHealthCheck(int delayMs = 200);
Q_INVOKABLE void clearRegisteredSizes();

signals:
void orientationChanged(Qt::Orientation);
Expand Down
64 changes: 63 additions & 1 deletion panels/dock/tray/traysortordermodel.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// 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

#include "traysortordermodel.h"
#include "constants.h"

Check warning on line 6 in panels/dock/tray/traysortordermodel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "constants.h" not found.
#include "trayitempositionmanager.h"

#include <QDebug>

Check warning on line 9 in panels/dock/tray/traysortordermodel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDebug> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDBusMessage>

Check warning on line 10 in panels/dock/tray/traysortordermodel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDBusMessage> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDBusConnection>

#include <DConfig>
Expand Down Expand Up @@ -361,6 +362,11 @@
m_isUpdating = true;
emit isUpdatingChanged(true);

// Clear registered sizes before re-assigning visual indexes
// This ensures that when items are repositioned, the empty placeholder
// will use the default item size instead of retaining the previous item's size
TrayItemPositionManager::instance().clearRegisteredSizes();

for (int i = 0; i < rowCount(); i++) {
item(i)->setData(-1, TraySortOrderModel::VisualIndexRole);
}
Expand Down Expand Up @@ -421,6 +427,7 @@
if (itemVisible && dockVisible) {
toogleCollapseActionVisible = true;
if (!m_collapsed) {
reserveStagedDropSpace(currentVisualIndex);
results[0]->setData(currentVisualIndex++, TraySortOrderModel::VisualIndexRole);
} else {
// When collapsed, collapsable items should be hidden (visualIndex = -1)
Expand All @@ -434,6 +441,7 @@
Q_ASSERT(!results.isEmpty());
results[0]->setData(toogleCollapseActionVisible, TraySortOrderModel::VisibilityRole);
if (toogleCollapseActionVisible) {
reserveStagedDropSpace(currentVisualIndex);
results[0]->setData(currentVisualIndex, TraySortOrderModel::VisualIndexRole);
currentVisualIndex++;
}
Expand All @@ -450,6 +458,7 @@
results[0]->setData(itemVisible, TraySortOrderModel::VisibilityRole);
results[0]->setData(dockVisible, TraySortOrderModel::DockVisibleRole);
if (itemVisible && dockVisible) {
reserveStagedDropSpace(currentVisualIndex);
results[0]->setData(currentVisualIndex, TraySortOrderModel::VisualIndexRole);
currentVisualIndex++;
}
Expand All @@ -459,6 +468,7 @@
results = findItems("internal/action-toggle-quick-settings");
Q_ASSERT(!results.isEmpty());
results[0]->setData(SECTION_FIXED, TraySortOrderModel::SectionTypeRole);
reserveStagedDropSpace(currentVisualIndex);
results[0]->setData(currentVisualIndex, TraySortOrderModel::VisualIndexRole);
currentVisualIndex++;

Expand Down Expand Up @@ -600,4 +610,56 @@
return QModelIndex();
}

void TraySortOrderModel::reserveStagedDropSpace(int &currentVisualIndex)
{
if (!m_stagedSurfaceId.isEmpty() && currentVisualIndex == m_stagedVisualIndex) {
currentVisualIndex++;
}
}

void TraySortOrderModel::stageDropPosition(const QString &surfaceId, int visualIndex)
{
if (m_stagedSurfaceId == surfaceId && m_stagedVisualIndex == visualIndex) {
return;
}

m_stagedSurfaceId = surfaceId;
m_stagedVisualIndex = visualIndex;
emit stagedDropChanged();

// Update visual indexes to show preview position
updateVisualIndexes();
}

void TraySortOrderModel::commitStagedDrop()
{
if (m_stagedSurfaceId.isEmpty() || m_stagedVisualIndex < 0) {
return;
}

// Reuse dropToDockTray logic for consistency
// isBefore is always true for staged drops (insert before the target position)
dropToDockTray(m_stagedSurfaceId, m_stagedVisualIndex, true);

// Clear staged state (dropToDockTray already called updateVisualIndexes)
m_stagedSurfaceId.clear();
m_stagedVisualIndex = -1;
emit stagedDropChanged();
}

void TraySortOrderModel::clearStagedDrop()
{
// Avoid redundant work if there is no staged drop
if (m_stagedSurfaceId.isEmpty() && m_stagedVisualIndex < 0) {
return;
}

m_stagedSurfaceId.clear();
m_stagedVisualIndex = -1;
emit stagedDropChanged();

// Update visual indexes to remove preview
updateVisualIndexes();
}

}
17 changes: 16 additions & 1 deletion panels/dock/tray/traysortordermodel.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

Expand Down Expand Up @@ -27,6 +27,8 @@ class TraySortOrderModel : public QStandardItemModel
Q_PROPERTY(bool actionsAlwaysVisible MEMBER m_actionsAlwaysVisible NOTIFY actionsAlwaysVisibleChanged)
Q_PROPERTY(bool isUpdating MEMBER m_isUpdating NOTIFY isUpdatingChanged)
Q_PROPERTY(QList<QVariantMap> availableSurfaces MEMBER m_availableSurfaces NOTIFY availableSurfacesChanged)
Q_PROPERTY(QString stagedSurfaceId MEMBER m_stagedSurfaceId NOTIFY stagedDropChanged)
Q_PROPERTY(int stagedVisualIndex MEMBER m_stagedVisualIndex NOTIFY stagedDropChanged)
public:
// enum SectionTypes {
// TrayAction,
Expand Down Expand Up @@ -67,6 +69,11 @@ class TraySortOrderModel : public QStandardItemModel
Q_INVOKABLE void setDockVisible(const QString & surfaceId, bool visible);
Q_INVOKABLE bool isDockVisible(const QString &surfaceId) const;
Q_INVOKABLE QModelIndex getModelIndexByVisualIndex(int visualIndex) const;

// Staged drop methods for drag preview
Q_INVOKABLE void stageDropPosition(const QString &surfaceId, int visualIndex);
Q_INVOKABLE void commitStagedDrop();
Q_INVOKABLE void clearStagedDrop();

signals:
void collapsedChanged(bool);
Expand All @@ -75,6 +82,7 @@ class TraySortOrderModel : public QStandardItemModel
void isUpdatingChanged(bool);
void visualItemCountChanged(int);
void availableSurfacesChanged(const QList<QVariantMap> &);
void stagedDropChanged();

private:
int m_visualItemCount = 0;
Expand All @@ -94,9 +102,16 @@ class TraySortOrderModel : public QStandardItemModel
QStringList m_hiddenIds;
// surface IDs that should be hidden from dock tray but keep VisibilityRole true.
QStringList m_dockHiddenIds;

// Staged drop state for drag preview
QString m_stagedSurfaceId;
int m_stagedVisualIndex = -1;

QStandardItem * findItemByVisualIndex(int visualIndex, VisualSections visualSection) const;
QStringList * getSection(const QString & sectionType);

// Helper function for reserving space during staged drop
void reserveStagedDropSpace(int &currentVisualIndex);
QString findSection(const QString &surfaceId, const QString &fallback, const QStringList &forbiddenSections, int pluginFlags);
void registerToSection(const QString & surfaceId, const QString & sectionType);
QStandardItem *createTrayItem(const QString &name,
Expand Down