File indexing completed on 2024-12-29 05:06:05

0001 // SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
0002 // SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
0003 // SPDX-License-Identifier: LGPL-2.0-or-later
0004 
0005 #include "widgetcontainer.h"
0006 
0007 #include <QCursor>
0008 #include <QGuiApplication>
0009 #include <QStyleHints>
0010 
0011 WidgetContainer::WidgetContainer(QQuickItem *parent)
0012     : QQuickItem(parent)
0013     , m_pressAndHoldTimer{new QTimer{this}}
0014 {
0015     m_pressAndHoldTimer->setInterval(QGuiApplication::styleHints()->mousePressAndHoldInterval());
0016     m_pressAndHoldTimer->setSingleShot(true);
0017     connect(m_pressAndHoldTimer, &QTimer::timeout, this, &WidgetContainer::startPressAndHold);
0018 
0019     setFiltersChildMouseEvents(true);
0020     setFlags(QQuickItem::ItemIsFocusScope);
0021     setActiveFocusOnTab(true);
0022     setAcceptedMouseButtons(Qt::LeftButton);
0023 
0024     connect(this, &WidgetContainer::activeFocusChanged, this, &WidgetContainer::onActiveFocusChanged);
0025 }
0026 
0027 bool WidgetContainer::editMode() const
0028 {
0029     return m_editMode;
0030 }
0031 
0032 void WidgetContainer::setEditMode(bool editMode)
0033 {
0034     if (m_editMode != editMode) {
0035         m_editMode = editMode;
0036 
0037         if (m_editMode) {
0038             setZ(1);
0039 
0040             if (m_pressed) {
0041                 // sendUngrabRecursive(m_contentItem);
0042                 QMouseEvent ev(QEvent::MouseButtonPress, mapFromScene(m_mouseDownPosition), m_mouseDownPosition, QPointF(), Qt::LeftButton, {}, {});
0043                 ev.setExclusiveGrabber(ev.point(0), this);
0044                 QCoreApplication::sendEvent(this, &ev);
0045             }
0046 
0047         } else {
0048             setZ(0);
0049         }
0050 
0051         Q_EMIT editModeChanged();
0052     }
0053 }
0054 
0055 bool WidgetContainer::childMouseEventFilter(QQuickItem *item, QEvent *event)
0056 {
0057     switch (event->type()) {
0058     case QEvent::MouseButtonPress: {
0059         QMouseEvent *me = static_cast<QMouseEvent *>(event);
0060         if (me->buttons() & Qt::LeftButton) {
0061             mousePressEvent(me);
0062         }
0063         break;
0064     }
0065     case QEvent::MouseMove: {
0066         QMouseEvent *me = static_cast<QMouseEvent *>(event);
0067         mouseMoveEvent(me);
0068         break;
0069     }
0070     case QEvent::MouseButtonRelease: {
0071         QMouseEvent *me = static_cast<QMouseEvent *>(event);
0072         mouseReleaseEvent(me);
0073         break;
0074     }
0075     case QEvent::UngrabMouse:
0076         mouseUngrabEvent();
0077         break;
0078     default:
0079         break;
0080     }
0081 
0082     return QQuickItem::childMouseEventFilter(item, event);
0083 }
0084 
0085 void WidgetContainer::mousePressEvent(QMouseEvent *event)
0086 {
0087     forceActiveFocus(Qt::MouseFocusReason);
0088 
0089     m_pressed = true;
0090     m_pressAndHoldTimer->start();
0091     m_mouseDownPosition = event->scenePosition();
0092     event->accept();
0093 }
0094 
0095 void WidgetContainer::mouseMoveEvent(QMouseEvent *event)
0096 {
0097     if (!m_editMode && QPointF(event->scenePosition() - m_mouseDownPosition).manhattanLength() >= QGuiApplication::styleHints()->startDragDistance()) {
0098         m_pressAndHoldTimer->stop();
0099     }
0100 
0101     QQuickItem::mouseMoveEvent(event);
0102 }
0103 
0104 void WidgetContainer::mouseReleaseEvent(QMouseEvent *event)
0105 {
0106     Q_EMIT pressReleased();
0107 
0108     m_pressAndHoldTimer->stop();
0109     m_pressed = false;
0110 
0111     event->accept();
0112 }
0113 
0114 void WidgetContainer::mouseUngrabEvent()
0115 {
0116     m_pressAndHoldTimer->stop();
0117     m_pressed = false;
0118 }
0119 
0120 void WidgetContainer::startPressAndHold()
0121 {
0122     setEditMode(true);
0123     Q_EMIT startEditMode(m_mouseDownPosition);
0124 }
0125 
0126 void WidgetContainer::onActiveFocusChanged(bool activeFocus)
0127 {
0128     if (!activeFocus) {
0129         setEditMode(false);
0130     }
0131 }