diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5baf5f6..e13cb04 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,24 +42,6 @@ jobs: sudo apt install cmake -y echo Installing automake... sudo apt install autoconf autoconf-archive automake libtool - echo Installing mono... - sudo apt install mono-complete - - uses: lukka/run-vcpkg@v11 - with: - vcpkgDirectory: "${{ github.workspace }}/lib/vcpkg" - vcpkgJsonGlob: "**/vcpkg.json" - - name: "Setup NuGet Credentials" - run: | - mono `vcpkg fetch nuget | tail -n 1` \ - sources add \ - -source "https://nuget.pkg.github.com/team-gets/index.json" \ - -storepasswordincleartext \ - -name "GitHub" \ - -username "team-gets" \ - -password "${{ secrets.GITHUB_TOKEN }}" - mono `vcpkg fetch nuget | tail -n 1` \ - setapikey "${{ secrets.GITHUB_TOKEN }}" \ - -source "https://nuget.pkg.github.com/team-gets/index.json" - name: Prepare CMake run: | cmake -S . -B build --preset=linux-gcc @@ -81,23 +63,6 @@ jobs: target: "desktop" arch: "win64_msvc2022_64" modules: "qtcharts" - - uses: lukka/run-vcpkg@v11 - with: - vcpkgDirectory: "${{ github.workspace }}/lib/vcpkg" - vcpkgJsonGlob: "**/vcpkg.json" - - name: "Setup NuGet Credentials" - shell: "bash" - run: | - `./lib/vcpkg/vcpkg fetch nuget | tail -n 1` \ - sources add \ - -source "https://nuget.pkg.github.com/team-gets/index.json" \ - -storepasswordincleartext \ - -name "GitHub" \ - -username "team-gets" \ - -password "${{ secrets.GITHUB_TOKEN }}" - `./lib/vcpkg/vcpkg fetch nuget | tail -n 1` \ - setapikey "${{ secrets.GITHUB_TOKEN }}" \ - -source "https://nuget.pkg.github.com/team-gets/index.json" - uses: ilammy/msvc-dev-cmd@v1.13.0 - name: Prepare CMake run: | diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 73f6bd0..0000000 --- a/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "lib/vcpkg"] - path = lib/vcpkg - url = https://github.com/microsoft/vcpkg.git -[submodule "lib/gr"] - path = lib/gr - url = https://github.com/sciapp/gr.git diff --git a/CMakeLists.txt b/CMakeLists.txt index dd557f4..6bfdbdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,4 @@ cmake_minimum_required(VERSION 3.30...4.0) -set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/lib/vcpkg/scripts/buildsystems/vcpkg.cmake" - CACHE STRING "Vcpkg toolchain file" FORCE) project(rig_gui LANGUAGES CXX C @@ -25,38 +23,14 @@ qt_standard_project_setup(REQUIRES 6.10) #target_compile_warn_all(guidev) # #target_link_libraries(guidev PRIVATE ${STD_APP_QT6_DEPS}) -# -## Ideally you would quickly iter on QML designs by using the dev gui app -#qt_add_qml_module(qml.a_circle -# URI qml.a_circle -# OUTPUT_DIRECTORY "qml/a_circle" -# QML_FILES -# "qml/circle.qml" -#) # Plotting Interface add_library(plotting_iface SHARED ${PLOTTING_SOURCES}) -target_link_libraries(plotting_iface PRIVATE Qt6::Core Qt6::Widgets) +target_link_libraries(plotting_iface PUBLIC Qt6::Core Qt6::Widgets) target_include_directories(plotting_iface PUBLIC ${PLOTTING_SRC_DIR}) target_compile_definitions(plotting_iface PRIVATE COMPILING_PLOT_API_DLL) target_compile_warn_all(plotting_iface) -find_package(PNG REQUIRED) -add_library(Libpng::Libpng ALIAS PNG::PNG) # Why does the vcpkg version not do this/why does GR do this -add_subdirectory_silence_warnings("${CMAKE_SOURCE_DIR}/lib/gr") - -# GR Backend Compilation -add_library(gr_backend SHARED ${GR_BKND_SOURCES}) -get_target_property(QT6GR_INCLUDES GR::GR INTERFACE_INCLUDE_DIRECTORIES) -target_include_directories(gr_backend PUBLIC - ${QT6GR_INCLUDES} "${CMAKE_SOURCE_DIR}/src") - -target_link_libraries(gr_backend PUBLIC plotting_iface) -target_link_libraries(gr_backend PUBLIC Qt6::Core Qt6::Widgets) -target_link_libraries(gr_backend PUBLIC GR::qt6gr qt6plugin) -target_compile_definitions(gr_backend PRIVATE COMPILING_GR_BACKEND_DLL) -target_compile_warn_all(gr_backend) - # QChart Backend Compilation add_library(qchart_backend SHARED ${QCHART_BKND_SOURCES}) target_include_directories(qchart_backend PUBLIC "${CMAKE_SOURCE_DIR}/src") @@ -76,4 +50,4 @@ target_include_directories(widgets_recreation PRIVATE ${STD_APP_INCLUDES}) target_compile_warn_all(widgets_recreation) target_link_libraries(widgets_recreation PRIVATE ${STD_APP_QT6_DEPS}) -target_link_libraries(widgets_recreation PRIVATE gr_backend qchart_backend) +target_link_libraries(widgets_recreation PRIVATE qchart_backend) diff --git a/cmake/cpp.cmake b/cmake/cpp.cmake index 8a3e41b..5797a34 100644 --- a/cmake/cpp.cmake +++ b/cmake/cpp.cmake @@ -14,7 +14,7 @@ set(APP_SOURCES # sorry set(OTHER_APP_SOURCES - "${CMAKE_SOURCE_DIR}/src/App/Recreation.cpp") + "${CMAKE_SOURCE_DIR}/src/App/testMultiplot.cpp") set(WINDOWING_SOURCES "${WINDOWING_SRC_DIR}/DevWindow.cpp" @@ -27,7 +27,8 @@ set(DIAL_SOURCES set(DISPLAYER_SOURCES "${WIDGETS_SRC_DIR}/Displays/QuantitiesRatesDisplay.cpp" "${WIDGETS_SRC_DIR}/Displays/QuantitiesRatesRow.cpp" - "${WIDGETS_SRC_DIR}/Displays/RateLabel.cpp") + "${WIDGETS_SRC_DIR}/Displays/RateLabel.cpp" + "${WIDGETS_SRC_DIR}/Displays/MultiPlotContainer.cpp") set(WIDGET_SOURCES ${WINDOWING_SOURCES} @@ -35,11 +36,7 @@ set(WIDGET_SOURCES ${DISPLAYER_SOURCES}) set(PLOTTING_SOURCES - "${PLOTTING_SRC_DIR}/Plot2D.cpp" - "${PLOTTING_SRC_DIR}/Container.cpp") - -set(GR_BKND_SOURCES - "${PLOTTING_SRC_DIR}/Backend/CoreGR.cpp") + "${PLOTTING_SRC_DIR}/Plot2D.cpp") set(QCHART_BKND_SOURCES "${PLOTTING_SRC_DIR}/Backend/CoreQChart.cpp") @@ -75,4 +72,4 @@ function(add_subdirectory_silence_warnings IN_DIRECTORY) add_subdirectory("${IN_DIRECTORY}" EXCLUDE_FROM_ALL) set_directory_properties(PROPERTIES COMPILE_OPTIONS "${oldCompileOpts}") -endfunction(set_directory_compile_silence_warnings) +endfunction(add_subdirectory_silence_warnings IN_DIRECTORY) diff --git a/lib/gr b/lib/gr deleted file mode 160000 index 53ed71e..0000000 --- a/lib/gr +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 53ed71e0f464868e1e1cba668895bb4b2d4e2228 diff --git a/lib/vcpkg b/lib/vcpkg deleted file mode 160000 index 4bc3a47..0000000 --- a/lib/vcpkg +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4bc3a47c7a63506e215e04e1473368adbaea6c27 diff --git a/src/App/testMultiplot.cpp b/src/App/testMultiplot.cpp new file mode 100644 index 0000000..fa514f8 --- /dev/null +++ b/src/App/testMultiplot.cpp @@ -0,0 +1,14 @@ +#include +#include +#include + +#include "Windowing/WidgetsRecreation.hpp" + +int main(int argc, char** argv) { + QApplication app(argc, argv); + + VSCL::FromPpt::Widgets window; + + window.show(); + return app.exec(); +} diff --git a/src/Plotting/Backend/APIGR.hpp b/src/Plotting/Backend/APIGR.hpp deleted file mode 100644 index 09d67c2..0000000 --- a/src/Plotting/Backend/APIGR.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#ifndef GR_BACKEND -#if defined(_WIN32) && !defined(__GNUC__) -#ifdef COMPILING_GR_BACKEND_DLL -#define GR_BACKEND __declspec(dllexport) -#else -#define GR_BACKEND __declspec(dllimport) -#endif // COMPILING_GR_BACKEND_DLL -#else -#define GR_BACKEND -#endif // _WIN32 && !__GNUC__ -#endif // GR_BACKEND diff --git a/src/Plotting/Backend/ColorGR.hpp b/src/Plotting/Backend/ColorGR.hpp deleted file mode 100644 index 03c9600..0000000 --- a/src/Plotting/Backend/ColorGR.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "Plotting/Appearance.hpp" - -namespace VSCL::Plot { - -// Reference gr.h 104-123 -// The polyline coloring function takes an int < 1024 -enum class ColorGR : uint16_t { - White = 0, - Black = 1, - Red = 236, - Green = 237, - Yellow = 238, - Blue = 239, - Orange = 240, - Purple = 241, - Cyan = 242, - Magenta = 243, - Lime = 244, - Pink = 245, - Teal = 246, - Lavender = 247, - Brown = 248, - Beige = 249, - Maroon = 250, - Mint = 251, - Olive = 252, - Apricot = 253, - Navy = 254, - Grey = 255 -}; // enum class ColorGR - -// Reference gks/util.c 213-463 -static const std::map ColorGRAsRGB = { - { ColorGR::White, ColorRGB{1.000000, 1.000000, 1.000000} }, - { ColorGR::Black, ColorRGB{0.0, 0.0, 0.0} }, - { ColorGR::Red, ColorRGB{0.901960, 0.098040, 0.294120} }, - { ColorGR::Green, ColorRGB{0.235290, 0.705880, 0.294120} }, - { ColorGR::Yellow, ColorRGB{1.000000, 0.882350, 0.098040} }, - { ColorGR::Blue, ColorRGB{0.000000, 0.509800, 0.784310} }, - { ColorGR::Orange, ColorRGB{0.960780, 0.509800, 0.188240} }, - { ColorGR::Purple, ColorRGB{0.568630, 0.117650, 0.705880} }, - { ColorGR::Cyan, ColorRGB{0.274510, 0.941180, 0.941180} }, - { ColorGR::Magenta, ColorRGB{0.941180, 0.196080, 0.901960} }, - { ColorGR::Lime, ColorRGB{0.823530, 0.960780, 0.235290} }, - { ColorGR::Pink, ColorRGB{0.980390, 0.745100, 0.831370} }, - { ColorGR::Teal, ColorRGB{0.000000, 0.501960, 0.501960} }, - { ColorGR::Lavender, ColorRGB{0.862750, 0.745100, 1.000000} }, - { ColorGR::Brown, ColorRGB{0.666670, 0.431370, 0.156860} }, - { ColorGR::Beige, ColorRGB{1.000000, 0.980390, 0.784310} }, - { ColorGR::Maroon, ColorRGB{0.501960, 0.000000, 0.000000} }, - { ColorGR::Mint, ColorRGB{0.666670, 1.000000, 0.764710} }, - { ColorGR::Olive, ColorRGB{0.501960, 0.501960, 0.000000} }, - { ColorGR::Apricot, ColorRGB{1.000000, 0.843140, 0.705880} }, - { ColorGR::Navy, ColorRGB{0.000000, 0.000000, 0.501960} }, - { ColorGR::Grey, ColorRGB{0.501960, 0.501960, 0.501960} } -}; // ColorGRAsRGB - -/* - * Find the RGB-spaced color from the input GR color name. - */ -static const ColorRGB RGBFromColorGR(ColorGR color) { - return ColorGRAsRGB.at(color); -}; - -/* - * Find a color that's close enough to or matching the input color. - * - * Defaults to RED: ColorRGB{0.901960, 0.098040, 0.294120} - * - */ -static const ColorGR ColorGRFromRGB(ColorRGB color, double tol = 1e-1) { - - for (std::pair colorpair : ColorGRAsRGB) { - const ColorRGB& rgb = colorpair.second; - - if (std::abs(rgb[0] - color[0]) > tol) { continue; } - if (std::abs(rgb[1] - color[1]) > tol) { continue; } - if (std::abs(rgb[2] - color[2]) > tol) { continue; } - - return colorpair.first; - } - - // default - return ColorGR::Red; -}; -} // VSCL::Plot diff --git a/src/Plotting/Backend/CoreGR.cpp b/src/Plotting/Backend/CoreGR.cpp deleted file mode 100644 index 705d4c7..0000000 --- a/src/Plotting/Backend/CoreGR.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include "gr.h" - -#include "./CoreGR.hpp" -#include "./ColorGR.hpp" - -namespace VSCL::Plot { - -PlotGR::PlotGR(QWidget* parent) : GRWidget(parent) { - SetWidgetRep(this); -}; - -void PlotGR::SetAxis(const Axis axis, const AxisInfo& info) { EmbeddablePlot2D::SetAxis(axis, info); draw(); } -void PlotGR::SetTitle(const std::string& title) { EmbeddablePlot2D::SetTitle(title); draw(); } - -void PlotGR::Plot() { - EmbeddablePlot2D::Plot(); - draw(); -} - -void PlotGR::EraseAllData() { - EmbeddablePlot2D::EraseAllData(); - draw(); -} - -int PlotGR::DoubleVectorToArray(const std::vector& original, - double* output, const size_t arrSize) { - - const size_t vecSize = original.size(); - const bool oversized = vecSize > arrSize; - - int stepSize = 1; - int endDelta = (oversized) ? -1 : 0; - // End delta will change so that it's inclusive of the last point - - // Must take samplings if it's too big to fit - if (oversized) - stepSize = static_cast(std::floor(vecSize / arrSize)); - - for (unsigned int i = 0; i < arrSize + endDelta; i += stepSize) { - output[i] = original[i]; - } - - if (oversized) - output[arrSize - 1] = original[arrSize - 1]; - - return 0; -} - -void PlotGR::UpdateAxes() { - // Horizontal Axis {{{ - const AxisInfo& taxe = GetAxisInfoView(Axis::Time); - double ttick = gr_tick(taxe.Range[0], taxe.Range[1]); - AxisScaling tscal = taxe.Scaling; - - switch (tscal) { - case AxisScaling::Log10: - gr_setscale(GR_OPTION_X_LOG); - break; - case AxisScaling::Ln: - gr_setscale(GR_OPTION_X_LN); - break; - case AxisScaling::Inverted: - gr_setscale(GR_OPTION_FLIP_X); - break; - case AxisScaling::Linear: - default: - gr_setscale(0); - break; - } - // }}} - // Vertical Axis {{{ - const AxisInfo& qaxe = GetAxisInfoView(Axis::Quantity); - double qtick = gr_tick(qaxe.Range[0], qaxe.Range[1]); - AxisScaling qscal = qaxe.Scaling; - - switch (qscal) { - case AxisScaling::Log10: - gr_setscale(GR_OPTION_Y_LOG); - break; - case AxisScaling::Ln: - gr_setscale(GR_OPTION_Y_LN); - break; - case AxisScaling::Inverted: - gr_setscale(GR_OPTION_FLIP_Y); - break; - case AxisScaling::Linear: - default: - gr_setscale(0); - break; - } - // }}} - - if (GetDrawGridState()) { - gr_setlinecolorind(ColorIndex(ColorGR::Grey)); - gr_setlinetype(1); - gr_grid(ttick, qtick, 0, 0, taxe.MajorSpacing, qaxe.MajorSpacing); - } - - gr_setlinecolorind(ColorIndex(ColorGR::Black)); - gr_setlinetype(1); - gr_axes(ttick, qtick, 0, 0, taxe.MajorSpacing, qaxe.MajorSpacing, -0.01); -} // void PlotGR::UpdateAxes(); - -void PlotGR::UpdateSeries() { - const std::vector serieses = GetSeriesInfosView(); - for (const SeriesInfo& series : serieses) { - const std::vector times = series.Times; - const std::vector quantities = series.Quantities; - if (times.size() < 2 || quantities.size() < 2) { continue; } - - // Magic number 512 (arbitrary power of 2) - const size_t vecSize = times.size(); - const size_t n = (vecSize < 512) ? vecSize : 512; - - double timeArr[512] = { 0.0 }; - double quantityArr[512] = { 0.0 }; - - DoubleVectorToArray(times, timeArr, n); - DoubleVectorToArray(quantities, quantityArr, n); - - // Appearance and drawing - switch (series.Style) { - case LineStyle::Dashed: - gr_setlinetype(2); // LINETYPE_DASHED - break; - case LineStyle::Dotted: - gr_setlinetype(3); // LINETYPE_DOTTED - break; - case LineStyle::Solid: - default: - gr_setlinetype(1); // LINETYPE_SOLID - break; - } - - ColorGR color = ColorGRFromRGB(series.Color); - gr_setlinecolorind(ColorIndex(color)); - gr_polyline((int)n, timeArr, quantityArr); - } -} // void PlotGR::UpdateSeries() - -void PlotGR::draw() { - const AxisInfo& taxe = GetAxisInfoView(Axis::Time); - const AxisInfo& qaxe = GetAxisInfoView(Axis::Quantity); - - double wxh = (double)width() / (double)height(); - double hxw = (double)height() / (double)width(); - double inset[4] = { 0.1, 0.97, 0.16, 0.9 }; // this is magic numbers - double wwsdims[4] = { 0, 1, 0, 1 }; - double vpdims[4]; - - if (width() > height()) { - wwsdims[3] = hxw; - double dims[4] = { inset[0], inset[1], inset[2]*hxw, inset[3]*hxw }; - memcpy(vpdims, dims, 4*sizeof(double)); - } - else { - wwsdims[1] = wxh; - double dims[4] = { inset[0]*wxh, inset[1]*wxh, inset[2], inset[3] }; - memcpy(vpdims, dims, 4*sizeof(double)); - } - - gr_setwswindow(wwsdims[0], wwsdims[1], wwsdims[2], wwsdims[3]); - gr_setviewport(vpdims[0], vpdims[1], vpdims[2], vpdims[3]); - gr_setwindow(taxe.Range[0], taxe.Range[1], qaxe.Range[0], qaxe.Range[1]); - - UpdateSeries(); - UpdateAxes(); -} -} // namespace VSCL::Plot -// vim: foldmethod=marker diff --git a/src/Plotting/Backend/CoreGR.hpp b/src/Plotting/Backend/CoreGR.hpp deleted file mode 100644 index c4aa975..0000000 --- a/src/Plotting/Backend/CoreGR.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include "qtgr/grwidget.h" - -#include "APIGR.hpp" -#include "Plotting/Plot2D.hpp" -#include "ColorGR.hpp" - -namespace VSCL::Plot { - -class PlotContainer; - -class GR_BACKEND PlotGR : public EmbeddablePlot2D, public GRWidget { - - friend class PlotContainer; - -public: - PlotGR(QWidget* parent); - - virtual void SetAxis(const Axis axis, const AxisInfo& info) override; - virtual void SetTitle(const std::string& title) override; - virtual void Plot() override; - virtual void EraseAllData() override; - -protected: - void UpdateAxes(); - void UpdateSeries(); - - virtual void draw() override; - - // Mostly here for interaction with GR C API - int DoubleVectorToArray(const std::vector& original, - double* output, const size_t arrSize); - -public: - static constexpr uint16_t ColorIndex(ColorGR color) { return static_cast(color); } -}; // class PlotGR -} // namespace VSCL::Plot diff --git a/src/Plotting/Backend/CoreQChart.cpp b/src/Plotting/Backend/CoreQChart.cpp index 6b7dbef..736fac8 100644 --- a/src/Plotting/Backend/CoreQChart.cpp +++ b/src/Plotting/Backend/CoreQChart.cpp @@ -3,16 +3,14 @@ namespace VSCL::Plot { -PlotQChart::PlotQChart(QWidget* parent) : QChartView(parent) { - SetWidgetRep(this); - - // These heap allocs are parented when they get added to each other - PlotChart = new QChart; - - LogTimeAxisQt = new QLogValueAxis; - LogQuantityAxisQt = new QLogValueAxis; - TimeAxisQt = new QValueAxis; - QuantityAxisQt = new QValueAxis; +PlotQChart::PlotQChart(QWidget* parent) + : EmbeddablePlot2D(parent) + , PlotChart(new QChart) + , PlotChartView(new QChartView(PlotChart, this)) + , LogTimeAxisQt(new QLogValueAxis(PlotChart)) + , LogQuantityAxisQt(new QLogValueAxis(PlotChart)) + , TimeAxisQt(new QValueAxis(PlotChart)) + , QuantityAxisQt(new QValueAxis(PlotChart)) { PlotChart->addAxis(TimeAxisQt, Qt::AlignBottom); TimeAxisQt->setLinePenColor(QColorConstants::Black); @@ -36,8 +34,10 @@ PlotQChart::PlotQChart(QWidget* parent) : QChartView(parent) { PlotChart->legend()->setVisible(false); PlotChart->setTheme(QChart::ChartThemeLight); - setChart(PlotChart); - setRenderHint(QPainter::RenderHint::Antialiasing); + PlotChartView->setChart(PlotChart); + PlotChartView->setRenderHint(QPainter::RenderHint::Antialiasing); + + layout()->addWidget(PlotChartView); } PlotQChart::~PlotQChart() { @@ -156,6 +156,10 @@ void PlotQChart::EraseAllData() { EmbeddablePlot2D::EraseAllData(); } +void PlotQChart::AddSeries() { + AddSeries({ }); +} + void PlotQChart::AddSeries(const SeriesInfo& newInfo) { EmbeddablePlot2D::AddSeries(newInfo); diff --git a/src/Plotting/Backend/CoreQChart.hpp b/src/Plotting/Backend/CoreQChart.hpp index 653d92a..9ee46c1 100644 --- a/src/Plotting/Backend/CoreQChart.hpp +++ b/src/Plotting/Backend/CoreQChart.hpp @@ -9,7 +9,7 @@ namespace VSCL::Plot { class PlotContainer; -class QCHART_BACKEND PlotQChart : public EmbeddablePlot2D, public QChartView { +class QCHART_BACKEND PlotQChart : virtual public EmbeddablePlot2D { friend class PlotContainer; @@ -21,11 +21,13 @@ class QCHART_BACKEND PlotQChart : public EmbeddablePlot2D, public QChartView { virtual void SetTitle(const std::string& title) override; virtual void Plot() override; virtual void EraseAllData() override; - + + virtual void AddSeries() override; virtual void AddSeries(const SeriesInfo& newInfo) override; private: QChart* PlotChart; + QChartView* PlotChartView; QLogValueAxis* LogTimeAxisQt; QLogValueAxis* LogQuantityAxisQt; diff --git a/src/Plotting/Container.cpp b/src/Plotting/Container.cpp deleted file mode 100644 index 6598ca7..0000000 --- a/src/Plotting/Container.cpp +++ /dev/null @@ -1,25 +0,0 @@ - -#include "Container.hpp" - -namespace VSCL::Plot { - -PlotContainer::PlotContainer(QWidget* parent, EmbeddablePlot2D* newPlot) - : QWidget(parent) { - QHBoxLayout* boxlay = new QHBoxLayout(this); - boxlay->setContentsMargins(5, 5, 5, 5); - setLayout(boxlay); - - Plot = newPlot; - Plot->GetWidgetRep()->setParent(this); - - QSizePolicy plotSizePolicy; - plotSizePolicy.setHorizontalPolicy(QSizePolicy::Expanding); - plotSizePolicy.setVerticalPolicy(QSizePolicy::Expanding); - Plot->GetWidgetRep()->setSizePolicy(plotSizePolicy); - - boxlay->addWidget(Plot->GetWidgetRep()); - - Plot->Plot(); -} - -} // namespace VSCL::Plot diff --git a/src/Plotting/Container.hpp b/src/Plotting/Container.hpp deleted file mode 100644 index 45430d5..0000000 --- a/src/Plotting/Container.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include - -#include "Plot2D.hpp" -#include "PlotAPI.hpp" - -namespace VSCL::Plot { - -// The intent is to put stuff next to the embedded plot -class PLOT_API PlotContainer : public QWidget { - - Q_OBJECT; - -public: - PlotContainer(QWidget* parent, EmbeddablePlot2D* newPlot); - -private: - EmbeddablePlot2D* Plot; - -}; // class AttitudePlotContainer -} // namespace VSCL::Plot diff --git a/src/Plotting/Plot2D.cpp b/src/Plotting/Plot2D.cpp index 6480ed5..7364a3b 100644 --- a/src/Plotting/Plot2D.cpp +++ b/src/Plotting/Plot2D.cpp @@ -11,6 +11,13 @@ void EmbeddablePlot2D::AddPoint(uint8_t idx, double time, double quantity, bool oldTime.push_back(time); oldQty.push_back(quantity); + + Plot::AxisInfo axInfo = this->GetAxisInfoView(Plot::Axis::Time); + double maxTime = oldTime.back(); + double minTime = std::max(0.0, maxTime - 10.0); + axInfo.Range = { minTime, minTime + 10.0 }; + SetAxis(Plot::Axis::Time, axInfo); + if (update) Plot(); } @@ -51,8 +58,7 @@ void EmbeddablePlot2D::SetAxis(const Axis axis, const AxisInfo& info) { void EmbeddablePlot2D::SetTitle(const std::string& title) { Title = title; Plot(); } void EmbeddablePlot2D::Plot() { - if (WidgetRep) - WidgetRep->update(); + update(); } void EmbeddablePlot2D::EraseAllData() { @@ -75,12 +81,6 @@ const AxisInfo& EmbeddablePlot2D::GetAxisInfoView(Axis axis) const { }; } -QWidget* EmbeddablePlot2D::GetWidgetRep() const { return WidgetRep; } -void EmbeddablePlot2D::SetWidgetRep(QWidget* newWidgetRep) { - WidgetRep = newWidgetRep; - WidgetRep->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); -} - // Series {{{ void EmbeddablePlot2D::AddSeries() { Series.push_back(SeriesInfo()); Plot(); } void EmbeddablePlot2D::AddSeries(std::string& name) { diff --git a/src/Plotting/Plot2D.hpp b/src/Plotting/Plot2D.hpp index 6ddf998..1a69cf0 100644 --- a/src/Plotting/Plot2D.hpp +++ b/src/Plotting/Plot2D.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -13,11 +14,13 @@ namespace VSCL::Plot { // 2D plotting interface. -// The embeddable plot has at most, one figure inside of it. A figure will have multiple serieses. -// -// TODO: probably look at typical plotting implementations for scientific programming -class PLOT_API EmbeddablePlot2D { +// The embeddable plot has at most, one figure inside of it. +// A figure can have multiple series. +class PLOT_API EmbeddablePlot2D : virtual public QWidget { public: + EmbeddablePlot2D() : EmbeddablePlot2D(nullptr) { } + EmbeddablePlot2D(QWidget* parent) : QWidget(parent) { setLayout(new QHBoxLayout(this)); } + void AddPoint(uint8_t idx, double time, double quantity, bool update = false); void AddPoint(double time, double quantity, bool update = false); void AddPoints(uint8_t idx, const std::vector& times, const std::vector& quantities, bool update = false); @@ -35,9 +38,6 @@ class PLOT_API EmbeddablePlot2D { // Clear data that was being stored. virtual void EraseAllData(); - QWidget* GetWidgetRep() const; - void SetWidgetRep(QWidget* newWidgetRep); - const AxisInfo& GetAxisInfoView(Axis axis) const; /* @@ -45,7 +45,7 @@ class PLOT_API EmbeddablePlot2D { */ // Add a blank series. - void AddSeries(); + virtual void AddSeries(); // Add a named series. void AddSeries(std::string& name); // Add a series using the following info. @@ -77,8 +77,8 @@ class PLOT_API EmbeddablePlot2D { virtual void SetColor(uint8_t idx, ColorRGB& color); virtual void SetColor(ColorRGB& color); - constexpr bool GetDrawGridState() { return DrawGrid; }; - constexpr void SetDrawGridState(bool newState) { DrawGrid = newState; }; + bool GetDrawGridState() { return DrawGrid; }; + void SetDrawGridState(bool newState) { DrawGrid = newState; }; private: std::string Title; diff --git a/src/Plotting/Series.hpp b/src/Plotting/Series.hpp index b726746..5e8c83e 100644 --- a/src/Plotting/Series.hpp +++ b/src/Plotting/Series.hpp @@ -9,8 +9,8 @@ namespace VSCL::Plot { struct SeriesInfo { std::string Name = ""; - std::vector Times = { 0.0 }; - std::vector Quantities = { 0.0 }; + std::vector Times = { }; + std::vector Quantities = { }; ColorRGB Color = {1.0, 0.0, 0.0}; double Alpha = 1.0; diff --git a/src/Widgets/Displays/MultiPlotContainer.cpp b/src/Widgets/Displays/MultiPlotContainer.cpp new file mode 100644 index 0000000..6d436b5 --- /dev/null +++ b/src/Widgets/Displays/MultiPlotContainer.cpp @@ -0,0 +1,35 @@ +#include + +#include "MultiPlotContainer.hpp" +#include "Plotting/Backend/CoreQChart.hpp" + +namespace VSCL { +MultiPlotContainer::MultiPlotContainer(QWidget* parent) : QWidget(parent) { + QVBoxLayout* Organizers = new QVBoxLayout(this); + Organizers->setContentsMargins(5, 5, 5, 5); + // Organizers->setSpacing(0); + setLayout(Organizers); +} + +MultiPlotContainer::MultiPlotContainer(QWidget* parent, int n) : MultiPlotContainer(parent) { + for (int i = 0; i < n; i++) { + Plot::EmbeddablePlot2D* plot = static_cast(new Plot::PlotQChart(this)); + plot->AddSeries(); + + Plots.append(plot); + layout()->addWidget(plot); + plot->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + // plot->GetWidgetRep()->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); + } + NumberOfPlots = n; +} + +void MultiPlotContainer::resizeEvent(QResizeEvent* event) { } +QList MultiPlotContainer::GetPlots() const { + return Plots; +} + +const QList& MultiPlotContainer::GetPlotsView() const { + return Plots; +} +} // namespace VSCL \ No newline at end of file diff --git a/src/Widgets/Displays/MultiPlotContainer.hpp b/src/Widgets/Displays/MultiPlotContainer.hpp new file mode 100644 index 0000000..89ce82d --- /dev/null +++ b/src/Widgets/Displays/MultiPlotContainer.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include +#include "Plotting/Plot2D.hpp" + +namespace VSCL { +class MultiPlotContainer : public QWidget { + + Q_OBJECT; + +public: + MultiPlotContainer(QWidget* parent); + MultiPlotContainer(QWidget* parent, int n); + virtual void resizeEvent(QResizeEvent *event) override; + + QList GetPlots() const; + const QList& GetPlotsView() const; + +private: + QList Plots; + int NumberOfPlots; + +}; // class MultiPlotContainer +} // namespace VSCL diff --git a/src/Widgets/Displays/QuantitiesRatesRow.cpp b/src/Widgets/Displays/QuantitiesRatesRow.cpp index 19df44c..564f99f 100644 --- a/src/Widgets/Displays/QuantitiesRatesRow.cpp +++ b/src/Widgets/Displays/QuantitiesRatesRow.cpp @@ -28,7 +28,7 @@ void QtyRateRow::resizeEvent(QResizeEvent* event) { } void QtyRateRow::AdjustFontSize() { - unsigned int tpt = static_cast(TitleFontAdjustment.AdjustPxSize(window())); + uint32_t tpt = static_cast(TitleFontAdjustment.AdjustPxSize(window())); if (tpt <= TitleFontAdjustment.PxSizeAtMinimum) { setTitle(tr("")); TitleFont.setPixelSize(1); diff --git a/src/Windowing/WidgetsRecreation.cpp b/src/Windowing/WidgetsRecreation.cpp index 8061f75..2010607 100644 --- a/src/Windowing/WidgetsRecreation.cpp +++ b/src/Windowing/WidgetsRecreation.cpp @@ -3,7 +3,6 @@ #include #include "WidgetsRecreation.hpp" -#include "Plotting/Backend/CoreGR.hpp" #include "Plotting/Backend/CoreQChart.hpp" // stupid temp thing {{{ @@ -44,13 +43,14 @@ Widgets::Widgets() { // Set up the static layout SetupCentralWidget(); SetupAttitudeDials(); - SetupTimeHistoryPlotQChart(); + // SetupTimeHistoryPlotQChart(); // <- old plot + SetupMultiPlot(); // <-new multiplot SetupAttQtysRatesDisplay(); SetupButtons(); + SetupStatusColumn(); SetGridColumnsMinimums(); SetGridRowsMinimums(); - ButtonFont = QFont(); SetAllButtonTextSize(); SetRoll(-32); @@ -154,6 +154,11 @@ void Widgets::SetupButtons() { LoadTestRoutineButton = new QPushButton(this); LoadTestRoutineButton->setText(tr("Load Test Routine")); + ArmedButton = new QPushButton(this); + ArmedButton->setText(tr("Disarmed")); + ArmedButton->setStyleSheet(" QPushButton { background-color: Yellow; color: Black; } } "); + connect(ArmedButton, &QPushButton::clicked, this, &Widgets::OnArmedButtonPressed); + QuantityCalculatorButton = new QPushButton(this); QuantityCalculatorButton->setText(tr("Calculate Quantity")); @@ -177,6 +182,9 @@ void Widgets::SetupStatusColumn() { LoadTestRoutineButton->setSizePolicy(vhexpanding); StatusColumnOrganizer->addWidget(LoadTestRoutineButton); + ArmedButton->setSizePolicy(vhexpanding); + StatusColumnOrganizer->addWidget(ArmedButton); + QuantityCalculatorButton->setSizePolicy(vhexpanding); StatusColumnOrganizer->addWidget(QuantityCalculatorButton); @@ -192,6 +200,7 @@ void Widgets::SetupStatusColumn() { void Widgets::SetAllButtonTextSize() { ButtonFont.setPixelSize(ButtonFontAdjustment.AdjustPxSize(window())); LoadTestRoutineButton->setFont(ButtonFont); + ArmedButton->setFont(ButtonFont); QuantityCalculatorButton->setFont(ButtonFont); LogOpenButton->setFont(ButtonFont); AbortButton->setFont(ButtonFont); @@ -199,40 +208,44 @@ void Widgets::SetAllButtonTextSize() { } // void Widgets::SetAllButtonTextSize() // }}} -void Widgets::SetupTimeHistoryPlotGR() { - Plot = new Plot::PlotGR(this); - TimeHistory = new Plot::PlotContainer(MajorContainer, Plot); - MajorLayout->addWidget(TimeHistory, 1, 0); +void Widgets::SetupMultiPlot() { + Plots = new MultiPlotContainer(this, 3); + MajorLayout->addWidget(Plots, 1, 0); + QList allPlots = Plots->GetPlots(); Plot::AxisInfo axInfo; axInfo.Range = { 0, 10 }; - axInfo.MajorSpacing = 10; - axInfo.MinorSpacing = 0.25; - Plot->SetAxis(Plot::Axis::Time, axInfo); - Plot::SeriesInfo rollInfo; - rollInfo.Name = "Roll"; - rollInfo.Color = Plot::RGBFromColorGR(Plot::ColorGR::Red); + Plot::AxisInfo justWtv; + justWtv.Range = {-180, 180}; + justWtv.MajorSpacing = 180; + justWtv.MinorSpacing = 45; - Plot::SeriesInfo pitchInfo; - pitchInfo.Name = "Pitch"; - pitchInfo.Color = Plot::RGBFromColorGR(Plot::ColorGR::Blue); + std::array RPY = {"Roll", "Pitch", "Yaw"}; + auto angle = RPY.begin(); + auto color = Plot::StandardColor.begin(); - Plot::SeriesInfo yawInfo; - yawInfo.Name = "Yaw"; - yawInfo.Color = Plot::RGBFromColorGR(Plot::ColorGR::Green); + for (Plot::EmbeddablePlot2D* p : allPlots) { + std::string name = *angle; + Plot::ColorRGB rgb = color->second; + Plot::SeriesInfo info; + info.Name = name; + info.Color = rgb; - Plot->SetSeries(0, rollInfo); - Plot->AddSeries(pitchInfo); - Plot->AddSeries(yawInfo); + p->AddSeries(info); - stupid_make_data(Plot); -} // void Widgets::SetupTimeHistoryPlotGR() + justWtv.Title = name; + p->SetAxis(Plot::Axis::Quantity, justWtv); + p->SetAxis(Plot::Axis::Time, axInfo); + + angle++; + color++; + } +} void Widgets::SetupTimeHistoryPlotQChart() { Plot = new Plot::PlotQChart(this); - TimeHistory = new Plot::PlotContainer(MajorContainer, Plot); - MajorLayout->addWidget(TimeHistory, 1, 0); + MajorLayout->addWidget(Plot, 1, 0); Plot::AxisInfo axInfo; axInfo.Range = { 0, 10 }; @@ -304,6 +317,20 @@ void Widgets::CreateActions() { AboutAct->setStatusTip(tr("Show the application's About box")); connect(AboutAct, &QAction::triggered, this, &Widgets::About); } // void Widgets::CreateActions() + +void Widgets::OnArmedButtonPressed() { + bArmedButtonActive = !bArmedButtonActive; + + if (bArmedButtonActive) { + // Active state - green color + ArmedButton->setText(tr("Armed")); + ArmedButton->setStyleSheet(" QPushButton { background-color: red; color: white; } } "); + } else { + // Inactive state - default color + ArmedButton->setText(tr("Disarmed")); + ArmedButton->setStyleSheet(" QPushButton { background-color: Yellow; color: Black; } } "); + } +} // void Widgets::OnArmedButtonPressed() // }}} } // namespace VSCL::FromPpt // vim: foldmethod=marker diff --git a/src/Windowing/WidgetsRecreation.hpp b/src/Windowing/WidgetsRecreation.hpp index 49d2768..3da5513 100644 --- a/src/Windowing/WidgetsRecreation.hpp +++ b/src/Windowing/WidgetsRecreation.hpp @@ -6,8 +6,9 @@ #include "Widgets/Dial/Composite.hpp" #include "Widgets/Displays/QuantitiesRatesDisplay.hpp" #include "Widgets/Displays/QuantitiesRatesRow.hpp" -#include "Plotting/Container.hpp" +#include "Plotting/Plot2D.hpp" #include "Util/Sizing.hpp" +#include "Widgets/Displays/MultiPlotContainer.hpp" namespace VSCL::FromPpt { class Widgets : public QMainWindow { @@ -24,7 +25,7 @@ class Widgets : public QMainWindow { void SetYawRate(double yaw); private: - QFont ButtonFont; + QFont ButtonFont{ }; QWidget* MajorContainer; QGridLayout* MajorLayout; @@ -42,8 +43,9 @@ class Widgets : public QMainWindow { void SetupAttitudeDials(); Plot::EmbeddablePlot2D* Plot; - Plot::PlotContainer* TimeHistory; - void SetupTimeHistoryPlotGR(); + MultiPlotContainer* Plots; + void SetupMultiPlot(); + void SetupTimeHistoryPlotQChart(); QtyRateDisplay* AttQtysRates; @@ -56,17 +58,18 @@ class Widgets : public QMainWindow { QGroupBox* StatusColumn; QVBoxLayout* StatusColumnOrganizer; QPushButton* LoadTestRoutineButton; + QPushButton* ArmedButton; QPushButton* QuantityCalculatorButton; QPushButton* LogOpenButton; QPushButton* AbortButton; + bool bArmedButtonActive = false; // Track armed button state Util::FontAdjustment ButtonFontAdjustment{ 12 }; void SetupButtons(); void SetupStatusColumn(); void SetAllButtonTextSize(); - -// Menubar and Actions {{{ private slots: void About(); + void OnArmedButtonPressed(); private: void CreateActions(); diff --git a/vcpkg.json b/vcpkg.json deleted file mode 100644 index fcda80c..0000000 --- a/vcpkg.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", - "name": "testrig-gui", - "dependencies": [ - "zlib", - "libjpeg-turbo", - "libpng", - "qhull", - "cairo", - "opengl" - ] -}