diff --git a/doc/img/channel.xcf b/doc/img/channel.xcf new file mode 100644 index 000000000..61cbff543 Binary files /dev/null and b/doc/img/channel.xcf differ diff --git a/doc/img/tool.xcf b/doc/img/tool.xcf index 94adf6f71..5d181b4c1 100644 Binary files a/doc/img/tool.xcf and b/doc/img/tool.xcf differ diff --git a/plugins/samplemimo/bladerf2mimo/bladerf2mimogui.ui b/plugins/samplemimo/bladerf2mimo/bladerf2mimogui.ui index 8b862d61e..30750ed28 100644 --- a/plugins/samplemimo/bladerf2mimo/bladerf2mimogui.ui +++ b/plugins/samplemimo/bladerf2mimo/bladerf2mimogui.ui @@ -313,7 +313,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplemimo/limesdrmimo/limesdrmimogui.ui b/plugins/samplemimo/limesdrmimo/limesdrmimogui.ui index 818a5d5cd..bdc8329e5 100644 --- a/plugins/samplemimo/limesdrmimo/limesdrmimogui.ui +++ b/plugins/samplemimo/limesdrmimo/limesdrmimogui.ui @@ -336,7 +336,7 @@ Liberation Mono - 20 + 16 50 false diff --git a/plugins/samplemimo/metismiso/metismisogui.ui b/plugins/samplemimo/metismiso/metismisogui.ui index df0c87514..bf3a59e48 100644 --- a/plugins/samplemimo/metismiso/metismisogui.ui +++ b/plugins/samplemimo/metismiso/metismisogui.ui @@ -306,7 +306,7 @@ Liberation Mono - 20 + 16 50 false false diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmimogui.ui b/plugins/samplemimo/plutosdrmimo/plutosdrmimogui.ui index 5434ff697..2f0ef9104 100644 --- a/plugins/samplemimo/plutosdrmimo/plutosdrmimogui.ui +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmimogui.ui @@ -313,7 +313,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplemimo/testmi/testmigui.ui b/plugins/samplemimo/testmi/testmigui.ui index 078537460..0baf16c66 100644 --- a/plugins/samplemimo/testmi/testmigui.ui +++ b/plugins/samplemimo/testmi/testmigui.ui @@ -223,7 +223,7 @@ Liberation Mono - 20 + 16 50 false false diff --git a/plugins/samplemimo/testmosync/testmosyncgui.ui b/plugins/samplemimo/testmosync/testmosyncgui.ui index 104df588a..e80a8714b 100644 --- a/plugins/samplemimo/testmosync/testmosyncgui.ui +++ b/plugins/samplemimo/testmosync/testmosyncgui.ui @@ -131,7 +131,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplemimo/xtrxmimo/xtrxmimogui.ui b/plugins/samplemimo/xtrxmimo/xtrxmimogui.ui index c59b43367..1cf55b59d 100644 --- a/plugins/samplemimo/xtrxmimo/xtrxmimogui.ui +++ b/plugins/samplemimo/xtrxmimo/xtrxmimogui.ui @@ -336,7 +336,7 @@ Liberation Mono - 20 + 16 50 false diff --git a/plugins/samplesink/bladerf1output/bladerf1outputgui.ui b/plugins/samplesink/bladerf1output/bladerf1outputgui.ui index d8260c1d4..2c2a63bc9 100644 --- a/plugins/samplesink/bladerf1output/bladerf1outputgui.ui +++ b/plugins/samplesink/bladerf1output/bladerf1outputgui.ui @@ -128,7 +128,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesink/bladerf2output/bladerf2outputgui.ui b/plugins/samplesink/bladerf2output/bladerf2outputgui.ui index a589a1d9c..fe54b2964 100644 --- a/plugins/samplesink/bladerf2output/bladerf2outputgui.ui +++ b/plugins/samplesink/bladerf2output/bladerf2outputgui.ui @@ -128,7 +128,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesink/fileoutput/fileoutputgui.ui b/plugins/samplesink/fileoutput/fileoutputgui.ui index 82c4c8094..a6c19111a 100644 --- a/plugins/samplesink/fileoutput/fileoutputgui.ui +++ b/plugins/samplesink/fileoutput/fileoutputgui.ui @@ -131,7 +131,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesink/hackrfoutput/hackrfoutputgui.ui b/plugins/samplesink/hackrfoutput/hackrfoutputgui.ui index 8b9e1e455..b27ca6e16 100644 --- a/plugins/samplesink/hackrfoutput/hackrfoutputgui.ui +++ b/plugins/samplesink/hackrfoutput/hackrfoutputgui.ui @@ -131,7 +131,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesink/limesdroutput/limesdroutputgui.ui b/plugins/samplesink/limesdroutput/limesdroutputgui.ui index 7fe2c2758..32b2efb93 100644 --- a/plugins/samplesink/limesdroutput/limesdroutputgui.ui +++ b/plugins/samplesink/limesdroutput/limesdroutputgui.ui @@ -128,7 +128,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputgui.ui b/plugins/samplesink/plutosdroutput/plutosdroutputgui.ui index 8dc5b657d..2220656be 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutputgui.ui +++ b/plugins/samplesink/plutosdroutput/plutosdroutputgui.ui @@ -128,7 +128,7 @@ Liberation Mono - 20 + 16 50 false diff --git a/plugins/samplesink/soapysdroutput/soapysdroutputgui.ui b/plugins/samplesink/soapysdroutput/soapysdroutputgui.ui index 985bb5c90..4ae211477 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputgui.ui +++ b/plugins/samplesink/soapysdroutput/soapysdroutputgui.ui @@ -116,7 +116,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesink/testsink/testsinkgui.ui b/plugins/samplesink/testsink/testsinkgui.ui index 1d491e993..65c8354e8 100644 --- a/plugins/samplesink/testsink/testsinkgui.ui +++ b/plugins/samplesink/testsink/testsinkgui.ui @@ -131,7 +131,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesink/usrpoutput/usrpoutputgui.ui b/plugins/samplesink/usrpoutput/usrpoutputgui.ui index 3e0d3ba25..fb66c98d9 100644 --- a/plugins/samplesink/usrpoutput/usrpoutputgui.ui +++ b/plugins/samplesink/usrpoutput/usrpoutputgui.ui @@ -138,7 +138,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesink/xtrxoutput/xtrxoutputgui.ui b/plugins/samplesink/xtrxoutput/xtrxoutputgui.ui index c04dd6267..349c33dda 100644 --- a/plugins/samplesink/xtrxoutput/xtrxoutputgui.ui +++ b/plugins/samplesink/xtrxoutput/xtrxoutputgui.ui @@ -128,7 +128,7 @@ Liberation Mono - 20 + 16 50 false diff --git a/plugins/samplesource/airspy/airspygui.ui b/plugins/samplesource/airspy/airspygui.ui index 1cf50415d..cd4ea6f06 100644 --- a/plugins/samplesource/airspy/airspygui.ui +++ b/plugins/samplesource/airspy/airspygui.ui @@ -122,7 +122,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/airspyhf/airspyhfgui.ui b/plugins/samplesource/airspyhf/airspyhfgui.ui index 40463d73b..c19aae71c 100644 --- a/plugins/samplesource/airspyhf/airspyhfgui.ui +++ b/plugins/samplesource/airspyhf/airspyhfgui.ui @@ -122,7 +122,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/bladerf1input/bladerf1inputgui.ui b/plugins/samplesource/bladerf1input/bladerf1inputgui.ui index c0321330a..531eb3311 100644 --- a/plugins/samplesource/bladerf1input/bladerf1inputgui.ui +++ b/plugins/samplesource/bladerf1input/bladerf1inputgui.ui @@ -122,7 +122,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/bladerf2input/bladerf2inputgui.ui b/plugins/samplesource/bladerf2input/bladerf2inputgui.ui index 7ec663a32..03fd1f2e3 100644 --- a/plugins/samplesource/bladerf2input/bladerf2inputgui.ui +++ b/plugins/samplesource/bladerf2input/bladerf2inputgui.ui @@ -122,7 +122,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/fcdpro/fcdprogui.ui b/plugins/samplesource/fcdpro/fcdprogui.ui index feae1eeb4..7af12e90b 100644 --- a/plugins/samplesource/fcdpro/fcdprogui.ui +++ b/plugins/samplesource/fcdpro/fcdprogui.ui @@ -122,7 +122,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/fcdproplus/fcdproplusgui.ui b/plugins/samplesource/fcdproplus/fcdproplusgui.ui index 8c414c5ed..319ff8471 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusgui.ui +++ b/plugins/samplesource/fcdproplus/fcdproplusgui.ui @@ -122,7 +122,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/hackrfinput/hackrfinputgui.ui b/plugins/samplesource/hackrfinput/hackrfinputgui.ui index 65d063e37..d28afc6ba 100644 --- a/plugins/samplesource/hackrfinput/hackrfinputgui.ui +++ b/plugins/samplesource/hackrfinput/hackrfinputgui.ui @@ -6,8 +6,8 @@ 0 0 - 310 - 300 + 360 + 272 @@ -18,8 +18,8 @@ - 310 - 300 + 360 + 0 @@ -122,7 +122,7 @@ Liberation Mono - 20 + 16 @@ -243,7 +243,7 @@ - + Bandpass Filter auto select @@ -658,23 +658,6 @@ - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - diff --git a/plugins/samplesource/kiwisdr/kiwisdrgui.ui b/plugins/samplesource/kiwisdr/kiwisdrgui.ui index bbf6bec05..16a4c787d 100644 --- a/plugins/samplesource/kiwisdr/kiwisdrgui.ui +++ b/plugins/samplesource/kiwisdr/kiwisdrgui.ui @@ -131,7 +131,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.ui b/plugins/samplesource/limesdrinput/limesdrinputgui.ui index 2d9d98b37..8bb19d189 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.ui +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.ui @@ -128,7 +128,7 @@ Liberation Mono - 20 + 16 50 false diff --git a/plugins/samplesource/perseus/perseusgui.ui b/plugins/samplesource/perseus/perseusgui.ui index 1d457ba29..c06331a1d 100644 --- a/plugins/samplesource/perseus/perseusgui.ui +++ b/plugins/samplesource/perseus/perseusgui.ui @@ -122,7 +122,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputgui.ui b/plugins/samplesource/plutosdrinput/plutosdrinputgui.ui index 336794851..709d10937 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputgui.ui +++ b/plugins/samplesource/plutosdrinput/plutosdrinputgui.ui @@ -128,7 +128,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/rtlsdr/rtlsdrgui.ui b/plugins/samplesource/rtlsdr/rtlsdrgui.ui index d4a6d75af..df02e0cd5 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrgui.ui +++ b/plugins/samplesource/rtlsdr/rtlsdrgui.ui @@ -122,7 +122,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/sdrplay/sdrplaygui.ui b/plugins/samplesource/sdrplay/sdrplaygui.ui index e9d07e273..f22caa9a8 100644 --- a/plugins/samplesource/sdrplay/sdrplaygui.ui +++ b/plugins/samplesource/sdrplay/sdrplaygui.ui @@ -122,7 +122,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3gui.ui b/plugins/samplesource/sdrplayv3/sdrplayv3gui.ui index f4665f4f5..bbf4c43c0 100644 --- a/plugins/samplesource/sdrplayv3/sdrplayv3gui.ui +++ b/plugins/samplesource/sdrplayv3/sdrplayv3gui.ui @@ -122,7 +122,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.ui b/plugins/samplesource/soapysdrinput/soapysdrinputgui.ui index ee59b8d69..f0781845a 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.ui +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.ui @@ -116,7 +116,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/testsource/testsourcegui.ui b/plugins/samplesource/testsource/testsourcegui.ui index d5768cdd8..ce3915af9 100644 --- a/plugins/samplesource/testsource/testsourcegui.ui +++ b/plugins/samplesource/testsource/testsourcegui.ui @@ -131,7 +131,7 @@ Liberation Mono - 20 + 16 diff --git a/plugins/samplesource/usrpinput/usrpinputgui.ui b/plugins/samplesource/usrpinput/usrpinputgui.ui index 80be6c42a..bbdafa362 100644 --- a/plugins/samplesource/usrpinput/usrpinputgui.ui +++ b/plugins/samplesource/usrpinput/usrpinputgui.ui @@ -138,7 +138,7 @@ Liberation Mono - 20 + 16 50 false diff --git a/plugins/samplesource/xtrxinput/xtrxinputgui.ui b/plugins/samplesource/xtrxinput/xtrxinputgui.ui index de4b9edce..8078a54e3 100644 --- a/plugins/samplesource/xtrxinput/xtrxinputgui.ui +++ b/plugins/samplesource/xtrxinput/xtrxinputgui.ui @@ -128,7 +128,7 @@ Liberation Mono - 20 + 16 50 false diff --git a/sdrbase/device/deviceenumerator.cpp b/sdrbase/device/deviceenumerator.cpp index c0ddec020..f4ecd56c9 100644 --- a/sdrbase/device/deviceenumerator.cpp +++ b/sdrbase/device/deviceenumerator.cpp @@ -506,3 +506,92 @@ int DeviceEnumerator::getMIMOSamplingDeviceIndex(const QString& deviceId, int se return -1; } + +int DeviceEnumerator::getBestRxSamplingDeviceIndex(const QString& deviceId, const QString& deviceSerial, int deviceSequence, int deviceItemIndex) +{ + return getBestSamplingDeviceIndex(m_rxEnumeration, deviceId, deviceSerial, deviceSequence, deviceItemIndex); +} + +int DeviceEnumerator::getBestTxSamplingDeviceIndex(const QString& deviceId, const QString& deviceSerial, int deviceSequence, int deviceItemIndex) +{ + return getBestSamplingDeviceIndex(m_txEnumeration, deviceId, deviceSerial, deviceSequence, deviceItemIndex); +} + +int DeviceEnumerator::getBestMIMOSamplingDeviceIndex(const QString& deviceId, const QString& deviceSerial, int deviceSequence) +{ + return getBestSamplingDeviceIndex(m_mimoEnumeration, deviceId, deviceSerial, deviceSequence, -1); +} + +int DeviceEnumerator::getBestSamplingDeviceIndex( + const DevicesEnumeration& devicesEnumeration, + const QString& deviceId, + const QString& deviceSerial, + int deviceSequence, + int deviceItemIndex +) +{ + DevicesEnumeration::const_iterator it = devicesEnumeration.begin(); + DevicesEnumeration::const_iterator itFirstOfKind = devicesEnumeration.end(); + DevicesEnumeration::const_iterator itMatchSequence = devicesEnumeration.end(); + + for (; it != devicesEnumeration.end(); ++it) + { + if ((it->m_samplingDevice.id == deviceId) && + ( + ((deviceItemIndex < 0) || (deviceItemIndex > it->m_samplingDevice.deviceNbItems)) || // take first if item index is negative or out of range + ((deviceItemIndex <= it->m_samplingDevice.deviceNbItems) && (deviceItemIndex == it->m_samplingDevice.deviceItemIndex)) // take exact item index if in range + ) + ) + { + if (itFirstOfKind == devicesEnumeration.end()) { + itFirstOfKind = it; + } + + if (deviceSerial.isNull() || deviceSerial.isEmpty()) + { + if (it->m_samplingDevice.sequence == deviceSequence) { + break; + } + } + else + { + if (it->m_samplingDevice.serial == deviceSerial) { + break; + } else if(it->m_samplingDevice.sequence == deviceSequence) { + itMatchSequence = it; + } + } + } + } + + if (it == devicesEnumeration.end()) // no exact match + { + if (itMatchSequence != devicesEnumeration.end()) // match sequence and device type ? + { + qDebug("DeviceEnumerator::getBestSamplingDeviceIndex: sequence matched: id: %s ser: %s seq: %d", + qPrintable(itMatchSequence->m_samplingDevice.id), + qPrintable(itMatchSequence->m_samplingDevice.serial), + itMatchSequence->m_samplingDevice.sequence); + return itMatchSequence - devicesEnumeration.begin(); + } + else if (itFirstOfKind != devicesEnumeration.end()) // match just device type ? + { + qDebug("DeviceEnumerator::getBestSamplingDeviceIndex: first of kind matched: id: %s ser: %s seq: %d", + qPrintable(itFirstOfKind->m_samplingDevice.id), + qPrintable(itFirstOfKind->m_samplingDevice.serial), + itFirstOfKind->m_samplingDevice.sequence); + return itFirstOfKind - devicesEnumeration.begin(); + } + else // definitely not found ! + { + qDebug("DeviceEnumerator::getBestSamplingDeviceIndex: no match"); + return -1; + } + } + else // exact match + { + qDebug("DeviceEnumerator::getBestSamplingDeviceIndex: serial matched (exact): id: %s ser: %s", + qPrintable(it->m_samplingDevice.id), qPrintable(it->m_samplingDevice.serial)); + return it - devicesEnumeration.begin(); + } +} diff --git a/sdrbase/device/deviceenumerator.h b/sdrbase/device/deviceenumerator.h index 3ef4f0489..3cd7e68d4 100644 --- a/sdrbase/device/deviceenumerator.h +++ b/sdrbase/device/deviceenumerator.h @@ -62,6 +62,9 @@ public: int getRxSamplingDeviceIndex(const QString& deviceId, int sequence, int deviceItemIndex); int getTxSamplingDeviceIndex(const QString& deviceId, int sequence, int deviceItemIndex); int getMIMOSamplingDeviceIndex(const QString& deviceId, int sequence); + int getBestRxSamplingDeviceIndex(const QString& deviceId, const QString& serial, int sequence, int deviceItemIndex); + int getBestTxSamplingDeviceIndex(const QString& deviceId, const QString& serial, int sequence, int deviceItemIndex); + int getBestMIMOSamplingDeviceIndex(const QString& deviceId, const QString& serial, int sequence); private: struct DeviceEnumeration @@ -91,6 +94,13 @@ private: bool isRxEnumerated(const QString& deviceHwId, int deviceSequence); bool isTxEnumerated(const QString& deviceHwId, int deviceSequence); bool isMIMOEnumerated(const QString& deviceHwId, int deviceSequence); + int getBestSamplingDeviceIndex( + const DevicesEnumeration& devicesEnumeration, + const QString& deviceId, + const QString& serial, + int sequence, + int deviceItemIndex + ); }; #endif /* SDRBASE_DEVICE_DEVICEENUMERATOR_H_ */ diff --git a/sdrbase/settings/configuration.cpp b/sdrbase/settings/configuration.cpp index 91210fa91..d2ef6ebcd 100644 --- a/sdrbase/settings/configuration.cpp +++ b/sdrbase/settings/configuration.cpp @@ -44,12 +44,20 @@ QByteArray Configuration::serialize() const QByteArray b = m_featureSetPreset.serialize(); s.writeBlob(3, b); - s.writeS32(100, m_workspaceGeometries.size()); + int nitems = m_workspaceGeometries.size() < 99 ? m_workspaceGeometries.size() : 99; + s.writeS32(100, nitems); - for(int i = 0; i < m_workspaceGeometries.size(); i++) { + for (int i = 0; i < nitems; i++) { s.writeBlob(101 + i, m_workspaceGeometries[i]); } + nitems = m_deviceSetPresets.size() < 99 ? m_deviceSetPresets.size() : 99; + s.writeS32(200, nitems); + + for (int i = 0; i < nitems; i++) { + s.writeBlob(201 + i, m_deviceSetPresets[i].serialize()); + } + return s.final(); } @@ -72,15 +80,24 @@ bool Configuration::deserialize(const QByteArray& data) d.readBlob(3, &b); m_featureSetPreset.deserialize(b); - int nbWorkspaces; - d.readS32(100, &nbWorkspaces, 0); + int nitems; + d.readS32(100, &nitems, 0); - for(int i = 0; i < nbWorkspaces; i++) + for(int i = 0; i < nitems; i++) { m_workspaceGeometries.push_back(QByteArray()); d.readBlob(101 + i, &m_workspaceGeometries.back()); } + d.readS32(200, &nitems, 0); + + for (int i = 0; i < nitems; i++) + { + d.readBlob(201 + i, &b); + m_deviceSetPresets.push_back(Preset()); + m_deviceSetPresets.back().deserialize(b); + } + return true; } else @@ -97,6 +114,7 @@ int Configuration::getNumberOfWorkspaces() const void Configuration::clearData() { + m_deviceSetPresets.clear(); m_featureSetPreset.clearFeatures(); m_workspaceGeometries.clear(); } diff --git a/sdrbase/settings/configuration.h b/sdrbase/settings/configuration.h index cbdbc37ed..d08d51371 100644 --- a/sdrbase/settings/configuration.h +++ b/sdrbase/settings/configuration.h @@ -26,6 +26,7 @@ #include #include "featuresetpreset.h" +#include "preset.h" #include "export.h" class SDRBASE_API WorkspaceConfiguration { @@ -47,10 +48,12 @@ public: 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; } + FeatureSetPreset& getFeatureSetPreset() { return m_featureSetPreset; } + const FeatureSetPreset& getFeatureSetPreset() const { return m_featureSetPreset; } + QList& getDeviceSetPresets() { return m_deviceSetPresets; } + const QList& getDeviceSetPresets() const { return m_deviceSetPresets; } void clearData(); static bool configCompare(const Configuration *p1, Configuration *p2) @@ -70,6 +73,7 @@ private: QString m_description; QList m_workspaceGeometries; FeatureSetPreset m_featureSetPreset; + QList m_deviceSetPresets; }; Q_DECLARE_METATYPE(const Configuration*) diff --git a/sdrbase/settings/preset.cpp b/sdrbase/settings/preset.cpp index cc4e00f7c..4cb5b598a 100644 --- a/sdrbase/settings/preset.cpp +++ b/sdrbase/settings/preset.cpp @@ -72,6 +72,14 @@ QByteArray Preset::serialize() const s.writeBool(6, m_presetType == PresetSource); s.writeS32(7, (int) m_presetType); s.writeBool(8, m_showSpectrum); + s.writeBlob(9, m_spectrumGeometry); + s.writeS32(10, m_spectrumWorkspaceIndex); + s.writeBlob(11, m_deviceGeometry); + s.writeS32(12, m_deviceWorkspaceIndex); + s.writeString(13, m_selectedDevice.m_deviceId); + s.writeString(14, m_selectedDevice.m_deviceSerial); + s.writeS32(15, m_selectedDevice.m_deviceSequence); + s.writeS32(16, m_selectedDevice.m_deviceItemIndex); s.writeS32(20, m_deviceConfigs.size()); @@ -129,13 +137,22 @@ bool Preset::deserialize(const QByteArray& data) d.readBlob(5, &m_spectrumConfig); d.readBool(6, &tmpBool, true); d.readS32(7, &tmp, PresetSource); - d.readBool(8, &m_showSpectrum, true); m_presetType = tmp < (int) PresetSource ? PresetSource : tmp > (int) PresetMIMO ? PresetMIMO : (PresetType) tmp; if (m_presetType != PresetMIMO) { m_presetType = tmpBool ? PresetSource : PresetSink; } + d.readBool(8, &m_showSpectrum, true); + d.readBlob(9, &m_spectrumGeometry); + d.readS32(10, &m_spectrumWorkspaceIndex, 0); + d.readBlob(11, &m_deviceGeometry); + d.readS32(12, &m_deviceWorkspaceIndex, 0); + d.readString(13, &m_selectedDevice.m_deviceId); + d.readString(14, &m_selectedDevice.m_deviceSerial); + d.readS32(15, &m_selectedDevice.m_deviceSequence); + d.readS32(16, &m_selectedDevice.m_deviceItemIndex); + // qDebug("Preset::deserialize: m_group: %s mode: %s m_description: %s m_centerFrequency: %llu", // qPrintable(m_group), // m_sourcePreset ? "Rx" : "Tx", @@ -205,7 +222,7 @@ void Preset::addOrUpdateDeviceConfig(const QString& sourceId, int sourceSequence, const QByteArray& config) { - DeviceeConfigs::iterator it = m_deviceConfigs.begin(); + DeviceConfigs::iterator it = m_deviceConfigs.begin(); for (; it != m_deviceConfigs.end(); ++it) { @@ -243,7 +260,7 @@ const QByteArray* Preset::findDeviceConfig( const QString& deviceSerial, int deviceSequence) const { - DeviceeConfigs::const_iterator it = m_deviceConfigs.begin(); + DeviceConfigs::const_iterator it = m_deviceConfigs.begin(); for (; it != m_deviceConfigs.end(); ++it) { @@ -254,46 +271,46 @@ const QByteArray* Preset::findDeviceConfig( return nullptr; } - +//_samplingDeviceId, m_samplingDeviceSerial, m_samplingDeviceSequence const QByteArray* Preset::findBestDeviceConfig( - const QString& sourceId, - const QString& sourceSerial, - int sourceSequence) const + const QString& deviceId, + const QString& deviceSerial, + int deviceSequence) const { // Special case for SoapySDR based on serial (driver name) - if (sourceId == "sdrangel.samplesource.soapysdrinput") { - return findBestDeviceConfigSoapy(sourceId, sourceSerial); - } else if (sourceId == "sdrangel.samplesource.soapysdroutput") { - return findBestDeviceConfigSoapy(sourceId, sourceSerial); + if (deviceId == "sdrangel.samplesource.soapysdrinput") { + return findBestDeviceConfigSoapy(deviceId, deviceSerial); + } else if (deviceId == "sdrangel.samplesource.soapysdroutput") { + return findBestDeviceConfigSoapy(deviceId, deviceSerial); } - DeviceeConfigs::const_iterator it = m_deviceConfigs.begin(); - DeviceeConfigs::const_iterator itFirstOfKind = m_deviceConfigs.end(); - DeviceeConfigs::const_iterator itMatchSequence = m_deviceConfigs.end(); + DeviceConfigs::const_iterator it = m_deviceConfigs.begin(); + DeviceConfigs::const_iterator itFirstOfKind = m_deviceConfigs.end(); + DeviceConfigs::const_iterator itMatchSequence = m_deviceConfigs.end(); for (; it != m_deviceConfigs.end(); ++it) { - if (it->m_deviceId == sourceId) + if (it->m_deviceId == deviceId) { if (itFirstOfKind == m_deviceConfigs.end()) { itFirstOfKind = it; } - if (sourceSerial.isNull() || sourceSerial.isEmpty()) + if (deviceSerial.isNull() || deviceSerial.isEmpty()) { - if (it->m_deviceSequence == sourceSequence) + if (it->m_deviceSequence == deviceSequence) { break; } } else { - if (it->m_deviceSerial == sourceSerial) + if (it->m_deviceSerial == deviceSerial) { break; } - else if(it->m_deviceSequence == sourceSequence) + else if(it->m_deviceSequence == deviceSequence) { itMatchSequence = it; } @@ -303,13 +320,13 @@ const QByteArray* Preset::findBestDeviceConfig( if (it == m_deviceConfigs.end()) // no exact match { - if (itMatchSequence != m_deviceConfigs.end()) // match sequence ? + if (itMatchSequence != m_deviceConfigs.end()) // match device type and sequence ? { qDebug("Preset::findBestDeviceConfig: sequence matched: id: %s ser: %s seq: %d", qPrintable(itMatchSequence->m_deviceId), qPrintable(itMatchSequence->m_deviceSerial), itMatchSequence->m_deviceSequence); return &(itMatchSequence->m_config); } - else if (itFirstOfKind != m_deviceConfigs.end()) // match source type ? + else if (itFirstOfKind != m_deviceConfigs.end()) // match just device type ? { qDebug("Preset::findBestDeviceConfig: first of kind matched: id: %s ser: %s seq: %d", qPrintable(itFirstOfKind->m_deviceId), qPrintable(itFirstOfKind->m_deviceSerial), itFirstOfKind->m_deviceSequence); @@ -337,8 +354,8 @@ const QByteArray* Preset::findBestDeviceConfigSoapy(const QString& sourceId, con return 0; // unable to process } - DeviceeConfigs::const_iterator it = m_deviceConfigs.begin(); - DeviceeConfigs::const_iterator itFirstOfKind = m_deviceConfigs.end(); + DeviceConfigs::const_iterator it = m_deviceConfigs.begin(); + DeviceConfigs::const_iterator itFirstOfKind = m_deviceConfigs.end(); for (; it != m_deviceConfigs.end(); ++it) { diff --git a/sdrbase/settings/preset.h b/sdrbase/settings/preset.h index 148fd74d8..edf306d7e 100644 --- a/sdrbase/settings/preset.h +++ b/sdrbase/settings/preset.h @@ -55,7 +55,19 @@ public: m_config(config) { } }; - typedef QList DeviceeConfigs; + typedef QList DeviceConfigs; + + struct SelectedDevice + { + QString m_deviceId; + QString m_deviceSerial; + int m_deviceSequence; + int m_deviceItemIndex; + + SelectedDevice() = default; + SelectedDevice(const SelectedDevice&) = default; + SelectedDevice& operator=(const SelectedDevice&) = default; + }; enum PresetType { @@ -90,6 +102,16 @@ public: void setSpectrumConfig(const QByteArray& data) { m_spectrumConfig = data; } const QByteArray& getSpectrumConfig() const { return m_spectrumConfig; } + void setSpectrumGeometry(const QByteArray& data) { m_spectrumGeometry = data; } + const QByteArray& getSpectrumGeometry() const { return m_spectrumGeometry; } + void setSpectrumWorkspaceIndex(int workspaceIndex) { m_spectrumWorkspaceIndex = workspaceIndex; } + int getSpectrumWorkspaceIndex() const { return m_spectrumWorkspaceIndex; } + void setSelectedDevice(const SelectedDevice& selectedDevice) { m_selectedDevice = selectedDevice; } + SelectedDevice getSelectedDevice() const { return m_selectedDevice; } + void setDeviceGeometry(const QByteArray& data) { m_deviceGeometry = data; } + const QByteArray& getDeviceGeometry() const { return m_deviceGeometry; } + void setDeviceWorkspaceIndex(int workspaceIndex) { m_deviceWorkspaceIndex = workspaceIndex; } + int getDeviceWorkspaceIndex() const { return m_deviceWorkspaceIndex; } bool hasDCOffsetCorrection() const { return m_dcOffsetCorrection; } void setDCOffsetCorrection(bool dcOffsetCorrection) { m_dcOffsetCorrection = dcOffsetCorrection; } @@ -154,6 +176,11 @@ protected: // general configuration QByteArray m_spectrumConfig; + QByteArray m_spectrumGeometry; + int m_spectrumWorkspaceIndex; + QByteArray m_deviceGeometry; + int m_deviceWorkspaceIndex; + SelectedDevice m_selectedDevice; // dc offset and i/q imbalance correction TODO: move it into the source data bool m_dcOffsetCorrection; @@ -163,14 +190,14 @@ protected: ChannelConfigs m_channelConfigs; // devices and configurations - DeviceeConfigs m_deviceConfigs; + DeviceConfigs m_deviceConfigs; // screen and dock layout bool m_showSpectrum; QByteArray m_layout; private: - const QByteArray* findBestDeviceConfigSoapy(const QString& sourceId, const QString& deviceSerial) const; + const QByteArray* findBestDeviceConfigSoapy(const QString& deviceId, const QString& deviceSerial) const; }; Q_DECLARE_METATYPE(const Preset*) diff --git a/sdrgui/CMakeLists.txt b/sdrgui/CMakeLists.txt index 357850af4..57a90f961 100644 --- a/sdrgui/CMakeLists.txt +++ b/sdrgui/CMakeLists.txt @@ -91,6 +91,8 @@ set(sdrgui_SOURCES feature/featuregui.cpp feature/featureuiset.cpp + mainspectrum/mainspectrumgui.cpp + soapygui/discreterangegui.cpp soapygui/intervalrangegui.cpp soapygui/itemsettinggui.cpp @@ -192,6 +194,8 @@ set(sdrgui_HEADERS feature/featuregui.h feature/featureuiset.h + mainspectrum/mainspectrumgui.h + soapygui/discreterangegui.h soapygui/intervalrangegui.h soapygui/itemsettinggui.h diff --git a/sdrgui/device/devicegui.cpp b/sdrgui/device/devicegui.cpp index c1c1b1727..28715039c 100644 --- a/sdrgui/device/devicegui.cpp +++ b/sdrgui/device/devicegui.cpp @@ -62,14 +62,22 @@ DeviceGUI::DeviceGUI(QWidget *parent) : m_addChannelsButton = new QPushButton(); m_addChannelsButton->setFixedSize(20, 20); - QIcon addChannelsIcon(":/create.png"); + QIcon addChannelsIcon(":/channels_add.png"); m_addChannelsButton->setIcon(addChannelsIcon); m_addChannelsButton->setToolTip("Add channels"); + m_deviceSetPresetsButton = new QPushButton(); + m_deviceSetPresetsButton->setFixedSize(20, 20); + QIcon deviceSetPresetsIcon(":/star.png"); + m_deviceSetPresetsButton->setIcon(deviceSetPresetsIcon); + m_deviceSetPresetsButton->setToolTip("Device set presets"); + m_titleLabel = new QLabel(); m_titleLabel->setText("Device"); m_titleLabel->setToolTip("Device identification"); m_titleLabel->setFixedHeight(20); + m_titleLabel->setMinimumWidth(20); + m_titleLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed); m_helpButton = new QPushButton(); m_helpButton->setFixedSize(20, 20); @@ -98,8 +106,22 @@ DeviceGUI::DeviceGUI(QWidget *parent) : m_statusLabel = new QLabel(); // m_statusLabel->setText("OK"); // for future use m_statusLabel->setFixedHeight(20); + m_statusLabel->setMinimumWidth(20); + m_statusLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed); m_statusLabel->setToolTip("Device status"); + m_showSpectrumButton = new QPushButton(); + m_showSpectrumButton->setFixedSize(20, 20); + QIcon showSpectrumIcon(":/dsb.png"); + m_showSpectrumButton->setIcon(showSpectrumIcon); + m_showSpectrumButton->setToolTip("Show main spectrum"); + + m_showAllChannelsButton = new QPushButton(); + m_showAllChannelsButton->setFixedSize(20, 20); + QIcon showAllChannelsIcon(":/channels.png"); + m_showAllChannelsButton->setIcon(showAllChannelsIcon); + m_showAllChannelsButton->setToolTip("Show all channels"); + m_layouts = new QVBoxLayout(); m_layouts->setContentsMargins(0, 4, 0, 4); m_layouts->setSpacing(2); @@ -110,14 +132,16 @@ DeviceGUI::DeviceGUI(QWidget *parent) : m_topLayout->addWidget(m_changeDeviceButton); m_topLayout->addWidget(m_reloadDeviceButton); m_topLayout->addWidget(m_addChannelsButton); + m_topLayout->addWidget(m_deviceSetPresetsButton); m_topLayout->addWidget(m_titleLabel); - m_topLayout->addStretch(1); + // m_topLayout->addStretch(1); m_topLayout->addWidget(m_helpButton); m_topLayout->addWidget(m_moveButton); m_topLayout->addWidget(m_shrinkButton); m_topLayout->addWidget(m_closeButton); m_sizeGripTopRight = new QSizeGrip(this); m_sizeGripTopRight->setStyleSheet("QSizeGrip { background-color: rgb(128, 128, 128); width: 10px; height: 10px; }"); + m_sizeGripTopRight->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_topLayout->addWidget(m_sizeGripTopRight, 0, Qt::AlignTop | Qt::AlignRight); m_centerLayout = new QHBoxLayout(); @@ -126,10 +150,13 @@ DeviceGUI::DeviceGUI(QWidget *parent) : m_bottomLayout = new QHBoxLayout(); m_bottomLayout->setContentsMargins(0, 0, 0, 0); + m_bottomLayout->addWidget(m_showSpectrumButton); + m_bottomLayout->addWidget(m_showAllChannelsButton); 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_sizeGripBottomRight->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + // m_bottomLayout->addStretch(1); m_bottomLayout->addWidget(m_sizeGripBottomRight, 0, Qt::AlignBottom | Qt::AlignRight); m_layouts->addLayout(m_topLayout); @@ -158,12 +185,15 @@ DeviceGUI::~DeviceGUI() delete m_sizeGripTopRight; delete m_topLayout; delete m_layouts; + delete m_showAllChannelsButton; + delete m_showSpectrumButton; delete m_statusLabel; delete m_closeButton; delete m_shrinkButton; delete m_moveButton; delete m_helpButton; delete m_titleLabel; + delete m_deviceSetPresetsButton; delete m_addChannelsButton; delete m_reloadDeviceButton; delete m_changeDeviceButton; diff --git a/sdrgui/device/devicegui.h b/sdrgui/device/devicegui.h index e6a947c93..a4167d704 100644 --- a/sdrgui/device/devicegui.h +++ b/sdrgui/device/devicegui.h @@ -101,11 +101,14 @@ private: QPushButton *m_changeDeviceButton; QPushButton *m_reloadDeviceButton; QPushButton *m_addChannelsButton; + QPushButton *m_deviceSetPresetsButton; QLabel *m_titleLabel; QPushButton *m_helpButton; QPushButton *m_moveButton; QPushButton *m_shrinkButton; QPushButton *m_closeButton; + QPushButton *m_showSpectrumButton; + QPushButton *m_showAllChannelsButton; QLabel *m_statusLabel; QVBoxLayout *m_layouts; QHBoxLayout *m_topLayout; diff --git a/sdrgui/device/deviceuiset.cpp b/sdrgui/device/deviceuiset.cpp index cb628124c..3570517df 100644 --- a/sdrgui/device/deviceuiset.cpp +++ b/sdrgui/device/deviceuiset.cpp @@ -25,31 +25,35 @@ #include "gui/glspectrum.h" #include "gui/glspectrumgui.h" #include "gui/channelwindow.h" +#include "gui/workspace.h" #include "device/devicegui.h" #include "device/deviceset.h" +#include "device/deviceapi.h" #include "plugin/pluginapi.h" #include "plugin/plugininterface.h" #include "channel/channelutils.h" #include "channel/channelapi.h" #include "channel/channelgui.h" +#include "mainspectrum/mainspectrumgui.h" #include "settings/preset.h" #include "deviceuiset.h" -DeviceUISet::DeviceUISet(int tabIndex, DeviceSet *deviceSet) +DeviceUISet::DeviceUISet(int deviceSetIndex, DeviceSet *deviceSet) { m_spectrum = new GLSpectrum; m_spectrumVis = deviceSet->m_spectrumVis; m_spectrumVis->setGLSpectrum(m_spectrum); m_spectrumGUI = new GLSpectrumGUI; m_spectrumGUI->setBuddies(m_spectrumVis, m_spectrum); + m_mainSpectrumGUI = new MainSpectrumGUI(m_spectrum, m_spectrumGUI); m_channelWindow = new ChannelWindow; m_deviceAPI = nullptr; m_deviceGUI = nullptr; m_deviceSourceEngine = nullptr; m_deviceSinkEngine = nullptr; m_deviceMIMOEngine = nullptr; - m_deviceTabIndex = tabIndex; + m_deviceSetIndex = deviceSetIndex; m_deviceSet = deviceSet; m_nbAvailableRxChannels = 0; // updated at enumeration for UI selector m_nbAvailableTxChannels = 0; // updated at enumeration for UI selector @@ -65,8 +69,9 @@ DeviceUISet::DeviceUISet(int tabIndex, DeviceSet *deviceSet) DeviceUISet::~DeviceUISet() { delete m_channelWindow; - delete m_spectrumGUI; - delete m_spectrum; + delete m_mainSpectrumGUI; + // delete m_spectrumGUI; // done above + // delete m_spectrum; } void DeviceUISet::setSpectrumScalingFactor(float scalef) @@ -156,6 +161,60 @@ ChannelAPI *DeviceUISet::getChannelAt(int channelIndex) return m_deviceSet->getChannelAt(channelIndex); } +void DeviceUISet::loadDeviceSetSettings( + const Preset* preset, + PluginAPI *pluginAPI, + QList *workspaces, + Workspace *currentWorkspace +) +{ + (void) workspaces; // TODO: use for channels + (void) currentWorkspace; // TODO: use for channels + + m_spectrumGUI->deserialize(preset->getSpectrumConfig()); + m_deviceAPI->loadSamplingDeviceSettings(preset); + + if (m_deviceSourceEngine) { // source device + loadRxChannelSettings(preset, pluginAPI); + } else if (m_deviceSinkEngine) { // sink device + loadTxChannelSettings(preset, pluginAPI); + } else if (m_deviceMIMOEngine) { // MIMO device + loadMIMOChannelSettings(preset, pluginAPI); + } +} + +void DeviceUISet::saveDeviceSetSettings(Preset* preset) const +{ + preset->setSpectrumConfig(m_spectrumGUI->serialize()); + preset->setSpectrumWorkspaceIndex(m_mainSpectrumGUI->getWorkspaceIndex()); + preset->setSpectrumGeometry(m_mainSpectrumGUI->saveGeometry()); + preset->setSelectedDevice(Preset::SelectedDevice{ + m_deviceAPI->getSamplingDeviceId(), + m_deviceAPI->getSamplingDeviceSerial(), + (int) m_deviceAPI->getSamplingDeviceSequence(), + (int) m_deviceAPI->getDeviceItemIndex() + }); + preset->clearChannels(); + + if (m_deviceSourceEngine) // source device + { + preset->setSourcePreset(); + saveRxChannelSettings(preset); + } + else if (m_deviceSinkEngine) // sink device + { + preset->setSinkPreset(); + saveTxChannelSettings(preset); + } + else if (m_deviceMIMOEngine) // MIMO device + { + preset->setMIMOPreset(); + saveMIMOChannelSettings(preset); + } + + m_deviceAPI->saveSamplingDeviceSettings(preset); +} + void DeviceUISet::loadRxChannelSettings(const Preset *preset, PluginAPI *pluginAPI) { if (preset->isSourcePreset()) @@ -224,7 +283,7 @@ void DeviceUISet::loadRxChannelSettings(const Preset *preset, PluginAPI *pluginA } } -void DeviceUISet::saveRxChannelSettings(Preset *preset) +void DeviceUISet::saveRxChannelSettings(Preset *preset) const { if (preset->isSourcePreset()) { @@ -308,7 +367,7 @@ void DeviceUISet::loadTxChannelSettings(const Preset *preset, PluginAPI *pluginA } -void DeviceUISet::saveTxChannelSettings(Preset *preset) +void DeviceUISet::saveTxChannelSettings(Preset *preset) const { if (preset->isSinkPreset()) { @@ -392,7 +451,7 @@ void DeviceUISet::loadMIMOChannelSettings(const Preset *preset, PluginAPI *plugi } } -void DeviceUISet::saveMIMOChannelSettings(Preset *preset) +void DeviceUISet::saveMIMOChannelSettings(Preset *preset) const { if (preset->isMIMOPreset()) { diff --git a/sdrgui/device/deviceuiset.h b/sdrgui/device/deviceuiset.h index 4965b431b..5d133d4b7 100644 --- a/sdrgui/device/deviceuiset.h +++ b/sdrgui/device/deviceuiset.h @@ -27,6 +27,7 @@ class SpectrumVis; class GLSpectrum; class GLSpectrumGUI; +class MainSpectrumGUI; class ChannelWindow; class DeviceAPI; class DeviceSet; @@ -39,6 +40,7 @@ class DeviceGUI; class ChannelAPI; class ChannelGUI; class Preset; +class Workspace; namespace SWGSDRangel { class SWGGLSpectrum; @@ -53,6 +55,7 @@ public: SpectrumVis *m_spectrumVis; GLSpectrum *m_spectrum; GLSpectrumGUI *m_spectrumGUI; + MainSpectrumGUI *m_mainSpectrumGUI; ChannelWindow *m_channelWindow; DeviceAPI *m_deviceAPI; DeviceGUI *m_deviceGUI; @@ -60,8 +63,12 @@ public: DSPDeviceSinkEngine *m_deviceSinkEngine; DSPDeviceMIMOEngine *m_deviceMIMOEngine; QByteArray m_mainWindowState; + QString m_selectedDeviceId; + QString m_selectedDeviceSerial; + int m_selectedDeviceSequence; + int m_selectedDeviceItemImdex; - DeviceUISet(int tabIndex, DeviceSet *deviceSet); + DeviceUISet(int deviceSetIndex, DeviceSet *deviceSet); ~DeviceUISet(); GLSpectrum *getSpectrum() { return m_spectrum; } //!< Direct spectrum getter @@ -73,12 +80,15 @@ public: void freeChannels(); void deleteChannel(int channelIndex); ChannelAPI *getChannelAt(int channelIndex); - void loadRxChannelSettings(const Preset* preset, PluginAPI *pluginAPI); - void saveRxChannelSettings(Preset* preset); - void loadTxChannelSettings(const Preset* preset, PluginAPI *pluginAPI); - void saveTxChannelSettings(Preset* preset); - void loadMIMOChannelSettings(const Preset* preset, PluginAPI *pluginAPI); - void saveMIMOChannelSettings(Preset* preset); + + void loadDeviceSetSettings( + const Preset* preset, + PluginAPI *pluginAPI, + QList *workspaces, + Workspace *currentWorkspace + ); + void saveDeviceSetSettings(Preset* preset) const; + void registerRxChannelInstance(ChannelAPI *channelAPI, ChannelGUI* channelGUI); void registerTxChannelInstance(ChannelAPI *channelAPI, ChannelGUI* channelGUI); void registerChannelInstance(ChannelAPI *channelAPI, ChannelGUI* channelGUI); @@ -129,12 +139,19 @@ private: // ChannelInstanceRegistrations m_rxChannelInstanceRegistrations; // ChannelInstanceRegistrations m_txChannelInstanceRegistrations; ChannelInstanceRegistrations m_channelInstanceRegistrations; - int m_deviceTabIndex; + int m_deviceSetIndex; DeviceSet *m_deviceSet; int m_nbAvailableRxChannels; //!< Number of Rx channels available for selection int m_nbAvailableTxChannels; //!< Number of Tx channels available for selection int m_nbAvailableMIMOChannels; //!< Number of MIMO channels available for selection + void loadRxChannelSettings(const Preset* preset, PluginAPI *pluginAPI); + void loadTxChannelSettings(const Preset* preset, PluginAPI *pluginAPI); + void loadMIMOChannelSettings(const Preset* preset, PluginAPI *pluginAPI); + void saveRxChannelSettings(Preset* preset) const; + void saveTxChannelSettings(Preset* preset) const; + void saveMIMOChannelSettings(Preset* preset) const; + private slots: void handleChannelGUIClosing(ChannelGUI* channelGUI); }; diff --git a/sdrgui/feature/featuregui.cpp b/sdrgui/feature/featuregui.cpp index 41638097e..248be215b 100644 --- a/sdrgui/feature/featuregui.cpp +++ b/sdrgui/feature/featuregui.cpp @@ -54,6 +54,8 @@ FeatureGUI::FeatureGUI(QWidget *parent) : m_titleLabel->setText("Feature"); m_titleLabel->setToolTip("Feature name"); m_titleLabel->setFixedHeight(20); + m_titleLabel->setMinimumWidth(20); + m_titleLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed); m_helpButton = new QPushButton(); m_helpButton->setFixedSize(20, 20); @@ -82,6 +84,8 @@ FeatureGUI::FeatureGUI(QWidget *parent) : m_statusLabel = new QLabel(); // m_statusLabel->setText("OK"); // for future use m_statusLabel->setFixedHeight(20); + m_statusLabel->setMinimumWidth(20); + m_statusLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed); m_statusLabel->setToolTip("Feature status"); m_layouts = new QVBoxLayout(); @@ -93,13 +97,14 @@ FeatureGUI::FeatureGUI(QWidget *parent) : m_topLayout->addWidget(m_indexLabel); m_topLayout->addWidget(m_settingsButton); m_topLayout->addWidget(m_titleLabel); - m_topLayout->addStretch(1); + // m_topLayout->addStretch(1); m_topLayout->addWidget(m_helpButton); m_topLayout->addWidget(m_moveButton); m_topLayout->addWidget(m_shrinkButton); m_topLayout->addWidget(m_closeButton); m_sizeGripTopRight = new QSizeGrip(this); m_sizeGripTopRight->setStyleSheet("QSizeGrip { background-color: rgb(128, 128, 128); width: 10px; height: 10px; }"); + m_sizeGripTopRight->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_topLayout->addWidget(m_sizeGripTopRight, 0, Qt::AlignTop | Qt::AlignRight); m_centerLayout = new QHBoxLayout(); @@ -110,7 +115,8 @@ 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_sizeGripBottomRight->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + // m_bottomLayout->addStretch(1); m_bottomLayout->addWidget(m_sizeGripBottomRight, 0, Qt::AlignBottom | Qt::AlignRight); m_layouts->addLayout(m_topLayout); diff --git a/sdrgui/feature/featureuiset.cpp b/sdrgui/feature/featureuiset.cpp index e09d2d0fb..3bf8c7453 100644 --- a/sdrgui/feature/featureuiset.cpp +++ b/sdrgui/feature/featureuiset.cpp @@ -134,7 +134,8 @@ void FeatureUISet::loadFeatureSetSettings( const FeatureSetPreset *preset, PluginAPI *pluginAPI, WebAPIAdapterInterface *apiAdapter, - Workspace *workspace + QList *workspaces, + Workspace *currentWorkspace ) { qDebug("FeatureUISet::loadFeatureSetSettings: Loading preset [%s | %s]", @@ -161,58 +162,6 @@ void FeatureUISet::loadFeatureSetSettings( qDebug("FeatureUISet::loadFeatureSetSettings: %d feature(s) in preset", preset->getFeatureCount()); - 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); - - 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); @@ -242,8 +191,19 @@ void FeatureUISet::loadFeatureSetSettings( qPrintable(featureConfig.m_featureIdURI)); featureGUI->deserialize(featureConfig.m_config); featureGUI->setIndex(feature->getIndexInFeatureSet()); - workspaces[featureGUI->getWorkspaceIndex()]->addToMdiArea((QMdiSubWindow*) featureGUI); - featureGUI->restoreGeometry(featureGUI->getGeometryBytes()); + int originalWorkspaceIndex = featureGUI->getWorkspaceIndex(); + + if (workspaces && (workspaces->size() > 0) && (originalWorkspaceIndex < workspaces->size())) // restore in original workspace + { + (*workspaces)[originalWorkspaceIndex]->addToMdiArea((QMdiSubWindow*) featureGUI); + featureGUI->restoreGeometry(featureGUI->getGeometryBytes()); + } + else if (currentWorkspace) // restore in current workspace + { + featureGUI->setWorkspaceIndex(currentWorkspace->getIndex()); + currentWorkspace->addToMdiArea((QMdiSubWindow*) featureGUI); + featureGUI->restoreGeometry(featureGUI->getGeometryBytes()); + } } } } diff --git a/sdrgui/feature/featureuiset.h b/sdrgui/feature/featureuiset.h index 372a3cb3e..e557527cf 100644 --- a/sdrgui/feature/featureuiset.h +++ b/sdrgui/feature/featureuiset.h @@ -52,13 +52,8 @@ public: const FeatureSetPreset* preset, PluginAPI *pluginAPI, WebAPIAdapterInterface *apiAdapter, - Workspace *workspace - ); - void loadFeatureSetSettings( - const FeatureSetPreset* preset, - PluginAPI *pluginAPI, - WebAPIAdapterInterface *apiAdapter, - QList& workspaces + QList *workspaces, + Workspace *currentWorkspace ); void saveFeatureSetSettings(FeatureSetPreset* preset); void freeFeatures(); diff --git a/sdrgui/gui/featurepresetsdialog.cpp b/sdrgui/gui/featurepresetsdialog.cpp index 6458a43e1..acd902766 100644 --- a/sdrgui/gui/featurepresetsdialog.cpp +++ b/sdrgui/gui/featurepresetsdialog.cpp @@ -34,6 +34,8 @@ FeaturePresetsDialog::FeaturePresetsDialog(QWidget* parent) : m_featureUISet(nullptr), m_pluginAPI(nullptr), m_apiAdapter(nullptr), + m_currentWorkspace(nullptr), + m_workspaces(nullptr), m_presetLoaded(false) { ui->setupUi(this); @@ -374,7 +376,7 @@ void FeaturePresetsDialog::loadPresetSettings(const FeatureSetPreset* preset) qPrintable(preset->getGroup()), qPrintable(preset->getDescription())); - m_featureUISet->loadFeatureSetSettings(preset, m_pluginAPI, m_apiAdapter, m_workspace); + m_featureUISet->loadFeatureSetSettings(preset, m_pluginAPI, m_apiAdapter, m_workspaces, m_currentWorkspace); m_presetLoaded = true; } diff --git a/sdrgui/gui/featurepresetsdialog.h b/sdrgui/gui/featurepresetsdialog.h index 1addbf404..c5b9c3d2b 100644 --- a/sdrgui/gui/featurepresetsdialog.h +++ b/sdrgui/gui/featurepresetsdialog.h @@ -44,7 +44,8 @@ public: void setFeatureUISet(FeatureUISet *featureUISet) { m_featureUISet = featureUISet; } void setPluginAPI(PluginAPI *pluginAPI) { m_pluginAPI = pluginAPI; } void setWebAPIAdapter(WebAPIAdapterInterface *apiAdapter) { m_apiAdapter = apiAdapter; } - void setWorkspace(Workspace *workspace) { m_workspace = workspace; } + void setCurrentWorkspace(Workspace *workspace) { m_currentWorkspace = workspace; } + void setWorkspaces(QList *workspaces) { m_workspaces = workspaces; } void populateTree(); bool wasPresetLoaded() const { return m_presetLoaded; } @@ -59,7 +60,8 @@ private: FeatureUISet *m_featureUISet; PluginAPI *m_pluginAPI; WebAPIAdapterInterface *m_apiAdapter; - Workspace *m_workspace; + Workspace *m_currentWorkspace; + QList *m_workspaces; bool m_presetLoaded; QTreeWidgetItem* addPresetToTree(const FeatureSetPreset* preset); diff --git a/sdrgui/gui/glspectrum.cpp b/sdrgui/gui/glspectrum.cpp index d9b846398..2c9c1513f 100644 --- a/sdrgui/gui/glspectrum.cpp +++ b/sdrgui/gui/glspectrum.cpp @@ -61,7 +61,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) : m_displayGrid(true), m_displayGridIntensity(5), m_displayTraceIntensity(50), - m_invertedWaterfall(false), + m_invertedWaterfall(true), m_displayMaxHold(false), m_currentSpectrum(nullptr), m_displayCurrent(false), @@ -69,7 +69,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) : m_rightMargin(0), m_topMargin(0), m_frequencyScaleHeight(0), - m_histogramHeight(20), + m_histogramHeight(80), m_waterfallHeight(0), m_bottomMargin(0), m_waterfallBuffer(nullptr), @@ -93,6 +93,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) : m_calibrationInterpMode(SpectrumSettings::CalibInterpLinear), m_messageQueueToGUI(nullptr) { + setObjectName("GLSpectrum"); setAutoFillBackground(false); setAttribute(Qt::WA_OpaquePaintEvent, true); setAttribute(Qt::WA_NoSystemBackground, true); @@ -100,7 +101,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) : setMinimumSize(200, 200); - m_waterfallShare = 0.66; + m_waterfallShare = 0.5; for (int i = 0; i <= 239; i++) { diff --git a/sdrgui/gui/workspace.cpp b/sdrgui/gui/workspace.cpp index 724f10116..a40b82bee 100644 --- a/sdrgui/gui/workspace.cpp +++ b/sdrgui/gui/workspace.cpp @@ -73,13 +73,13 @@ Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) : m_vline1->setFrameShadow(QFrame::Sunken); m_addFeatureButton = new QPushButton(); - QIcon addFeatureIcon(":/tool.png"); + QIcon addFeatureIcon(":/tool_add.png"); m_addFeatureButton->setIcon(addFeatureIcon); m_addFeatureButton->setToolTip("Add features"); m_addFeatureButton->setFixedSize(20, 20); m_featurePresetsButton = new QPushButton(); - QIcon presetsIcon(":/star.png"); + QIcon presetsIcon(":/tool_star.png"); m_featurePresetsButton->setIcon(presetsIcon); m_featurePresetsButton->setToolTip("Feature presets"); m_featurePresetsButton->setFixedSize(20, 20); diff --git a/sdrgui/mainspectrum/mainspectrumgui.cpp b/sdrgui/mainspectrum/mainspectrumgui.cpp new file mode 100644 index 000000000..04349036b --- /dev/null +++ b/sdrgui/mainspectrum/mainspectrumgui.cpp @@ -0,0 +1,290 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mainwindow.h" +#include "gui/glspectrum.h" +#include "gui/glspectrumgui.h" +#include "gui/workspaceselectiondialog.h" +#include "mainspectrumgui.h" + +MainSpectrumGUI::MainSpectrumGUI(GLSpectrum *spectrum, GLSpectrumGUI *spectrumGUI, QWidget *parent) : + QMdiSubWindow(parent), + m_spectrum(spectrum), + m_spectrumGUI(spectrumGUI), + m_deviceType(DeviceRx), + m_deviceSetIndex(0), + m_drag(false) +{ + qDebug("MainSpectrumGUI::MainSpectrumGUI: %p", parent); + setWindowFlags(windowFlags() | Qt::FramelessWindowHint); + + m_indexLabel = new QLabel(); + m_indexLabel->setFixedSize(32, 16); + m_indexLabel->setStyleSheet("QLabel { background-color: rgb(128, 128, 128); qproperty-alignment: AlignCenter; }"); + m_indexLabel->setText(tr("X:%1").arg(m_deviceSetIndex)); + m_indexLabel->setToolTip("Device type and set index"); + + m_spacerLabel = new QLabel(); + m_spacerLabel->setFixedWidth(5); + + m_titleLabel = new QLabel(); + m_titleLabel->setText("Device"); + m_titleLabel->setToolTip("Device identification"); + m_titleLabel->setFixedHeight(20); + m_titleLabel->setMinimumWidth(20); + m_titleLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed); + + m_helpButton = new QPushButton(); + m_helpButton->setFixedSize(20, 20); + QIcon helpIcon(":/help.png"); + m_helpButton->setIcon(helpIcon); + m_helpButton->setToolTip("Show spectrum window documentation in browser"); + + m_moveButton = new QPushButton(); + m_moveButton->setFixedSize(20, 20); + QIcon moveIcon(":/exit.png"); + m_moveButton->setIcon(moveIcon); + m_moveButton->setToolTip("Move to workspace"); + + m_shrinkButton = new QPushButton(); + m_shrinkButton->setFixedSize(20, 20); + QIcon shrinkIcon(":/shrink.png"); + m_shrinkButton->setIcon(shrinkIcon); + m_shrinkButton->setToolTip("Adjust window to minimum size"); + + m_hideButton = new QPushButton(); + m_hideButton->setFixedSize(20, 20); + QIcon hideIcon(":/hide.png"); + m_hideButton->setIcon(hideIcon); + m_hideButton->setToolTip("Hide device"); + + m_statusLabel = new QLabel(); + // m_statusLabel->setText("OK"); // for future use + m_statusLabel->setFixedHeight(10); + m_statusLabel->setMinimumWidth(10); + m_statusLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed); + // m_statusLabel->setToolTip("Spectrum status"); + + m_layouts = new QVBoxLayout(); + m_layouts->setContentsMargins(0, 4, 0, 4); + m_layouts->setSpacing(0); + + m_topLayout = new QHBoxLayout(); + m_topLayout->setContentsMargins(0, 0, 0, 0); + m_topLayout->addWidget(m_indexLabel); + m_topLayout->addWidget(m_spacerLabel); + m_topLayout->addWidget(m_titleLabel); + // m_topLayout->addStretch(1); + m_topLayout->addWidget(m_helpButton); + m_topLayout->addWidget(m_moveButton); + m_topLayout->addWidget(m_shrinkButton); + m_topLayout->addWidget(m_hideButton); + m_sizeGripTopRight = new QSizeGrip(this); + m_sizeGripTopRight->setStyleSheet("QSizeGrip { background-color: rgb(128, 128, 128); width: 10px; height: 10px; }"); + m_sizeGripTopRight->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + m_topLayout->addWidget(m_sizeGripTopRight, 0, Qt::AlignTop | Qt::AlignRight); + + m_spectrumLayout = new QHBoxLayout(); + m_spectrumLayout->addWidget(spectrum); + spectrum->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_spectrumGUILayout = new QHBoxLayout(); + m_spectrumGUILayout->addWidget(spectrumGUI); + + m_bottomLayout = new QHBoxLayout(); + m_bottomLayout->setContentsMargins(0, 0, 0, 0); + m_bottomLayout->addWidget(m_statusLabel); + m_sizeGripBottomRight = new QSizeGrip(this); + m_sizeGripBottomRight->setStyleSheet("QSizeGrip { background-color: rgb(128, 128, 128); width: 10px; height: 10px; }"); + m_sizeGripBottomRight->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + //m_bottomLayout->addStretch(1); + m_bottomLayout->addWidget(m_sizeGripBottomRight, 0, Qt::AlignBottom | Qt::AlignRight); + + m_layouts->addLayout(m_topLayout); + m_layouts->addLayout(m_spectrumLayout); + m_layouts->addLayout(m_spectrumGUILayout); + m_layouts->addLayout(m_bottomLayout); + + QObjectCleanupHandler().add(layout()); + setLayout(m_layouts); + + connect(m_helpButton, SIGNAL(clicked()), this, SLOT(showHelp())); + connect(m_moveButton, SIGNAL(clicked()), this, SLOT(openMoveToWorkspaceDialog())); + connect(m_shrinkButton, SIGNAL(clicked()), this, SLOT(shrinkWindow())); + connect(this, SIGNAL(forceShrink()), this, SLOT(shrinkWindow())); + connect(m_hideButton, SIGNAL(clicked()), this, SLOT(hide())); + connect(this, SIGNAL(forceClose()), this, SLOT(close())); + + shrinkWindow(); +} + +MainSpectrumGUI::~MainSpectrumGUI() +{ + qDebug("MainSpectrumGUI::~MainSpectrumGUI"); + m_spectrumLayout->removeWidget(m_spectrum); + m_spectrumGUILayout->removeWidget(m_spectrumGUI); + delete m_sizeGripBottomRight; + delete m_bottomLayout; + delete m_spectrumGUILayout; + delete m_spectrumLayout; + delete m_sizeGripTopRight; + delete m_topLayout; + delete m_layouts; + delete m_statusLabel; + delete m_hideButton; + delete m_shrinkButton; + delete m_moveButton; + delete m_helpButton; + delete m_titleLabel; + delete m_spacerLabel; + delete m_indexLabel; + qDebug("MainSpectrumGUI::~MainSpectrumGUI: end"); +} + +void MainSpectrumGUI::closeEvent(QCloseEvent *event) +{ + qDebug("MainSpectrumGUI::closeEvent"); + emit closing(); + event->accept(); +} + +void MainSpectrumGUI::mousePressEvent(QMouseEvent* event) +{ + if ((event->button() == Qt::LeftButton) && isOnMovingPad()) + { + m_drag = true; + m_DragPosition = event->globalPos() - pos(); + event->accept(); + } +} + +void MainSpectrumGUI::mouseMoveEvent(QMouseEvent* event) +{ + if ((event->buttons() & Qt::LeftButton) && isOnMovingPad()) + { + move(event->globalPos() - m_DragPosition); + event->accept(); + } +} + +void MainSpectrumGUI::showHelp() +{ + if (m_helpURL.isEmpty()) { + return; + } + + QString url; + + if (m_helpURL.startsWith("http")) { + url = m_helpURL; + } else { + url = QString("https://github.com/f4exb/sdrangel/blob/master/%1").arg(m_helpURL); // Something like "plugins/channelrx/chanalyzer/readme.md" + } + + QDesktopServices::openUrl(QUrl(url)); +} + +void MainSpectrumGUI::openMoveToWorkspaceDialog() +{ + int numberOfWorkspaces = MainWindow::getInstance()->getNumberOfWorkspaces(); + WorkspaceSelectionDialog dialog(numberOfWorkspaces, this); + dialog.exec(); + + if (dialog.hasChanged()) { + emit moveToWorkspace(dialog.getSelectedIndex()); + } +} + +void MainSpectrumGUI::shrinkWindow() +{ + qDebug("MainSpectrumGUI::shrinkWindow"); + adjustSize(); + resize(width(), 360); +} + +void MainSpectrumGUI::setTitle(const QString& title) +{ + m_titleLabel->setText(title); +} + +QString MainSpectrumGUI::getTitle() const +{ + return m_titleLabel->text(); +} + +bool MainSpectrumGUI::isOnMovingPad() +{ + return m_indexLabel->underMouse() || + m_spacerLabel->underMouse() || + m_titleLabel->underMouse() || + m_statusLabel->underMouse(); +} + +void MainSpectrumGUI::setIndex(int index) +{ + m_deviceSetIndex = index; + m_indexLabel->setText(tr("%1:%2").arg(getDeviceTypeTag()).arg(m_deviceSetIndex)); +} + +void MainSpectrumGUI::setDeviceType(DeviceType type) +{ + m_deviceType = type; + m_indexLabel->setStyleSheet(tr("QLabel { background-color: %1; qproperty-alignment: AlignCenter; }").arg(getDeviceTypeColor())); +} + +void MainSpectrumGUI::setToolTip(const QString& tooltip) +{ + m_titleLabel->setToolTip(tooltip); +} + +QString MainSpectrumGUI::getDeviceTypeColor() +{ + switch(m_deviceType) + { + case DeviceRx: + return "rgb(0, 128, 0)"; + case DeviceTx: + return "rgb(204, 0, 0)"; + case DeviceMIMO: + return "rgb(0, 0, 192)"; + default: + return "rgb(128, 128, 128)"; + } +} + +QString MainSpectrumGUI::getDeviceTypeTag() +{ + switch(m_deviceType) + { + case DeviceRx: + return "R"; + case DeviceTx: + return "T"; + case DeviceMIMO: + return "M"; + default: + return "X"; + } +} diff --git a/sdrgui/mainspectrum/mainspectrumgui.h b/sdrgui/mainspectrum/mainspectrumgui.h new file mode 100644 index 000000000..4a03ba983 --- /dev/null +++ b/sdrgui/mainspectrum/mainspectrumgui.h @@ -0,0 +1,110 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRGUI_MAINSPECTRUM_MAINSPECTRUMGUIGUI_H_ +#define SDRGUI_MAINSPECTRUM_MAINSPECTRUMGUIGUI_H_ + +#include +#include + +#include "util/messagequeue.h" +#include "export.h" + +class GLSpectrum; +class GLSpectrumGUI; +class QLabel; +class QPushButton; +class QVBoxLayout; +class QHBoxLayout; +class QSizeGrip; + +class SDRGUI_API MainSpectrumGUI : public QMdiSubWindow +{ + Q_OBJECT +public: + enum DeviceType + { + DeviceRx, + DeviceTx, + DeviceMIMO + }; + + MainSpectrumGUI(GLSpectrum *spectrum, GLSpectrumGUI *spectrumGUI, QWidget *parent = nullptr); + virtual ~MainSpectrumGUI(); + + void setDeviceType(DeviceType type); + DeviceType getDeviceType() const { return m_deviceType; } + void setTitle(const QString& title); + QString getTitle() const; + void setToolTip(const QString& tooltip); + void setIndex(int index); + int getIndex() const { return m_deviceSetIndex; } + void setWorkspaceIndex(int index) { m_workspaceIndex = index; } + int getWorkspaceIndex() const { return m_workspaceIndex; } + void setGeometryBytes(const QByteArray& blob) { m_geometryBytes = blob; } + const QByteArray& getGeometryBytes() const { return m_geometryBytes; } + +private: + GLSpectrum *m_spectrum; + GLSpectrumGUI *m_spectrumGUI; + int m_workspaceIndex; + QByteArray m_geometryBytes; + DeviceType m_deviceType; + int m_deviceSetIndex; + QString m_deviceTitle; + QString m_deviceTooltip; + QString m_helpURL; + + QLabel *m_indexLabel; + QLabel *m_spacerLabel; + QLabel *m_titleLabel; + QPushButton *m_helpButton; + QPushButton *m_moveButton; + QPushButton *m_shrinkButton; + QPushButton *m_hideButton; + QLabel *m_statusLabel; + QVBoxLayout *m_layouts; + QHBoxLayout *m_topLayout; + QHBoxLayout *m_spectrumLayout; + QHBoxLayout *m_spectrumGUILayout; + QHBoxLayout *m_bottomLayout; + QSizeGrip *m_sizeGripTopRight; + QSizeGrip *m_sizeGripBottomRight; + bool m_drag; + QPoint m_DragPosition; + + void closeEvent(QCloseEvent *event); + void mousePressEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event); + bool isOnMovingPad(); + QString getDeviceTypeColor(); + QString getDeviceTypeTag(); + +private slots: + void showHelp(); + void openMoveToWorkspaceDialog(); + void shrinkWindow(); + +signals: + void forceClose(); + void closing(); + void moveToWorkspace(int workspaceIndex); + void forceShrink(); +}; + + +#endif // SDRGUI_MAINSPECTRUM_MAINSPECTRUMGUIGUI_H_ diff --git a/sdrgui/mainwindow.cpp b/sdrgui/mainwindow.cpp index 76d0881ee..3b9d3f654 100644 --- a/sdrgui/mainwindow.cpp +++ b/sdrgui/mainwindow.cpp @@ -47,6 +47,7 @@ #include "feature/featureset.h" #include "feature/feature.h" #include "feature/featuregui.h" +#include "mainspectrum/mainspectrumgui.h" #include "commands/commandkeyreceiver.h" #include "gui/indicator.h" #include "gui/presetitem.h" @@ -261,7 +262,7 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse splash->showStatusMessage("load current configuration...", Qt::white); qDebug() << "MainWindow::MainWindow: load current configuration..."; - // loadPresetSettings(m_mainCore->m_settings.getWorkingPreset(), 0); + // loadDeviceSetPresetSettings(m_mainCore->m_settings.getWorkingPreset(), 0); m_apiAdapter = new WebAPIAdapter(); // loadFeatureSetPresetSettings(m_mainCore->m_settings.getWorkingFeatureSetPreset(), 0); loadConfiguration(m_mainCore->m_settings.getWorkingConfiguration()); @@ -389,16 +390,27 @@ void MainWindow::sampleSourceAdd(Workspace *workspace, int deviceIndex) deviceIndex = DeviceEnumerator::instance()->getFileInputDeviceIndex(); } - sampleSourceImplement(deviceSetIndex, deviceIndex, deviceAPI, m_deviceUIs.back(), workspace); + sampleSourceCreate(deviceSetIndex, deviceIndex, deviceAPI, m_deviceUIs.back()); + m_deviceUIs.back()->m_deviceGUI->setWorkspaceIndex(workspace->getIndex()); + m_deviceUIs.back()->m_mainSpectrumGUI->setWorkspaceIndex(workspace->getIndex()); + + QObject::connect( + m_deviceUIs.back()->m_mainSpectrumGUI, + &MainSpectrumGUI::moveToWorkspace, + this, + [=](int wsIndexDest){ this->mainSpectrumMove(m_deviceUIs.back()->m_mainSpectrumGUI, wsIndexDest); } + ); + + workspace->addToMdiArea(m_deviceUIs.back()->m_deviceGUI); + workspace->addToMdiArea(m_deviceUIs.back()->m_mainSpectrumGUI); emit m_mainCore->deviceSetAdded(deviceSetIndex, deviceAPI); } -void MainWindow::sampleSourceImplement( +void MainWindow::sampleSourceCreate( int deviceSetIndex, int deviceIndex, DeviceAPI *deviceAPI, - DeviceUISet *deviceUISet, - Workspace *workspace + DeviceUISet *deviceUISet ) { int selectedDeviceIndex = deviceIndex; @@ -506,15 +518,23 @@ void MainWindow::sampleSourceImplement( ); deviceAPI->getSampleSource()->setMessageQueueToGUI(deviceGUI->getInputMessageQueue()); deviceUISet->m_deviceGUI = deviceGUI; + const PluginInterface::SamplingDevice *selectedDevice = DeviceEnumerator::instance()->getRxSamplingDevice(selectedDeviceIndex); + deviceUISet->m_selectedDeviceId = selectedDevice->id; + deviceUISet->m_selectedDeviceSerial = selectedDevice->serial; + deviceUISet->m_selectedDeviceSequence = selectedDevice->sequence; + deviceUISet->m_selectedDeviceItemImdex = selectedDevice->deviceItemIndex; deviceUISet->m_deviceAPI->getSampleSource()->init(); // Finalize GUI setup and add it to workspace MDI deviceGUI->setDeviceType(DeviceGUI::DeviceRx); deviceGUI->setIndex(deviceSetIndex); - deviceGUI->setWorkspaceIndex(workspace->getIndex()); deviceGUI->setToolTip(samplingDevice->displayedName); deviceGUI->setTitle(samplingDevice->displayedName.split(" ")[0]); deviceGUI->setCurrentDeviceIndex(selectedDeviceIndex); - workspace->addToMdiArea((QMdiSubWindow*) deviceGUI); + MainSpectrumGUI *mainSpectrumGUI = deviceUISet->m_mainSpectrumGUI; + mainSpectrumGUI->setDeviceType(MainSpectrumGUI::DeviceRx); + mainSpectrumGUI->setIndex(deviceSetIndex); + mainSpectrumGUI->setToolTip(samplingDevice->displayedName); + mainSpectrumGUI->setTitle(samplingDevice->displayedName.split(" ")[0]); } void MainWindow::sampleSinkAdd(Workspace *workspace, int deviceIndex) @@ -552,16 +572,27 @@ void MainWindow::sampleSinkAdd(Workspace *workspace, int deviceIndex) deviceIndex = DeviceEnumerator::instance()->getFileOutputDeviceIndex(); // create a file output by default } - sampleSinkImplement(deviceSetIndex, deviceIndex, deviceAPI, m_deviceUIs.back(), workspace); + sampleSinkCreate(deviceSetIndex, deviceIndex, deviceAPI, m_deviceUIs.back()); + m_deviceUIs.back()->m_deviceGUI->setWorkspaceIndex(workspace->getIndex()); + m_deviceUIs.back()->m_mainSpectrumGUI->setWorkspaceIndex(workspace->getIndex()); + + QObject::connect( + m_deviceUIs.back()->m_mainSpectrumGUI, + &MainSpectrumGUI::moveToWorkspace, + this, + [=](int wsIndexDest){ this->mainSpectrumMove(m_deviceUIs.back()->m_mainSpectrumGUI, wsIndexDest); } + ); + + workspace->addToMdiArea(m_deviceUIs.back()->m_deviceGUI); + workspace->addToMdiArea(m_deviceUIs.back()->m_mainSpectrumGUI); emit m_mainCore->deviceSetAdded(deviceSetIndex, deviceAPI); } -void MainWindow::sampleSinkImplement( +void MainWindow::sampleSinkCreate( int deviceSetIndex, int deviceIndex, DeviceAPI *deviceAPI, - DeviceUISet *deviceUISet, - Workspace *workspace + DeviceUISet *deviceUISet ) { int selectedDeviceIndex = deviceIndex; @@ -669,15 +700,23 @@ void MainWindow::sampleSinkImplement( ); deviceAPI->getSampleSink()->setMessageQueueToGUI(deviceGUI->getInputMessageQueue()); deviceUISet->m_deviceGUI = deviceGUI; + const PluginInterface::SamplingDevice *selectedDevice = DeviceEnumerator::instance()->getRxSamplingDevice(selectedDeviceIndex); + deviceUISet->m_selectedDeviceId = selectedDevice->id; + deviceUISet->m_selectedDeviceSerial = selectedDevice->serial; + deviceUISet->m_selectedDeviceSequence = selectedDevice->sequence; + deviceUISet->m_selectedDeviceItemImdex = selectedDevice->deviceItemIndex; deviceUISet->m_deviceAPI->getSampleSink()->init(); // Finalize GUI setup and add it to workspace MDI deviceGUI->setDeviceType(DeviceGUI::DeviceTx); deviceGUI->setIndex(deviceSetIndex); - deviceGUI->setWorkspaceIndex(workspace->getIndex()); deviceGUI->setToolTip(samplingDevice->displayedName); deviceGUI->setTitle(samplingDevice->displayedName.split(" ")[0]); deviceGUI->setCurrentDeviceIndex(selectedDeviceIndex); - workspace->addToMdiArea((QMdiSubWindow*) deviceGUI); + MainSpectrumGUI *spectrumGUI = deviceUISet->m_mainSpectrumGUI; + spectrumGUI->setDeviceType(MainSpectrumGUI::DeviceTx); + spectrumGUI->setIndex(deviceSetIndex); + spectrumGUI->setToolTip(samplingDevice->displayedName); + spectrumGUI->setTitle(samplingDevice->displayedName.split(" ")[0]); } void MainWindow::sampleMIMOAdd(Workspace *workspace, int deviceIndex) @@ -723,16 +762,27 @@ void MainWindow::sampleMIMOAdd(Workspace *workspace, int deviceIndex) deviceIndex = DeviceEnumerator::instance()->getTestMIMODeviceIndex(); // create a test MIMO by default } - sampleMIMOImplement(deviceSetIndex, deviceIndex, deviceAPI, m_deviceUIs.back(), workspace); + sampleMIMOCreate(deviceSetIndex, deviceIndex, deviceAPI, m_deviceUIs.back()); + m_deviceUIs.back()->m_deviceGUI->setWorkspaceIndex(workspace->getIndex()); + m_deviceUIs.back()->m_mainSpectrumGUI->setWorkspaceIndex(workspace->getIndex()); + + QObject::connect( + m_deviceUIs.back()->m_mainSpectrumGUI, + &MainSpectrumGUI::moveToWorkspace, + this, + [=](int wsIndexDest){ this->mainSpectrumMove(m_deviceUIs.back()->m_mainSpectrumGUI, wsIndexDest); } + ); + + workspace->addToMdiArea(m_deviceUIs.back()->m_deviceGUI); + workspace->addToMdiArea(m_deviceUIs.back()->m_mainSpectrumGUI); emit m_mainCore->deviceSetAdded(deviceSetIndex, deviceAPI); } -void MainWindow::sampleMIMOImplement( +void MainWindow::sampleMIMOCreate( int deviceSetIndex, int deviceIndex, DeviceAPI *deviceAPI, - DeviceUISet *deviceUISet, - Workspace *workspace + DeviceUISet *deviceUISet ) { int selectedDeviceIndex = deviceIndex; @@ -806,20 +856,28 @@ void MainWindow::sampleMIMOImplement( ); deviceAPI->getSampleMIMO()->setMessageQueueToGUI(deviceGUI->getInputMessageQueue()); deviceUISet->m_deviceGUI = deviceGUI; + const PluginInterface::SamplingDevice *selectedDevice = DeviceEnumerator::instance()->getRxSamplingDevice(selectedDeviceIndex); + deviceUISet->m_selectedDeviceId = selectedDevice->id; + deviceUISet->m_selectedDeviceSerial = selectedDevice->serial; + deviceUISet->m_selectedDeviceSequence = selectedDevice->sequence; + deviceUISet->m_selectedDeviceItemImdex = selectedDevice->deviceItemIndex; deviceUISet->m_deviceAPI->getSampleMIMO()->init(); // Finalize GUI setup and add it to workspace MDI deviceGUI->setDeviceType(DeviceGUI::DeviceMIMO); deviceGUI->setIndex(deviceSetIndex); - deviceGUI->setWorkspaceIndex(workspace->getIndex()); deviceGUI->setToolTip(samplingDevice->displayedName); deviceGUI->setTitle(samplingDevice->displayedName.split(" ")[0]); deviceGUI->setCurrentDeviceIndex(selectedDeviceIndex); - workspace->addToMdiArea((QMdiSubWindow*) deviceGUI); + MainSpectrumGUI *spectrumGUI = deviceUISet->m_mainSpectrumGUI; + spectrumGUI->setDeviceType(MainSpectrumGUI::DeviceMIMO); + spectrumGUI->setIndex(deviceSetIndex); + spectrumGUI->setToolTip(samplingDevice->displayedName); + spectrumGUI->setTitle(samplingDevice->displayedName.split(" ")[0]); } void MainWindow::removeLastDevice() { - int removedTabIndex = m_deviceUIs.size() - 1; + int removedDeviceSetIndex = m_deviceUIs.size() - 1; if (m_deviceUIs.back()->m_deviceSourceEngine) // source tab { @@ -837,12 +895,12 @@ void MainWindow::removeLastDevice() m_deviceUIs.back()->m_deviceGUI->destroy(); m_deviceUIs.back()->m_deviceAPI->resetSamplingDeviceId(); m_deviceUIs.back()->m_deviceAPI->getPluginInterface()->deleteSampleSourcePluginInstanceInput( - m_deviceUIs.back()->m_deviceAPI->getSampleSource()); + m_deviceUIs.back()->m_deviceAPI->getSampleSource()); m_deviceUIs.back()->m_deviceAPI->clearBuddiesLists(); // clear old API buddies lists // ui->tabChannels->removeTab(ui->tabChannels->count() - 1); - m_deviceWidgetTabs.removeLast(); + // m_deviceWidgetTabs.removeLast(); // restoreDeviceTabs(); DeviceAPI *sourceAPI = m_deviceUIs.back()->m_deviceAPI; @@ -869,12 +927,12 @@ void MainWindow::removeLastDevice() m_deviceUIs.back()->m_deviceGUI->destroy(); m_deviceUIs.back()->m_deviceAPI->resetSamplingDeviceId(); m_deviceUIs.back()->m_deviceAPI->getPluginInterface()->deleteSampleSinkPluginInstanceOutput( - m_deviceUIs.back()->m_deviceAPI->getSampleSink()); + m_deviceUIs.back()->m_deviceAPI->getSampleSink()); m_deviceUIs.back()->m_deviceAPI->clearBuddiesLists(); // clear old API buddies lists // ui->tabChannels->removeTab(ui->tabChannels->count() - 1); - m_deviceWidgetTabs.removeLast(); + // m_deviceWidgetTabs.removeLast(); // restoreDeviceTabs(); DeviceAPI *sinkAPI = m_deviceUIs.back()->m_deviceAPI; @@ -902,11 +960,11 @@ void MainWindow::removeLastDevice() m_deviceUIs.back()->m_deviceGUI->destroy(); m_deviceUIs.back()->m_deviceAPI->resetSamplingDeviceId(); m_deviceUIs.back()->m_deviceAPI->getPluginInterface()->deleteSampleMIMOPluginInstanceMIMO( - m_deviceUIs.back()->m_deviceAPI->getSampleMIMO()); + m_deviceUIs.back()->m_deviceAPI->getSampleMIMO()); // ui->tabChannels->removeTab(ui->tabChannels->count() - 1); - m_deviceWidgetTabs.removeLast(); + // m_deviceWidgetTabs.removeLast(); // restoreDeviceTabs(); DeviceAPI *mimoAPI = m_deviceUIs.back()->m_deviceAPI; @@ -920,7 +978,7 @@ void MainWindow::removeLastDevice() m_deviceUIs.pop_back(); m_mainCore->removeLastDeviceSet(); - emit m_mainCore->deviceSetRemoved(removedTabIndex); + emit m_mainCore->deviceSetRemoved(removedDeviceSetIndex); } void MainWindow::addFeatureSet() @@ -990,75 +1048,41 @@ void MainWindow::loadSettings() m_mainCore->setLoggingOptions(); } -void MainWindow::loadPresetSettings(const Preset* preset, int tabIndex) +void MainWindow::loadDeviceSetPresetSettings(const Preset* preset, int deviceSetIndex) { - qDebug("MainWindow::loadPresetSettings: preset [%s | %s]", + qDebug("MainWindow::loadDeviceSetPresetSettings: preset [%s | %s]", qPrintable(preset->getGroup()), qPrintable(preset->getDescription())); - if (tabIndex >= 0) + if (deviceSetIndex >= 0) { - DeviceUISet *deviceUI = m_deviceUIs[tabIndex]; - deviceUI->m_spectrumGUI->deserialize(preset->getSpectrumConfig()); - deviceUI->m_deviceAPI->loadSamplingDeviceSettings(preset); - - if (deviceUI->m_deviceSourceEngine) { // source device - deviceUI->loadRxChannelSettings(preset, m_pluginManager->getPluginAPI()); - } else if (deviceUI->m_deviceSinkEngine) { // sink device - deviceUI->loadTxChannelSettings(preset, m_pluginManager->getPluginAPI()); - } else if (deviceUI->m_deviceMIMOEngine) { // MIMO device - deviceUI->loadMIMOChannelSettings(preset, m_pluginManager->getPluginAPI()); - } + DeviceUISet *deviceUISet = m_deviceUIs[deviceSetIndex]; + deviceUISet->loadDeviceSetSettings(preset, m_pluginManager->getPluginAPI(), &m_workspaces, nullptr); } - m_spectrumToggleViewAction->setChecked(preset->getShowSpectrum()); + // m_spectrumToggleViewAction->setChecked(preset->getShowSpectrum()); - // has to be last step - if (!preset->getLayout().isEmpty()) { - restoreState(preset->getLayout()); - } + // // has to be last step + // if (!preset->getLayout().isEmpty()) { + // restoreState(preset->getLayout()); + // } // tabifyDockWidget(ui->presetDock, ui->commandsDock); // override this setting // ui->presetDock->raise(); } -void MainWindow::savePresetSettings(Preset* preset, int tabIndex) +void MainWindow::saveDeviceSetPresetSettings(Preset* preset, int deviceSetIndex) { - qDebug("MainWindow::savePresetSettings: preset [%s | %s]", + qDebug("MainWindow::saveDeviceSetPresetSettings: preset [%s | %s]", qPrintable(preset->getGroup()), qPrintable(preset->getDescription())); // Save from currently selected source tab //int currentSourceTabIndex = ui->tabInputsView->currentIndex(); - DeviceUISet *deviceUI = m_deviceUIs[tabIndex]; - - if (deviceUI->m_deviceSourceEngine) // source device - { - preset->setSpectrumConfig(deviceUI->m_spectrumGUI->serialize()); - preset->clearChannels(); - preset->setSourcePreset(); - deviceUI->saveRxChannelSettings(preset); - deviceUI->m_deviceAPI->saveSamplingDeviceSettings(preset); - } - else if (deviceUI->m_deviceSinkEngine) // sink device - { - preset->setSpectrumConfig(deviceUI->m_spectrumGUI->serialize()); - preset->clearChannels(); - preset->setSinkPreset(); - deviceUI->saveTxChannelSettings(preset); - deviceUI->m_deviceAPI->saveSamplingDeviceSettings(preset); - } - else if (deviceUI->m_deviceMIMOEngine) // MIMO device - { - preset->setSpectrumConfig(deviceUI->m_spectrumGUI->serialize()); - preset->clearChannels(); - preset->setMIMOPreset(); - deviceUI->saveMIMOChannelSettings(preset); - deviceUI->m_deviceAPI->saveSamplingDeviceSettings(preset); - } - - preset->setShowSpectrum(m_spectrumToggleViewAction->isChecked()); - preset->setLayout(saveState()); + DeviceUISet *deviceUISet = m_deviceUIs[deviceSetIndex]; + deviceUISet->saveDeviceSetSettings(preset); + // preset->setShowSpectrum(m_spectrumToggleViewAction->isChecked()); + // preset->setLayout(saveState()); } void MainWindow::loadFeatureSetPresetSettings(const FeatureSetPreset* preset, int featureSetIndex, Workspace *workspace) @@ -1071,7 +1095,7 @@ void MainWindow::loadFeatureSetPresetSettings(const FeatureSetPreset* preset, in { FeatureUISet *featureSetUI = m_featureUIs[featureSetIndex]; qDebug("MainWindow::loadFeatureSetPresetSettings: m_apiAdapter: %p", m_apiAdapter); - featureSetUI->loadFeatureSetSettings(preset, m_pluginManager->getPluginAPI(), m_apiAdapter, workspace); + featureSetUI->loadFeatureSetSettings(preset, m_pluginManager->getPluginAPI(), m_apiAdapter, &m_workspaces, workspace); } } @@ -1091,14 +1115,20 @@ void MainWindow::saveFeatureSetPresetSettings(FeatureSetPreset* preset, int feat void MainWindow::loadConfiguration(const Configuration *configuration) { - qDebug("MainWindow::loadConfiguration: configuration [%s | %s] %d workspaces", + qDebug("MainWindow::loadConfiguration: configuration [%s | %s] %d workspace(s) - %d device set(s) - %d feature(s)", qPrintable(configuration->getGroup()), qPrintable(configuration->getDescription()), - configuration->getNumberOfWorkspaces() + configuration->getNumberOfWorkspaces(), + configuration->getDeviceSetPresets().size(), + configuration->getFeatureSetPreset().getFeatureCount() ); // Wipe out everything first + // Device sets + while (m_deviceUIs.size() > 0) { + removeLastDevice(); + } // Features m_featureUIs[0]->freeFeatures(); // Workspaces @@ -1113,8 +1143,66 @@ void MainWindow::loadConfiguration(const Configuration *configuration) for (int i = 0; i < configuration->getNumberOfWorkspaces(); i++) { addWorkspace(); } + + if (m_workspaces.size() <= 0) { // cannot go further if there are no workspaces + return; + } + + // Device sets + const QList& deviceSetPresets = configuration->getDeviceSetPresets(); + + for (const auto& deviceSetPreset : deviceSetPresets) + { + if (deviceSetPreset.isSourcePreset()) + { + int bestDeviceIndex = DeviceEnumerator::instance()->getBestRxSamplingDeviceIndex( + deviceSetPreset.getSelectedDevice().m_deviceId, + deviceSetPreset.getSelectedDevice().m_deviceSerial, + deviceSetPreset.getSelectedDevice().m_deviceSequence, + deviceSetPreset.getSelectedDevice().m_deviceItemIndex + ); + int workspaceIndex = deviceSetPreset.getDeviceWorkspaceIndex() < m_workspaces.size() ? + deviceSetPreset.getDeviceWorkspaceIndex() : + 0; + sampleSourceAdd(m_workspaces[workspaceIndex], bestDeviceIndex); + } + else if (deviceSetPreset.isSinkPreset()) + { + int bestDeviceIndex = DeviceEnumerator::instance()->getBestTxSamplingDeviceIndex( + deviceSetPreset.getSelectedDevice().m_deviceId, + deviceSetPreset.getSelectedDevice().m_deviceSerial, + deviceSetPreset.getSelectedDevice().m_deviceSequence, + deviceSetPreset.getSelectedDevice().m_deviceItemIndex + ); + int workspaceIndex = deviceSetPreset.getDeviceWorkspaceIndex() < m_workspaces.size() ? + deviceSetPreset.getDeviceWorkspaceIndex() : + 0; + sampleSinkAdd(m_workspaces[workspaceIndex], bestDeviceIndex); + } else if (deviceSetPreset.isMIMOPreset()) + { + int bestDeviceIndex = DeviceEnumerator::instance()->getBestMIMOSamplingDeviceIndex( + deviceSetPreset.getSelectedDevice().m_deviceId, + deviceSetPreset.getSelectedDevice().m_deviceSerial, + deviceSetPreset.getSelectedDevice().m_deviceSequence + ); + int workspaceIndex = deviceSetPreset.getDeviceWorkspaceIndex() < m_workspaces.size() ? + deviceSetPreset.getDeviceWorkspaceIndex() : + 0; + sampleMIMOAdd(m_workspaces[workspaceIndex], bestDeviceIndex); + } + + m_deviceUIs.back()->m_deviceGUI->restoreGeometry(deviceSetPreset.getDeviceGeometry()); + m_deviceUIs.back()->m_mainSpectrumGUI->restoreGeometry(deviceSetPreset.getSpectrumGeometry()); + m_deviceUIs.back()->loadDeviceSetSettings(&deviceSetPreset, m_pluginManager->getPluginAPI(), &m_workspaces, nullptr); + } // Features - m_featureUIs[0]->loadFeatureSetSettings(&configuration->getFeatureSetPreset(), m_pluginManager->getPluginAPI(), m_apiAdapter, m_workspaces); + m_featureUIs[0]->loadFeatureSetSettings( + &configuration->getFeatureSetPreset(), + m_pluginManager->getPluginAPI(), + m_apiAdapter, + &m_workspaces, + nullptr + ); for (int i = 0; i < m_featureUIs[0]->getNumberOfFeatures(); i++) { @@ -1142,6 +1230,18 @@ void MainWindow::saveConfiguration(Configuration *configuration) ); configuration->clearData(); + QList& deviceSetPresets = configuration->getDeviceSetPresets(); + + for (const auto& deviceUISet : m_deviceUIs) + { + deviceSetPresets.push_back(Preset()); + deviceUISet->saveDeviceSetSettings(&deviceSetPresets.back()); + deviceSetPresets.back().setSpectrumGeometry(deviceUISet->m_mainSpectrumGUI->saveGeometry()); + deviceSetPresets.back().setSpectrumWorkspaceIndex(deviceUISet->m_mainSpectrumGUI->getWorkspaceIndex()); + deviceSetPresets.back().setDeviceGeometry(deviceUISet->m_deviceGUI->saveGeometry()); + deviceSetPresets.back().setDeviceWorkspaceIndex(deviceUISet->m_deviceGUI->getWorkspaceIndex()); + } + m_featureUIs[0]->saveFeatureSetSettings(&configuration->getFeatureSetPreset()); for (const auto& workspace : m_workspaces) { @@ -1279,15 +1379,14 @@ void MainWindow::closeEvent(QCloseEvent *closeEvent) s.setValue("mainWindowGeometry", qCompress(saveGeometry()).toBase64()); s.setValue("mainWindowState", qCompress(saveState()).toBase64()); - // savePresetSettings(m_mainCore->m_settings.getWorkingPreset(), 0); + // saveDeviceSetPresetSettings(m_mainCore->m_settings.getWorkingPreset(), 0); // saveFeatureSetPresetSettings(m_mainCore->m_settings.getWorkingFeatureSetPreset(), 0); saveConfiguration(m_mainCore->m_settings.getWorkingConfiguration()); m_mainCore->m_settings.save(); - // while (m_deviceUIs.size() > 0) - // { - // removeLastDevice(); - // } + while (m_deviceUIs.size() > 0) { + removeLastDevice(); + } closeEvent->accept(); } @@ -1348,13 +1447,13 @@ QTreeWidgetItem* MainWindow::addPresetToTree(const Preset* preset) void MainWindow::applySettings() { - // loadPresetSettings(m_mainCore->m_settings.getWorkingPreset(), 0); + // loadDeviceSetPresetSettings(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; - QTreeWidgetItem *treeItem; + // int middleIndex = m_mainCore->m_settings.getPresetCount() / 2; + // QTreeWidgetItem *treeItem; // ui->presetTree->clear(); // for (int i = 0; i < m_mainCore->m_settings.getPresetCount(); ++i) @@ -1381,13 +1480,13 @@ bool MainWindow::handleMessage(const Message& cmd) if (MainCore::MsgLoadPreset::match(cmd)) { MainCore::MsgLoadPreset& notif = (MainCore::MsgLoadPreset&) cmd; - loadPresetSettings(notif.getPreset(), notif.getDeviceSetIndex()); + loadDeviceSetPresetSettings(notif.getPreset(), notif.getDeviceSetIndex()); return true; } else if (MainCore::MsgSavePreset::match(cmd)) { // MainCore::MsgSavePreset& notif = (MainCore::MsgSavePreset&) cmd; - // savePresetSettings(notif.getPreset(), notif.getDeviceSetIndex()); + // saveDeviceSetPresetSettings(notif.getPreset(), notif.getDeviceSetIndex()); // if (notif.isNewPreset()) { ui->presetTree->setCurrentItem(addPresetToTree(notif.getPreset())); } // m_mainCore->m_settings.sortPresets(); // m_mainCore->m_settings.save(); @@ -1747,7 +1846,7 @@ void MainWindow::on_presetSave_clicked() // if(dlg.exec() == QDialog::Accepted) { // Preset* preset = m_mainCore->m_settings.newPreset(dlg.group(), dlg.description()); - // savePresetSettings(preset, ui->tabInputsView->currentIndex()); + // saveDeviceSetPresetSettings(preset, ui->tabInputsView->currentIndex()); // ui->presetTree->setCurrentItem(addPresetToTree(preset)); // } @@ -1769,7 +1868,7 @@ void MainWindow::on_presetUpdate_clicked() // if (preset != 0) // { // Preset* preset_mod = const_cast(preset); - // savePresetSettings(preset_mod, ui->tabInputsView->currentIndex()); + // saveDeviceSetPresetSettings(preset_mod, ui->tabInputsView->currentIndex()); // changedPreset = preset; // } // } @@ -1943,7 +2042,7 @@ void MainWindow::on_presetImport_clicked() void MainWindow::on_action_saveAll_triggered() { - // savePresetSettings(m_mainCore->m_settings.getWorkingPreset(), ui->tabInputsView->currentIndex()); + // saveDeviceSetPresetSettings(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(); @@ -1971,7 +2070,7 @@ void MainWindow::on_presetLoad_clicked() // return; // } - // loadPresetSettings(preset, ui->tabInputsView->currentIndex()); + // loadDeviceSetPresetSettings(preset, ui->tabInputsView->currentIndex()); } void MainWindow::on_presetDelete_clicked() @@ -2215,7 +2314,9 @@ void MainWindow::sampleSourceChange(int deviceSetIndex, int newDeviceIndex, Work deviceUISet->m_deviceAPI->getPluginInterface()->deleteSampleSourcePluginInstanceInput(deviceUISet->m_deviceAPI->getSampleSource()); deviceUISet->m_deviceAPI->clearBuddiesLists(); // clear old API buddies lists - sampleSourceImplement(deviceSetIndex, newDeviceIndex, deviceUISet->m_deviceAPI, deviceUISet, workspace); + sampleSourceCreate(deviceSetIndex, newDeviceIndex, deviceUISet->m_deviceAPI, deviceUISet); + deviceUISet->m_deviceGUI->setWorkspaceIndex(workspace->getIndex()); + workspace->addToMdiArea(deviceUISet->m_deviceGUI); } } @@ -2235,7 +2336,9 @@ void MainWindow::sampleSinkChange(int deviceSetIndex, int newDeviceIndex, Worksp deviceUISet->m_deviceAPI->getPluginInterface()->deleteSampleSinkPluginInstanceOutput(deviceUISet->m_deviceAPI->getSampleSink()); deviceUISet->m_deviceAPI->clearBuddiesLists(); // clear old API buddies lists - sampleSinkImplement(deviceSetIndex, newDeviceIndex, deviceUISet->m_deviceAPI, deviceUISet, workspace); + sampleSourceCreate(deviceSetIndex, newDeviceIndex, deviceUISet->m_deviceAPI, deviceUISet); + deviceUISet->m_deviceGUI->setWorkspaceIndex(workspace->getIndex()); + workspace->addToMdiArea(deviceUISet->m_deviceGUI); } } @@ -2254,7 +2357,9 @@ void MainWindow::sampleMIMOChange(int deviceSetIndex, int newDeviceIndex, Worksp deviceUISet->m_deviceAPI->resetSamplingDeviceId(); deviceUISet->m_deviceAPI->getPluginInterface()->deleteSampleMIMOPluginInstanceMIMO(deviceUISet->m_deviceAPI->getSampleMIMO()); - sampleMIMOImplement(deviceSetIndex, deviceSetIndex, deviceUISet->m_deviceAPI, deviceUISet, workspace); + sampleSourceCreate(deviceSetIndex, newDeviceIndex, deviceUISet->m_deviceAPI, deviceUISet); + deviceUISet->m_deviceGUI->setWorkspaceIndex(workspace->getIndex()); + workspace->addToMdiArea(deviceUISet->m_deviceGUI); } } @@ -2383,6 +2488,19 @@ void MainWindow::deviceMove(DeviceGUI *gui, int wsIndexDestnation) m_workspaces[wsIndexDestnation]->addToMdiArea(gui); } +void MainWindow::mainSpectrumMove(MainSpectrumGUI *gui, int wsIndexDestnation) +{ + int wsIndexOrigin = gui->getWorkspaceIndex(); + + if (wsIndexOrigin == wsIndexDestnation) { + return; + } + + m_workspaces[wsIndexOrigin]->removeFromMdiArea(gui); + gui->setWorkspaceIndex(wsIndexDestnation); + m_workspaces[wsIndexDestnation]->addToMdiArea(gui); +} + void MainWindow::openFeaturePresetsDialog(QPoint p, Workspace *workspace) { FeaturePresetsDialog dialog; @@ -2390,7 +2508,8 @@ void MainWindow::openFeaturePresetsDialog(QPoint p, Workspace *workspace) dialog.setPresets(m_mainCore->m_settings.getFeatureSetPresets()); dialog.setPluginAPI(m_pluginManager->getPluginAPI()); dialog.setWebAPIAdapter(m_apiAdapter); - dialog.setWorkspace(workspace); + dialog.setCurrentWorkspace(workspace); + dialog.setWorkspaces(&m_workspaces); dialog.populateTree(); dialog.move(p); dialog.exec(); diff --git a/sdrgui/mainwindow.h b/sdrgui/mainwindow.h index 65d2673b8..1a5151365 100644 --- a/sdrgui/mainwindow.h +++ b/sdrgui/mainwindow.h @@ -40,6 +40,7 @@ class DSPDeviceSourceEngine; class DSPDeviceSinkEngine; class Indicator; class GLSpectrumGUI; +class MainSpectrumGUI; class PluginAPI; class ChannelGUI; class ChannelMarker; @@ -123,8 +124,8 @@ private: QProcess *m_fftWisdomProcess; void loadSettings(); - void loadPresetSettings(const Preset* preset, int tabIndex); - void savePresetSettings(Preset* preset, int tabIndex); + void loadDeviceSetPresetSettings(const Preset* preset, int deviceSetIndex); + void saveDeviceSetPresetSettings(Preset* preset, int deviceSetIndex); void loadFeatureSetPresetSettings(const FeatureSetPreset* preset, int featureSetIndex, Workspace *workspace); void saveFeatureSetPresetSettings(FeatureSetPreset* preset, int featureSetIndex); @@ -145,26 +146,23 @@ private: void sampleSourceChange(int deviceSetIndex, int newDeviceIndex, Workspace *workspace); void sampleSinkChange(int deviceSetIndex, int newDeviceIndex, Workspace *workspace); void sampleMIMOChange(int deviceSetIndex, int newDeviceIndex, Workspace *workspace); - void sampleSourceImplement( + void sampleSourceCreate( int deviceSetIndex, int deviceIndex, DeviceAPI *deviceAPI, - DeviceUISet *deviceUISet, - Workspace *workspace + DeviceUISet *deviceUISet ); - void sampleSinkImplement( + void sampleSinkCreate( int deviceSetIndex, int deviceIndex, DeviceAPI *deviceAPI, - DeviceUISet *deviceUISet, - Workspace *workspace + DeviceUISet *deviceUISet ); - void sampleMIMOImplement( + void sampleMIMOCreate( int deviceSetIndex, int deviceIndex, DeviceAPI *deviceAPI, - DeviceUISet *deviceUISet, - Workspace *workspace + DeviceUISet *deviceUISet ); void deleteFeature(int featureSetIndex, int featureIndex); @@ -209,6 +207,7 @@ private slots: void featureMove(FeatureGUI *gui, int wsIndexDestnation); void openFeaturePresetsDialog(QPoint p, Workspace *workspace); void deviceMove(DeviceGUI *gui, int wsIndexDestnation); + void mainSpectrumMove(MainSpectrumGUI *gui, int wsIndexDestnation); void on_action_Quick_Start_triggered(); void on_action_Main_Window_triggered(); void on_action_Loaded_Plugins_triggered(); diff --git a/sdrgui/resources/channels.png b/sdrgui/resources/channels.png new file mode 100644 index 000000000..14c223fe4 Binary files /dev/null and b/sdrgui/resources/channels.png differ diff --git a/sdrgui/resources/channels_add.png b/sdrgui/resources/channels_add.png new file mode 100644 index 000000000..29011351a Binary files /dev/null and b/sdrgui/resources/channels_add.png differ diff --git a/sdrgui/resources/res.qrc b/sdrgui/resources/res.qrc index bb851fc62..4b39bd761 100644 --- a/sdrgui/resources/res.qrc +++ b/sdrgui/resources/res.qrc @@ -117,6 +117,8 @@ tx.png mimo.png tool.png + tool_add.png + tool_star.png gear.png corner_topleft.png corner_topright.png @@ -130,6 +132,8 @@ shrink.png exit.png hide.png + channels.png + channels_add.png LiberationMono-Regular.ttf LiberationSans-Regular.ttf diff --git a/sdrgui/resources/tool_add.png b/sdrgui/resources/tool_add.png new file mode 100644 index 000000000..479974212 Binary files /dev/null and b/sdrgui/resources/tool_add.png differ diff --git a/sdrgui/resources/tool_star.png b/sdrgui/resources/tool_star.png new file mode 100644 index 000000000..530c6a6b1 Binary files /dev/null and b/sdrgui/resources/tool_star.png differ