diff --git a/CMakeLists.txt b/CMakeLists.txt index 0192228..9d53b1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,8 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") include(FetchContent) include("./cmake/cpp.cmake") -include("./cmake/qml.cmake") +include(target_compile_warn_all) +include(target_copy_dll) qt_standard_project_setup(REQUIRES 6.10) find_package(yaml-cpp) @@ -22,15 +23,13 @@ find_package(yaml-cpp) add_subdirectory("${UTIL_SRC_DIR}/Filesystem") add_subdirectory("${PLOTTING_SRC_DIR}") -# Widgets Recreation -qt_add_executable(widgets_recreation WIN32 MACOSX_BUNDLE - "${WINDOWING_SRC_DIR}/WidgetsRecreation.cpp" - ${OTHER_APP_SOURCES} ${WIDGET_SOURCES}) - -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 VSCL::Plot::QChart) +qt_add_executable(testrig_gui WIN32 + ${APP_SOURCES} ${WIDGET_SOURCES}) +target_include_directories(testrig_gui PRIVATE ${STD_APP_INCLUDES}) +target_compile_warn_all(testrig_gui) +target_link_libraries(testrig_gui PRIVATE ${STD_APP_QT6_DEPS}) +target_link_libraries(testrig_gui PRIVATE VSCL::Plot::QChart) +target_link_libraries(testrig_gui PRIVATE VSCL::FS) +add_executable(VSCL::TestrigGUI ALIAS testrig_gui) add_subdirectory("${CMAKE_SOURCE_DIR}/test") diff --git a/cmake/cpp.cmake b/cmake/cpp.cmake index 364fd90..472ec2e 100644 --- a/cmake/cpp.cmake +++ b/cmake/cpp.cmake @@ -11,23 +11,14 @@ set(PLOTTING_SRC_DIR "${CMAKE_SOURCE_DIR}/src/Plotting") set(UTIL_SRC_DIR "${CMAKE_SOURCE_DIR}/src/Util") set(APP_SOURCES - "${CMAKE_SOURCE_DIR}/src/App/Main.cpp") - -# sorry -set(OTHER_APP_SOURCES - "${CMAKE_SOURCE_DIR}/src/App/testMultiplot.cpp") - -set(WINDOWING_SOURCES - "${WINDOWING_SRC_DIR}/DevWindow.cpp" - "${WINDOWING_SRC_DIR}/NumericTestWidget.cpp") + "${CMAKE_SOURCE_DIR}/src/Main.cpp" + "${WINDOWING_SRC_DIR}/MainWindow.cpp") set(DIAL_SOURCES "${WIDGETS_SRC_DIR}/Dial/Attitude.cpp" "${WIDGETS_SRC_DIR}/Dial/Composite.cpp") 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/MultiPlotContainer.cpp" "${WIDGETS_SRC_DIR}/Displays/StatusCollector.cpp") @@ -54,33 +45,3 @@ set(STD_APP_QT6_DEPS Qt6::Quick Qt6::Widgets Qt6::QuickWidgets) - -function(target_compile_warn_all IN_TARGET_NAME) - if (MSVC) - target_compile_options(${IN_TARGET_NAME} PRIVATE "/W4") - else() - target_compile_options(${IN_TARGET_NAME} PRIVATE "-Wall") - endif() -endfunction(target_compile_warn_all) - -function(add_subdirectory_silence_warnings IN_DIRECTORY) - get_directory_property(oldCompileOpts COMPILE_OPTIONS) - - if (MSVC) - add_compile_options("/W0") - else() - add_compile_options("-w") - endif() - add_subdirectory("${IN_DIRECTORY}" EXCLUDE_FROM_ALL) - - set_directory_properties(PROPERTIES COMPILE_OPTIONS "${oldCompileOpts}") -endfunction(add_subdirectory_silence_warnings IN_DIRECTORY) - -function(target_copy_dll IN_TARGET) - if (WIN32) - add_custom_command(TARGET ${IN_TARGET} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - $ $ - COMMAND_EXPAND_LISTS) - endif() -endfunction(target_copy_dll IN_TARGET) diff --git a/cmake/qml.cmake b/cmake/qml.cmake deleted file mode 100644 index e69de29..0000000 diff --git a/cmake/target_compile_warn_all.cmake b/cmake/target_compile_warn_all.cmake new file mode 100644 index 0000000..250e1ae --- /dev/null +++ b/cmake/target_compile_warn_all.cmake @@ -0,0 +1,7 @@ +function(target_compile_warn_all IN_TARGET_NAME) + if (MSVC) + target_compile_options(${IN_TARGET_NAME} PRIVATE "/W4") + else() + target_compile_options(${IN_TARGET_NAME} PRIVATE "-Wall") + endif() +endfunction(target_compile_warn_all) diff --git a/cmake/target_copy_dll.cmake b/cmake/target_copy_dll.cmake new file mode 100644 index 0000000..0fbb2e4 --- /dev/null +++ b/cmake/target_copy_dll.cmake @@ -0,0 +1,8 @@ +function(target_copy_dll IN_TARGET) + if (WIN32) + add_custom_command(TARGET ${IN_TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + $ $ + COMMAND_EXPAND_LISTS) + endif() +endfunction(target_copy_dll IN_TARGET) diff --git a/src/App/Main.cpp b/src/App/Main.cpp deleted file mode 100644 index 6536d7d..0000000 --- a/src/App/Main.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include - -#include "Windowing/DevWindow.hpp" - -int main(int argc, char** argv) { - QApplication app(argc, argv); - - VSCL::DevWindow window; - if (argc > 1) { window.SetQMLFromPath(QUrl::fromLocalFile(argv[1])); } - - window.show(); - return app.exec(); -} diff --git a/src/App/Recreation.cpp b/src/App/Recreation.cpp deleted file mode 100644 index b0d3f38..0000000 --- a/src/App/Recreation.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#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/App/testMultiplot.cpp b/src/App/testMultiplot.cpp deleted file mode 100644 index fa514f8..0000000 --- a/src/App/testMultiplot.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#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/Main.cpp b/src/Main.cpp new file mode 100644 index 0000000..50921e0 --- /dev/null +++ b/src/Main.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +#include "Windowing/MainWindow.hpp" +#include "Util/Filesystem/Config.hpp" +#include "Util/Filesystem/State.hpp" + +namespace fs = std::filesystem; + +static VSCL::Settings settings{}; +static VSCL::State state{}; + +int main(int argc, char** argv) { + QApplication app(argc, argv); + + fs::path cfg = VSCL::FS::GetConfigFile(); + if (!fs::is_regular_file(cfg)) { + std::ofstream streem(cfg.string()); + streem << VSCL::FS::SerializeConfigToYAML(settings); + } + else { + settings = VSCL::FS::ReadConfig(cfg); + } + + fs::path stat = VSCL::FS::GetStateFile(); + if (!fs::is_regular_file(stat)) { + std::ofstream streem(stat.string()); + streem << VSCL::FS::SerializeStateToYAML(state); + } + + VSCL::MainWindow window; + + QString message = window.tr("Test Rig Operations"); + window.statusBar()->showMessage(message); + + window.setWindowTitle(window.tr("VSCL Gyroscopic Test Rig")); + window.setMinimumSize( + VSCL::Util::MINIMUM_WIDTH, VSCL::Util::MINIMUM_HEIGHT); + + window.resize(VSCL::Util::MINIMUM_WIDTH, VSCL::Util::MINIMUM_HEIGHT); + + window.show(); + return app.exec(); +} diff --git a/src/Util/Filesystem/Config.cpp b/src/Util/Filesystem/Config.cpp index 0bcd289..28a5909 100644 --- a/src/Util/Filesystem/Config.cpp +++ b/src/Util/Filesystem/Config.cpp @@ -8,7 +8,6 @@ namespace stdfs = std::filesystem; namespace VSCL::FS { - stdfs::path GetConfigFile() { constexpr std::string_view cfgwhere = GetStandardPath("config"); return GetUserAppData() / cfgwhere / "config.yaml"; @@ -32,6 +31,24 @@ YAML::Node SerializeConfigToYAML(const VSCL::Settings& settings) { return top_lvl; } +VSCL::Settings DeserializeConfigFromYAML(const YAML::Node& serialized) { + if (!serialized["Data"] && !serialized["Connection"]) return VSCL::Settings{}; + + const YAML::Node& data = serialized["Data"]; + const YAML::Node& conn = serialized["Connection"]; + + return VSCL::Settings { + .Data { + .OutputDirectory = stdfs::path(data["OutputDirectory"].as()), + .LogPrefix = data["LogPrefix"].as(), + }, + .Connect { + .DefaultInterface = conn["DefaultInterface"].as(), + .DefaultGatewayPort = conn["DefaultGatewayPort"].as(), + }, + }; +} + void WriteConfig(const VSCL::Settings& settings) { YAML::Node yamlized = SerializeConfigToYAML(settings); @@ -40,4 +57,8 @@ void WriteConfig(const VSCL::Settings& settings) { cfg << yamlized; } +VSCL::Settings ReadConfig(const std::filesystem::path& path) { + YAML::Node yamlized = YAML::LoadFile(path.string()); + return DeserializeConfigFromYAML(yamlized); +} } // namespace VSCL::FS diff --git a/src/Util/Filesystem/Config.hpp b/src/Util/Filesystem/Config.hpp index 675fa8a..8c2a966 100644 --- a/src/Util/Filesystem/Config.hpp +++ b/src/Util/Filesystem/Config.hpp @@ -7,6 +7,9 @@ namespace VSCL::FS { std::filesystem::path GetConfigFile(); YAML::Node SerializeConfigToYAML(const VSCL::Settings& settings); +VSCL::Settings DeserializeConfigFromYAML(const YAML::Node& serialized); + void WriteConfig(const VSCL::Settings& settings); +VSCL::Settings ReadConfig(const std::filesystem::path& path); } // namespace VSCL::FS diff --git a/src/Util/Filesystem/Settings.hpp b/src/Util/Filesystem/Settings.hpp index da2264b..87dbb8d 100644 --- a/src/Util/Filesystem/Settings.hpp +++ b/src/Util/Filesystem/Settings.hpp @@ -5,7 +5,7 @@ namespace VSCL { struct DataSettings { // Where to output recorded data std::filesystem::path OutputDirectory = - FS::GetUserAppData() / FS::GetStandardPath("config"); + FS::GetUserAppData() / FS::GetStandardPath("data"); // Data csv log prefix std::string LogPrefix = "run"; diff --git a/src/Util/Filesystem/State.cpp b/src/Util/Filesystem/State.cpp index beb7b79..a0b81bb 100644 --- a/src/Util/Filesystem/State.cpp +++ b/src/Util/Filesystem/State.cpp @@ -1,4 +1,7 @@ #include +#include +#include + #include "UserPaths.hpp" #include "State.hpp" @@ -17,6 +20,7 @@ stdfs::path GetStateFile() { YAML::Node SerializeStateToYAML(const VSCL::State& state) { YAML::Node top_lvl; top_lvl["LatestSocket"] = state.LatestSocket.string(); + top_lvl["LatestRecord"] = std::format("{}", std::chrono::utc_clock::now()); return top_lvl; } diff --git a/src/Widgets/Displays/QuantitiesRatesDisplay.cpp b/src/Widgets/Displays/QuantitiesRatesDisplay.cpp deleted file mode 100644 index 10ac802..0000000 --- a/src/Widgets/Displays/QuantitiesRatesDisplay.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "QuantitiesRatesDisplay.hpp" -#include "QuantitiesRatesRow.hpp" - -namespace VSCL { - -QtyRateDisplay::QtyRateDisplay(const QString& title, QWidget* parent) - : QGroupBox(title, parent) - , Organizer(new QVBoxLayout(this)) { - Organizer->setContentsMargins(10, 10, 10, 10); - setLayout(Organizer); -}; - -const QList& QtyRateDisplay::GetRowsView() const { return Rows; } -void QtyRateDisplay::AddRow(QtyRateRow* new_row) { Rows.append(new_row); Organizer->addWidget(new_row); } - -} // namespace VSCL diff --git a/src/Widgets/Displays/QuantitiesRatesDisplay.hpp b/src/Widgets/Displays/QuantitiesRatesDisplay.hpp deleted file mode 100644 index 20f7164..0000000 --- a/src/Widgets/Displays/QuantitiesRatesDisplay.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include - -namespace VSCL { - -class QtyRateRow; - -class QtyRateDisplay : public QGroupBox { - - Q_OBJECT; - friend class QtyRateRow; - -public: - QtyRateDisplay(const QString& title, QWidget* parent = nullptr); - - const QList& GetRowsView() const; - -protected: - void AddRow(QtyRateRow* new_row); - -private: - QList Rows; - - QVBoxLayout* Organizer; - -}; // class QtyRateDisplay -} // namespace VSCL diff --git a/src/Widgets/Displays/QuantitiesRatesRow.cpp b/src/Widgets/Displays/QuantitiesRatesRow.cpp deleted file mode 100644 index bfdb72c..0000000 --- a/src/Widgets/Displays/QuantitiesRatesRow.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "QuantitiesRatesRow.hpp" -#include "QuantitiesRatesDisplay.hpp" - -namespace VSCL { -QtyRateRow::QtyRateRow(const QString& title, QtyRateDisplay* parent) - : QGroupBox(title, parent) - , Title(title) - , Organizer(new QHBoxLayout(this)) - , QuantityLabel(new QLabel(this)) - , RateLabel(new QLabel(this)) { - - parent->AddRow(this); - setLayout(Organizer); - - Organizer->setContentsMargins(5, 5, 5, 5); - Organizer->addWidget(QuantityLabel); - Organizer->addWidget(RateLabel); - - QuantityLabel->setText(QString::number(Quantity) + QuantityUnits); - RateLabel->setText(QString::number(Rate) + RateUnits); - - AdjustFontSize(); -} - -void QtyRateRow::resizeEvent(QResizeEvent* event) { - QGroupBox::resizeEvent(event); - AdjustFontSize(); -} - -void QtyRateRow::AdjustFontSize() { - uint32_t tpt = static_cast(TITLE_FONT_ADJUSTMENT.AdjustPxSize(window())); - if (tpt <= TITLE_FONT_ADJUSTMENT.PxSizeAtMinimum) { - setTitle(tr("")); - TitleFont.setPixelSize(1); - } - else { - setTitle(Title); - TitleFont.setPixelSize(tpt); - } - - setFont(TitleFont); - - LabelFont.setPixelSize(NUMERIC_FONT_ADJUSTMENT.AdjustPxSize(window())); - QuantityLabel->setFont(LabelFont); - RateLabel->setFont(LabelFont); -} - -void QtyRateRow::SetQuantity(double new_quantity) { - Quantity = new_quantity; - QuantityLabel->setText(QString::number(Quantity) + QuantityUnits); -} -void QtyRateRow::SetRate(double new_rate) { - Rate = new_rate; - RateLabel->setText(QString::number(Rate) + RateUnits); -} - -void QtyRateRow::SetQuantityUnits(const QString& units) { QuantityUnits = units; } -void QtyRateRow::SetRateUnits(const QString& units) { RateUnits = units; } - -} // namespace VSCL - diff --git a/src/Widgets/Displays/QuantitiesRatesRow.hpp b/src/Widgets/Displays/QuantitiesRatesRow.hpp deleted file mode 100644 index ea5f607..0000000 --- a/src/Widgets/Displays/QuantitiesRatesRow.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include -#include "Util/Sizing.hpp" - -namespace VSCL { - -class QtyRateDisplay; - -class QtyRateRow : public QGroupBox { - - Q_OBJECT; - friend class QtyRateDisplay; - -public: - QtyRateRow(const QString& title, QtyRateDisplay* parent); - virtual void resizeEvent(QResizeEvent* event); - - void SetQuantity(double new_quantity); - void SetRate(double new_rate); - - void SetQuantityUnits(const QString& units); - void SetRateUnits(const QString& units); - -private: - - double Quantity = 0.0; - double Rate = 0.0; - - QString QuantityUnits = tr(""); - QString RateUnits = tr("/s"); - - QString Title; - QFont TitleFont{ }; - QFont LabelFont{ }; - - QHBoxLayout* Organizer; - QLabel* QuantityLabel; - QLabel* RateLabel; - - void AdjustFontSize(); - static constexpr Util::FontAdjustment TITLE_FONT_ADJUSTMENT { - .PxSizeAtMinimum = 8, - .AdjustToWidth = false - }; - - static constexpr Util::FontAdjustment NUMERIC_FONT_ADJUSTMENT { - .PxSizeAtMinimum = 8, - .AdjustToWidth = false - }; - -}; // class QtyRateDisplay -} // namespace VSCL diff --git a/src/Widgets/Displays/StatusCollector.cpp b/src/Widgets/Displays/StatusCollector.cpp index 2a4041e..2eea1e0 100644 --- a/src/Widgets/Displays/StatusCollector.cpp +++ b/src/Widgets/Displays/StatusCollector.cpp @@ -11,11 +11,6 @@ QString BuildStatusStyleSheet(const QString& object_name, Status status) { " border-radius: 5px;" " margin-top: 20px;" "}" - " QGroupBox#statusColumn::title {" - " subcontrol-origin: margin;" - " subcontrol-position: top left;" - " padding: 0 0px;" - "}" ).arg(object_name).arg(QString::fromStdString(color)); } diff --git a/src/Windowing/DevWindow.cpp b/src/Windowing/DevWindow.cpp deleted file mode 100644 index 097786c..0000000 --- a/src/Windowing/DevWindow.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include - -#include - -#include "DevWindow.hpp" -#include "Dial/Attitude.hpp" - -namespace VSCL { -DevWindow::DevWindow() - : QMainWindow() - , Stacker(new QStackedWidget(this)) - , MainQuick(new QQuickWidget(this)) - { - - AttitudeDial* dial = new AttitudeDial(this); - NumericDisplaysTest = new NumericTestWidget(this, dial, [dial](int new_value) { dial->SetDialAngle(new_value); }); - - setCentralWidget(Stacker); - Stacker->addWidget(MainQuick); - Stacker->addWidget(NumericDisplaysTest); - - QLayout* layout = Stacker->layout(); - layout->setContentsMargins(5, 5, 5, 5); - - CreateActions(); - CreateMenus(); - - QString message = tr("Howdy"); - statusBar()->showMessage(message); - - setWindowTitle(tr("VSCL Gyroscopic Test Rig")); - setMinimumSize(160, 160); - resize(720, 480); -} // void DevWindow::DevWindow() - -void DevWindow::SetQMLFromPath(const QUrl& path) { - MainQuick->setSource(path); - CurrentQML = path; -} - -void DevWindow::SwapSetting() { - switch (CurrentSetting) { - case DevWindow::NUMERIC_TESTING: - Stacker->setCurrentIndex(1); - CurrentSetting = DevWindow::QML_VIEW; - break; - case DevWindow::QML_VIEW: - Stacker->setCurrentIndex(0); - CurrentSetting = DevWindow::NUMERIC_TESTING; - break; - } -} - -void DevWindow::OpenQML() { - std::string currentWd = std::filesystem::current_path().string(); - const char* cwd = currentWd.c_str(); - QUrl qmlPath = QFileDialog::getOpenFileUrl(this, - tr("Open QML Source"), QUrl::fromLocalFile(cwd), - tr("QML Sources (*.qml)")); - - SetQMLFromPath(qmlPath); -} // void DevWindow::OpenQML() - -void DevWindow::ReloadQML() { - SetQMLFromPath(CurrentQML); -} // void DevWindow::ReloadQML() - -void DevWindow::About() { - QMessageBox::about(this, tr("About"), - tr("Currently in development mode.")); -} // void DevWindow::About() - -void DevWindow::CreateMenus() { - FileMenu = menuBar()->addMenu(tr("&File")); - FileMenu->addAction(QMLLoadAct); - FileMenu->addAction(SwapSettingAct); - FileMenu->addSeparator(); - FileMenu->addAction(ExitAct); - - EditMenu = menuBar()->addMenu(tr("&Edit")); - EditMenu->addAction(ReloadAct); - - HelpMenu = menuBar()->addMenu(tr("&Help")); - HelpMenu->addAction(AboutAct); -} // void DevWindow::CreateMenus() - -void DevWindow::CreateActions() { - QMLLoadAct = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::DocumentOpen), - tr("Load QML"), this); - QMLLoadAct->setShortcuts(QKeySequence::Open); - QMLLoadAct->setStatusTip(tr("Load QML into the viewport.")); - connect(QMLLoadAct, &QAction::triggered, this, &DevWindow::OpenQML); - - SwapSettingAct = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::DocumentOpen), - tr("Change Setting"), this); - SwapSettingAct->setShortcuts(QKeySequence::NextChild); - SwapSettingAct->setStatusTip(tr("Change between QML viewport and numeric testing modes")); - connect(SwapSettingAct, &QAction::triggered, this, &DevWindow::SwapSetting); - - ExitAct = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::ApplicationExit), - tr("Exit"), this); - ExitAct->setShortcuts(QKeySequence::Quit); - ExitAct->setStatusTip(tr("Exit the application")); - connect(ExitAct, &QAction::triggered, this, &QWidget::close); - - ReloadAct = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::EditRedo), - tr("Reload"), this); - ReloadAct->setShortcuts(QKeySequence::Redo); - ReloadAct->setStatusTip(tr("Reload QML sources")); - connect(ReloadAct, &QAction::triggered, this, &DevWindow::ReloadQML); - - AboutAct = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::HelpAbout), - tr("&About"), this); - AboutAct->setStatusTip(tr("Show the application's About box")); - connect(AboutAct, &QAction::triggered, this, &DevWindow::About); -} // void DevWindow::CreateActions() -} // namespace VSCL diff --git a/src/Windowing/DevWindow.hpp b/src/Windowing/DevWindow.hpp deleted file mode 100644 index a232cca..0000000 --- a/src/Windowing/DevWindow.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "NumericTestWidget.hpp" - -namespace VSCL { -class DevWindow : public QMainWindow { - -public: - DevWindow(); - - enum Setting { - QML_VIEW, - NUMERIC_TESTING - }; - - void SetQMLFromPath(const QUrl& path); - void SwapSetting(); - QStackedWidget* GetStackedWidget(); - -protected: - -private slots: - void OpenQML(); - void ReloadQML(); - void About(); - -private: - Setting CurrentSetting = Setting::NUMERIC_TESTING; - QStackedWidget* Stacker; - - /* - * QML Viewer - */ - - // The Main Viewport - QQuickWidget* MainQuick; - - // Path to the currently loaded QML - QUrl CurrentQML; - - /* - * Numeric widget display testing - */ - - // The main tester view - NumericTestWidget* NumericDisplaysTest; - - /* - * Actions - */ - - void CreateActions(); - void CreateMenus(); - - QMenu* FileMenu; - QMenu* EditMenu; - QMenu* HelpMenu; - - QAction* QMLLoadAct; - QAction* ExitAct; - QAction* ReloadAct; - QAction* AboutAct; - QAction* SwapSettingAct; -}; // class DevWindow -} // namespace VSCL diff --git a/src/Windowing/MainWindow.cpp b/src/Windowing/MainWindow.cpp new file mode 100644 index 0000000..4f53d2d --- /dev/null +++ b/src/Windowing/MainWindow.cpp @@ -0,0 +1,218 @@ +#include "Windowing/MainWindow.hpp" +#include "Util/Filesystem/UserPaths.hpp" +#include "Widgets/Displays/StatusCollector.hpp" + +namespace VSCL { +MainWindow::MainWindow() + : MajorContainer(new QWidget) + + , AttitudeDialRow(new QFrame(MajorContainer)) + , RollDial(new CompositeDial(tr("Roll"), AttitudeDialRow)) + , PitchDial(new CompositeDial(tr("Pitch"), AttitudeDialRow)) + , YawDial(new CompositeDial(tr("Yaw"), AttitudeDialRow)) + + , Plots(new MultiPlotContainer(MajorContainer, 3)) + + , ActionsRow(new QGroupBox(tr(""), MajorContainer)) + , StandbyIndicator(new QPushButton(ActionsRow)) + , ArmedIndicator(new QPushButton(ActionsRow)) + , InitiateButton(new QPushButton(ActionsRow)) + , AbortButton(new QPushButton(ActionsRow)) + + , MajorLayout(new QGridLayout) // Parented when SetupCentralWidget() + , AttitudeDialOrganizer(new QVBoxLayout(AttitudeDialRow)) + , ActionsRowOrganizer(new QHBoxLayout(ActionsRow)) +{ + // Set up the static layout + SetupCentralWidget(); + SetupAttitudeDials(); + SetupMultiPlot(); + + SetupActionsRow(); + SetupButtons(); + SetAllButtonTextSize(); + + // Set up menubar and statusbar + CreateActions(); + CreateMenus(); + +} // void MainWindow::MainWindow() + +void MainWindow::resizeEvent(QResizeEvent* event) { + QMainWindow::resizeEvent(event); + + const QRect& dims = centralWidget()->geometry(); + MajorLayout->setColumnMinimumWidth( 0, 4 * dims.width() / 5); + MajorLayout->setColumnMinimumWidth( 1, 1 * dims.width() / 5); + MajorLayout->setRowMinimumHeight( 0, 4 * dims.height() / 5); + MajorLayout->setRowMinimumHeight( 1, 1 * dims.height() / 5); + + SetAllButtonTextSize(); +} // void MainWindow::resizeEvent() +// Layout and Widgets Setup {{{ +void MainWindow::SetupCentralWidget() { + setCentralWidget(MajorContainer); + + MajorContainer->setLayout(MajorLayout); + MajorLayout->setContentsMargins(35, 35, 35, 35); + + QSizePolicy majorPolicy; + majorPolicy.setHorizontalPolicy(QSizePolicy::MinimumExpanding); + majorPolicy.setVerticalPolicy(QSizePolicy::MinimumExpanding); + MajorContainer->setSizePolicy(majorPolicy); + + MajorLayout->addWidget(Plots, 0, 0); + MajorLayout->addWidget(AttitudeDialRow, 0, 1); + MajorLayout->addWidget(ActionsRow, 1, 0, 1, 2); +} // void MainWindow::SetupCentralWidget() + +void MainWindow::SetupAttitudeDials() { + AttitudeDialOrganizer->setContentsMargins(20, 20, 20, 20); + AttitudeDialRow->setLayout(AttitudeDialOrganizer); + + QSizePolicy dialsPolicy; + dialsPolicy.setHorizontalPolicy(QSizePolicy::MinimumExpanding); + dialsPolicy.setVerticalPolicy(QSizePolicy::MinimumExpanding); + AttitudeDialRow->setSizePolicy(dialsPolicy); + + AttitudeDialOrganizer->addWidget(RollDial); + AttitudeDialOrganizer->addWidget(PitchDial); + AttitudeDialOrganizer->addWidget(YawDial); +} // void MainWindow::SetupCentralWidget() + +// Buttons {{{ +void MainWindow::SetupButtons() { + StandbyIndicator->setText(tr("Standby")); + SetButtonStatus(StandbyIndicator, Status::STANDBY); + + ArmedIndicator->setText(tr("Disarmed")); + SetButtonStatus(ArmedIndicator, Status::DISARMED); + + InitiateButton->setText(tr("Initiate")); + AbortButton->setText(tr("Abort")); + AbortButton->setStyleSheet("color: red"); + + AbortFont.setBold(true); +} // void MainWindow::SetupButtons() + +void MainWindow::SetupActionsRow() { + ActionsRow->setObjectName("StatusRow"); + + SetGroupBoxStatus(ActionsRow, Status::DISARMED); + + QSizePolicy vhexpanding; + vhexpanding.setVerticalPolicy(QSizePolicy::MinimumExpanding); + vhexpanding.setHorizontalPolicy(QSizePolicy::MinimumExpanding); + + StandbyIndicator->setSizePolicy(vhexpanding); + ActionsRowOrganizer->addWidget(StandbyIndicator); + + ArmedIndicator->setSizePolicy(vhexpanding); + ActionsRowOrganizer->addWidget(ArmedIndicator); + + InitiateButton->setSizePolicy(vhexpanding); + ActionsRowOrganizer->addWidget(InitiateButton); + + AbortButton->setSizePolicy(vhexpanding); + ActionsRowOrganizer->addWidget(AbortButton); + + ActionsRow->setLayout(ActionsRowOrganizer); +} // void MainWindow::SetupActionsRow() + +void MainWindow::SetAllButtonTextSize() { + ButtonFont.setPixelSize(ButtonFontAdjustment.AdjustPxSize(window())); + + StandbyIndicator->setFont(ButtonFont); + ArmedIndicator->setFont(ButtonFont); + InitiateButton->setFont(ButtonFont); + ActionsRow->setFont(ButtonFont); + + AbortFont.setPixelSize(AbortFontAdjustment.AdjustPxSize(window())); + AbortButton->setFont(AbortFont); +} // void MainWindow::SetAllButtonTextSize() +// }}} + +void MainWindow::SetupMultiPlot() { + QList all_plts = Plots->GetPlots(); + + Plot::AxisInfo time_info; + time_info.Range = { 0, 10 }; + + Plot::AxisInfo ang_info; + ang_info.Range = {-180, 180}; + ang_info.MajorSpacing = 180; + ang_info.MinorSpacing = 45; + + std::array angels = {"Roll", "Pitch", "Yaw"}; + auto angle = angels.begin(); + auto color = Plot::STANDARD_COLOR.begin(); + + std::ranges::for_each(all_plts, + [&](Plot::EmbeddablePlot2D* plt) { + Plot::SeriesInfo info { + .Name = std::string(*angle), + .Color = color->second + }; + + plt->AddSeries(info); + plt->SetAxis(Plot::Axis::QUANTITY, ang_info); + plt->SetAxis(Plot::Axis::TIME, time_info); + + angle++; + color++; + }); +} +// }}} +// Menubar and Actions {{{ +void MainWindow::About() { + QMessageBox::about(this, tr("About"), + tr("Operations of the test rig are performed graphically through this application. " + "For more information, check the README.")); +} // void MainWindow::About() + +void MainWindow::LoadTestRoutine() { + QString fname = QFileDialog::getOpenFileName(this, + tr("Load Routine"), + QString::fromStdString(FS::GetUserAppData().string()), + tr("Python Files (*.py)")); + // TODO: IMPL ME +} + +void MainWindow::CreateMenus() { + FileMenu = menuBar()->addMenu(tr("&File")); + FileMenu->addAction(LoadAct); + FileMenu->addSeparator(); + FileMenu->addAction(ExitAct); + + EditMenu = menuBar()->addMenu(tr("&Edit")); + + HelpMenu = menuBar()->addMenu(tr("&Help")); + HelpMenu->addAction(AboutAct); +} // void MainWindow::CreateMenus() + +void MainWindow::CreateActions() { + // File Menu + LoadAct = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::DocumentOpen), + tr("Load Routine"), this); + LoadAct->setShortcuts(QKeySequence::Open); + LoadAct->setStatusTip(tr("Load a test routine from Python")); + connect(LoadAct, &QAction::triggered, this, &MainWindow::LoadTestRoutine); + + ExitAct = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::ApplicationExit), + tr("Exit"), this); + ExitAct->setShortcuts(QKeySequence::Quit); + ExitAct->setStatusTip(tr("Exit the application")); + connect(ExitAct, &QAction::triggered, this, &QWidget::close); + + // Edit Menu + + + // Help Menu + AboutAct = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::HelpAbout), + tr("&About"), this); + AboutAct->setStatusTip(tr("Show the application's About box")); + connect(AboutAct, &QAction::triggered, this, &MainWindow::About); +} // void MainWindow::CreateActions() +// }}} +} // namespace VSCL +// vim: foldmethod=marker diff --git a/src/Windowing/WidgetsRecreation.hpp b/src/Windowing/MainWindow.hpp similarity index 53% rename from src/Windowing/WidgetsRecreation.hpp rename to src/Windowing/MainWindow.hpp index bde32bd..9712952 100644 --- a/src/Windowing/WidgetsRecreation.hpp +++ b/src/Windowing/MainWindow.hpp @@ -1,79 +1,58 @@ #pragma once -#include #include #include "Widgets/Dial/Composite.hpp" -#include "Widgets/Displays/QuantitiesRatesDisplay.hpp" -#include "Widgets/Displays/QuantitiesRatesRow.hpp" -#include "Plotting/Plot2D.hpp" -#include "Util/Sizing.hpp" #include "Widgets/Displays/MultiPlotContainer.hpp" +#include "Util/Sizing.hpp" -namespace VSCL::FromPpt { -class Widgets : public QMainWindow { +namespace VSCL { +class MainWindow : public QMainWindow { + + Q_OBJECT; public: - Widgets(); + MainWindow(); virtual void resizeEvent(QResizeEvent* event) override; - void SetRoll(double roll); - void SetPitch(double pitch); - void SetYaw(double yaw); - void SetRollRate(double roll); - void SetPitchRate(double pitch); - void SetYawRate(double yaw); - private: - QFont ButtonFont{ }; - Util::FontAdjustment ButtonFontAdjustment{ .PxSizeAtMinimum=12 }; - QFont AbortFont{ }; - Util::FontAdjustment AbortFontAdjustment{ .PxSizeAtMinimum=12 }; - QWidget* MajorContainer; - QGridLayout* MajorLayout; - void SetupCentralWidget(); - void SetGridColumnsMinimums(); - void SetGridRowsMinimums(); QFrame* AttitudeDialRow; - QVBoxLayout* AttitudeDialOrganizer; - CompositeDial* RollDial; CompositeDial* PitchDial; CompositeDial* YawDial; - std::array Dials; - void SetupAttitudeDials(); - Plot::EmbeddablePlot2D* Plot; MultiPlotContainer* Plots; - void SetupMultiPlot(); - void SetupTimeHistoryPlotQChart(); - - QtyRateDisplay* AttQtysRates; - QtyRateRow* RollQtyRate; - QtyRateRow* PitchQtyRate; - QtyRateRow* YawQtyRate; - void SetupAttQtysRatesDisplay(); - - // im not entirely sure of this part - QGroupBox* StatusColumn; - QHBoxLayout* StatusColumnOrganizer; + QGroupBox* ActionsRow; QPushButton* StandbyIndicator; QPushButton* ArmedIndicator; QPushButton* InitiateButton; - QPushButton* LogOpenButton; QPushButton* AbortButton; - bool ArmedButtonActive = false; // Track armed button state + bool ArmedButtonActive = false; + + QGridLayout* MajorLayout; + QVBoxLayout* AttitudeDialOrganizer; + QHBoxLayout* ActionsRowOrganizer; + QFont ButtonFont{ }; + Util::FontAdjustment ButtonFontAdjustment{ .PxSizeAtMinimum=12 }; + QFont AbortFont{ }; + Util::FontAdjustment AbortFontAdjustment{ .PxSizeAtMinimum=12 }; + + void SetupCentralWidget(); + void SetupAttitudeDials(); + void SetupMultiPlot(); + void SetupTimeHistoryPlotQChart(); + void SetupActionsRow(); void SetupButtons(); - void SetupStatusColumn(); void SetAllButtonTextSize(); +// Actions private slots: void About(); - void OnArmedButtonPressed(); + void LoadTestRoutine(); private: void CreateActions(); @@ -83,9 +62,9 @@ private slots: QMenu* EditMenu; QMenu* HelpMenu; + QAction* LoadAct; QAction* ExitAct; QAction* AboutAct; -// }}} -}; // class Widgets -} // namespace VSCL::FromPpt +}; // class MainWindow }}} +} // namespace VSCL // vim: foldmethod=marker diff --git a/src/Windowing/NumericTestWidget.cpp b/src/Windowing/NumericTestWidget.cpp deleted file mode 100644 index e9a2899..0000000 --- a/src/Windowing/NumericTestWidget.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include - -#include "NumericTestWidget.hpp" - -namespace VSCL { - -NumericTestWidget::NumericTestWidget( - QWidget* parent, QWidget* what_to_test, - std::function method) - : QWidget(parent) - , TesterSpinbox(new QDoubleSpinBox(this)) - , WidgetBeingTested(what_to_test) { - - QGridLayout* grid = new QGridLayout(this); - grid->setContentsMargins(25, 25, 25, 25); - grid->addWidget(TesterSpinbox, 0, 0); - grid->addWidget(WidgetBeingTested, 0, 1); - setLayout(grid); - - TesterSpinbox->setRange(0.0, 360.0); - TesterSpinbox->setSuffix("°"); - TesterSpinbox->setWrapping(true); - - QSizePolicy sizePolicy; - sizePolicy.setHorizontalPolicy(QSizePolicy::Expanding); - sizePolicy.setVerticalPolicy(QSizePolicy::Expanding); - - WidgetBeingTested->setSizePolicy(sizePolicy); - - connect(TesterSpinbox, &QDoubleSpinBox::valueChanged, WidgetBeingTested, method); -} // NumericTestWidget ctor - -void NumericTestWidget::setVisible(bool visible) { - TesterSpinbox->setVisible(visible); - WidgetBeingTested->setVisible(visible); - QWidget::setVisible(visible); -} - -QDoubleSpinBox* NumericTestWidget::GetSpinbox() const { return TesterSpinbox; } -QWidget* NumericTestWidget::GetTestedWidget() const { return WidgetBeingTested; } - -} // namespace VSCL diff --git a/src/Windowing/NumericTestWidget.hpp b/src/Windowing/NumericTestWidget.hpp deleted file mode 100644 index 6c8da67..0000000 --- a/src/Windowing/NumericTestWidget.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include -#include - -namespace VSCL { -class NumericTestWidget : public QWidget { - - Q_OBJECT; - -public: - NumericTestWidget(QWidget* parent, QWidget* what_to_test, - std::function method); - - virtual void setVisible(bool visible) override; - -private: - QDoubleSpinBox* TesterSpinbox; - QWidget* WidgetBeingTested; - -public: - QDoubleSpinBox* GetSpinbox() const; - QWidget* GetTestedWidget() const; - -}; // class NumericTestWidget -} // namespace VSCL diff --git a/src/Windowing/WidgetsRecreation.cpp b/src/Windowing/WidgetsRecreation.cpp deleted file mode 100644 index 7b71200..0000000 --- a/src/Windowing/WidgetsRecreation.cpp +++ /dev/null @@ -1,339 +0,0 @@ -#include -#include -#include - -#include "WidgetsRecreation.hpp" -#include "Plotting/Backend/CoreQChart.hpp" -#include "Widgets/Displays/StatusCollector.hpp" - -// stupid temp thing {{{ -static void StupidMakeData(VSCL::Plot::EmbeddablePlot2D* plot) { - double ph1, ph2, ph3; - - std::srand(std::chrono::system_clock::now().time_since_epoch().count() + 1); - ph1 = std::rand() % 12; - std::srand(std::chrono::system_clock::now().time_since_epoch().count() + 3); - ph2 = std::rand() % 12; - std::srand(std::chrono::system_clock::now().time_since_epoch().count() + 2); - ph3 = std::rand() % 12; - - for (int i = 0; i < 100; i++) { - plot->AddPoint(0, i/10.0, std::cos(0.1 * i + ph1/12) / 2.0 + 0.5); - plot->AddPoint(1, i/10.0, std::sin(0.1 * i - ph2/12) / 2.0 + 0.5); - plot->AddPoint(2, i/10.0, std::cos(0.1 * i + ph3/12) / 2.0 + 0.5); - } - - plot->Plot(); -} -// }}} - -namespace VSCL::FromPpt { -Widgets::Widgets() { - // Set up menubar and statusbar - CreateActions(); - CreateMenus(); - - QString message = tr("Test Rig Operations"); - statusBar()->showMessage(message); - - // Geometry and window characteristics - setWindowTitle(tr("VSCL Gyroscopic Test Rig")); - setMinimumSize(Util::MINIMUM_WIDTH, Util::MINIMUM_HEIGHT); - resize(Util::MINIMUM_WIDTH, Util::MINIMUM_HEIGHT); - - // Set up the static layout - SetupCentralWidget(); - SetupAttitudeDials(); - SetupMultiPlot(); // <-new multiplot - SetupButtons(); - SetupStatusColumn(); - SetGridColumnsMinimums(); - SetGridRowsMinimums(); - - SetAllButtonTextSize(); - - SetRoll(-32); - SetPitch(5); - SetYaw(100); -} // void Widgets::Widgets() - -void Widgets::resizeEvent(QResizeEvent* event) { - QMainWindow::resizeEvent(event); - - SetGridColumnsMinimums(); - SetGridRowsMinimums(); - SetAllButtonTextSize(); -} // void Widgets::resizeEvent() - -void Widgets::SetRoll(double roll) { - RollDial->SetDialAngle(roll); - // RollQtyRate->SetQuantity(roll); -} - -void Widgets::SetPitch(double pitch) { - PitchDial->SetDialAngle(pitch); - // PitchQtyRate->SetQuantity(pitch); -} - -void Widgets::SetYaw(double yaw) { - YawDial->SetDialAngle(yaw); - // YawQtyRate->SetQuantity(yaw); -} - -void Widgets::SetRollRate(double roll) { - RollQtyRate->SetRate(roll); -} - -void Widgets::SetPitchRate(double pitch) { - PitchQtyRate->SetRate(pitch); -} - -void Widgets::SetYawRate(double yaw) { - YawQtyRate->SetRate(yaw); -} - -// Layout and Widgets Setup {{{ -void Widgets::SetupCentralWidget() { - MajorContainer = new QWidget(this); - - QSizePolicy majorPolicy; - majorPolicy.setHorizontalPolicy(QSizePolicy::MinimumExpanding); - majorPolicy.setVerticalPolicy(QSizePolicy::MinimumExpanding); - MajorContainer->setSizePolicy(majorPolicy); - - MajorLayout = new QGridLayout(MajorContainer); - MajorLayout->setContentsMargins(35, 35, 35, 35); - MajorContainer->setLayout(MajorLayout); - - setCentralWidget(MajorContainer); -} // void Widgets::SetupCentralWidget() - -void Widgets::SetupAttitudeDials() { - AttitudeDialRow = new QFrame(MajorContainer); - MajorLayout->addWidget(AttitudeDialRow, 0, 1); - - AttitudeDialOrganizer = new QVBoxLayout(AttitudeDialRow); - AttitudeDialOrganizer->setContentsMargins(20, 20, 20, 20); - AttitudeDialRow->setLayout(AttitudeDialOrganizer); - - QSizePolicy dialsPolicy; - dialsPolicy.setHorizontalPolicy(QSizePolicy::MinimumExpanding); - dialsPolicy.setVerticalPolicy(QSizePolicy::MinimumExpanding); - AttitudeDialRow->setSizePolicy(dialsPolicy); - - RollDial = new CompositeDial(QString("Roll"), AttitudeDialRow); - AttitudeDialOrganizer->addWidget(RollDial); - - PitchDial = new CompositeDial(QString("Pitch"), AttitudeDialRow); - AttitudeDialOrganizer->addWidget(PitchDial); - - YawDial = new CompositeDial(QString("Yaw"), AttitudeDialRow); - AttitudeDialOrganizer->addWidget(YawDial); - - Dials = { RollDial, PitchDial, YawDial }; -} // void Widgets::SetupCentralWidget() - -void Widgets::SetGridColumnsMinimums() { - if (!MajorLayout) { return; }; - const QRect& dims = centralWidget()->geometry(); - MajorLayout->setColumnMinimumWidth(0, 4 * dims.width() / 5); - MajorLayout->setColumnMinimumWidth(1, 1 * dims.width() / 5); -} // void Widgets::SetGridColumnsMinimums() - -void Widgets::SetGridRowsMinimums() { - if (!MajorLayout) { return; } - const QRect& dims = centralWidget()->geometry(); - MajorLayout->setRowMinimumHeight(0, 4 * dims.height() / 5); - MajorLayout->setRowMinimumHeight(1, 1 * dims.height() / 5); -} // void Widgets::SetGridRowsMinimums() - -// Buttons {{{ -void Widgets::SetupButtons() { - StandbyIndicator = new QPushButton(this); - StandbyIndicator->setText(tr("Standby")); - SetButtonStatus(StandbyIndicator, Status::STANDBY); - - ArmedIndicator = new QPushButton(this); - ArmedIndicator->setText(tr("Disarmed")); - SetButtonStatus(ArmedIndicator, Status::DISARMED); - // testing below - // connect(ArmedIndicator, &QPushButton::clicked, this, &Widgets::OnArmedButtonPressed); - - InitiateButton = new QPushButton(this); - InitiateButton->setText(tr("Initiate")); - - AbortButton = new QPushButton(this); - AbortButton->setText(tr("Abort")); - AbortButton->setStyleSheet("color: red"); - - AbortFont.setBold(true); -} // void Widgets::SetupButtons() - -void Widgets::SetupStatusColumn() { - StatusColumn = new QGroupBox(tr("Operate"), this); - StatusColumn->setObjectName("statusColumn"); - - SetGroupBoxStatus(StatusColumn, Status::DISARMED); - - MajorLayout->addWidget(StatusColumn, 1, 0, 1, 2); - - QSizePolicy vhexpanding; - vhexpanding.setVerticalPolicy(QSizePolicy::MinimumExpanding); - vhexpanding.setHorizontalPolicy(QSizePolicy::MinimumExpanding); - - StatusColumnOrganizer = new QHBoxLayout(StatusColumn); - StandbyIndicator->setSizePolicy(vhexpanding); - StatusColumnOrganizer->addWidget(StandbyIndicator); - - ArmedIndicator->setSizePolicy(vhexpanding); - StatusColumnOrganizer->addWidget(ArmedIndicator); - - InitiateButton->setSizePolicy(vhexpanding); - StatusColumnOrganizer->addWidget(InitiateButton); - - AbortButton->setSizePolicy(vhexpanding); - StatusColumnOrganizer->addWidget(AbortButton); - - StatusColumn->setLayout(StatusColumnOrganizer); -} // void Widgets::SetupStatusColumn() - -void Widgets::SetAllButtonTextSize() { - ButtonFont.setPixelSize(ButtonFontAdjustment.AdjustPxSize(window())); - StandbyIndicator->setFont(ButtonFont); - ArmedIndicator->setFont(ButtonFont); - InitiateButton->setFont(ButtonFont); - StatusColumn->setFont(ButtonFont); - - AbortFont.setPixelSize(AbortFontAdjustment.AdjustPxSize(window())); - AbortButton->setFont(AbortFont); -} // void Widgets::SetAllButtonTextSize() -// }}} - -void Widgets::SetupMultiPlot() { - Plots = new MultiPlotContainer(this, 3); - MajorLayout->addWidget(Plots, 0, 0); - QList allPlots = Plots->GetPlots(); - - Plot::AxisInfo axInfo; - axInfo.Range = { 0, 10 }; - - Plot::AxisInfo justWtv; - justWtv.Range = {-180, 180}; - justWtv.MajorSpacing = 180; - justWtv.MinorSpacing = 45; - - std::array RPY = {"Roll", "Pitch", "Yaw"}; - auto angle = RPY.begin(); - auto color = Plot::STANDARD_COLOR.begin(); - - for (Plot::EmbeddablePlot2D* p : allPlots) { - std::string name = *angle; - Plot::ColorRGB rgb = color->second; - Plot::SeriesInfo info; - info.Name = name; - info.Color = rgb; - - p->AddSeries(info); - - 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); - MajorLayout->addWidget(Plot, 1, 0); - - Plot::AxisInfo axInfo; - axInfo.Range = { 0, 10 }; - axInfo.MajorSpacing = 1; - axInfo.MinorSpacing = 0.5; - Plot->SetAxis(Plot::Axis::TIME, axInfo); - - Plot::SeriesInfo rollInfo; - rollInfo.Name = "Roll"; - rollInfo.Color = Plot::STANDARD_COLOR.at("Red"); - - Plot::SeriesInfo pitchInfo; - pitchInfo.Name = "Pitch"; - pitchInfo.Color = Plot::STANDARD_COLOR.at("Green"); - - Plot::SeriesInfo yawInfo; - yawInfo.Name = "Yaw"; - yawInfo.Color = Plot::STANDARD_COLOR.at("Blue"); - - Plot->AddSeries(rollInfo); - Plot->AddSeries(pitchInfo); - Plot->AddSeries(yawInfo); - - StupidMakeData(Plot); -} // void Widgets::SetupTimeHistoryPlotQChart() - -void Widgets::SetupAttQtysRatesDisplay() { - AttQtysRates = new QtyRateDisplay(tr(""), this); - MajorLayout->addWidget(AttQtysRates, 1, 0); - - RollQtyRate = new QtyRateRow(tr("Roll"), AttQtysRates); - RollQtyRate->SetQuantityUnits("°"); - RollQtyRate->SetRateUnits("°/s"); - PitchQtyRate = new QtyRateRow(tr("Pitch"), AttQtysRates); - PitchQtyRate->SetQuantityUnits("°"); - PitchQtyRate->SetRateUnits("°/s"); - YawQtyRate = new QtyRateRow(tr("Yaw"), AttQtysRates); - YawQtyRate->SetQuantityUnits("°"); - YawQtyRate->SetRateUnits("°/s"); -} // void Widgets::SetupAttQtyRatesDisplay() - -// }}} -// Menubar and Actions {{{ -void Widgets::About() { - QMessageBox::about(this, tr("About"), - tr("This is a recreation of the original UI layout provided.")); -} // void Widgets::About() - -void Widgets::CreateMenus() { - FileMenu = menuBar()->addMenu(tr("&File")); - FileMenu->addSeparator(); - FileMenu->addAction(ExitAct); - - EditMenu = menuBar()->addMenu(tr("&Edit")); - - HelpMenu = menuBar()->addMenu(tr("&Help")); - HelpMenu->addAction(AboutAct); -} // void Widgets::CreateMenus() - -void Widgets::CreateActions() { - ExitAct = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::ApplicationExit), - tr("Exit"), this); - ExitAct->setShortcuts(QKeySequence::Quit); - ExitAct->setStatusTip(tr("Exit the application")); - connect(ExitAct, &QAction::triggered, this, &QWidget::close); - - AboutAct = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::HelpAbout), - tr("&About"), this); - AboutAct->setStatusTip(tr("Show the application's About box")); - connect(AboutAct, &QAction::triggered, this, &Widgets::About); -} // void Widgets::CreateActions() - -void Widgets::OnArmedButtonPressed() { - ArmedButtonActive = !ArmedButtonActive; - - if (ArmedButtonActive) { - // Armed state - Red - ArmedIndicator->setText(tr("Armed")); - SetButtonStatus(ArmedIndicator, Status::ARMED); - SetGroupBoxStatus(StatusColumn, Status::ARMED); - } else { - // Disarmed state - Yellow - ArmedIndicator->setText(tr("Disarmed")); - SetButtonStatus(ArmedIndicator, Status::DISARMED); - SetGroupBoxStatus(StatusColumn, Status::DISARMED); - } -} // void Widgets::OnArmedButtonPressed() -// }}} -} // namespace VSCL::FromPpt -// vim: foldmethod=marker