basic charts

This commit is contained in:
Benedek László 2024-05-14 23:02:08 +02:00
parent 679b2d3eca
commit a3af29a572
8 changed files with 140 additions and 44 deletions

View File

@ -0,0 +1,26 @@
#pragma once
#include <graph/server/spec.h>
#include <qabstractseries.h>
#include <QChart>
#include <QChartView>
#include <QLineSeries>
#include <QListWidgetItem>
#include <QValueAxis>
namespace Graph::GUI {
class ChartWidget : public QListWidgetItem {
public:
ChartWidget(QWidget* parent = nullptr, const chart_spec_t& spec = chart_spec_t());
~ChartWidget();
QChartView* getView() const { return view; }
QChart* getChart() const { return chart; }
QList<QAbstractSeries*> getSeries() const { return chart->series(); }
private:
QChartView* view;
QChart* chart;
QValueAxis *x, *y;
};
} // namespace Graph::GUI

View File

@ -4,7 +4,11 @@
#include <QMenuBar>
#include <QStatusBar>
#include <QToolBar>
#include <vector>
#include "graph/server/gui/chart/chart.h"
#include <graph/server/plugin.h>
#include <qlineseries.h>
#include <qlistwidget.h>
namespace Ui {
class MainWindow;
@ -24,6 +28,7 @@ private slots:
private:
Ui::MainWindow *ui;
PluginModel* pluginsModel;
PluginModel* pluginModel;
std::vector<ChartWidget*> charts;
};
} // namespace Graph::GUI

View File

