コード例 #1
0
ファイル: test_proxy.py プロジェクト: rcaferraz/kiwi
    def setUp(self):
        self.view = FakeView()
        self.view.add('checkbutton', bool, ProxyCheckButton)
        self.view.add('entry', str, ProxyEntry)
        self.view.add('label', str, ProxyLabel)
        self.view.add('spinbutton', int, ProxySpinButton)
        self.view.add('hscale', float, ProxyHScale)
        self.view.add('vscale', float, ProxyVScale)
        self.view.add('button', str, ProxyButton)
        self.view.add('buttonpixbuf', gdk.Pixbuf, ProxyButton)

        self.view.add('textview', str, ProxyTextView)
        self.radio_first = self.view.add('radiobutton', str, ProxyRadioButton)
        self.radio_first.set_property('data_value', 'first')
        self.radio_second = ProxyRadioButton()
        self.radio_second.set_group(self.radio_first)
        self.radio_second.set_property('data_value', 'second')

        self.view.hscale.get_adjustment().upper = 200
        self.view.vscale.get_adjustment().upper = 250

        self.comboentry = self.view.add('comboentry', str, ProxyComboEntry)
        self.comboentry.prefill(['CE1', 'CE2', 'CE3'])
        self.comboentry.show()

        self.combobox = self.view.add('combobox', str, ProxyComboBox)
        self.combobox.prefill(['CB1', 'CB2', 'CB3'])
        self.combobox.show()

        self.model = Model()
        self.proxy = Proxy(self.view, self.model, self.view.widgets)
コード例 #2
0
ファイル: test_ComboBox.py プロジェクト: rosemberg-al/kiwi
 def setUp(self):
     self.model = Settable(attr=0)
     proxy = Proxy(FakeView(), self.model)
     self.combo = disabledeprecationcall(self.type)
     self.combo.data_type = int
     self.combo.model_attribute = 'attr'
     self.combo.prefill([('foo', 0), ('bar', 1)])
     proxy.add_widget('attr', self.combo)
     self.combo.show()
コード例 #3
0
ファイル: test_ComboBox.py プロジェクト: rcaferraz/kiwi
 def setUp(self):
     self.model = Settable(attr=0)
     proxy = Proxy(FakeView(), self.model)
     self.combo = disabledeprecationcall(self.type)
     self.combo.data_type = int
     self.combo.model_attribute = 'attr'
     self.combo.prefill([('foo', 0),
                         ('bar', 1)])
     proxy.add_widget('attr', self.combo)
     self.combo.show()
コード例 #4
0
ファイル: test_ComboBox.py プロジェクト: rosemberg-al/kiwi
    def test_prefill_attr_none(self):
        model = Settable(attr=None)
        proxy = Proxy(FakeView(), model)
        combo = ProxyComboEntry()
        combo.data_type = int
        combo.model_attribute = 'attr'
        combo.prefill([('foo', 10), ('bar', 20)])
        proxy.add_widget('attr', combo)

        self.assertEqual(model.attr, None)
コード例 #5
0
ファイル: test_ComboBox.py プロジェクト: hackedbellini/kiwi
    def test_prefill_attr_none(self):
        model = Settable(attr=None)
        proxy = Proxy(FakeView(), model)
        combo = ProxyComboEntry()
        combo.data_type = int
        combo.model_attribute = 'attr'
        combo.prefill([('foo', 10), ('bar', 20)])
        proxy.add_widget('attr', combo)

        self.assertEqual(model.attr, None)
コード例 #6
0
ファイル: test_ComboBox.py プロジェクト: rosemberg-al/kiwi
    def test_prefill_attr_none(self):
        model = Settable(attr=None)
        proxy = Proxy(FakeView(), model)
        combo = ProxyComboBox()
        combo.data_type = int
        combo.model_attribute = 'attr'
        combo.prefill([('foo', 10), ('bar', 20)])
        proxy.add_widget('attr', combo)

        # Even though attr is None, the combo doesn't allow something
        # not prefilled in it to be selected. In this case, it will select
        # the first item (prefill actually does that) instead.
        self.assertEqual(model.attr, 10)
