chart spec dialog

This commit is contained in:
Benedek László 2024-05-15 00:36:55 +02:00
parent a3af29a572
commit 4cfefdd1ab
7 changed files with 390 additions and 23 deletions

View File

@ -1,14 +1,22 @@
#pragma once #pragma once
#ifdef __cplusplus
#include <cstdint> #include <cstdint>
#else
#include <stdint.h>
#endif
typedef bool (*init_t)(); typedef struct {
double x, y;
} point_t;
typedef bool (*start_t)();
typedef void (*destroy_t)(); typedef void (*destroy_t)();
typedef void (*update_callback_t)(); typedef void (*update_callback_t)(unsigned int chartIndex, const char* seriesName, const point_t* points);
typedef struct { typedef struct {
uint32_t version; uint32_t version;
init_t init_method; start_t init_method;
destroy_t destroy_method; destroy_t destroy_method;
update_callback_t update_callback; update_callback_t update_callback;
} plugin_t; } plugin_t;

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include <graph/server/spec.h> #include <graph/server/spec.h>
#include <qabstractseries.h>
#include <QChart> #include <QChart>
#include <QChartView> #include <QChartView>
#include <QLineSeries> #include <QLineSeries>

View File

@ -1,14 +1,14 @@
#pragma once #pragma once
#include <graph/server/plugin.h>
#include <qlineseries.h>
#include <qlistwidget.h>
#include <QMainWindow> #include <QMainWindow>
#include <QMenuBar> #include <QMenuBar>
#include <QStatusBar> #include <QStatusBar>
#include <QToolBar> #include <QToolBar>
#include <vector> #include <vector>
#include "graph/server/gui/chart/chart.h" #include "graph/server/gui/chart/chart.h"
#include <graph/server/plugin.h>
#include <qlineseries.h>
#include <qlistwidget.h>
namespace Ui { namespace Ui {
class MainWindow; class MainWindow;
@ -17,16 +17,16 @@ class MainWindow;
namespace Graph::GUI { namespace Graph::GUI {
class MainWindow : public QMainWindow { class MainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
public: public:
explicit MainWindow(QWidget *parent = nullptr); explicit MainWindow(QWidget* parent = nullptr);
~MainWindow(); ~MainWindow();
private slots: private slots:
void on_action_Add_triggered(); void on_action_Add_triggered();
void on_action_Load_triggered(); void on_action_Load_triggered();
private: private:
Ui::MainWindow *ui; Ui::MainWindow* ui;
PluginModel* pluginModel; PluginModel* pluginModel;
std::vector<ChartWidget*> charts; std::vector<ChartWidget*> charts;

View File

@ -0,0 +1,26 @@
#pragma once
#include <qstringlistmodel.h>
#include <QDialog>
#include <graph/server/spec.h>
namespace Ui {
class SpecDialog;
}
namespace Graph::GUI {
class SpecDialog : public QDialog {
Q_OBJECT
public:
explicit SpecDialog(QWidget* parent = nullptr);
~SpecDialog();
QStringList getList() const { return series->stringList(); }
chart_spec_t getSpec() const;
private:
Ui::SpecDialog* ui;
QStringListModel* series;
};
} // namespace Graph::GUI

View File

@ -1,15 +1,13 @@
#include <graph/server/gui/chart/chart.h>
#include <graph/server/gui/mainwindow.h> #include <graph/server/gui/mainwindow.h>
#include <graph/server/gui/specdialog/specdialog.h>
#include <graph/server/plugin.h> #include <graph/server/plugin.h>
#include <graph/server/spec.h>
#include <graph/server/ui_mainwindow.h> #include <graph/server/ui_mainwindow.h>
#include <qlineseries.h>
#include <qlistwidget.h>
#include <qpoint.h>
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
#include "graph/server/gui/chart/chart.h"
#include "graph/server/spec.h"
namespace Graph::GUI { namespace Graph::GUI {
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) { MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
@ -40,17 +38,22 @@ MainWindow::~MainWindow() {
} }
void MainWindow::on_action_Add_triggered() { void MainWindow::on_action_Add_triggered() {
ChartWidget* chart = SpecDialog dialog;
new ChartWidget(ui->graphsListWidget, {.title = "My Title", .grid = true, .legend = true, .axis = {.x = {.label = "x axis"}, .y = {.label = "y axis"}}}); if (dialog.exec() == SpecDialog::Rejected)
return;
ChartWidget* chart = new ChartWidget(ui->graphsListWidget, dialog.getSpec());
ui->graphsListWidget->addItem(chart); ui->graphsListWidget->addItem(chart);
ui->graphsListWidget->setItemWidget(chart, chart->getView()); ui->graphsListWidget->setItemWidget(chart, chart->getView());
for (QString title : dialog.getList()) {
QLineSeries* series = new QLineSeries(); QLineSeries* series = new QLineSeries();
series->setName("some series"); series->setName(title);
*series << QPointF(0, 1) << QPointF(1, 2) << QPoint(2, 3);
chart->getChart()->addSeries(series); chart->getChart()->addSeries(series);
*series << QPointF(0, 1) << QPointF(1, 2) << QPoint(2, 3);
}
} }
void MainWindow::on_action_Load_triggered() { void MainWindow::on_action_Load_triggered() {

View File

@ -0,0 +1,38 @@
#include <graph/server/gui/specdialog/specdialog.h>
#include <graph/server/spec.h>
#include <graph/server/ui_specdialog.h>
namespace Graph::GUI {
SpecDialog::SpecDialog(QWidget* parent) : QDialog(parent), ui(new Ui::SpecDialog) {
ui->setupUi(this);
series = new QStringListModel(this);
ui->seriesListView->setModel(series);
ui->seriesListView->setEditTriggers(QAbstractItemView::AnyKeyPressed | QAbstractItemView::DoubleClicked);
connect(ui->addSeriesButton, &QPushButton::clicked, [&]() {
int row = series->rowCount();
series->insertRow(row);
QModelIndex index = series->index(row);
ui->seriesListView->setCurrentIndex(index);
ui->seriesListView->edit(index);
});
connect(ui->removeSeriesButton, &QPushButton::clicked, [&]() { series->removeRow(ui->seriesListView->currentIndex().row()); });
}
SpecDialog::~SpecDialog() {
delete series;
}
chart_spec_t SpecDialog::getSpec() const {
return {
.title = ui->chartTitle->text(),
.grid = (ui->grid->checkState() == Qt::Checked),
.legend = (ui->legend->checkState() == Qt::Checked),
.axis = {
.x = {.label = ui->xTitle->text(), .auto_limit = (ui->xAutoRange->checkState() == Qt::Checked), .min = ui->xMin->value(), .max = ui->xMax->value()},
.y = {.label = ui->yTitle->text(), .auto_limit = (ui->yAutoRange->checkState() == Qt::Checked), .min = ui->yMin->value(), .max = ui->yMax->value()}}};
}
} // namespace Graph::GUI

View File

@ -0,0 +1,293 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SpecDialog</class>
<widget class="QDialog" name="SpecDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>302</width>
<height>372</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Chart Specification</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLineEdit" name="chartTitle">
<property name="placeholderText">
<string>Chart Title</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="seriesTab">
<attribute name="title">
<string>Series</string>
</attribute>
<layout class="QVBoxLayout" name="seriesVerticalLayout">
<item>
<widget class="QListView" name="seriesListView"/>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="addSeriesButton">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeSeriesButton">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="axisTab">
<attribute name="title">
<string>Axis</string>
</attribute>
<layout class="QHBoxLayout" name="axisHorizontalLayout">
<item alignment="Qt::AlignTop">
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="xVerticalLayout">
<item alignment="Qt::AlignTop">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16</height>
</size>
</property>
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="xTitle">
<property name="placeholderText">
<string>Axis Title</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="xAutoRange">
<property name="text">
<string>Auto-Range</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="xMin">
<property name="toolTip">
<string>minimum</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="xMax">
<property name="toolTip">
<string>
&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;maximum&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QFrame" name="frame_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="yVerticalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16</height>
</size>
</property>
<property name="text">
<string>Y</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="yTitle">
<property name="placeholderText">
<string>Axis Title</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="yAutoRange">
<property name="text">
<string>Auto-Range</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="yMin">
<property name="toolTip">
<string>
&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;minimum&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="yMax">
<property name="toolTip">
<string>
&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;maximum&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="displayTab">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<attribute name="title">
<string>Display</string>
</attribute>
<layout class="QVBoxLayout" name="displayVerticalLayout">
<item>
<widget class="QCheckBox" name="legend">
<property name="text">
<string>Legend</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="grid">
<property name="text">
<string>Grid</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SpecDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SpecDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>