KSane

selectionitem.cpp
1/*
2 * SPDX-FileCopyrightText: 2008 Kare Sars <kare dot sars at iki dot fi>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6
7#include "selectionitem.h"
8#include <QGraphicsView>
9#include <QGraphicsScene>
10#include <QCursor>
11#include <QList>
12
13namespace KSaneIface
14{
15
16static const qreal selMargin = 4.0;
17static const QPointF boundMargin(selMargin, selMargin);
18static const qreal addRemMargin = 8.0;
19static const QPointF addRemMarginPoint(addRemMargin, addRemMargin);
20
21struct SelectionItem::Private {
22 QPen penDark;
23 QPen penLight;
24 QPen penAddRemFg;
25 QRectF rect;
26 qreal maxX;
27 qreal maxY;
28 bool hasMaxX;
29 bool hasMaxY;
30 bool hasMax;
31 bool isSaved;
32 bool showAddRem;
33 qreal invZoom;
34 qreal selMargin;
35 QRectF addRemRect;
36 qreal devicePixelRatio = 1.0;
37
38 bool addButtonEnabled = true;
39};
40
41SelectionItem::SelectionItem(const QRectF &rect) : QGraphicsItem(), d(new Private)
42{
43 d->hasMaxX = false;
44 d->hasMaxY = false;
45 d->hasMax = false;
46 setRect(rect);
47
48 d->penDark.setColor(Qt::black);
49 d->penDark.setStyle(Qt::SolidLine);
50 d->penDark.setWidth(0);
51 d->penLight.setColor(Qt::white);
52 d->penLight.setStyle(Qt::DashLine);
53 d->penLight.setWidth(0);
54
55 // FIXME We should probably use some standard KDE color here and not hard code it
56 d->penAddRemFg.setColor(Qt::darkGreen);
57 d->penAddRemFg.setStyle(Qt::SolidLine);
58 d->penAddRemFg.setWidth(3);
59
60 d->isSaved = false;
61 d->showAddRem = false;
62 d->invZoom = 1;
63 d->selMargin = selMargin;
64
65 d->addRemRect = QRectF(0, 0, 0, 0);
66
67 d->devicePixelRatio = 1.0;
68}
69
70SelectionItem::~SelectionItem()
71{
72 delete d;
73}
74
75void SelectionItem::saveZoom(qreal zoom)
76{
77 if (zoom < 0.00001) {
78 zoom = 0.00001;
79 }
80 d->invZoom = 1 / zoom;
81
82 d->selMargin = selMargin * d->invZoom;
83
84 qreal margin = addRemMargin * d->invZoom;
85 QPointF pMargin = addRemMarginPoint * d->invZoom;
86 d->addRemRect = QRectF(d->rect.center() / d->devicePixelRatio - pMargin, QSizeF(margin * 2.0, margin * 2.0));
87 d->penAddRemFg.setWidthF(3.0 * d->invZoom);
88}
89
90void SelectionItem::setSaved(bool isSaved)
91{
92 if (isSaved) {
93 d->penDark.setColor(Qt::darkBlue);
94 d->penLight.setColor(Qt::red);
95 d->penAddRemFg.setColor(Qt::darkRed);
96 d->isSaved = true;
97 } else {
98 d->penDark.setColor(Qt::black);
99 d->penLight.setColor(Qt::white);
100 d->penAddRemFg.setColor(Qt::darkGreen);
101 d->isSaved = false;
102 }
103}
104
105void SelectionItem::setMaxRight(qreal maxX)
106{
107 d->maxX = maxX;
108 d->hasMaxX = true;
109 if (d->hasMaxY) {
110 d->hasMax = true;
111 }
112}
113
114void SelectionItem::setMaxBottom(qreal maxY)
115{
116 d->maxY = maxY;
117 d->hasMaxY = true;
118 if (d->hasMaxX) {
119 d->hasMax = true;
120 }
121}
122
123SelectionItem::Intersects SelectionItem::intersects(const QPointF &point)
124{
125 bool oldState = d->showAddRem;
126 d->showAddRem = false;
127
128 if ((point.x() < (d->rect.left() - d->selMargin)) ||
129 (point.x() > (d->rect.right() + d->selMargin)) ||
130 (point.y() < (d->rect.top() - d->selMargin)) ||
131 (point.y() > (d->rect.bottom() + d->selMargin))) {
132 if (oldState != d->showAddRem) {
133 update();
134 }
135 return None;
136 }
137
138 if (point.x() < (d->rect.left() + d->selMargin)) {
139 if (oldState != d->showAddRem) {
140 update();
141 }
142 if (point.y() < (d->rect.top() + d->selMargin)) {
143 return TopLeft;
144 }
145 if (point.y() > (d->rect.bottom() - d->selMargin)) {
146 return BottomLeft;
147 }
148 return Left;
149 }
150
151 if (point.x() > (d->rect.right() - d->selMargin)) {
152 if (oldState != d->showAddRem) {
153 update();
154 }
155 if (point.y() < (d->rect.top() + d->selMargin)) {
156 return TopRight;
157 }
158 if (point.y() > (d->rect.bottom() - d->selMargin)) {
159 return BottomRight;
160 }
161 return Right;
162 }
163
164 if (point.y() < (d->rect.top() + d->selMargin)) {
165 if (oldState != d->showAddRem) {
166 update();
167 }
168 return Top;
169 }
170 if (point.y() > (d->rect.bottom() - d->selMargin)) {
171 if (oldState != d->showAddRem) {
172 update();
173 }
174 return Bottom;
175 }
176
177 d->showAddRem = d->addButtonEnabled;
178 if (oldState != d->showAddRem) {
179 update();
180 }
181
182 if (d->addButtonEnabled && d->addRemRect.contains(point / d->devicePixelRatio)) {
183 return AddRemove;
184 }
185 return Move;
186}
187
188void SelectionItem::setRect(const QRectF &rect)
189{
190 prepareGeometryChange();
191 d->rect = rect;
192 d->rect = d->rect.normalized();
193 if (d->hasMax) {
194 if (d->rect.top() < 0) {
195 d->rect.setTop(0);
196 }
197 if (d->rect.left() < 0) {
198 d->rect.setLeft(0);
199 }
200 if (d->rect.right() > d->maxX) {
201 d->rect.setRight(d->maxX);
202 }
203 if (d->rect.bottom() > d->maxY) {
204 d->rect.setBottom(d->maxY);
205 }
206 }
207
208 // calculate the add/remove rectangle
209 qreal margin = addRemMargin * d->invZoom;
210 QPointF pMargin = addRemMarginPoint * d->invZoom;
211 d->addRemRect = QRectF(d->rect.center() / d->devicePixelRatio - pMargin, QSizeF(margin * 2, margin * 2));
212}
213
214QPointF SelectionItem::fixTranslation(QPointF dp)
215{
216 if ((d->rect.left() + dp.x()) < 0) {
217 dp.setX(-d->rect.left());
218 }
219 if ((d->rect.top() + dp.y()) < 0) {
220 dp.setY(-d->rect.top());
221 }
222 if ((d->rect.right() + dp.x()) > d->maxX) {
223 dp.setX(d->maxX - d->rect.right());
224 }
225 if ((d->rect.bottom() + dp.y()) > d->maxY) {
226 dp.setY(d->maxY - d->rect.bottom());
227 }
228 return dp;
229}
230
231QRectF SelectionItem::rect()
232{
233 return d->rect;
234}
235
236qreal SelectionItem::devicePixelRatio() const
237{
238 return d->devicePixelRatio;
239}
240
241void SelectionItem::setDevicePixelRatio(qreal dpr)
242{
243 d->devicePixelRatio = dpr;
244}
245
246QRectF SelectionItem::boundingRect() const
247{
248 const auto dpr = d->devicePixelRatio;
249 QRectF tmp(d->rect.topLeft() / dpr - boundMargin, d->rect.bottomRight() / dpr + boundMargin);
250 return tmp.united(d->addRemRect);
251}
252
253void SelectionItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
254{
255 const auto dpr = d->devicePixelRatio;
256 QRectF rect(d->rect.topLeft() / dpr, d->rect.size() / dpr);
257
258 painter->setPen(d->penDark);
259 painter->drawRect(rect);
260
261 painter->setPen(d->penLight);
262 painter->drawRect(rect);
263
264 if (d->showAddRem) {
265 painter->fillRect(d->addRemRect, QBrush(Qt::white));
266 QLineF minus(d->addRemRect.left() + 3 * d->invZoom, d->addRemRect.center().y(),
267 d->addRemRect.right() - 3 * d->invZoom, d->addRemRect.center().y());
268 painter->setPen(d->penAddRemFg);
269
270 painter->drawLine(minus);
271
272 if (!d->isSaved) {
273 QLineF plus(d->addRemRect.center().x(), d->addRemRect.top() + 3 * d->invZoom,
274 d->addRemRect.center().x(), d->addRemRect.bottom() - 3 * d->invZoom);
275 painter->drawLine(plus);
276 }
277 }
278}
279
280void SelectionItem::setAddButtonEnabled(bool enabled)
281{
282 d->addButtonEnabled = enabled;
283}
284
285
286} // NameSpace KSaneIface
void update(Part *part, const QByteArray &data, qint64 dataSize)
QAction * zoom(const QObject *recvr, const char *slot, QObject *parent)
void drawLine(const QLine &line)
void drawRect(const QRect &rectangle)
void fillRect(const QRect &rectangle, QGradient::Preset preset)
void setPen(Qt::PenStyle style)
void setX(qreal x)
void setY(qreal y)
qreal x() const const
qreal y() const const
QRectF normalized() const const
SolidLine
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 17:06:01 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.