コード例 #7
0
ファイル: test_ComboBox.py プロジェクト: hackedbellini/kiwi
    def test_prefill_attr_none(self):
        model = Settable(attr=None)
        proxy = Proxy(FakeView(), model)
        combo = ProxyComboBox()
        combo.data_type = int
        combo.model_attribute = 'attr'
        combo.prefill([('foo', 10), ('bar', 20)])
        proxy.add_widget('attr', combo)

        # Even though attr is None, the combo doesn't allow something
        # not prefilled in it to be selected. In this case, it will select
        # the first item (prefill actually does that) instead.
        self.assertEqual(model.attr, 10)
コード例 #8
0
    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
コード例 #9
0
ファイル: views.py プロジェクト: hsavolai/vmlab
    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
コード例 #10
0
ファイル: test_proxy.py プロジェクト: rcaferraz/kiwi
class TestProxy(unittest.TestCase):
    def setUp(self):
        self.view = FakeView()
        self.view.add('checkbutton', bool, ProxyCheckButton)
        self.view.add('entry', str, ProxyEntry)
        self.view.add('label', str, ProxyLabel)
        self.view.add('spinbutton', int, ProxySpinButton)
        self.view.add('hscale', float, ProxyHScale)
        self.view.add('vscale', float, ProxyVScale)
        self.view.add('button', str, ProxyButton)
        self.view.add('buttonpixbuf', gdk.Pixbuf, ProxyButton)

        self.view.add('textview', str, ProxyTextView)
        self.radio_first = self.view.add('radiobutton', str, ProxyRadioButton)
        self.radio_first.set_property('data_value', 'first')
        self.radio_second = ProxyRadioButton()
        self.radio_second.set_group(self.radio_first)
        self.radio_second.set_property('data_value', 'second')

        self.view.hscale.get_adjustment().upper = 200
        self.view.vscale.get_adjustment().upper = 250

        self.comboentry = self.view.add('comboentry', str, ProxyComboEntry)
        self.comboentry.prefill(['CE1', 'CE2', 'CE3'])
        self.comboentry.show()

        self.combobox = self.view.add('combobox', str, ProxyComboBox)
        self.combobox.prefill(['CB1', 'CB2', 'CB3'])
        self.combobox.show()

        self.model = Model()
        self.proxy = Proxy(self.view, self.model, self.view.widgets)

    def testCheckButton(self):
        self.assertEqual(self.model.checkbutton, True)
        self.view.checkbutton.set_active(False)
        self.assertEqual(self.model.checkbutton, False)

    def testEntry(self):
        self.assertEqual(self.model.entry, 'foo')
        self.view.entry.set_text('bar')
        self.assertEqual(self.model.entry, 'bar')

        # If the widget is insensitive, it should not change the model
        self.view.entry.set_sensitive(False)
        self.view.entry.set_text('bin')
        self.assertEqual(self.model.entry, 'bar')

    def testLabel(self):
        self.assertEqual(self.model.label, 'label')
        self.view.label.set_text('other label')
        # When the proxy label is updated, the model should not change. Labels
        # are non interactive widget, and the user cannot edit the value.
        self.assertEqual(self.model.label, 'label')

    def testRadioButton(self):
        self.assertEqual(self.model.radiobutton, 'first')
        self.radio_second.set_active(True)
        self.assertEqual(self.model.radiobutton, 'second')
        self.radio_first.set_active(True)
        self.assertEqual(self.model.radiobutton, 'first')

    def testHScale(self):
        self.assertEqual(self.model.vscale, 100)
        self.view.vscale.set_value(220)
        self.assertEqual(self.model.vscale, 220)

    def testVScale(self):
        self.assertEqual(self.model.vscale, 100)
        self.view.vscale.set_value(200)
        self.assertEqual(self.model.vscale, 200)

    def testSpinButton(self):
        self.assertEqual(self.model.spinbutton, 100)
        self.view.spinbutton.set_text("200")
        self.assertEqual(self.model.spinbutton, 200)

        # If the widget is insensitive, it should not change the model
        self.view.spinbutton.set_sensitive(False)
        self.view.spinbutton.set_text('400')
        self.assertEqual(self.model.spinbutton, 200)

    def testTextView(self):
        self.assertEqual(self.model.textview, 'sliff')
        self.view.textview.get_buffer().set_text('sloff')
        self.assertEqual(self.model.textview, 'sloff')

    def testComboEntry(self):
        self.assertEqual(self.model.comboentry, 'CE1')
        self.view.comboentry.select('CE2')
        self.assertEqual(self.model.comboentry, 'CE2')
        self.view.comboentry.entry.set_text('CENone')
        self.assertEqual(self.model.comboentry, None)

    def testComboBox(self):
        self.assertEqual(self.model.combobox, 'CB1')
        self.view.combobox.select('CB2')
        self.assertEqual(self.model.combobox, 'CB2')

    def testButton(self):
        self.assertEqual(self.model.button, 'button')
        self.view.button.update('sliff')
        self.assertEqual(self.model.button, 'sliff')

    def testEmptyModel(self):
        self.radio_second.set_active(True)

        self.proxy.set_model(None)

        self.assertEqual(self.view.entry.read(), ValueUnset)
        self.assertEqual(self.view.checkbutton.read(), False)
        self.assertEqual(self.view.radiobutton.read(), 'first')
        self.assertEqual(self.view.label.read(), '', 'label')
        self.assertEqual(self.view.spinbutton.read(), ValueUnset, 'spinbutton')
        self.assertEqual(self.view.textview.read(), '', 'textview')
        self.assertEqual(self.view.comboentry.read(), None, 'comboentry')
        self.assertEqual(self.view.combobox.read(), 'CB1', 'combobox')

    def testValueUnset(self):
        self.view.entry.update(ValueUnset)
        self.assertEqual(self.view.entry.get_text(), "")
        self.view.spinbutton.update(ValueUnset)
        self.assertEqual(self.view.spinbutton.get_text(), "")

    def testValidationIcon(self):
        def validate_entry(entry, value):
            if value == 'error':
                return ValidationError()

        entry = self.view.entry
        entry.connect('validate', validate_entry)

        original_set_invalid = self.view.entry.set_invalid
        with mock.patch.object(entry, 'set_invalid') as set_invalid:
            # Avoid fading so we can check the icon at the same time the
            # widget becomes invalid
            set_invalid.side_effect = lambda text: original_set_invalid(
                text=text, fade=False)

            self.proxy.update('entry', 'ok')
            self.assertEqual(entry.get_property("secondary-icon-pixbuf"), None)

            self.proxy.update('entry', 'error')
            # Making the widget invalid should put the validation icon on it
            self.assertNotEqual(entry.get_property("secondary-icon-pixbuf"), None)

            entry.set_sensitive(False)
            # But if the widget becomes insensitive, the icon should be removed
            self.assertEqual(entry.get_property("secondary-icon-pixbuf"), None)

            entry.set_sensitive(True)
            # And re-added when the widget becomes sensitive again
            self.assertNotEqual(entry.get_property("secondary-icon-pixbuf"), None)

    def testValueChangeWhenWidgetInalid(self):
        def validate_entry(entry, value):
            if entry.make_invalid:
                return ValidationError("")

        self.view.entry.connect('validate', validate_entry)

        self.view.entry.make_invalid = False
        self.view.entry.update("Propagated immediatly")
        self.assertEqual(self.model.entry, "Propagated immediatly")

        self.view.entry.make_invalid = True
        self.view.entry.update("Propagated later")
        self.assertEqual(self.model.entry, "Propagated immediatly")

        self.view.entry.make_invalid = False
        self.view.entry.validate(force=True)
        self.assertEqual(self.model.entry, "Propagated later")

    def testUpdateValueConversion(self):
        # entry has data_type of str, so an int should be converted to str
        self.proxy.update('entry', 666)
        self.assertEqual(self.view.entry.read(), '666')

        # entry has data_type of str, so an int should be converted to str
        self.view.entry.set_property('data-type', unicode)
        with self.assertRaises(TypeError) as te:
            # encode to iso-8859-1 so it will produce an UnicodeDecodeError
            self.proxy.update('entry', 'não'.encode('iso-8859-1'))
        self.assertEqual(
            te.exception.message,
            ("attribute entry of model <Model button='button', "
             "checkbutton=True, combobox='CB1', comboentry='CE1', "
             "entry='666', hscale=100.0, label='label', "
             "radiobutton='first', spinbutton=100, textview='sliff', "
             "vscale=100.0> cannot be converted to unicode"))

        # spinbutton has data_type of float, it should not try to
        # do the conversion, even thought it's trivial
        with self.assertRaises(TypeError) as te:
            self.proxy.update('spinbutton', '1')
        self.assertEqual(
            te.exception.message,
            ("attribute spinbutton of model <Model button='button', "
             "checkbutton=True, combobox='CB1', comboentry='CE1', "
             "entry='666', hscale=100.0, label='label', "
             "radiobutton='first', spinbutton=100, textview='sliff', "
             "vscale=100.0> requires a value of type int, not str"))
