diff --git a/doc/img/hide.xcf b/doc/img/hide.xcf new file mode 100644 index 000000000..022857dd4 Binary files /dev/null and b/doc/img/hide.xcf differ diff --git a/plugins/feature/afc/afcgui.h b/plugins/feature/afc/afcgui.h index 1b376f9a0..83c73a537 100644 --- a/plugins/feature/afc/afcgui.h +++ b/plugins/feature/afc/afcgui.h @@ -43,6 +43,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } private: Ui::AFCGUI* ui; diff --git a/plugins/feature/afc/afcsettings.cpp b/plugins/feature/afc/afcsettings.cpp index 7eec426c9..d8dc8eed5 100644 --- a/plugins/feature/afc/afcsettings.cpp +++ b/plugins/feature/afc/afcsettings.cpp @@ -44,6 +44,7 @@ void AFCSettings::resetToDefaults() m_reverseAPIPort = 8888; m_reverseAPIFeatureSetIndex = 0; m_reverseAPIFeatureIndex = 0; + m_workspaceIndex = 0; } QByteArray AFCSettings::serialize() const @@ -69,6 +70,9 @@ QByteArray AFCSettings::serialize() const s.writeBlob(15, m_rollupState->serialize()); } + s.writeS32(16, m_workspaceIndex); + s.writeBlob(17, m_geometryBytes); + return s.final(); } @@ -118,6 +122,9 @@ bool AFCSettings::deserialize(const QByteArray& data) m_rollupState->deserialize(bytetmp); } + d.readS32(16, &m_workspaceIndex, 0); + d.readBlob(17, &m_geometryBytes); + return true; } else diff --git a/plugins/feature/afc/afcsettings.h b/plugins/feature/afc/afcsettings.h index 115cdfebf..fb3d750a4 100644 --- a/plugins/feature/afc/afcsettings.h +++ b/plugins/feature/afc/afcsettings.h @@ -40,6 +40,8 @@ struct AFCSettings uint16_t m_reverseAPIFeatureSetIndex; uint16_t m_reverseAPIFeatureIndex; Serializable *m_rollupState; + int m_workspaceIndex; + QByteArray m_geometryBytes; AFCSettings(); void resetToDefaults(); diff --git a/plugins/feature/ais/aisgui.h b/plugins/feature/ais/aisgui.h index a1e43584a..7bc3651a6 100644 --- a/plugins/feature/ais/aisgui.h +++ b/plugins/feature/ais/aisgui.h @@ -57,6 +57,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } private: Ui::AISGUI* ui; diff --git a/plugins/feature/ais/aissettings.cpp b/plugins/feature/ais/aissettings.cpp index 7d902d105..bdc7145f9 100644 --- a/plugins/feature/ais/aissettings.cpp +++ b/plugins/feature/ais/aissettings.cpp @@ -47,6 +47,7 @@ void AISSettings::resetToDefaults() m_reverseAPIPort = 8888; m_reverseAPIFeatureSetIndex = 0; m_reverseAPIFeatureIndex = 0; + m_workspaceIndex = 0; for (int i = 0; i < AIS_VESSEL_COLUMNS; i++) { @@ -71,6 +72,9 @@ QByteArray AISSettings::serialize() const s.writeBlob(27, m_rollupState->serialize()); } + s.writeS32(27, m_workspaceIndex); + s.writeBlob(28, m_geometryBytes); + for (int i = 0; i < AIS_VESSEL_COLUMNS; i++) { s.writeS32(300 + i, m_vesselColumnIndexes[i]); } @@ -122,6 +126,9 @@ bool AISSettings::deserialize(const QByteArray& data) m_rollupState->deserialize(bytetmp); } + d.readS32(27, &m_workspaceIndex, 0); + d.readBlob(28, &m_geometryBytes); + for (int i = 0; i < AIS_VESSEL_COLUMNS; i++) { d.readS32(300 + i, &m_vesselColumnIndexes[i], i); } diff --git a/plugins/feature/ais/aissettings.h b/plugins/feature/ais/aissettings.h index d29fe3f84..2cf555800 100644 --- a/plugins/feature/ais/aissettings.h +++ b/plugins/feature/ais/aissettings.h @@ -39,6 +39,8 @@ struct AISSettings uint16_t m_reverseAPIFeatureSetIndex; uint16_t m_reverseAPIFeatureIndex; Serializable *m_rollupState; + int m_workspaceIndex; + QByteArray m_geometryBytes; int m_vesselColumnIndexes[AIS_VESSEL_COLUMNS]; int m_vesselColumnSizes[AIS_VESSEL_COLUMNS]; diff --git a/plugins/feature/antennatools/antennatoolsgui.h b/plugins/feature/antennatools/antennatoolsgui.h index c21c8654b..95823f9a3 100644 --- a/plugins/feature/antennatools/antennatoolsgui.h +++ b/plugins/feature/antennatools/antennatoolsgui.h @@ -46,6 +46,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } private: Ui::AntennaToolsGUI* ui; diff --git a/plugins/feature/antennatools/antennatoolssettings.cpp b/plugins/feature/antennatools/antennatoolssettings.cpp index 2dd559bbe..2dce3f633 100644 --- a/plugins/feature/antennatools/antennatoolssettings.cpp +++ b/plugins/feature/antennatools/antennatoolssettings.cpp @@ -49,6 +49,7 @@ void AntennaToolsSettings::resetToDefaults() m_reverseAPIPort = 8888; m_reverseAPIFeatureSetIndex = 0; m_reverseAPIFeatureIndex = 0; + m_workspaceIndex = 0; } QByteArray AntennaToolsSettings::serialize() const @@ -78,6 +79,9 @@ QByteArray AntennaToolsSettings::serialize() const s.writeBlob(19, m_rollupState->serialize()); } + s.writeS32(20, m_workspaceIndex); + s.writeBlob(21, m_geometryBytes); + return s.final(); } @@ -131,6 +135,9 @@ bool AntennaToolsSettings::deserialize(const QByteArray& data) m_rollupState->deserialize(bytetmp); } + d.readS32(20, &m_workspaceIndex, 0); + d.readBlob(21, &m_geometryBytes); + return true; } else diff --git a/plugins/feature/antennatools/antennatoolssettings.h b/plugins/feature/antennatools/antennatoolssettings.h index 704f17501..3302cdfd4 100644 --- a/plugins/feature/antennatools/antennatoolssettings.h +++ b/plugins/feature/antennatools/antennatoolssettings.h @@ -51,6 +51,8 @@ struct AntennaToolsSettings uint16_t m_reverseAPIFeatureSetIndex; uint16_t m_reverseAPIFeatureIndex; Serializable *m_rollupState; + int m_workspaceIndex; + QByteArray m_geometryBytes; AntennaToolsSettings(); void resetToDefaults(); diff --git a/plugins/feature/aprs/aprsgui.h b/plugins/feature/aprs/aprsgui.h index 412387164..f1a89d1e5 100644 --- a/plugins/feature/aprs/aprsgui.h +++ b/plugins/feature/aprs/aprsgui.h @@ -105,6 +105,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } protected: void resizeEvent(QResizeEvent* size); diff --git a/plugins/feature/aprs/aprssettings.cpp b/plugins/feature/aprs/aprssettings.cpp index 5e843f04b..b9b2036af 100644 --- a/plugins/feature/aprs/aprssettings.cpp +++ b/plugins/feature/aprs/aprssettings.cpp @@ -77,6 +77,7 @@ void APRSSettings::resetToDefaults() m_reverseAPIPort = 8888; m_reverseAPIFeatureSetIndex = 0; m_reverseAPIFeatureIndex = 0; + m_workspaceIndex = 0; for (int i = 0; i < APRS_PACKETS_TABLE_COLUMNS; i++) { @@ -143,6 +144,9 @@ QByteArray APRSSettings::serialize() const s.writeBlob(20, m_rollupState->serialize()); } + s.writeS32(21, m_workspaceIndex); + s.writeBlob(22, m_geometryBytes); + for (int i = 0; i < APRS_PACKETS_TABLE_COLUMNS; i++) s.writeS32(100 + i, m_packetsTableColumnIndexes[i]); for (int i = 0; i < APRS_PACKETS_TABLE_COLUMNS; i++) @@ -222,6 +226,9 @@ bool APRSSettings::deserialize(const QByteArray& data) m_rollupState->deserialize(bytetmp); } + d.readS32(21, &m_workspaceIndex, 0); + d.readBlob(22, &m_geometryBytes); + for (int i = 0; i < APRS_PACKETS_TABLE_COLUMNS; i++) d.readS32(100 + i, &m_packetsTableColumnIndexes[i], i); for (int i = 0; i < APRS_PACKETS_TABLE_COLUMNS; i++) diff --git a/plugins/feature/aprs/aprssettings.h b/plugins/feature/aprs/aprssettings.h index 509bdd160..99c58894f 100644 --- a/plugins/feature/aprs/aprssettings.h +++ b/plugins/feature/aprs/aprssettings.h @@ -77,6 +77,8 @@ struct APRSSettings uint16_t m_reverseAPIFeatureSetIndex; uint16_t m_reverseAPIFeatureIndex; Serializable *m_rollupState; + int m_workspaceIndex; + QByteArray m_geometryBytes; int m_packetsTableColumnIndexes[APRS_PACKETS_TABLE_COLUMNS];//!< How the columns are ordered in the table int m_packetsTableColumnSizes[APRS_PACKETS_TABLE_COLUMNS]; //!< Size of the columns in the table diff --git a/plugins/feature/demodanalyzer/demodanalyzergui.h b/plugins/feature/demodanalyzer/demodanalyzergui.h index b11100ecf..e26fddd60 100644 --- a/plugins/feature/demodanalyzer/demodanalyzergui.h +++ b/plugins/feature/demodanalyzer/demodanalyzergui.h @@ -49,6 +49,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } private: Ui::DemodAnalyzerGUI* ui; diff --git a/plugins/feature/demodanalyzer/demodanalyzersettings.cpp b/plugins/feature/demodanalyzer/demodanalyzersettings.cpp index 12419b2cc..d261e5417 100644 --- a/plugins/feature/demodanalyzer/demodanalyzersettings.cpp +++ b/plugins/feature/demodanalyzer/demodanalyzersettings.cpp @@ -76,6 +76,7 @@ void DemodAnalyzerSettings::resetToDefaults() m_reverseAPIPort = 8888; m_reverseAPIFeatureSetIndex = 0; m_reverseAPIFeatureIndex = 0; + m_workspaceIndex = 0; } QByteArray DemodAnalyzerSettings::serialize() const @@ -103,6 +104,9 @@ QByteArray DemodAnalyzerSettings::serialize() const s.writeBlob(12, m_rollupState->serialize()); } + s.writeS32(13, m_workspaceIndex); + s.writeBlob(14, m_geometryBytes); + return s.final(); } @@ -158,6 +162,9 @@ bool DemodAnalyzerSettings::deserialize(const QByteArray& data) m_rollupState->deserialize(bytetmp); } + d.readS32(13, &m_workspaceIndex, 0); + d.readBlob(14, &m_geometryBytes); + return true; } else diff --git a/plugins/feature/demodanalyzer/demodanalyzersettings.h b/plugins/feature/demodanalyzer/demodanalyzersettings.h index c4ba8516a..d3670d181 100644 --- a/plugins/feature/demodanalyzer/demodanalyzersettings.h +++ b/plugins/feature/demodanalyzer/demodanalyzersettings.h @@ -52,6 +52,8 @@ struct DemodAnalyzerSettings Serializable *m_spectrumGUI; Serializable *m_scopeGUI; Serializable *m_rollupState; + int m_workspaceIndex; + QByteArray m_geometryBytes; DemodAnalyzerSettings(); void resetToDefaults(); diff --git a/plugins/feature/gs232controller/gs232controllergui.h b/plugins/feature/gs232controller/gs232controllergui.h index 1fbd42d03..887d5d783 100644 --- a/plugins/feature/gs232controller/gs232controllergui.h +++ b/plugins/feature/gs232controller/gs232controllergui.h @@ -45,6 +45,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } private: Ui::GS232ControllerGUI* ui; diff --git a/plugins/feature/gs232controller/gs232controllersettings.cpp b/plugins/feature/gs232controller/gs232controllersettings.cpp index 0e9f3d756..fd9a34278 100644 --- a/plugins/feature/gs232controller/gs232controllersettings.cpp +++ b/plugins/feature/gs232controller/gs232controllersettings.cpp @@ -69,6 +69,7 @@ void GS232ControllerSettings::resetToDefaults() m_connection = SERIAL; m_host = "127.0.0.1"; m_port = 4533; + m_workspaceIndex = 0; } QByteArray GS232ControllerSettings::serialize() const @@ -104,6 +105,9 @@ QByteArray GS232ControllerSettings::serialize() const s.writeBlob(26, m_rollupState->serialize()); } + s.writeS32(27, m_workspaceIndex); + s.writeBlob(28, m_geometryBytes); + return s.final(); } @@ -163,6 +167,9 @@ bool GS232ControllerSettings::deserialize(const QByteArray& data) m_rollupState->deserialize(bytetmp); } + d.readS32(27, &m_workspaceIndex, 0); + d.readBlob(28, &m_geometryBytes); + return true; } else diff --git a/plugins/feature/gs232controller/gs232controllersettings.h b/plugins/feature/gs232controller/gs232controllersettings.h index f922022f8..3db11f2ce 100644 --- a/plugins/feature/gs232controller/gs232controllersettings.h +++ b/plugins/feature/gs232controller/gs232controllersettings.h @@ -68,6 +68,8 @@ struct GS232ControllerSettings uint16_t m_reverseAPIPort; uint16_t m_reverseAPIFeatureSetIndex; uint16_t m_reverseAPIFeatureIndex; + int m_workspaceIndex; + QByteArray m_geometryBytes; GS232ControllerSettings(); void resetToDefaults(); diff --git a/plugins/feature/jogdialcontroller/jogdialcontrollergui.h b/plugins/feature/jogdialcontroller/jogdialcontrollergui.h index d7d27633c..932b5592d 100644 --- a/plugins/feature/jogdialcontroller/jogdialcontrollergui.h +++ b/plugins/feature/jogdialcontroller/jogdialcontrollergui.h @@ -47,6 +47,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } protected: void focusInEvent(QFocusEvent* e); diff --git a/plugins/feature/jogdialcontroller/jogdialcontrollersettings.cpp b/plugins/feature/jogdialcontroller/jogdialcontrollersettings.cpp index 8893cbe5e..01900a482 100644 --- a/plugins/feature/jogdialcontroller/jogdialcontrollersettings.cpp +++ b/plugins/feature/jogdialcontroller/jogdialcontrollersettings.cpp @@ -71,6 +71,7 @@ void JogdialControllerSettings::resetToDefaults() m_reverseAPIPort = 8888; m_reverseAPIFeatureSetIndex = 0; m_reverseAPIFeatureIndex = 0; + m_workspaceIndex = 0; } QByteArray JogdialControllerSettings::serialize() const @@ -89,6 +90,9 @@ QByteArray JogdialControllerSettings::serialize() const s.writeBlob(12, m_rollupState->serialize()); } + s.writeS32(13, m_workspaceIndex); + s.writeBlob(14, m_geometryBytes); + return s.final(); } @@ -131,6 +135,9 @@ bool JogdialControllerSettings::deserialize(const QByteArray& data) m_rollupState->deserialize(bytetmp); } + d.readS32(13, &m_workspaceIndex, 0); + d.readBlob(14, &m_geometryBytes); + return true; } else diff --git a/plugins/feature/jogdialcontroller/jogdialcontrollersettings.h b/plugins/feature/jogdialcontroller/jogdialcontrollersettings.h index 5d1b82773..fecb052a4 100644 --- a/plugins/feature/jogdialcontroller/jogdialcontrollersettings.h +++ b/plugins/feature/jogdialcontroller/jogdialcontrollersettings.h @@ -52,6 +52,8 @@ struct JogdialControllerSettings uint16_t m_reverseAPIFeatureSetIndex; uint16_t m_reverseAPIFeatureIndex; Serializable *m_rollupState; + int m_workspaceIndex; + QByteArray m_geometryBytes; JogdialControllerSettings(); void resetToDefaults(); diff --git a/plugins/feature/map/mapgui.h b/plugins/feature/map/mapgui.h index 16ad02a19..774810f8d 100644 --- a/plugins/feature/map/mapgui.h +++ b/plugins/feature/map/mapgui.h @@ -72,6 +72,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } AzEl *getAzEl() { return &m_azEl; } Map *getMap() { return m_map; } QQuickItem *getMapItem(); diff --git a/plugins/feature/map/mapsettings.cpp b/plugins/feature/map/mapsettings.cpp index 732e58502..8df0b3501 100644 --- a/plugins/feature/map/mapsettings.cpp +++ b/plugins/feature/map/mapsettings.cpp @@ -106,6 +106,7 @@ void MapSettings::resetToDefaults() m_eciCamera = false; m_modelDir = HttpDownloadManager::downloadDir() + "/3d"; m_antiAliasing = "None"; + m_workspaceIndex = 0; } QByteArray MapSettings::serialize() const @@ -144,6 +145,8 @@ QByteArray MapSettings::serialize() const s.writeBool(30, m_eciCamera); s.writeString(31, m_cesiumIonAPIKey); s.writeString(32, m_antiAliasing); + s.writeS32(33, m_workspaceIndex); + s.writeBlob(34, m_geometryBytes); return s.final(); } @@ -210,6 +213,8 @@ bool MapSettings::deserialize(const QByteArray& data) d.readBool(30, &m_eciCamera, false); d.readString(31, &m_cesiumIonAPIKey, ""); d.readString(32, &m_antiAliasing, "None"); + d.readS32(33, &m_workspaceIndex, 0); + d.readBlob(34, &m_geometryBytes); return true; } diff --git a/plugins/feature/map/mapsettings.h b/plugins/feature/map/mapsettings.h index e190f770a..7ce04b65f 100644 --- a/plugins/feature/map/mapsettings.h +++ b/plugins/feature/map/mapsettings.h @@ -90,6 +90,8 @@ struct MapSettings Serializable *m_rollupState; bool m_map2DEnabled; QString m_mapType; // "Street Map", "Satellite Map", etc.. as selected in combobox + int m_workspaceIndex; + QByteArray m_geometryBytes; // 3D Map settings bool m_map3DEnabled; diff --git a/plugins/feature/pertester/pertestergui.h b/plugins/feature/pertester/pertestergui.h index b5fe9b0fa..2306bf792 100644 --- a/plugins/feature/pertester/pertestergui.h +++ b/plugins/feature/pertester/pertestergui.h @@ -45,6 +45,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } private: Ui::PERTesterGUI* ui; diff --git a/plugins/feature/pertester/pertestersettings.cpp b/plugins/feature/pertester/pertestersettings.cpp index 7499902d4..0121b1d8d 100644 --- a/plugins/feature/pertester/pertestersettings.cpp +++ b/plugins/feature/pertester/pertestersettings.cpp @@ -50,6 +50,7 @@ void PERTesterSettings::resetToDefaults() m_reverseAPIPort = 8888; m_reverseAPIFeatureSetIndex = 0; m_reverseAPIFeatureIndex = 0; + m_workspaceIndex = 0; } QByteArray PERTesterSettings::serialize() const @@ -78,6 +79,8 @@ QByteArray PERTesterSettings::serialize() const s.writeBlob(27, m_rollupState->serialize()); } + s.writeS32(28, m_workspaceIndex); + return s.final(); } @@ -146,6 +149,9 @@ bool PERTesterSettings::deserialize(const QByteArray& data) m_rollupState->deserialize(bytetmp); } + d.readS32(28, &m_workspaceIndex, 0); + d.readBlob(29, &m_geometryBytes); + return true; } else diff --git a/plugins/feature/pertester/pertestersettings.h b/plugins/feature/pertester/pertestersettings.h index ea2cfcc83..119aebbcd 100644 --- a/plugins/feature/pertester/pertestersettings.h +++ b/plugins/feature/pertester/pertestersettings.h @@ -48,6 +48,8 @@ struct PERTesterSettings uint16_t m_reverseAPIFeatureSetIndex; uint16_t m_reverseAPIFeatureIndex; Serializable *m_rollupState; + int m_workspaceIndex; + QByteArray m_geometryBytes; PERTesterSettings(); void resetToDefaults(); diff --git a/plugins/feature/radiosonde/radiosondegui.h b/plugins/feature/radiosonde/radiosondegui.h index 18202ab61..1bd135232 100644 --- a/plugins/feature/radiosonde/radiosondegui.h +++ b/plugins/feature/radiosonde/radiosondegui.h @@ -74,6 +74,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } private: Ui::RadiosondeGUI* ui; diff --git a/plugins/feature/radiosonde/radiosondesettings.cpp b/plugins/feature/radiosonde/radiosondesettings.cpp index 565d44877..2e2f016b6 100644 --- a/plugins/feature/radiosonde/radiosondesettings.cpp +++ b/plugins/feature/radiosonde/radiosondesettings.cpp @@ -76,6 +76,8 @@ QByteArray RadiosondeSettings::serialize() const s.writeS32(10, (int)m_y1); s.writeS32(11, (int)m_y2); + s.writeS32(12, m_workspaceIndex); + s.writeBlob(13, m_geometryBytes); for (int i = 0; i < RADIOSONDES_COLUMNS; i++) { s.writeS32(300 + i, m_radiosondesColumnIndexes[i]); @@ -130,6 +132,8 @@ bool RadiosondeSettings::deserialize(const QByteArray& data) d.readS32(10, (int *)&m_y1, (int)ALTITUDE); d.readS32(11, (int *)&m_y2, (int)TEMPERATURE); + d.readS32(12, &m_workspaceIndex, 0); + d.readBlob(13, &m_geometryBytes); for (int i = 0; i < RADIOSONDES_COLUMNS; i++) { d.readS32(300 + i, &m_radiosondesColumnIndexes[i], i); diff --git a/plugins/feature/radiosonde/radiosondesettings.h b/plugins/feature/radiosonde/radiosondesettings.h index 4c199c731..878b39bfc 100644 --- a/plugins/feature/radiosonde/radiosondesettings.h +++ b/plugins/feature/radiosonde/radiosondesettings.h @@ -39,6 +39,8 @@ struct RadiosondeSettings uint16_t m_reverseAPIFeatureSetIndex; uint16_t m_reverseAPIFeatureIndex; Serializable *m_rollupState; + int m_workspaceIndex; + QByteArray m_geometryBytes; enum ChartData { NONE, diff --git a/plugins/feature/rigctlserver/rigctlservergui.h b/plugins/feature/rigctlserver/rigctlservergui.h index 679b61dd6..51f429a09 100644 --- a/plugins/feature/rigctlserver/rigctlservergui.h +++ b/plugins/feature/rigctlserver/rigctlservergui.h @@ -45,6 +45,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } private: Ui::RigCtlServerGUI* ui; diff --git a/plugins/feature/rigctlserver/rigctlserversettings.cpp b/plugins/feature/rigctlserver/rigctlserversettings.cpp index a875dc5d1..ad00529cb 100644 --- a/plugins/feature/rigctlserver/rigctlserversettings.cpp +++ b/plugins/feature/rigctlserver/rigctlserversettings.cpp @@ -44,6 +44,7 @@ void RigCtlServerSettings::resetToDefaults() m_reverseAPIPort = 8888; m_reverseAPIFeatureSetIndex = 0; m_reverseAPIFeatureIndex = 0; + m_workspaceIndex = 0; } QByteArray RigCtlServerSettings::serialize() const @@ -66,6 +67,9 @@ QByteArray RigCtlServerSettings::serialize() const s.writeBlob(12, m_rollupState->serialize()); } + s.writeS32(13, m_workspaceIndex); + s.writeBlob(14, m_geometryBytes); + return s.final(); } @@ -119,6 +123,9 @@ bool RigCtlServerSettings::deserialize(const QByteArray& data) m_rollupState->deserialize(bytetmp); } + d.readS32(13, &m_workspaceIndex, 0); + d.readBlob(14, &m_geometryBytes); + return true; } else diff --git a/plugins/feature/rigctlserver/rigctlserversettings.h b/plugins/feature/rigctlserver/rigctlserversettings.h index 70bdabf65..b76562b38 100644 --- a/plugins/feature/rigctlserver/rigctlserversettings.h +++ b/plugins/feature/rigctlserver/rigctlserversettings.h @@ -60,6 +60,8 @@ struct RigCtlServerSettings uint16_t m_reverseAPIFeatureSetIndex; uint16_t m_reverseAPIFeatureIndex; Serializable *m_rollupState; + int m_workspaceIndex; + QByteArray m_geometryBytes; RigCtlServerSettings(); void resetToDefaults(); diff --git a/plugins/feature/satellitetracker/satellitetrackergui.h b/plugins/feature/satellitetracker/satellitetrackergui.h index 2d192f48b..143d81bd6 100644 --- a/plugins/feature/satellitetracker/satellitetrackergui.h +++ b/plugins/feature/satellitetracker/satellitetrackergui.h @@ -52,6 +52,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } private: Ui::SatelliteTrackerGUI* ui; diff --git a/plugins/feature/satellitetracker/satellitetrackersettings.cpp b/plugins/feature/satellitetracker/satellitetrackersettings.cpp index 1d7eaa9ad..9afab8bd5 100644 --- a/plugins/feature/satellitetracker/satellitetrackersettings.cpp +++ b/plugins/feature/satellitetracker/satellitetrackersettings.cpp @@ -78,6 +78,8 @@ void SatelliteTrackerSettings::resetToDefaults() m_dateTimeSelect = NOW; m_mapFeature = ""; m_fileInputDevice = ""; + m_workspaceIndex = 0; + for (int i = 0; i < SAT_COL_COLUMNS; i++) { m_columnIndexes[i] = i; @@ -134,6 +136,8 @@ QByteArray SatelliteTrackerSettings::serialize() const s.writeS32(42, (int)m_dateTimeSelect); s.writeString(43, m_mapFeature); s.writeString(44, m_fileInputDevice); + s.writeS32(45, m_workspaceIndex); + s.writeBlob(46, m_geometryBytes); for (int i = 0; i < SAT_COL_COLUMNS; i++) { s.writeS32(100 + i, m_columnIndexes[i]); @@ -225,6 +229,8 @@ bool SatelliteTrackerSettings::deserialize(const QByteArray& data) d.readS32(42, (int *)&m_dateTimeSelect, (int)NOW); d.readString(43, &m_mapFeature, ""); d.readString(44, &m_fileInputDevice, ""); + d.readS32(45, &m_workspaceIndex, 0); + d.readBlob(46, &m_geometryBytes); for (int i = 0; i < SAT_COL_COLUMNS; i++) { d.readS32(100 + i, &m_columnIndexes[i], i); diff --git a/plugins/feature/satellitetracker/satellitetrackersettings.h b/plugins/feature/satellitetracker/satellitetrackersettings.h index 238d1f5c7..34495e41b 100644 --- a/plugins/feature/satellitetracker/satellitetrackersettings.h +++ b/plugins/feature/satellitetracker/satellitetrackersettings.h @@ -94,6 +94,8 @@ struct SatelliteTrackerSettings uint16_t m_reverseAPIFeatureSetIndex; uint16_t m_reverseAPIFeatureIndex; Serializable *m_rollupState; + int m_workspaceIndex; + QByteArray m_geometryBytes; SatelliteTrackerSettings(); void resetToDefaults(); diff --git a/plugins/feature/simpleptt/simplepttgui.h b/plugins/feature/simpleptt/simplepttgui.h index 3062bde6a..bee5244d8 100644 --- a/plugins/feature/simpleptt/simplepttgui.h +++ b/plugins/feature/simpleptt/simplepttgui.h @@ -44,6 +44,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } private: Ui::SimplePTTGUI* ui; diff --git a/plugins/feature/simpleptt/simplepttsettings.cpp b/plugins/feature/simpleptt/simplepttsettings.cpp index 1029d312f..efbafdbd8 100644 --- a/plugins/feature/simpleptt/simplepttsettings.cpp +++ b/plugins/feature/simpleptt/simplepttsettings.cpp @@ -47,6 +47,7 @@ void SimplePTTSettings::resetToDefaults() m_reverseAPIPort = 8888; m_reverseAPIFeatureSetIndex = 0; m_reverseAPIFeatureIndex = 0; + m_workspaceIndex = 0; } QByteArray SimplePTTSettings::serialize() const @@ -74,6 +75,8 @@ QByteArray SimplePTTSettings::serialize() const s.writeBool(15, m_vox); s.writeBool(16, m_voxEnable); s.writeS32(17, m_voxHold); + s.writeS32(18, m_workspaceIndex); + s.writeBlob(19, m_geometryBytes); return s.final(); } @@ -125,7 +128,9 @@ bool SimplePTTSettings::deserialize(const QByteArray& data) d.readS32(14, &m_voxLevel, -20); d.readBool(15, &m_vox, false); d.readBool(16, &m_voxEnable, false); - d.readS32(16, &m_voxHold, 500); + d.readS32(17, &m_voxHold, 500); + d.readS32(18, &m_workspaceIndex, 0); + d.readBlob(19, &m_geometryBytes); return true; } diff --git a/plugins/feature/simpleptt/simplepttsettings.h b/plugins/feature/simpleptt/simplepttsettings.h index 00a12a77c..39c9a2fdb 100644 --- a/plugins/feature/simpleptt/simplepttsettings.h +++ b/plugins/feature/simpleptt/simplepttsettings.h @@ -42,6 +42,8 @@ struct SimplePTTSettings uint16_t m_reverseAPIFeatureSetIndex; uint16_t m_reverseAPIFeatureIndex; Serializable *m_rollupState; + int m_workspaceIndex; + QByteArray m_geometryBytes; SimplePTTSettings(); void resetToDefaults(); diff --git a/plugins/feature/startracker/startrackergui.h b/plugins/feature/startracker/startrackergui.h index 2d41484da..802cfae69 100644 --- a/plugins/feature/startracker/startrackergui.h +++ b/plugins/feature/startracker/startrackergui.h @@ -66,6 +66,10 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } private: Ui::StarTrackerGUI* ui; diff --git a/plugins/feature/startracker/startrackersettings.cpp b/plugins/feature/startracker/startrackersettings.cpp index f15aad679..b83e3d802 100644 --- a/plugins/feature/startracker/startrackersettings.cpp +++ b/plugins/feature/startracker/startrackersettings.cpp @@ -82,6 +82,7 @@ void StarTrackerSettings::resetToDefaults() m_weatherUpdatePeriod = 60; m_drawSunOnSkyTempChart = true; m_drawMoonOnSkyTempChart = true; + m_workspaceIndex = 0; } QByteArray StarTrackerSettings::serialize() const @@ -136,6 +137,9 @@ QByteArray StarTrackerSettings::serialize() const s.writeBlob(44, m_rollupState->serialize()); } + s.writeS32(45, m_workspaceIndex); + s.writeBlob(46, m_geometryBytes); + return s.final(); } @@ -221,6 +225,9 @@ bool StarTrackerSettings::deserialize(const QByteArray& data) m_rollupState->deserialize(bytetmp); } + d.readS32(45, &m_workspaceIndex, 0); + d.readBlob(46, &m_geometryBytes); + return true; } else diff --git a/plugins/feature/startracker/startrackersettings.h b/plugins/feature/startracker/startrackersettings.h index 9232eea9c..eec6f2627 100644 --- a/plugins/feature/startracker/startrackersettings.h +++ b/plugins/feature/startracker/startrackersettings.h @@ -72,6 +72,8 @@ struct StarTrackerSettings bool m_drawSunOnSkyTempChart; bool m_drawMoonOnSkyTempChart; Serializable *m_rollupState; + int m_workspaceIndex; + QByteArray m_geometryBytes; StarTrackerSettings(); void resetToDefaults(); diff --git a/plugins/feature/vorlocalizer/vorlocalizergui.h b/plugins/feature/vorlocalizer/vorlocalizergui.h index b2d1f34f0..0f498a930 100644 --- a/plugins/feature/vorlocalizer/vorlocalizergui.h +++ b/plugins/feature/vorlocalizer/vorlocalizergui.h @@ -214,6 +214,10 @@ public: bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } void selectVOR(VORGUI *vorGUI, bool selected); + virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; } + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } private: friend class VORGUI; diff --git a/plugins/feature/vorlocalizer/vorlocalizersettings.cpp b/plugins/feature/vorlocalizer/vorlocalizersettings.cpp index 760a450d4..a6e4da6c7 100644 --- a/plugins/feature/vorlocalizer/vorlocalizersettings.cpp +++ b/plugins/feature/vorlocalizer/vorlocalizersettings.cpp @@ -41,7 +41,7 @@ void VORLocalizerSettings::resetToDefaults() m_reverseAPIPort = 8888; m_reverseAPIFeatureSetIndex = 0; m_reverseAPIFeatureIndex = 0; - + m_workspaceIndex = 0; for (int i = 0; i < VORDEMOD_COLUMNS; i++) { @@ -69,6 +69,9 @@ QByteArray VORLocalizerSettings::serialize() const s.writeBlob(19, m_rollupState->serialize()); } + s.writeS32(20, m_workspaceIndex); + s.writeBlob(21, m_geometryBytes); + for (int i = 0; i < VORDEMOD_COLUMNS; i++) { s.writeS32(100 + i, m_columnIndexes[i]); } @@ -123,6 +126,9 @@ bool VORLocalizerSettings::deserialize(const QByteArray& data) m_rollupState->deserialize(bytetmp); } + d.readS32(20, &m_workspaceIndex, 0); + d.readBlob(21, &m_geometryBytes); + for (int i = 0; i < VORDEMOD_COLUMNS; i++) { d.readS32(100 + i, &m_columnIndexes[i], i); } diff --git a/plugins/feature/vorlocalizer/vorlocalizersettings.h b/plugins/feature/vorlocalizer/vorlocalizersettings.h index 410c96331..c34a0f790 100644 --- a/plugins/feature/vorlocalizer/vorlocalizersettings.h +++ b/plugins/feature/vorlocalizer/vorlocalizersettings.h @@ -74,7 +74,8 @@ struct VORLocalizerSettings uint16_t m_reverseAPIFeatureSetIndex; uint16_t m_reverseAPIFeatureIndex; Serializable *m_rollupState; - + int m_workspaceIndex; + QByteArray m_geometryBytes; static const int VORDEMOD_COLUMNS = 11; static const int VOR_COL_NAME = 0; diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt index 899bd7bdc..c8be0d4b8 100644 --- a/sdrbase/CMakeLists.txt +++ b/sdrbase/CMakeLists.txt @@ -176,6 +176,7 @@ set(sdrbase_SOURCES pipes/objectpipe.cpp pipes/objectpipesregistrations.cpp + settings/configuration.cpp settings/featuresetpreset.cpp settings/preferences.cpp settings/preset.cpp @@ -389,6 +390,7 @@ set(sdrbase_HEADERS plugin/pluginapi.h plugin/pluginmanager.h + settings/configuration.h settings/featuresetpreset.h settings/preferences.h settings/preset.h diff --git a/sdrbase/pipes/messagepipeslegacy.cpp b/sdrbase/pipes/messagepipeslegacy.cpp deleted file mode 100644 index 6d9355bba..000000000 --- a/sdrbase/pipes/messagepipeslegacy.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// 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 deleted file mode 100644 index 562e582a8..000000000 --- a/sdrbase/pipes/messagepipeslegacy.h +++ /dev/null @@ -1,59 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// 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/settings/configuration.cpp b/sdrbase/settings/configuration.cpp new file mode 100644 index 000000000..91210fa91 --- /dev/null +++ b/sdrbase/settings/configuration.cpp @@ -0,0 +1,102 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 Edouard Griffiths, F4EXB. // +// // +// Swagger server adapter interface // +// // +// 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 "util/simpleserializer.h" +#include "configuration.h" + +Configuration::Configuration() +{ + resetToDefaults(); +} + +Configuration::~Configuration() +{ } + +void Configuration::resetToDefaults() +{ + m_group = "default"; + m_description = "no name"; + m_workspaceGeometries.clear(); +} + +QByteArray Configuration::serialize() const +{ + SimpleSerializer s(1); + + s.writeString(1, m_group); + s.writeString(2, m_description); + QByteArray b = m_featureSetPreset.serialize(); + s.writeBlob(3, b); + + s.writeS32(100, m_workspaceGeometries.size()); + + for(int i = 0; i < m_workspaceGeometries.size(); i++) { + s.writeBlob(101 + i, m_workspaceGeometries[i]); + } + + return s.final(); +} + +bool Configuration::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if (!d.isValid()) + { + resetToDefaults(); + return false; + } + + if (d.getVersion() == 1) + { + d.readString(1, &m_group, "default"); + d.readString(2, &m_description, "no name"); + + QByteArray b; + d.readBlob(3, &b); + m_featureSetPreset.deserialize(b); + + int nbWorkspaces; + d.readS32(100, &nbWorkspaces, 0); + + for(int i = 0; i < nbWorkspaces; i++) + { + m_workspaceGeometries.push_back(QByteArray()); + d.readBlob(101 + i, &m_workspaceGeometries.back()); + } + + return true; + } + else + { + resetToDefaults(); + return false; + } +} + +int Configuration::getNumberOfWorkspaces() const +{ + return m_workspaceGeometries.size(); +} + +void Configuration::clearData() +{ + m_featureSetPreset.clearFeatures(); + m_workspaceGeometries.clear(); +} diff --git a/sdrbase/settings/configuration.h b/sdrbase/settings/configuration.h new file mode 100644 index 000000000..cbdbc37ed --- /dev/null +++ b/sdrbase/settings/configuration.h @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 Edouard Griffiths, F4EXB. // +// // +// Swagger server adapter interface // +// // +// 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_CONFIGURATION_H +#define INCLUDE_CONFIGURATION_H + +#include +#include +#include +#include + +#include "featuresetpreset.h" +#include "export.h" + +class SDRBASE_API WorkspaceConfiguration { +public: +}; + +class SDRBASE_API Configuration { +public: + Configuration(); + ~Configuration(); + void resetToDefaults(); + + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + + void setGroup(const QString& group) { m_group = group; } + const QString& getGroup() const { return m_group; } + void setDescription(const QString& description) { m_description = description; } + const QString& getDescription() const { return m_description; } + + int getNumberOfWorkspaces() const; + FeatureSetPreset& getFeatureSetPreset() { return m_featureSetPreset; } + const FeatureSetPreset& getFeatureSetPreset() const { return m_featureSetPreset; } + QList& getWorkspaceGeometries() { return m_workspaceGeometries; } + const QList& getWorkspaceGeometries() const { return m_workspaceGeometries; } + void clearData(); + + static bool configCompare(const Configuration *p1, Configuration *p2) + { + if (p1->m_group != p2->m_group) + { + return p1->m_group < p2->m_group; + } + else + { + return p1->m_description < p2->m_description; + } + } + +private: + QString m_group; + QString m_description; + QList m_workspaceGeometries; + FeatureSetPreset m_featureSetPreset; +}; + +Q_DECLARE_METATYPE(const Configuration*) +Q_DECLARE_METATYPE(Configuration*) + +#endif // INCLUDE_CONFIGURATION_H diff --git a/sdrbase/settings/mainsettings.cpp b/sdrbase/settings/mainsettings.cpp index 51d6ad8d9..560b7ecd1 100644 --- a/sdrbase/settings/mainsettings.cpp +++ b/sdrbase/settings/mainsettings.cpp @@ -52,8 +52,9 @@ void MainSettings::load() QSettings s; m_preferences.deserialize(qUncompress(QByteArray::fromBase64(s.value("preferences").toByteArray()))); - m_workingPreset.deserialize(qUncompress(QByteArray::fromBase64(s.value("current").toByteArray()))); - m_workingFeatureSetPreset.deserialize(qUncompress(QByteArray::fromBase64(s.value("current-featureset").toByteArray()))); + // m_workingPreset.deserialize(qUncompress(QByteArray::fromBase64(s.value("current").toByteArray()))); + // m_workingFeatureSetPreset.deserialize(qUncompress(QByteArray::fromBase64(s.value("current-featureset").toByteArray()))); + m_workingConfiguration.deserialize(qUncompress(QByteArray::fromBase64(s.value("current-configuration").toByteArray()))); if (m_audioDeviceManager) { m_audioDeviceManager->deserialize(qUncompress(QByteArray::fromBase64(s.value("audio").toByteArray()))); @@ -113,6 +114,22 @@ void MainSettings::load() delete featureSetPreset; } + s.endGroup(); + } + else if (groups[i].startsWith("configuration")) + { + s.beginGroup(groups[i]); + Configuration* configuration = new Configuration; + + if (configuration->deserialize(qUncompress(QByteArray::fromBase64(s.value("data").toByteArray())))) + { + m_configurations.append(configuration); + } + else + { + delete configuration; + } + s.endGroup(); } } @@ -126,8 +143,9 @@ void MainSettings::save() const QSettings s; s.setValue("preferences", qCompress(m_preferences.serialize()).toBase64()); - s.setValue("current", qCompress(m_workingPreset.serialize()).toBase64()); - s.setValue("current-featureset", qCompress(m_workingFeatureSetPreset.serialize()).toBase64()); + // s.setValue("current", qCompress(m_workingPreset.serialize()).toBase64()); + // s.setValue("current-featureset", qCompress(m_workingFeatureSetPreset.serialize()).toBase64()); + s.setValue("current-configuration", qCompress(m_workingConfiguration.serialize()).toBase64()); if (m_audioDeviceManager) { s.setValue("audio", qCompress(m_audioDeviceManager->serialize()).toBase64()); @@ -171,6 +189,14 @@ void MainSettings::save() const s.endGroup(); } + for (int i = 0; i < m_configurations.count(); ++i) + { + QString group = QString("configuration-%1").arg(i + 1); + s.beginGroup(group); + s.setValue("data", qCompress(m_configurations[i]->serialize()).toBase64()); + s.endGroup(); + } + s.setValue("hwDeviceUserArgs", qCompress(m_hardwareDeviceUserArgs.serialize()).toBase64()); s.setValue("limeRFEUSBCalib", qCompress(m_limeRFEUSBCalib.serialize()).toBase64()); } @@ -181,6 +207,7 @@ void MainSettings::initialize() clearCommands(); clearPresets(); clearFeatureSetPresets(); + clearConfigurations(); } void MainSettings::resetToDefaults() @@ -188,6 +215,7 @@ void MainSettings::resetToDefaults() m_preferences.resetToDefaults(); m_workingPreset.resetToDefaults(); m_workingFeatureSetPreset.resetToDefaults(); + m_workingConfiguration.resetToDefaults(); } // DeviceSet presets @@ -395,7 +423,7 @@ void MainSettings::renameFeatureSetPresetGroup(const QString& oldGroupName, cons for (int i = 0; i < nbPresets; i++) { - if (getPreset(i)->getGroup() == oldGroupName) + if (getFeatureSetPreset(i)->getGroup() == oldGroupName) { FeatureSetPreset *preset_mod = const_cast(getFeatureSetPreset(i)); preset_mod->setGroup(newGroupName); @@ -427,3 +455,83 @@ void MainSettings::clearFeatureSetPresets() m_featureSetPresets.clear(); } + +// Configurations + +Configuration* MainSettings::newConfiguration(const QString& group, const QString& description) +{ + Configuration* configuration = new Configuration(); + configuration->setGroup(group); + configuration->setDescription(description); + m_configurations.append(configuration); + return configuration; +} + +void MainSettings::addConfiguration(Configuration *configuration) +{ + m_configurations.append(configuration); +} + +void MainSettings::deleteConfiguration(const Configuration *configuration) +{ + m_configurations.removeAll((Configuration*) configuration); + delete (Configuration*) configuration; +} + +const Configuration* MainSettings::getConfiguration(const QString& groupName, const QString& description) const +{ + int nbConfigurations = getConfigurationCount(); + + for (int i = 0; i < nbConfigurations; i++) + { + if ((getConfiguration(i)->getGroup() == groupName) && + (getConfiguration(i)->getDescription() == description)) + { + return getConfiguration(i); + } + } + + return nullptr; +} + +void MainSettings::sortConfigurations() +{ + std::sort(m_configurations.begin(), m_configurations.end(), Configuration::configCompare); +} + +void MainSettings::renameConfigurationGroup(const QString& oldGroupName, const QString& newGroupName) +{ + int nbConfigurations = getConfigurationCount(); + + for (int i = 0; i < nbConfigurations; i++) + { + if (getConfiguration(i)->getGroup() == oldGroupName) + { + Configuration *configuration_mod = const_cast(getConfiguration(i)); + configuration_mod->setGroup(newGroupName); + } + } +} + +void MainSettings::deleteConfigurationGroup(const QString& groupName) +{ + Configurations::iterator it = m_configurations.begin(); + + while (it != m_configurations.end()) + { + if ((*it)->getGroup() == groupName) { + it = m_configurations.erase(it); + } else { + ++it; + } + } +} + +void MainSettings::clearConfigurations() +{ + foreach (Configuration *configuration, m_configurations) { + delete configuration; + } + + m_configurations.clear(); +} diff --git a/sdrbase/settings/mainsettings.h b/sdrbase/settings/mainsettings.h index aa67fbe6a..cf9a7fa85 100644 --- a/sdrbase/settings/mainsettings.h +++ b/sdrbase/settings/mainsettings.h @@ -8,6 +8,7 @@ #include "preferences.h" #include "preset.h" #include "featuresetpreset.h" +#include "configuration.h" #include "export.h" #include "plugin/pluginmanager.h" @@ -70,6 +71,20 @@ public: FeatureSetPreset* getWorkingFeatureSetPreset() { return &m_workingFeatureSetPreset; } QList *getFeatureSetPresets() { return &m_featureSetPresets; } + Configuration* newConfiguration(const QString& group, const QString& description); + void addConfiguration(Configuration *configuration); + void deleteConfiguration(const Configuration *configuration); + int getConfigurationCount() const { return m_configurations.size(); } + const Configuration* getConfiguration(int index) const { return m_configurations[index]; } + const Configuration* getConfiguration(const QString& groupName, const QString& description) const; + void sortConfigurations(); + void renameConfigurationGroup(const QString& oldGroupName, const QString& newGroupName); + void deleteConfigurationGroup(const QString& groupName); + void clearConfigurations(); + const Configuration& getWorkingConfigurationConst() const { return m_workingConfiguration; } + Configuration* getWorkingConfiguration() { return &m_workingConfiguration; } + QList *getConfigurations() { return &m_configurations; } + const QString& getSourceDevice() const { return m_preferences.getSourceDevice(); } void setSourceDevice(const QString& value) { @@ -174,13 +189,16 @@ protected: Preferences m_preferences; AudioDeviceManager *m_audioDeviceManager; Preset m_workingPreset; - FeatureSetPreset m_workingFeatureSetPreset; typedef QList Presets; Presets m_presets; typedef QList Commands; Commands m_commands; + FeatureSetPreset m_workingFeatureSetPreset; typedef QList FeatureSetPresets; FeatureSetPresets m_featureSetPresets; + Configuration m_workingConfiguration; + typedef QList Configurations; + Configurations m_configurations; DeviceUserArgs m_hardwareDeviceUserArgs; LimeRFEUSBCalib m_limeRFEUSBCalib; AMBEEngine *m_ambeEngine; diff --git a/sdrgui/CMakeLists.txt b/sdrgui/CMakeLists.txt index 3a58139d0..4ed80997d 100644 --- a/sdrgui/CMakeLists.txt +++ b/sdrgui/CMakeLists.txt @@ -23,6 +23,7 @@ set(sdrgui_SOURCES gui/commanditem.cpp gui/commandsdialog.cpp gui/commandoutputdialog.cpp + gui/configurationsdialog.cpp gui/crightclickenabler.cpp gui/customtextedit.cpp gui/cwkeyergui.cpp @@ -120,6 +121,7 @@ set(sdrgui_HEADERS gui/commanditem.h gui/commandsdialog.h gui/commandoutputdialog.h + gui/configurationsdialog.h gui/crightclickenabler.h gui/customtextedit.h gui/cwkeyergui.h @@ -212,6 +214,7 @@ set(sdrgui_FORMS gui/channeladddialog.ui gui/commandsdialog.ui gui/commandoutputdialog.ui + gui/configurationsdialog.ui gui/cwkeyergui.ui gui/devicestreamselectiondialog.ui gui/deviceuserargsdialog.ui diff --git a/sdrgui/feature/featuregui.cpp b/sdrgui/feature/featuregui.cpp index 18128e2c1..05e5f8d02 100644 --- a/sdrgui/feature/featuregui.cpp +++ b/sdrgui/feature/featuregui.cpp @@ -33,7 +33,6 @@ FeatureGUI::FeatureGUI(QWidget *parent) : QMdiSubWindow(parent), m_featureIndex(0), - m_workspaceIndex(0), m_contextMenuType(ContextMenuNone), m_drag(false) { @@ -81,7 +80,7 @@ FeatureGUI::FeatureGUI(QWidget *parent) : m_closeButton->setToolTip("Close feature"); m_statusLabel = new QLabel(); - m_statusLabel->setText("OK"); // for future use + // m_statusLabel->setText("OK"); // for future use m_statusLabel->setFixedHeight(20); m_statusLabel->setToolTip("Feature status"); @@ -111,6 +110,7 @@ FeatureGUI::FeatureGUI(QWidget *parent) : 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->addStretch(1); m_bottomLayout->addWidget(m_sizeGripBottomRight, 0, Qt::AlignBottom | Qt::AlignRight); m_layouts->addLayout(m_topLayout); diff --git a/sdrgui/feature/featuregui.h b/sdrgui/feature/featuregui.h index c51691acb..ce185df40 100644 --- a/sdrgui/feature/featuregui.h +++ b/sdrgui/feature/featuregui.h @@ -49,6 +49,11 @@ public: virtual void resetToDefaults() = 0; virtual QByteArray serialize() const = 0; virtual bool deserialize(const QByteArray& data) = 0; + // Data saved in the derived settings + virtual void setWorkspaceIndex(int index)= 0; + virtual int getWorkspaceIndex() const = 0; + virtual void setGeometryBytes(const QByteArray& blob) = 0; + virtual QByteArray getGeometryBytes() const = 0; virtual MessageQueue* getInputMessageQueue() = 0; @@ -56,8 +61,7 @@ public: 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; } + int getIndex() const { return m_featureIndex; } protected: void closeEvent(QCloseEvent *event); @@ -66,7 +70,6 @@ protected: void resetContextMenuType() { m_contextMenuType = ContextMenuNone; } int m_featureIndex; - int m_workspaceIndex; QString m_helpURL; RollupContents m_rollupContents; ContextMenuType m_contextMenuType; diff --git a/sdrgui/feature/featureuiset.cpp b/sdrgui/feature/featureuiset.cpp index 621d811c1..e09d2d0fb 100644 --- a/sdrgui/feature/featureuiset.cpp +++ b/sdrgui/feature/featureuiset.cpp @@ -112,6 +112,24 @@ Feature *FeatureUISet::getFeatureAt(int featureIndex) } } +const FeatureGUI *FeatureUISet::getFeatureGuiAt(int featureIndex) const +{ + if ((featureIndex >= 0) && (featureIndex < m_featureInstanceRegistrations.count())) { + return m_featureInstanceRegistrations.at(featureIndex).m_gui; + } else{ + return nullptr; + } +} + +FeatureGUI *FeatureUISet::getFeatureGuiAt(int featureIndex) +{ + if ((featureIndex >= 0) && (featureIndex < m_featureInstanceRegistrations.count())) { + return m_featureInstanceRegistrations.at(featureIndex).m_gui; + } else{ + return nullptr; + } +} + void FeatureUISet::loadFeatureSetSettings( const FeatureSetPreset *preset, PluginAPI *pluginAPI, @@ -147,6 +165,7 @@ void FeatureUISet::loadFeatureSetSettings( { const FeatureSetPreset::FeatureConfig& featureConfig = preset->getFeatureConfig(i); FeatureGUI *featureGUI = nullptr; + Feature *feature = nullptr; // create feature instance @@ -158,14 +177,9 @@ void FeatureUISet::loadFeatureSetSettings( qPrintable((*featureRegistrations)[i].m_featureIdURI), qPrintable(featureConfig.m_featureIdURI) ); - Feature *feature = - (*featureRegistrations)[i].m_plugin->createFeature(apiAdapter); - featureGUI = - (*featureRegistrations)[i].m_plugin->createFeatureGUI(this, feature); + feature = (*featureRegistrations)[i].m_plugin->createFeature(apiAdapter); + featureGUI = (*featureRegistrations)[i].m_plugin->createFeatureGUI(this, feature); registerFeatureInstance(featureGUI, feature); - featureGUI->setIndex(feature->getIndexInFeatureSet()); - featureGUI->setWorkspaceIndex(workspace->getIndex()); - workspace->addToMdiArea((QMdiSubWindow*) featureGUI); break; } } @@ -173,9 +187,63 @@ void FeatureUISet::loadFeatureSetSettings( if (featureGUI) { qDebug("FeatureUISet::loadFeatureSetSettings: deserializing feature [%s]", - qPrintable(featureConfig.m_featureIdURI) - ); + qPrintable(featureConfig.m_featureIdURI)); featureGUI->deserialize(featureConfig.m_config); + + if (workspace) // restore in current workspace + { + featureGUI->setIndex(feature->getIndexInFeatureSet()); + featureGUI->setWorkspaceIndex(workspace->getIndex()); + workspace->addToMdiArea((QMdiSubWindow*) featureGUI); + } + } + } +} + +void FeatureUISet::loadFeatureSetSettings( + const FeatureSetPreset* preset, + PluginAPI *pluginAPI, + WebAPIAdapterInterface *apiAdapter, + QList& workspaces +) +{ + // This method loads from scratch - load from configuration + qDebug("FeatureUISet::loadFeatureSetSettings: %d feature(s) in preset", preset->getFeatureCount()); + + // Available feature plugins + PluginAPI::FeatureRegistrations *featureRegistrations = pluginAPI->getFeatureRegistrations(); + + for (int i = 0; i < preset->getFeatureCount(); i++) + { + const FeatureSetPreset::FeatureConfig& featureConfig = preset->getFeatureConfig(i); + FeatureGUI *featureGUI = nullptr; + Feature *feature = nullptr; + + // create feature instance + + for(int i = 0; i < featureRegistrations->count(); i++) + { + if (FeatureUtils::compareFeatureURIs((*featureRegistrations)[i].m_featureIdURI, featureConfig.m_featureIdURI)) + { + qDebug("FeatureUISet::loadFeatureSetSettings: creating new feature [%s] from config [%s]", + qPrintable((*featureRegistrations)[i].m_featureIdURI), + qPrintable(featureConfig.m_featureIdURI) + ); + feature = (*featureRegistrations)[i].m_plugin->createFeature(apiAdapter); + featureGUI = (*featureRegistrations)[i].m_plugin->createFeatureGUI(this, feature); + registerFeatureInstance(featureGUI, feature); + break; + } + } + + if (featureGUI) + { + qDebug("FeatureUISet::loadFeatureSetSettings: deserializing feature [%s]", + qPrintable(featureConfig.m_featureIdURI)); + featureGUI->deserialize(featureConfig.m_config); + featureGUI->setIndex(feature->getIndexInFeatureSet()); + workspaces[featureGUI->getWorkspaceIndex()]->addToMdiArea((QMdiSubWindow*) featureGUI); + featureGUI->restoreGeometry(featureGUI->getGeometryBytes()); } } } @@ -187,6 +255,8 @@ void FeatureUISet::saveFeatureSetSettings(FeatureSetPreset *preset) qDebug("FeatureUISet::saveFeatureSetSettings: saving feature [%s]", qPrintable(m_featureInstanceRegistrations.at(i).m_feature->getURI()) ); + FeatureGUI *featureGUI = m_featureInstanceRegistrations.at(i).m_gui; + featureGUI->setGeometryBytes(featureGUI->saveGeometry()); preset->addFeature( m_featureInstanceRegistrations.at(i).m_feature->getURI(), m_featureInstanceRegistrations.at(i).m_gui->serialize() diff --git a/sdrgui/feature/featureuiset.h b/sdrgui/feature/featureuiset.h index b82ff1e82..372a3cb3e 100644 --- a/sdrgui/feature/featureuiset.h +++ b/sdrgui/feature/featureuiset.h @@ -46,13 +46,22 @@ public: void deleteFeature(int featureIndex); const Feature *getFeatureAt(int featureIndex) const; Feature *getFeatureAt(int featureIndex); + const FeatureGUI *getFeatureGuiAt(int featureIndex) const; + FeatureGUI *getFeatureGuiAt(int featureIndex); void loadFeatureSetSettings( const FeatureSetPreset* preset, PluginAPI *pluginAPI, WebAPIAdapterInterface *apiAdapter, Workspace *workspace ); + void loadFeatureSetSettings( + const FeatureSetPreset* preset, + PluginAPI *pluginAPI, + WebAPIAdapterInterface *apiAdapter, + QList& workspaces + ); void saveFeatureSetSettings(FeatureSetPreset* preset); + void freeFeatures(); private: struct FeatureInstanceRegistration @@ -79,7 +88,6 @@ private: int m_featureTabIndex; FeatureSet *m_featureSet; - void freeFeatures(); private slots: void handleClosingFeatureGUI(FeatureGUI *featureGUI); diff --git a/sdrgui/gui/commandsdialog.cpp b/sdrgui/gui/commandsdialog.cpp index 6efab2cb5..faae90c80 100644 --- a/sdrgui/gui/commandsdialog.cpp +++ b/sdrgui/gui/commandsdialog.cpp @@ -50,10 +50,9 @@ void CommandsDialog::populateTree() { MainCore::instance()->m_settings.sortCommands(); ui->commandTree->clear(); - QTreeWidgetItem *treeItem; for (int i = 0; i < MainCore::instance()->m_settings.getCommandCount(); ++i) { - treeItem = addCommandToTree(MainCore::instance()->m_settings.getCommand(i)); + addCommandToTree(MainCore::instance()->m_settings.getCommand(i)); } } @@ -222,11 +221,6 @@ void CommandsDialog::on_commandOutput_clicked() } } -void CommandsDialog::on_commandsSave_clicked() -{ - MainCore::instance()->m_settings.save(); -} - void CommandsDialog::on_commandDelete_clicked() { QTreeWidgetItem* item = ui->commandTree->currentItem(); diff --git a/sdrgui/gui/commandsdialog.h b/sdrgui/gui/commandsdialog.h index 508bf97e4..30655b701 100644 --- a/sdrgui/gui/commandsdialog.h +++ b/sdrgui/gui/commandsdialog.h @@ -60,7 +60,6 @@ private slots: void on_commandEdit_clicked(); void on_commandRun_clicked(); void on_commandOutput_clicked(); - void on_commandsSave_clicked(); void on_commandDelete_clicked(); void on_commandKeyboardConnect_toggled(bool checked); }; diff --git a/sdrgui/gui/commandsdialog.ui b/sdrgui/gui/commandsdialog.ui index 10e606ee3..91dc4183f 100644 --- a/sdrgui/gui/commandsdialog.ui +++ b/sdrgui/gui/commandsdialog.ui @@ -123,20 +123,6 @@ - - - - Save commands in settings - - - - - - - :/save.png:/save.png - - - @@ -179,6 +165,9 @@ + + false + Toggle keyboard to command connection diff --git a/sdrgui/gui/configurationsdialog.cpp b/sdrgui/gui/configurationsdialog.cpp new file mode 100644 index 000000000..eb9266ded --- /dev/null +++ b/sdrgui/gui/configurationsdialog.cpp @@ -0,0 +1,403 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "gui/addpresetdialog.h" +#include "configurationsdialog.h" +#include "ui_configurationsdialog.h" + +#include "settings/configuration.h" + +ConfigurationsDialog::ConfigurationsDialog(QWidget* parent) : + QDialog(parent), + ui(new Ui::ConfigurationsDialog) +{ + ui->setupUi(this); +} + +ConfigurationsDialog::~ConfigurationsDialog() +{ + delete ui; +} + +void ConfigurationsDialog::populateTree() +{ + if (!m_configurations) { + return; + } + + QList::const_iterator it = m_configurations->begin(); + int middleIndex = m_configurations->size() / 2; + QTreeWidgetItem *treeItem; + ui->configurationsTree->clear(); + + for (int i = 0; it != m_configurations->end(); ++it, i++) + { + treeItem = addConfigurationToTree(*it); + + if (i == middleIndex) { + ui->configurationsTree->setCurrentItem(treeItem); + } + } + + updateConfigurationControls(); +} + +QTreeWidgetItem* ConfigurationsDialog::addConfigurationToTree(const Configuration* configuration) +{ + QTreeWidgetItem* group = nullptr; + + for (int i = 0; i < ui->configurationsTree->topLevelItemCount(); i++) + { + if (ui->configurationsTree->topLevelItem(i)->text(0) == configuration->getGroup()) + { + group = ui->configurationsTree->topLevelItem(i); + break; + } + } + + if (!group) + { + QStringList sl; + sl.append(configuration->getGroup()); + group = new QTreeWidgetItem(ui->configurationsTree, sl, PGroup); + group->setFirstColumnSpanned(true); + group->setExpanded(true); + ui->configurationsTree->sortByColumn(0, Qt::AscendingOrder); + } + + QStringList sl; + sl.append(configuration->getDescription()); + QTreeWidgetItem* item = new QTreeWidgetItem(group, sl, PItem); // description column + item->setTextAlignment(0, Qt::AlignLeft); + item->setData(0, Qt::UserRole, QVariant::fromValue(configuration)); + + updateConfigurationControls(); + return item; +} + +void ConfigurationsDialog::updateConfigurationControls() +{ + ui->configurationsTree->resizeColumnToContents(0); + + if (ui->configurationsTree->currentItem()) + { + ui->configurationDelete->setEnabled(true); + ui->configurationLoad->setEnabled(true); + } + else + { + ui->configurationDelete->setEnabled(false); + ui->configurationLoad->setEnabled(false); + } +} + +void ConfigurationsDialog::on_configurationSave_clicked() +{ + QStringList groups; + QString group; + QString description = ""; + + for (int i = 0; i < ui->configurationsTree->topLevelItemCount(); i++) { + groups.append(ui->configurationsTree->topLevelItem(i)->text(0)); + } + + QTreeWidgetItem* item = ui->configurationsTree->currentItem(); + + if (item) + { + if (item->type() == PGroup) + { + group = item->text(0); + } + else if (item->type() == PItem) + { + group = item->parent()->text(0); + description = item->text(0); + } + } + + AddPresetDialog dlg(groups, group, this); + + if (description.length() > 0) { + dlg.setDescription(description); + } + + if (dlg.exec() == QDialog::Accepted) + { + Configuration* configuration = newConfiguration(dlg.group(), dlg.description()); + emit saveConfiguration(configuration); + ui->configurationsTree->setCurrentItem(addConfigurationToTree(configuration)); + } + + sortConfigurations(); +} + +void ConfigurationsDialog::on_configurationUpdate_clicked() +{ + QTreeWidgetItem* item = ui->configurationsTree->currentItem(); + const Configuration* changedConfiguration = nullptr; + + if (item) + { + if( item->type() == PItem) + { + const Configuration* configuration = qvariant_cast(item->data(0, Qt::UserRole)); + + if (configuration) + { + Configuration* configuration_mod = const_cast(configuration); + emit saveConfiguration(configuration_mod); + changedConfiguration = configuration; + } + } + } + + sortConfigurations(); + ui->configurationsTree->clear(); + + for (int i = 0; i < m_configurations->size(); ++i) + { + QTreeWidgetItem *item_x = addConfigurationToTree(m_configurations->at(i)); + const Configuration* configuration_x = qvariant_cast(item_x->data(0, Qt::UserRole)); + + if (changedConfiguration && (configuration_x == changedConfiguration)) { // set cursor on changed configuration + ui->configurationsTree->setCurrentItem(item_x); + } + } +} + +void ConfigurationsDialog::on_configurationEdit_clicked() +{ + QTreeWidgetItem* item = ui->configurationsTree->currentItem(); + QStringList groups; + bool change = false; + const Configuration *changedConfiguration = nullptr; + QString newGroupName; + + for (int i = 0; i < ui->configurationsTree->topLevelItemCount(); i++) { + groups.append(ui->configurationsTree->topLevelItem(i)->text(0)); + } + + if (item) + { + if (item->type() == PItem) + { + const Configuration* configuration = qvariant_cast(item->data(0, Qt::UserRole)); + AddPresetDialog dlg(groups, configuration->getGroup(), this); + dlg.setDescription(configuration->getDescription()); + + if (dlg.exec() == QDialog::Accepted) + { + Configuration* configuration_mod = const_cast(configuration); + configuration_mod->setGroup(dlg.group()); + configuration_mod->setDescription(dlg.description()); + change = true; + changedConfiguration = configuration; + } + } + else if (item->type() == PGroup) + { + AddPresetDialog dlg(groups, item->text(0), this); + dlg.showGroupOnly(); + dlg.setDialogTitle("Edit configuration group"); + + if (dlg.exec() == QDialog::Accepted) + { + renameConfigurationGroup(item->text(0), dlg.group()); + newGroupName = dlg.group(); + change = true; + } + } + } + + if (change) + { + sortConfigurations(); + ui->configurationsTree->clear(); + + for (int i = 0; i < m_configurations->size(); ++i) + { + QTreeWidgetItem *item_x = addConfigurationToTree(m_configurations->at(i)); + const Configuration* configuration_x = qvariant_cast(item_x->data(0, Qt::UserRole)); + + if (changedConfiguration && (configuration_x == changedConfiguration)) { // set cursor on changed configuration + ui->configurationsTree->setCurrentItem(item_x); + } + } + + if (!changedConfiguration) // on group name change set cursor on the group that has been changed + { + for(int i = 0; i < ui->configurationsTree->topLevelItemCount(); i++) + { + QTreeWidgetItem* item = ui->configurationsTree->topLevelItem(i); + + if (item->text(0) == newGroupName) { + ui->configurationsTree->setCurrentItem(item); + } + } + } + } +} + +void ConfigurationsDialog::on_configurationDelete_clicked() +{ + QTreeWidgetItem* item = ui->configurationsTree->currentItem(); + + if (item == 0) + { + updateConfigurationControls(); + return; + } + else + { + if (item->type() == PItem) + { + const Configuration* configuration = qvariant_cast(item->data(0, Qt::UserRole)); + + if (configuration) + { + if ( + QMessageBox::question( + this, + tr("Delete Configuration"), + tr("Do you want to delete configuration '%1'?").arg(configuration->getDescription()), + QMessageBox::No | QMessageBox::Yes, + QMessageBox::No + ) == QMessageBox::Yes + ) + { + delete item; + deleteConfiguration(configuration); + } + } + } + else if (item->type() == PGroup) + { + if ( + QMessageBox::question( + this, + tr("Delete configuration group"), + tr("Do you want to delete configuration group '%1'?").arg(item->text(0)), + QMessageBox::No | QMessageBox::Yes, + QMessageBox::No + ) == QMessageBox::Yes + ) + { + deleteConfigurationGroup(item->text(0)); + + ui->configurationsTree->clear(); + + for (int i = 0; i < m_configurations->size(); ++i) { + addConfigurationToTree(m_configurations->at(i)); + } + } + } + } +} + +void ConfigurationsDialog::on_configurationLoad_clicked() +{ + qDebug() << "ConfigurationsDialog::on_configurationLoad_clicked"; + + QTreeWidgetItem* item = ui->configurationsTree->currentItem(); + + if (!item) + { + qDebug("ConfigurationsDialog::on_configurationLoad_clicked: item null"); + updateConfigurationControls(); + return; + } + + const Configuration* configuration = qvariant_cast(item->data(0, Qt::UserRole)); + + if (!configuration) + { + qDebug("ConfigurationsDialog::on_configurationLoad_clicked: configuration null"); + return; + } + + emit loadConfiguration(configuration); +} + +void ConfigurationsDialog::on_configurationTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) +{ + (void) current; + (void) previous; + updateConfigurationControls(); +} + +void ConfigurationsDialog::on_configurationTree_itemActivated(QTreeWidgetItem *item, int column) +{ + (void) item; + (void) column; + on_configurationLoad_clicked(); +} + +Configuration* ConfigurationsDialog::newConfiguration(const QString& group, const QString& description) +{ + Configuration* configuration = new Configuration(); + configuration->setGroup(group); + configuration->setDescription(description); + addConfiguration(configuration); + return configuration; +} + +void ConfigurationsDialog::addConfiguration(Configuration *configuration) +{ + m_configurations->append(configuration); +} + +void ConfigurationsDialog::sortConfigurations() +{ + std::sort(m_configurations->begin(), m_configurations->end(), Configuration::configCompare); +} + +void ConfigurationsDialog::renameConfigurationGroup(const QString& oldGroupName, const QString& newGroupName) +{ + for (int i = 0; i < m_configurations->size(); i++) + { + if (m_configurations->at(i)->getGroup() == oldGroupName) + { + Configuration *configuration_mod = const_cast(m_configurations->at(i)); + configuration_mod->setGroup(newGroupName); + } + } +} + +void ConfigurationsDialog::deleteConfiguration(const Configuration* configuration) +{ + m_configurations->removeAll((Configuration*) configuration); + delete (Configuration*) configuration; +} + +void ConfigurationsDialog::deleteConfigurationGroup(const QString& groupName) +{ + QList::iterator it = m_configurations->begin(); + + while (it != m_configurations->end()) + { + if ((*it)->getGroup() == groupName) { + it = m_configurations->erase(it); + } else { + ++it; + } + } +} diff --git a/sdrgui/gui/configurationsdialog.h b/sdrgui/gui/configurationsdialog.h new file mode 100644 index 000000000..12489e533 --- /dev/null +++ b/sdrgui/gui/configurationsdialog.h @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_CONFIGURATIONSDIALOG_H_ +#define SDRGUI_GUI_CONFIGURATIONSDIALOG_H_ + +#include +#include +#include + +#include "export.h" + +class Configuration; +class FeatureUISet; +class WebAPIAdapterInterface; +class PluginAPI; +class Workspace; + +namespace Ui { + class ConfigurationsDialog; +} + +class SDRGUI_API ConfigurationsDialog : public QDialog { + Q_OBJECT +public: + explicit ConfigurationsDialog(QWidget* parent = nullptr); + ~ConfigurationsDialog(); + void setConfigurations(QList* configurations) { m_configurations = configurations; } + void populateTree(); + +private: + enum { + PGroup, + PItem + }; + + Ui::ConfigurationsDialog* ui; + QList *m_configurations; + + QTreeWidgetItem* addConfigurationToTree(const Configuration* configuration); + void updateConfigurationControls(); + Configuration* newConfiguration(const QString& group, const QString& description); + void addConfiguration(Configuration *configuration); + void sortConfigurations(); + void renameConfigurationGroup(const QString& oldGroupName, const QString& newGroupName); + void deleteConfiguration(const Configuration* configuration); + void deleteConfigurationGroup(const QString& groupName); + +private slots: + void on_configurationSave_clicked(); + void on_configurationUpdate_clicked(); + void on_configurationEdit_clicked(); + void on_configurationDelete_clicked(); + void on_configurationLoad_clicked(); + void on_configurationTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + void on_configurationTree_itemActivated(QTreeWidgetItem *item, int column); + +signals: + void saveConfiguration(Configuration*); + void loadConfiguration(const Configuration*); +}; + +#endif // SDRGUI_GUI_CONFIGURATIONSDIALOG_H_ diff --git a/sdrgui/gui/configurationsdialog.ui b/sdrgui/gui/configurationsdialog.ui new file mode 100644 index 000000000..d7938bdcc --- /dev/null +++ b/sdrgui/gui/configurationsdialog.ui @@ -0,0 +1,244 @@ + + + ConfigurationsDialog + + + + 0 + 0 + 392 + 414 + + + + + Liberation Sans + 9 + + + + Configurations + + + + + 40 + 380 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + 0 + 10 + 392 + 310 + + + + + + + List of configurations + + + 5 + + + true + + + 1 + + + 5 + + + + Description + + + + + + + + + + 0 + 330 + 392 + 34 + + + + + + + Save current workspaces configuration as new configuration + + + ... + + + + :/create.png:/create.png + + + + 16 + 16 + + + + + + + + Update selected configuration with current workspaces configuration + + + ... + + + + :/recycle.png:/recycle.png + + + + 16 + 16 + + + + + + + + Edit configuration details + + + + + + + :/edit.png:/edit.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Delete selected configuration + + + ... + + + + :/bin.png:/bin.png + + + + 16 + 16 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Load selected configuration + + + ... + + + + :/load.png:/load.png + + + + 16 + 16 + + + + + + + + + + + + + buttonBox + accepted() + ConfigurationsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + ConfigurationsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/sdrgui/gui/featurepresetsdialog.cpp b/sdrgui/gui/featurepresetsdialog.cpp index 9d842ac07..6458a43e1 100644 --- a/sdrgui/gui/featurepresetsdialog.cpp +++ b/sdrgui/gui/featurepresetsdialog.cpp @@ -21,8 +21,10 @@ #include "gui/addpresetdialog.h" #include "feature/featureuiset.h" -#include "featurepresetsdialog.h" #include "settings/featuresetpreset.h" +#include "maincore.h" + +#include "featurepresetsdialog.h" #include "ui_featurepresetsdialog.h" FeaturePresetsDialog::FeaturePresetsDialog(QWidget* parent) : @@ -31,7 +33,8 @@ FeaturePresetsDialog::FeaturePresetsDialog(QWidget* parent) : m_featureSetPresets(nullptr), m_featureUISet(nullptr), m_pluginAPI(nullptr), - m_apiAdapter(nullptr) + m_apiAdapter(nullptr), + m_presetLoaded(false) { ui->setupUi(this); } @@ -188,10 +191,6 @@ void FeaturePresetsDialog::on_presetUpdate_clicked() } } -void FeaturePresetsDialog::on_settingsSave_clicked() -{ -} - void FeaturePresetsDialog::on_presetEdit_clicked() { QTreeWidgetItem* item = ui->presetsTree->currentItem(); @@ -376,6 +375,7 @@ void FeaturePresetsDialog::loadPresetSettings(const FeatureSetPreset* preset) qPrintable(preset->getDescription())); m_featureUISet->loadFeatureSetSettings(preset, m_pluginAPI, m_apiAdapter, m_workspace); + m_presetLoaded = true; } void FeaturePresetsDialog::sortFeatureSetPresets() diff --git a/sdrgui/gui/featurepresetsdialog.h b/sdrgui/gui/featurepresetsdialog.h index 7785be0f2..1addbf404 100644 --- a/sdrgui/gui/featurepresetsdialog.h +++ b/sdrgui/gui/featurepresetsdialog.h @@ -46,6 +46,7 @@ public: void setWebAPIAdapter(WebAPIAdapterInterface *apiAdapter) { m_apiAdapter = apiAdapter; } void setWorkspace(Workspace *workspace) { m_workspace = workspace; } void populateTree(); + bool wasPresetLoaded() const { return m_presetLoaded; } private: enum { @@ -59,6 +60,7 @@ private: PluginAPI *m_pluginAPI; WebAPIAdapterInterface *m_apiAdapter; Workspace *m_workspace; + bool m_presetLoaded; QTreeWidgetItem* addPresetToTree(const FeatureSetPreset* preset); void updatePresetControls(); @@ -74,7 +76,6 @@ private: private slots: void on_presetSave_clicked(); void on_presetUpdate_clicked(); - void on_settingsSave_clicked(); void on_presetEdit_clicked(); void on_presetDelete_clicked(); void on_presetLoad_clicked(); diff --git a/sdrgui/gui/featurepresetsdialog.ui b/sdrgui/gui/featurepresetsdialog.ui index 55de482eb..1ee9c22f2 100644 --- a/sdrgui/gui/featurepresetsdialog.ui +++ b/sdrgui/gui/featurepresetsdialog.ui @@ -118,26 +118,6 @@ - - - - Save the current settings (inc. presets) - - - ... - - - - :/save.png:/save.png - - - - 16 - 16 - - - - diff --git a/sdrgui/gui/workspace.cpp b/sdrgui/gui/workspace.cpp index 3509a6810..fc7eed526 100644 --- a/sdrgui/gui/workspace.cpp +++ b/sdrgui/gui/workspace.cpp @@ -37,6 +37,7 @@ Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) : setWidget(m_mdi); setWindowTitle(tr("W%1").arg(m_index)); + setObjectName(tr("W%1").arg(m_index)); m_titleBar = new QWidget(); m_titleBarLayout = new QHBoxLayout(); @@ -105,7 +106,7 @@ Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) : m_normalButton->setFixedSize(20, 20); m_closeButton = new QPushButton(); - QIcon closeIcon(":/cross.png"); + QIcon closeIcon(":/hide.png"); m_closeButton->setIcon(closeIcon); m_closeButton->setToolTip("Hide workspace"); m_closeButton->setFixedSize(20, 20); @@ -269,3 +270,18 @@ void Workspace::removeFromMdiArea(QMdiSubWindow *sub) { m_mdi->removeSubWindow(sub); } + +int Workspace::getNumberOfSubWindows() const +{ + return m_mdi->subWindowList().size(); +} + +QByteArray Workspace::saveMdiGeometry() +{ + return qCompress(m_mdi->saveGeometry()); +} + +void Workspace::restoreMdiGeometry(const QByteArray& blob) +{ + m_mdi->restoreGeometry(qUncompress(blob)); +} diff --git a/sdrgui/gui/workspace.h b/sdrgui/gui/workspace.h index 56b307fad..3944ddfad 100644 --- a/sdrgui/gui/workspace.h +++ b/sdrgui/gui/workspace.h @@ -44,6 +44,9 @@ public: void addAvailableFeatures(const QStringList& featureNames) { m_featureAddDialog.addFeatureNames(featureNames); } void addToMdiArea(QMdiSubWindow *sub); void removeFromMdiArea(QMdiSubWindow *sub); + int getNumberOfSubWindows() const; + QByteArray saveMdiGeometry(); + void restoreMdiGeometry(const QByteArray& blob); private: int m_index; diff --git a/sdrgui/mainwindow.cpp b/sdrgui/mainwindow.cpp index a98ae3a54..65a464ee5 100644 --- a/sdrgui/mainwindow.cpp +++ b/sdrgui/mainwindow.cpp @@ -66,6 +66,7 @@ #include "gui/workspace.h" #include "gui/featurepresetsdialog.h" #include "gui/commandsdialog.h" +#include "gui/configurationsdialog.h" #include "dsp/dspengine.h" #include "dsp/spectrumvis.h" #include "dsp/dspcommands.h" @@ -263,6 +264,7 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse // loadPresetSettings(m_mainCore->m_settings.getWorkingPreset(), 0); m_apiAdapter = new WebAPIAdapter(); // loadFeatureSetPresetSettings(m_mainCore->m_settings.getWorkingFeatureSetPreset(), 0); + loadConfiguration(m_mainCore->m_settings.getWorkingConfiguration()); splash->showStatusMessage("update preset controls...", Qt::white); qDebug() << "MainWindow::MainWindow: update preset controls..."; @@ -324,6 +326,7 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse MainWindow::~MainWindow() { + m_mainCore->m_settings.save(); m_apiServer->stop(); delete m_apiServer; delete m_requestMapper; @@ -773,8 +776,8 @@ void MainWindow::loadSettings() m_mainCore->m_settings.load(); m_mainCore->m_settings.sortPresets(); - int middleIndex = m_mainCore->m_settings.getPresetCount() / 2; - QTreeWidgetItem *treeItem; + // int middleIndex = m_mainCore->m_settings.getPresetCount() / 2; + // QTreeWidgetItem *treeItem; // for (int i = 0; i < m_mainCore->m_settings.getPresetCount(); ++i) // { @@ -787,10 +790,10 @@ void MainWindow::loadSettings() m_mainCore->m_settings.sortCommands(); - for (int i = 0; i < m_mainCore->m_settings.getCommandCount(); ++i) - { - treeItem = addCommandToTree(m_mainCore->m_settings.getCommand(i)); - } + // for (int i = 0; i < m_mainCore->m_settings.getCommandCount(); ++i) + // { + // treeItem = addCommandToTree(m_mainCore->m_settings.getCommand(i)); + // } m_mainCore->setLoggingOptions(); } @@ -894,8 +897,64 @@ void MainWindow::saveFeatureSetPresetSettings(FeatureSetPreset* preset, int feat featureUI->saveFeatureSetSettings(preset); } -void MainWindow::saveCommandSettings() +void MainWindow::loadConfiguration(const Configuration *configuration) { + qDebug("MainWindow::loadConfiguration: configuration [%s | %s] %d workspaces", + qPrintable(configuration->getGroup()), + qPrintable(configuration->getDescription()), + configuration->getNumberOfWorkspaces() + ); + + // Wipe out everything first + + // Features + m_featureUIs[0]->freeFeatures(); + // Workspaces + for (const auto& workspace : m_workspaces) { + delete workspace; + } + m_workspaces.clear(); + + // Reconstruct + + // Workspaces + for (int i = 0; i < configuration->getNumberOfWorkspaces(); i++) { + addWorkspace(); + } + // Features + m_featureUIs[0]->loadFeatureSetSettings(&configuration->getFeatureSetPreset(), m_pluginManager->getPluginAPI(), m_apiAdapter, m_workspaces); + + for (int i = 0; i < m_featureUIs[0]->getNumberOfFeatures(); i++) + { + FeatureGUI *gui = m_featureUIs[0]->getFeatureGuiAt(i); + QObject::connect( + gui, + &FeatureGUI::moveToWorkspace, + this, + [=](int wsIndexDest){ this->featureMove(gui, wsIndexDest); } + ); + } + + // Lastly restore workspaces geometry + for (int i = 0; i < configuration->getNumberOfWorkspaces(); i++) { + m_workspaces[i]->restoreGeometry(configuration->getWorkspaceGeometries()[i]); + } +} + +void MainWindow::saveConfiguration(Configuration *configuration) +{ + qDebug("MainWindow::saveConfiguration: configuration [%s | %s] %d workspaces", + qPrintable(configuration->getGroup()), + qPrintable(configuration->getDescription()), + m_workspaces.size() + ); + + configuration->clearData(); + m_featureUIs[0]->saveFeatureSetSettings(&configuration->getFeatureSetPreset()); + + for (const auto& workspace : m_workspaces) { + configuration->getWorkspaceGeometries().push_back(workspace->saveGeometry()); + } } QString MainWindow::openGLVersion() @@ -950,8 +1009,14 @@ void MainWindow::createMenuBar() QAction *viewAllWorkspacesAction = workspacesMenu->addAction("View all"); viewAllWorkspacesAction->setToolTip("View all workspaces"); QObject::connect(viewAllWorkspacesAction, &QAction::triggered, this, &MainWindow::viewAllWorkspaces); + QAction *removeEmptyWorkspacesAction = workspacesMenu->addAction("Remove empty"); + removeEmptyWorkspacesAction->setToolTip("Remove empty workspaces"); + QObject::connect(removeEmptyWorkspacesAction, &QAction::triggered, this, &MainWindow::removeEmptyWorkspaces); QMenu *preferencesMenu = menuBar->addMenu("Preferences"); + QAction *configurationsAction = preferencesMenu->addAction("Configurations"); + configurationsAction->setToolTip("Manage configurations"); + QObject::connect(configurationsAction, &QAction::triggered, this, &MainWindow::on_action_Configurations_triggered); QAction *audioAction = preferencesMenu->addAction("Audio"); audioAction->setToolTip("Audio preferences"); QObject::connect(audioAction, &QAction::triggered, this, &MainWindow::on_action_Audio_triggered); @@ -977,6 +1042,9 @@ void MainWindow::createMenuBar() QAction *commandsAction = preferencesMenu->addAction("Commands"); commandsAction->setToolTip("External commands dialog"); QObject::connect(commandsAction, &QAction::triggered, this, &MainWindow::on_action_commands_triggered); + QAction *saveAllAction = preferencesMenu->addAction("Save all"); + saveAllAction->setToolTip("Save all current settings"); + QObject::connect(saveAllAction, &QAction::triggered, this, &MainWindow::on_action_saveAll_triggered); QMenu *helpMenu = menuBar->addMenu("Help"); QAction *quickStartAction = helpMenu->addAction("Quick start"); @@ -1021,7 +1089,8 @@ void MainWindow::closeEvent(QCloseEvent *closeEvent) // savePresetSettings(m_mainCore->m_settings.getWorkingPreset(), 0); // saveFeatureSetPresetSettings(m_mainCore->m_settings.getWorkingFeatureSetPreset(), 0); - // m_mainCore->m_settings.save(); + saveConfiguration(m_mainCore->m_settings.getWorkingConfiguration()); + m_mainCore->m_settings.save(); // while (m_deviceUIs.size() > 0) // { @@ -1128,6 +1197,7 @@ void MainWindow::applySettings() { // loadPresetSettings(m_mainCore->m_settings.getWorkingPreset(), 0); // loadFeatureSetPresetSettings(m_mainCore->m_settings.getWorkingFeatureSetPreset(), 0); + loadConfiguration(m_mainCore->m_settings.getWorkingConfiguration()); m_mainCore->m_settings.sortPresets(); int middleIndex = m_mainCore->m_settings.getPresetCount() / 2; @@ -1420,6 +1490,24 @@ void MainWindow::viewAllWorkspaces() } } +void MainWindow::removeEmptyWorkspaces() +{ + QList::iterator it = m_workspaces.begin(); + + while (it != m_workspaces.end()) + { + if ((*it)->getNumberOfSubWindows() == 0) + { + removeDockWidget(*it); + it = m_workspaces.erase(it); + } + else + { + ++it; + } + } +} + void MainWindow::on_action_View_Fullscreen_toggled(bool checked) { if(checked) { @@ -1674,11 +1762,13 @@ void MainWindow::on_presetImport_clicked() // } } -void MainWindow::on_settingsSave_clicked() +void MainWindow::on_action_saveAll_triggered() { // savePresetSettings(m_mainCore->m_settings.getWorkingPreset(), ui->tabInputsView->currentIndex()); // saveFeatureSetPresetSettings(m_mainCore->m_settings.getWorkingFeatureSetPreset(), ui->tabFeatures->currentIndex()); + saveConfiguration(m_mainCore->m_settings.getWorkingConfiguration()); m_mainCore->m_settings.save(); + QMessageBox::information(this, tr("Done"), tr("All curent settings saved")); } void MainWindow::on_presetLoad_clicked() @@ -1777,6 +1867,26 @@ void MainWindow::on_action_Loaded_Plugins_triggered() pluginsDialog.exec(); } +void MainWindow::on_action_Configurations_triggered() +{ + ConfigurationsDialog dialog(this); + dialog.setConfigurations(m_mainCore->m_settings.getConfigurations()); + dialog.populateTree(); + QObject::connect( + &dialog, + &ConfigurationsDialog::saveConfiguration, + this, + &MainWindow::saveConfiguration + ); + QObject::connect( + &dialog, + &ConfigurationsDialog::loadConfiguration, + this, + &MainWindow::loadConfiguration + ); + dialog.exec(); +} + void MainWindow::on_action_Audio_triggered() { AudioDialogX audioDialog(m_dspEngine->getAudioDeviceManager(), this); @@ -2329,6 +2439,20 @@ void MainWindow::openFeaturePresetsDialog(QPoint p, Workspace *workspace) dialog.populateTree(); dialog.move(p); dialog.exec(); + + if (dialog.wasPresetLoaded()) + { + for (int i = 0; i < m_featureUIs[0]->getNumberOfFeatures(); i++) + { + FeatureGUI *gui = m_featureUIs[0]->getFeatureGuiAt(i); + QObject::connect( + gui, + &FeatureGUI::moveToWorkspace, + this, + [=](int wsIndexDest){ this->featureMove(gui, wsIndexDest); } + ); + } + } } void MainWindow::deleteFeature(int featureSetIndex, int featureIndex) diff --git a/sdrgui/mainwindow.h b/sdrgui/mainwindow.h index 13f077016..0481bc8e0 100644 --- a/sdrgui/mainwindow.h +++ b/sdrgui/mainwindow.h @@ -128,7 +128,6 @@ private: void savePresetSettings(Preset* preset, int tabIndex); void loadFeatureSetPresetSettings(const FeatureSetPreset* preset, int featureSetIndex, Workspace *workspace); void saveFeatureSetPresetSettings(FeatureSetPreset* preset, int featureSetIndex); - void saveCommandSettings(); QString openGLVersion(); void createMenuBar(); @@ -162,6 +161,9 @@ private slots: void updateStatus(); void addWorkspace(); void viewAllWorkspaces(); + void removeEmptyWorkspaces(); + void loadConfiguration(const Configuration *configuration); + void saveConfiguration(Configuration *configuration); void on_action_View_Fullscreen_toggled(bool checked); void on_presetSave_clicked(); @@ -169,11 +171,12 @@ private slots: void on_presetEdit_clicked(); void on_presetExport_clicked(); void on_presetImport_clicked(); - void on_settingsSave_clicked(); + void on_action_saveAll_triggered(); void on_presetLoad_clicked(); void on_presetDelete_clicked(); void on_presetTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); void on_presetTree_itemActivated(QTreeWidgetItem *item, int column); + void on_action_Configurations_triggered(); void on_action_Audio_triggered(); void on_action_Logging_triggered(); void on_action_FFT_triggered(); diff --git a/sdrgui/resources/hide.png b/sdrgui/resources/hide.png new file mode 100644 index 000000000..d92ceae15 Binary files /dev/null and b/sdrgui/resources/hide.png differ diff --git a/sdrgui/resources/res.qrc b/sdrgui/resources/res.qrc index 73b00a400..bb851fc62 100644 --- a/sdrgui/resources/res.qrc +++ b/sdrgui/resources/res.qrc @@ -129,6 +129,7 @@ help.png shrink.png exit.png + hide.png LiberationMono-Regular.ttf LiberationSans-Regular.ttf