1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2026-08-10 21:43:31 -04:00

Allow zooming in on chart and hiding of series.

This commit is contained in:
Jon Beniston
2026-08-01 21:09:30 +01:00
parent 77e43defe6
commit 2cb8091c54
4 changed files with 146 additions and 3 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 367 KiB

+128
View File
@@ -24,6 +24,7 @@
#include <QAction>
#include <QClipboard>
#include <QPainter>
#include <QWheelEvent>
#include "feature/featureuiset.h"
#include "feature/featurewebapiutils.h"
@@ -381,6 +382,95 @@ void AISGUI::resetChartAxes()
m_shipYAxis->setRange(0.0, 10.0);
}
static void scaleChartAxis(qint64& start, qint64& end, qint64 minimumRange, int delta, qreal centre)
{
qint64 range = end - start;
const double factor = std::pow(0.5, std::abs(delta) / 120.0);
qint64 newRange;
if (delta < 0) {
newRange = range / factor;
} else {
newRange = range * factor;
}
range = std::max(minimumRange / 2, range);
newRange = std::max(minimumRange, newRange);
if (delta < 0) {
start -= centre * range;
} else {
start += centre * newRange;
}
end = start + newRange;
}
bool AISGUI::eventFilter(QObject *obj, QEvent *event)
{
if ((obj == ui->chart) && (event->type() == QEvent::Wheel))
{
QWheelEvent *wheelEvent = static_cast<QWheelEvent *>(event);
const int delta = wheelEvent->angleDelta().y();
if (m_messageSeries)
{
const QPointF point = wheelEvent->position();
const QRectF plotArea = m_chart->plotArea();
if ((plotArea.width() > 0.0) && (plotArea.height() > 0.0))
{
if (wheelEvent->modifiers() & Qt::ShiftModifier)
{
qreal y = (point.y() - plotArea.y()) / plotArea.height();
y = 1.0 - std::min(1.0, std::max(0.0, y));
if (m_messageSeries->isVisible())
{
qint64 min = (qint64) m_messageYAxis->min();
qint64 max = (qint64) m_messageYAxis->max();
scaleChartAxis(min, max, 2LL, delta / 2, y);
min = std::max(0LL, min);
max = std::min(5000LL, max);
m_messageYAxis->setMin((qreal) min);
m_messageYAxis->setMax((qreal) max);
}
if (m_shipSeries->isVisible())
{
qint64 min = (qint64) m_shipYAxis->min();
qint64 max = (qint64) m_shipYAxis->max();
scaleChartAxis(min, max, 2LL, delta / 2, y);
min = std::max(0LL, min);
max = std::min(5000LL, max);
m_shipYAxis->setMin((qreal) min);
m_shipYAxis->setMax((qreal) max);
}
}
else if (m_messageSeries->count() > 1)
{
qreal x = (point.x() - plotArea.x()) / plotArea.width();
x = std::min(1.0, std::max(0.0, x));
qint64 startMS = m_chartXAxis->min().toMSecsSinceEpoch();
qint64 endMS = m_chartXAxis->max().toMSecsSinceEpoch();
scaleChartAxis(startMS, endMS, 10000LL, delta, x);
startMS = std::max((qint64) m_messageSeries->at(0).x(), startMS);
endMS = std::min((qint64) m_messageSeries->at(m_messageSeries->count() - 1).x(), endMS);
m_chartXAxis->setMin(QDateTime::fromMSecsSinceEpoch(startMS));
m_chartXAxis->setMax(QDateTime::fromMSecsSinceEpoch(endMS));
}
}
}
wheelEvent->accept();
return true;
}
return FeatureGUI::eventFilter(obj, event);
}
void AISGUI::plotChart()
{
QChart *oldChart = m_chart;
@@ -414,9 +504,47 @@ void AISGUI::plotChart()
resetChartAxes();
ui->chart->setChart(m_chart);
ui->chart->installEventFilter(this);
const auto markers = m_chart->legend()->markers();
for (QLegendMarker *marker : markers) {
connect(marker, &QLegendMarker::clicked, this, &AISGUI::legendMarkerClicked);
}
delete oldChart;
}
void AISGUI::legendMarkerClicked()
{
QLegendMarker *marker = qobject_cast<QLegendMarker *>(sender());
if (!marker) {
return;
}
marker->series()->setVisible(!marker->series()->isVisible());
marker->setVisible(true);
const qreal alpha = marker->series()->isVisible() ? 1.0 : 0.5;
QBrush brush = marker->labelBrush();
QColor color = brush.color();
color.setAlphaF(alpha);
brush.setColor(color);
marker->setLabelBrush(brush);
brush = marker->brush();
color = brush.color();
color.setAlphaF(alpha);
brush.setColor(color);
marker->setBrush(brush);
QPen pen = marker->pen();
color = pen.color();
color.setAlphaF(alpha);
pen.setColor(color);
marker->setPen(pen);
}
void AISGUI::updateChart()
{
const QDateTime now = QDateTime::currentDateTime();
+4
View File
@@ -164,6 +164,7 @@ private slots:
void on_deleteVessels_clicked();
void clearChart(const QPoint& p);
void updateChart();
void legendMarkerClicked();
void vesselSelectionChanged(int currentRow, int currentColumn, int previousRow, int previousColumn);
void shipPhoto(const VesselFinderPhoto *photo);
void on_vessels_cellDoubleClicked(int row, int column);
@@ -173,6 +174,9 @@ private slots:
void vesselsColumnSelectMenu(QPoint pos);
void vesselsColumnSelectMenuChecked(bool checked = false);
void removeOldVessels();
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
};
#endif // INCLUDE_FEATURE_AISGUI_H_
+14 -3
View File
@@ -12,6 +12,19 @@ The AIS feature can draw corresponding objects on the [Map](../../feature/map/re
![AIS feature plugin GUI](../../../doc/img/AIS_plugin.png)
<h3>1: Display Chart</h3>
When checked, a chart will be displayed that shows AIS message rates in messages per second.
The chart is updated every second. Data older than 10 minutes is averaged over a minute, in order to keep the number of data points managable.
Click a series name in the chart legend to hide or show that series. Use the mouse wheel to zoom the time axis around the cursor, or hold Shift while using the wheel to zoom the visible vertical axes.
Right click the chart button to reset the collected chart data.
<h3>2: Delete All Vessels</h3>
Click to delete all vessels from the table and map.
<h3>Vessels Table</h3>
The vessels table displays the current status for each vessel, base station or aid-to-navigation, based on the latest received messages, aggregated from all AIS Demodulators.
@@ -34,9 +47,7 @@ The vessels table displays the current status for each vessel, base station or a
* Updated - Gives the date and time the last message was received.
* Messages - Displays the number of messages received.
* Selecting a vessel displays its first available VesselFinder gallery image to the right of the table. The photographer credit below the image links to the vessel's gallery.
The chart button displays the received AIS message rate and number of ships over time. Right click the chart button to reset the collected chart data. The delete button removes every table item and its corresponding object from the Map feature.
Selecting a vessel displays its first available VesselFinder gallery image to the right of the table. The photographer credit below the image links to the vessel's gallery.
Right clicking on the table header allows you to select which columns to show. The columns can be reordered by left clicking and dragging the column header.