コード例 #11
0
ファイル: test_proxy.py プロジェクト: Schevo/kiwi
class TestProxy(unittest.TestCase):
    def setUp(self):
        self.view = FakeView()
        self.view.add('checkbutton', bool, ProxyCheckButton)
        self.view.add('entry', str, ProxyEntry)
        self.view.add('label', str, ProxyLabel)
        self.view.add('spinbutton', int, ProxySpinButton)
        self.view.add('hscale', float, ProxyHScale)
        self.view.add('vscale', float, ProxyVScale)
        self.view.add('button', str, ProxyButton)
        self.view.add('buttonpixbuf', gdk.Pixbuf, ProxyButton)

        self.view.add('textview', str, ProxyTextView)
        self.radio_first = self.view.add('radiobutton', str, ProxyRadioButton)
        self.radio_first.set_property('data_value', 'first')
        self.radio_second = ProxyRadioButton()
        self.radio_second.set_group(self.radio_first)
        self.radio_second.set_property('data_value', 'second')

        self.view.hscale.get_adjustment().upper = 200
        self.view.vscale.get_adjustment().upper = 250

        self.comboentry = self.view.add('comboentry', str, ProxyComboEntry)
        self.comboentry.prefill(['CE1','CE2','CE3'])
        self.comboentry.show()

        self.combobox = self.view.add('combobox', str, ProxyComboBox)
        self.combobox.prefill(['CB1','CB2','CB3'])
        self.combobox.show()

        self.model = Model()
        self.proxy = Proxy(self.view, self.model, self.view.widgets)

    def testCheckButton(self):
        self.assertEqual(self.model.checkbutton, True)
        self.view.checkbutton.set_active(False)
        self.assertEqual(self.model.checkbutton, False)

    def testEntry(self):
        self.assertEqual(self.model.entry, 'foo')
        self.view.entry.set_text('bar')
        self.assertEqual(self.model.entry, 'bar')

    def testLabel(self):
        self.assertEqual(self.model.label, 'label')
        self.view.label.set_text('other label')
        self.assertEqual(self.model.label, 'other label')

    def testRadioButton(self):
        self.assertEqual(self.model.radiobutton, 'first')
        self.radio_second.set_active(True)
        self.assertEqual(self.model.radiobutton, 'second')
        self.radio_first.set_active(True)
        self.assertEqual(self.model.radiobutton, 'first')

    def testHScale(self):
        self.assertEqual(self.model.vscale, 100)
        self.view.vscale.set_value(220)
        self.assertEqual(self.model.vscale, 220)

    def testVScale(self):
        self.assertEqual(self.model.vscale, 100)
        self.view.vscale.set_value(200)
        self.assertEqual(self.model.vscale, 200)

    def testSpinButton(self):
        self.assertEqual(self.model.spinbutton, 100)
        self.view.spinbutton.set_text("200")
        self.assertEqual(self.model.spinbutton, 200)

    def testTextView(self):
        self.assertEqual(self.model.textview, 'sliff')
        self.view.textview.get_buffer().set_text('sloff')
        self.assertEqual(self.model.textview, 'sloff')

    def testComboEntry(self):
        self.assertEqual(self.model.comboentry, 'CE1')
        self.view.comboentry.select('CE2')
        self.assertEqual(self.model.comboentry, 'CE2')
        self.view.comboentry.entry.set_text('CENone')
        self.assertEqual(self.model.comboentry, None)

    def testComboBox(self):
        self.assertEqual(self.model.combobox, 'CB1')
        self.view.combobox.select('CB2')
        self.assertEqual(self.model.combobox, 'CB2')

    def testButton(self):
        self.assertEqual(self.model.button, 'button')
        self.view.button.update('sliff')
        self.assertEqual(self.model.button, 'sliff')

    def testButtonPixbuf(self):
        if sys.platform == 'win32':
            return

        conv = converter.get_converter(gdk.Pixbuf)

        filename = environ.find_resource('pixmap', 'validation-error-16.png')
        pixbuf = gdk.pixbuf_new_from_file(filename)
        self.assertEqual(self.view.buttonpixbuf.data_type, 'Pixbuf')
        self.view.buttonpixbuf.update(pixbuf)
        self.assertEqual(type(self.view.buttonpixbuf.read()), gdk.Pixbuf)
        self.assertEqual(conv.as_string(self.model.buttonpixbuf),
                         conv.as_string(pixbuf))
        self.view.buttonpixbuf.update(None)
        self.assertEqual(self.view.buttonpixbuf.read(), None)
        self.assertEqual(self.model.buttonpixbuf, None)

    def testEmptyModel(self):
        self.radio_second.set_active(True)

        self.proxy.set_model(None)

        self.assertEqual(self.view.entry.read(), ValueUnset)
        self.assertEqual(self.view.checkbutton.read(), False)
        self.assertEqual(self.view.radiobutton.read(), 'first')
        self.assertEqual(self.view.label.read(), '', 'label')
        self.assertEqual(self.view.spinbutton.read(), ValueUnset, 'spinbutton')
        self.assertEqual(self.view.textview.read(), ValueUnset, 'textview')
        self.assertEqual(self.view.comboentry.read(), None, 'comboentry')
        self.assertEqual(self.view.combobox.read(), 'CB1', 'combobox')

    def testValueUnset(self):
        self.view.entry.update(ValueUnset)
        self.assertEqual(self.view.entry.get_text(), "")
        self.view.spinbutton.update(ValueUnset)
        self.assertEqual(self.view.spinbutton.get_text(), "")
