basic custom chart widget
This commit is contained in:
parent
966db4f4e1
commit
df8cd70b0d
@ -13,7 +13,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef int (*run_method_t)();
|
typedef int (*run_method_t)();
|
||||||
typedef int (*destroy_t)();
|
typedef int (*destroy_t)();
|
||||||
typedef void (*update_callback_t)(unsigned int chartIndex, const char* seriesName, const point_t* points, int count);
|
typedef void (*update_callback_t)(unsigned int chartIndex, const char* seriesName, const point_t* points, unsigned long count);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
|
@ -2,36 +2,36 @@
|
|||||||
|
|
||||||
#include <graph/plugins/plugin.h>
|
#include <graph/plugins/plugin.h>
|
||||||
#include <graph/server/spec.h>
|
#include <graph/server/spec.h>
|
||||||
#include <qevent.h>
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QChart>
|
|
||||||
#include <QChartView>
|
|
||||||
#include <QLineSeries>
|
|
||||||
#include <QListWidgetItem>
|
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QValueAxis>
|
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
|
||||||
namespace Graph::GUI {
|
namespace Graph::GUI {
|
||||||
class ChartWidget : public QListWidgetItem {
|
class ChartWidget : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ChartWidget(QWidget* parent = nullptr, const chart_spec_t& spec = chart_spec_t());
|
ChartWidget(QWidget* parent = nullptr, const chart_spec_t& spec = chart_spec_t());
|
||||||
~ChartWidget();
|
~ChartWidget();
|
||||||
|
|
||||||
void addData(const char* seriesName, const point_t* points, int count);
|
void addData(const char* seriesName, const point_t* points, unsigned long count);
|
||||||
|
|
||||||
QChartView* getView() const { return view; }
|
|
||||||
QList<QAbstractSeries*> getSeries() const { return chart->series(); }
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QChartView* view;
|
|
||||||
QChart* chart;
|
|
||||||
QValueAxis *x, *y;
|
|
||||||
chart_spec_t spec;
|
chart_spec_t spec;
|
||||||
int decimateState = 0;
|
int decimateState = 0;
|
||||||
|
|
||||||
QMutex mutex;
|
QMutex mutex;
|
||||||
|
|
||||||
|
std::list<point_t> points;
|
||||||
|
|
||||||
|
double scaleX, scaleY;
|
||||||
|
int marginX = 40;
|
||||||
|
int marginY = 20;
|
||||||
|
QPointF pointToCoord(const point_t& point);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ContextMenu : public QMenu {
|
class ContextMenu : public QMenu {
|
||||||
|
@ -28,7 +28,7 @@ class MainWindow : public QMainWindow {
|
|||||||
static MainWindow* getInstance();
|
static MainWindow* getInstance();
|
||||||
static void close();
|
static void close();
|
||||||
|
|
||||||
void addData(unsigned int chartIndex, const char* seriesName, const point_t* points, int count);
|
void addData(unsigned int chartIndex, const char* seriesName, const point_t* points, unsigned long count);
|
||||||
|
|
||||||
void removeChart(ChartWidget* chartWidget);
|
void removeChart(ChartWidget* chartWidget);
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ struct chart_spec_t {
|
|||||||
bool grid = false;
|
bool grid = false;
|
||||||
bool legend = false;
|
bool legend = false;
|
||||||
bool keep_all = true;
|
bool keep_all = true;
|
||||||
int keep_limit;
|
unsigned long keep_limit;
|
||||||
int decimate;
|
int decimate;
|
||||||
struct {
|
struct {
|
||||||
axis_spec_t x, y;
|
axis_spec_t x, y;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
find_package(Qt6 REQUIRED COMPONENTS Widgets Charts)
|
find_package(Qt6 REQUIRED COMPONENTS Widgets)
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTORCC ON)
|
set(CMAKE_AUTORCC ON)
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
@ -17,5 +17,5 @@ add_executable(server
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(server PRIVATE "${CMAKE_BINARY_DIR}/src")
|
target_include_directories(server PRIVATE "${CMAKE_BINARY_DIR}/src")
|
||||||
target_link_libraries(server PRIVATE dl Qt6::Widgets Qt6::Charts)
|
target_link_libraries(server PRIVATE dl Qt6::Widgets)
|
||||||
set_target_properties(server PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
set_target_properties(server PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
@ -1,150 +1,163 @@
|
|||||||
#include <graph/server/gui/chart/chart.h>
|
#include <graph/server/gui/chart/chart.h>
|
||||||
#include <graph/server/gui/mainwindow.h>
|
#include <graph/server/gui/mainwindow.h>
|
||||||
#include <qabstractseries.h>
|
#include <qbrush.h>
|
||||||
#include <qlineseries.h>
|
#include <qnamespace.h>
|
||||||
#include <qmutex.h>
|
#include <qpoint.h>
|
||||||
#include <QIcon>
|
#include <qpolygon.h>
|
||||||
|
#include <qsize.h>
|
||||||
|
#include <QPainter>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <string>
|
||||||
|
#include "graph/plugins/plugin.h"
|
||||||
|
|
||||||
#define MIN(a, b) (a < b ? a : b)
|
#define MIN(a, b) (a < b ? a : b)
|
||||||
#define MAX(a, b) (a > b ? a : b)
|
#define MAX(a, b) (a > b ? a : b)
|
||||||
|
|
||||||
namespace Graph::GUI {
|
namespace Graph::GUI {
|
||||||
ChartWidget::ChartWidget(QWidget* parent, const chart_spec_t& spec) : QListWidgetItem(), spec(spec) {
|
ChartWidget::ChartWidget(QWidget* parent, const chart_spec_t& spec) : QWidget(parent), spec(spec) {
|
||||||
view = new QChartView(parent);
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
chart = new QChart();
|
|
||||||
|
|
||||||
// chart
|
setMinimumSize(QSize(600, 350));
|
||||||
if (spec.legend)
|
|
||||||
chart->legend()->show();
|
|
||||||
else
|
|
||||||
chart->legend()->hide();
|
|
||||||
|
|
||||||
chart->setTitle(spec.title);
|
|
||||||
|
|
||||||
// axis
|
|
||||||
x = new QValueAxis();
|
|
||||||
y = new QValueAxis();
|
|
||||||
|
|
||||||
if (!spec.axis.x.auto_limit)
|
|
||||||
x->setRange(spec.axis.x.min, spec.axis.x.max);
|
|
||||||
if (!spec.axis.y.auto_limit)
|
|
||||||
y->setRange(spec.axis.y.min, spec.axis.y.max);
|
|
||||||
|
|
||||||
x->setTitleText(spec.axis.x.label);
|
|
||||||
y->setTitleText(spec.axis.y.label);
|
|
||||||
|
|
||||||
chart->addAxis(x, Qt::AlignBottom);
|
|
||||||
chart->addAxis(y, Qt::AlignLeft);
|
|
||||||
|
|
||||||
for (const QString& title : spec.series) {
|
|
||||||
QLineSeries* series = new QLineSeries(view);
|
|
||||||
series->setName(title);
|
|
||||||
chart->addSeries(series);
|
|
||||||
series->attachAxis(x);
|
|
||||||
series->attachAxis(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
view->setRenderHint(QPainter::Antialiasing);
|
|
||||||
view->setChart(chart);
|
|
||||||
view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
||||||
setSizeHint(view->sizeHint() * 4);
|
|
||||||
|
|
||||||
// context menu
|
// context menu
|
||||||
view->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
|
setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
|
||||||
view->connect(view, &QChartView::customContextMenuRequested, view, [this](const QPoint& pos) {
|
connect(this, &QWidget::customContextMenuRequested, this, [this](const QPoint& pos) {
|
||||||
ContextMenu menu(nullptr, this);
|
ContextMenu menu(nullptr, this);
|
||||||
menu.exec(view->mapToGlobal(pos));
|
menu.exec(mapToGlobal(pos));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ChartWidget::~ChartWidget() {
|
ChartWidget::~ChartWidget() {}
|
||||||
// delete view;
|
|
||||||
// delete chart;
|
|
||||||
// delete x;
|
|
||||||
// delete y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChartWidget::addData(const char* seriesName, const point_t* points, int count) {
|
void ChartWidget::addData(const char* seriesName, const point_t* points, unsigned long count) {
|
||||||
QMutexLocker locker(&mutex);
|
QMutexLocker locker(&mutex);
|
||||||
|
|
||||||
std::cout << "locked: " << locker.isLocked() << std::endl;
|
double minX = std::numeric_limits<double>::max();
|
||||||
|
double minY = std::numeric_limits<double>::max();
|
||||||
|
double maxX = std::numeric_limits<double>::min();
|
||||||
|
double maxY = std::numeric_limits<double>::min();
|
||||||
|
|
||||||
QString name(seriesName);
|
if (!spec.keep_all) {
|
||||||
|
if (count >= spec.keep_limit) {
|
||||||
double minX = spec.keep_all ? x->min() : std::numeric_limits<double>::max();
|
this->points.clear();
|
||||||
double minY = spec.keep_all ? y->min() : std::numeric_limits<double>::max();
|
} else if (this->points.size() + count > spec.keep_limit) {
|
||||||
double maxX = spec.keep_all ? x->max() : std::numeric_limits<double>::min();
|
std::list<point_t>::iterator end = std::next(this->points.begin(), this->points.size() - (spec.keep_limit - count));
|
||||||
double maxY = spec.keep_all ? y->max() : std::numeric_limits<double>::min();
|
this->points.erase(this->points.begin(), end);
|
||||||
|
|
||||||
for (QAbstractSeries* series : chart->series()) {
|
|
||||||
if (series->name() == name) {
|
|
||||||
if (!spec.keep_all) {
|
|
||||||
if (count >= spec.keep_limit) {
|
|
||||||
((QLineSeries*)series)->clear();
|
|
||||||
} else if (((QLineSeries*)series)->count() + count > spec.keep_limit) {
|
|
||||||
std::cout << "count: " << count << ", size: " << ((QLineSeries*)series)->count() << ", remove: " << ((QLineSeries*)series)->count() - (spec.keep_limit - count) << std::endl;
|
|
||||||
((QLineSeries*)series)->removePoints(0, ((QLineSeries*)series)->count() - (spec.keep_limit - count));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "starting min/max" << std::endl;
|
|
||||||
for (const QPointF& point : ((QLineSeries*)series)->points()) {
|
|
||||||
if (spec.axis.x.auto_limit) {
|
|
||||||
minX = MIN(minX, point.x());
|
|
||||||
maxX = MAX(maxX, point.x());
|
|
||||||
}
|
|
||||||
if (spec.axis.y.auto_limit) {
|
|
||||||
minY = MIN(minY, point.y());
|
|
||||||
maxY = MAX(maxY, point.y());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << "got min/max" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "start adding" << std::endl;
|
|
||||||
QList<QPointF> newPoints;
|
|
||||||
|
|
||||||
for (int i = spec.keep_all ? 0 : MAX(0, count - spec.keep_limit); i < count; i++) {
|
|
||||||
if (decimateState >= spec.decimate)
|
|
||||||
decimateState = 0;
|
|
||||||
if (decimateState++ % spec.decimate != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (spec.axis.x.auto_limit) {
|
|
||||||
minX = MIN(minX, points[i].x);
|
|
||||||
maxX = MAX(maxX, points[i].x);
|
|
||||||
}
|
|
||||||
if (spec.axis.y.auto_limit) {
|
|
||||||
minY = MIN(minY, points[i].y);
|
|
||||||
maxY = MAX(maxY, points[i].y);
|
|
||||||
}
|
|
||||||
|
|
||||||
newPoints.append(QPointF(points[i].x, points[i].y));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "adding" << std::endl;
|
|
||||||
((QLineSeries*)series)->append(newPoints);
|
|
||||||
|
|
||||||
if (spec.axis.x.auto_limit)
|
|
||||||
x->setRange(MIN(x->min(), minX), MAX(x->max(), maxX));
|
|
||||||
if (spec.axis.y.auto_limit)
|
|
||||||
y->setRange(MIN(y->min(), minY), MAX(y->max(), maxY));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const point_t& point : this->points) {
|
||||||
|
if (spec.axis.x.auto_limit) {
|
||||||
|
minX = MIN(minX, point.x);
|
||||||
|
maxX = MAX(maxX, point.x);
|
||||||
|
}
|
||||||
|
if (spec.axis.y.auto_limit) {
|
||||||
|
minY = MIN(minY, point.y);
|
||||||
|
maxY = MAX(maxY, point.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned long i = spec.keep_all ? 0 : (count < spec.keep_limit ? 0 : count - spec.keep_limit); i < count; i++) {
|
||||||
|
if (decimateState >= spec.decimate)
|
||||||
|
decimateState = 0;
|
||||||
|
if (decimateState++ % spec.decimate != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
this->points.push_back(points[i]);
|
||||||
|
|
||||||
|
if (spec.axis.x.auto_limit) {
|
||||||
|
minX = MIN(minX, points[i].x);
|
||||||
|
maxX = MAX(maxX, points[i].x);
|
||||||
|
}
|
||||||
|
if (spec.axis.y.auto_limit) {
|
||||||
|
minY = MIN(minY, points[i].y);
|
||||||
|
maxY = MAX(maxY, points[i].y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spec.axis.x.auto_limit) {
|
||||||
|
spec.axis.x.min = minX;
|
||||||
|
spec.axis.x.max = maxX;
|
||||||
|
}
|
||||||
|
if (spec.axis.y.auto_limit) {
|
||||||
|
spec.axis.y.min = minY;
|
||||||
|
spec.axis.y.max = maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChartWidget::clear() {
|
void ChartWidget::clear() {
|
||||||
QMutexLocker locker(&mutex);
|
QMutexLocker locker(&mutex);
|
||||||
|
points.clear();
|
||||||
|
}
|
||||||
|
|
||||||
for (QAbstractSeries* series : chart->series()) {
|
QSize ChartWidget::sizeHint() const {
|
||||||
((QLineSeries*)series)->clear();
|
if (width() < minimumWidth() || height() < minimumHeight())
|
||||||
|
return minimumSize();
|
||||||
|
return QSize(width(), height());
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF ChartWidget::pointToCoord(const point_t& point) {
|
||||||
|
return QPointF((point.x - spec.axis.x.min) * scaleX + marginX, height() - (point.y - spec.axis.y.min) * scaleY - marginY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChartWidget::paintEvent(QPaintEvent* e) {
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
|
||||||
|
QPainter painter(this);
|
||||||
|
|
||||||
|
// background
|
||||||
|
painter.fillRect(QRectF(0, 0, width(), height()), Qt::lightGray);
|
||||||
|
painter.fillRect(QRectF(marginX, marginY, width() - 2 * marginX, height() - 2 * marginY), Qt::white);
|
||||||
|
|
||||||
|
// title
|
||||||
|
painter.setPen(Qt::black);
|
||||||
|
painter.drawText(QRect(0, 0, width(), marginY), Qt::AlignCenter, spec.title);
|
||||||
|
|
||||||
|
// limits
|
||||||
|
// y max-mid-min
|
||||||
|
painter.drawText(QRect(0, marginY, marginX, marginY), Qt::AlignCenter, QString::number(spec.axis.y.max));
|
||||||
|
painter.drawText(QRect(0, height() / 2 - marginY / 2, marginX, marginY), Qt::AlignCenter, QString::number((spec.axis.y.max + spec.axis.y.min) / 2));
|
||||||
|
painter.drawText(QRect(0, height() - marginY * 2, marginX, marginY), Qt::AlignCenter, QString::number(spec.axis.y.min));
|
||||||
|
|
||||||
|
// x min-mid-max
|
||||||
|
painter.drawText(QRect(marginX, height() - marginY, marginX, marginY), Qt::AlignCenter, QString::number(spec.axis.x.min));
|
||||||
|
painter.drawText(QRect(width() / 2 - marginX / 2, height() - marginY, marginX, marginY), Qt::AlignCenter,
|
||||||
|
QString::number((spec.axis.x.min + spec.axis.x.max) / 2));
|
||||||
|
painter.drawText(QRect(width() - marginX * 2, height() - marginY, marginX, marginY), Qt::AlignCenter, QString::number(spec.axis.x.max));
|
||||||
|
|
||||||
|
// grid
|
||||||
|
if (spec.grid) {
|
||||||
|
painter.setPen(Qt::lightGray);
|
||||||
|
|
||||||
|
int innerHeight = height() - 2 * marginY;
|
||||||
|
painter.drawLine(marginX, marginY + innerHeight / 4, width() - marginX, marginY + innerHeight / 4);
|
||||||
|
painter.drawLine(marginX, marginY + innerHeight / 2, width() - marginX, marginY + innerHeight / 2);
|
||||||
|
painter.drawLine(marginX, marginY + 3 * innerHeight / 4, width() - marginX, marginY + 3 * innerHeight / 4);
|
||||||
|
|
||||||
|
int innerWidth = width() - 2 * marginX;
|
||||||
|
painter.drawLine(marginX + innerWidth / 4, marginY, marginX + innerWidth / 4, height() - marginY);
|
||||||
|
painter.drawLine(marginX + innerWidth / 2, marginY, marginX + innerWidth / 2, height() - marginY);
|
||||||
|
painter.drawLine(marginX + 3 * innerWidth / 4, marginY, marginX + 3 * innerWidth / 4, height() - marginY);
|
||||||
}
|
}
|
||||||
x->setRange(spec.axis.x.min, spec.axis.x.max);
|
|
||||||
y->setRange(spec.axis.y.min, spec.axis.y.max);
|
// points
|
||||||
decimateState = 0;
|
scaleX = (width() - marginX * 2) / (spec.axis.x.max - spec.axis.x.min);
|
||||||
|
scaleY = (height() - marginY * 2) / (spec.axis.y.max - spec.axis.y.min);
|
||||||
|
|
||||||
|
painter.setPen(QPen(Qt::black, 1));
|
||||||
|
|
||||||
|
QPolygonF polygon;
|
||||||
|
for (const point_t point : points) {
|
||||||
|
// TODO: only paint visible points
|
||||||
|
// (+ 1-1 before and after)
|
||||||
|
polygon << pointToCoord(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.drawPolyline(polygon);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextMenu::ContextMenu(QWidget* parent, ChartWidget* chartWidget) : QMenu(parent) {
|
ContextMenu::ContextMenu(QWidget* parent, ChartWidget* chartWidget) : QMenu(parent) {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <graph/server/plugin.h>
|
#include <graph/server/plugin.h>
|
||||||
#include <graph/server/spec.h>
|
#include <graph/server/spec.h>
|
||||||
#include <graph/server/ui_mainwindow.h>
|
#include <graph/server/ui_mainwindow.h>
|
||||||
|
#include <qlistwidget.h>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -33,11 +34,11 @@ void MainWindow::close() {
|
|||||||
delete instance;
|
delete instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addData(unsigned int chartIndex, const char* seriesName, const point_t* points, int count) {
|
void addData(unsigned int chartIndex, const char* seriesName, const point_t* points, unsigned long count) {
|
||||||
MainWindow::getInstance()->addData(chartIndex, seriesName, points, count);
|
MainWindow::getInstance()->addData(chartIndex, seriesName, points, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::addData(unsigned int chartIndex, const char* seriesName, const point_t* points, int count) {
|
void MainWindow::addData(unsigned int chartIndex, const char* seriesName, const point_t* points, unsigned long count) {
|
||||||
if (chartIndex >= charts.size())
|
if (chartIndex >= charts.size())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -83,8 +84,10 @@ void MainWindow::on_action_Add_triggered() {
|
|||||||
|
|
||||||
charts.push_back(chart);
|
charts.push_back(chart);
|
||||||
|
|
||||||
ui->graphsListWidget->addItem(chart);
|
QListWidgetItem* item = new QListWidgetItem();
|
||||||
ui->graphsListWidget->setItemWidget(chart, chart->getView());
|
|
||||||
|
ui->graphsListWidget->addItem(item);
|
||||||
|
ui->graphsListWidget->setItemWidget(item, chart);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_action_Load_triggered() {
|
void MainWindow::on_action_Load_triggered() {
|
||||||
@ -136,6 +139,14 @@ void MainWindow::on_action_Load_triggered() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::removeChart(ChartWidget* chartWidget) {
|
void MainWindow::removeChart(ChartWidget* chartWidget) {
|
||||||
|
for (int i = 0; i < ui->graphsListWidget->count(); i++) {
|
||||||
|
ChartWidget* widget = (ChartWidget*)ui->graphsListWidget->itemWidget(ui->graphsListWidget->item(i));
|
||||||
|
if (widget == chartWidget) {
|
||||||
|
ui->graphsListWidget->takeItem(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto it = charts.begin(); it != charts.end(); it++) {
|
for (auto it = charts.begin(); it != charts.end(); it++) {
|
||||||
if ((*it) == chartWidget) {
|
if ((*it) == chartWidget) {
|
||||||
charts.erase(it);
|
charts.erase(it);
|
||||||
|
@ -45,7 +45,7 @@ chart_spec_t SpecDialog::getSpec() const {
|
|||||||
.grid = ui->grid->isChecked(),
|
.grid = ui->grid->isChecked(),
|
||||||
.legend = ui->legend->isChecked(),
|
.legend = ui->legend->isChecked(),
|
||||||
.keep_all = ui->keepAll->isChecked(),
|
.keep_all = ui->keepAll->isChecked(),
|
||||||
.keep_limit = ui->keep->value(),
|
.keep_limit = static_cast<unsigned long>(ui->keep->value()),
|
||||||
.decimate = ui->decimate->value(),
|
.decimate = ui->decimate->value(),
|
||||||
.axis = {.x = {.label = ui->xTitle->text(), .auto_limit = ui->xAutoRange->isChecked(), .min = ui->xMin->value(), .max = ui->xMax->value()},
|
.axis = {.x = {.label = ui->xTitle->text(), .auto_limit = ui->xAutoRange->isChecked(), .min = ui->xMin->value(), .max = ui->xMax->value()},
|
||||||
.y = {.label = ui->yTitle->text(), .auto_limit = ui->yAutoRange->isChecked(), .min = ui->yMin->value(), .max = ui->yMax->value()}},
|
.y = {.label = ui->yTitle->text(), .auto_limit = ui->yAutoRange->isChecked(), .min = ui->yMin->value(), .max = ui->yMax->value()}},
|
||||||
|
16
test/test.py
16
test/test.py
@ -21,7 +21,7 @@ def sine_array(args):
|
|||||||
start = 0
|
start = 0
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
x = np.linspace(start, start+0.5, 100)
|
x = np.linspace(start, start+0.5, args.num)
|
||||||
y = np.sin(x)
|
y = np.sin(x)
|
||||||
|
|
||||||
start += 0.5
|
start += 0.5
|
||||||
@ -33,18 +33,18 @@ def sine_array(args):
|
|||||||
}
|
}
|
||||||
|
|
||||||
r = requests.post(f"http://{args.address}:{args.port}/add", json=data)
|
r = requests.post(f"http://{args.address}:{args.port}/add", json=data)
|
||||||
sleep(0.25)
|
sleep(args.delay)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
break
|
break
|
||||||
|
|
||||||
def star(args):
|
def star(args):
|
||||||
points = [
|
points = [
|
||||||
(2,2),
|
(2/4,2/2),
|
||||||
(3,0),
|
(3/4,0),
|
||||||
(0,1),
|
(0,1/2),
|
||||||
(4,1),
|
(4/4,1/2),
|
||||||
(1,0),
|
(1/4,0),
|
||||||
(2,2)
|
(2/4,2/2)
|
||||||
]
|
]
|
||||||
for point in points:
|
for point in points:
|
||||||
requests.get(f"http://{args.address}:{args.port}/add?chart={args.chart}&series={args.series}&x={point[0]}&y={point[1]}")
|
requests.get(f"http://{args.address}:{args.port}/add?chart={args.chart}&series={args.series}&x={point[0]}&y={point[1]}")
|
||||||
|
Loading…
Reference in New Issue
Block a user