diff --git a/inc/graph/server/gui/chart/chart.h b/inc/graph/server/gui/chart/chart.h new file mode 100644 index 0000000..ddb819d --- /dev/null +++ b/inc/graph/server/gui/chart/chart.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +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 getSeries() const { return chart->series(); } + + private: + QChartView* view; + QChart* chart; + QValueAxis *x, *y; +}; +} // namespace Graph::GUI diff --git a/inc/graph/server/gui/mainwindow.h b/inc/graph/server/gui/mainwindow.h index 9e89b07..fc09188 100644 --- a/inc/graph/server/gui/mainwindow.h +++ b/inc/graph/server/gui/mainwindow.h @@ -4,7 +4,11 @@ #include #include #include +#include +#include "graph/server/gui/chart/chart.h" #include +#include +#include namespace Ui { class MainWindow; @@ -24,6 +28,7 @@ private slots: private: Ui::MainWindow *ui; - PluginModel* pluginsModel; + PluginModel* pluginModel; + std::vector charts; }; } // namespace Graph::GUI diff --git a/inc/graph/server/spec.h b/inc/graph/server/spec.h index 9ea7702..2ba2819 100644 --- a/inc/graph/server/spec.h +++ b/inc/graph/server/spec.h @@ -1,22 +1,19 @@ #pragma once -#include -#include +#include -struct graph_spec_t { - std::string title; +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 { - struct x { - std::string label; - uint64_t limit = UINT64_MAX; - }; - struct y { - std::string label; - bool auto_limit = true; - double min; - double max; - }; - }; + struct { + axis_spec_t x, y; + } axis; }; \ No newline at end of file diff --git a/src/graph/server/CMakeLists.txt b/src/graph/server/CMakeLists.txt index 407bfe1..243d671 100644 --- a/src/graph/server/CMakeLists.txt +++ b/src/graph/server/CMakeLists.txt @@ -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}") \ No newline at end of file diff --git a/src/graph/server/gui/chart/chart.cpp b/src/graph/server/gui/chart/chart.cpp new file mode 100644 index 0000000..099e3d7 --- /dev/null +++ b/src/graph/server/gui/chart/chart.cpp @@ -0,0 +1,44 @@ +#include +#include +#include + +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 \ No newline at end of file diff --git a/src/graph/server/gui/mainwindow.cpp b/src/graph/server/gui/mainwindow.cpp index ec85109..0af40b2 100644 --- a/src/graph/server/gui/mainwindow.cpp +++ b/src/graph/server/gui/mainwindow.cpp @@ -1,33 +1,57 @@ #include #include #include +#include +#include +#include #include #include #include #include +#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()); - ui->pluginsListView->doItemsLayout(); + 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); } diff --git a/src/graph/server/gui/mainwindow.ui b/src/graph/server/gui/mainwindow.ui index 4646e48..1e38c3d 100644 --- a/src/graph/server/gui/mainwindow.ui +++ b/src/graph/server/gui/mainwindow.ui @@ -76,21 +76,25 @@ &Load - - - - &Unload + + Ctrl+L &Add + + Ctrl+A + &Remove + + Ctrl+R + diff --git a/src/graph/server/plugin.cpp b/src/graph/server/plugin.cpp index 9ae9512..087d75f 100644 --- a/src/graph/server/plugin.cpp +++ b/src/graph/server/plugin.cpp @@ -1,8 +1,5 @@ #include #include -#include -#include -#include #include #include