diff --git a/__main__.py b/__main__.py index bba533fa..e3e5ea7f 100644 --- a/__main__.py +++ b/__main__.py @@ -42,7 +42,7 @@ except ImportError: raise ImportError('Require labscript_utils > 2.1.0') -check_version('labscript_utils', '2.3.1', '3') +check_version('labscript_utils', '2.6.', '3') check_version('qtutils', '2.0.0', '3.0.0') check_version('zprocess', '1.1.2', '3') check_version('labscript_devices', '2.0', '3') diff --git a/device_base_class.py b/device_base_class.py index e5924259..8e5ca10a 100644 --- a/device_base_class.py +++ b/device_base_class.py @@ -158,10 +158,10 @@ def _create_DO_object(self,parent_device,BLACS_hardware_name,labscript_hardware_ # Find the connection name device = self.get_child_from_connection_table(parent_device,labscript_hardware_name) connection_name = device.name if device else '-' - + # Instantiate the DO object return DO(BLACS_hardware_name, connection_name, self.device_name, self.program_device, self.settings) - + def create_analog_outputs(self,analog_properties): for hardware_name,properties in analog_properties.items(): # Create and save the AO object @@ -209,6 +209,10 @@ def create_digital_widgets(self,channel_properties): for hardware_name,properties in channel_properties.items(): properties.setdefault('args',[]) properties.setdefault('kwargs',{}) + + device = self.get_child_from_connection_table(self.device_name,hardware_name) + properties['kwargs']['inverted'] = bool(device.properties.get('inverted', False) if device else properties['kwargs'].get('inverted', False)) + if hardware_name in self._DO: widgets[hardware_name] = self._DO[hardware_name].create_widget(*properties['args'],**properties['kwargs']) diff --git a/output_classes.py b/output_classes.py index 019fa32a..0421ef2d 100644 --- a/output_classes.py +++ b/output_classes.py @@ -21,7 +21,7 @@ from labscript_utils.qtwidgets.analogoutput import AnalogOutput -from labscript_utils.qtwidgets.digitaloutput import DigitalOutput +from labscript_utils.qtwidgets.digitaloutput import DigitalOutput, InvertedDigitalOutput from labscript_utils.qtwidgets.ddsoutput import DDSOutput try: from labscript_utils.unitconversions import * @@ -438,8 +438,8 @@ def __init__(self, hardware_name, connection_name, device_name, program_function self._widget_list = [] self._device_name = device_name - self._logger = logging.getLogger('BLACS.%s.%s'%(self._device_name,hardware_name)) - + self._logger = logging.getLogger('BLACS.%s.%s'%(self._device_name,hardware_name)) + # Note that while we could store self._current_state and self._locked in the # settings dictionary, this dictionary is available to other parts of BLACS # and using separate variables avoids those parts from being able to directly @@ -474,16 +474,20 @@ def _update_from_settings(self,settings): # Update the lock state self._update_lock(self._settings['locked']) - - def create_widget(self,*args,**kwargs): - widget = DigitalOutput('%s\n%s'%(self._hardware_name,self._connection_name),*args,**kwargs) - self.add_widget(widget) + + def create_widget(self, *args, **kwargs): + inverted = kwargs.pop("inverted", False) + if not inverted: + widget = DigitalOutput('%s\n%s'%(self._hardware_name,self._connection_name),*args,**kwargs) + else: + widget = InvertedDigitalOutput('%s\n%s'%(self._hardware_name,self._connection_name),*args,**kwargs) + self.add_widget(widget, inverted=inverted) return widget - - def add_widget(self,widget): + + def add_widget(self, widget, inverted=False): if widget not in self._widget_list: widget.set_DO(self,True,False) - widget.toggled.connect(self.set_value) + widget.toggled.connect(self.set_value if not inverted else lambda state: self.set_value(not state)) self._widget_list.append(widget) self.set_value(self._current_state,False) self._update_lock(self._locked) @@ -521,8 +525,8 @@ def _update_lock(self,locked): def set_value(self,state,program=True): # conversion to integer, then bool means we can safely pass in # either a string '1' or '0', True or False or 1 or 0 - state = bool(int(state)) - + state = bool(int(state)) + # We are programatically setting the state, so break the check lock function logic self._current_state = state diff --git a/plugins/theme/__init__.py b/plugins/theme/__init__.py index 04a058cb..35a8baf8 100644 --- a/plugins/theme/__init__.py +++ b/plugins/theme/__init__.py @@ -23,39 +23,77 @@ DEFAULT_STYLESHEET = """DigitalOutput { font-size: 12px; - background-color: rgb(20,75,20,192); - border: 1px solid rgb(20,75,20,128); + background-color: rgb(50,100,50,255); + border: 1px solid rgb(50,100,50,128); border-radius: 3px; padding: 2px; color: #202020; } DigitalOutput:hover { - background-color: #148214; + background-color: rgb(50,130,50); border: None; } DigitalOutput:disabled{ - background-color: rgb(20,75,20,120); + background-color: rgb(50,100,50,128); color: #505050; } DigitalOutput:checked { background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #48dd48, stop: 1 #20ff20); + stop: 0 rgb(32,200,32), stop: 1 rgb(32,255,32)); border: 1px solid #8f8f91; color: #000000; } DigitalOutput:hover:checked { background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #48dd48, stop: 1 #78ff78); + stop: 0 rgb(32,200,32), stop: 1 rgb(120,255,120)); border: 1px solid #8f8f91; } DigitalOutput:checked:disabled{ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #7ee77e, stop: 1 #62ff62); + stop: 0 rgba(32,200,32,128), stop: 1 rgba(32,255,32,128)); + color: #606060; +} + +InvertedDigitalOutput { + font-size: 12px; + background-color: rgb(70,100,170,255); + border: 1px solid rgb(70,100,170,128); + border-radius: 3px; + padding: 2px; + color: #202020; +} + +InvertedDigitalOutput:hover { + background-color: rgb(70, 130, 220); + border: None; +} + +InvertedDigitalOutput:disabled{ + background-color: rgba(70,100,170,128); + color: #505050; +} + +InvertedDigitalOutput:checked { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 rgb(50,150,221), stop: 1 rgb(32,192,255)); + border: 1px solid #8f8f91; + color: #000000; +} + +InvertedDigitalOutput:hover:checked { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 rgb(50,150,221), stop: 1 rgb(120,192,255)); + border: 1px solid #8f8f91; +} + +InvertedDigitalOutput:checked:disabled{ + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 rgba(50,150,221,128), stop: 1 rgba(32,192,255,128)); color: #606060; } """