fix form evaluation for optional fields

This commit is contained in:
Jakob Ketterl 2021-03-24 23:17:50 +01:00
parent 6ddced4689
commit 19496d46a3
13 changed files with 40 additions and 31 deletions

View File

@ -275,7 +275,7 @@ class NewSdrDeviceController(SettingsFormController):
return [ return [
Section( Section(
"New device settings", "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()]), DropdownInput("type", "Device type", [Option(name, name) for name in SdrDeviceDescription.getTypes()]),
TextInput("id", "Device ID", validator=RequiredValidator()), TextInput("id", "Device ID", validator=RequiredValidator()),
) )

View File

@ -15,6 +15,7 @@ from owrx.property.filter import ByLambda
from owrx.form import Input, TextInput, NumberInput, CheckboxInput, ModesInput, ExponentialInput from owrx.form import Input, TextInput, NumberInput, CheckboxInput, ModesInput, ExponentialInput
from owrx.form.converter import OptionalConverter from owrx.form.converter import OptionalConverter
from owrx.form.device import GainInput, SchedulerInput, WaterfallLevelsInput from owrx.form.device import GainInput, SchedulerInput, WaterfallLevelsInput
from owrx.form.validator import RequiredValidator
from owrx.controllers.settings import Section from owrx.controllers.settings import Section
from typing import List from typing import List
from enum import Enum from enum import Enum
@ -520,7 +521,9 @@ class OptionalSection(Section):
def parse(self, data): def parse(self, data):
data, errors = super().parse(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: for k in self.optional:
if k not in data: if k not in data:
data[k] = None 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)] return [module_name for _, module_name, _ in pkgutil.walk_packages(__path__) if has_description(module_name)]
def getDeviceInputs(self) -> List[Input]: 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]: 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]: def getInputs(self) -> List[Input]:
return [ return [
@ -593,10 +602,10 @@ class SdrDeviceDescription(object):
# default is True since most devices have agc. override in subclasses if agc is not available # default is True since most devices have agc. override in subclasses if agc is not available
return True return True
def getMandatoryKeys(self): def getDeviceMandatoryKeys(self):
return ["name", "enabled"] return ["name", "enabled"]
def getOptionalKeys(self): def getDeviceOptionalKeys(self):
return [ return [
"ppm", "ppm",
"always-on", "always-on",
@ -615,7 +624,7 @@ class SdrDeviceDescription(object):
def getDeviceSection(self): def getDeviceSection(self):
return OptionalSection( return OptionalSection(
"Device settings", self.getDeviceInputs(), self.getMandatoryKeys(), self.getOptionalKeys() "Device settings", self.getDeviceInputs(), self.getDeviceMandatoryKeys(), self.getDeviceOptionalKeys()
) )
def getProfileSection(self): def getProfileSection(self):

View File

@ -31,8 +31,8 @@ class AirspyDeviceDescription(SoapyConnectorDeviceDescription):
), ),
] ]
def getOptionalKeys(self): def getDeviceOptionalKeys(self):
return super().getOptionalKeys() + ["bias_tee", "bitpack"] return super().getDeviceOptionalKeys() + ["bias_tee", "bitpack"]
def getProfileOptionalKeys(self): def getProfileOptionalKeys(self):
return super().getProfileOptionalKeys() + ["bias_tee"] return super().getProfileOptionalKeys() + ["bias_tee"]

View File

@ -90,8 +90,8 @@ class ConnectorDeviceDescription(SdrDeviceDescription):
), ),
] ]
def getOptionalKeys(self): def getDeviceOptionalKeys(self):
return super().getOptionalKeys() + ["rtltcp_compat", "iqswap"] return super().getDeviceOptionalKeys() + ["rtltcp_compat", "iqswap"]
def getProfileOptionalKeys(self): def getProfileOptionalKeys(self):
return super().getProfileOptionalKeys() + ["iqswap"] return super().getProfileOptionalKeys() + ["iqswap"]

View File

@ -18,8 +18,8 @@ class HackrfDeviceDescription(SoapyConnectorDeviceDescription):
def getInputs(self) -> List[Input]: def getInputs(self) -> List[Input]:
return super().getInputs() + [BiasTeeInput()] return super().getInputs() + [BiasTeeInput()]
def getOptionalKeys(self): def getDeviceOptionalKeys(self):
return super().getOptionalKeys() + ["bias_tee"] return super().getDeviceOptionalKeys() + ["bias_tee"]
def getProfileOptionalKeys(self): def getProfileOptionalKeys(self):
return super().getProfileOptionalKeys() + ["bias_tee"] return super().getProfileOptionalKeys() + ["bias_tee"]

View File

