1 // Copyright 2005-2019 The Mumble Developers. All rights reserved.
2 // Use of this source code is governed by a BSD-style license
3 // that can be found in the LICENSE file at the root of the
4 // Mumble source tree or at <https://www.mumble.info/LICENSE>.
5
6 #include "mumble_pch.hpp"
7
8 #include "OverlayPositionableItem.h"
9
OverlayPositionableItem(QRectF * posPtr,const bool isPositionable)10 OverlayPositionableItem::OverlayPositionableItem(QRectF *posPtr, const bool isPositionable)
11 : m_position(posPtr)
12 , m_isPositionEditable(isPositionable)
13 , m_qgeiHandle(NULL) {
14 }
15
~OverlayPositionableItem()16 OverlayPositionableItem::~OverlayPositionableItem() {
17 delete m_qgeiHandle;
18 m_qgeiHandle = NULL;
19 }
20
createPositioningHandle()21 void OverlayPositionableItem::createPositioningHandle() {
22 m_qgeiHandle = new QGraphicsEllipseItem(QRectF(-4.0f, -4.0f, 8.0f, 8.0f));
23 m_qgeiHandle->setPen(QPen(Qt::darkRed, 0.0f));
24 m_qgeiHandle->setBrush(Qt::red);
25 m_qgeiHandle->setZValue(0.5f);
26 m_qgeiHandle->setFlag(QGraphicsItem::ItemIsMovable);
27 m_qgeiHandle->setFlag(QGraphicsItem::ItemIsSelectable);
28 scene()->addItem(m_qgeiHandle);
29 m_qgeiHandle->installSceneEventFilter(this);
30 }
31
sceneEventFilter(QGraphicsItem * watched,QEvent * e)32 bool OverlayPositionableItem::sceneEventFilter(QGraphicsItem *watched, QEvent *e) {
33 switch (e->type()) {
34 case QEvent::GraphicsSceneMouseMove:
35 case QEvent::GraphicsSceneMouseRelease:
36 QMetaObject::invokeMethod(this, "onMove", Qt::QueuedConnection);
37 break;
38 default:
39 break;
40 }
41 return QGraphicsItem::sceneEventFilter(watched, e);
42 }
43
onMove()44 void OverlayPositionableItem::onMove() {
45 if (m_qgeiHandle == NULL) {
46 return;
47 }
48
49 const QRectF &sr = scene()->sceneRect();
50 const QPointF &p = m_qgeiHandle->pos();
51
52 m_position->setX(qBound<qreal>(0.0f, p.x() / sr.width(), 1.0f));
53 m_position->setY(qBound<qreal>(0.0f, p.y() / sr.height(), 1.0f));
54
55 m_qgeiHandle->setPos(m_position->x() * sr.width(), m_position->y() * sr.height());
56
57 updateRender();
58 }
59
updateRender()60 void OverlayPositionableItem::updateRender() {
61 const QRectF &sr = scene()->sceneRect();
62 // Translate the 0..1 float position to the real scene coordinates (relative to absolute position)
63 QPoint absPos(iroundf(sr.width() * m_position->x() + 0.5f), iroundf(sr.height() * m_position->y() + 0.5f));
64
65 if (m_isPositionEditable) {
66 if (m_qgeiHandle == NULL) {
67 createPositioningHandle();
68 }
69 m_qgeiHandle->setPos(absPos.x(), absPos.y());
70 }
71
72 QRectF br = boundingRect();
73 // Limit the position by the elements width (to make sure it is right-/bottom-bound rather than outside of the scene
74 QPoint maxPos(iroundf(sr.width() - br.width() + 0.5f), iroundf(sr.height() - br.height() + 0.5f));
75 int basex = qBound<int>(0, absPos.x(), maxPos.x());
76 int basey = qBound<int>(0, absPos.y(), maxPos.y());
77 setPos(basex, basey);
78 }
79
setItemVisible(const bool & visible)80 void OverlayPositionableItem::setItemVisible(const bool &visible) {
81 setVisible(visible);
82 if (m_qgeiHandle != NULL) {
83 m_qgeiHandle->setVisible(visible);
84 }
85 }
86