diff --git a/.clangd b/.clangd index e15f8e6..6401b34 100644 --- a/.clangd +++ b/.clangd @@ -1,4 +1,4 @@ CompileFlags: - Add: [-xc++, -Wall] + Add: [-xc++, -Wall, -std=c++20] Remove: [-mno-direct-extern-access] CompilationDatabase: build diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bfdbdb..c17e6b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ project(rig_gui set(CMAKE_EXPORT_COMPILE_COMMANDS true) set(CMAKE_AUTOMOC ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_CXX_STANDARD 20) find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick Widgets QuickWidgets Charts) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") diff --git a/cmake/cpp.cmake b/cmake/cpp.cmake index 5797a34..8bf6d65 100644 --- a/cmake/cpp.cmake +++ b/cmake/cpp.cmake @@ -28,7 +28,8 @@ 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/MultiPlotContainer.cpp" + "${WIDGETS_SRC_DIR}/Displays/StatusCollector.cpp") set(WIDGET_SOURCES ${WINDOWING_SOURCES} diff --git a/src/Widgets/Dial/Composite.cpp b/src/Widgets/Dial/Composite.cpp index a3f1e3b..64a38de 100644 --- a/src/Widgets/Dial/Composite.cpp +++ b/src/Widgets/Dial/Composite.cpp @@ -15,9 +15,9 @@ CompositeDial::CompositeDial(QWidget* parent) this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); this->setLayout(MajorOrganizer); MajorOrganizer->setAlignment(Qt::AlignHCenter); - MajorOrganizer->setAlignment(DialNameLabel, Qt::AlignHCenter | Qt::AlignTop); - MajorOrganizer->addWidget(DialNameLabel, 0, 0, 1, 1); - MajorOrganizer->addWidget(DialRateDuo, 1, 0, 5, 1); + // MajorOrganizer->setAlignment(DialNameLabel, Qt::AlignCenter); + MajorOrganizer->addWidget(DialNameLabel, 0, 0); + MajorOrganizer->addWidget(DialRateDuo, 0, 1); // Set dial-rate combo layout DialRateDuo->setLayout(DuoOrganizer); @@ -30,7 +30,7 @@ CompositeDial::CompositeDial(QWidget* parent) DialNameLabel->setScaledContents(true); DialNameLabel->setFont(DialNameFont); DialNameLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); - DialNameLabel->setAlignment(Qt::AlignHCenter | Qt::AlignTop); + DialNameLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); // Set how the dial-rate combo resizes QSizePolicy expandPolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); diff --git a/src/Widgets/Displays/StatusCollector.cpp b/src/Widgets/Displays/StatusCollector.cpp new file mode 100644 index 0000000..8ba8af0 --- /dev/null +++ b/src/Widgets/Displays/StatusCollector.cpp @@ -0,0 +1,61 @@ +#include "StatusCollector.hpp" + +#include +#include + +namespace VSCL{ + +QString buildStatusStyleSheet(const std::string& objectName, Status status) { + std::string color = StatusColorMap.at(status); + + std::string sheet = std::format( + "QGroupBox#{} {{" + " border: 2px solid {};" + " border-radius: 5px;" + " margin-top: 20px;" + "}}" + "QGroupBox#statusColumn::title {{" + " subcontrol-origin: margin;" + " subcontrol-position: top left;" + " padding: 0 0px;" + "}}", + objectName, + color + ); + + return QString::fromStdString(sheet); +} + +void setGroupBoxStatus(QGroupBox *box, Status status) { + const std::string objectName = box->objectName().toStdString(); + QString sheet = buildStatusStyleSheet(objectName, status); + + box->setStyleSheet(sheet); + + box->style()->unpolish(box); + box->style()->polish(box); + box->update(); +} + +QString buildButtonStyleSheet(Status status) { + std::string color = StatusColorMap.at(status); + + std::string sheet = std::format( + " QPushButton {{ background-color: {}; color: black; }}", + color + ); + + return QString::fromStdString(sheet); +} + +void setButtonStatus(QPushButton* button, Status status) { + QString sheet = buildButtonStyleSheet(status); + + button->setStyleSheet(sheet); + + button->style()->unpolish(button); + button->style()->polish(button); + button->update(); +} + +} // namespace VSCL diff --git a/src/Widgets/Displays/StatusCollector.hpp b/src/Widgets/Displays/StatusCollector.hpp new file mode 100644 index 0000000..4e7defe --- /dev/null +++ b/src/Widgets/Displays/StatusCollector.hpp @@ -0,0 +1,33 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace VSCL { +enum class Status { + Armed, // Red + Disarmed, // White + Standby, // White # true/false of Standby + Active, // Yellow + Opened, // Green + Closed // Grey +}; + +static const std::map StatusColorMap = { + {Status::Armed, "red"}, + {Status::Disarmed, "#fbfbfb"}, + {Status::Standby, "#fbfbfb"}, + {Status::Active, "yellow"}, + {Status::Opened, "green"}, + {Status::Closed, "gray"} +}; + +QString buildStatusStyleSheet(const std::string& objectName, Status status); +void setGroupBoxStatus(QGroupBox* box, Status status); + +QString buildButtonStyleSheet(Status status); +void setButtonStatus(QPushButton* button, Status status); + +} // namespace VSCL \ No newline at end of file diff --git a/src/Windowing/WidgetsRecreation.cpp b/src/Windowing/WidgetsRecreation.cpp index 2010607..9c6e220 100644 --- a/src/Windowing/WidgetsRecreation.cpp +++ b/src/Windowing/WidgetsRecreation.cpp @@ -4,6 +4,7 @@ #include "WidgetsRecreation.hpp" #include "Plotting/Backend/CoreQChart.hpp" +#include "Widgets/Displays/statusCollector.hpp" // stupid temp thing {{{ static void stupid_make_data(VSCL::Plot::EmbeddablePlot2D* plot) { @@ -45,7 +46,7 @@ Widgets::Widgets() { SetupAttitudeDials(); // SetupTimeHistoryPlotQChart(); // <- old plot SetupMultiPlot(); // <-new multiplot - SetupAttQtysRatesDisplay(); + // SetupAttQtysRatesDisplay(); // <- No need anymore SetupButtons(); SetupStatusColumn(); SetGridColumnsMinimums(); @@ -68,17 +69,17 @@ void Widgets::resizeEvent(QResizeEvent* event) { void Widgets::SetRoll(double roll) { RollDial->SetDialAngle(roll); - RollQtyRate->SetQuantity(roll); + // RollQtyRate->SetQuantity(roll); } void Widgets::SetPitch(double pitch) { PitchDial->SetDialAngle(pitch); - PitchQtyRate->SetQuantity(pitch); + // PitchQtyRate->SetQuantity(pitch); } void Widgets::SetYaw(double yaw) { YawDial->SetDialAngle(yaw); - YawQtyRate->SetQuantity(yaw); + // YawQtyRate->SetQuantity(yaw); } void Widgets::SetRollRate(double roll) { @@ -93,7 +94,6 @@ void Widgets::SetYawRate(double yaw) { YawQtyRate->SetRate(yaw); } - // Layout and Widgets Setup {{{ void Widgets::SetupCentralWidget() { MajorContainer = new QWidget(this); @@ -112,9 +112,9 @@ void Widgets::SetupCentralWidget() { void Widgets::SetupAttitudeDials() { AttitudeDialRow = new QFrame(MajorContainer); - MajorLayout->addWidget(AttitudeDialRow, 0, 0); + MajorLayout->addWidget(AttitudeDialRow, 0, 1); - AttitudeDialOrganizer = new QHBoxLayout(AttitudeDialRow); + AttitudeDialOrganizer = new QVBoxLayout(AttitudeDialRow); AttitudeDialOrganizer->setContentsMargins(20, 20, 20, 20); AttitudeDialRow->setLayout(AttitudeDialOrganizer); @@ -138,58 +138,63 @@ void Widgets::SetupAttitudeDials() { void Widgets::SetGridColumnsMinimums() { if (!MajorLayout) { return; }; const QRect& dims = centralWidget()->geometry(); - MajorLayout->setColumnMinimumWidth(0, 2 * dims.width() / 3); - MajorLayout->setColumnMinimumWidth(1, dims.width() / 3); + 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, dims.height() / 3); - MajorLayout->setRowMinimumHeight(1, 2 * dims.height() / 3); + MajorLayout->setRowMinimumHeight(0, 4 * dims.height() / 5); + MajorLayout->setRowMinimumHeight(1, 1 * dims.height() / 5); } // void Widgets::SetGridRowsMinimums() // Buttons {{{ void Widgets::SetupButtons() { - LoadTestRoutineButton = new QPushButton(this); - LoadTestRoutineButton->setText(tr("Load Test Routine")); + StandbyIndicator = new QPushButton(this); + StandbyIndicator->setText(tr("Standby")); + setButtonStatus(StandbyIndicator, Status::Standby); - ArmedButton = new QPushButton(this); - ArmedButton->setText(tr("Disarmed")); - ArmedButton->setStyleSheet(" QPushButton { background-color: Yellow; color: Black; } } "); - connect(ArmedButton, &QPushButton::clicked, this, &Widgets::OnArmedButtonPressed); + ArmedIndicator = new QPushButton(this); + ArmedIndicator->setText(tr("Disarmed")); + setButtonStatus(ArmedIndicator, Status::Disarmed); + // connect(ArmedIndicator, &QPushButton::clicked, this, &Widgets::OnArmedButtonPressed); - QuantityCalculatorButton = new QPushButton(this); - QuantityCalculatorButton->setText(tr("Calculate Quantity")); + InitiateButton = new QPushButton(this); + InitiateButton->setText(tr("Initiate")); - LogOpenButton = new QPushButton(this); - LogOpenButton->setText(tr("Open Log")); + // LogOpenButton = new QPushButton(this); + // LogOpenButton->setText(tr("Open Log")); AbortButton = new QPushButton(this); AbortButton->setText(tr("Abort")); - AbortButton->setStyleSheet(" QPushButton { background-color: red } "); + AbortButton->setStyleSheet(" QPushButton { background-color: red ; color: white} "); } // void Widgets::SetupButtons() void Widgets::SetupStatusColumn() { StatusColumn = new QGroupBox(tr("Operate"), this); - MajorLayout->addWidget(StatusColumn, 1, 1); + 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 QVBoxLayout(StatusColumn); - LoadTestRoutineButton->setSizePolicy(vhexpanding); - StatusColumnOrganizer->addWidget(LoadTestRoutineButton); + StatusColumnOrganizer = new QHBoxLayout(StatusColumn); + StandbyIndicator->setSizePolicy(vhexpanding); + StatusColumnOrganizer->addWidget(StandbyIndicator); - ArmedButton->setSizePolicy(vhexpanding); - StatusColumnOrganizer->addWidget(ArmedButton); + ArmedIndicator->setSizePolicy(vhexpanding); + StatusColumnOrganizer->addWidget(ArmedIndicator); - QuantityCalculatorButton->setSizePolicy(vhexpanding); - StatusColumnOrganizer->addWidget(QuantityCalculatorButton); + InitiateButton->setSizePolicy(vhexpanding); + StatusColumnOrganizer->addWidget(InitiateButton); - LogOpenButton->setSizePolicy(vhexpanding); - StatusColumnOrganizer->addWidget(LogOpenButton); + // LogOpenButton->setSizePolicy(vhexpanding); + // StatusColumnOrganizer->addWidget(LogOpenButton); AbortButton->setSizePolicy(vhexpanding); StatusColumnOrganizer->addWidget(AbortButton); @@ -199,10 +204,10 @@ void Widgets::SetupStatusColumn() { void Widgets::SetAllButtonTextSize() { ButtonFont.setPixelSize(ButtonFontAdjustment.AdjustPxSize(window())); - LoadTestRoutineButton->setFont(ButtonFont); - ArmedButton->setFont(ButtonFont); - QuantityCalculatorButton->setFont(ButtonFont); - LogOpenButton->setFont(ButtonFont); + StandbyIndicator->setFont(ButtonFont); + ArmedIndicator->setFont(ButtonFont); + InitiateButton->setFont(ButtonFont); + // LogOpenButton->setFont(ButtonFont); AbortButton->setFont(ButtonFont); StatusColumn->setFont(ButtonFont); } // void Widgets::SetAllButtonTextSize() @@ -210,7 +215,7 @@ void Widgets::SetAllButtonTextSize() { void Widgets::SetupMultiPlot() { Plots = new MultiPlotContainer(this, 3); - MajorLayout->addWidget(Plots, 1, 0); + MajorLayout->addWidget(Plots, 0, 0); QList allPlots = Plots->GetPlots(); Plot::AxisInfo axInfo; @@ -274,7 +279,7 @@ void Widgets::SetupTimeHistoryPlotQChart() { void Widgets::SetupAttQtysRatesDisplay() { AttQtysRates = new QtyRateDisplay(tr(""), this); - MajorLayout->addWidget(AttQtysRates, 0, 1); + MajorLayout->addWidget(AttQtysRates, 1, 0); RollQtyRate = new QtyRateRow(tr("Roll"), AttQtysRates); RollQtyRate->SetQuantityUnits("°"); @@ -322,13 +327,15 @@ void Widgets::OnArmedButtonPressed() { bArmedButtonActive = !bArmedButtonActive; if (bArmedButtonActive) { - // Active state - green color - ArmedButton->setText(tr("Armed")); - ArmedButton->setStyleSheet(" QPushButton { background-color: red; color: white; } } "); + // Armed state - Red + ArmedIndicator->setText(tr("Armed")); + setButtonStatus(ArmedIndicator, Status::Armed); + setGroupBoxStatus(StatusColumn, Status::Armed); } else { - // Inactive state - default color - ArmedButton->setText(tr("Disarmed")); - ArmedButton->setStyleSheet(" QPushButton { background-color: Yellow; color: Black; } } "); + // Disarmed state - Yellow + ArmedIndicator->setText(tr("Disarmed")); + setButtonStatus(ArmedIndicator, Status::Disarmed); + setGroupBoxStatus(StatusColumn, Status::Disarmed); } } // void Widgets::OnArmedButtonPressed() // }}} diff --git a/src/Windowing/WidgetsRecreation.hpp b/src/Windowing/WidgetsRecreation.hpp index 3da5513..cd6a148 100644 --- a/src/Windowing/WidgetsRecreation.hpp +++ b/src/Windowing/WidgetsRecreation.hpp @@ -34,7 +34,7 @@ class Widgets : public QMainWindow { void SetGridRowsMinimums(); QFrame* AttitudeDialRow; - QHBoxLayout* AttitudeDialOrganizer; + QVBoxLayout* AttitudeDialOrganizer; CompositeDial* RollDial; CompositeDial* PitchDial; @@ -56,10 +56,10 @@ class Widgets : public QMainWindow { // im not entirely sure of this part QGroupBox* StatusColumn; - QVBoxLayout* StatusColumnOrganizer; - QPushButton* LoadTestRoutineButton; - QPushButton* ArmedButton; - QPushButton* QuantityCalculatorButton; + QHBoxLayout* StatusColumnOrganizer; + QPushButton* StandbyIndicator; + QPushButton* ArmedIndicator; + QPushButton* InitiateButton; QPushButton* LogOpenButton; QPushButton* AbortButton; bool bArmedButtonActive = false; // Track armed button state