File indexing completed on 2025-04-27 03:58:23
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2011-03-04 0007 * Description : A simple item to click, drag and release 0008 * 0009 * SPDX-FileCopyrightText: 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "clickdragreleaseitem.h" 0016 0017 // Qt includes 0018 0019 #include <QApplication> 0020 #include <QGraphicsSceneMouseEvent> 0021 #include <QKeyEvent> 0022 #include <QObject> 0023 #include <QPointF> 0024 0025 // Local includes 0026 0027 #include "digikam_debug.h" 0028 #include "itemvisibilitycontroller.h" 0029 0030 namespace Digikam 0031 { 0032 0033 enum ClickDragState 0034 { 0035 HoverState, 0036 PressedState, 0037 PressDragState, 0038 ClickedMoveState 0039 }; 0040 0041 class Q_DECL_HIDDEN ClickDragReleaseItem::Private 0042 { 0043 public: 0044 0045 explicit Private() 0046 : state(HoverState) 0047 { 0048 } 0049 0050 template <class Event> bool isDrag(Event* e) 0051 { 0052 return ((pressPos - e->scenePos()).manhattanLength() > QApplication::startDragDistance()); 0053 } 0054 0055 template <class Event> QRectF rect(Event* e) 0056 { 0057 return QRectF(pressPos, e->scenePos()).normalized(); 0058 } 0059 0060 public: 0061 0062 ClickDragState state; 0063 QPointF pressPos; 0064 }; 0065 0066 // ---------------------------------------------------------------------------- 0067 0068 ClickDragReleaseItem::ClickDragReleaseItem(QGraphicsItem* const parent) 0069 : QGraphicsObject(parent), 0070 d (new Private) 0071 { 0072 setCursor(Qt::CrossCursor); 0073 setFlags(ItemIsFocusable | ItemHasNoContents); 0074 } 0075 0076 ClickDragReleaseItem::~ClickDragReleaseItem() 0077 { 0078 delete d; 0079 } 0080 0081 QRectF ClickDragReleaseItem::boundingRect() const 0082 { 0083 if (parentItem()) 0084 { 0085 return QRectF(QPointF(0, 0), parentItem()->boundingRect().size()); 0086 } 0087 0088 return QRectF(); 0089 } 0090 0091 void ClickDragReleaseItem::paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) 0092 { 0093 } 0094 0095 /** 0096 * 1) Press - Drag - Release: 0097 * mousePress, PressedState -> mouseMoveEvent over threshold, PressDragState -> mouseReleaseEvent, finished 0098 * 2) Click - Move - Click: 0099 * mousePressEvent, PressedState -> mouseReleaseEvent, ClickedMoveState -> 0100 * hoverMoveEvent -> mouseReleaseEvent, finished 0101 */ 0102 0103 void ClickDragReleaseItem::mousePressEvent(QGraphicsSceneMouseEvent* e) 0104 { 0105 if (e->button() != Qt::LeftButton) 0106 { 0107 Q_EMIT cancelled(); 0108 return; 0109 } 0110 0111 if (d->state == HoverState) 0112 { 0113 d->pressPos = e->scenePos(); 0114 d->state = PressedState; 0115 Q_EMIT started(e->scenePos()); 0116 } 0117 } 0118 0119 void ClickDragReleaseItem::mouseMoveEvent(QGraphicsSceneMouseEvent* e) 0120 { 0121 if (d->state == PressedState && d->isDrag(e)) 0122 { 0123 d->state = PressDragState; 0124 setCursor(Qt::SizeFDiagCursor); 0125 } 0126 0127 if (d->state == PressDragState) 0128 { 0129 Q_EMIT moving(d->rect(e)); 0130 } 0131 } 0132 0133 void ClickDragReleaseItem::hoverMoveEvent(QGraphicsSceneHoverEvent* e) 0134 { 0135 if (d->state == ClickedMoveState) 0136 { 0137 Q_EMIT moving(d->rect(e)); 0138 } 0139 } 0140 0141 void ClickDragReleaseItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* e) 0142 { 0143 if (d->state == PressedState) 0144 { 0145 // click-move-click mode first click. 0146 // It cannot be over the drag threshold in this state, would be caught in moveEvent. 0147 0148 d->state = ClickedMoveState; 0149 setCursor(Qt::SizeFDiagCursor); 0150 setAcceptHoverEvents(true); 0151 } 0152 else if (d->state == ClickedMoveState) 0153 { 0154 // click-move-click mode second click 0155 0156 d->state = HoverState; 0157 setCursor(Qt::CrossCursor); 0158 setAcceptHoverEvents(false); 0159 Q_EMIT finished(d->rect(e)); 0160 } 0161 else if (d->state == PressDragState) 0162 { 0163 if (d->isDrag(e)) 0164 { 0165 Q_EMIT finished(d->rect(e)); 0166 } 0167 else 0168 { 0169 Q_EMIT cancelled(); 0170 } 0171 0172 d->state = HoverState; 0173 setCursor(Qt::CrossCursor); 0174 setAcceptHoverEvents(false); 0175 } 0176 } 0177 0178 void ClickDragReleaseItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* e) 0179 { 0180 e->ignore(); 0181 } 0182 0183 void ClickDragReleaseItem::keyPressEvent(QKeyEvent* e) 0184 { 0185 qCDebug(DIGIKAM_WIDGETS_LOG) << e; 0186 0187 switch (e->key()) 0188 { 0189 case Qt::Key_Backspace: 0190 case Qt::Key_Escape: 0191 Q_EMIT cancelled(); 0192 break; 0193 0194 default: 0195 e->ignore(); 0196 break; 0197 } 0198 } 0199 0200 } // namespace Digikam 0201 0202 #include "moc_clickdragreleaseitem.cpp"