KQuickImageEditor

resizehandle.cpp
1/*
2 * SPDX-FileCopyrightText: (C) 2019 Marco Martin <mart@kde.org>
3 * SPDX-FileCopyrightText: (C) 2020 Carl Schwan <carl@carlschwan.eu>
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 */
7
8#include "resizehandle.h"
9#include "resizerectangle.h"
10
11#include <QCursor>
12#include <cmath>
13
14ResizeHandle::ResizeHandle(QQuickItem *parent)
15 : QQuickItem(parent)
16{
17 setAcceptedMouseButtons(Qt::LeftButton);
18
19 auto syncCursor = [this]() {
20 switch (m_resizeCorner) {
21 case Left:
22 case Right:
23 setCursor(QCursor(Qt::SizeHorCursor));
24 break;
25 case Top:
26 case Bottom:
27 setCursor(QCursor(Qt::SizeVerCursor));
28 break;
29 case TopLeft:
30 case BottomRight:
31 setCursor(QCursor(Qt::SizeFDiagCursor));
32 break;
33 case TopRight:
34 case BottomLeft:
35 default:
36 setCursor(Qt::SizeBDiagCursor);
37 }
38 };
39
40 syncCursor();
41 connect(this, &ResizeHandle::resizeCornerChanged, this, syncCursor);
42}
43
44QQuickItem *ResizeHandle::rectangle() const
45{
46 return m_rectangle;
47}
48
49void ResizeHandle::setResizeCorner(ResizeHandle::Corner corner)
50{
51 if (m_resizeCorner == corner) {
52 return;
53 }
54 m_resizeCorner = corner;
55 Q_EMIT resizeCornerChanged();
56}
57
58void ResizeHandle::setRectangle(QQuickItem *rectangle)
59{
60 if (m_rectangle == rectangle) {
61 return;
62 }
63 m_rectangle = qobject_cast<ResizeRectangle *>(rectangle);
64 Q_EMIT rectangleChanged();
65}
66
67bool ResizeHandle::resizeBlocked() const
68{
69 return false; // m_resizeWidthBlocked || m_resizeHeightBlocked;
70}
71
72bool ResizeHandle::resizeLeft() const
73{
74 return m_resizeCorner == Left || m_resizeCorner == TopLeft || m_resizeCorner == BottomLeft;
75}
76
77bool ResizeHandle::resizeTop() const
78{
79 return m_resizeCorner == Top || m_resizeCorner == TopLeft || m_resizeCorner == TopRight;
80}
81
82bool ResizeHandle::resizeRight() const
83{
84 return m_resizeCorner == Right || m_resizeCorner == TopRight || m_resizeCorner == BottomRight;
85}
86
87bool ResizeHandle::resizeBottom() const
88{
89 return m_resizeCorner == Bottom || m_resizeCorner == BottomLeft || m_resizeCorner == BottomRight;
90}
91
92void ResizeHandle::setResizeBlocked(bool width, bool height)
93{
94 if (m_resizeWidthBlocked == width && m_resizeHeightBlocked == height) {
95 return;
96 }
97
98 m_resizeWidthBlocked = width;
99 m_resizeHeightBlocked = height;
100
101 Q_EMIT resizeBlockedChanged();
102}
103
104void ResizeHandle::mousePressEvent(QMouseEvent *event)
105{
106 m_mouseDownPosition = event->windowPos();
107 m_mouseDownGeometry = QRectF(m_rectangle->insideX(), m_rectangle->insideY(), m_rectangle->insideWidth(), m_rectangle->insideHeight());
108 setResizeBlocked(false, false);
109 event->accept();
110}
111
112void ResizeHandle::mouseMoveEvent(QMouseEvent *event)
113{
114 const QPointF difference = m_mouseDownPosition - event->windowPos();
115
116 const QSizeF minimumSize = QSize(20, 20);
117
118 // Horizontal resize
119 if (resizeLeft()) {
120 const qreal width = qMax(minimumSize.width(), m_mouseDownGeometry.width() + difference.x());
121 const qreal x = m_mouseDownGeometry.x() + (m_mouseDownGeometry.width() - width);
122
123 m_rectangle->setInsideX(x);
124 m_rectangle->setInsideWidth(width);
125 setResizeBlocked(m_mouseDownGeometry.width() + difference.x() < minimumSize.width(), m_resizeHeightBlocked);
126 } else if (resizeRight()) {
127 const qreal width = qMax(minimumSize.width(), m_mouseDownGeometry.width() - difference.x());
128
129 m_rectangle->setInsideWidth(width);
130 setResizeBlocked(m_mouseDownGeometry.width() - difference.x() < minimumSize.width(), m_resizeHeightBlocked);
131 }
132
133 // Vertical Resize
134 if (resizeTop()) {
135 const qreal height = qMax(minimumSize.height(), m_mouseDownGeometry.height() + difference.y());
136 const qreal y = m_mouseDownGeometry.y() + (m_mouseDownGeometry.height() - height);
137
138 m_rectangle->setInsideY(y);
139 m_rectangle->setInsideHeight(height);
140 setResizeBlocked(m_resizeWidthBlocked, m_mouseDownGeometry.height() + difference.y() < minimumSize.height());
141 } else if (resizeBottom()) {
142 const qreal height = qMax(minimumSize.height(), m_mouseDownGeometry.height() - difference.y());
143
144 m_rectangle->setInsideHeight(qMax(height, minimumSize.height()));
145 setResizeBlocked(m_resizeWidthBlocked, m_mouseDownGeometry.height() - difference.y() < minimumSize.height());
146 }
147
148 event->accept();
149}
150
151void ResizeHandle::mouseReleaseEvent(QMouseEvent *event)
152{
153 event->accept();
154
155 setResizeBlocked(false, false);
156 Q_EMIT resizeBlockedChanged();
157}
158
159#include "moc_resizehandle.cpp"
Q_EMITQ_EMIT
T qobject_cast(QObject *object)
qreal x() const const
qreal y() const const
qreal height() const const
qreal width() const const
SizeHorCursor
LeftButton
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Feb 21 2025 11:55:19 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.