1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-06-05 17:53:02 +02:00

Make the legend interactive

This commit is contained in:
Martin Tůma 2025-06-01 10:33:16 +02:00
parent 466c538e17
commit 1466de5ddf
9 changed files with 170 additions and 67 deletions

View File

@ -23,6 +23,7 @@ greaterThan(QT_MAJOR_VERSION, 5) {
CONFIG += object_parallel_to_source
INCLUDEPATH += ./src
HEADERS += src/common/config.h \
src/GUI/legendentryitem.h \
src/GUI/legenditem.h \
src/common/garmin.h \
src/common/coordinates.h \
@ -277,6 +278,7 @@ HEADERS += src/common/config.h \
src/data/geojsonparser.h
SOURCES += src/main.cpp \
src/GUI/legendentryitem.cpp \
src/GUI/legenditem.cpp \
src/common/coordinates.cpp \
src/common/rectc.cpp \

View File

@ -0,0 +1,72 @@
#include <QPainter>
#include <QCursor>
#include "font.h"
#include "legendentryitem.h"
#define PADDING 2
LegendEntryItem::LegendEntryItem(const QColor &color, const QString &text,
QGraphicsItem *parent) : QGraphicsItem(parent), _color(color), _text(text)
{
_textColor = Qt::black;
_font.setPixelSize(FONT_SIZE);
_font.setFamily(FONT_FAMILY);
QFontMetrics fm(_font);
_boundingRect = QRectF(0, 0, FONT_SIZE * 2 + PADDING * 2
+ fm.tightBoundingRect(text).width() + PADDING * 2,
FONT_SIZE + PADDING * 2);
setCursor(Qt::ArrowCursor);
setAcceptHoverEvents(true);
}
void LegendEntryItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
QFontMetrics fm(_font);
painter->setRenderHint(QPainter::Antialiasing, false);
painter->setFont(_font);
painter->setBrush(_color);
painter->setPen(QPen(Qt::black));
painter->drawRect(PADDING, PADDING, FONT_SIZE * 2, FONT_SIZE);
painter->setPen(QPen(_textColor));
painter->drawText(FONT_SIZE * 2 + PADDING * 2 + PADDING,
PADDING + fm.ascent(), _text);
//painter->setPen(Qt::red);
//painter->setBrush(Qt::NoBrush);
//painter->drawRect(boundingRect());
}
void LegendEntryItem::setTextColor(const QColor &color)
{
_textColor = color;
update();
}
void LegendEntryItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event);
_font.setBold(true);
setZValue(zValue() + 1.0);
update();
emit selected(true);
}
void LegendEntryItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event);
_font.setBold(false);
setZValue(zValue() - 1.0);
update();
emit selected(false);
}

34
src/GUI/legendentryitem.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef LEGENDENTRYITEM_H
#define LEGENDENTRYITEM_H
#include <QGraphicsItem>
#include <QFont>
class LegendEntryItem : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
LegendEntryItem(const QColor &color, const QString &text,
QGraphicsItem *parent = 0);
QRectF boundingRect() const {return _boundingRect;}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget);
void setTextColor(const QColor &color);
signals:
void selected(bool);
private:
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
QRectF _boundingRect;
QColor _color, _textColor;
QString _text;
QFont _font;
};
#endif // LEGENDENTRYITEM_H

View File

@ -1,17 +1,17 @@
#include <cmath>
#include <QPainter>
#include <QFileInfo>
#include "font.h"
#include "pathitem.h"
#include "graphitem.h"
#include "planeitem.h"
#include "legendentryitem.h"
#include "legenditem.h"
#define PADDING 4
LegendItem::LegendItem(QGraphicsItem *parent) : QGraphicsItem(parent)
{
_color = Qt::black;
_bgColor = Qt::white;
_drawBackground = false;
_font.setPixelSize(FONT_SIZE);
_font.setFamily(FONT_FAMILY);
}
void LegendItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
@ -28,21 +28,6 @@ void LegendItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option
bc.setAlpha(196);
painter->setBrush(QBrush(bc));
painter->drawRect(_boundingRect);
painter->setBrush(Qt::NoBrush);
}
QFontMetrics fm(_font);
painter->setFont(_font);
for (int i = 0; i < _items.size(); i++) {
const Item &itm = _items.at(i);
painter->setBrush(itm.color);
painter->setPen(QPen(Qt::black));
painter->drawRect(0, i * (FONT_SIZE + PADDING), FONT_SIZE * 2, FONT_SIZE);
painter->setPen(QPen(_color));
painter->drawText(FONT_SIZE * 2 + PADDING, i * (FONT_SIZE + PADDING)
+ fm.ascent(), itm.text);
}
//painter->setPen(Qt::red);
@ -50,23 +35,43 @@ void LegendItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option
//painter->drawRect(boundingRect());
}
void LegendItem::addItem(const QColor &color, const QString &text)
void LegendItem::addItem(PathItem *item)
{
prepareGeometryChange();
_items.append(Item(color, text));
LegendEntryItem *li = new LegendEntryItem(item->color(),
item->name().isEmpty() ? QFileInfo(item->file()).fileName() : item->name(),
this);
li->setPos(0, _items.size() * li->boundingRect().height());
QFontMetrics fm(_font);
qreal maxWidth = qMax((int)_boundingRect.width() - (FONT_SIZE * 2 + PADDING),
fm.tightBoundingRect(text).width());
_boundingRect = QRectF(0, 0, FONT_SIZE * 2 + PADDING + maxWidth,
_items.size() * (FONT_SIZE + PADDING) - (PADDING - 1));
_items.append(li);
_boundingRect = QRectF(0, 0, qMax(_boundingRect.width(),
li->boundingRect().width()), _items.size() * li->boundingRect().height());
QObject::connect(li, &LegendEntryItem::selected, item, &PathItem::hoverAll);
}
void LegendItem::addItem(PlaneItem *item)
{
if (item->name().isEmpty())
return;
prepareGeometryChange();
LegendEntryItem *li = new LegendEntryItem(item->color(), item->name(), this);
li->setPos(0, _items.size() * li->boundingRect().height());
_items.append(li);
_boundingRect = QRectF(0, 0, qMax(_boundingRect.width(),
li->boundingRect().width()), _items.size() * li->boundingRect().height());
}
void LegendItem::setColor(const QColor &color)
{
_color = color;
update();
for (int i = 0; i < _items.size(); i++)
_items.at(i)->setTextColor(color);
}
void LegendItem::setBackgroundColor(const QColor &color)
@ -84,6 +89,8 @@ void LegendItem::drawBackground(bool draw)
void LegendItem::clear()
{
prepareGeometryChange();
qDeleteAll(_items);
_items.clear();
_boundingRect = QRectF();
}

