diff --git a/app/main.cpp b/app/main.cpp index 943c2a9b7..045b6e88a 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -49,20 +49,20 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo qApp->setStyle(QStyleFactory::create("fusion")); QPalette palette; - palette.setColor(QPalette::Window, QColor(53,53,53)); + palette.setColor(QPalette::Window, QColor(64,64,64)); palette.setColor(QPalette::WindowText, Qt::white); palette.setColor(QPalette::Base, QColor(25,25,25)); palette.setColor(QPalette::AlternateBase, QColor(53,53,53)); palette.setColor(QPalette::ToolTipBase, Qt::white); palette.setColor(QPalette::ToolTipText, Qt::black); palette.setColor(QPalette::Text, Qt::white); - palette.setColor(QPalette::Button, QColor(0x40, 0x40, 0x40)); + palette.setColor(QPalette::Button, QColor(64,64,64)); palette.setColor(QPalette::ButtonText, Qt::white); palette.setColor(QPalette::BrightText, Qt::red); - palette.setColor(QPalette::Light, QColor(53,53,53).lighter(125).lighter()); - palette.setColor(QPalette::Mid, QColor(53,53,53).lighter(125)); - palette.setColor(QPalette::Dark, QColor(53,53,53).lighter(125).darker()); + palette.setColor(QPalette::Light, QColor(64,64,64).lighter(125).lighter()); + palette.setColor(QPalette::Mid, QColor(64,64,64).lighter(125)); + palette.setColor(QPalette::Dark, QColor(64,64,64).lighter(125).darker()); palette.setColor(QPalette::Link, QColor(0,0xa0,0xa0)); palette.setColor(QPalette::LinkVisited, QColor(0,0xa0,0xa0).lighter()); diff --git a/doc/img/corner.xcf b/doc/img/corner.xcf new file mode 100644 index 000000000..1fb705730 Binary files /dev/null and b/doc/img/corner.xcf differ diff --git a/doc/img/cross.xcf b/doc/img/cross.xcf new file mode 100644 index 000000000..7c64325c5 Binary files /dev/null and b/doc/img/cross.xcf differ diff --git a/doc/img/dock.xcf b/doc/img/dock.xcf new file mode 100644 index 000000000..b7bd5f1d1 Binary files /dev/null and b/doc/img/dock.xcf differ diff --git a/doc/img/exit.xcf b/doc/img/exit.xcf new file mode 100644 index 000000000..711f58188 Binary files /dev/null and b/doc/img/exit.xcf differ diff --git a/doc/img/gear.xcf b/doc/img/gear.xcf new file mode 100644 index 000000000..f0b589179 Binary files /dev/null and b/doc/img/gear.xcf differ diff --git a/doc/img/help.xcf b/doc/img/help.xcf new file mode 100644 index 000000000..ddb3d0411 Binary files /dev/null and b/doc/img/help.xcf differ diff --git a/doc/img/mimo.xcf b/doc/img/mimo.xcf new file mode 100644 index 000000000..d3c4e98c9 Binary files /dev/null and b/doc/img/mimo.xcf differ diff --git a/doc/img/rxtx.xcf b/doc/img/rxtx.xcf new file mode 100644 index 000000000..d1cb79a4d Binary files /dev/null and b/doc/img/rxtx.xcf differ diff --git a/doc/img/shrink.xcf b/doc/img/shrink.xcf new file mode 100644 index 000000000..c77dfa390 Binary files /dev/null and b/doc/img/shrink.xcf differ diff --git a/doc/img/tiles.xcf b/doc/img/tiles.xcf new file mode 100644 index 000000000..7bc7066a3 Binary files /dev/null and b/doc/img/tiles.xcf differ diff --git a/doc/img/tool.xcf b/doc/img/tool.xcf new file mode 100644 index 000000000..94adf6f71 Binary files /dev/null and b/doc/img/tool.xcf differ diff --git a/plugins/feature/afc/afcgui.cpp b/plugins/feature/afc/afcgui.cpp index cb2acc19f..d83f986fe 100644 --- a/plugins/feature/afc/afcgui.cpp +++ b/plugins/feature/afc/afcgui.cpp @@ -118,7 +118,7 @@ void AFCGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -130,7 +130,8 @@ AFCGUI::AFCGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur m_doApplySettings(true), m_lastFeatureState(0) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/afc/readme.md"; setAttribute(Qt::WA_DeleteOnClose, true); @@ -140,8 +141,7 @@ AFCGUI::AFCGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur ui->toleranceFrequency->setColorMapper(ColorMapper(ColorMapper::GrayYellow)); ui->toleranceFrequency->setValueRange(5, 0, 99999L); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_afc = reinterpret_cast(feature); m_afc->setMessageQueueToGUI(&m_inputMessageQueue); @@ -162,6 +162,7 @@ AFCGUI::AFCGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur requestDeviceSetLists(); displaySettings(); applySettings(true); + makeUIConnections(); } AFCGUI::~AFCGUI() @@ -178,6 +179,7 @@ void AFCGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); ui->hasTargetFrequency->setChecked(m_settings.m_hasTargetFrequency); ui->transverterTarget->setChecked(m_settings.m_transverterTarget); @@ -185,7 +187,7 @@ void AFCGUI::displaySettings() ui->toleranceFrequency->setValue(m_settings.m_freqTolerance); ui->targetPeriod->setValue(m_settings.m_trackerAdjustPeriod); ui->targetPeriodText->setText(tr("%1").arg(m_settings.m_trackerAdjustPeriod)); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); blockApplySettings(false); } @@ -269,7 +271,6 @@ void AFCGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -279,7 +280,6 @@ void AFCGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); @@ -414,3 +414,18 @@ void AFCGUI::applySettings(bool force) m_afc->getInputMessageQueue()->push(message); } } + +void AFCGUI::makeUIConnections() +{ + QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &AFCGUI::on_startStop_toggled); + QObject::connect(ui->hasTargetFrequency, &ButtonSwitch::toggled, this, &AFCGUI::on_hasTargetFrequency_toggled); + QObject::connect(ui->targetFrequency, &ValueDial::changed, this, &AFCGUI::on_targetFrequency_changed); + QObject::connect(ui->transverterTarget, &ButtonSwitch::toggled, this, &AFCGUI::on_transverterTarget_toggled); + QObject::connect(ui->toleranceFrequency, &ValueDial::changed, this, &AFCGUI::on_toleranceFrequency_changed); + QObject::connect(ui->deviceTrack, &QPushButton::clicked, this, &AFCGUI::on_deviceTrack_clicked); + QObject::connect(ui->devicesRefresh, &QPushButton::clicked, this, &AFCGUI::on_devicesRefresh_clicked); + QObject::connect(ui->trackerDevice, QOverload::of(&QComboBox::currentIndexChanged), this, &AFCGUI::on_trackerDevice_currentIndexChanged); + QObject::connect(ui->trackedDevice, QOverload::of(&QComboBox::currentIndexChanged), this, &AFCGUI::on_trackedDevice_currentIndexChanged); + QObject::connect(ui->devicesApply, &QPushButton::clicked, this, &AFCGUI::on_devicesApply_clicked); + QObject::connect(ui->targetPeriod, &QDial::valueChanged, this, &AFCGUI::on_targetPeriod_valueChanged); +} diff --git a/plugins/feature/afc/afcgui.h b/plugins/feature/afc/afcgui.h index 9f76e4333..1b376f9a0 100644 --- a/plugins/feature/afc/afcgui.h +++ b/plugins/feature/afc/afcgui.h @@ -67,6 +67,7 @@ private: void requestDeviceSetLists(); void updateDeviceSetLists(const AFC::MsgDeviceSetListsReport& report); bool handleMessage(const Message& message); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/afc/afcgui.ui b/plugins/feature/afc/afcgui.ui index bb6c85553..373da46f5 100644 --- a/plugins/feature/afc/afcgui.ui +++ b/plugins/feature/afc/afcgui.ui @@ -1,7 +1,7 @@ AFCGUI - + 0 @@ -406,12 +406,6 @@ - - RollupWidget - QWidget -
gui/rollupwidget.h
- 1 -
ButtonSwitch QToolButton @@ -423,6 +417,12 @@
gui/valuedial.h
1
+ + RollupContents + QWidget +
gui/rollupcontents.h
+ 1 +
diff --git a/plugins/feature/ais/aisgui.cpp b/plugins/feature/ais/aisgui.cpp index 9b284bbdd..e480f9223 100644 --- a/plugins/feature/ais/aisgui.cpp +++ b/plugins/feature/ais/aisgui.cpp @@ -166,7 +166,8 @@ void AISGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + shrinkWindow(); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -178,11 +179,11 @@ AISGUI::AISGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur m_doApplySettings(true), m_lastFeatureState(0) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/ais/readme.md"; setAttribute(Qt::WA_DeleteOnClose, true); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_ais = reinterpret_cast(feature); m_ais->setMessageQueueToGUI(&m_inputMessageQueue); @@ -238,6 +239,7 @@ void AISGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); // Order and size columns @@ -253,9 +255,9 @@ void AISGUI::displaySettings() header->moveSection(header->visualIndex(i), m_settings.m_vesselColumnIndexes[i]); } - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); blockApplySettings(false); - arrangeRollups(); + getRollupContents()->arrangeRollups(); } void AISGUI::leaveEvent(QEvent*) @@ -272,7 +274,6 @@ void AISGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -282,7 +283,6 @@ void AISGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); diff --git a/plugins/feature/ais/aisgui.ui b/plugins/feature/ais/aisgui.ui index 5c3b9fb9f..bfeaf9342 100644 --- a/plugins/feature/ais/aisgui.ui +++ b/plugins/feature/ais/aisgui.ui @@ -1,7 +1,7 @@ AISGUI - + 0 @@ -206,9 +206,9 @@ - RollupWidget + RollupContents QWidget -
gui/rollupwidget.h
+
gui/rollupcontents.h
1
diff --git a/plugins/feature/antennatools/antennatoolsgui.cpp b/plugins/feature/antennatools/antennatoolsgui.cpp index f37f7fef8..07dc57f00 100644 --- a/plugins/feature/antennatools/antennatoolsgui.cpp +++ b/plugins/feature/antennatools/antennatoolsgui.cpp @@ -102,7 +102,7 @@ void AntennaToolsGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -114,12 +114,12 @@ AntennaToolsGUI::AntennaToolsGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe m_doApplySettings(true), m_deviceSets(0) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/antennatools/readme.md"; setAttribute(Qt::WA_DeleteOnClose, true); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_antennatools = reinterpret_cast(feature); m_antennatools->setMessageQueueToGUI(&m_inputMessageQueue); @@ -136,6 +136,7 @@ AntennaToolsGUI::AntennaToolsGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe displaySettings(); applySettings(true); + makeUIConnections(); } AntennaToolsGUI::~AntennaToolsGUI() @@ -152,6 +153,7 @@ void AntennaToolsGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); ui->dipoleFrequency->setValue(m_settings.m_dipoleFrequencyMHz); ui->dipoleFrequencySelect->setCurrentIndex(m_settings.m_dipoleFrequencySelect); @@ -170,7 +172,24 @@ void AntennaToolsGUI::displaySettings() calcDishBeamwidth(); calcDishGain(); calcDishEffectiveArea(); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); +} + +void AntennaToolsGUI::makeUIConnections() +{ + QObject::connect(ui->dipoleFrequency, qOverload(&QDoubleSpinBox::valueChanged), this, &AntennaToolsGUI::on_dipoleFrequency_valueChanged); + QObject::connect(ui->dipoleFrequencySelect, qOverload(&QComboBox::currentIndexChanged), this, &AntennaToolsGUI::on_dipoleFrequencySelect_currentIndexChanged); + QObject::connect(ui->dipoleEndEffectFactor, qOverload(&QDoubleSpinBox::valueChanged), this, &AntennaToolsGUI::on_dipoleEndEffectFactor_valueChanged); + QObject::connect(ui->dipoleLengthUnits, qOverload(&QComboBox::currentIndexChanged), this, &AntennaToolsGUI::on_dipoleLengthUnits_currentIndexChanged); + QObject::connect(ui->dipoleLength, qOverload(&QDoubleSpinBox::valueChanged), this, &AntennaToolsGUI::on_dipoleLength_valueChanged); + QObject::connect(ui->dipoleElementLength, qOverload(&QDoubleSpinBox::valueChanged), this, &AntennaToolsGUI::on_dipoleElementLength_valueChanged); + QObject::connect(ui->dishFrequency, qOverload(&QDoubleSpinBox::valueChanged), this, &AntennaToolsGUI::on_dishFrequency_valueChanged); + QObject::connect(ui->dishFrequencySelect, qOverload(&QComboBox::currentIndexChanged), this, &AntennaToolsGUI::on_dishFrequencySelect_currentIndexChanged); + QObject::connect(ui->dishDiameter, qOverload(&QDoubleSpinBox::valueChanged), this, &AntennaToolsGUI::on_dishDiameter_valueChanged); + QObject::connect(ui->dishLengthUnits, qOverload(&QComboBox::currentIndexChanged), this, &AntennaToolsGUI::on_dishLengthUnits_currentIndexChanged); + QObject::connect(ui->dishDepth, qOverload(&QDoubleSpinBox::valueChanged), this, &AntennaToolsGUI::on_dishDepth_valueChanged); + QObject::connect(ui->dishEfficiency, qOverload(&QSpinBox::valueChanged), this, &AntennaToolsGUI::on_dishEfficiency_valueChanged); + QObject::connect(ui->dishSurfaceError, qOverload(&QDoubleSpinBox::valueChanged), this, &AntennaToolsGUI::on_dishSurfaceError_valueChanged); } void AntennaToolsGUI::leaveEvent(QEvent*) @@ -187,7 +206,6 @@ void AntennaToolsGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -197,7 +215,6 @@ void AntennaToolsGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); diff --git a/plugins/feature/antennatools/antennatoolsgui.h b/plugins/feature/antennatools/antennatoolsgui.h index 5d4213ab4..c21c8654b 100644 --- a/plugins/feature/antennatools/antennatoolsgui.h +++ b/plugins/feature/antennatools/antennatoolsgui.h @@ -67,6 +67,7 @@ private: void applySettings(bool force = false); void displaySettings(); bool handleMessage(const Message& message); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/antennatools/antennatoolsgui.ui b/plugins/feature/antennatools/antennatoolsgui.ui index 7cdbb6a19..73cff9790 100644 --- a/plugins/feature/antennatools/antennatoolsgui.ui +++ b/plugins/feature/antennatools/antennatoolsgui.ui @@ -1,7 +1,7 @@ AntennaToolsGUI - + 0 @@ -503,9 +503,9 @@ - RollupWidget + RollupContents QWidget -
gui/rollupwidget.h
+
gui/rollupcontents.h
1
diff --git a/plugins/feature/aprs/aprsgui.cpp b/plugins/feature/aprs/aprsgui.cpp index 1023bb53b..bc4949c8c 100644 --- a/plugins/feature/aprs/aprsgui.cpp +++ b/plugins/feature/aprs/aprsgui.cpp @@ -418,7 +418,7 @@ void APRSGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -430,12 +430,12 @@ APRSGUI::APRSGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feat m_doApplySettings(true), m_lastFeatureState(0) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/aprs/readme.md"; setAttribute(Qt::WA_DeleteOnClose, true); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_aprs = reinterpret_cast(feature); m_aprs->setMessageQueueToGUI(&m_inputMessageQueue); @@ -564,6 +564,7 @@ APRSGUI::APRSGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feat displaySettings(); applySettings(true); + makeUIConnections(); } APRSGUI::~APRSGUI() @@ -629,6 +630,7 @@ void APRSGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); ui->igate->setChecked(m_settings.m_igateEnabled); ui->stationFilter->setCurrentIndex((int)m_settings.m_stationFilter); @@ -643,7 +645,7 @@ void APRSGUI::displaySettings() displayTableSettings(ui->telemetryTable, telemetryTableMenu, m_settings.m_telemetryTableColumnSizes, m_settings.m_telemetryTableColumnIndexes, APRS_TELEMETRY_TABLE_COLUMNS); displayTableSettings(ui->motionTable, motionTableMenu, m_settings.m_motionTableColumnSizes, m_settings.m_motionTableColumnIndexes, APRS_MOTION_TABLE_COLUMNS); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); blockApplySettings(false); } @@ -683,7 +685,6 @@ void APRSGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -693,7 +694,6 @@ void APRSGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); @@ -2026,3 +2026,20 @@ void APRSGUI::on_viewOnMap_clicked() } } } + +void APRSGUI::makeUIConnections() +{ + QObject::connect(ui->stationFilter, qOverload(&QComboBox::currentIndexChanged), this, &APRSGUI::on_stationFilter_currentIndexChanged); + QObject::connect(ui->stationSelect, qOverload(&QComboBox::currentIndexChanged), this, &APRSGUI::on_stationSelect_currentIndexChanged); + QObject::connect(ui->filterAddressee, &QLineEdit::editingFinished, this, &APRSGUI::on_filterAddressee_editingFinished); + QObject::connect(ui->deleteMessages, &QPushButton::clicked, this, &APRSGUI::on_deleteMessages_clicked); + QObject::connect(ui->weatherTimeSelect, qOverload(&QComboBox::currentIndexChanged), this, &APRSGUI::on_weatherTimeSelect_currentIndexChanged); + QObject::connect(ui->weatherPlotSelect, qOverload(&QComboBox::currentIndexChanged), this, &APRSGUI::on_weatherPlotSelect_currentIndexChanged); + QObject::connect(ui->telemetryTimeSelect, qOverload(&QComboBox::currentIndexChanged), this, &APRSGUI::on_telemetryTimeSelect_currentIndexChanged); + QObject::connect(ui->telemetryPlotSelect, qOverload(&QComboBox::currentIndexChanged), this, &APRSGUI::on_telemetryPlotSelect_currentIndexChanged); + QObject::connect(ui->motionTimeSelect, qOverload(&QComboBox::currentIndexChanged), this, &APRSGUI::on_motionTimeSelect_currentIndexChanged); + QObject::connect(ui->motionPlotSelect, qOverload(&QComboBox::currentIndexChanged), this, &APRSGUI::on_motionPlotSelect_currentIndexChanged); + QObject::connect(ui->displaySettings, &QPushButton::clicked, this, &APRSGUI::on_displaySettings_clicked); + QObject::connect(ui->igate, &ButtonSwitch::toggled, this, &APRSGUI::on_igate_toggled); + QObject::connect(ui->viewOnMap, &QPushButton::clicked, this, &APRSGUI::on_viewOnMap_clicked); +} diff --git a/plugins/feature/aprs/aprsgui.h b/plugins/feature/aprs/aprsgui.h index 170c2282f..412387164 100644 --- a/plugins/feature/aprs/aprsgui.h +++ b/plugins/feature/aprs/aprsgui.h @@ -155,6 +155,7 @@ private: void displaySettings(); void updateChannelList(); bool handleMessage(const Message& message); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/aprs/aprsgui.ui b/plugins/feature/aprs/aprsgui.ui index 68a8c1acf..8194bb504 100644 --- a/plugins/feature/aprs/aprsgui.ui +++ b/plugins/feature/aprs/aprsgui.ui @@ -1,7 +1,7 @@ APRSGUI - + 0 @@ -1447,17 +1447,17 @@ - - RollupWidget - QWidget -
gui/rollupwidget.h
- 1 -
ButtonSwitch QToolButton
gui/buttonswitch.h
+ + RollupContents + QWidget +
gui/rollupcontents.h
+ 1 +
QChartView QGraphicsView diff --git a/plugins/feature/demodanalyzer/demodanalyzergui.cpp b/plugins/feature/demodanalyzer/demodanalyzergui.cpp index 7b064fc4a..4d42071bb 100644 --- a/plugins/feature/demodanalyzer/demodanalyzergui.cpp +++ b/plugins/feature/demodanalyzer/demodanalyzergui.cpp @@ -125,7 +125,7 @@ void DemodAnalyzerGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -139,11 +139,11 @@ DemodAnalyzerGUI::DemodAnalyzerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUI m_lastFeatureState(0), m_selectedChannel(nullptr) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/demodanalyzer/readme.md"; setAttribute(Qt::WA_DeleteOnClose, true); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_demodAnalyzer = reinterpret_cast(feature); m_demodAnalyzer->setMessageQueueToGUI(&m_inputMessageQueue); @@ -177,6 +177,7 @@ DemodAnalyzerGUI::DemodAnalyzerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUI displaySettings(); applySettings(true); + makeUIConnections(); } DemodAnalyzerGUI::~DemodAnalyzerGUI() @@ -193,9 +194,10 @@ void DemodAnalyzerGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); ui->log2Decim->setCurrentIndex(m_settings.m_log2Decim); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); blockApplySettings(false); } @@ -253,7 +255,6 @@ void DemodAnalyzerGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -263,7 +264,6 @@ void DemodAnalyzerGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); @@ -369,3 +369,12 @@ void DemodAnalyzerGUI::applySettings(bool force) m_demodAnalyzer->getInputMessageQueue()->push(message); } } + +void DemodAnalyzerGUI::makeUIConnections() +{ + QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &DemodAnalyzerGUI::on_startStop_toggled); + QObject::connect(ui->devicesRefresh, &QPushButton::clicked, this, &DemodAnalyzerGUI::on_devicesRefresh_clicked); + QObject::connect(ui->channels, qOverload(&QComboBox::currentIndexChanged), this, &DemodAnalyzerGUI::on_channels_currentIndexChanged); + QObject::connect(ui->channelApply, &QPushButton::clicked, this, &DemodAnalyzerGUI::on_channelApply_clicked); + QObject::connect(ui->log2Decim, qOverload(&QComboBox::currentIndexChanged), this, &DemodAnalyzerGUI::on_log2Decim_currentIndexChanged); +} diff --git a/plugins/feature/demodanalyzer/demodanalyzergui.h b/plugins/feature/demodanalyzer/demodanalyzergui.h index 69f0fab22..b11100ecf 100644 --- a/plugins/feature/demodanalyzer/demodanalyzergui.h +++ b/plugins/feature/demodanalyzer/demodanalyzergui.h @@ -78,6 +78,7 @@ private: void displaySampleRate(int sampleRate); void updateChannelList(); bool handleMessage(const Message& message); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/demodanalyzer/demodanalyzergui.ui b/plugins/feature/demodanalyzer/demodanalyzergui.ui index 49a3fdcd0..6b4316257 100644 --- a/plugins/feature/demodanalyzer/demodanalyzergui.ui +++ b/plugins/feature/demodanalyzer/demodanalyzergui.ui @@ -1,7 +1,7 @@ DemodAnalyzerGUI - + 0 @@ -370,9 +370,14 @@ - RollupWidget + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+ + RollupContents QWidget -
gui/rollupwidget.h
+
gui/rollupcontents.h
1
@@ -387,11 +392,6 @@
gui/glspectrumgui.h
1
- - ButtonSwitch - QToolButton -
gui/buttonswitch.h
-
GLScope QWidget diff --git a/plugins/feature/gs232controller/gs232controllergui.cpp b/plugins/feature/gs232controller/gs232controllergui.cpp index 6d8110bc7..ffba05030 100644 --- a/plugins/feature/gs232controller/gs232controllergui.cpp +++ b/plugins/feature/gs232controller/gs232controllergui.cpp @@ -127,7 +127,7 @@ void GS232ControllerGUI::onWidgetRolled(QWidget* widget, bool rollDown) { (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -140,11 +140,11 @@ GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featu m_lastFeatureState(0), m_lastOnTarget(false) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/gs232controller/readme.md"; setAttribute(Qt::WA_DeleteOnClose, true); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_gs232Controller = reinterpret_cast(feature); m_gs232Controller->setMessageQueueToGUI(&m_inputMessageQueue); @@ -165,6 +165,7 @@ GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featu displaySettings(); applySettings(true); + makeUIConnections(); } GS232ControllerGUI::~GS232ControllerGUI() @@ -181,6 +182,7 @@ void GS232ControllerGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); ui->azimuth->setValue(m_settings.m_azimuth); ui->elevation->setValue(m_settings.m_elevation); @@ -202,7 +204,7 @@ void GS232ControllerGUI::displaySettings() ui->elevationMin->setValue(m_settings.m_elevationMin); ui->elevationMax->setValue(m_settings.m_elevationMax); ui->tolerance->setValue(m_settings.m_tolerance); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); updateConnectionWidgets(); blockApplySettings(false); } @@ -298,7 +300,6 @@ void GS232ControllerGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -308,7 +309,6 @@ void GS232ControllerGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); @@ -528,3 +528,25 @@ void GS232ControllerGUI::applySettings(bool force) m_gs232Controller->getInputMessageQueue()->push(message); } } + +void GS232ControllerGUI::makeUIConnections() +{ + QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &GS232ControllerGUI::on_startStop_toggled); + QObject::connect(ui->protocol, qOverload(&QComboBox::currentIndexChanged), this, &GS232ControllerGUI::on_protocol_currentIndexChanged); + QObject::connect(ui->connection, qOverload(&QComboBox::currentIndexChanged), this, &GS232ControllerGUI::on_connection_currentIndexChanged); + QObject::connect(ui->serialPort, qOverload(&QComboBox::currentIndexChanged), this, &GS232ControllerGUI::on_serialPort_currentIndexChanged); + QObject::connect(ui->host, &QLineEdit::editingFinished, this, &GS232ControllerGUI::on_host_editingFinished); + QObject::connect(ui->port, qOverload(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_port_valueChanged); + QObject::connect(ui->baudRate, qOverload(&QComboBox::currentIndexChanged), this, &GS232ControllerGUI::on_baudRate_currentIndexChanged); + QObject::connect(ui->track, &QCheckBox::stateChanged, this, &GS232ControllerGUI::on_track_stateChanged); + QObject::connect(ui->azimuth, qOverload(&QDoubleSpinBox::valueChanged), this, &GS232ControllerGUI::on_azimuth_valueChanged); + QObject::connect(ui->elevation, qOverload(&QDoubleSpinBox::valueChanged), this, &GS232ControllerGUI::on_elevation_valueChanged); + QObject::connect(ui->sources, &QComboBox::currentTextChanged, this, &GS232ControllerGUI::on_sources_currentTextChanged); + QObject::connect(ui->azimuthOffset, qOverload(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_azimuthOffset_valueChanged); + QObject::connect(ui->elevationOffset, qOverload(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_elevationOffset_valueChanged); + QObject::connect(ui->azimuthMin, qOverload(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_azimuthMin_valueChanged); + QObject::connect(ui->azimuthMax, qOverload(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_azimuthMax_valueChanged); + QObject::connect(ui->elevationMin, qOverload(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_elevationMin_valueChanged); + QObject::connect(ui->elevationMax, qOverload(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_elevationMax_valueChanged); + QObject::connect(ui->tolerance, qOverload(&QDoubleSpinBox::valueChanged), this, &GS232ControllerGUI::on_tolerance_valueChanged); +} diff --git a/plugins/feature/gs232controller/gs232controllergui.h b/plugins/feature/gs232controller/gs232controllergui.h index 5ecdd8932..1fbd42d03 100644 --- a/plugins/feature/gs232controller/gs232controllergui.h +++ b/plugins/feature/gs232controller/gs232controllergui.h @@ -71,6 +71,7 @@ private: void updatePipeList(const QList& sources); void updateSerialPortList(); bool handleMessage(const Message& message); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/gs232controller/gs232controllergui.ui b/plugins/feature/gs232controller/gs232controllergui.ui index 656be9249..3b7ff827b 100644 --- a/plugins/feature/gs232controller/gs232controllergui.ui +++ b/plugins/feature/gs232controller/gs232controllergui.ui @@ -1,7 +1,7 @@ GS232ControllerGUI - + 0 @@ -541,17 +541,17 @@ - - RollupWidget - QWidget -
gui/rollupwidget.h
- 1 -
ButtonSwitch QToolButton
gui/buttonswitch.h
+ + RollupContents + QWidget +
gui/rollupcontents.h
+ 1 +
startStop diff --git a/plugins/feature/jogdialcontroller/jogdialcontrollergui.cpp b/plugins/feature/jogdialcontroller/jogdialcontrollergui.cpp index 12afa2009..56a038a48 100644 --- a/plugins/feature/jogdialcontroller/jogdialcontrollergui.cpp +++ b/plugins/feature/jogdialcontroller/jogdialcontrollergui.cpp @@ -132,7 +132,7 @@ void JogdialControllerGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -145,11 +145,11 @@ JogdialControllerGUI::JogdialControllerGUI(PluginAPI* pluginAPI, FeatureUISet *f m_lastFeatureState(0), m_selectedChannel(nullptr) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/jogdialcontroller/readme.md"; setAttribute(Qt::WA_DeleteOnClose, true); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_jogdialController = reinterpret_cast(feature); m_jogdialController->setMessageQueueToGUI(&m_inputMessageQueue); @@ -169,6 +169,7 @@ JogdialControllerGUI::JogdialControllerGUI(PluginAPI* pluginAPI, FeatureUISet *f displaySettings(); applySettings(true); + makeUIConnections(); } JogdialControllerGUI::~JogdialControllerGUI() @@ -185,8 +186,9 @@ void JogdialControllerGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); blockApplySettings(false); } @@ -243,7 +245,6 @@ void JogdialControllerGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -253,7 +254,6 @@ void JogdialControllerGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); @@ -362,3 +362,10 @@ void JogdialControllerGUI::focusOutEvent(QFocusEvent*) ui->focusIndicator->setStyleSheet("QLabel { background-color: gray; border-radius: 8px; }"); // gray ui->focusIndicator->setToolTip("Idle"); } + +void JogdialControllerGUI::makeUIConnections() +{ + QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &JogdialControllerGUI::on_startStop_toggled); + QObject::connect(ui->devicesRefresh, &QPushButton::clicked, this, &JogdialControllerGUI::on_devicesRefresh_clicked); + QObject::connect(ui->channels, qOverload(&QComboBox::currentIndexChanged), this, &JogdialControllerGUI::on_channels_currentIndexChanged); +} diff --git a/plugins/feature/jogdialcontroller/jogdialcontrollergui.h b/plugins/feature/jogdialcontroller/jogdialcontrollergui.h index a6b680ceb..d7d27633c 100644 --- a/plugins/feature/jogdialcontroller/jogdialcontrollergui.h +++ b/plugins/feature/jogdialcontroller/jogdialcontrollergui.h @@ -76,6 +76,7 @@ private: void displaySettings(); void updateChannelList(); bool handleMessage(const Message& message); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/jogdialcontroller/jogdialcontrollergui.ui b/plugins/feature/jogdialcontroller/jogdialcontrollergui.ui index 5b9a8e687..142ba45fc 100644 --- a/plugins/feature/jogdialcontroller/jogdialcontrollergui.ui +++ b/plugins/feature/jogdialcontroller/jogdialcontrollergui.ui @@ -1,7 +1,7 @@ JogdialControllerGUI - + 0 @@ -193,17 +193,17 @@ - - RollupWidget - QWidget -
gui/rollupwidget.h
- 1 -
ButtonSwitch QToolButton
gui/buttonswitch.h
+ + RollupContents + QWidget +
gui/rollupcontents.h
+ 1 +
diff --git a/plugins/feature/map/mapgui.cpp b/plugins/feature/map/mapgui.cpp index c344eb856..de5401908 100644 --- a/plugins/feature/map/mapgui.cpp +++ b/plugins/feature/map/mapgui.cpp @@ -162,7 +162,7 @@ void MapGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -179,7 +179,8 @@ MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur m_radioTimeDialog(this), m_cesium(nullptr) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/map/readme.md"; m_osmPort = 0; @@ -201,8 +202,7 @@ MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur m_webServer->addPathSubstitution("3d", m_settings.m_modelDir); setAttribute(Qt::WA_DeleteOnClose, true); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_map = reinterpret_cast(feature); m_map->setMessageQueueToGUI(&m_inputMessageQueue); @@ -268,6 +268,8 @@ MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur connect(&m_redrawMapTimer, &QTimer::timeout, this, &MapGUI::redrawMap); m_redrawMapTimer.setSingleShot(true); ui->map->installEventFilter(this); + + makeUIConnections(); } MapGUI::~MapGUI() @@ -847,6 +849,7 @@ void MapGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); ui->displayNames->setChecked(m_settings.m_displayNames); ui->displaySelectedGroundTracks->setChecked(m_settings.m_displaySelectedGroundTracks); @@ -857,7 +860,7 @@ void MapGUI::displaySettings() m_mapModel.updateItemSettings(m_settings.m_itemSettings); applyMap2DSettings(true); applyMap3DSettings(true); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); blockApplySettings(false); } @@ -875,7 +878,6 @@ void MapGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -885,7 +887,6 @@ void MapGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); @@ -1214,3 +1215,18 @@ void MapGUI::preferenceChanged(int elementType) update(m_map, &m_antennaMapItem, "Station"); } } + +void MapGUI::makeUIConnections() +{ + QObject::connect(ui->displayNames, &ButtonSwitch::clicked, this, &MapGUI::on_displayNames_clicked); + QObject::connect(ui->displayAllGroundTracks, &ButtonSwitch::clicked, this, &MapGUI::on_displayAllGroundTracks_clicked); + QObject::connect(ui->displaySelectedGroundTracks, &ButtonSwitch::clicked, this, &MapGUI::on_displaySelectedGroundTracks_clicked); + QObject::connect(ui->find, &QLineEdit::returnPressed, this, &MapGUI::on_find_returnPressed); + QObject::connect(ui->maidenhead, &QToolButton::clicked, this, &MapGUI::on_maidenhead_clicked); + QObject::connect(ui->deleteAll, &QToolButton::clicked, this, &MapGUI::on_deleteAll_clicked); + QObject::connect(ui->displaySettings, &QToolButton::clicked, this, &MapGUI::on_displaySettings_clicked); + QObject::connect(ui->mapTypes, qOverload(&QComboBox::currentIndexChanged), this, &MapGUI::on_mapTypes_currentIndexChanged); + QObject::connect(ui->beacons, &QToolButton::clicked, this, &MapGUI::on_beacons_clicked); + QObject::connect(ui->ibpBeacons, &QToolButton::clicked, this, &MapGUI::on_ibpBeacons_clicked); + QObject::connect(ui->radiotime, &QToolButton::clicked, this, &MapGUI::on_radiotime_clicked); +} diff --git a/plugins/feature/map/mapgui.h b/plugins/feature/map/mapgui.h index 96cbf2c2b..16ad02a19 100644 --- a/plugins/feature/map/mapgui.h +++ b/plugins/feature/map/mapgui.h @@ -132,6 +132,7 @@ private: QString maptilerAPIKey() const; QString cesiumIonAPIKey() const; void redrawMap(); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/map/mapgui.ui b/plugins/feature/map/mapgui.ui index c0596d44a..70834ba70 100644 --- a/plugins/feature/map/mapgui.ui +++ b/plugins/feature/map/mapgui.ui @@ -1,7 +1,7 @@ MapGUI - + 0 @@ -339,7 +339,7 @@ - + 0 @@ -365,9 +365,9 @@
QtQuickWidgets/QQuickWidget
- RollupWidget + QWebEngineView QWidget -
gui/rollupwidget.h
+
QtWebEngineWidgets/QWebEngineView
1
@@ -376,9 +376,9 @@
gui/buttonswitch.h
- QWebEngineView + RollupContents QWidget -
QWebEngineView
+
gui/rollupcontents.h
1
diff --git a/plugins/feature/pertester/pertestergui.cpp b/plugins/feature/pertester/pertestergui.cpp index cc3083931..d53ce34c3 100644 --- a/plugins/feature/pertester/pertestergui.cpp +++ b/plugins/feature/pertester/pertestergui.cpp @@ -114,7 +114,7 @@ void PERTesterGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -126,11 +126,11 @@ PERTesterGUI::PERTesterGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Fea m_doApplySettings(true), m_lastFeatureState(0) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/pertester/readme.md"; setAttribute(Qt::WA_DeleteOnClose, true); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_perTester = reinterpret_cast(feature); m_perTester->setMessageQueueToGUI(&m_inputMessageQueue); @@ -145,6 +145,7 @@ PERTesterGUI::PERTesterGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Fea displaySettings(); applySettings(true); + makeUIConnections(); } PERTesterGUI::~PERTesterGUI() @@ -161,6 +162,7 @@ void PERTesterGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); ui->packetCount->setValue(m_settings.m_packetCount); ui->start->setCurrentIndex((int)m_settings.m_start); @@ -175,9 +177,9 @@ void PERTesterGUI::displaySettings() ui->txUDPPort->setText(QString::number(m_settings.m_txUDPPort)); ui->rxUDPAddress->setText(m_settings.m_rxUDPAddress); ui->rxUDPPort->setText(QString::number(m_settings.m_rxUDPPort)); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); blockApplySettings(false); - arrangeRollups(); + getRollupContents()->arrangeRollups(); } void PERTesterGUI::leaveEvent(QEvent*) @@ -194,7 +196,6 @@ void PERTesterGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -204,7 +205,6 @@ void PERTesterGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); @@ -251,7 +251,7 @@ void PERTesterGUI::on_start_currentIndexChanged(int index) ui->satellites->setVisible(m_settings.m_start != PERTesterSettings::START_IMMEDIATELY); ui->satellitesLabel->setVisible(m_settings.m_start != PERTesterSettings::START_IMMEDIATELY); applySettings(); - arrangeRollups(); + getRollupContents()->arrangeRollups(); } void PERTesterGUI::on_satellites_editingFinished() @@ -353,3 +353,20 @@ void PERTesterGUI::applySettings(bool force) m_perTester->getInputMessageQueue()->push(message); } } + +void PERTesterGUI::makeUIConnections() +{ + QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &PERTesterGUI::on_startStop_toggled); + QObject::connect(ui->resetStats, &QToolButton::clicked, this, &PERTesterGUI::on_resetStats_clicked); + QObject::connect(ui->packetCount, qOverload(&QSpinBox::valueChanged), this, &PERTesterGUI::on_packetCount_valueChanged); + QObject::connect(ui->start, qOverload(&QComboBox::currentIndexChanged), this, &PERTesterGUI::on_start_currentIndexChanged); + QObject::connect(ui->satellites, &QLineEdit::editingFinished, this, &PERTesterGUI::on_satellites_editingFinished); + QObject::connect(ui->interval, qOverload(&QDoubleSpinBox::valueChanged), this, &PERTesterGUI::on_interval_valueChanged); + QObject::connect(ui->packet, &QPlainTextEdit::textChanged, this, &PERTesterGUI::on_packet_textChanged); + QObject::connect(ui->leading, qOverload(&QSpinBox::valueChanged), this, &PERTesterGUI::on_leading_valueChanged); + QObject::connect(ui->trailing, qOverload(&QSpinBox::valueChanged), this, &PERTesterGUI::on_trailing_valueChanged); + QObject::connect(ui->txUDPAddress, &QLineEdit::editingFinished, this, &PERTesterGUI::on_txUDPAddress_editingFinished); + QObject::connect(ui->txUDPPort, &QLineEdit::editingFinished, this, &PERTesterGUI::on_txUDPPort_editingFinished); + QObject::connect(ui->rxUDPAddress, &QLineEdit::editingFinished, this, &PERTesterGUI::on_rxUDPAddress_editingFinished); + QObject::connect(ui->rxUDPPort, &QLineEdit::editingFinished, this, &PERTesterGUI::on_rxUDPPort_editingFinished); +} diff --git a/plugins/feature/pertester/pertestergui.h b/plugins/feature/pertester/pertestergui.h index 26f26e585..b5fe9b0fa 100644 --- a/plugins/feature/pertester/pertestergui.h +++ b/plugins/feature/pertester/pertestergui.h @@ -66,6 +66,7 @@ private: void applySettings(bool force = false); void displaySettings(); bool handleMessage(const Message& message); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/pertester/pertestergui.ui b/plugins/feature/pertester/pertestergui.ui index ff1e2d391..648ee13db 100644 --- a/plugins/feature/pertester/pertestergui.ui +++ b/plugins/feature/pertester/pertestergui.ui @@ -1,7 +1,7 @@ PERTesterGUI - + 0 @@ -554,17 +554,17 @@ Substitutions: - - RollupWidget - QWidget -
gui/rollupwidget.h
- 1 -
ButtonSwitch QToolButton
gui/buttonswitch.h
+ + RollupContents + QWidget +
gui/rollupcontents.h
+ 1 +
startStop diff --git a/plugins/feature/radiosonde/radiosondegui.cpp b/plugins/feature/radiosonde/radiosondegui.cpp index 871d02a27..af4416ecb 100644 --- a/plugins/feature/radiosonde/radiosondegui.cpp +++ b/plugins/feature/radiosonde/radiosondegui.cpp @@ -117,7 +117,7 @@ void RadiosondeGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -129,11 +129,11 @@ RadiosondeGUI::RadiosondeGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, F m_doApplySettings(true), m_lastFeatureState(0) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/radiosonde/readme.md"; setAttribute(Qt::WA_DeleteOnClose, true); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_radiosonde = reinterpret_cast(feature); m_radiosonde->setMessageQueueToGUI(&m_inputMessageQueue); @@ -180,6 +180,7 @@ RadiosondeGUI::RadiosondeGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, F displaySettings(); applySettings(true); + makeUIConnections(); plotChart(); } @@ -199,6 +200,7 @@ void RadiosondeGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); // Order and size columns @@ -217,9 +219,9 @@ void RadiosondeGUI::displaySettings() ui->y1->setCurrentIndex((int)m_settings.m_y1); ui->y2->setCurrentIndex((int)m_settings.m_y2); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); blockApplySettings(false); - arrangeRollups(); + getRollupContents()->arrangeRollups(); } void RadiosondeGUI::leaveEvent(QEvent*) @@ -236,7 +238,6 @@ void RadiosondeGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -246,7 +247,6 @@ void RadiosondeGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); @@ -853,3 +853,12 @@ void RadiosondeGUI::on_deleteAll_clicked() m_radiosondes.remove(serial); } } + +void RadiosondeGUI::makeUIConnections() +{ + QObject::connect(ui->radiosondes, &QTableWidget::itemSelectionChanged, this, &RadiosondeGUI::on_radiosondes_itemSelectionChanged); + QObject::connect(ui->radiosondes, &QTableWidget::cellDoubleClicked, this, &RadiosondeGUI::on_radiosondes_cellDoubleClicked); + QObject::connect(ui->y1, qOverload(&QComboBox::currentIndexChanged), this, &RadiosondeGUI::on_y1_currentIndexChanged); + QObject::connect(ui->y2, qOverload(&QComboBox::currentIndexChanged), this, &RadiosondeGUI::on_y2_currentIndexChanged); + QObject::connect(ui->deleteAll, &QPushButton::clicked, this, &RadiosondeGUI::on_deleteAll_clicked); +} diff --git a/plugins/feature/radiosonde/radiosondegui.h b/plugins/feature/radiosonde/radiosondegui.h index 3a9b2883f..18202ab61 100644 --- a/plugins/feature/radiosonde/radiosondegui.h +++ b/plugins/feature/radiosonde/radiosondegui.h @@ -98,6 +98,7 @@ private: void applySettings(bool force = false); void displaySettings(); bool handleMessage(const Message& message); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/radiosonde/radiosondegui.ui b/plugins/feature/radiosonde/radiosondegui.ui index 14a31362f..810a16bfa 100644 --- a/plugins/feature/radiosonde/radiosondegui.ui +++ b/plugins/feature/radiosonde/radiosondegui.ui @@ -1,7 +1,7 @@ RadiosondeGUI - + 0 @@ -426,9 +426,9 @@ - RollupWidget + RollupContents QWidget -
gui/rollupwidget.h
+
gui/rollupcontents.h
1
diff --git a/plugins/feature/rigctlserver/rigctlservergui.cpp b/plugins/feature/rigctlserver/rigctlservergui.cpp index da18a7698..be2b11a10 100644 --- a/plugins/feature/rigctlserver/rigctlservergui.cpp +++ b/plugins/feature/rigctlserver/rigctlservergui.cpp @@ -114,7 +114,7 @@ void RigCtlServerGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -126,11 +126,11 @@ RigCtlServerGUI::RigCtlServerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe m_doApplySettings(true), m_lastFeatureState(0) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/rigctlserver/readme.md"; setAttribute(Qt::WA_DeleteOnClose, true); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_rigCtlServer = reinterpret_cast(feature); m_rigCtlServer->setMessageQueueToGUI(&m_inputMessageQueue); @@ -146,6 +146,7 @@ RigCtlServerGUI::RigCtlServerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe updateDeviceSetList(); displaySettings(); applySettings(true); + makeUIConnections(); } RigCtlServerGUI::~RigCtlServerGUI() @@ -162,10 +163,11 @@ void RigCtlServerGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); ui->rigCtrlPort->setValue(m_settings.m_rigCtlPort); ui->maxFrequencyOffset->setValue(m_settings.m_maxFrequencyOffset); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); blockApplySettings(false); } @@ -281,7 +283,6 @@ void RigCtlServerGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -291,7 +292,6 @@ void RigCtlServerGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); @@ -398,3 +398,14 @@ void RigCtlServerGUI::applySettings(bool force) m_rigCtlServer->getInputMessageQueue()->push(message); } } + +void RigCtlServerGUI::makeUIConnections() +{ + QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &RigCtlServerGUI::on_startStop_toggled); + QObject::connect(ui->enable, &QCheckBox::toggled, this, &RigCtlServerGUI::on_enable_toggled); + QObject::connect(ui->devicesRefresh, &QPushButton::clicked, this, &RigCtlServerGUI::on_devicesRefresh_clicked); + QObject::connect(ui->device, qOverload(&QComboBox::currentIndexChanged), this, &RigCtlServerGUI::on_device_currentIndexChanged); + QObject::connect(ui->channel, qOverload(&QComboBox::currentIndexChanged), this, &RigCtlServerGUI::on_channel_currentIndexChanged); + QObject::connect(ui->rigCtrlPort, qOverload(&QSpinBox::valueChanged), this, &RigCtlServerGUI::on_rigCtrlPort_valueChanged); + QObject::connect(ui->maxFrequencyOffset, qOverload(&QSpinBox::valueChanged), this, &RigCtlServerGUI::on_maxFrequencyOffset_valueChanged); +} diff --git a/plugins/feature/rigctlserver/rigctlservergui.h b/plugins/feature/rigctlserver/rigctlservergui.h index 1529ae2bf..679b61dd6 100644 --- a/plugins/feature/rigctlserver/rigctlservergui.h +++ b/plugins/feature/rigctlserver/rigctlservergui.h @@ -68,6 +68,7 @@ private: void updateDeviceSetList(); bool updateChannelList(); //!< true if channel index has changed bool handleMessage(const Message& message); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/rigctlserver/rigctlservergui.ui b/plugins/feature/rigctlserver/rigctlservergui.ui index 3e3873dbd..6a5992d14 100644 --- a/plugins/feature/rigctlserver/rigctlservergui.ui +++ b/plugins/feature/rigctlserver/rigctlservergui.ui @@ -1,7 +1,7 @@ RigCtlServerGUI - + 0 @@ -263,17 +263,17 @@ Default is 10000. - - RollupWidget - QWidget -
gui/rollupwidget.h
- 1 -
ButtonSwitch QToolButton
gui/buttonswitch.h
+ + RollupContents + QWidget +
gui/rollupcontents.h
+ 1 +
diff --git a/plugins/feature/satellitetracker/satellitetrackergui.cpp b/plugins/feature/satellitetracker/satellitetrackergui.cpp index d3f983817..157de5899 100644 --- a/plugins/feature/satellitetracker/satellitetrackergui.cpp +++ b/plugins/feature/satellitetracker/satellitetrackergui.cpp @@ -230,7 +230,7 @@ void SatelliteTrackerGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -248,11 +248,11 @@ SatelliteTrackerGUI::SatelliteTrackerGUI(PluginAPI* pluginAPI, FeatureUISet *fea m_polarChart(nullptr), m_geostationarySatVisible(false) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/satellitetracker/readme.md"; setAttribute(Qt::WA_DeleteOnClose, true); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_satelliteTracker = reinterpret_cast(feature); m_satelliteTracker->setMessageQueueToGUI(&m_inputMessageQueue); @@ -303,6 +303,7 @@ SatelliteTrackerGUI::SatelliteTrackerGUI(PluginAPI* pluginAPI, FeatureUISet *fea displaySettings(); applySettings(true); + makeUIConnections(); // Get initial list of satellites on_updateSatData_clicked(); @@ -322,6 +323,7 @@ void SatelliteTrackerGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); ui->latitude->setValue(m_settings.m_latitude); ui->longitude->setValue(m_settings.m_longitude); @@ -337,7 +339,7 @@ void SatelliteTrackerGUI::displaySettings() ui->dateTime->setDateTime(QDateTime::fromString(m_settings.m_dateTime, Qt::ISODateWithMs)); ui->autoTarget->setChecked(m_settings.m_autoTarget); ui->darkTheme->setChecked(m_settings.m_chartsDarkTheme); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); plotChart(); blockApplySettings(false); } @@ -356,7 +358,6 @@ void SatelliteTrackerGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -366,7 +367,6 @@ void SatelliteTrackerGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); @@ -1313,3 +1313,26 @@ void SatelliteTrackerGUI::on_deviceFeatureSelect_currentIndexChanged(int index) } applySettings(); } + +void SatelliteTrackerGUI::makeUIConnections() +{ + QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &SatelliteTrackerGUI::on_startStop_toggled); + QObject::connect(ui->useMyPosition, &QToolButton::clicked, this, &SatelliteTrackerGUI::on_useMyPosition_clicked); + QObject::connect(ui->latitude, qOverload(&QDoubleSpinBox::valueChanged), this, &SatelliteTrackerGUI::on_latitude_valueChanged); + QObject::connect(ui->longitude, qOverload(&QDoubleSpinBox::valueChanged), this, &SatelliteTrackerGUI::on_longitude_valueChanged); + QObject::connect(ui->target, &QComboBox::currentTextChanged, this, &SatelliteTrackerGUI::on_target_currentTextChanged); + QObject::connect(ui->displaySettings, &QToolButton::clicked, this, &SatelliteTrackerGUI::on_displaySettings_clicked); + QObject::connect(ui->radioControl, &QToolButton::clicked, this, &SatelliteTrackerGUI::on_radioControl_clicked); + QObject::connect(ui->dateTimeSelect, qOverload(&QComboBox::currentIndexChanged), this, &SatelliteTrackerGUI::on_dateTimeSelect_currentIndexChanged); + QObject::connect(ui->dateTime, &WrappingDateTimeEdit::dateTimeChanged, this, &SatelliteTrackerGUI::on_dateTime_dateTimeChanged); + QObject::connect(ui->viewOnMap, &QToolButton::clicked, this, &SatelliteTrackerGUI::on_viewOnMap_clicked); + QObject::connect(ui->updateSatData, &QToolButton::clicked, this, &SatelliteTrackerGUI::on_updateSatData_clicked); + QObject::connect(ui->selectSats, &QToolButton::clicked, this, &SatelliteTrackerGUI::on_selectSats_clicked); + QObject::connect(ui->autoTarget, &ButtonSwitch::clicked, this, &SatelliteTrackerGUI::on_autoTarget_clicked); + QObject::connect(ui->chartSelect, qOverload(&QComboBox::currentIndexChanged), this, &SatelliteTrackerGUI::on_chartSelect_currentIndexChanged); + QObject::connect(ui->nextPass, &QToolButton::clicked, this, &SatelliteTrackerGUI::on_nextPass_clicked); + QObject::connect(ui->prevPass, &QToolButton::clicked, this, &SatelliteTrackerGUI::on_prevPass_clicked); + QObject::connect(ui->darkTheme, &QToolButton::clicked, this, &SatelliteTrackerGUI::on_darkTheme_clicked); + QObject::connect(ui->satTable, &QTableWidget::cellDoubleClicked, this, &SatelliteTrackerGUI::on_satTable_cellDoubleClicked); + QObject::connect(ui->deviceFeatureSelect, qOverload(&QComboBox::currentIndexChanged), this, &SatelliteTrackerGUI::on_deviceFeatureSelect_currentIndexChanged); +} diff --git a/plugins/feature/satellitetracker/satellitetrackergui.h b/plugins/feature/satellitetracker/satellitetrackergui.h index f9c9939e9..2d192f48b 100644 --- a/plugins/feature/satellitetracker/satellitetrackergui.h +++ b/plugins/feature/satellitetracker/satellitetrackergui.h @@ -130,6 +130,7 @@ private: void updateDeviceFeatureCombo(const QStringList &items, const QString &selected); void updateFileInputList(); void updateMapList(); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/satellitetracker/satellitetrackergui.ui b/plugins/feature/satellitetracker/satellitetrackergui.ui index f15e45f34..fb84bab4a 100644 --- a/plugins/feature/satellitetracker/satellitetrackergui.ui +++ b/plugins/feature/satellitetracker/satellitetrackergui.ui @@ -1,7 +1,7 @@ SatelliteTrackerGUI - + 0 @@ -716,17 +716,17 @@ - - RollupWidget - QWidget -
gui/rollupwidget.h
- 1 -
ButtonSwitch QToolButton
gui/buttonswitch.h
+ + RollupContents + QWidget +
gui/rollupcontents.h
+ 1 +
QChartView QGraphicsView diff --git a/plugins/feature/simpleptt/simplepttgui.cpp b/plugins/feature/simpleptt/simplepttgui.cpp index 695a5800d..9ec1e52d5 100644 --- a/plugins/feature/simpleptt/simplepttgui.cpp +++ b/plugins/feature/simpleptt/simplepttgui.cpp @@ -138,7 +138,7 @@ void SimplePTTGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -150,11 +150,11 @@ SimplePTTGUI::SimplePTTGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Fea m_doApplySettings(true), m_lastFeatureState(0) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/simpleptt/readme.md"; setAttribute(Qt::WA_DeleteOnClose, true); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_simplePTT = reinterpret_cast(feature); m_simplePTT->setMessageQueueToGUI(&m_inputMessageQueue); @@ -180,6 +180,7 @@ SimplePTTGUI::SimplePTTGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Fea updateDeviceSetLists(); displaySettings(); applySettings(true); + makeUIConnections(); } SimplePTTGUI::~SimplePTTGUI() @@ -196,10 +197,11 @@ void SimplePTTGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); ui->rxtxDelay->setValue(m_settings.m_rx2TxDelayMs); ui->txrxDelay->setValue(m_settings.m_tx2RxDelayMs); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); ui->vox->setChecked(m_settings.m_vox); ui->voxEnable->setChecked(m_settings.m_voxEnable); ui->voxLevel->setValue(m_settings.m_voxLevel); @@ -301,7 +303,6 @@ void SimplePTTGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -311,7 +312,6 @@ void SimplePTTGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); @@ -479,3 +479,18 @@ void SimplePTTGUI::audioSelect() applySettings(); } } + +void SimplePTTGUI::makeUIConnections() +{ + QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &SimplePTTGUI::on_startStop_toggled); + QObject::connect(ui->devicesRefresh, &QPushButton::clicked, this, &SimplePTTGUI::on_devicesRefresh_clicked); + QObject::connect(ui->rxDevice, qOverload(&QComboBox::currentIndexChanged), this, &SimplePTTGUI::on_rxDevice_currentIndexChanged); + QObject::connect(ui->txDevice, qOverload(&QComboBox::currentIndexChanged), this, &SimplePTTGUI::on_txDevice_currentIndexChanged); + QObject::connect(ui->rxtxDelay, qOverload(&QSpinBox::valueChanged), this, &SimplePTTGUI::on_rxtxDelay_valueChanged); + QObject::connect(ui->txrxDelay, qOverload(&QSpinBox::valueChanged), this, &SimplePTTGUI::on_txrxDelay_valueChanged); + QObject::connect(ui->ptt, &ButtonSwitch::toggled, this, &SimplePTTGUI::on_ptt_toggled); + QObject::connect(ui->vox, &ButtonSwitch::toggled, this, &SimplePTTGUI::on_vox_toggled); + QObject::connect(ui->voxEnable, &QCheckBox::clicked, this, &SimplePTTGUI::on_voxEnable_clicked); + QObject::connect(ui->voxLevel, &QDial::valueChanged, this, &SimplePTTGUI::on_voxLevel_valueChanged); + QObject::connect(ui->voxHold, qOverload(&QSpinBox::valueChanged), this, &SimplePTTGUI::on_voxHold_valueChanged); +} diff --git a/plugins/feature/simpleptt/simplepttgui.h b/plugins/feature/simpleptt/simplepttgui.h index b2b73fb7e..3062bde6a 100644 --- a/plugins/feature/simpleptt/simplepttgui.h +++ b/plugins/feature/simpleptt/simplepttgui.h @@ -69,6 +69,7 @@ private: void displaySettings(); void updateDeviceSetLists(); bool handleMessage(const Message& message); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/simpleptt/simplepttgui.ui b/plugins/feature/simpleptt/simplepttgui.ui index 619aaf38a..0293fff1a 100644 --- a/plugins/feature/simpleptt/simplepttgui.ui +++ b/plugins/feature/simpleptt/simplepttgui.ui @@ -1,7 +1,7 @@ SimplePTTGUI - + 0 @@ -448,17 +448,17 @@ - - RollupWidget - QWidget -
gui/rollupwidget.h
- 1 -
ButtonSwitch QToolButton
gui/buttonswitch.h
+ + RollupContents + QWidget +
gui/rollupcontents.h
+ 1 +
diff --git a/plugins/feature/startracker/startrackergui.cpp b/plugins/feature/startracker/startrackergui.cpp index 4fde5482c..fb85c5ed0 100644 --- a/plugins/feature/startracker/startrackergui.cpp +++ b/plugins/feature/startracker/startrackergui.cpp @@ -224,7 +224,7 @@ void StarTrackerGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -254,11 +254,11 @@ StarTrackerGUI::StarTrackerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, m_moonRA(0.0), m_moonDec(0.0) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/startracker/readme.md"; setAttribute(Qt::WA_DeleteOnClose, true); - setChannelWidget(false); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); m_starTracker = reinterpret_cast(feature); m_starTracker->setMessageQueueToGUI(&m_inputMessageQueue); @@ -325,6 +325,7 @@ StarTrackerGUI::StarTrackerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, ui->dateTime->setDateTime(QDateTime::currentDateTime()); displaySettings(); applySettings(true); + makeUIConnections(); // Populate subchart menu on_chartSelect_currentIndexChanged(0); @@ -392,6 +393,7 @@ void StarTrackerGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); ui->darkTheme->setChecked(m_settings.m_chartsDarkTheme); if (m_solarFluxChart) { @@ -445,7 +447,7 @@ void StarTrackerGUI::displaySettings() ui->frequency->setValue(m_settings.m_frequency/1000000.0); ui->beamwidth->setValue(m_settings.m_beamwidth); updateForTarget(); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); plotChart(); blockApplySettings(false); } @@ -464,7 +466,6 @@ void StarTrackerGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -474,7 +475,6 @@ void StarTrackerGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); @@ -2036,3 +2036,38 @@ void StarTrackerGUI::downloadFinished(const QString& filename, bool success) if (success) readSolarFlux(); } + +void StarTrackerGUI::makeUIConnections() +{ + QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &StarTrackerGUI::on_startStop_toggled); + QObject::connect(ui->link, &ButtonSwitch::clicked, this, &StarTrackerGUI::on_link_clicked); + QObject::connect(ui->useMyPosition, &QToolButton::clicked, this, &StarTrackerGUI::on_useMyPosition_clicked); + QObject::connect(ui->latitude, qOverload(&QDoubleSpinBox::valueChanged), this, &StarTrackerGUI::on_latitude_valueChanged); + QObject::connect(ui->longitude, qOverload(&QDoubleSpinBox::valueChanged), this, &StarTrackerGUI::on_longitude_valueChanged); + QObject::connect(ui->rightAscension, &QLineEdit::editingFinished, this, &StarTrackerGUI::on_rightAscension_editingFinished); + QObject::connect(ui->declination, &QLineEdit::editingFinished, this, &StarTrackerGUI::on_declination_editingFinished); + QObject::connect(ui->azimuth, &DMSSpinBox::valueChanged, this, &StarTrackerGUI::on_azimuth_valueChanged); + QObject::connect(ui->elevation, &DMSSpinBox::valueChanged, this, &StarTrackerGUI::on_elevation_valueChanged); + QObject::connect(ui->azimuthOffset, qOverload(&QDoubleSpinBox::valueChanged), this, &StarTrackerGUI::on_azimuthOffset_valueChanged); + QObject::connect(ui->elevationOffset, qOverload(&QDoubleSpinBox::valueChanged), this, &StarTrackerGUI::on_elevationOffset_valueChanged); + QObject::connect(ui->galacticLatitude, &DMSSpinBox::valueChanged, this, &StarTrackerGUI::on_galacticLatitude_valueChanged); + QObject::connect(ui->galacticLongitude, &DMSSpinBox::valueChanged, this, &StarTrackerGUI::on_galacticLongitude_valueChanged); + QObject::connect(ui->frequency, qOverload(&QSpinBox::valueChanged), this, &StarTrackerGUI::on_frequency_valueChanged); + QObject::connect(ui->beamwidth, qOverload(&QDoubleSpinBox::valueChanged), this, &StarTrackerGUI::on_beamwidth_valueChanged); + QObject::connect(ui->target, &QComboBox::currentTextChanged, this, &StarTrackerGUI::on_target_currentTextChanged); + QObject::connect(ui->displaySettings, &QToolButton::clicked, this, &StarTrackerGUI::on_displaySettings_clicked); + QObject::connect(ui->dateTimeSelect, &QComboBox::currentTextChanged, this, &StarTrackerGUI::on_dateTimeSelect_currentTextChanged); + QObject::connect(ui->dateTime, &WrappingDateTimeEdit::dateTimeChanged, this, &StarTrackerGUI::on_dateTime_dateTimeChanged); + QObject::connect(ui->viewOnMap, &QToolButton::clicked, this, &StarTrackerGUI::on_viewOnMap_clicked); + QObject::connect(ui->chartSelect, qOverload(&QComboBox::currentIndexChanged), this, &StarTrackerGUI::on_chartSelect_currentIndexChanged); + QObject::connect(ui->chartSubSelect, qOverload(&QComboBox::currentIndexChanged), this, &StarTrackerGUI::on_chartSubSelect_currentIndexChanged); + QObject::connect(ui->downloadSolarFlux, &QToolButton::clicked, this, &StarTrackerGUI::on_downloadSolarFlux_clicked); + QObject::connect(ui->darkTheme, &QToolButton::clicked, this, &StarTrackerGUI::on_darkTheme_clicked); + QObject::connect(ui->zoomIn, &QToolButton::clicked, this, &StarTrackerGUI::on_zoomIn_clicked); + QObject::connect(ui->zoomOut, &QToolButton::clicked, this, &StarTrackerGUI::on_zoomOut_clicked); + QObject::connect(ui->addAnimationFrame, &QToolButton::clicked, this, &StarTrackerGUI::on_addAnimationFrame_clicked); + QObject::connect(ui->clearAnimation, &QToolButton::clicked, this, &StarTrackerGUI::on_clearAnimation_clicked); + QObject::connect(ui->saveAnimation, &QToolButton::clicked, this, &StarTrackerGUI::on_saveAnimation_clicked); + QObject::connect(ui->drawSun, &QToolButton::clicked, this, &StarTrackerGUI::on_drawSun_clicked); + QObject::connect(ui->drawMoon, &QToolButton::clicked, this, &StarTrackerGUI::on_drawMoon_clicked); +} diff --git a/plugins/feature/startracker/startrackergui.h b/plugins/feature/startracker/startrackergui.h index b3e6b89d3..2d41484da 100644 --- a/plugins/feature/startracker/startrackergui.h +++ b/plugins/feature/startracker/startrackergui.h @@ -153,6 +153,7 @@ private: void raDecChanged(); void updateChartSubSelect(); void updateSolarFlux(bool all); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/startracker/startrackergui.ui b/plugins/feature/startracker/startrackergui.ui index 11866fb24..3f42355e6 100644 --- a/plugins/feature/startracker/startrackergui.ui +++ b/plugins/feature/startracker/startrackergui.ui @@ -1,7 +1,7 @@ StarTrackerGUI - + 0 @@ -846,17 +846,17 @@ This can be specified as a decimal (E.g. 34.23) or in degrees, minutes and secon - - RollupWidget - QWidget -
gui/rollupwidget.h
- 1 -
ButtonSwitch QToolButton
gui/buttonswitch.h
+ + RollupContents + QWidget +
gui/rollupcontents.h
+ 1 +
QChartView QGraphicsView diff --git a/plugins/feature/vorlocalizer/vorlocalizergui.cpp b/plugins/feature/vorlocalizer/vorlocalizergui.cpp index ae89e4612..e27fc2332 100644 --- a/plugins/feature/vorlocalizer/vorlocalizergui.cpp +++ b/plugins/feature/vorlocalizer/vorlocalizergui.cpp @@ -1174,7 +1174,7 @@ void VORLocalizerGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) widget; (void) rollDown; - saveState(m_rollupState); + getRollupContents()->saveState(m_rollupState); applySettings(); } @@ -1184,7 +1184,6 @@ void VORLocalizerGUI::onMenuDialogCalled(const QPoint &p) { BasicFeatureSettingsDialog dialog(this); dialog.setTitle(m_settings.m_title); - dialog.setColor(m_settings.m_rgbColor); dialog.setUseReverseAPI(m_settings.m_useReverseAPI); dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); @@ -1194,7 +1193,6 @@ void VORLocalizerGUI::onMenuDialogCalled(const QPoint &p) dialog.move(p); dialog.exec(); - m_settings.m_rgbColor = dialog.getColor().rgb(); m_settings.m_title = dialog.getTitle(); m_settings.m_useReverseAPI = dialog.useReverseAPI(); m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); @@ -1225,7 +1223,8 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe m_lastFeatureState(0), m_rrSecondsCount(0) { - ui->setupUi(this); + ui->setupUi(getRollupContents()); + getRollupContents()->arrangeRollups(); m_helpURL = "plugins/feature/vorlocalizer/readme.md"; ui->map->rootContext()->setContextProperty("vorModel", &m_vorModel); @@ -1235,7 +1234,7 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe m_muteIcon.addPixmap(QPixmap("://sound_on.png"), QIcon::Normal, QIcon::Off); setAttribute(Qt::WA_DeleteOnClose, true); - connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(getRollupContents(), SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); connect(&m_dlm, &HttpDownloadManager::downloadComplete, this, &VORLocalizerGUI::downloadFinished); @@ -1328,6 +1327,7 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe displaySettings(); applySettings(true); + makeUIConnections(); } VORLocalizerGUI::~VORLocalizerGUI() @@ -1353,6 +1353,7 @@ void VORLocalizerGUI::displaySettings() { setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); blockApplySettings(true); @@ -1378,7 +1379,7 @@ void VORLocalizerGUI::displaySettings() ui->centerShift->setValue(m_settings.m_centerShift/1000); ui->forceRRAveraging->setChecked(m_settings.m_forceRRAveraging); - restoreState(m_rollupState); + getRollupContents()->restoreState(m_rollupState); blockApplySettings(false); } @@ -1449,3 +1450,14 @@ void VORLocalizerGUI::tick() m_tickCount = 0; } } + +void VORLocalizerGUI::makeUIConnections() +{ + QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &VORLocalizerGUI::on_startStop_toggled); + QObject::connect(ui->getOurAirportsVORDB, &QPushButton::clicked, this, &VORLocalizerGUI::on_getOurAirportsVORDB_clicked); + QObject::connect(ui->getOpenAIPVORDB, &QPushButton::clicked, this, &VORLocalizerGUI::on_getOpenAIPVORDB_clicked); + QObject::connect(ui->magDecAdjust, &ButtonSwitch::toggled, this, &VORLocalizerGUI::on_magDecAdjust_toggled); + QObject::connect(ui->rrTime, &QDial::valueChanged, this, &VORLocalizerGUI::on_rrTime_valueChanged); + QObject::connect(ui->centerShift, &QDial::valueChanged, this, &VORLocalizerGUI::on_centerShift_valueChanged); + QObject::connect(ui->channelsRefresh, &QPushButton::clicked, this, &VORLocalizerGUI::on_channelsRefresh_clicked); +} diff --git a/plugins/feature/vorlocalizer/vorlocalizergui.h b/plugins/feature/vorlocalizer/vorlocalizergui.h index 6a0092879..b2d1f34f0 100644 --- a/plugins/feature/vorlocalizer/vorlocalizergui.h +++ b/plugins/feature/vorlocalizer/vorlocalizergui.h @@ -252,6 +252,7 @@ private: void applySettings(bool force = false); void displaySettings(); bool handleMessage(const Message& message); + void makeUIConnections(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/feature/vorlocalizer/vorlocalizergui.ui b/plugins/feature/vorlocalizer/vorlocalizergui.ui index 256d519fd..2824b96e4 100644 --- a/plugins/feature/vorlocalizer/vorlocalizergui.ui +++ b/plugins/feature/vorlocalizer/vorlocalizergui.ui @@ -1,7 +1,7 @@ VORLocalizerGUI - + 0 @@ -200,6 +200,7 @@ + Ubuntu 8 @@ -542,17 +543,17 @@ QToolTip{background-color: white; color: black;} QWidget
QtQuickWidgets/QQuickWidget
- - RollupWidget - QWidget -
gui/rollupwidget.h
- 1 -
ButtonSwitch QToolButton
gui/buttonswitch.h
+ + RollupContents + QWidget +
gui/rollupcontents.h
+ 1 +
getOurAirportsVORDB diff --git a/sdrbase/pipes/messagepipeslegacy.cpp b/sdrbase/pipes/messagepipeslegacy.cpp new file mode 100644 index 000000000..6d9355bba --- /dev/null +++ b/sdrbase/pipes/messagepipeslegacy.cpp @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "util/messagequeue.h" + +#include "messagepipeslegacygcworker.h" +#include "messagepipeslegacy.h" +#include "pipeendpoint.h" + +MessagePipesLegacy::MessagePipesLegacy() +{ + m_gcWorker = new MessagePipesLegacyGCWorker(); + m_gcWorker->setC2FRegistrations( + m_registrations.getMutex(), + m_registrations.getElements(), + m_registrations.getConsumers() + ); + m_gcWorker->moveToThread(&m_gcThread); + startGC(); +} + +MessagePipesLegacy::~MessagePipesLegacy() +{ + if (m_gcWorker->isRunning()) { + stopGC(); + } +} + +MessageQueue *MessagePipesLegacy::registerChannelToFeature(const PipeEndPoint *source, PipeEndPoint *dest, const QString& type) +{ + qDebug("MessagePipesLegacy::registerChannelToFeature: %p %p %s", source, dest, qPrintable(type)); + return m_registrations.registerProducerToConsumer(source, dest, type); +} + +MessageQueue *MessagePipesLegacy::unregisterChannelToFeature(const PipeEndPoint *source, PipeEndPoint *dest, const QString& type) +{ + qDebug("MessagePipesLegacy::unregisterChannelToFeature: %p %p %s", source, dest, qPrintable(type)); + MessageQueue *messageQueue = m_registrations.unregisterProducerToConsumer(source, dest, type); + m_gcWorker->addMessageQueueToDelete(messageQueue); + return messageQueue; +} + +QList* MessagePipesLegacy::getMessageQueues(const PipeEndPoint *source, const QString& type) +{ + //qDebug("MessagePipesLegacy::getMessageQueues: %p %s", source, qPrintable(type)); + return m_registrations.getElements(source, type); +} + +void MessagePipesLegacy::startGC() +{ + qDebug("MessagePipesLegacy::startGC"); + m_gcWorker->startWork(); + m_gcThread.start(); +} + +void MessagePipesLegacy::stopGC() +{ + qDebug("MessagePipesLegacy::stopGC"); + m_gcWorker->stopWork(); + m_gcThread.quit(); + m_gcThread.wait(); +} diff --git a/sdrbase/pipes/messagepipeslegacy.h b/sdrbase/pipes/messagepipeslegacy.h new file mode 100644 index 000000000..562e582a8 --- /dev/null +++ b/sdrbase/pipes/messagepipeslegacy.h @@ -0,0 +1,59 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRBASE_PIPES_MESSAGEPIPESLEGACY_H_ +#define SDRBASE_PIPES_MESSAGEPIPESLEGACY_H_ + +#include +#include +#include +#include +#include + +#include "export.h" + +#include "messagepipeslegacycommon.h" +#include "elementpipesregistrations.h" + +class PipeEndPoint; +class MessagePipesLegacyGCWorker; +class MessageQueue; + +class SDRBASE_API MessagePipesLegacy : public QObject +{ + Q_OBJECT +public: + MessagePipesLegacy(); + MessagePipesLegacy(const MessagePipesLegacy&) = delete; + MessagePipesLegacy& operator=(const MessagePipesLegacy&) = delete; + ~MessagePipesLegacy(); + + // FIXME: Names of these functions should probably change, as we now support channel or feature at either end + MessageQueue *registerChannelToFeature(const PipeEndPoint *source, PipeEndPoint *dest, const QString& type); + MessageQueue *unregisterChannelToFeature(const PipeEndPoint *source, PipeEndPoint *dest, const QString& type); + QList* getMessageQueues(const PipeEndPoint *source, const QString& type); + +private: + ElementPipesRegistrations m_registrations; + QThread m_gcThread; //!< Garbage collector thread + MessagePipesLegacyGCWorker *m_gcWorker; //!< Garbage collector + + void startGC(); //!< Start garbage collector + void stopGC(); //!< Stop garbage collector +}; + +#endif // SDRBASE_PIPES_MESSAGEPIPESLEGACY_H_ diff --git a/sdrbase/pipes/messagepipeslegacycommon.cpp b/sdrbase/pipes/messagepipeslegacycommon.cpp new file mode 100644 index 000000000..984a452d5 --- /dev/null +++ b/sdrbase/pipes/messagepipeslegacycommon.cpp @@ -0,0 +1,20 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "messagepipeslegacycommon.h" + +MESSAGE_CLASS_DEFINITION(MessagePipesLegacyCommon::MsgReportChannelDeleted, Message) diff --git a/sdrbase/pipes/messagepipeslegacycommon.h b/sdrbase/pipes/messagepipeslegacycommon.h new file mode 100644 index 000000000..42f3b9600 --- /dev/null +++ b/sdrbase/pipes/messagepipeslegacycommon.h @@ -0,0 +1,61 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRBASE_PIPES_MESSAGEPIPESLEGACYCOMON_H_ +#define SDRBASE_PIPES_MESSAGEPIPESLEGACYCOMON_H_ + +#include +#include +#include + +#include "export.h" +#include "util/message.h" +#include "elementpipescommon.h" + +class PipeEndPoint; +class MessageQueue; + +class SDRBASE_API MessagePipesLegacyCommon +{ +public: + typedef ElementPipesCommon::RegistrationKey ChannelRegistrationKey; + + /** Send this message to stakeholders when the garbage collector finds that a channel was deleted */ + class SDRBASE_API MsgReportChannelDeleted : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const MessageQueue *getMessageQueue() const { return m_messageQueue; } + const ChannelRegistrationKey& getChannelRegistrationKey() const { return m_channelRegistrationKey; } + + static MsgReportChannelDeleted* create(const MessageQueue *messageQueue, const ChannelRegistrationKey& channelRegistrationKey) { + return new MsgReportChannelDeleted(messageQueue, channelRegistrationKey); + } + + private: + const MessageQueue *m_messageQueue; + ChannelRegistrationKey m_channelRegistrationKey; + + MsgReportChannelDeleted(const MessageQueue *messageQueue, const ChannelRegistrationKey& channelRegistrationKey) : + Message(), + m_messageQueue(messageQueue), + m_channelRegistrationKey(channelRegistrationKey) + { } + }; +}; + +#endif // SDRBASE_PIPES_MESSAGEPIPESLEGACYCOMON_H_ diff --git a/sdrbase/pipes/messagepipeslegacygcworker.cpp b/sdrbase/pipes/messagepipeslegacygcworker.cpp new file mode 100644 index 000000000..f05c65bc3 --- /dev/null +++ b/sdrbase/pipes/messagepipeslegacygcworker.cpp @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "channel/channelapi.h" +#include "feature/feature.h" +#include "util/messagequeue.h" +#include "maincore.h" +#include "messagepipeslegacycommon.h" +#include "messagepipeslegacygcworker.h" + +bool MessagePipesLegacyGCWorker::MessagePipesGC::existsProducer(const PipeEndPoint *pipeEndPoint) +{ + return MainCore::instance()->existsChannel((const ChannelAPI *)pipeEndPoint) + || MainCore::instance()->existsFeature((const Feature *)pipeEndPoint); +} + +bool MessagePipesLegacyGCWorker::MessagePipesGC::existsConsumer(const PipeEndPoint *pipeEndPoint) +{ + return MainCore::instance()->existsChannel((const ChannelAPI *)pipeEndPoint) + || MainCore::instance()->existsFeature((const Feature *)pipeEndPoint); +} + +void MessagePipesLegacyGCWorker::MessagePipesGC::sendMessageToConsumer( + const MessageQueue *, + MessagePipesLegacyCommon::ChannelRegistrationKey, + PipeEndPoint *) +{ +} + +MessagePipesLegacyGCWorker::MessagePipesLegacyGCWorker() : + m_running(false) +{} + +MessagePipesLegacyGCWorker::~MessagePipesLegacyGCWorker() +{} + +void MessagePipesLegacyGCWorker::startWork() +{ + connect(&m_gcTimer, SIGNAL(timeout()), this, SLOT(processGC())); + m_gcTimer.start(10000); // collect garbage every 10s + m_running = true; +} + +void MessagePipesLegacyGCWorker::stopWork() +{ + m_running = false; + m_gcTimer.stop(); + disconnect(&m_gcTimer, SIGNAL(timeout()), this, SLOT(processGC())); +} + +void MessagePipesLegacyGCWorker::addMessageQueueToDelete(MessageQueue *messageQueue) +{ + if (messageQueue) + { + m_gcTimer.start(10000); // restart GC to make sure deletion is postponed + m_messagePipesGC.addElementToDelete(messageQueue); + } +} + +void MessagePipesLegacyGCWorker::processGC() +{ + // qDebug("MessagePipesLegacyGCWorker::processGC"); + m_messagePipesGC.processGC(); +} diff --git a/sdrbase/pipes/messagepipeslegacygcworker.h b/sdrbase/pipes/messagepipeslegacygcworker.h new file mode 100644 index 000000000..309b13125 --- /dev/null +++ b/sdrbase/pipes/messagepipeslegacygcworker.h @@ -0,0 +1,69 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRBASE_PIPES_MESSAGEPIPESLEGACYGCWORKER_H_ +#define SDRBASE_PIPES_MESSAGEPIPESLEGACYGCWORKER_H_ + +#include +#include + +#include "export.h" + +#include "messagepipeslegacycommon.h" +#include "elementpipesgc.h" + +class QMutex; + +class SDRBASE_API MessagePipesLegacyGCWorker : public QObject +{ + Q_OBJECT +public: + MessagePipesLegacyGCWorker(); + ~MessagePipesLegacyGCWorker(); + + void setC2FRegistrations( + QMutex *c2fMutex, + QMap> *c2fQueues, + QMap> *c2fPipeEndPoints + ) + { + m_messagePipesGC.setRegistrations(c2fMutex, c2fQueues, c2fPipeEndPoints); + } + + void startWork(); + void stopWork(); + void addMessageQueueToDelete(MessageQueue *messageQueue); + bool isRunning() const { return m_running; } + +private: + class MessagePipesGC : public ElementPipesGC + { + private: + virtual bool existsProducer(const PipeEndPoint *pipeEndPoint); + virtual bool existsConsumer(const PipeEndPoint *pipeEndPoint); + virtual void sendMessageToConsumer(const MessageQueue *messageQueue, MessagePipesLegacyCommon::ChannelRegistrationKey key, PipeEndPoint *pipeEndPoint); + }; + + MessagePipesGC m_messagePipesGC; + bool m_running; + QTimer m_gcTimer; + +private slots: + void processGC(); //!< Collect garbage +}; + +#endif // SDRBASE_PIPES_MESSAGEPIPESLEGACYGCWORKER_H_ diff --git a/sdrbase/pipes/pipeendpoint.cpp b/sdrbase/pipes/pipeendpoint.cpp new file mode 100644 index 000000000..9a3ba38eb --- /dev/null +++ b/sdrbase/pipes/pipeendpoint.cpp @@ -0,0 +1,185 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include + +#include "dsp/dspengine.h" +#include "device/deviceset.h" +#include "channel/channelapi.h" +#include "feature/featureset.h" +#include "feature/feature.h" +#include "maincore.h" + +#include "pipeendpoint.h" + +MESSAGE_CLASS_DEFINITION(PipeEndPoint::MsgReportPipes, Message) + +QList PipeEndPoint::updateAvailablePipeSources(QString pipeName, QStringList pipeTypes, QStringList pipeURIs, PipeEndPoint *destination) +{ + MainCore *mainCore = MainCore::instance(); + MessagePipesLegacy& messagePipes = mainCore->getMessagePipesLegacy(); + std::vector& deviceSets = mainCore->getDeviceSets(); + QHash availablePipes; + + // Source is a channel + int deviceIndex = 0; + for (std::vector::const_iterator it = deviceSets.begin(); it != deviceSets.end(); ++it, deviceIndex++) + { + DSPDeviceSourceEngine *deviceSourceEngine = (*it)->m_deviceSourceEngine; + DSPDeviceSinkEngine *deviceSinkEngine = (*it)->m_deviceSinkEngine; + + if (deviceSourceEngine || deviceSinkEngine) + { + for (int chi = 0; chi < (*it)->getNumberOfChannels(); chi++) + { + ChannelAPI *channel = (*it)->getChannelAt(chi); + int i = pipeURIs.indexOf(channel->getURI()); + + if (i >= 0) + { + if (!availablePipes.contains(channel)) + { + MessageQueue *messageQueue = messagePipes.registerChannelToFeature(channel, destination, pipeName); + if (MainCore::instance()->existsFeature((const Feature *)destination)) + { + // Destination is feature + Feature *featureDest = (Feature *)destination; + QObject::connect( + messageQueue, + &MessageQueue::messageEnqueued, + featureDest, + [=](){ featureDest->handlePipeMessageQueue(messageQueue); }, + Qt::QueuedConnection + ); + } + else + { + // Destination is a channel + // Can't use Qt::QueuedConnection because ChannelAPI isn't a QObject + ChannelAPI *channelDest = (ChannelAPI *)destination; + QObject::connect( + messageQueue, + &MessageQueue::messageEnqueued, + [=](){ channelDest->handlePipeMessageQueue(messageQueue); } + ); + } + } + + AvailablePipeSource availablePipe = + AvailablePipeSource{ + deviceSinkEngine != nullptr ? AvailablePipeSource::TX : AvailablePipeSource::RX, + deviceIndex, + chi, + channel, + pipeTypes.at(i) + }; + availablePipes[channel] = availablePipe; + } + } + } + } + + // Source is a feature + std::vector& featureSets = mainCore->getFeatureeSets(); + int featureIndex = 0; + for (std::vector::const_iterator it = featureSets.begin(); it != featureSets.end(); ++it, featureIndex++) + { + for (int fi = 0; fi < (*it)->getNumberOfFeatures(); fi++) + { + Feature *feature = (*it)->getFeatureAt(fi); + int i = pipeURIs.indexOf(feature->getURI()); + + if (i >= 0) + { + if (!availablePipes.contains(feature)) + { + MessageQueue *messageQueue = messagePipes.registerChannelToFeature(feature, destination, pipeName); + if (MainCore::instance()->existsFeature((const Feature *)destination)) + { + // Destination is feature + Feature *featureDest = (Feature *)destination; + QObject::connect( + messageQueue, + &MessageQueue::messageEnqueued, + featureDest, + [=](){ featureDest->handlePipeMessageQueue(messageQueue); }, + Qt::QueuedConnection + ); + } + else + { + // Destination is a channel + // Can't use Qt::QueuedConnection because ChannelAPI isn't a QObject + ChannelAPI *channelDest = (ChannelAPI *)destination; + QObject::connect( + messageQueue, + &MessageQueue::messageEnqueued, + [=](){ channelDest->handlePipeMessageQueue(messageQueue); } + ); + } + } + + AvailablePipeSource availablePipe = + AvailablePipeSource{ + AvailablePipeSource::Feature, + featureIndex, + fi, + feature, + pipeTypes.at(i) + }; + availablePipes[feature] = availablePipe; + } + } + } + + QList availablePipeList; + QHash::iterator it = availablePipes.begin(); + + for (; it != availablePipes.end(); ++it) { + availablePipeList.push_back(*it); + } + return availablePipeList; +} + +PipeEndPoint *PipeEndPoint::getPipeEndPoint(const QString name, const QList &availablePipeSources) +{ + QRegExp re("([TRF])([0-9]+):([0-9]+) ([a-zA-Z0-9]+)"); + if (re.exactMatch(name)) + { + QString type = re.capturedTexts()[1]; + int setIndex = re.capturedTexts()[2].toInt(); + int index = re.capturedTexts()[3].toInt(); + QString id = re.capturedTexts()[4]; + + QListIterator itr(availablePipeSources); + while (itr.hasNext()) + { + AvailablePipeSource p = itr.next(); + if ((p.m_setIndex == setIndex) && (p.m_index == index) && (id == p.m_id)) { + return p.m_source; + } + } + } + else + { + qDebug() << "PipeEndPoint::getPipeEndPoint: " << name << " is malformed"; + } + return nullptr; +} diff --git a/sdrbase/pipes/pipeendpoint.h b/sdrbase/pipes/pipeendpoint.h new file mode 100644 index 000000000..5de230b09 --- /dev/null +++ b/sdrbase/pipes/pipeendpoint.h @@ -0,0 +1,100 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// Parent for ChannelAPI and Features, where either can be used. // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRBASE_PIPES_PIPEENDPOINT_H_ +#define SDRBASE_PIPES_PIPEENDPOINT_H_ + +#include +#include +#include + +#include "util/message.h" +#include "export.h" + +class Feature; + +class SDRBASE_API PipeEndPoint { +public: + + // Used by pipe sinks (channels or features) to record details about available pipe sources (channels or features) + struct AvailablePipeSource + { + enum {RX, TX, Feature} m_type; + int m_setIndex; + int m_index; + PipeEndPoint *m_source; + QString m_id; + + AvailablePipeSource() = default; + AvailablePipeSource(const AvailablePipeSource&) = default; + AvailablePipeSource& operator=(const AvailablePipeSource&) = default; + friend bool operator==(const AvailablePipeSource &lhs, const AvailablePipeSource &rhs) + { + return (lhs.m_type == rhs.m_type) + && (lhs.m_setIndex == rhs.m_setIndex) + && (lhs.m_source == rhs.m_source) + && (lhs.m_id == rhs.m_id); + } + + QString getTypeName() const + { + QStringList typeNames = {"R", "T", "F"}; + return typeNames[m_type]; + } + + // Name for use in GUI combo boxes and WebAPI + QString getName() const + { + QString type; + + return QString("%1%2:%3 %4").arg(getTypeName()) + .arg(m_setIndex) + .arg(m_index) + .arg(m_id); + } + }; + + class SDRBASE_API MsgReportPipes : public Message { + MESSAGE_CLASS_DECLARATION + + public: + QList& getAvailablePipes() { return m_availablePipes; } + + static MsgReportPipes* create() { + return new MsgReportPipes(); + } + + private: + QList m_availablePipes; + + MsgReportPipes() : + Message() + {} + }; + + +protected: + + // Utility functions for pipe sinks to manage list of sources + QList updateAvailablePipeSources(QString pipeName, QStringList pipeTypes, QStringList pipeURIs, PipeEndPoint *destination); + PipeEndPoint *getPipeEndPoint(const QString name, const QList &availablePipeSources); + +}; + +#endif // SDRBASE_PIPES_PIPEENDPOINT_H_ diff --git a/sdrgui/CMakeLists.txt b/sdrgui/CMakeLists.txt index 3013ac2aa..2b8a85c4a 100644 --- a/sdrgui/CMakeLists.txt +++ b/sdrgui/CMakeLists.txt @@ -57,6 +57,7 @@ set(sdrgui_SOURCES gui/mypositiondialog.cpp gui/pluginsdialog.cpp gui/presetitem.cpp + gui/rollupcontents.cpp gui/rollupwidget.cpp gui/samplingdevicedialog.cpp gui/samplingdevicesdock.cpp @@ -73,6 +74,8 @@ set(sdrgui_SOURCES gui/tvscreenanalog.cpp gui/valuedial.cpp gui/valuedialz.cpp + gui/workspace.cpp + gui/workspaceselectiondialog.cpp gui/wsspectrumsettingsdialog.cpp gui/wrappingdatetimeedit.cpp @@ -152,6 +155,7 @@ set(sdrgui_HEADERS gui/physicalunit.h gui/pluginsdialog.h gui/presetitem.h + gui/rollupcontents.h gui/rollupwidget.h gui/samplingdevicedialog.h gui/samplingdevicesdock.h @@ -168,6 +172,8 @@ set(sdrgui_HEADERS gui/tvscreenanalog.h gui/valuedial.h gui/valuedialz.h + gui/workspace.h + gui/workspaceselectiondialog.h gui/wsspectrumsettingsdialog.h gui/wrappingdatetimeedit.h @@ -224,6 +230,7 @@ set(sdrgui_FORMS gui/myposdialog.ui gui/transverterdialog.ui gui/loggingdialog.ui + gui/workspaceselectiondialog.ui gui/wsspectrumsettingsdialog.ui soapygui/discreterangegui.ui soapygui/intervalrangegui.ui diff --git a/sdrgui/feature/featuregui.cpp b/sdrgui/feature/featuregui.cpp index df0790251..18128e2c1 100644 --- a/sdrgui/feature/featuregui.cpp +++ b/sdrgui/feature/featuregui.cpp @@ -16,12 +16,216 @@ /////////////////////////////////////////////////////////////////////////////////// #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mainwindow.h" +#include "gui/workspaceselectiondialog.h" #include "featuregui.h" +FeatureGUI::FeatureGUI(QWidget *parent) : + QMdiSubWindow(parent), + m_featureIndex(0), + m_workspaceIndex(0), + m_contextMenuType(ContextMenuNone), + m_drag(false) +{ + qDebug("FeatureGUI::FeatureGUI"); + setWindowFlags(windowFlags() | Qt::FramelessWindowHint); + + m_indexLabel = new QLabel(); + m_indexLabel->setFixedSize(40, 16); + m_indexLabel->setStyleSheet("QLabel { background-color: rgb(128, 128, 128); qproperty-alignment: AlignCenter; }"); + m_indexLabel->setText(tr("F:%1").arg(m_featureIndex)); + m_indexLabel->setToolTip("Feature index"); + + m_settingsButton = new QPushButton(); + QIcon settingsIcon(":/gear.png"); + m_settingsButton->setIcon(settingsIcon); + m_settingsButton->setToolTip("Common settings"); + + m_titleLabel = new QLabel(); + m_titleLabel->setText("Feature"); + m_titleLabel->setToolTip("Feature name"); + m_titleLabel->setFixedHeight(20); + + m_helpButton = new QPushButton(); + m_helpButton->setFixedSize(20, 20); + QIcon helpIcon(":/help.png"); + m_helpButton->setIcon(helpIcon); + m_helpButton->setToolTip("Show feature documentation in browser"); + + m_moveButton = new QPushButton(); + m_moveButton->setFixedSize(20, 20); + QIcon moveIcon(":/exit.png"); + m_moveButton->setIcon(moveIcon); + m_moveButton->setToolTip("Move to workspace"); + + m_shrinkButton = new QPushButton(); + m_shrinkButton->setFixedSize(20, 20); + QIcon shrinkIcon(":/shrink.png"); + m_shrinkButton->setIcon(shrinkIcon); + m_shrinkButton->setToolTip("Adjust window to minimum size"); + + m_closeButton = new QPushButton(); + m_closeButton->setFixedSize(20, 20); + QIcon closeIcon(":/cross.png"); + m_closeButton->setIcon(closeIcon); + m_closeButton->setToolTip("Close feature"); + + m_statusLabel = new QLabel(); + m_statusLabel->setText("OK"); // for future use + m_statusLabel->setFixedHeight(20); + m_statusLabel->setToolTip("Feature status"); + + m_layouts = new QVBoxLayout(); + m_layouts->setContentsMargins(0, 4, 0, 4); + m_layouts->setSpacing(2); + + m_topLayout = new QHBoxLayout(); + m_topLayout->setContentsMargins(0, 0, 0, 0); + m_topLayout->addWidget(m_indexLabel); + m_topLayout->addWidget(m_settingsButton); + m_topLayout->addWidget(m_titleLabel); + m_topLayout->addStretch(1); + m_topLayout->addWidget(m_helpButton); + m_topLayout->addWidget(m_moveButton); + m_topLayout->addWidget(m_shrinkButton); + m_topLayout->addWidget(m_closeButton); + m_sizeGripTopRight = new QSizeGrip(this); + m_sizeGripTopRight->setStyleSheet("QSizeGrip { background-color: rgb(128, 128, 128); width: 10px; height: 10px; }"); + m_topLayout->addWidget(m_sizeGripTopRight, 0, Qt::AlignTop | Qt::AlignRight); + + m_centerLayout = new QHBoxLayout(); + m_centerLayout->addWidget(&m_rollupContents); + + m_bottomLayout = new QHBoxLayout(); + m_bottomLayout->setContentsMargins(0, 0, 0, 0); + m_bottomLayout->addWidget(m_statusLabel); + m_sizeGripBottomRight = new QSizeGrip(this); + m_sizeGripBottomRight->setStyleSheet("QSizeGrip { background-color: rgb(128, 128, 128); width: 10px; height: 10px; }"); + m_bottomLayout->addWidget(m_sizeGripBottomRight, 0, Qt::AlignBottom | Qt::AlignRight); + + m_layouts->addLayout(m_topLayout); + m_layouts->addLayout(m_centerLayout); + m_layouts->addLayout(m_bottomLayout); + + QObjectCleanupHandler().add(layout()); + setLayout(m_layouts); + + connect(m_settingsButton, SIGNAL(clicked()), this, SLOT(activateSettingsDialog())); + connect(m_helpButton, SIGNAL(clicked()), this, SLOT(showHelp())); + connect(m_moveButton, SIGNAL(clicked()), this, SLOT(openMoveToWorkspaceDialog())); + connect(m_shrinkButton, SIGNAL(clicked()), this, SLOT(shrinkWindow())); + connect(this, SIGNAL(forceShrink()), this, SLOT(shrinkWindow())); + connect(m_closeButton, SIGNAL(clicked()), this, SLOT(close())); +} + +FeatureGUI::~FeatureGUI() +{ + delete m_sizeGripBottomRight; + delete m_bottomLayout; + delete m_centerLayout; + delete m_sizeGripTopRight; + delete m_topLayout; + delete m_layouts; + delete m_statusLabel; + delete m_closeButton; + delete m_shrinkButton; + delete m_moveButton; + delete m_helpButton; + delete m_titleLabel; + delete m_settingsButton; + delete m_indexLabel; +} + void FeatureGUI::closeEvent(QCloseEvent *event) { qDebug("FeatureGUI::closeEvent"); emit closing(); event->accept(); } + +void FeatureGUI::mousePressEvent(QMouseEvent* event) +{ + if ((event->button() == Qt::LeftButton) && isOnMovingPad()) + { + m_drag = true; + m_DragPosition = event->globalPos() - pos(); + event->accept(); + } +} + +void FeatureGUI::mouseMoveEvent(QMouseEvent* event) +{ + if ((event->buttons() & Qt::LeftButton) && isOnMovingPad()) + { + move(event->globalPos() - m_DragPosition); + event->accept(); + } +} + +void FeatureGUI::activateSettingsDialog() +{ + QPoint p = mapFromGlobal(QCursor::pos()); + m_contextMenuType = ContextMenuChannelSettings; + emit customContextMenuRequested(p); +} + +void FeatureGUI::showHelp() +{ + if (m_helpURL.isEmpty()) { + return; + } + + QString url; + + if (m_helpURL.startsWith("http")) { + url = m_helpURL; + } else { + url = QString("https://github.com/f4exb/sdrangel/blob/master/%1").arg(m_helpURL); // Something like "plugins/channelrx/chanalyzer/readme.md" + } + + QDesktopServices::openUrl(QUrl(url)); +} + +void FeatureGUI::openMoveToWorkspaceDialog() +{ + int numberOfWorkspaces = MainWindow::getInstance()->getNumberOfWorkspaces(); + WorkspaceSelectionDialog dialog(numberOfWorkspaces, this); + dialog.exec(); + + if (dialog.hasChanged()) { + emit moveToWorkspace(dialog.getSelectedIndex()); + } +} + +void FeatureGUI::shrinkWindow() +{ + qDebug("FeatureGUI::shrinkWindow"); + adjustSize(); +} + +void FeatureGUI::setTitle(const QString& title) +{ + m_titleLabel->setText(title); +} + +bool FeatureGUI::isOnMovingPad() +{ + return m_indexLabel->underMouse() || m_titleLabel->underMouse() || m_statusLabel->underMouse(); +} + +void FeatureGUI::setIndex(int index) +{ + m_featureIndex = index; + m_indexLabel->setText(tr("F:%1").arg(m_featureIndex)); +} + diff --git a/sdrgui/feature/featuregui.h b/sdrgui/feature/featuregui.h index 90fe4bc4c..c51691acb 100644 --- a/sdrgui/feature/featuregui.h +++ b/sdrgui/feature/featuregui.h @@ -18,20 +18,32 @@ #ifndef SDRGUI_FEATURE_FEATUREGUI_H_ #define SDRGUI_FEATURE_FEATUREGUI_H_ -#include "gui/rollupwidget.h" +#include + +#include "gui/rollupcontents.h" #include "export.h" class QCloseEvent; class MessageQueue; +class QLabel; +class QPushButton; +class QVBoxLayout; +class QHBoxLayout; +class QSizeGrip; -class SDRGUI_API FeatureGUI : public RollupWidget +class SDRGUI_API FeatureGUI : public QMdiSubWindow { Q_OBJECT public: - FeatureGUI(QWidget *parent = nullptr) : - RollupWidget(parent) - { } - virtual ~FeatureGUI() { } + enum ContextMenuType + { + ContextMenuNone, + ContextMenuChannelSettings, + ContextMenuStreamSettings + }; + + FeatureGUI(QWidget *parent = nullptr); + virtual ~FeatureGUI(); virtual void destroy() = 0; virtual void resetToDefaults() = 0; @@ -40,11 +52,57 @@ public: virtual MessageQueue* getInputMessageQueue() = 0; + RollupContents *getRollupContents() { return &m_rollupContents; } + void setTitleColor(const QColor&) {} // not implemented for a feature + void setTitle(const QString& title); + void setIndex(int index); + void setWorkspaceIndex(int index) { m_workspaceIndex = index; } + int getWorkspaceIndex() const { return m_workspaceIndex; } + protected: void closeEvent(QCloseEvent *event); + void mousePressEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event); + void resetContextMenuType() { m_contextMenuType = ContextMenuNone; } + + int m_featureIndex; + int m_workspaceIndex; + QString m_helpURL; + RollupContents m_rollupContents; + ContextMenuType m_contextMenuType; + +protected slots: + void shrinkWindow(); + +private: + bool isOnMovingPad(); + + QLabel *m_indexLabel; + QPushButton *m_settingsButton; + QLabel *m_titleLabel; + QPushButton *m_helpButton; + QPushButton *m_moveButton; + QPushButton *m_shrinkButton; + QPushButton *m_closeButton; + QLabel *m_statusLabel; + QVBoxLayout *m_layouts; + QHBoxLayout *m_topLayout; + QHBoxLayout *m_centerLayout; + QHBoxLayout *m_bottomLayout; + QSizeGrip *m_sizeGripTopRight; + QSizeGrip *m_sizeGripBottomRight; + bool m_drag; + QPoint m_DragPosition; + +private slots: + void activateSettingsDialog(); + void showHelp(); + void openMoveToWorkspaceDialog(); signals: void closing(); + void moveToWorkspace(int workspaceIndex); + void forceShrink(); }; #endif // SDRGUI_FEATURE_FEATUREGUI_H_ diff --git a/sdrgui/feature/featureuiset.cpp b/sdrgui/feature/featureuiset.cpp index c86e5fa08..621d811c1 100644 --- a/sdrgui/feature/featureuiset.cpp +++ b/sdrgui/feature/featureuiset.cpp @@ -15,7 +15,7 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "gui/featurewindow.h" +#include "gui/workspace.h" #include "plugin/pluginapi.h" #include "settings/featuresetpreset.h" #include "feature/featureutils.h" @@ -27,7 +27,6 @@ FeatureUISet::FeatureUISet(int tabIndex, FeatureSet *featureSet) { - m_featureWindow = new FeatureWindow; m_featureTabIndex = tabIndex; m_featureSet = featureSet; } @@ -35,12 +34,11 @@ FeatureUISet::FeatureUISet(int tabIndex, FeatureSet *featureSet) FeatureUISet::~FeatureUISet() { freeFeatures(); - delete m_featureWindow; } -void FeatureUISet::addRollupWidget(QWidget *widget) +void FeatureUISet::addRollupWidget(QWidget *) // TODO: remove { - m_featureWindow->addRollupWidget(widget); + // m_featureWindow->addRollupWidget(widget); } void FeatureUISet::registerFeatureInstance(FeatureGUI* featureGUI, Feature *feature) @@ -114,7 +112,12 @@ Feature *FeatureUISet::getFeatureAt(int featureIndex) } } -void FeatureUISet::loadFeatureSetSettings(const FeatureSetPreset *preset, PluginAPI *pluginAPI, WebAPIAdapterInterface *apiAdapter) +void FeatureUISet::loadFeatureSetSettings( + const FeatureSetPreset *preset, + PluginAPI *pluginAPI, + WebAPIAdapterInterface *apiAdapter, + Workspace *workspace +) { qDebug("FeatureUISet::loadFeatureSetSettings: Loading preset [%s | %s]", qPrintable(preset->getGroup()), @@ -160,6 +163,9 @@ void FeatureUISet::loadFeatureSetSettings(const FeatureSetPreset *preset, Plugin featureGUI = (*featureRegistrations)[i].m_plugin->createFeatureGUI(this, feature); registerFeatureInstance(featureGUI, feature); + featureGUI->setIndex(feature->getIndexInFeatureSet()); + featureGUI->setWorkspaceIndex(workspace->getIndex()); + workspace->addToMdiArea((QMdiSubWindow*) featureGUI); break; } } diff --git a/sdrgui/feature/featureuiset.h b/sdrgui/feature/featureuiset.h index af9aa9c5c..b82ff1e82 100644 --- a/sdrgui/feature/featureuiset.h +++ b/sdrgui/feature/featureuiset.h @@ -25,13 +25,13 @@ #include "export.h" class QWidget; -class FeatureWindow; class FeatureGUI; class PluginAPI; class FeatureSet; class Feature; class FeatureSetPreset; class WebAPIAdapterInterface; +class Workspace; class SDRGUI_API FeatureUISet : public QObject { @@ -46,11 +46,14 @@ public: void deleteFeature(int featureIndex); const Feature *getFeatureAt(int featureIndex) const; Feature *getFeatureAt(int featureIndex); - void loadFeatureSetSettings(const FeatureSetPreset* preset, PluginAPI *pluginAPI, WebAPIAdapterInterface *apiAdapter); + void loadFeatureSetSettings( + const FeatureSetPreset* preset, + PluginAPI *pluginAPI, + WebAPIAdapterInterface *apiAdapter, + Workspace *workspace + ); void saveFeatureSetSettings(FeatureSetPreset* preset); - FeatureWindow *m_featureWindow; - private: struct FeatureInstanceRegistration { diff --git a/sdrgui/gui/basicfeaturesettingsdialog.cpp b/sdrgui/gui/basicfeaturesettingsdialog.cpp index f90a4ddcd..f7695af78 100644 --- a/sdrgui/gui/basicfeaturesettingsdialog.cpp +++ b/sdrgui/gui/basicfeaturesettingsdialog.cpp @@ -10,8 +10,6 @@ BasicFeatureSettingsDialog::BasicFeatureSettingsDialog(QWidget *parent) : { ui->setupUi(this); ui->title->setText(m_title); - m_color =m_color; - paintColor(); } BasicFeatureSettingsDialog::~BasicFeatureSettingsDialog() @@ -27,35 +25,6 @@ void BasicFeatureSettingsDialog::setTitle(const QString& title) ui->title->blockSignals(false); } -void BasicFeatureSettingsDialog::setColor(const QColor& color) -{ - m_color = color; - paintColor(); -} - -void BasicFeatureSettingsDialog::paintColor() -{ - QPixmap pm(24, 24); - pm.fill(m_color); - ui->colorBtn->setIcon(pm); - ui->colorText->setText(tr("#%1%2%3") - .arg(m_color.red(), 2, 16, QChar('0')) - .arg(m_color.green(), 2, 16, QChar('0')) - .arg(m_color.blue(), 2, 16, QChar('0'))); -} - -void BasicFeatureSettingsDialog::on_colorBtn_clicked() -{ - QColor c = m_color; - c = QColorDialog::getColor(c, this, tr("Select Color for Channel"), QColorDialog::DontUseNativeDialog); - - if (c.isValid()) - { - m_color = c; - paintColor(); - } -} - void BasicFeatureSettingsDialog::on_title_editingFinished() { m_title = ui->title->text(); diff --git a/sdrgui/gui/basicfeaturesettingsdialog.h b/sdrgui/gui/basicfeaturesettingsdialog.h index 629cdf6f5..4891212e0 100644 --- a/sdrgui/gui/basicfeaturesettingsdialog.h +++ b/sdrgui/gui/basicfeaturesettingsdialog.h @@ -34,9 +34,7 @@ public: explicit BasicFeatureSettingsDialog(QWidget *parent = nullptr); ~BasicFeatureSettingsDialog(); void setTitle(const QString& title); - void setColor(const QColor& color); const QString& getTitle() const { return m_title; } - const QColor& getColor() const { return m_color; } bool useReverseAPI() const { return m_useReverseAPI; } const QString& getReverseAPIAddress() const { return m_reverseAPIAddress; } uint16_t getReverseAPIPort() const { return m_reverseAPIPort; } @@ -50,7 +48,6 @@ public: bool hasChanged() const { return m_hasChanged; } private slots: - void on_colorBtn_clicked(); void on_title_editingFinished(); void on_reverseAPI_toggled(bool checked); void on_reverseAPIAddress_editingFinished(); @@ -61,7 +58,6 @@ private slots: private: Ui::BasicFeatureSettingsDialog *ui; - QColor m_color; QString m_title; bool m_useReverseAPI; QString m_reverseAPIAddress; @@ -69,8 +65,6 @@ private: uint16_t m_reverseAPIFeatureSetIndex; uint16_t m_reverseAPIFeatureIndex; bool m_hasChanged; - - void paintColor(); }; #endif // INCLUDE_SDRGUI_BASICFEATURESETTINGSDIALOG_H diff --git a/sdrgui/gui/basicfeaturesettingsdialog.ui b/sdrgui/gui/basicfeaturesettingsdialog.ui index 9c9aa2442..0e72cd7fc 100644 --- a/sdrgui/gui/basicfeaturesettingsdialog.ui +++ b/sdrgui/gui/basicfeaturesettingsdialog.ui @@ -6,10 +6,16 @@ 0 0 - 456 - 158 + 439 + 118 + + + 0 + 0 + + Liberation Sans @@ -44,53 +50,6 @@ - - - - - - - 0 - 0 - - - - Color - - - - - - - Channel marker color - - - - - - - - - - #ff0000 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - diff --git a/sdrgui/gui/featurepresetsdialog.cpp b/sdrgui/gui/featurepresetsdialog.cpp index aaf188d9c..9d842ac07 100644 --- a/sdrgui/gui/featurepresetsdialog.cpp +++ b/sdrgui/gui/featurepresetsdialog.cpp @@ -375,7 +375,7 @@ void FeaturePresetsDialog::loadPresetSettings(const FeatureSetPreset* preset) qPrintable(preset->getGroup()), qPrintable(preset->getDescription())); - m_featureUISet->loadFeatureSetSettings(preset, m_pluginAPI, m_apiAdapter); + m_featureUISet->loadFeatureSetSettings(preset, m_pluginAPI, m_apiAdapter, m_workspace); } void FeaturePresetsDialog::sortFeatureSetPresets() diff --git a/sdrgui/gui/featurepresetsdialog.h b/sdrgui/gui/featurepresetsdialog.h index 49f3d7c2c..7785be0f2 100644 --- a/sdrgui/gui/featurepresetsdialog.h +++ b/sdrgui/gui/featurepresetsdialog.h @@ -29,6 +29,7 @@ class FeatureSetPreset; class FeatureUISet; class WebAPIAdapterInterface; class PluginAPI; +class Workspace; namespace Ui { class FeaturePresetsDialog; @@ -43,6 +44,7 @@ public: void setFeatureUISet(FeatureUISet *featureUISet) { m_featureUISet = featureUISet; } void setPluginAPI(PluginAPI *pluginAPI) { m_pluginAPI = pluginAPI; } void setWebAPIAdapter(WebAPIAdapterInterface *apiAdapter) { m_apiAdapter = apiAdapter; } + void setWorkspace(Workspace *workspace) { m_workspace = workspace; } void populateTree(); private: @@ -56,6 +58,7 @@ private: FeatureUISet *m_featureUISet; PluginAPI *m_pluginAPI; WebAPIAdapterInterface *m_apiAdapter; + Workspace *m_workspace; QTreeWidgetItem* addPresetToTree(const FeatureSetPreset* preset); void updatePresetControls(); diff --git a/sdrgui/gui/rollupcontents.cpp b/sdrgui/gui/rollupcontents.cpp new file mode 100644 index 000000000..d8077c96c --- /dev/null +++ b/sdrgui/gui/rollupcontents.cpp @@ -0,0 +1,601 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +#include "gui/rollupcontents.h" +#include "settings/rollupstate.h" +#include "ui_glspectrumgui.h" + +RollupContents::RollupContents(QWidget* parent) : + QWidget(parent), + m_highlighted(false), + m_streamIndicator("S"), + // m_channelWidget(true), + m_newHeight(0) +{ + setMinimumSize(250, 150); + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + setBackgroundRole(QPalette::Window); + + setAutoFillBackground(false); + setAttribute(Qt::WA_OpaquePaintEvent, true); +} + +// QByteArray RollupWidget::saveState(int version) const +// { +// QByteArray state; +// QDataStream stream(&state, QIODevice::WriteOnly); +// int count = 0; + +// for (int i = 0; i < children().count(); ++i) +// { +// QWidget* r = qobject_cast(children()[i]); + +// if (r) { +// count++; +// } +// } + +// stream << VersionMarker; +// stream << version; +// stream << count; + +// for (int i = 0; i < children().count(); ++i) +// { +// QWidget* r = qobject_cast(children()[i]); + +// if (r) +// { +// stream << r->objectName(); + +// if (r->isHidden()) { +// stream << (int) 0; +// } else { +// stream << (int) 1; +// } +// } +// } + +// return state; +// } + +void RollupContents::saveState(RollupState &state) const +{ + QList& childrenStates = state.getChildren(); + childrenStates.clear(); + + for (const auto &child : children()) + { + QWidget* r = qobject_cast(child); + + if (r && isRollupChild(r)) { + childrenStates.push_back({r->objectName(), r->isHidden()}); + } + } +} + +// bool RollupWidget::restoreState(const QByteArray& state, int version) +// { +// if (state.isEmpty()) { +// return false; +// } + +// QByteArray sd = state; +// QDataStream stream(&sd, QIODevice::ReadOnly); +// int marker, v; +// stream >> marker; +// stream >> v; + +// if ((stream.status() != QDataStream::Ok) || (marker != VersionMarker) || (v != version)) { +// return false; +// } + +// int count; +// stream >> count; + +// if (stream.status() != QDataStream::Ok) { +// return false; +// } + +// for (int i = 0; i < count; ++i) +// { +// QString name; +// int visible; + +// stream >> name; +// stream >> visible; + +// if (stream.status() != QDataStream::Ok) { +// return false; +// } + +// for (int j = 0; j < children().count(); ++j) +// { +// QWidget* r = qobject_cast(children()[j]); + +// if (r) +// { +// if (r->objectName() == name) +// { +// if (visible) { +// r->show(); +// } else { +// r->hide(); +// } + +// break; +// } +// } +// } +// } + +// return true; +// } + +void RollupContents::restoreState(const RollupState& state) +{ + const QList& childrenStates = state.getChildren(); + + for (const auto &object : children()) + { + QWidget* r = qobject_cast(object); + + if (r && isRollupChild(r)) + { + for (const auto &childState : childrenStates) + { + if (childState.m_objectName.compare(r->objectName()) == 0) + { + if (childState.m_isHidden) { + r->hide(); + } else { + r->show(); + } + + break; + } + } + } + } +} + +void RollupContents::setHighlighted(bool highlighted) +{ + if (m_highlighted != highlighted) + { + m_highlighted = highlighted; + update(); + } +} + +int RollupContents::arrangeRollups() +{ + QFontMetrics fm(font()); + int pos; + + // First calculate minimum height needed, to determine how much extra space + // we have that can be split between expanding widgets + pos = 2; // fm.height() + 4; + int expandingChildren = 0; + for (int i = 0; i < children().count(); ++i) + { + QWidget* r = qobject_cast(children()[i]); + + if ((r != nullptr) && isRollupChild(r)) + { + pos += fm.height() + 2; + if (!r->isHidden()) + { + if (r->sizePolicy().verticalPolicy() & QSizePolicy::ExpandFlag) { + expandingChildren++; + } + int h = 0; + if (r->hasHeightForWidth()) { + h = r->heightForWidth(width() - 4); + } else { + h = r->minimumSizeHint().height(); + } + pos += h + 5; + } + } + } + + setMinimumHeight(pos); + + // Split extra space equally between widgets + // If there's a remainder, we give it to the first widget + // In the future, we should probably respect 'Vertical Stretch' + int extraSpace; + int firstExtra; + if ((expandingChildren > 0) && (m_newHeight > pos)) + { + int totalExtra = m_newHeight - pos; + extraSpace = totalExtra / expandingChildren; + firstExtra = totalExtra - (extraSpace * expandingChildren); + } + else + { + extraSpace = 0; + firstExtra = 0; + } + + // Now reposition and resize child widgets + pos = 2; // fm.height() + 4; + for (int i = 0; i < children().count(); ++i) + { + QWidget* r = qobject_cast(children()[i]); + + if ((r != nullptr) && isRollupChild(r)) + { + pos += fm.height() + 2; + + if (!r->isHidden()) + { + r->move(2, pos + 3); + + int h = 0; + if (r->hasHeightForWidth()) { + h = r->heightForWidth(width() - 4); + } else { + h = r->minimumSizeHint().height(); + } + if (r->sizePolicy().verticalPolicy() & QSizePolicy::ExpandFlag) + { + h += extraSpace; + h += firstExtra; + firstExtra = 0; + } + + r->resize(width() - 4, h); + pos += r->height() + 5; + } + } + } + + if (expandingChildren == 0) { + setMaximumHeight(pos); + } else { + setMaximumHeight(16777215); + } + updateGeometry(); + return pos; +} + +void RollupContents::paintEvent(QPaintEvent*) +{ + QPainter p(this); + QColor frame = palette().highlight().color(); + + // Eigenbau + QFontMetrics fm(font()); + + p.setRenderHint(QPainter::Antialiasing, true); + + // Ecken (corners) + p.setPen(Qt::NoPen); + p.setBrush(palette().base()); + p.drawRect(0, 0, 5, 5); + p.drawRect(width() - 5, 0, 5, 5); + p.drawRect(0, height() - 5, 5, 5); + p.drawRect(width() - 5, height() - 5, 5, 5); + + // Rahmen (frame) + p.setPen(m_highlighted ? Qt::white : frame); + p.setBrush(palette().window()); + QRectF r(rect()); + r.adjust(0.5, 0.5, -0.5, -0.5); + p.drawRoundedRect(r, 3.0, 3.0, Qt::AbsoluteSize); + + // // Titel-Hintergrund (Title background) + // p.setPen(Qt::NoPen); + // p.setBrush(m_titleColor); + // QPainterPath path; + // path.moveTo(1.5, fm.height() + 2.5); + // path.lineTo(width() - 1.5, fm.height() + 2.5); + // path.lineTo(width() - 1.5, 3.5); + // path.arcTo(QRectF(width() - 3.5, 0, 2.5, 2.5), 270, -90); + // path.lineTo(3.5, 1.5); + // path.arcTo(QRectF(1.5, 2.5, 2.5, 2.5), 90, 90); + // p.drawPath(path); + + // // Titel-Abschlusslinie (Title closing line) + // p.setPen(frame); + // p.drawLine(QPointF(0.5, 2 + fm.height() + 1.5), QPointF(width() - 1.5, 2 + fm.height() + 1.5)); + + // // Aktiv-Button links + // p.setPen(QPen(palette().windowText().color(), 1.0)); + // p.setBrush(palette().light()); + // p.drawRoundedRect(QRectF(3.5, 3.5, fm.ascent(), fm.ascent()), 2.0, 2.0, Qt::AbsoluteSize); + // p.setPen(QPen(Qt::white, 1.0)); + // p.drawText(QRectF(3.5, 2.5, fm.ascent(), fm.ascent()), Qt::AlignCenter, "c"); + + // if (m_channelWidget) + // { + // // Stromkanal-Button links (Current channel) + // p.setPen(QPen(palette().windowText().color(), 1.0)); + // p.setBrush(palette().light()); + // p.drawRoundedRect(QRectF(5.5 + fm.ascent(), 2.5, fm.ascent() + 2.0, fm.ascent() + 2.0), 2.0, 2.0, Qt::AbsoluteSize); + // p.setPen(QPen(Qt::white, 1.0)); + // p.drawText(QRectF(5.5 + fm.ascent(), 2.5, fm.ascent() + 2.0, fm.ascent() + 2.0), Qt::AlignCenter, m_streamIndicator); + // } + + // // Help button + // if (!m_helpURL.isEmpty()) + // { + // p.setRenderHint(QPainter::Antialiasing, true); + // p.setPen(QPen(palette().windowText().color(), 1.0)); + // p.setBrush(palette().light()); + // r = QRectF(width() - 2*(3.5 + fm.ascent()), 3.5, fm.ascent(), fm.ascent()); + // p.drawRoundedRect(r, 2.0, 2.0, Qt::AbsoluteSize); + // p.drawText(QRectF(width() - 2*(3.5 + fm.ascent()), 5, fm.ascent(), fm.ascent() - 2), Qt::AlignCenter, "?"); + // } + + // //p.drawLine(r.topLeft() + QPointF(1, 1), r.bottomRight() + QPointF(-1, -1)); + // //p.drawLine(r.bottomLeft() + QPointF(1, -1), r.topRight() + QPointF(-1, 1)); + + // // Schließen-Button rechts (Close button on the right) + // p.setRenderHint(QPainter::Antialiasing, true); + // p.setPen(QPen(palette().windowText().color(), 1.0)); + // p.setBrush(palette().light()); + // r = QRectF(width() - 3.5 - fm.ascent(), 3.5, fm.ascent(), fm.ascent()); + // p.drawRoundedRect(r, 2.0, 2.0, Qt::AbsoluteSize); + // p.setPen(QPen(palette().windowText().color(), 1.5)); + // p.drawLine(r.topLeft() + QPointF(1, 1), r.bottomRight() + QPointF(-1, -1)); + // p.drawLine(r.bottomLeft() + QPointF(1, -1), r.topRight() + QPointF(-1, 1)); + + // // Titel + // //p.setPen(palette().highlightedText().color()); + // p.setPen(m_titleTextColor); + // p.drawText(QRect(2 + 2*fm.height() + 2, 2, width() - 6 - 3*fm.height(), fm.height()), + // fm.elidedText(windowTitle(), Qt::ElideMiddle, width() - 6 - 3*fm.height(), 0)); + + // Rollups + int pos = 2; // fm.height() + 4; + + const QObjectList& c = children(); + QObjectList::ConstIterator w = c.begin(); + QObjectList::ConstIterator n = c.begin(); + + for (n = c.begin(); n != c.end(); ++n) + { + if (qobject_cast(*n) != nullptr) { + break; + } + } + + for (w = n; w != c.end(); w = n) + { + if (n != c.end()) { + ++n; + } + + for (; n != c.end(); ++n) + { + if (qobject_cast(*n) != nullptr) { + break; + } + } + + pos += paintRollup(qobject_cast(*w), pos, &p, n == c.end(), frame); + } +} + +int RollupContents::paintRollup(QWidget* rollup, int pos, QPainter* p, bool last, const QColor& frame) +{ + QFontMetrics fm(font()); + int height = 1; + + // Titel-Abschlusslinie + if (!rollup->isHidden()) + { + p->setPen(palette().dark().color()); + p->drawLine(QPointF(1.5, pos + fm.height() + 1.5), QPointF(width() - 1.5, pos + fm.height() + 1.5)); + p->setPen(palette().light().color()); + p->drawLine(QPointF(1.5, pos + fm.height() + 2.5), QPointF(width() - 1.5, pos + fm.height() + 2.5)); + height += 2; + } + else + { + if (!last) + { + p->setPen(frame); + p->drawLine(QPointF(1.5, pos + fm.height() + 1.5), QPointF(width() - 1.5, pos + fm.height() + 1.5)); + height++; + } + } + + // Titel + p->setPen(palette().windowText().color()); + p->drawText(QRect(2 + fm.height(), pos, width() - 4 - fm.height(), fm.height()), + fm.elidedText(rollup->windowTitle(), Qt::ElideMiddle, width() - 4 - fm.height(), 0)); + height += fm.height(); + + // Ausklapp-Icon + p->setPen(palette().windowText().color()); + p->setBrush(palette().windowText()); + + if (!rollup->isHidden()) + { + QPolygonF a; + a.append(QPointF(3.5, pos + 2)); + a.append(QPointF(3.5 + fm.ascent(), pos + 2)); + a.append(QPointF(3.5 + fm.ascent() / 2.0, pos + fm.height() - 2)); + p->drawPolygon(a); + } + else + { + QPolygonF a; + a.append(QPointF(3.5, pos + 2)); + a.append(QPointF(3.5, pos + fm.height() - 2)); + a.append(QPointF(3.5 + fm.ascent(), pos + fm.height() / 2)); + p->drawPolygon(a); + } + + // Inhalt + if (!rollup->isHidden() && (!last)) + { + // Rollup-Abschlusslinie + p->setPen(frame); + p->drawLine(QPointF(1.5, pos + fm.height() + rollup->height() + 6.5), + QPointF(width() - 1.5, pos + fm.height() + rollup->height() + 6.5)); + height += rollup->height() + 4; + } + + return height; +} + +void RollupContents::resizeEvent(QResizeEvent* size) +{ + m_newHeight = size->size().height(); + arrangeRollups(); + QWidget::resizeEvent(size); +} + +void RollupContents::mousePressEvent(QMouseEvent* event) +{ + QFontMetrics fm(font()); + + // // menu box left + // if (QRectF(3.5, 3.5, fm.ascent(), fm.ascent()).contains(event->pos())) + // { + // m_contextMenuType = ContextMenuChannelSettings; + // emit customContextMenuRequested(event->globalPos()); + // return; + // } + + // if (m_channelWidget) + // { + // // Stream channel menu left + // if (QRectF(5.5 + fm.ascent(), 2.5, fm.ascent() + 2.0, fm.ascent() + 2.0).contains(event->pos())) + // { + // m_contextMenuType = ContextMenuStreamSettings; + // emit customContextMenuRequested(event->globalPos()); + // return; + // } + // } + + // // help button + // if(!m_helpURL.isEmpty() && QRectF(width() - 2*(3.5 + fm.ascent()), 3.5, fm.ascent(), fm.ascent()).contains(event->pos())) + // { + // QString url; + // if (m_helpURL.startsWith("http")) { + // url = m_helpURL; + // } else { + // url = QString("https://github.com/f4exb/sdrangel/blob/master/%1").arg(m_helpURL); // Something like "plugins/channelrx/chanalyzer/readme.md" + // } + // QDesktopServices::openUrl(QUrl(url)); + // return; + // } + + // // close button right + // if(QRectF(width() - 3.5 - fm.ascent(), 3.5, fm.ascent(), fm.ascent()).contains(event->pos())) { + // close(); + // return; + // } + + // check if we need to change a rollup widget + int pos = 2; // fm.height() + 4; + + for (int i = 0; i < children().count(); ++i) + { + QWidget* r = qobject_cast(children()[i]); + + if (r) + { + if ((event->y() >= pos) && (event->y() < (pos + fm.height() + 3))) + { + if (r->isHidden()) + { + r->show(); + //emit widgetRolled(r, true); + } + else + { + r->hide(); + //emit widgetRolled(r, false); + } + + arrangeRollups(); + repaint(); + return; + } + else + { + pos += fm.height() + 2; + + if (!r->isHidden()) { + pos += r->height() + 5; + } + } + } + } +} + +bool RollupContents::event(QEvent* event) +{ + if (event->type() == QEvent::ChildAdded) + { + ((QChildEvent*)event)->child()->installEventFilter(this); + arrangeRollups(); + } + else if (event->type() == QEvent::ChildRemoved) + { + ((QChildEvent*)event)->child()->removeEventFilter(this); + arrangeRollups(); + } + + return QWidget::event(event); +} + +bool RollupContents::eventFilter(QObject* object, QEvent* event) +{ + if (event->type() == QEvent::Show) + { + if (children().contains(object)) + { + arrangeRollups(); + emit widgetRolled(qobject_cast(object), true); + } + } + else if (event->type() == QEvent::Hide) + { + if (children().contains(object)) + { + arrangeRollups(); + emit widgetRolled(qobject_cast(object), false); + } + } + else if (event->type() == QEvent::WindowTitleChange) + { + if (children().contains(object)) { + repaint(); + } + } + + return QWidget::eventFilter(object, event); +} + +bool RollupContents::isRollupChild(QWidget *childWidget) +{ + return (qobject_cast(childWidget) == nullptr); // exclude Dialogs from rollups +} diff --git a/sdrgui/gui/rollupcontents.h b/sdrgui/gui/rollupcontents.h new file mode 100644 index 000000000..e4eeb3ca6 --- /dev/null +++ b/sdrgui/gui/rollupcontents.h @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 Edouard Griffiths, F4EXB // +// // +// API for features // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_ROLLUPCONTENTS_H +#define INCLUDE_ROLLUPCONTENTS_H + +#include +#include "export.h" + +class RollupState; + +class SDRGUI_API RollupContents : public QWidget { + Q_OBJECT + +public: + RollupContents(QWidget* parent = nullptr); + void setHighlighted(bool highlighted); + // void setChannelWidget(bool channelWidget) { m_channelWidget = channelWidget; } + // QByteArray saveState(int version = 0) const; + void saveState(RollupState& state) const; + // bool restoreState(const QByteArray& state, int version = 0); + void restoreState(const RollupState& state); + int arrangeRollups(); + +signals: + void widgetRolled(QWidget* widget, bool rollDown); + +protected: + enum { + VersionMarker = 0xff + }; + + bool m_highlighted; + QString m_streamIndicator; + QString m_helpURL; + + void paintEvent(QPaintEvent*); + int paintRollup(QWidget* rollup, int pos, QPainter* p, bool last, const QColor& frame); + + void resizeEvent(QResizeEvent* size); + void mousePressEvent(QMouseEvent* event); + + bool event(QEvent* event); + bool eventFilter(QObject* object, QEvent* event); + +private: + static bool isRollupChild(QWidget *childWidget); //!< chidl is part of rollups (ex: not a dialog) + // bool m_channelWidget; + int m_newHeight; +}; + +#endif // INCLUDE_ROLLUPCONTENTS_H diff --git a/sdrgui/gui/workspace.cpp b/sdrgui/gui/workspace.cpp new file mode 100644 index 000000000..3509a6810 --- /dev/null +++ b/sdrgui/gui/workspace.cpp @@ -0,0 +1,271 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 F4EXB // +// written by Edouard Griffiths // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include + +#include "workspace.h" + +Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) : + QDockWidget(parent, flags), + m_index(index), + m_featureAddDialog(this) +{ + m_mdi = new QMdiArea(this); + m_mdi->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_mdi->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + setWidget(m_mdi); + + setWindowTitle(tr("W%1").arg(m_index)); + + m_titleBar = new QWidget(); + m_titleBarLayout = new QHBoxLayout(); + m_titleBarLayout->setMargin(0); + m_titleBar->setLayout(m_titleBarLayout); + + m_titleLabel = new QLabel(); + m_titleLabel->setFixedSize(32, 16); + m_titleLabel->setStyleSheet("QLabel { background-color: rgb(128, 128, 128); qproperty-alignment: AlignCenter; }"); + m_titleLabel->setText(windowTitle()); + + m_addRxDeviceButton = new QPushButton(); + QIcon addRxIcon(":/rx.png"); + m_addRxDeviceButton->setIcon(addRxIcon); + m_addRxDeviceButton->setToolTip("Add Rx device"); + m_addRxDeviceButton->setFixedSize(20, 20); + + m_addTxDeviceButton = new QPushButton(); + QIcon addTxIcon(":/tx.png"); + m_addTxDeviceButton->setIcon(addTxIcon); + m_addTxDeviceButton->setToolTip("Add Tx device"); + m_addTxDeviceButton->setFixedSize(20, 20); + + m_addMIMODeviceButton = new QPushButton(); + QIcon addMIMOIcon(":/mimo.png"); + m_addMIMODeviceButton->setIcon(addMIMOIcon); + m_addMIMODeviceButton->setToolTip("Add MIMO device"); + m_addMIMODeviceButton->setFixedSize(20, 20); + + m_vline1 = new QFrame(); + m_vline1->setFrameShape(QFrame::VLine); + m_vline1->setFrameShadow(QFrame::Sunken); + + m_addFeatureButton = new QPushButton(); + QIcon addFeatureIcon(":/tool.png"); + m_addFeatureButton->setIcon(addFeatureIcon); + m_addFeatureButton->setToolTip("Add features"); + m_addFeatureButton->setFixedSize(20, 20); + + m_featurePresetsButton = new QPushButton(); + QIcon presetsIcon(":/star.png"); + m_featurePresetsButton->setIcon(presetsIcon); + m_featurePresetsButton->setToolTip("Feature presets"); + m_featurePresetsButton->setFixedSize(20, 20); + + m_vline2 = new QFrame(); + m_vline2->setFrameShape(QFrame::VLine); + m_vline2->setFrameShadow(QFrame::Sunken); + + m_cascadeSubWindows = new QPushButton(); + QIcon cascadeSubWindowsIcon(":/cascade.png"); + m_cascadeSubWindows->setIcon(cascadeSubWindowsIcon); + m_cascadeSubWindows->setToolTip("Cascade sub windows"); + m_cascadeSubWindows->setFixedSize(20, 20); + + m_tileSubWindows = new QPushButton(); + QIcon tileSubWindowsIcon(":/tiles.png"); + m_tileSubWindows->setIcon(tileSubWindowsIcon); + m_tileSubWindows->setToolTip("Tile sub windows"); + m_tileSubWindows->setFixedSize(20, 20); + + m_normalButton = new QPushButton(); + QIcon normalIcon(":/dock.png"); + m_normalButton->setIcon(normalIcon); + m_normalButton->setToolTip("Dock/undock"); + m_normalButton->setFixedSize(20, 20); + + m_closeButton = new QPushButton(); + QIcon closeIcon(":/cross.png"); + m_closeButton->setIcon(closeIcon); + m_closeButton->setToolTip("Hide workspace"); + m_closeButton->setFixedSize(20, 20); + + m_titleBarLayout->addWidget(m_titleLabel); + m_titleBarLayout->addWidget(m_addRxDeviceButton); + m_titleBarLayout->addWidget(m_addTxDeviceButton); + m_titleBarLayout->addWidget(m_addMIMODeviceButton); + m_titleBarLayout->addWidget(m_vline1); + m_titleBarLayout->addWidget(m_addFeatureButton); + m_titleBarLayout->addWidget(m_featurePresetsButton); + m_titleBarLayout->addWidget(m_vline2); + m_titleBarLayout->addWidget(m_cascadeSubWindows); + m_titleBarLayout->addWidget(m_tileSubWindows); + m_titleBarLayout->addStretch(1); + m_titleBarLayout->addWidget(m_normalButton); + m_titleBarLayout->addWidget(m_closeButton); + setTitleBarWidget(m_titleBar); + + QObject::connect( + m_addRxDeviceButton, + &QPushButton::clicked, + this, + &Workspace::addRxDevice + ); + + QObject::connect( + m_addTxDeviceButton, + &QPushButton::clicked, + this, + &Workspace::addTxDevice + ); + + QObject::connect( + m_addMIMODeviceButton, + &QPushButton::clicked, + this, + &Workspace::addMIMODevice + ); + + QObject::connect( + m_addFeatureButton, + &QPushButton::clicked, + this, + &Workspace::addFeatureDialog + ); + + QObject::connect( + m_featurePresetsButton, + &QPushButton::clicked, + this, + &Workspace::featurePresetsDialog + ); + + QObject::connect( + m_cascadeSubWindows, + &QPushButton::clicked, + this, + &Workspace::cascadeSubWindows + ); + + QObject::connect( + m_tileSubWindows, + &QPushButton::clicked, + this, + &Workspace::tileSubWindows + ); + + QObject::connect( + m_normalButton, + &QPushButton::clicked, + this, + &Workspace::toggleFloating + ); + + connect(m_closeButton, SIGNAL(clicked()), this, SLOT(hide())); + + QObject::connect( + &m_featureAddDialog, + &FeatureAddDialog::addFeature, + this, + &Workspace::addFeatureEmitted + ); +} + +Workspace::~Workspace() +{ + delete m_closeButton; + delete m_normalButton; + delete m_tileSubWindows; + delete m_cascadeSubWindows; + delete m_vline2; + delete m_vline1; + delete m_addRxDeviceButton; + delete m_addTxDeviceButton; + delete m_addMIMODeviceButton; + delete m_addFeatureButton; + delete m_featurePresetsButton; + delete m_titleLabel; + delete m_titleBarLayout; + delete m_titleBar; + delete m_mdi; +} + +void Workspace::toggleFloating() +{ + setFloating(!isFloating()); +} + +void Workspace::addRxDevice() +{ + +} + +void Workspace::addTxDevice() +{ + +} + +void Workspace::addMIMODevice() +{ + +} + +void Workspace::addFeatureDialog() +{ + m_featureAddDialog.exec(); +} + +void Workspace::addFeatureEmitted(int featureIndex) +{ + if (featureIndex >= 0) { + emit addFeature(this, featureIndex); + } +} + +void Workspace::featurePresetsDialog() +{ + QPoint p = mapFromGlobal(QCursor::pos()); + emit featurePresetsDialogRequested(p, this); +} + +void Workspace::cascadeSubWindows() +{ + m_mdi->cascadeSubWindows(); +} + +void Workspace::tileSubWindows() +{ + m_mdi->tileSubWindows(); +} + +void Workspace::addToMdiArea(QMdiSubWindow *sub) +{ + sub->setParent(m_mdi); + m_mdi->addSubWindow(sub); + sub->show(); +} + +void Workspace::removeFromMdiArea(QMdiSubWindow *sub) +{ + m_mdi->removeSubWindow(sub); +} diff --git a/sdrgui/gui/workspace.h b/sdrgui/gui/workspace.h new file mode 100644 index 000000000..56b307fad --- /dev/null +++ b/sdrgui/gui/workspace.h @@ -0,0 +1,84 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 F4EXB // +// written by Edouard Griffiths // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRGUI_GUI_WORKSPACE_H_ +#define SDRGUI_GUI_WORKSPACE_H_ + +#include + +#include "export.h" +#include "featureadddialog.h" + +class QHBoxLayout; +class QLabel; +class QPushButton; +class QStringList; +class QMdiArea; +class QMdiSubWindow; +class QFrame; + +class SDRGUI_API Workspace : public QDockWidget +{ + Q_OBJECT +public: + Workspace(int index, QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags()); + ~Workspace(); + + int getIndex() const { return m_index; } + void resetAvailableFeatures() { m_featureAddDialog.resetFeatureNames(); } + void addAvailableFeatures(const QStringList& featureNames) { m_featureAddDialog.addFeatureNames(featureNames); } + void addToMdiArea(QMdiSubWindow *sub); + void removeFromMdiArea(QMdiSubWindow *sub); + +private: + int m_index; + QPushButton *m_addRxDeviceButton; + QPushButton *m_addTxDeviceButton; + QPushButton *m_addMIMODeviceButton; + QFrame *m_vline1; + QPushButton *m_addFeatureButton; + QPushButton *m_featurePresetsButton; + QFrame *m_vline2; + QPushButton *m_cascadeSubWindows; + QPushButton *m_tileSubWindows; + QWidget *m_titleBar; + QHBoxLayout *m_titleBarLayout; + QLabel *m_titleLabel; + QPushButton *m_normalButton; + QPushButton *m_closeButton; + FeatureAddDialog m_featureAddDialog; + QMdiArea *m_mdi; + +private slots: + void addRxDevice(); + void addTxDevice(); + void addMIMODevice(); + void addFeatureDialog(); + void featurePresetsDialog(); + void cascadeSubWindows(); + void tileSubWindows(); + void addFeatureEmitted(int featureIndex); + void toggleFloating(); + +signals: + void addFeature(Workspace*, int); + void featurePresetsDialogRequested(QPoint, Workspace*); +}; + + +#endif // SDRGUI_GUI_WORKSPACE_H_ diff --git a/sdrgui/gui/workspaceselectiondialog.cpp b/sdrgui/gui/workspaceselectiondialog.cpp new file mode 100644 index 000000000..ef0cff326 --- /dev/null +++ b/sdrgui/gui/workspaceselectiondialog.cpp @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 F4EXB // +// written by Edouard Griffiths // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "workspaceselectiondialog.h" +#include "ui_workspaceselectiondialog.h" + +WorkspaceSelectionDialog::WorkspaceSelectionDialog(int numberOfWorkspaces, QWidget *parent) : + QDialog(parent), + ui(new Ui::WorkspaceSelectionDialog), + m_numberOfWorkspaces(numberOfWorkspaces), + m_hasChanged(false) +{ + ui->setupUi(this); + + for (int i = 0; i < m_numberOfWorkspaces; i++) { + ui->workspaceList->addItem(tr("W:%1").arg(i)); + } +} + +WorkspaceSelectionDialog::~WorkspaceSelectionDialog() +{ + delete ui; +} + +void WorkspaceSelectionDialog::accept() +{ + m_selectedRow = ui->workspaceList->currentRow(); + m_hasChanged = true; + QDialog::accept(); +} diff --git a/sdrgui/gui/workspaceselectiondialog.h b/sdrgui/gui/workspaceselectiondialog.h new file mode 100644 index 000000000..6ac68bfbc --- /dev/null +++ b/sdrgui/gui/workspaceselectiondialog.h @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 F4EXB // +// written by Edouard Griffiths // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRGUI_GUI_WORKSPACESELECTIONDIALOG_H_ +#define SDRGUI_GUI_WORKSPACESELECTIONDIALOG_H_ + +#include + +#include "export.h" + +namespace Ui { + class WorkspaceSelectionDialog; +} + +class SDRGUI_API WorkspaceSelectionDialog : public QDialog +{ + Q_OBJECT +public: + explicit WorkspaceSelectionDialog(int numberOfWorkspaces, QWidget *parent = nullptr); + ~WorkspaceSelectionDialog(); + + bool hasChanged() const { return m_hasChanged; } + int getSelectedIndex() const { return m_selectedRow; } + +private: + Ui::WorkspaceSelectionDialog *ui; + int m_numberOfWorkspaces; + int m_selectedRow; + bool m_hasChanged; + +private slots: + void accept(); +}; + +#endif // SDRGUI_GUI_WORKSPACESELECTIONDIALOG_H_ diff --git a/sdrgui/gui/workspaceselectiondialog.ui b/sdrgui/gui/workspaceselectiondialog.ui new file mode 100644 index 000000000..56d37e4f6 --- /dev/null +++ b/sdrgui/gui/workspaceselectiondialog.ui @@ -0,0 +1,67 @@ + + + WorkspaceSelectionDialog + + + + 0 + 0 + 209 + 201 + + + + Workspace + + + true + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + WorkspaceSelectionDialog + accept() + + + 104 + 177 + + + 104 + 100 + + + + + buttonBox + rejected() + WorkspaceSelectionDialog + reject() + + + 104 + 177 + + + 104 + 100 + + + + + diff --git a/sdrgui/mainwindow.cpp b/sdrgui/mainwindow.cpp index 6190dffa2..595067bdd 100644 --- a/sdrgui/mainwindow.cpp +++ b/sdrgui/mainwindow.cpp @@ -31,6 +31,10 @@ #include #include +#include +#include +#include + #include "device/devicegui.h" #include "device/deviceapi.h" #include "device/deviceuiset.h" @@ -41,6 +45,7 @@ #include "feature/featureuiset.h" #include "feature/featureset.h" #include "feature/feature.h" +#include "feature/featuregui.h" #include "commands/commandkeyreceiver.h" #include "gui/indicator.h" #include "gui/presetitem.h" @@ -60,6 +65,8 @@ #include "gui/mypositiondialog.h" #include "gui/fftwisdomdialog.h" #include "gui/ambedevicesdialog.h" +#include "gui/workspace.h" +#include "gui/featurepresetsdialog.h" #include "dsp/dspengine.h" #include "dsp/spectrumvis.h" #include "dsp/dspcommands.h" @@ -82,7 +89,8 @@ #include
+ + + 2 + + + E&xit @@ -995,6 +1001,7 @@ channelDock commandsDock featureDock + workspaceDock @@ -1021,6 +1028,12 @@
gui/featuresdock.h
1
+ + Workspace + QDockWidget +
gui/workspace.h
+ 1 +
presetTree diff --git a/sdrgui/resources/cascade.png b/sdrgui/resources/cascade.png new file mode 100644 index 000000000..be5f32e4d Binary files /dev/null and b/sdrgui/resources/cascade.png differ diff --git a/sdrgui/resources/corner_botleft.png b/sdrgui/resources/corner_botleft.png new file mode 100644 index 000000000..eae1e73f1 Binary files /dev/null and b/sdrgui/resources/corner_botleft.png differ diff --git a/sdrgui/resources/corner_botright.png b/sdrgui/resources/corner_botright.png new file mode 100644 index 000000000..d2934d18e Binary files /dev/null and b/sdrgui/resources/corner_botright.png differ diff --git a/sdrgui/resources/corner_topleft.png b/sdrgui/resources/corner_topleft.png new file mode 100644 index 000000000..a924b2353 Binary files /dev/null and b/sdrgui/resources/corner_topleft.png differ diff --git a/sdrgui/resources/corner_topright.png b/sdrgui/resources/corner_topright.png new file mode 100644 index 000000000..8dec8d88c Binary files /dev/null and b/sdrgui/resources/corner_topright.png differ diff --git a/sdrgui/resources/cross.png b/sdrgui/resources/cross.png new file mode 100644 index 000000000..043ec1f2f Binary files /dev/null and b/sdrgui/resources/cross.png differ diff --git a/sdrgui/resources/dock.png b/sdrgui/resources/dock.png new file mode 100644 index 000000000..bf0030fef Binary files /dev/null and b/sdrgui/resources/dock.png differ diff --git a/sdrgui/resources/exit.png b/sdrgui/resources/exit.png new file mode 100644 index 000000000..439c31442 Binary files /dev/null and b/sdrgui/resources/exit.png differ diff --git a/sdrgui/resources/gear.png b/sdrgui/resources/gear.png new file mode 100644 index 000000000..e82c5afdc Binary files /dev/null and b/sdrgui/resources/gear.png differ diff --git a/sdrgui/resources/help.png b/sdrgui/resources/help.png new file mode 100644 index 000000000..be372f929 Binary files /dev/null and b/sdrgui/resources/help.png differ diff --git a/sdrgui/resources/mimo.png b/sdrgui/resources/mimo.png new file mode 100644 index 000000000..f44b7752c Binary files /dev/null and b/sdrgui/resources/mimo.png differ diff --git a/sdrgui/resources/res.qrc b/sdrgui/resources/res.qrc index 436229a08..73b00a400 100644 --- a/sdrgui/resources/res.qrc +++ b/sdrgui/resources/res.qrc @@ -113,6 +113,22 @@ zoomall.png zoomin.png zoomout.png + rx.png + tx.png + mimo.png + tool.png + gear.png + corner_topleft.png + corner_topright.png + corner_botleft.png + corner_botright.png + cross.png + cascade.png + tiles.png + dock.png + help.png + shrink.png + exit.png LiberationMono-Regular.ttf LiberationSans-Regular.ttf diff --git a/sdrgui/resources/rx.png b/sdrgui/resources/rx.png new file mode 100644 index 000000000..348aa693e Binary files /dev/null and b/sdrgui/resources/rx.png differ diff --git a/sdrgui/resources/shrink.png b/sdrgui/resources/shrink.png new file mode 100644 index 000000000..e849b14c8 Binary files /dev/null and b/sdrgui/resources/shrink.png differ diff --git a/sdrgui/resources/tiles.png b/sdrgui/resources/tiles.png new file mode 100644 index 000000000..625205090 Binary files /dev/null and b/sdrgui/resources/tiles.png differ diff --git a/sdrgui/resources/tool.png b/sdrgui/resources/tool.png new file mode 100644 index 000000000..4f0282b11 Binary files /dev/null and b/sdrgui/resources/tool.png differ diff --git a/sdrgui/resources/tx.png b/sdrgui/resources/tx.png new file mode 100644 index 000000000..0ad47ba2c Binary files /dev/null and b/sdrgui/resources/tx.png differ