mirror of https://github.com/qTox/qTox.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
333 lines
9.6 KiB
333 lines
9.6 KiB
/* |
|
Copyright © 2015-2019 by The qTox Project Contributors |
|
|
|
This file is part of qTox, a Qt-based graphical interface for Tox. |
|
|
|
qTox is libre software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
qTox is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with qTox. If not, see <http://www.gnu.org/licenses/>. |
|
*/ |
|
|
|
#include "screengrabberchooserrectitem.h" |
|
|
|
#include <QCursor> |
|
#include <QGraphicsScene> |
|
#include <QGraphicsSceneMouseEvent> |
|
#include <QPainter> |
|
|
|
enum |
|
{ |
|
HandleSize = 10, |
|
MinRectSize = 2, |
|
}; |
|
|
|
ScreenGrabberChooserRectItem::ScreenGrabberChooserRectItem(QGraphicsScene* scene) |
|
{ |
|
scene->addItem(this); |
|
setCursor(QCursor(Qt::OpenHandCursor)); |
|
|
|
this->mainRect = createHandleItem(scene); |
|
this->topLeft = createHandleItem(scene); |
|
this->topCenter = createHandleItem(scene); |
|
this->topRight = createHandleItem(scene); |
|
this->rightCenter = createHandleItem(scene); |
|
this->bottomRight = createHandleItem(scene); |
|
this->bottomCenter = createHandleItem(scene); |
|
this->bottomLeft = createHandleItem(scene); |
|
this->leftCenter = createHandleItem(scene); |
|
|
|
this->topLeft->setCursor(QCursor(Qt::SizeFDiagCursor)); |
|
this->bottomRight->setCursor(QCursor(Qt::SizeFDiagCursor)); |
|
this->topRight->setCursor(QCursor(Qt::SizeBDiagCursor)); |
|
this->bottomLeft->setCursor(QCursor(Qt::SizeBDiagCursor)); |
|
this->leftCenter->setCursor(QCursor(Qt::SizeHorCursor)); |
|
this->rightCenter->setCursor(QCursor(Qt::SizeHorCursor)); |
|
this->topCenter->setCursor(QCursor(Qt::SizeVerCursor)); |
|
this->bottomCenter->setCursor(QCursor(Qt::SizeVerCursor)); |
|
|
|
this->mainRect->setRect(QRect()); |
|
hideHandles(); |
|
} |
|
|
|
ScreenGrabberChooserRectItem::~ScreenGrabberChooserRectItem() |
|
{ |
|
} |
|
|
|
QRectF ScreenGrabberChooserRectItem::boundingRect() const |
|
{ |
|
return QRectF(-HandleSize - 1, -HandleSize - 1, rectWidth + HandleSize + 1, |
|
rectHeight + HandleSize + 1); |
|
} |
|
|
|
void ScreenGrabberChooserRectItem::beginResize(QPointF mousePos) |
|
{ |
|
rectWidth = this->rectHeight = 0; |
|
mainRect->setRect(QRect()); |
|
state = Resizing; |
|
startPos = mousePos; |
|
|
|
setCursor(QCursor(Qt::CrossCursor)); |
|
hideHandles(); |
|
mainRect->grabMouse(); |
|
} |
|
|
|
QRect ScreenGrabberChooserRectItem::chosenRect() const |
|
{ |
|
QRect rect(x(), y(), rectWidth, rectHeight); |
|
if (rectWidth < 0) { |
|
rect.setX(rect.x() + rectWidth); |
|
rect.setWidth(-rectWidth); |
|
} |
|
|
|
if (rectHeight < 0) { |
|
rect.setY(rect.y() + rectHeight); |
|
rect.setHeight(-rectHeight); |
|
} |
|
|
|
return rect; |
|
} |
|
|
|
void ScreenGrabberChooserRectItem::showHandles() |
|
{ |
|
this->topLeft->show(); |
|
this->topCenter->show(); |
|
this->topRight->show(); |
|
this->rightCenter->show(); |
|
this->bottomRight->show(); |
|
this->bottomCenter->show(); |
|
this->bottomLeft->show(); |
|
this->leftCenter->show(); |
|
} |
|
|
|
void ScreenGrabberChooserRectItem::hideHandles() |
|
{ |
|
this->topLeft->hide(); |
|
this->topCenter->hide(); |
|
this->topRight->hide(); |
|
this->rightCenter->hide(); |
|
this->bottomRight->hide(); |
|
this->bottomCenter->hide(); |
|
this->bottomLeft->hide(); |
|
this->leftCenter->hide(); |
|
} |
|
|
|
void ScreenGrabberChooserRectItem::mousePress(QGraphicsSceneMouseEvent* event) |
|
{ |
|
if (event->button() == Qt::LeftButton) { |
|
this->state = Moving; |
|
setCursor(QCursor(Qt::ClosedHandCursor)); |
|
} |
|
} |
|
|
|
void ScreenGrabberChooserRectItem::mouseMove(QGraphicsSceneMouseEvent* event) |
|
{ |
|
if (this->state == Moving) { |
|
QPointF delta = event->scenePos() - event->lastScenePos(); |
|
moveBy(delta.x(), delta.y()); |
|
} else if (this->state == Resizing) { |
|
prepareGeometryChange(); |
|
QPointF size = event->scenePos() - scenePos(); |
|
mainRect->setRect(0, 0, size.x(), size.y()); |
|
rectWidth = size.x(); |
|
rectHeight = size.y(); |
|
|
|
updateHandlePositions(); |
|
} else { |
|
return; |
|
} |
|
|
|
emit regionChosen(chosenRect()); |
|
} |
|
|
|
void ScreenGrabberChooserRectItem::mouseRelease(QGraphicsSceneMouseEvent* event) |
|
{ |
|
if (event->button() == Qt::LeftButton) { |
|
setCursor(QCursor(Qt::OpenHandCursor)); |
|
|
|
QPointF delta = (event->scenePos() - startPos); |
|
if (qAbs(delta.x()) < MinRectSize || qAbs(delta.y()) < MinRectSize) { |
|
rectWidth = rectHeight = 0; |
|
mainRect->setRect(QRect()); |
|
} else { |
|
QRect normalized = chosenRect(); |
|
|
|
rectWidth = normalized.width(); |
|
rectHeight = normalized.height(); |
|
setPos(normalized.x(), normalized.y()); |
|
mainRect->setRect(0, 0, rectWidth, rectHeight); |
|
|
|
updateHandlePositions(); |
|
showHandles(); |
|
} |
|
|
|
emit regionChosen(chosenRect()); |
|
state = None; |
|
mainRect->ungrabMouse(); |
|
} |
|
} |
|
|
|
void ScreenGrabberChooserRectItem::mouseDoubleClick(QGraphicsSceneMouseEvent* event) |
|
{ |
|
Q_UNUSED(event); |
|
emit doubleClicked(); |
|
} |
|
|
|
void ScreenGrabberChooserRectItem::mousePressHandle(int x, int y, QGraphicsSceneMouseEvent* event) |
|
{ |
|
Q_UNUSED(x); |
|
Q_UNUSED(y); |
|
|
|
if (event->button() == Qt::LeftButton) |
|
this->state = HandleResizing; |
|
} |
|
|
|
void ScreenGrabberChooserRectItem::mouseMoveHandle(int x, int y, QGraphicsSceneMouseEvent* event) |
|
{ |
|
if (this->state != HandleResizing) |
|
return; |
|
|
|
QPointF delta = event->scenePos() - event->lastScenePos(); |
|
delta.rx() *= qAbs(x); |
|
delta.ry() *= qAbs(y); |
|
|
|
// We increase if the multiplier and the delta have the same sign |
|
bool increaseX = ((x < 0) == (delta.x() < 0)); |
|
bool increaseY = ((y < 0) == (delta.y() < 0)); |
|
|
|
if ((delta.x() < 0 && increaseX) || (delta.x() >= 0 && !increaseX)) { |
|
moveBy(delta.x(), 0); |
|
delta.rx() *= -1; |
|
} |
|
|
|
if ((delta.y() < 0 && increaseY) || (delta.y() >= 0 && !increaseY)) { |
|
moveBy(0, delta.y()); |
|
delta.ry() *= -1; |
|
} |
|
|
|
// |
|
this->rectWidth += delta.x(); |
|
this->rectHeight += delta.y(); |
|
this->mainRect->setRect(0, 0, this->rectWidth, this->rectHeight); |
|
updateHandlePositions(); |
|
emit regionChosen(chosenRect()); |
|
} |
|
|
|
void ScreenGrabberChooserRectItem::mouseReleaseHandle(int x, int y, QGraphicsSceneMouseEvent* event) |
|
{ |
|
Q_UNUSED(x); |
|
Q_UNUSED(y); |
|
|
|
if (event->button() == Qt::LeftButton) |
|
this->state = None; |
|
} |
|
|
|
QPoint ScreenGrabberChooserRectItem::getHandleMultiplier(QGraphicsItem* handle) |
|
{ |
|
if (handle == this->topLeft) |
|
return QPoint(-1, -1); |
|
|
|
if (handle == this->topCenter) |
|
return QPoint(0, -1); |
|
|
|
if (handle == this->topRight) |
|
return QPoint(1, -1); |
|
|
|
if (handle == this->rightCenter) |
|
return QPoint(1, 0); |
|
|
|
if (handle == this->bottomRight) |
|
return QPoint(1, 1); |
|
|
|
if (handle == this->bottomCenter) |
|
return QPoint(0, 1); |
|
|
|
if (handle == this->bottomLeft) |
|
return QPoint(-1, 1); |
|
|
|
if (handle == this->leftCenter) |
|
return QPoint(-1, 0); |
|
|
|
return QPoint(); |
|
} |
|
|
|
void ScreenGrabberChooserRectItem::updateHandlePositions() |
|
{ |
|
this->topLeft->setPos(-HandleSize, -HandleSize); |
|
this->topCenter->setPos((this->rectWidth - HandleSize) / 2, -HandleSize); |
|
this->topRight->setPos(this->rectWidth, -HandleSize); |
|
this->rightCenter->setPos(this->rectWidth, (this->rectHeight - HandleSize) / 2); |
|
this->bottomRight->setPos(this->rectWidth, this->rectHeight); |
|
this->bottomCenter->setPos((this->rectWidth - HandleSize) / 2, this->rectHeight); |
|
this->bottomLeft->setPos(-HandleSize, this->rectHeight); |
|
this->leftCenter->setPos(-HandleSize, (this->rectHeight - HandleSize) / 2); |
|
} |
|
|
|
QGraphicsRectItem* ScreenGrabberChooserRectItem::createHandleItem(QGraphicsScene* scene) |
|
{ |
|
QGraphicsRectItem* handle = new QGraphicsRectItem(0, 0, HandleSize, HandleSize); |
|
handle->setPen(QPen(Qt::blue)); |
|
handle->setBrush(Qt::NoBrush); |
|
|
|
scene->addItem(handle); |
|
addToGroup(handle); |
|
|
|
handle->installSceneEventFilter(this); |
|
return handle; |
|
} |
|
|
|
bool ScreenGrabberChooserRectItem::sceneEventFilter(QGraphicsItem* watched, QEvent* event) |
|
{ |
|
if (watched == this->mainRect) |
|
forwardMainRectEvent(event); |
|
else |
|
forwardHandleEvent(watched, event); |
|
|
|
return true; |
|
} |
|
|
|
void ScreenGrabberChooserRectItem::forwardMainRectEvent(QEvent* event) |
|
{ |
|
QGraphicsSceneMouseEvent* mouseEvent = static_cast<QGraphicsSceneMouseEvent*>(event); |
|
|
|
switch (event->type()) { |
|
case QEvent::GraphicsSceneMousePress: |
|
return mousePress(mouseEvent); |
|
case QEvent::GraphicsSceneMouseMove: |
|
return mouseMove(mouseEvent); |
|
case QEvent::GraphicsSceneMouseRelease: |
|
return mouseRelease(mouseEvent); |
|
case QEvent::GraphicsSceneMouseDoubleClick: |
|
return mouseDoubleClick(mouseEvent); |
|
default: |
|
return; |
|
} |
|
} |
|
|
|
void ScreenGrabberChooserRectItem::forwardHandleEvent(QGraphicsItem* watched, QEvent* event) |
|
{ |
|
QGraphicsSceneMouseEvent* mouseEvent = static_cast<QGraphicsSceneMouseEvent*>(event); |
|
QPoint multiplier = getHandleMultiplier(watched); |
|
|
|
if (multiplier.isNull()) |
|
return; |
|
|
|
switch (event->type()) { |
|
case QEvent::GraphicsSceneMousePress: |
|
return mousePressHandle(multiplier.x(), multiplier.y(), mouseEvent); |
|
case QEvent::GraphicsSceneMouseMove: |
|
return mouseMoveHandle(multiplier.x(), multiplier.y(), mouseEvent); |
|
case QEvent::GraphicsSceneMouseRelease: |
|
return mouseReleaseHandle(multiplier.x(), multiplier.y(), mouseEvent); |
|
default: |
|
return; |
|
} |
|
}
|
|
|