shift-shell/containments/homescreens/folio/delegatetoucharea.h
Marco Allegretti 9bccbeede6 Add drag-reorder for dock favourites
Click-and-drag reordering of favourites bar items in convergence
mode.  The existing touch-based press-and-hold drag is kept for
mobile; in convergence mode, press-and-hold opens the context
menu only.

DelegateTouchArea owns the exclusive mouse grab at the C++ level,
so drag detection (threshold crossing + delta signals) is added
there rather than using a QML DragHandler.  Displaced items
animate into their new positions while the dragged item follows
the cursor.

Expose FavouritesModel::moveEntry as Q_INVOKABLE so QML can
persist the reorder.
2026-04-12 14:15:13 +02:00

84 lines
2.5 KiB
C++

// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <QQuickItem>
#include <QTimer>
#include <Qt>
/**
* @short A component that is similar to MouseArea but allows for a
* simpler tracking of dragging movements after pressing and holding.
*
* @author Devin Lin <devin@kde.org>
*/
class DelegateTouchArea : public QQuickItem
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged FINAL)
Q_PROPERTY(bool hovered READ hovered NOTIFY hoveredChanged FINAL)
Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged FINAL)
Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape RESET unsetCursor NOTIFY cursorShapeChanged FINAL)
Q_PROPERTY(QPointF pressPosition READ pressPosition NOTIFY pressPositionChanged FINAL)
QML_NAMED_ELEMENT(DelegateTouchArea)
public:
DelegateTouchArea(QQuickItem *parent = nullptr);
bool pressed();
bool hovered();
bool dragging();
Qt::CursorShape cursorShape();
void setCursorShape(Qt::CursorShape cursorShape);
void unsetCursor();
QPointF pressPosition();
Q_SIGNALS:
void clicked();
void rightMousePress();
void pressAndHold();
void pressAndHoldReleased();
void draggingChanged();
void dragMoved(qreal deltaX);
void pressedChanged(bool pressed);
void hoveredChanged(bool hovered);
void cursorShapeChanged();
void pressPositionChanged();
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseUngrabEvent() override;
void touchEvent(QTouchEvent *event) override;
void touchUngrabEvent() override;
void hoverEnterEvent(QHoverEvent *event) override;
void hoverLeaveEvent(QHoverEvent *event) override;
private Q_SLOTS:
void startPressAndHold();
private:
void setPressed(bool pressed);
void setHovered(bool hovered);
void setDragging(bool dragging);
void handlePressEvent(QPointerEvent *event, QPointF point);
void handleReleaseEvent(QPointerEvent *event, bool click);
void handleMoveEvent(QPointerEvent *event, QPointF point);
bool m_pressed{false};
bool m_hovered{false};
bool m_dragging{false};
bool m_pressAndHeld{false};
Qt::CursorShape m_cursorShape{Qt::ArrowCursor};
QPointF m_mouseDownPosition{};
QTimer *m_pressAndHoldTimer{nullptr};
};
QML_DECLARE_TYPE(DelegateTouchArea)