@ -58,9 +58,9 @@ class PerseussdrDeviceDescription(DirectSourceDeviceDescription):
CheckboxInput("wideband", "Disable analog filters"), CheckboxInput("wideband", "Disable analog filters"),
] ]
def getOptionalKeys(self): def getDeviceOptionalKeys(self):
# no rf_gain # 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", "attenuator",
"adc_preamp", "adc_preamp",
"adc_dither", "adc_dither",

View File

@ -27,8 +27,8 @@ class RtlSdrDeviceDescription(ConnectorDeviceDescription):
DirectSamplingInput(), DirectSamplingInput(),
] ]
def getOptionalKeys(self): def getDeviceOptionalKeys(self):
return super().getOptionalKeys() + ["device", "bias_tee", "direct_sampling"] return super().getDeviceOptionalKeys() + ["device", "bias_tee", "direct_sampling"]
def getProfileOptionalKeys(self): def getProfileOptionalKeys(self):
return super().getProfileOptionalKeys() + ["bias_tee", "direct_sampling"] return super().getProfileOptionalKeys() + ["bias_tee", "direct_sampling"]

View File

@ -18,8 +18,8 @@ class RtlSdrSoapyDeviceDescription(SoapyConnectorDeviceDescription):
def getInputs(self) -> List[Input]: def getInputs(self) -> List[Input]:
return super().getInputs() + [BiasTeeInput(), DirectSamplingInput()] return super().getInputs() + [BiasTeeInput(), DirectSamplingInput()]
def getOptionalKeys(self): def getDeviceOptionalKeys(self):
return super().getOptionalKeys() + ["bias_tee", "direct_sampling"] return super().getDeviceOptionalKeys() + ["bias_tee", "direct_sampling"]
def getProfileOptionalKeys(self): def getProfileOptionalKeys(self):
return super().getProfileOptionalKeys() + ["bias_tee", "direct_sampling"] return super().getProfileOptionalKeys() + ["bias_tee", "direct_sampling"]

View File

@ -25,5 +25,5 @@ class RtlTcpDeviceDescription(ConnectorDeviceDescription):
def getInputs(self) -> List[Input]: def getInputs(self) -> List[Input]:
return super().getInputs() + [RemoteInput()] return super().getInputs() + [RemoteInput()]
def getMandatoryKeys(self): def getDeviceMandatoryKeys(self):
return super().getMandatoryKeys() + ["device"] return super().getDeviceMandatoryKeys() + ["device"]

View File

@ -44,8 +44,8 @@ class RundsDeviceDescription(ConnectorDeviceDescription):
CheckboxInput("long", "Use 32-bit sample size (LONG)"), CheckboxInput("long", "Use 32-bit sample size (LONG)"),
] ]
def getMandatoryKeys(self): def getDeviceMandatoryKeys(self):
return super().getMandatoryKeys() + ["device"] return super().getDeviceMandatoryKeys() + ["device"]
def getOptionalKeys(self): def getDeviceOptionalKeys(self):
return super().getOptionalKeys() + ["protocol", "long"] return super().getDeviceOptionalKeys() + ["protocol", "long"]

View File

@ -54,8 +54,8 @@ class SdrplayDeviceDescription(SoapyConnectorDeviceDescription):
), ),
] ]
def getOptionalKeys(self): def getDeviceOptionalKeys(self):
return super().getOptionalKeys() + ["bias_tee", "rf_notch", "dab_notch", "if_mode"] return super().getDeviceOptionalKeys() + ["bias_tee", "rf_notch", "dab_notch", "if_mode"]
def getProfileOptionalKeys(self): def getProfileOptionalKeys(self):
return super().getProfileOptionalKeys() + ["bias_tee", "rf_notch", "dab_notch", "if_mode"] return super().getProfileOptionalKeys() + ["bias_tee", "rf_notch", "dab_notch", "if_mode"]

View File

@ -98,8 +98,8 @@ class SoapyConnectorDeviceDescription(ConnectorDeviceDescription):
TextInput("antenna", "Antenna"), TextInput("antenna", "Antenna"),
] ]
def getOptionalKeys(self): def getDeviceOptionalKeys(self):
return super().getOptionalKeys() + ["device", "rf_gain", "antenna"] return super().getDeviceOptionalKeys() + ["device", "rf_gain", "antenna"]
def getProfileOptionalKeys(self): def getProfileOptionalKeys(self):
return super().getProfileOptionalKeys() + ["antenna"] return super().getProfileOptionalKeys() + ["antenna"]

View File

@ -29,5 +29,5 @@ class SoapyRemoteDeviceDescription(SoapyConnectorDeviceDescription):
), ),
] ]
def getOptionalKeys(self): def getDeviceOptionalKeys(self):
return super().getOptionalKeys() + ["remote_driver"] return super().getDeviceOptionalKeys() + ["remote_driver"]