diff --git a/owrx/controllers/settings/sdr.py b/owrx/controllers/settings/sdr.py index 524f1b1..6dfb68c 100644 --- a/owrx/controllers/settings/sdr.py +++ b/owrx/controllers/settings/sdr.py @@ -275,7 +275,7 @@ class NewSdrDeviceController(SettingsFormController): return [ Section( "New device settings", - TextInput("name", "Device name"), + TextInput("name", "Device name", validator=RequiredValidator()), DropdownInput("type", "Device type", [Option(name, name) for name in SdrDeviceDescription.getTypes()]), TextInput("id", "Device ID", validator=RequiredValidator()), ) diff --git a/owrx/source/__init__.py b/owrx/source/__init__.py index a5fb7db..dcdf338 100644 --- a/owrx/source/__init__.py +++ b/owrx/source/__init__.py @@ -15,6 +15,7 @@ from owrx.property.filter import ByLambda from owrx.form import Input, TextInput, NumberInput, CheckboxInput, ModesInput, ExponentialInput from owrx.form.converter import OptionalConverter from owrx.form.device import GainInput, SchedulerInput, WaterfallLevelsInput +from owrx.form.validator import RequiredValidator from owrx.controllers.settings import Section from typing import List from enum import Enum @@ -520,7 +521,9 @@ class OptionalSection(Section): def parse(self, data): data, errors = super().parse(data) - # remove optional keys if they have been removed from the form + # filter out errors for optional fields + errors = [e for e in errors if e.getKey() not in self.optional or e.getKey() in data] + # remove optional keys if they have been removed from the form by setting them to None for k in self.optional: if k not in data: data[k] = None @@ -550,10 +553,16 @@ class SdrDeviceDescription(object): return [module_name for _, module_name, _ in pkgutil.walk_packages(__path__) if has_description(module_name)] def getDeviceInputs(self) -> List[Input]: - return [TextInput("name", "Device name")] + self.getInputs() + keys = self.getDeviceMandatoryKeys() + self.getDeviceOptionalKeys() + return [TextInput("name", "Device name", validator=RequiredValidator())] + [ + i for i in self.getInputs() if i.id in keys + ] def getProfileInputs(self) -> List[Input]: - return [TextInput("name", "Profile name")] + self.getInputs() + keys = self.getProfileMandatoryKeys() + self.getProfileOptionalKeys() + return [TextInput("name", "Profile name", validator=RequiredValidator())] + [ + i for i in self.getInputs() if i.id in keys + ] def getInputs(self) -> List[Input]: return [ @@ -593,10 +602,10 @@ class SdrDeviceDescription(object): # default is True since most devices have agc. override in subclasses if agc is not available return True - def getMandatoryKeys(self): + def getDeviceMandatoryKeys(self): return ["name", "enabled"] - def getOptionalKeys(self): + def getDeviceOptionalKeys(self): return [ "ppm", "always-on", @@ -615,7 +624,7 @@ class SdrDeviceDescription(object): def getDeviceSection(self): return OptionalSection( - "Device settings", self.getDeviceInputs(), self.getMandatoryKeys(), self.getOptionalKeys() + "Device settings", self.getDeviceInputs(), self.getDeviceMandatoryKeys(), self.getDeviceOptionalKeys() ) def getProfileSection(self): diff --git a/owrx/source/airspy.py b/owrx/source/airspy.py index a6b64ff..ab201dd 100644 --- a/owrx/source/airspy.py +++ b/owrx/source/airspy.py @@ -31,8 +31,8 @@ class AirspyDeviceDescription(SoapyConnectorDeviceDescription): ), ] - def getOptionalKeys(self): - return super().getOptionalKeys() + ["bias_tee", "bitpack"] + def getDeviceOptionalKeys(self): + return super().getDeviceOptionalKeys() + ["bias_tee", "bitpack"] def getProfileOptionalKeys(self): return super().getProfileOptionalKeys() + ["bias_tee"] diff --git a/owrx/source/connector.py b/owrx/source/connector.py index 6789e3f..67b91df 100644 --- a/owrx/source/connector.py +++ b/owrx/source/connector.py @@ -90,8 +90,8 @@ class ConnectorDeviceDescription(SdrDeviceDescription): ), ] - def getOptionalKeys(self): - return super().getOptionalKeys() + ["rtltcp_compat", "iqswap"] + def getDeviceOptionalKeys(self): + return super().getDeviceOptionalKeys() + ["rtltcp_compat", "iqswap"] def getProfileOptionalKeys(self): return super().getProfileOptionalKeys() + ["iqswap"] diff --git a/owrx/source/hackrf.py b/owrx/source/hackrf.py index fbbab7d..db67d0b 100644 --- a/owrx/source/hackrf.py +++ b/owrx/source/hackrf.py @@ -18,8 +18,8 @@ class HackrfDeviceDescription(SoapyConnectorDeviceDescription): def getInputs(self) -> List[Input]: return super().getInputs() + [BiasTeeInput()] - def getOptionalKeys(self): - return super().getOptionalKeys() + ["bias_tee"] + def getDeviceOptionalKeys(self): + return super().getDeviceOptionalKeys() + ["bias_tee"] def getProfileOptionalKeys(self): return super().getProfileOptionalKeys() + ["bias_tee"] diff --git a/owrx/source/perseussdr.py b/owrx/source/perseussdr.py index 5d0dacc..3a8d4d4 100644 --- a/owrx/source/perseussdr.py +++ b/owrx/source/perseussdr.py @@ -58,9 +58,9 @@ class PerseussdrDeviceDescription(DirectSourceDeviceDescription): CheckboxInput("wideband", "Disable analog filters"), ] - def getOptionalKeys(self): + def getDeviceOptionalKeys(self): # no rf_gain - return [key for key in super().getOptionalKeys() if key != "rf_gain"] + [ + return [key for key in super().getDeviceOptionalKeys() if key != "rf_gain"] + [ "attenuator", "adc_preamp", "adc_dither", diff --git a/owrx/source/rtl_sdr.py b/owrx/source/rtl_sdr.py index f725e3d..1c84ab0 100644 --- a/owrx/source/rtl_sdr.py +++ b/owrx/source/rtl_sdr.py @@ -27,8 +27,8 @@ class RtlSdrDeviceDescription(ConnectorDeviceDescription): DirectSamplingInput(), ] - def getOptionalKeys(self): - return super().getOptionalKeys() + ["device", "bias_tee", "direct_sampling"] + def getDeviceOptionalKeys(self): + return super().getDeviceOptionalKeys() + ["device", "bias_tee", "direct_sampling"] def getProfileOptionalKeys(self): return super().getProfileOptionalKeys() + ["bias_tee", "direct_sampling"] diff --git a/owrx/source/rtl_sdr_soapy.py b/owrx/source/rtl_sdr_soapy.py index e437b80..8016e7c 100644 --- a/owrx/source/rtl_sdr_soapy.py +++ b/owrx/source/rtl_sdr_soapy.py @@ -18,8 +18,8 @@ class RtlSdrSoapyDeviceDescription(SoapyConnectorDeviceDescription): def getInputs(self) -> List[Input]: return super().getInputs() + [BiasTeeInput(), DirectSamplingInput()] - def getOptionalKeys(self): - return super().getOptionalKeys() + ["bias_tee", "direct_sampling"] + def getDeviceOptionalKeys(self): + return super().getDeviceOptionalKeys() + ["bias_tee", "direct_sampling"] def getProfileOptionalKeys(self): return super().getProfileOptionalKeys() + ["bias_tee", "direct_sampling"] diff --git a/owrx/source/rtl_tcp.py b/owrx/source/rtl_tcp.py index 5bf2712..3daec3f 100644 --- a/owrx/source/rtl_tcp.py +++ b/owrx/source/rtl_tcp.py @@ -25,5 +25,5 @@ class RtlTcpDeviceDescription(ConnectorDeviceDescription): def getInputs(self) -> List[Input]: return super().getInputs() + [RemoteInput()] - def getMandatoryKeys(self): - return super().getMandatoryKeys() + ["device"] + def getDeviceMandatoryKeys(self): + return super().getDeviceMandatoryKeys() + ["device"] diff --git a/owrx/source/runds.py b/owrx/source/runds.py index 224d65d..028c49d 100644 --- a/owrx/source/runds.py +++ b/owrx/source/runds.py @@ -44,8 +44,8 @@ class RundsDeviceDescription(ConnectorDeviceDescription): CheckboxInput("long", "Use 32-bit sample size (LONG)"), ] - def getMandatoryKeys(self): - return super().getMandatoryKeys() + ["device"] + def getDeviceMandatoryKeys(self): + return super().getDeviceMandatoryKeys() + ["device"] - def getOptionalKeys(self): - return super().getOptionalKeys() + ["protocol", "long"] + def getDeviceOptionalKeys(self): + return super().getDeviceOptionalKeys() + ["protocol", "long"] diff --git a/owrx/source/sdrplay.py b/owrx/source/sdrplay.py index 3bfb385..b3a7741 100644 --- a/owrx/source/sdrplay.py +++ b/owrx/source/sdrplay.py @@ -54,8 +54,8 @@ class SdrplayDeviceDescription(SoapyConnectorDeviceDescription): ), ] - def getOptionalKeys(self): - return super().getOptionalKeys() + ["bias_tee", "rf_notch", "dab_notch", "if_mode"] + def getDeviceOptionalKeys(self): + return super().getDeviceOptionalKeys() + ["bias_tee", "rf_notch", "dab_notch", "if_mode"] def getProfileOptionalKeys(self): return super().getProfileOptionalKeys() + ["bias_tee", "rf_notch", "dab_notch", "if_mode"] diff --git a/owrx/source/soapy.py b/owrx/source/soapy.py index 2597dcf..df3ce8a 100644 --- a/owrx/source/soapy.py +++ b/owrx/source/soapy.py @@ -98,8 +98,8 @@ class SoapyConnectorDeviceDescription(ConnectorDeviceDescription): TextInput("antenna", "Antenna"), ] - def getOptionalKeys(self): - return super().getOptionalKeys() + ["device", "rf_gain", "antenna"] + def getDeviceOptionalKeys(self): + return super().getDeviceOptionalKeys() + ["device", "rf_gain", "antenna"] def getProfileOptionalKeys(self): return super().getProfileOptionalKeys() + ["antenna"] diff --git a/owrx/source/soapy_remote.py b/owrx/source/soapy_remote.py index 19be5a5..c3ed174 100644 --- a/owrx/source/soapy_remote.py +++ b/owrx/source/soapy_remote.py @@ -29,5 +29,5 @@ class SoapyRemoteDeviceDescription(SoapyConnectorDeviceDescription): ), ] - def getOptionalKeys(self): - return super().getOptionalKeys() + ["remote_driver"] + def getDeviceOptionalKeys(self): + return super().getDeviceOptionalKeys() + ["remote_driver"]