def _setup_widget(self, widget_name, widget): if not IProxyWidget.providedBy(widget): raise ProxyError("The widget %s (%r), in view %s is not " "a kiwi widget and cannot be added to a proxy" % (widget_name, widget, self._view.__class__.__name__)) data_type = _get_widget_data_type(widget) if data_type is None: raise ProxyError("The kiwi widget %s (%r) in view %s should " "have a data type set" % ( widget_name, widget, self._view.__class__.__name__)) attribute = widget.get_property('model-attribute') if not attribute: attribute = widget_name widget.set_property('model-attribute', widget_name) # Do a isinstance here instead of in the callback, # as an optimization, it'll never change in runtime anyway connection_id = widget.connect( 'content-changed', self._on_widget__content_changed, attribute, IValidatableProxyWidget.providedBy(widget)) widget.set_data('content-changed-id', connection_id) if IValidatableProxyWidget.providedBy(widget): connection_id = widget.connect( 'notify::visible', self._on_widget__notify) widget.set_data('notify-visible-id', connection_id) connection_id = widget.connect( 'notify::sensitive', self._on_widget__notify) widget.set_data('notify-sensitive-id', connection_id) connection_id = widget.connect( 'validation-changed', self._on_widget__validation_changed, attribute) widget.set_data('validation-changed-id', connection_id) model_attributes = self._model_attributes # save this widget in our map if (attribute in model_attributes and # RadioButtons are allowed several times not gobject.type_is_a(widget, 'GtkRadioButton')): old_widget = model_attributes[attribute] raise KeyError("The widget %s (%r) in view %s is already in " "the proxy, defined by widget %s (%r)" % ( widget_name, widget, self._view.__class__.__name__, old_widget.name, old_widget)) model_attributes[attribute] = widget self._reset_widget(attribute, widget)
def _reset_widget(self, attribute, widget): if self._model is None: # if we have no model, leave value unset so we pick up # the widget default below. value = ValueUnset else: # if we have a model, grab its value to update the widgets self._register_proxy_in_model(attribute) value = kgetattr(self._model, attribute, ValueUnset) self.update(attribute, value, block=True) from kiwi.ui.widgets.combo import ProxyComboBox # FIXME: If the initial value is None and it is not a valid option, # the ProxyComboBox may ignore it and keep the currently selected # value instead. See ProxyComboBox.update for more information. # Remove this when fixing the callsites or finding a better solution if (isinstance(widget, ProxyComboBox) and self._model is not None and value is None): self._update_attribute(widget, attribute, widget.read()) # The initial value of the model is set, at this point # do a read, it'll trigger a validation for widgets who # supports it. if not IValidatableProxyWidget.providedBy(widget): return widget.validate(force=True)
def add_proxy(self, model=None, widgets=None): """ Add a proxy to this view that automatically update a model when the view changes. Arguments: - model. the object we are proxing. It can be None if we don't have a model yet and we want to display the interface and set it up with future models. - widgets. the list of widgets that contains model attributes to be proxied. If it is None (or not specified) it will be the whole list of widgets this View has. This method return a Proxy object that you may want to use to force updates or setting new models. Keep a reference to it since there is no way to get that proxy later on. You have been warned (tm) """ log.debug( '%s: adding proxy for %s' % (self.__class__.__name__, model and model.__class__.__name__)) widgets = widgets or self.widgets proxy_widgets = [] for widget_name in widgets: widget = getattr(self, widget_name, None) if widget is None: continue if not IValidatableProxyWidget.providedBy(widget): continue try: widget.connect('validation-changed', self._on_child__validation_changed, widget_name) except TypeError: raise AssertionError("%r does not have a validation-changed " "signal." % widget) proxy_widgets.append((widget_name, widget)) proxy = Proxy(self, model, widgets) self._proxies.append(proxy) for widget_name, widget in proxy_widgets: # Do not store validation value for invisible/insensitive widgets. # If they turn visible/sensitive, _on_child__validation_changed # will handle that if (not widget.get_property('visible') or not widget.get_property('sensitive')): continue # Proxy.__init__ will call widget.validate(force=True), so we # can use rely on widget.is_valid() here self._validation[widget_name] = widget.is_valid() validation_log.info( "%s: %s=%r (initial)" % (self.__class__.__name__, widget_name, widget.is_valid())) return proxy
def add_proxy(self, model=None, widgets=None): """ Add a proxy to this view that automatically update a model when the view changes. Arguments: - model. the object we are proxing. It can be None if we don't have a model yet and we want to display the interface and set it up with future models. - widgets. the list of widgets that contains model attributes to be proxied. If it is None (or not specified) it will be the whole list of widgets this View has. This method return a Proxy object that you may want to use to force updates or setting new models. Keep a reference to it since there is no way to get that proxy later on. You have been warned (tm) """ log('%s: adding proxy for %s' % ( self.__class__.__name__, model and model.__class__.__name__)) widgets = widgets or self.widgets proxy_widgets = [] for widget_name in widgets: widget = getattr(self, widget_name, None) if widget is None: continue if not IValidatableProxyWidget.providedBy(widget): continue try: widget.connect('validation-changed', self._on_child__validation_changed, widget_name) except TypeError: raise AssertionError("%r does not have a validation-changed " "signal." % widget) proxy_widgets.append((widget_name, widget)) proxy = Proxy(self, model, widgets) self._proxies.append(proxy) for widget_name, widget in proxy_widgets: # Do not store validation value for invisible/insensitive widgets. # If they turn visible/sensitive, _on_child__validation_changed # will handle that if (not widget.get_property('visible') or not widget.get_property('sensitive')): continue # Proxy.__init__ will call widget.validate(force=True), so we # can use rely on widget.is_valid() here self._validation[widget_name] = widget.is_valid() validation_log.info("%s: %s=%r (initial)" % ( self.__class__.__name__, widget_name, widget.is_valid())) return proxy
def add_proxy(self, model=None, widgets=None): """ Add a proxy to this view that automatically update a model when the view changes. Arguments: - model. the object we are proxing. It can be None if we don't have a model yet and we want to display the interface and set it up with future models. - widgets. the list of widgets that contains model attributes to be proxied. If it is None (or not specified) it will be the whole list of widgets this View has. This method return a Proxy object that you may want to use to force updates or setting new models. Keep a reference to it since there is no way to get that proxy later on. You have been warned (tm) """ log('%s: adding proxy for %s' % ( self.__class__.__name__, model and model.__class__.__name__)) widgets = widgets or self.widgets for widget_name in widgets: widget = getattr(self, widget_name, None) if widget is None: continue if not IValidatableProxyWidget.providedBy(widget): continue try: widget.connect('validation-changed', self._on_child__validation_changed, widget_name) except TypeError: raise AssertionError("%r does not have a validation-changed " "signal." % widget) if (widget.props.mandatory and widget.props.sensitive and widget.props.visible): try: value = widget.read() empty = value is ValueUnset or value is None validation_log.info("%s: %s=%r (initial)" % ( self.__class__.__name__, widget_name, value)) if empty: self._validation[widget_name] = False # FIXME: This is probably wrong, but we get improperly placed # thousand operators in other places that has to be fixed first except ValidationError: pass proxy = Proxy(self, model, widgets) self._proxies.append(proxy) return proxy
def _write_widget(self, widget, indent=0, props=None, extra=None): extra = extra or [] line_props = [] name = self._items.get(hash(widget), '') if name: line_props.append(name) line_props.extend(self._get_packing_properties(widget)) spaces = (' ' * (indent * 2)) if not props: props = [] if not widget.get_visible(): props.append('hidden') if not widget.get_sensitive(): props.append('insensitive') if (widget.get_sensitive() and widget.get_visible() and not widget.get_can_focus() and self._is_interactive_widget(widget)): props.append('unfocusable') fmt = "%s %s is not focusable" self.failures.append(fmt % (gobject.type_name(widget), self._items.get(hash(widget), '???'))) if IValidatableProxyWidget.providedBy(widget): if (not widget.is_valid() and widget.get_sensitive() and widget.get_visible()): if widget.mandatory: props.append('mandatory') else: props.append('invalid') if props: prop_lines = ' ' + ', '.join(props) else: prop_lines = '' self.output += "%s%s(%s):%s\n" % ( spaces, gobject.type_name(widget), ', '.join(line_props), prop_lines) spaces = (' ' * ((indent + 1) * 2)) for line in extra: self.output += spaces + line + '\n'
def _write_widget(self, widget, indent=0, props=None, extra=None): extra = extra or [] line_props = [] name = self._items.get(widget, '') if name: line_props.append(name) line_props.extend(self._get_packing_properties(widget)) spaces = (' ' * (indent * 2)) if not props: props = [] g_name = GObject.type_name(widget) if g_name in ['GtkHBox', 'GtkVBox']: g_name = 'GtkBox' elif g_name in ['GtkHButtonBox', 'GtkVButtonBox']: g_name = 'GtkButtonBox' if not widget.get_visible(): props.append('hidden') if not widget.get_sensitive(): props.append('insensitive') if (widget.get_sensitive() and widget.get_visible() and not widget.get_can_focus() and self._is_interactive_widget(widget)): props.append('unfocusable') fmt = "%s %s is not focusable" self.failures.append(fmt % (g_name, self._items.get(widget, '???'))) if IValidatableProxyWidget.providedBy(widget): if (not widget.is_valid() and widget.get_sensitive() and widget.get_visible()): if widget.mandatory: props.append('mandatory') else: props.append('invalid') if props: prop_lines = ' ' + ', '.join(props) else: prop_lines = '' self.output += "%s%s(%s):%s\n" % (spaces, g_name, ', '.join(line_props), prop_lines) spaces = (' ' * ((indent + 1) * 2)) for line in extra: self.output += spaces + line + '\n'
def remove_widget(self, name): """ Removes a widget from the proxy :param name: the name of the widget to remove """ if not name in self._model_attributes: raise TypeError("there is no widget called %s" % name) widget = self._model_attributes.pop(name) widget.disconnect(widget._content_changed_id) if IValidatableProxyWidget.providedBy(widget): for data_name in ['_notify_visible_id', '_notify_sensitive_id']: widget.disconnect(getattr(widget, data_name))
def remove_widget(self, name): """ Removes a widget from the proxy :param name: the name of the widget to remove """ if not name in self._model_attributes: raise TypeError("there is no widget called %s" % name) widget = self._model_attributes.pop(name) widget.disconnect(widget.get_data('content-changed-id')) if IValidatableProxyWidget.providedBy(widget): for data_name in ('notify-visible-id', 'notify-sensitive-id'): widget.disconnect(widget.get_data(data_name))
def remove_widget(self, name): """ Removes a widget from the proxy :param name: the name of the widget to remove """ if not name in self._model_attributes: raise TypeError("there is no widget called %s" % name) widget = self._model_attributes.pop(name) widget.disconnect(widget.get_data("content-changed-id")) if IValidatableProxyWidget.providedBy(widget): for data_name in ("notify-visible-id", "notify-sensitive-id"): widget.disconnect(widget.get_data(data_name))
def _reset_widget(self, attribute, widget): if self._model is None: # if we have no model, leave value unset so we pick up # the widget default below. value = ValueUnset else: # if we have a model, grab its value to update the widgets self._register_proxy_in_model(attribute) value = kgetattr(self._model, attribute, ValueUnset) self.update(attribute, value, block=True) # The initial value of the model is set, at this point # do a read, it'll trigger a validation for widgets who # supports it. if not IValidatableProxyWidget.providedBy(widget): return widget.validate(force=True)
def add_proxy(self, model=None, widgets=None): """ Add a proxy to this view that automatically update a model when the view changes. Arguments: - model. the object we are proxing. It can be None if we don't have a model yet and we want to display the interface and set it up with future models. - widgets. the list of widgets that contains model attributes to be proxied. If it is None (or not specified) it will be the whole list of widgets this View has. This method return a Proxy object that you may want to use to force updates or setting new models. Keep a reference to it since there is no way to get that proxy later on. You have been warned (tm) """ log('%s: adding proxy for %s' % ( self.__class__.__name__, model and model.__class__.__name__)) widgets = widgets or self.widgets for widget_name in widgets: widget = getattr(self, widget_name, None) if widget is None: continue if not IValidatableProxyWidget.providedBy(widget): continue try: widget.connect('validation-changed', self._on_child__validation_changed, widget_name) except TypeError: raise AssertionError("%r does not have a validation-changed " "signal." % widget) proxy = Proxy(self, model, widgets) self._proxies.append(proxy) return proxy
def _write_widget(self, widget, indent=0, props=None, extra=None): extra = extra or [] line_props = [] name = self._items.get(widget, '') # FIXME python3: There're 2 tests that use SaleWithToolbarSearch that # are getting the name as 'results' or 'sales'. Idk what exactly is # happening in _add_namespace... if isinstance(widget, SearchResultListView) and name == 'sales': name = 'results' if name: line_props.append(name) line_props.extend(self._get_packing_properties(widget)) spaces = (' ' * (indent * 2)) if not props: props = [] g_name = GObject.type_name(widget) if g_name in ['GtkHBox', 'GtkVBox']: g_name = 'GtkBox' elif g_name in ['GtkHButtonBox', 'GtkVButtonBox']: g_name = 'GtkButtonBox' if not widget.get_visible(): props.append('hidden') if not widget.get_sensitive(): props.append('insensitive') if (widget.get_sensitive() and widget.get_visible() and not widget.get_can_focus() and self._is_interactive_widget(widget)): props.append('unfocusable') fmt = "%s %s is not focusable" self.failures.append(fmt % (g_name, self._items.get(widget, '???'))) if IValidatableProxyWidget.providedBy(widget): if (not widget.is_valid() and widget.get_sensitive() and widget.get_visible()): if widget.mandatory: props.append('mandatory') else: props.append('invalid') if props: prop_lines = ' ' + ', '.join(props) else: prop_lines = '' self.output += "%s%s(%s):%s\n" % ( spaces, g_name, ', '.join(line_props), prop_lines) spaces = (' ' * ((indent + 1) * 2)) for line in extra: self.output += spaces + line + '\n'