Skip to content

Commit

Permalink
Make overlay FPS and clock positionable
Browse files Browse the repository at this point in the history
* Implement #1068, making the FPS and clock in the overlay positionable
like our user-block

* Introduce class OverlayPositionableItem to generalize our red
draggable anchor to set the position in the overlay settings
** Has a configuration and a display mode; with and without the anchor
** Receives a pointer to the position setting

The fps position was already set up to save, the timer not.
Use storage names according to the show flags ("time" rather than
"clock").

The anchor ("handle") and text-item are added to the scene as independant
objects to allow moving the anchor to the bottom/right, at which point
the item is prevented from bleeding over the edge (so a linked movement
of individual items with custom behavior at the right/bottom edge case).

Additional Notes:

Using relative values for positioning, the default values are best-effort
values. The space between the items (the top value of the FPS) will differ
between different screen/scene sizes.

The position is saved as a rectangle, even though a point would be enough.

Handling of visibility is sub-optimal, but works. (As we use two
independent, linked items, we have to implement our own setVisible
method, and currently only call in OverlayConfig (when using config
mode).

It looks like the overlaytext used to create a text pixmap could be
replaced by QGraphicsTextItem.
  • Loading branch information
Kissaki committed Oct 11, 2015
1 parent f732ec4 commit 8bf9b0a
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 21 deletions.
8 changes: 5 additions & 3 deletions src/mumble/OverlayClient.cpp
Expand Up @@ -31,7 +31,7 @@
#include "mumble_pch.hpp"

#include "OverlayClient.h"

#include "OverlayPositionableItem.h"
#include "OverlayEditor.h"
#include "OverlayText.h"
#include "User.h"
Expand Down Expand Up @@ -80,13 +80,13 @@ OverlayClient::OverlayClient(QLocalSocket *socket, QObject *p)
qgs.addItem(&ougUsers);
ougUsers.show();

qgpiFPS = new QGraphicsPixmapItem();
qgpiFPS = new OverlayPositionableItem(&g.s.os.qrfFps);
qgs.addItem(qgpiFPS);
qgpiFPS->setPos(g.s.os.qrfFps.x(), g.s.os.qrfFps.y());
qgpiFPS->show();

// Time
qgpiTime = new QGraphicsPixmapItem();
qgpiTime = new OverlayPositionableItem(&g.s.os.qrfTime);
qgs.addItem(qgpiTime);
qgpiTime->setPos(g.s.os.qrfTime.x(), g.s.os.qrfTime.y());
qgpiTime->show();
Expand Down Expand Up @@ -130,6 +130,7 @@ void OverlayClient::updateFPS() {
// offset to use basepoint
//TODO: settings are providing a top left anchor, so shift down by ascent
qgpiFPS->setOffset(-pm.qpBasePoint + QPoint(0, pm.iAscent));
qgpiFPS->updateRender();
} else {
qgpiFPS->setPixmap(QPixmap());
}
Expand All @@ -140,6 +141,7 @@ void OverlayClient::updateTime() {
const BasepointPixmap &pm = OverlayTextLine(QString(QLatin1String("%1")).arg(QTime::currentTime().toString()), g.s.os.qfFps).createPixmap(g.s.os.qcFps);
qgpiTime->setPixmap(pm);
qgpiTime->setOffset(-pm.qpBasePoint + QPoint(0, pm.iAscent));
qgpiTime->updateRender();
} else {
qgpiTime->setPixmap(QPixmap());
}
Expand Down
5 changes: 3 additions & 2 deletions src/mumble/OverlayClient.h
Expand Up @@ -43,6 +43,7 @@ class ClientUser;
class Overlay;
class QLibrary;
class QLocalServer;
class OverlayPositionableItem;

class OverlayClient : public QObject {
friend class Overlay;
Expand All @@ -60,8 +61,8 @@ class OverlayClient : public QObject {
int iOffsetX, iOffsetY;
QGraphicsPixmapItem *qgpiCursor;
QGraphicsPixmapItem *qgpiLogo;
QGraphicsPixmapItem *qgpiFPS;
QGraphicsPixmapItem *qgpiTime;
OverlayPositionableItem *qgpiFPS;
OverlayPositionableItem *qgpiTime;

/// The process ID of the process this OverlayClient is connected to.
quint64 uiPid;
Expand Down
31 changes: 21 additions & 10 deletions src/mumble/OverlayConfig.cpp
Expand Up @@ -34,6 +34,7 @@

#include "Overlay.h"
#include "OverlayUserGroup.h"
#include "OverlayPositionableItem.h"
#include "OverlayText.h"
#include "User.h"
#include "Channel.h"
Expand All @@ -58,7 +59,7 @@ static ConfigWidget *OverlayConfigDialogNew(Settings &st) {
static ConfigRegistrar registrar(6000, OverlayConfigDialogNew);
#endif

void OverlayConfig::initDisplay() {
void OverlayConfig::initDisplayFps() {
// set up FPS preview
qgsFpsPreview.clear();
qgsFpsPreview.setBackgroundBrush(qgvFpsPreview->backgroundBrush());
Expand All @@ -72,18 +73,26 @@ void OverlayConfig::initDisplay() {
qgvFpsPreview->setScene(&qgsFpsPreview);
qgvFpsPreview->centerOn(qgpiFpsDemo);

qgpiFpsLive = new OverlayPositionableItem(&s.os.qrfFps, true);
qgpiFpsLive->setZValue(-2.0f);
refreshFpsLive();
}

void OverlayConfig::initDisplayClock() {
qgpiTimeLive = new OverlayPositionableItem(&s.os.qrfTime, true);
qgpiTimeLive->setZValue(-2.0f);
refreshTimeLive();
}

void OverlayConfig::initDisplay() {
// set up overlay preview
qgpiScreen = new QGraphicsPixmapItem();
qgpiScreen->setPixmap(qpScreen);
qgpiScreen->setOpacity(0.5f);
qgpiScreen->setZValue(-10.0f);

qgpiFpsLive = new QGraphicsPixmapItem();
qgpiFpsLive->setZValue(-2.0f);
qgpiTimeLive = new QGraphicsPixmapItem();
qgpiTimeLive->setZValue(-2.0f);
refreshFpsLive();
refreshTimeLive();
initDisplayFps();
initDisplayClock();

qgtiInstructions = new QGraphicsTextItem();
qgtiInstructions->setHtml(QString::fromLatin1("<ul><li>%1</li><li>%2</li><li>%3</li></ul>").arg(
Expand Down Expand Up @@ -129,24 +138,23 @@ void OverlayConfig::refreshFpsDemo() {

void OverlayConfig::refreshFpsLive() {
if (s.os.bFps) {
qgpiFpsLive->setPos(s.os.qrfFps.topLeft() * fViewScale);
qgpiFpsLive->setPixmap(bpFpsDemo.scaled(bpFpsDemo.size() * fViewScale));
qgpiFpsLive->setOffset((-bpFpsDemo.qpBasePoint + QPoint(0, bpFpsDemo.iAscent)) * fViewScale);
} else {
qgpiFpsLive->setPixmap(QPixmap());
}
qgpiFpsLive->setItemVisible(s.os.bFps);
}

void OverlayConfig::refreshTimeLive() {
if (s.os.bTime) {
bpTimeDemo = OverlayTextLine(QString::fromLatin1("%1").arg(QTime::currentTime().toString()), s.os.qfFps).createPixmap(s.os.qcFps);
qgpiTimeLive->setPixmap(bpTimeDemo);
qgpiTimeLive->setPos(s.os.qrfTime.topLeft() * fViewScale);
qgpiTimeLive->setPixmap(bpTimeDemo.scaled(bpTimeDemo.size() * fViewScale));
qgpiTimeLive->setOffset((-bpTimeDemo.qpBasePoint + QPoint(0, bpTimeDemo.iAscent)) * fViewScale);
} else {
qgpiTimeLive->setPixmap(QPixmap());
}
qgpiTimeLive->setItemVisible(s.os.bTime);
}

OverlayConfig::OverlayConfig(Settings &st) :
Expand Down Expand Up @@ -429,6 +437,9 @@ void OverlayConfig::resizeScene(bool force) {
qgvView->fitInView(qgs.sceneRect(), Qt::KeepAspectRatio);
oug->updateLayout();
oug->updateUsers();

qgpiFpsLive->updateRender();
qgpiTimeLive->updateRender();
}

void OverlayConfig::on_qpbAdd_clicked() {
Expand Down
7 changes: 5 additions & 2 deletions src/mumble/OverlayConfig.h
Expand Up @@ -38,13 +38,16 @@

class OverlayUserGroup;
struct OverlayAppInfo;
class OverlayPositionableItem;

class OverlayConfig : public ConfigWidget, public Ui::OverlayConfig {
private:
Q_OBJECT
Q_DISABLE_COPY(OverlayConfig)

void initDisplay();
void initDisplayFps();
void initDisplayClock();
void refreshFpsDemo();
void refreshFpsLive();
void refreshTimeLive();
Expand All @@ -56,8 +59,8 @@ class OverlayConfig : public ConfigWidget, public Ui::OverlayConfig {
BasepointPixmap bpFpsDemo;
BasepointPixmap bpTimeDemo;
QGraphicsPixmapItem *qgpiFpsDemo;
QGraphicsPixmapItem *qgpiFpsLive;
QGraphicsPixmapItem *qgpiTimeLive;
OverlayPositionableItem *qgpiFpsLive;
OverlayPositionableItem *qgpiTimeLive;
OverlayUserGroup *oug;
QGraphicsTextItem *qgtiInstructions;

Expand Down
81 changes: 81 additions & 0 deletions src/mumble/OverlayPositionableItem.cpp
@@ -0,0 +1,81 @@

#include "mumble_pch.hpp"

#include "OverlayPositionableItem.h"

OverlayPositionableItem::OverlayPositionableItem(QRectF *posPtr, const bool isPositionable)
: m_position(posPtr)
, m_isPositionEditable(isPositionable)
, m_qgeiHandle(NULL) {
}

OverlayPositionableItem::~OverlayPositionableItem() {
delete m_qgeiHandle;
m_qgeiHandle = NULL;
}

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 *event ) {
switch (event->type()) {
case QEvent::GraphicsSceneMouseMove:
case QEvent::GraphicsSceneMouseRelease:
QMetaObject::invokeMethod(this, "onMove", Qt::QueuedConnection);
break;
default:
break;
}
return QGraphicsItem::sceneEventFilter(watched, event);
}

void OverlayPositionableItem::onMove() {
if (m_qgeiHandle == NULL) {
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(iroundf(sr.width() * m_position->x() + 0.5f), iroundf(sr.height() * m_position->y() + 0.5f));

if (m_isPositionEditable) {
if (m_qgeiHandle == NULL) {
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(iroundf(sr.width() - br.width() + 0.5f), iroundf(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 != NULL) {
m_qgeiHandle->setVisible(visible);
}
}
29 changes: 29 additions & 0 deletions src/mumble/OverlayPositionableItem.h
@@ -0,0 +1,29 @@
#ifndef MUMBLE_MUMBLE_OVERLAYPOSITIONABLEITEM_H
#define MUMBLE_MUMBLE_OVERLAYPOSITIONABLEITEM_H

#if QT_VERSION >= 0x050000
# include <QtWidgets/QGraphicsItem>
#else
# include <QtGui/QGraphicsItem>
#endif

class OverlayPositionableItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT
Q_DISABLE_COPY(OverlayPositionableItem);
public:
OverlayPositionableItem(QRectF *posPtr, const bool isPositionable=false);
virtual ~OverlayPositionableItem();
void updateRender();
void setItemVisible(const bool &visible);
private:
const bool m_isPositionEditable;
/// Float value between 0 and 1 where 0,0 is top left, and 1,1 is bottom right
QRectF *m_position;
QGraphicsEllipseItem *m_qgeiHandle;
void createPositioningHandle();
bool sceneEventFilter(QGraphicsItem *, QEvent *) Q_DECL_OVERRIDE;
private slots:
void onMove();
};

#endif
6 changes: 4 additions & 2 deletions src/mumble/Settings.cpp
Expand Up @@ -150,9 +150,9 @@ OverlaySettings::OverlaySettings() {
qcFps = Qt::white;
fFps = 0.75f;
qfFps = qfUserName;
qrfFps = QRectF(10, 50, -1, 0.023438f);
qrfFps = QRectF(0.0f, 0.05, -1, 0.023438f);
bFps = false;
qrfTime = QRectF(10, 10, -1, 0.023438f);
qrfTime = QRectF(0.0f, 0.0, -1, 0.023438f);
bTime = false;

bUseWhitelist = false;
Expand Down Expand Up @@ -549,6 +549,7 @@ void OverlaySettings::load(QSettings* settings_ptr) {
SAVELOAD(qrfMutedDeafened, "mutedrect");
SAVELOAD(qrfAvatar, "avatarrect");
SAVELOAD(qrfFps, "fpsrect");
SAVELOAD(qrfTime, "timerect");

LOADFLAG(qaUserName, "useralign");
LOADFLAG(qaChannel, "channelalign");
Expand Down Expand Up @@ -856,6 +857,7 @@ void OverlaySettings::save(QSettings* settings_ptr) {
SAVELOAD(qrfMutedDeafened, "mutedrect");
SAVELOAD(qrfAvatar, "avatarrect");
SAVELOAD(qrfFps, "fpsrect");
SAVELOAD(qrfTime, "timerect");

SAVEFLAG(qaUserName, "useralign");
SAVEFLAG(qaChannel, "channelalign");
Expand Down
6 changes: 4 additions & 2 deletions src/mumble/mumble.pro
Expand Up @@ -147,7 +147,8 @@ HEADERS *= BanEditor.h \
MumbleApplication.h \
ApplicationPalette.h \
ThemeInfo.h \
Themes.h
Themes.h \
OverlayPositionableItem.h

SOURCES *= BanEditor.cpp \
ACLEditor.cpp \
Expand Down Expand Up @@ -209,7 +210,8 @@ SOURCES *= BanEditor.cpp \
MumbleApplication.cpp \
smallft.cpp \
ThemeInfo.cpp \
Themes.cpp
Themes.cpp \
OverlayPositionableItem.cpp

DIST *= ../../icons/mumble.ico licenses.h smallft.h ../../icons/mumble.xpm murmur_pch.h mumble.plist
RESOURCES *= mumble.qrc mumble_translations.qrc mumble_flags.qrc ../../themes/MumbleTheme.qrc
Expand Down

0 comments on commit 8bf9b0a

Please sign in to comment.