qt: use ReadableObservableManager to get observables in ReadableGraphDisplay

This commit is contained in:
Jussi Kuokkanen 2019-12-01 13:50:01 +02:00
parent 9c836dc34a
commit 70347cc038
4 changed files with 157 additions and 28 deletions

View File

@ -37,10 +37,10 @@ void ReadableBrowser::genBrowserTree(ReadableTreeView *treeView, QStandardItemMo
}
QStandardItem *newItem = addBrowserItem(node, item);
if (!node->constant && node->value_callback) {
/*if (!node->constant && node->value_callback) {
tc_readable_result_t res = node->value_callback(node);
qDebug() << res.valid << res.data.uint_value;
}
}*/
for (uint16_t i = 0; i < node->children_count; i++) {
traverse(node->children_nodes[i], newItem);
@ -74,6 +74,11 @@ QStandardItem *ReadableBrowser::addBrowserItem(tc_readable_node_t* node, QStanda
item->setDragEnabled(true);
QVariant v;
v.setValue(ReadableData(node));
item->setData(v, Qt::UserRole);
parent->appendRow(item);
return item;

View File

@ -1,11 +1,12 @@
#include "ReadableDisplay.h"
#include "ReadableDisplay.h"
#include <ReadableObservableManager.h>
ReadableDisplay::ReadableDisplay(QWidget *parent) : QWidget(parent) {
setAcceptDrops(true);
m_displayWidgetLayout = new QVBoxLayout;
m_displayWidgetLayout->addWidget(new ReadableGraphDisplay);
m_displayWidgetLayout->addWidget(new ReadableGraphDisplay(new ReadableObservableManager));
setLayout(m_displayWidgetLayout);
}

View File

@ -1,30 +1,38 @@
#include "ReadableGraphDisplay.h"
#include <ReadableData.h>
#include <ReadableMasterObservable.h>
#include <QDragEnterEvent>
#include <QMimeData>
ReadableGraphDisplay::ReadableGraphDisplay(QWidget *parent) : QChartView(parent) {
// FIXME: drops are only accepted only on a small area on the widget
ReadableGraphDisplay::ReadableGraphDisplay(ReadableObservableManager *manager, QWidget *parent) : QChartView(parent) {
m_observableManager = manager;
setAcceptDrops(true);
setRenderHint(QPainter::Antialiasing);
m_chart = new QChart;
m_chart->setBackgroundRoundness(0);
m_chart->setBackgroundBrush(QBrush(QPalette().color(QPalette::Background)));
m_chart->legend()->setLabelColor(QPalette().color(QPalette::Text));
m_chart->setAcceptDrops(true);
setChart(m_chart);
m_chart->addSeries(&series);
m_referenceObservable = nullptr;
m_chart->addAxis(&xAxis, Qt::AlignBottom);
m_chart->addAxis(&yAxis, Qt::AlignLeft);
series.attachAxis(&xAxis);
series.attachAxis(&yAxis);
yAxis.setLabelsColor(QPalette().color(QPalette::Text));
xAxis.setLabelsColor(QPalette().color(QPalette::Text));
yAxis.setRange(0, 70000);
xAxis.setRange(0, 20);
xAxis.setRange(-20, 0);
yAxisMargin = 0.1;
x = 0;
}
@ -45,22 +53,17 @@ void ReadableGraphDisplay::dragEnterEvent(QDragEnterEvent *event) {
}
void ReadableGraphDisplay::dropEvent(QDropEvent *event) {
//QVariantList itemDataList;
QByteArray b_data = event->mimeData()->data(ReadableData::mimeType());
qDebug() << b_data;
// Convert mime data to QVariantList
QDataStream stream(&b_data, QIODevice::ReadOnly);
QVariant v;
stream >> v;
qDebug() << v;
if (!v.canConvert<ReadableData>()) {
qDebug() << "can't convert";
return;
}
ReadableData d = qvariant_cast<ReadableData>(v);
@ -71,16 +74,111 @@ void ReadableGraphDisplay::dropEvent(QDropEvent *event) {
return;
}*/
ReadableMasterObservable *mo = new ReadableMasterObservable(&d);
QLineSeries *series = new QLineSeries(this);
series->setName(d.name());
connect(mo->createObservable(std::chrono::milliseconds(2000)), &ReadableObservable::valueUpdated, [=](tc_readable_result_t res) {
if (!res.valid) {
return;
}
m_chart->addSeries(series);
series->attachAxis(&xAxis);
series->attachAxis(&yAxis);
m_seriesList.append(series);
if (!m_referenceObservable) {
m_referenceObservable = m_observableManager->observable(&d, std::chrono::milliseconds(2000));
qDebug() << res.data.uint_value << res.valid;
x++;
series.append(x, res.data.uint_value);
connect(m_referenceObservable, &ReadableObservable::valueUpdated, [=](tc_readable_result_t res) {
addToSeries(series, res);
addQueuedValues();
});
}
connect(m_observableManager->observable(&d, std::chrono::milliseconds(2000)), &ReadableObservable::valueUpdated, [=](tc_readable_result_t res) {
ValueQueue vq = {
.series = series,
.res = res
};
m_queuedValues.append(vq);
});
connect(series, &QLineSeries::pointAdded, [=]() {
adjustYAxisBounds(series);
});
for (QLegendMarker *marker : m_chart->legend()->markers()) {
connect(marker, &QLegendMarker::clicked, []() {
qDebug() << "marker clicked";
});
}
}
bool ReadableGraphDisplay::addToSeries(QLineSeries *series, tc_readable_result_t res) {
if (!res.valid) {
return false;
}
qreal value;
switch (res.data.data_type) {
case TC_TYPE_INT:
//series->append(x, res.data.int_value);
value = res.data.int_value;
break;
case TC_TYPE_UINT:
value = res.data.uint_value;
break;
case TC_TYPE_DOUBLE:
value = res.data.double_value;
break;
default:
return false;
}
// Shift the series by -<update period> in the x axis
QVector <QPointF> points = series->pointsVector();
for (int i = 0; i < points.length(); i++) {
points[i].setX(points[i].x() - 2);
}
if (points.length() > 20) {
points.pop_front();
}
series->replace(points);
series->append(0, value);
return true;
}
void ReadableGraphDisplay::addQueuedValues() {
for (ValueQueue vq : m_queuedValues) {
addToSeries(vq.series, vq.res);
}
m_queuedValues.clear();
}
void ReadableGraphDisplay::adjustYAxisBounds(QLineSeries *series) {
QVector <qreal> yVector;
for (QLineSeries *series : m_seriesList) {
for (QPointF point : series->points()) {
yVector.append(point.y());
}
}
qreal yMax = *std::max_element(yVector.begin(), yVector.end());
qreal yMin = *std::min_element(yVector.begin(), yVector.end());
if (qFuzzyCompare(yMin, yMax)) {
// The graph is a straight line
yAxis.setMax(yMax + (yMax * yAxisMargin));
yAxis.setMin(yMax - (yMax * yAxisMargin));
}
else {
yAxis.setMax(yMax + abs(yMax - yMin) * yAxisMargin);
yAxis.setMin(yMin - abs(yMax - yMin) * yAxisMargin);
}
}

View File

@ -3,17 +3,23 @@
#include <QChartView>
#include <QGraphicsItem>
#include <QtCharts/QChart>
#include <QLegendMarker>
#include <QLineSeries>
#include <QCategoryAxis>
#include <QDebug>
#include <ReadableMasterObservable.h>
#include <ReadableObservableManager.h>
// Graph view for updating readables. QVariantLists convertible to ReadableData can be dropped on this widget.
using namespace QtCharts;
class ReadableGraphDisplay : public QChartView {
public:
ReadableGraphDisplay(QWidget *parent = nullptr);
ReadableGraphDisplay(ReadableObservableManager *manager, QWidget *parent = nullptr);
public slots:
//void updateBounds(qreal y);
protected:
bool event(QEvent *event);
@ -25,11 +31,30 @@ protected:
private:
Q_OBJECT
// Struct for queueing values
struct ValueQueue {
QLineSeries *series;
tc_readable_result_t res;
};
double yAxisMargin; // Margin as a percentage (0-1) of the plot between min/max values and x axis min/max
ReadableObservableManager *m_observableManager; // For creating observables
QChart *m_chart;
QValueAxis xAxis, yAxis;
int x;
QLineSeries series;
QVector <QLineSeries*> m_seriesList;
ReadableObservable *m_referenceObservable; // Observable that controls when queued values are added
QVector <ValueQueue> m_queuedValues;
bool addToSeries(QLineSeries *series, tc_readable_result_t res); // Add a value to series. Returns res.valid
void addQueuedValues();
void adjustYAxisBounds(QLineSeries *series);
};