def _populate_app_fields(self): with WindowServiceProxy(59000) as w: self.video_mode_map = w.get_video_mode_map() if self.video_mode_map: self._video_available = True else: self._video_available = False self.video_mode_keys = sorted(self.video_mode_map.keys()) if self._video_available: self.device_key, self.devices = w.get_video_source_configs() field_list = [ Integer.named('overlay_opacity').using(default=50, optional=True), Directory.named('device_directory').using(default='', optional=True), String.named('transform_matrix').using(default='', optional=True, properties={'show_in_gui': False}), ] if self._video_available: video_mode_enum = Enum.named('video_mode').valued( *self.video_mode_keys).using(default=self.video_mode_keys[0], optional=True) video_enabled_boolean = Boolean.named('video_enabled').using( default=False, optional=True, properties={'show_in_gui': True}) recording_enabled_boolean = Boolean.named('recording_enabled').using( default=False, optional=True, properties={'show_in_gui': False}) field_list.append(video_mode_enum) field_list.append(video_enabled_boolean) field_list.append(recording_enabled_boolean) return Form.of(*field_list)
class DmfDeviceController(SingletonPlugin, AppDataController): implements(IPlugin) AppFields = Form.of(Directory.named('device_directory') .using(default='', optional=True)) def __init__(self): self.name = "microdrop.gui.dmf_device_controller" self.previous_device_dir = None self._modified = False @property def modified(self): return self._modified @modified.setter def modified(self, value): self._modified = value if getattr(self, 'menu_rename_dmf_device', None): self.menu_rename_dmf_device.set_sensitive(not value) self.menu_save_dmf_device.set_sensitive(value) @gtk_threadsafe def on_app_options_changed(self, plugin_name): try: if plugin_name == self.name: values = self.get_app_values() if 'device_directory' in values: self.apply_device_dir(values['device_directory']) except (Exception,): _L().info(''.join(traceback.format_exc())) raise def apply_device_dir(self, device_directory): app = get_app() # if the device directory is empty or None, set a default if not device_directory: device_directory = (ph.path(app.config.data['data_dir']) .joinpath('devices')) self.set_app_values({'device_directory': device_directory}) if self.previous_device_dir and (device_directory == self.previous_device_dir): # If the data directory hasn't changed, we do nothing return False device_directory = ph.path(device_directory) if self.previous_device_dir: device_directory.makedirs_p() if device_directory.listdir(): result = yesno('Merge?', '''\ Target directory [%s] is not empty. Merge contents with current devices [%s] (overwriting common paths in the target directory)?''' % (device_directory, self.previous_device_dir)) if not result == gtk.RESPONSE_YES: return False original_directory = ph.path(self.previous_device_dir) for d in original_directory.dirs(): copytree(d, device_directory.joinpath(d.name)) for f in original_directory.files(): f.copyfile(device_directory.joinpath(f.name)) original_directory.rmtree() elif not device_directory.isdir(): # if the device directory doesn't exist, copy the skeleton dir if device_directory.parent: device_directory.parent.makedirs_p() base_path().joinpath('devices').copytree(device_directory) self.previous_device_dir = device_directory return True def on_plugin_enable(self): ''' .. versionchanged:: 2.11.2 Use :func:`gtk_threadsafe` decorator to wrap GTK code blocks, ensuring the code runs in the main GTK thread. ''' app = get_app() app.dmf_device_controller = self defaults = self.get_default_app_options() data = app.get_data(self.name) for k, v in defaults.items(): if k not in data: data[k] = v app.set_data(self.name, data) emit_signal('on_app_options_changed', [self.name]) self.menu_detect_connections = \ app.builder.get_object('menu_detect_connections') self.menu_import_dmf_device = \ app.builder.get_object('menu_import_dmf_device') self.menu_load_dmf_device = \ app.builder.get_object('menu_load_dmf_device') self.menu_rename_dmf_device = \ app.builder.get_object('menu_rename_dmf_device') self.menu_save_dmf_device = \ app.builder.get_object('menu_save_dmf_device') self.menu_save_dmf_device_as = \ app.builder.get_object('menu_save_dmf_device_as') app.signals["on_menu_detect_connections_activate"] = \ self.on_detect_connections app.signals["on_menu_import_dmf_device_activate"] = \ self.on_import_dmf_device app.signals["on_menu_load_dmf_device_activate"] = \ self.on_load_dmf_device app.signals["on_menu_rename_dmf_device_activate"] = \ self.on_rename_dmf_device app.signals["on_menu_save_dmf_device_activate"] = \ self.on_save_dmf_device app.signals["on_menu_save_dmf_device_as_activate"] = \ self.on_save_dmf_device_as @gtk_threadsafe def _init_ui(): # disable menu items until a device is loaded self.menu_detect_connections.set_sensitive(False) self.menu_rename_dmf_device.set_sensitive(False) self.menu_save_dmf_device.set_sensitive(False) self.menu_save_dmf_device_as.set_sensitive(False) _init_ui() def on_protocol_pause(self): pass def on_app_exit(self): self.save_check() def load_device(self, file_path, **kwargs): ''' Load device file. Parameters ---------- file_path : str A MicroDrop device `.svg` file or a (deprecated) MicroDrop 1.0 device. ''' logger = _L() # use logger with method context app = get_app() self.modified = False device = app.dmf_device file_path = ph.path(file_path) if not file_path.isfile(): old_version_file_path = (file_path.parent .joinpath(OLD_DEVICE_FILENAME)) if old_version_file_path: # SVG device file does not exist, but old-style (i.e., v0.3.0) # device file found. try: # Try to import old-style device to new SVG format. self.import_device(old_version_file_path) logger.warning('Auto-converted old-style device to new SVG' ' device format. Open in Inkscape to ' 'verify scale and adjacent electrode ' 'connections.') except Exception, e: logger.error('Error importing device. %s', e, exc_info=True) return else: logger.error('Error opening device. Please ensure file ' 'exists and is readable.', exc_info=True) return # SVG device file exists. Load the device. try: logger.info('[DmfDeviceController].load_device: %s' % file_path) if app.get_device_directory().realpath() == (file_path.realpath() .parent.parent): # Selected device file is in MicroDrop devices directory. new_device = False else: # Selected device file is not in MicroDrop devices directory. # Copy file to devices directory under subdirectory with same # name as file. new_device_directory = (app.get_device_directory().realpath() .joinpath(file_path.namebase) .noconflict()) new_device_directory.makedirs_p() new_file_path = new_device_directory.joinpath('device.svg') file_path.copy(new_file_path) file_path = new_file_path new_device = True # Load device from SVG file. device = DmfDevice.load(file_path, name=file_path.parent.name, **kwargs) if new_device: # Inform user that device was copied from original location # into MicroDrop devices directory. pgh.ui.dialogs.info('Device imported successfully', long='New device copied into MicroDrop ' 'devices directory:\n{}'.format(file_path), parent=app.main_window_controller.view) logger.info('[DmfDeviceController].load_device: Copied new ' 'device to: %s', file_path) emit_signal("on_dmf_device_swapped", [app.dmf_device, device]) except Exception: logger.error('Error loading device.', exc_info=True)
def AppFields(self): return Form.of( Directory.named('notebook_directory').using(default='', optional=True), )