コード例 #12
0
ファイル: test_proxy.py プロジェクト: gxela/kiwi-gtk
class TestProxy(unittest.TestCase):
    def setUp(self):
        self.view = FakeView()
        self.view.add('checkbutton', bool, ProxyCheckButton)
        self.view.add('entry', str, ProxyEntry)
        self.view.add('label', str, ProxyLabel)
        self.view.add('spinbutton', int, ProxySpinButton)
        self.view.add('hscale', float, ProxyHScale)
        self.view.add('vscale', float, ProxyVScale)
        self.view.add('button', str, ProxyButton)
        self.view.add('buttonpixbuf', gdk.Pixbuf, ProxyButton)

        self.view.add('textview', str, ProxyTextView)
        self.radio_first = self.view.add('radiobutton', str, ProxyRadioButton)
        self.radio_first.set_property('data_value', 'first')
        self.radio_second = ProxyRadioButton()
        self.radio_second.set_group(self.radio_first)
        self.radio_second.set_property('data_value', 'second')

        self.view.hscale.get_adjustment().upper = 200
        self.view.vscale.get_adjustment().upper = 250

        self.comboentry = self.view.add('comboentry', str, ProxyComboEntry)
        self.comboentry.prefill(['CE1', 'CE2', 'CE3'])
        self.comboentry.show()

        self.combobox = self.view.add('combobox', str, ProxyComboBox)
        self.combobox.prefill(['CB1', 'CB2', 'CB3'])
        self.combobox.show()

        self.model = Model()
        self.proxy = Proxy(self.view, self.model, self.view.widgets)

    def testCheckButton(self):
        self.assertEqual(self.model.checkbutton, True)
        self.view.checkbutton.set_active(False)
        self.assertEqual(self.model.checkbutton, False)

    def testEntry(self):
        self.assertEqual(self.model.entry, 'foo')
        self.view.entry.set_text('bar')
        self.assertEqual(self.model.entry, 'bar')

        # If the widget is insensitive, it should not change the model
        self.view.entry.set_sensitive(False)
        self.view.entry.set_text('bin')
        self.assertEqual(self.model.entry, 'bar')

    def testLabel(self):
        self.assertEqual(self.model.label, 'label')
        self.view.label.set_text('other label')
        # When the proxy label is updated, the model should not change. Labels
        # are non interactive widget, and the user cannot edit the value.
        self.assertEqual(self.model.label, 'label')

    def testRadioButton(self):
        self.assertEqual(self.model.radiobutton, 'first')
        self.radio_second.set_active(True)
        self.assertEqual(self.model.radiobutton, 'second')
        self.radio_first.set_active(True)
        self.assertEqual(self.model.radiobutton, 'first')

    def testHScale(self):
        self.assertEqual(self.model.vscale, 100)
        self.view.vscale.set_value(220)
        self.assertEqual(self.model.vscale, 220)

    def testVScale(self):
        self.assertEqual(self.model.vscale, 100)
        self.view.vscale.set_value(200)
        self.assertEqual(self.model.vscale, 200)

    def testSpinButton(self):
        self.assertEqual(self.model.spinbutton, 100)
        self.view.spinbutton.set_text("200")
        self.assertEqual(self.model.spinbutton, 200)

        # If the widget is insensitive, it should not change the model
        self.view.spinbutton.set_sensitive(False)
        self.view.spinbutton.set_text('400')
        self.assertEqual(self.model.spinbutton, 200)

    def testTextView(self):
        self.assertEqual(self.model.textview, 'sliff')
        self.view.textview.get_buffer().set_text('sloff')
        self.assertEqual(self.model.textview, 'sloff')

    def testComboEntry(self):
        self.assertEqual(self.model.comboentry, 'CE1')
        self.view.comboentry.select('CE2')
        self.assertEqual(self.model.comboentry, 'CE2')
        self.view.comboentry.entry.set_text('CENone')
        self.assertEqual(self.model.comboentry, None)

    def testComboBox(self):
        self.assertEqual(self.model.combobox, 'CB1')
        self.view.combobox.select('CB2')
        self.assertEqual(self.model.combobox, 'CB2')

    def testButton(self):
        self.assertEqual(self.model.button, 'button')
        self.view.button.update('sliff')
        self.assertEqual(self.model.button, 'sliff')

    def testEmptyModel(self):
        self.radio_second.set_active(True)

        self.proxy.set_model(None)

        self.assertEqual(self.view.entry.read(), ValueUnset)
        self.assertEqual(self.view.checkbutton.read(), False)
        self.assertEqual(self.view.radiobutton.read(), 'first')
        self.assertEqual(self.view.label.read(), '', 'label')
        self.assertEqual(self.view.spinbutton.read(), ValueUnset, 'spinbutton')
        self.assertEqual(self.view.textview.read(), ValueUnset, 'textview')
        self.assertEqual(self.view.comboentry.read(), None, 'comboentry')
        self.assertEqual(self.view.combobox.read(), 'CB1', 'combobox')

    def testValueUnset(self):
        self.view.entry.update(ValueUnset)
        self.assertEqual(self.view.entry.get_text(), "")
        self.view.spinbutton.update(ValueUnset)
        self.assertEqual(self.view.spinbutton.get_text(), "")

    def testValueChangeWhenWidgetInalid(self):
        def validate_entry(entry, value):
            if entry.make_invalid:
                return ValidationError("")

        self.view.entry.connect('validate', validate_entry)

        self.view.entry.make_invalid = False
        self.view.entry.update("Propagated immediatly")
        self.assertEqual(self.model.entry, "Propagated immediatly")

        self.view.entry.make_invalid = True
        self.view.entry.update("Propagated later")
        self.assertEqual(self.model.entry, "Propagated immediatly")

        self.view.entry.make_invalid = False
        self.view.entry.validate(force=True)
        self.assertEqual(self.model.entry, "Propagated later")