qTox  Version: nightly | Commit: bc751c8e1cac455f9690654fcfe0f560d2d7dfdd
screengrabberchooserrectitem.cpp
Go to the documentation of this file.
1 /*
2  Copyright © 2015-2019 by The qTox Project Contributors
3 
4  This file is part of qTox, a Qt-based graphical interface for Tox.
5 
6  qTox is libre software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  qTox is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with qTox. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
21 
22 #include <QCursor>
23 #include <QGraphicsScene>
24 #include <QGraphicsSceneMouseEvent>
25 #include <QPainter>
26 
27 enum
28 {
29  HandleSize = 10,
31 };
32 
34 {
35  scene->addItem(this);
36  setCursor(QCursor(Qt::OpenHandCursor));
37 
38  this->mainRect = createHandleItem(scene);
39  this->topLeft = createHandleItem(scene);
40  this->topCenter = createHandleItem(scene);
41  this->topRight = createHandleItem(scene);
42  this->rightCenter = createHandleItem(scene);
43  this->bottomRight = createHandleItem(scene);
44  this->bottomCenter = createHandleItem(scene);
45  this->bottomLeft = createHandleItem(scene);
46  this->leftCenter = createHandleItem(scene);
47 
48  this->topLeft->setCursor(QCursor(Qt::SizeFDiagCursor));
49  this->bottomRight->setCursor(QCursor(Qt::SizeFDiagCursor));
50  this->topRight->setCursor(QCursor(Qt::SizeBDiagCursor));
51  this->bottomLeft->setCursor(QCursor(Qt::SizeBDiagCursor));
52  this->leftCenter->setCursor(QCursor(Qt::SizeHorCursor));
53  this->rightCenter->setCursor(QCursor(Qt::SizeHorCursor));
54  this->topCenter->setCursor(QCursor(Qt::SizeVerCursor));
55  this->bottomCenter->setCursor(QCursor(Qt::SizeVerCursor));
56 
57  this->mainRect->setRect(QRect());
58  hideHandles();
59 }
60 
62 {
63 }
64 
66 {
67  return QRectF(-HandleSize - 1, -HandleSize - 1, rectWidth + HandleSize + 1,
68  rectHeight + HandleSize + 1);
69 }
70 
72 {
73  rectWidth = this->rectHeight = 0;
74  mainRect->setRect(QRect());
75  state = Resizing;
76  startPos = mousePos;
77 
78  setCursor(QCursor(Qt::CrossCursor));
79  hideHandles();
80  mainRect->grabMouse();
81 }
82 
84 {
85  QRect rect(x(), y(), rectWidth, rectHeight);
86  if (rectWidth < 0) {
87  rect.setX(rect.x() + rectWidth);
88  rect.setWidth(-rectWidth);
89  }
90 
91  if (rectHeight < 0) {
92  rect.setY(rect.y() + rectHeight);
93  rect.setHeight(-rectHeight);
94  }
95 
96  return rect;
97 }
98 
100 {
101  this->topLeft->show();
102  this->topCenter->show();
103  this->topRight->show();
104  this->rightCenter->show();
105  this->bottomRight->show();
106  this->bottomCenter->show();
107  this->bottomLeft->show();
108  this->leftCenter->show();
109 }
110 
112 {
113  this->topLeft->hide();
114  this->topCenter->hide();
115  this->topRight->hide();
116  this->rightCenter->hide();
117  this->bottomRight->hide();
118  this->bottomCenter->hide();
119  this->bottomLeft->hide();
120  this->leftCenter->hide();
121 }
122 
123 void ScreenGrabberChooserRectItem::mousePress(QGraphicsSceneMouseEvent* event)
124 {
125  if (event->button() == Qt::LeftButton) {
126  this->state = Moving;
127  setCursor(QCursor(Qt::ClosedHandCursor));
128  }
129 }
130 
131 void ScreenGrabberChooserRectItem::mouseMove(QGraphicsSceneMouseEvent* event)
132 {
133  if (this->state == Moving) {
134  QPointF delta = event->scenePos() - event->lastScenePos();
135  moveBy(delta.x(), delta.y());
136  } else if (this->state == Resizing) {
137  prepareGeometryChange();
138  QPointF size = event->scenePos() - scenePos();
139  mainRect->setRect(0, 0, size.x(), size.y());
140  rectWidth = size.x();
141  rectHeight = size.y();
142 
144  } else {
145  return;
146  }
147 
148  emit regionChosen(chosenRect());
149 }
150 
151 void ScreenGrabberChooserRectItem::mouseRelease(QGraphicsSceneMouseEvent* event)
152 {
153  if (event->button() == Qt::LeftButton) {
154  setCursor(QCursor(Qt::OpenHandCursor));
155 
156  QPointF delta = (event->scenePos() - startPos);
157  if (qAbs(delta.x()) < MinRectSize || qAbs(delta.y()) < MinRectSize) {
158  rectWidth = rectHeight = 0;
159  mainRect->setRect(QRect());
160  } else {
161  QRect normalized = chosenRect();
162 
163  rectWidth = normalized.width();
164  rectHeight = normalized.height();
165  setPos(normalized.x(), normalized.y());
166  mainRect->setRect(0, 0, rectWidth, rectHeight);
167 
169  showHandles();
170  }
171 
172  emit regionChosen(chosenRect());
173  state = None;
174  mainRect->ungrabMouse();
175  }
176 }
177 
178 void ScreenGrabberChooserRectItem::mouseDoubleClick(QGraphicsSceneMouseEvent* event)
179 {
180  Q_UNUSED(event)
181  emit doubleClicked();
182 }
183 
184 void ScreenGrabberChooserRectItem::mousePressHandle(int x, int y, QGraphicsSceneMouseEvent* event)
185 {
186  Q_UNUSED(x)
187  Q_UNUSED(y)
188 
189  if (event->button() == Qt::LeftButton)
190  this->state = HandleResizing;
191 }
192 
193 void ScreenGrabberChooserRectItem::mouseMoveHandle(int x, int y, QGraphicsSceneMouseEvent* event)
194 {
195  if (this->state != HandleResizing)
196  return;
197 
198  QPointF delta = event->scenePos() - event->lastScenePos();
199  delta.rx() *= qAbs(x);
200  delta.ry() *= qAbs(y);
201 
202  // We increase if the multiplier and the delta have the same sign
203  bool increaseX = ((x < 0) == (delta.x() < 0));
204  bool increaseY = ((y < 0) == (delta.y() < 0));
205 
206  if ((delta.x() < 0 && increaseX) || (delta.x() >= 0 && !increaseX)) {
207  moveBy(delta.x(), 0);
208  delta.rx() *= -1;
209  }
210 
211  if ((delta.y() < 0 && increaseY) || (delta.y() >= 0 && !increaseY)) {
212  moveBy(0, delta.y());
213  delta.ry() *= -1;
214  }
215 
216  //
217  this->rectWidth += delta.x();
218  this->rectHeight += delta.y();
219  this->mainRect->setRect(0, 0, this->rectWidth, this->rectHeight);
221  emit regionChosen(chosenRect());
222 }
223 
224 void ScreenGrabberChooserRectItem::mouseReleaseHandle(int x, int y, QGraphicsSceneMouseEvent* event)
225 {
226  Q_UNUSED(x)
227  Q_UNUSED(y)
228 
229  if (event->button() == Qt::LeftButton)
230  this->state = None;
231 }
232 
234 {
235  if (handle == this->topLeft)
236  return QPoint(-1, -1);
237 
238  if (handle == this->topCenter)
239  return QPoint(0, -1);
240 
241  if (handle == this->topRight)
242  return QPoint(1, -1);
243 
244  if (handle == this->rightCenter)
245  return QPoint(1, 0);
246 
247  if (handle == this->bottomRight)
248  return QPoint(1, 1);
249 
250  if (handle == this->bottomCenter)
251  return QPoint(0, 1);
252 
253  if (handle == this->bottomLeft)
254  return QPoint(-1, 1);
255 
256  if (handle == this->leftCenter)
257  return QPoint(-1, 0);
258 
259  return QPoint();
260 }
261 
263 {
264  this->topLeft->setPos(-HandleSize, -HandleSize);
265  this->topCenter->setPos((this->rectWidth - HandleSize) / 2, -HandleSize);
266  this->topRight->setPos(this->rectWidth, -HandleSize);
267  this->rightCenter->setPos(this->rectWidth, (this->rectHeight - HandleSize) / 2);
268  this->bottomRight->setPos(this->rectWidth, this->rectHeight);
269  this->bottomCenter->setPos((this->rectWidth - HandleSize) / 2, this->rectHeight);
270  this->bottomLeft->setPos(-HandleSize, this->rectHeight);
271  this->leftCenter->setPos(-HandleSize, (this->rectHeight - HandleSize) / 2);
272 }
273 
274 QGraphicsRectItem* ScreenGrabberChooserRectItem::createHandleItem(QGraphicsScene* scene)
275 {
276  QGraphicsRectItem* handle = new QGraphicsRectItem(0, 0, HandleSize, HandleSize);
277  handle->setPen(QPen(Qt::blue));
278  handle->setBrush(Qt::NoBrush);
279 
280  scene->addItem(handle);
281  addToGroup(handle);
282 
283  handle->installSceneEventFilter(this);
284  return handle;
285 }
286 
287 bool ScreenGrabberChooserRectItem::sceneEventFilter(QGraphicsItem* watched, QEvent* event)
288 {
289  if (watched == this->mainRect)
290  forwardMainRectEvent(event);
291  else
292  forwardHandleEvent(watched, event);
293 
294  return true;
295 }
296 
298 {
299  QGraphicsSceneMouseEvent* mouseEvent = static_cast<QGraphicsSceneMouseEvent*>(event);
300 
301  switch (event->type()) {
302  case QEvent::GraphicsSceneMousePress:
303  return mousePress(mouseEvent);
304  case QEvent::GraphicsSceneMouseMove:
305  return mouseMove(mouseEvent);
306  case QEvent::GraphicsSceneMouseRelease:
307  return mouseRelease(mouseEvent);
308  case QEvent::GraphicsSceneMouseDoubleClick:
309  return mouseDoubleClick(mouseEvent);
310  default:
311  return;
312  }
313 }
314 
315 void ScreenGrabberChooserRectItem::forwardHandleEvent(QGraphicsItem* watched, QEvent* event)
316 {
317  QGraphicsSceneMouseEvent* mouseEvent = static_cast<QGraphicsSceneMouseEvent*>(event);
318  QPoint multiplier = getHandleMultiplier(watched);
319 
320  if (multiplier.isNull())
321  return;
322 
323  switch (event->type()) {
324  case QEvent::GraphicsSceneMousePress:
325  return mousePressHandle(multiplier.x(), multiplier.y(), mouseEvent);
326  case QEvent::GraphicsSceneMouseMove:
327  return mouseMoveHandle(multiplier.x(), multiplier.y(), mouseEvent);
328  case QEvent::GraphicsSceneMouseRelease:
329  return mouseReleaseHandle(multiplier.x(), multiplier.y(), mouseEvent);
330  default:
331  return;
332  }
333 }
ScreenGrabberChooserRectItem::rightCenter
QGraphicsRectItem * rightCenter
Definition: screengrabberchooserrectitem.h:82
ScreenGrabberChooserRectItem::bottomCenter
QGraphicsRectItem * bottomCenter
Definition: screengrabberchooserrectitem.h:84
ScreenGrabberChooserRectItem::topRight
QGraphicsRectItem * topRight
Definition: screengrabberchooserrectitem.h:81
ScreenGrabberChooserRectItem::None
@ None
Definition: screengrabberchooserrectitem.h:50
ScreenGrabberChooserRectItem::topLeft
QGraphicsRectItem * topLeft
Definition: screengrabberchooserrectitem.h:79
ScreenGrabberChooserRectItem::mouseMoveHandle
void mouseMoveHandle(int x, int y, QGraphicsSceneMouseEvent *event)
Definition: screengrabberchooserrectitem.cpp:193
ScreenGrabberChooserRectItem::Moving
@ Moving
Definition: screengrabberchooserrectitem.h:53
ScreenGrabberChooserRectItem::mousePressHandle
void mousePressHandle(int x, int y, QGraphicsSceneMouseEvent *event)
Definition: screengrabberchooserrectitem.cpp:184
ScreenGrabberChooserRectItem::hideHandles
void hideHandles()
Definition: screengrabberchooserrectitem.cpp:111
ScreenGrabberChooserRectItem::ScreenGrabberChooserRectItem
ScreenGrabberChooserRectItem(QGraphicsScene *scene)
Definition: screengrabberchooserrectitem.cpp:33
MinRectSize
@ MinRectSize
Definition: screengrabberchooserrectitem.cpp:30
ScreenGrabberChooserRectItem::chosenRect
QRect chosenRect() const
Definition: screengrabberchooserrectitem.cpp:83
ScreenGrabberChooserRectItem::sceneEventFilter
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) final
Definition: screengrabberchooserrectitem.cpp:287
ScreenGrabberChooserRectItem::rectHeight
int rectHeight
Definition: screengrabberchooserrectitem.h:58
ScreenGrabberChooserRectItem::mouseReleaseHandle
void mouseReleaseHandle(int x, int y, QGraphicsSceneMouseEvent *event)
Definition: screengrabberchooserrectitem.cpp:224
ScreenGrabberChooserRectItem::bottomRight
QGraphicsRectItem * bottomRight
Definition: screengrabberchooserrectitem.h:83
ScreenGrabberChooserRectItem::boundingRect
QRectF boundingRect() const final
Definition: screengrabberchooserrectitem.cpp:65
ScreenGrabberChooserRectItem::doubleClicked
void doubleClicked()
ScreenGrabberChooserRectItem::forwardMainRectEvent
void forwardMainRectEvent(QEvent *event)
Definition: screengrabberchooserrectitem.cpp:297
ScreenGrabberChooserRectItem::Resizing
@ Resizing
Definition: screengrabberchooserrectitem.h:51
ScreenGrabberChooserRectItem::mouseRelease
void mouseRelease(QGraphicsSceneMouseEvent *event)
Definition: screengrabberchooserrectitem.cpp:151
ScreenGrabberChooserRectItem::mouseDoubleClick
void mouseDoubleClick(QGraphicsSceneMouseEvent *event)
Definition: screengrabberchooserrectitem.cpp:178
ScreenGrabberChooserRectItem::leftCenter
QGraphicsRectItem * leftCenter
Definition: screengrabberchooserrectitem.h:86
ScreenGrabberChooserRectItem::updateHandlePositions
void updateHandlePositions()
Definition: screengrabberchooserrectitem.cpp:262
ScreenGrabberChooserRectItem::mouseMove
void mouseMove(QGraphicsSceneMouseEvent *event)
Definition: screengrabberchooserrectitem.cpp:131
ScreenGrabberChooserRectItem::state
State state
Definition: screengrabberchooserrectitem.h:56
ScreenGrabberChooserRectItem::bottomLeft
QGraphicsRectItem * bottomLeft
Definition: screengrabberchooserrectitem.h:85
ScreenGrabberChooserRectItem::createHandleItem
QGraphicsRectItem * createHandleItem(QGraphicsScene *scene)
Definition: screengrabberchooserrectitem.cpp:274
ScreenGrabberChooserRectItem::mousePress
void mousePress(QGraphicsSceneMouseEvent *event)
Definition: screengrabberchooserrectitem.cpp:123
ScreenGrabberChooserRectItem::forwardHandleEvent
void forwardHandleEvent(QGraphicsItem *watched, QEvent *event)
Definition: screengrabberchooserrectitem.cpp:315
ScreenGrabberChooserRectItem::showHandles
void showHandles()
Definition: screengrabberchooserrectitem.cpp:99
ScreenGrabberChooserRectItem::mainRect
QGraphicsRectItem * mainRect
Definition: screengrabberchooserrectitem.h:78
ScreenGrabberChooserRectItem::startPos
QPointF startPos
Definition: screengrabberchooserrectitem.h:59
screengrabberchooserrectitem.h
ScreenGrabberChooserRectItem::~ScreenGrabberChooserRectItem
~ScreenGrabberChooserRectItem()
Definition: screengrabberchooserrectitem.cpp:61
ScreenGrabberChooserRectItem::topCenter
QGraphicsRectItem * topCenter
Definition: screengrabberchooserrectitem.h:80
ScreenGrabberChooserRectItem::getHandleMultiplier
QPoint getHandleMultiplier(QGraphicsItem *handle)
Definition: screengrabberchooserrectitem.cpp:233
ScreenGrabberChooserRectItem::beginResize
void beginResize(QPointF mousePos)
Definition: screengrabberchooserrectitem.cpp:71
ScreenGrabberChooserRectItem::HandleResizing
@ HandleResizing
Definition: screengrabberchooserrectitem.h:52
ScreenGrabberChooserRectItem::regionChosen
void regionChosen(QRect rect)
ScreenGrabberChooserRectItem::rectWidth
int rectWidth
Definition: screengrabberchooserrectitem.h:57
HandleSize
@ HandleSize
Definition: screengrabberchooserrectitem.cpp:29