View File

@ -3,7 +3,11 @@
#include <QGraphicsItem>
class LegendItem : public QGraphicsItem
class LegendEntryItem;
class PathItem;
class PlaneItem;
class LegendItem : public QGraphicsItem
{
public:
LegendItem(QGraphicsItem *parent = 0);
@ -12,27 +16,18 @@ public:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget);
void addItem(PathItem *item);
void addItem(PlaneItem *item);
void setDigitalZoom(qreal zoom);
void addItem(const QColor &color, const QString &text);
void setColor(const QColor &color);
void setBackgroundColor(const QColor &color);
void drawBackground(bool draw);
void clear();
private:
struct Item
{
Item(const QColor &color, const QString &text)
: color(color), text(text) {}
QColor color;
QString text;
};
QList<Item> _items;
QList<LegendEntryItem*> _items;
QRectF _boundingRect;
QColor _color, _bgColor;
QFont _font;
QColor _bgColor;
bool _drawBackground;
};

View File

@ -153,30 +153,18 @@ void MapView::updateLegend()
if (_showTracks) {
for (int i = 0; i < _tracks.size(); i++)
addLegendEntry(_tracks.at(i));
_legend->addItem(_tracks.at(i));
}
if (_showRoutes) {
for (int i = 0; i < _routes.size(); i++)
addLegendEntry(_routes.at(i));
_legend->addItem(_routes.at(i));
}
if (_showAreas) {
for (int i = 0; i < _areas.size(); i++)
addLegendEntry(_areas.at(i));
_legend->addItem(_areas.at(i));
}
}
void MapView::addLegendEntry(const PathItem *ti)
{
_legend->addItem(ti->color(), ti->name().isEmpty()
? QFileInfo(ti->file()).fileName() : ti->name());
}
void MapView::addLegendEntry(const PlaneItem *plane)
{
if (!plane->name().isEmpty())
_legend->addItem(plane->color(), plane->name());
}
PathItem *MapView::addTrack(const Track &track)
{
if (!track.isValid()) {
@ -204,7 +192,7 @@ PathItem *MapView::addTrack(const Track &track)
if (_showTracks) {
addPOI(_poi->points(ti->path()));
addLegendEntry(ti);
_legend->addItem(ti);
}
return ti;
@ -238,7 +226,7 @@ PathItem *MapView::addRoute(const Route &route)
if (_showRoutes) {
addPOI(_poi->points(ri->path()));
addLegendEntry(ri);
_legend->addItem(ri);
}
return ri;
@ -266,7 +254,7 @@ void MapView::addArea(const Area &area)
if (_showAreas) {
addPOI(_poi->points(ai->bounds()));
addLegendEntry(ai);
_legend->addItem(ai);
}
}
@ -309,7 +297,7 @@ MapItem *MapView::addMap(MapAction *map)
if (_showAreas) {
addPOI(_poi->points(mi->bounds()));
addLegendEntry(mi);
_legend->addItem(mi);
}
return mi;

View File

@ -168,8 +168,6 @@ private:
void pinchGesture(QPinchGesture *gesture);
void skipColor() {_palette.nextColor();}
void setHidpi(bool hidpi);
void addLegendEntry(const PathItem *path);
void addLegendEntry(const PlaneItem *plane);
void updateLegend();
void mouseMoveEvent(QMouseEvent *event);

View File

@ -388,9 +388,9 @@ void PathItem::drawMarkerBackground(bool draw)
_markerInfo->drawBackground(draw);
}
void PathItem::hover(bool hover)
void PathItem::hover(bool hvr)
{
if (hover) {
if (hvr) {
_pen.setWidth((width() + 1) * pow(2, -_digitalZoom));
setZValue(zValue() + 1.0);
} else {
@ -401,6 +401,12 @@ void PathItem::hover(bool hover)
update();
}
void PathItem::hoverAll(bool hvr)
{
hover(hvr);
emit selected(hvr);
}
void PathItem::showMarker(bool show)
{
if (_showMarker == show)

View File

@ -60,7 +60,8 @@ public:
static void setTimeZone(const QTimeZone &zone) {_timeZone = zone;}
public slots:
void hover(bool hover);
void hover(bool hvr);
void hoverAll(bool hvr);
signals:
void selected(bool);