@ -1,22 +1,19 @@
#pragma once
#include <cstdint>
#include <string>
#include <QString>
struct graph_spec_t {
std::string title;
bool grid = false;
bool legend = false;
struct axis {
struct x {
std::string label;
uint64_t limit = UINT64_MAX;
};
struct y {
std::string label;
struct axis_spec_t {
QString label;
bool auto_limit = true;
double min;
double max;
};
};
};
struct chart_spec_t {
QString title;
bool grid = false;
bool legend = false;
struct {
axis_spec_t x, y;
} axis;
};

View File

@ -1,4 +1,4 @@
find_package(Qt6 REQUIRED COMPONENTS Widgets)
find_package(Qt6 REQUIRED COMPONENTS Widgets Charts)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
@ -6,14 +6,13 @@ set(CMAKE_AUTOUIC ON)
file(GLOB_RECURSE SERVER_SOURCES "*.cpp")
file(GLOB_RECURSE SERVER_UI "*.ui")
file(GLOB_RECURSE SERVER_RES "*.qrc")
# file(GLOB_RECURSE SERVER_HEADERS "${CMAKE_SOURCE_DIR}/inc/graph/server/*.h")
file(GLOB_RECURSE SERVER_HEADERS "../../../inc/graph/server/*.h")
cmake_print_variables(SERVER_SOURCES)
cmake_print_variables(SERVER_UI)
cmake_print_variables(SERVER_RES)
cmake_print_variables(SERVER_HEADERS)
cmake_print_variables(CMAKE_BINARY_DIR)
# cmake_print_variables(SERVER_SOURCES)
# cmake_print_variables(SERVER_UI)
# cmake_print_variables(SERVER_RES)
# cmake_print_variables(SERVER_HEADERS)
# cmake_print_variables(CMAKE_BINARY_DIR)
qt_wrap_cpp(SERVER_GEN_SRC ${SERVER_SRC})
qt_wrap_ui(SERVER_GEN_UI ${SERVER_UI})
@ -24,5 +23,5 @@ add_executable(server
)
target_include_directories(server PRIVATE "${CMAKE_BINARY_DIR}/src")
target_link_libraries(server PRIVATE dl Qt6::Widgets)
target_link_libraries(server PRIVATE dl Qt6::Widgets Qt6::Charts)
set_target_properties(server PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")

View File

@ -0,0 +1,44 @@
#include <graph/server/gui/chart/chart.h>
#include <qsizepolicy.h>
#include <iostream>
namespace Graph::GUI {
ChartWidget::ChartWidget(QWidget* parent, const chart_spec_t& spec) : QListWidgetItem() {
view = new QChartView(parent);
chart = new QChart();
// chart
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);
view->setChart(chart);
view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setSizeHint(view->sizeHint()*2);
}
ChartWidget::~ChartWidget() {
// delete view;
// delete chart;
// delete x;
// delete y;
}
} // namespace Graph::GUI

View File

@ -1,33 +1,57 @@
#include <graph/server/gui/mainwindow.h>
#include <graph/server/plugin.h>
#include <graph/server/ui_mainwindow.h>
#include <qlineseries.h>
#include <qlistwidget.h>
#include <qpoint.h>
#include <QFileDialog>
#include <QMessageBox>
#include <iostream>
#include <stdexcept>
#include "graph/server/gui/chart/chart.h"
#include "graph/server/spec.h"
namespace Graph::GUI {
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
// plugins
pluginsModel = new PluginModel(this);
ui->pluginsListView->setModel(pluginsModel);
pluginModel = new PluginModel(this);
ui->pluginsListView->setModel(pluginModel);
// unload plugin
connect(ui->pluginsListView, &QListView::doubleClicked, [&](const QModelIndex& index) {
pluginsModel->removeRow(index.row());
pluginsModel->remove(index.row());
QMessageBox::StandardButton result = QMessageBox::question(this, "Unload plugin?", "Are you sure?", QMessageBox::Yes | QMessageBox::Cancel);
if (result == QMessageBox::Yes) {
pluginModel->removeRow(index.row());
pluginModel->remove(index.row());
ui->pluginsListView->doItemsLayout();
}
});
}
MainWindow::~MainWindow() {
delete ui;
delete pluginsModel;
for (ChartWidget* chart : charts) {
delete chart;
}
delete pluginModel;
}
void MainWindow::on_action_Add_triggered() {}
void MainWindow::on_action_Add_triggered() {
ChartWidget* chart =
new ChartWidget(ui->graphsListWidget, {.title = "My Title", .grid = true, .legend = true, .axis = {.x = {.label = "x axis"}, .y = {.label = "y axis"}}});
ui->graphsListWidget->addItem(chart);
ui->graphsListWidget->setItemWidget(chart, chart->getView());
QLineSeries* series = new QLineSeries();
series->setName("some series");
*series << QPointF(0, 1) << QPointF(1, 2) << QPoint(2, 3);
chart->getChart()->addSeries(series);
}
void MainWindow::on_action_Load_triggered() {
QString file = QFileDialog::getOpenFileName(this, "Load plugin", ".", "Plugins (*.so *.dll *.dylib)");
@ -36,15 +60,15 @@ void MainWindow::on_action_Load_triggered() {
return;
try {
pluginsModel->add(new Plugin(file.toStdString()));
pluginModel->add(new Plugin(file.toStdString()));
} catch (std::runtime_error e) {
std::cout << e.what() << std::endl;
QMessageBox::critical(this, "Error", "Failed to load plugin.", QMessageBox::StandardButton::Ignore);
}
int row = pluginsModel->rowCount();
pluginsModel->insertRow(row);
QModelIndex index = pluginsModel->index(row);
int row = pluginModel->rowCount();
pluginModel->insertRow(row);
QModelIndex index = pluginModel->index(row);
ui->pluginsListView->doItemsLayout();
ui->pluginsListView->setCurrentIndex(index);
}

View File

@ -76,21 +76,25 @@
<property name="text">
<string>&amp;Load</string>
</property>
</action>
<action name="action_Unload">
<property name="text">
<string>&amp;Unload</string>
<property name="shortcut">
<string>Ctrl+L</string>
</property>
</action>
<action name="action_Add">
<property name="text">
<string>&amp;Add</string>
</property>
<property name="shortcut">
<string>Ctrl+A</string>
</property>
</action>
<action name="action_Remove">
<property name="text">
<string>&amp;Remove</string>
</property>
<property name="shortcut">
<string>Ctrl+R</string>
</property>
</action>
</widget>
<resources/>

View File

@ -1,8 +1,5 @@
#include <dlfcn.h>
#include <graph/server/plugin.h>
#include <qnamespace.h>
#include <qobject.h>
#include <qvariant.h>
#include <stdexcept>
#include <string>