def _init(self, etree, control, parent=None): self.etree = etree # Element tree to parse self.control = control # Control class (for callback connect) self.parent = parent # Parent widget self.id = None # ID of this widget (if specified) self.data = utils.Bunch() # Metadata to append to object self.actions = [] # List of actions self.manifest = utils.Bunch() # Dict of element ids self.bgimage = None # Background image self.bgpos = (0, 0) # Background position 'x,y' or 'center,top' etc.. self.bgsize = 'fit' # Background size 'x,y' or 'fit' self.bgfade = 0 # Fade bgimage when changed (0 to disable) self.bgopacity = 1.0 # Current bgopacity (used during transition) self.click_enabled = False # Set True when click event enabled self.dblclick_enabled = False # Set True when dblclick event enabled self.installEventFilter(self) # Capture events for interactions self._init_attributes() # Process all attributes (and actions) self.children = self._append_children() # Build all Children # if init is too fast, widgets are not visible time.sleep(0.0001) if parent is not None: try: # log.debug("Init %s in %s", etree, parent.objectName()) parent.layout().addWidget(self) except AttributeError as err: log.debug("Something terrible happened. %s", err) except Exception as ex: log.debug("Something terrible happened. %s", ex)
class Config(BaseConfig): TEMPLATE = os.path.join(PLUGINDIR, 'sickbeard_config.html') FIELDS = utils.Bunch(BaseConfig.FIELDS, host={}, apikey={}) def validate_host(self, field, value): if not value: return value url = PING_URL % {'host': value, 'apikey': 1234} response = utils.http_request(url, timeout=2).get('response') if not response: raise ValidationError('Host not reachable.') if response.status != 200: raise ValidationError('Invalid response from server: %s' % response.status) return value def validate_apikey(self, field, value): if not value: return value host = self.fields.host.value if host is None: host = self.pi_config.get(self.namespace, 'host') url = PING_URL % {'host': host, 'apikey': value} response = utils.http_request(url, timeout=2).get('response') if not response: raise ValidationError('Host not reachable.') if response.status != 200: raise ValidationError('Invalid response from server: %s' % response.status) content = json.loads(response.read().decode('utf-8')) if content.get('result') != 'success': raise ValidationError('Invalid API key specified.') return value
class Config(BaseConfig): TEMPLATE = os.path.join(PLUGINDIR, 'sonarr_config.html') FIELDS = utils.Bunch(BaseConfig.FIELDS, host={}, apikey={}) def validate_host(self, field, value): if not value: return value url = UPDATE_URL % {'host': value, 'apikey': 1234, 'end': '2000-01-01'} response = utils.http_request(url, timeout=2) if utils.rget(response, 'error.code') != 401: raise ValidationError('Host not reachable.') return value def validate_apikey(self, field, value): if not value: return value host = self.fields.host.value if host is None: host = self.pi_config.get(self.namespace, 'host') url = UPDATE_URL % {'host': host, 'apikey': value, 'end': '2000-01-01'} response = utils.http_request(url, timeout=2).get('response') if utils.rget(response, 'error.code') == 401: raise ValidationError('Invalid API key specified.') content = json.loads(response.read().decode('utf-8')) if not isinstance(content, list): raise ValidationError('Invalid response from server.') return value
class Config(BaseConfig): TEMPLATE = os.path.join(PLUGINDIR, 'plexserver_config.html') FIELDS = utils.Bunch(BaseConfig.FIELDS, host={}, username={'save_to_keyring':True}, password={'save_to_keyring':True}) def validate_password(self, field, value): if not value: return value try: MyPlexAccount.signin(self.fields.username.value, value) return value except Unauthorized: raise ValidationError('Invalid username or password.') def validate_host(self, field, value): if not value: return value try: username = self.fields.username.value password = self.fields.password.value fetch_plex_instance(self.pi_dash, username, password, value) return value except Unauthorized: raise ValidationError('Invalid username or password.') except NotFound: raise ValidationError('Server host or name not found.') except: raise ValidationError('Invalid server.')
def __init__(self, pi_dash, pi_config): self.name = utils.name(self.__module__) # Name of this Plugin self.namespace = utils.namespace( self.__module__) # Namespace of this Config self.template = self._init_template() # Template for config settings self.fields = utils.Bunch() # Fields in this Config PiWidget.__init__(self, self.template, self) # Init parent widget # PiFrameVertical.__init__(self, self.template, self) # Init parent widget self.pi_dash = pi_dash # Reference to PiDashboard self.pi_config = pi_config # Reference to Main Config self._init_default_interval() self._init_fields()
class Config(BaseConfig): TEMPLATE = os.path.join(PLUGINDIR, 'wunderground_config.html') FIELDS = utils.Bunch(BaseConfig.FIELDS, apikey={}, query={}, location = {'default':'autoip'}, ) def validate_apikey(self, field, value): if not value: return value url = UPDATE_URL % {'apikey':value, 'location':'autoip'} response = utils.http_request(url, timeout=2).get('response') if not response: raise ValidationError('No response from Weather Underground.') content = json.loads(response.read().decode('utf-8')) if 'response' not in content: raise ValidationError('Invalid response from Weather Underground.') if 'current_observation' not in content: raise ValidationError('Invalid API key specified.') return value def validate_query(self, field, value): if not value or value == 'autoip': self.fields.location.value = 'autoip' field.help.setText(field.help_default) return value url = QUERY_URL % {'query':value} response = utils.http_request(url, timeout=2).get('response') if not response: raise ValidationError('No response from Weather Underground.') content = json.loads(response.read().decode('utf-8')) if not content.get('RESULTS'): raise ValidationError('Unable to determine specified location.') result = content['RESULTS'][0] self.fields.location.value = result['ll'].replace(' ',',') field.help.setText(result['name']) return value
def _init_field(self, name, meta): field = utils.Bunch(meta) # Convert to Bunch field.name = name # Name of this field field.input = self.manifest.get(name) # QT input element field.controlgroup = self.manifest.get('controlgroup_%s' % name) # QT control group field.status = self.manifest.get('status_%s' % name) # QT status label field.help = self.manifest.get('help_%s' % name) # QT help label field.help_default = field.help.text( ) if field.help else None # Default help text field.default = field.get('default', '') # Default value field.value = self._get_value(field) # Current value (to be saved) field.lastchecked = field.value # Last value verified field.validator = getattr(self, 'validate_%s' % name, None) # Validator callback if name in self.manifest: if getattr(field.input, 'textEdited', None): field.input.textEdited.connect( lambda txt, field=field: self._editing(field, txt)) if getattr(field.input, 'editingFinished', None): field.input.editingFinished.connect( lambda field=field: self._validate(field)) field.input.set_value(field.value) self.fields[name] = field
class Config(BaseConfig): TEMPLATE = os.path.join(PLUGINDIR, 'externalip_config.html') FIELDS = utils.Bunch(BaseConfig.FIELDS, url = {'default': DEFUALT_URL} )
class Config(BaseConfig): TEMPLATE = os.path.join(PLUGINDIR, 'picasa_config.html') FIELDS = utils.Bunch(BaseConfig.FIELDS, username={}, ignores={})
class Config(BaseConfig): TEMPLATE = os.path.join(PLUGINDIR, 'plexmedia_config.html') FIELDS = utils.Bunch(BaseConfig.FIELDS, ignores={})
class Config(BaseConfig): TEMPLATE = os.path.join(PLUGINDIR, 'filesystem_config.html') FIELDS = utils.Bunch(BaseConfig.FIELDS, fstypes={'default': DEFAULT_FSTYPES})
class BaseConfig(PiWidget): STATUS_OK = '✔' STATUS_ERROR = '✘' STATUS_LOADING = '…' TEMPLATE = os.path.join(PLUGINDIR, '_default_config.html') FIELDS = utils.Bunch(enabled={'default': True}, interval={'default': 60}) def __init__(self, pi_dash, pi_config): self.name = utils.name(self.__module__) # Name of this Plugin self.namespace = utils.namespace( self.__module__) # Namespace of this Config self.template = self._init_template() # Template for config settings self.fields = utils.Bunch() # Fields in this Config PiWidget.__init__(self, self.template, self) # Init parent widget # PiFrameVertical.__init__(self, self.template, self) # Init parent widget self.pi_dash = pi_dash # Reference to PiDashboard self.pi_config = pi_config # Reference to Main Config self._init_default_interval() self._init_fields() def _init_template(self): with open(self.TEMPLATE) as tpl: template = ElementTree.fromstring(tpl.read()) return template def _init_default_interval(self): if 'interval' in self.FIELDS: module = self.pi_dash.modules[self.namespace] default_interval = module.Plugin.DEFAULT_INTERVAL self.FIELDS.interval['default'] = default_interval def _init_fields(self): for name, meta in self.FIELDS.items(): self._init_field(name, meta) def _init_field(self, name, meta): field = utils.Bunch(meta) # Convert to Bunch field.name = name # Name of this field field.input = self.manifest.get(name) # QT input element field.controlgroup = self.manifest.get('controlgroup_%s' % name) # QT control group field.status = self.manifest.get('status_%s' % name) # QT status label field.help = self.manifest.get('help_%s' % name) # QT help label field.help_default = field.help.text( ) if field.help else None # Default help text field.default = field.get('default', '') # Default value field.value = self._get_value(field) # Current value (to be saved) field.lastchecked = field.value # Last value verified field.validator = getattr(self, 'validate_%s' % name, None) # Validator callback if name in self.manifest: if getattr(field.input, 'textEdited', None): field.input.textEdited.connect( lambda txt, field=field: self._editing(field, txt)) if getattr(field.input, 'editingFinished', None): field.input.editingFinished.connect( lambda field=field: self._validate(field)) field.input.set_value(field.value) self.fields[name] = field def _get_value(self, field): from_keyring = field.get('save_to_keyring', False) return self.pi_config.get(self.namespace, field.name, field.default, from_keyring) def _editing(self, field, text): self._set_field_status(field, self.STATUS_LOADING, '') @threaded_method def _validate(self, field, force=False): if not field.input: return try: # self._set_field_status(field, self.STATUS_LOADING, '') value = field.input.get_value() if field.validator: result = field.validator(field, value) value = value if result is None else result log.info('Validation passed for %s.%s', self.namespace, field.name) self._set_field_status(field, self.STATUS_OK, '') except Exception as err: log.warn('Validation Error for %s.%s: %s', self.namespace, field.name, err) self._set_field_status(field, self.STATUS_ERROR, str(err)) finally: log.info('Setting value %s.%s: %s', self.namespace, field.name, value) field.value = value def _set_field_status(self, field, status, errmsg): if field.controlgroup: field.controlgroup.setToolTip(errmsg) if field.status: field.status.setText(status) def validate_interval(self, field, value): try: interval = int(value) assert 1 <= interval <= 3600, 'Value out of bounds.' return interval except: raise ValidationError('Interval seconds must be a number 1-3600.')
class Config(BaseConfig): TEMPLATE = os.path.join(PLUGINDIR, 'network_config.html') FIELDS = utils.Bunch(BaseConfig.FIELDS, ignores = {'default':DEFAULT_IGNORES} )