90 lines
2.8 KiB
C++
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);
|
|
}
|
|
}
|