mumble-voip_mumble/src/mumble/OverlayPositionableItem.cpp

90 lines
2.8 KiB
C++

// Copyright 2015-2023 The Mumble Developers. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file at the root of the
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
#include "OverlayPositionableItem.h"
#include "Utils.h"
#include <QtCore/QEvent>
#include <QtGui/QPen>
#include <QtWidgets/QGraphicsScene>
OverlayPositionableItem::OverlayPositionableItem(QRectF *posPtr, const bool isPositionable)
: m_position(posPtr), m_isPositionEditable(isPositionable), m_qgeiHandle(nullptr) {
}
OverlayPositionableItem::~OverlayPositionableItem() {
delete m_qgeiHandle;
m_qgeiHandle = nullptr;
}
void OverlayPositionableItem::createPositioningHandle() {
m_qgeiHandle = new QGraphicsEllipseItem(QRectF(-4.0f, -4.0f, 8.0f, 8.0f));
m_qgeiHandle->setPen(QPen(Qt::darkRed, 0.0f));
m_qgeiHandle->setBrush(Qt::red);
m_qgeiHandle->setZValue(0.5f);
m_qgeiHandle->setFlag(QGraphicsItem::ItemIsMovable);
m_qgeiHandle->setFlag(QGraphicsItem::ItemIsSelectable);
scene()->addItem(m_qgeiHandle);
m_qgeiHandle->installSceneEventFilter(this);
}
bool OverlayPositionableItem::sceneEventFilter(QGraphicsItem *watched, QEvent *e) {
switch (e->type()) {
case QEvent::GraphicsSceneMouseMove:
case QEvent::GraphicsSceneMouseRelease:
QMetaObject::invokeMethod(this, "onMove", Qt::QueuedConnection);
break;
default:
break;
}
return QGraphicsItem::sceneEventFilter(watched, e);
}
void OverlayPositionableItem::onMove() {
if (!m_qgeiHandle) {
return;
}
const QRectF &sr = scene()->sceneRect();
const QPointF &p = m_qgeiHandle->pos();
m_position->setX(qBound< qreal >(0.0f, p.x() / sr.width(), 1.0f));
m_position->setY(qBound< qreal >(0.0f, p.y() / sr.height(), 1.0f));
m_qgeiHandle->setPos(m_position->x() * sr.width(), m_position->y() * sr.height());
updateRender();
}
void OverlayPositionableItem::updateRender() {
const QRectF &sr = scene()->sceneRect();
// Translate the 0..1 float position to the real scene coordinates (relative to absolute position)
QPoint absPos(static_cast< int >(sr.width() * m_position->x() + 0.5f),
static_cast< int >(sr.height() * m_position->y() + 0.5f));
if (m_isPositionEditable) {
if (!m_qgeiHandle) {
createPositioningHandle();
}
m_qgeiHandle->setPos(absPos.x(), absPos.y());
}
QRectF br = boundingRect();
// Limit the position by the elements width (to make sure it is right-/bottom-bound rather than outside of the scene
QPoint maxPos(static_cast< int >(sr.width() - br.width() + 0.5f),
static_cast< int >(sr.height() - br.height() + 0.5f));
int basex = qBound< int >(0, absPos.x(), maxPos.x());
int basey = qBound< int >(0, absPos.y(), maxPos.y());
setPos(basex, basey);
}
void OverlayPositionableItem::setItemVisible(const bool &visible) {
setVisible(visible);
if (m_qgeiHandle) {
m_qgeiHandle->setVisible(visible);
}
}