Example #1
0
    def register_adapters(self):

        # labels

        self.adapt("expan", "label10")

        ad = Adapter(self.model, "toggle")
        ad.connect_widget(self.view["label_t1"], setter=lambda w,v: \
                            w.set_markup("<big><b>%i</b></big>" % v))
        self.adapt(ad)
        self.adapt("toggle", "label_t2")
        # Before PyGTK 2.14 this will display the object ID instead of
        # something useful.
        self.adapt("color", "label_t3")
        self.adapt("url", "label_t4")
        self.adapt("spin", "label_t5")

        # controls
        self.adapt("expan", "expander1")
        self.adapt("toggle", "togglebutton1")
        self.adapt("toggle", "checkbutton1")
        self.adapt("color", "colorbutton1")
        self.adapt("url", "linkbutton1")
        self.adapt("spin", "spinbutton2")

        return
Example #2
0
    def register_adapters(self):

        # labels

        self.adapt("expan", "label10")

        ad = Adapter(self.model, "toggle")
        ad.connect_widget(self.view["label_t1"], setter=lambda w,v: \
                            w.set_markup("<big><b>%i</b></big>" % v))
        self.adapt(ad)
        self.adapt("toggle", "label_t2")
        # Before PyGTK 2.14 this will display the object ID instead of
        # something useful.
        self.adapt("color", "label_t3")
        self.adapt("url", "label_t4")
        self.adapt("spin", "label_t5")

        # controls
        self.adapt("expan", "expander1")
        self.adapt("toggle", "togglebutton1")
        self.adapt("toggle", "checkbutton1")
        self.adapt("color", "colorbutton1")
        self.adapt("url", "linkbutton1")
        self.adapt("spin", "spinbutton2")

        return
Example #3
0
    def __init__(self,
                 model,
                 prop_name,
                 prop_read=None,
                 prop_write=None,
                 value_error=None,
                 spurious=False):

        UserClassAdapter.__init__(self, model, prop_name,
                                  lambda c, i: c.__getitem__(i),
                                  lambda c, v, i: c.__setitem__(i, v),
                                  prop_read, prop_write, value_error, spurious)

        prop = Adapter._get_property(self)

        #prop =  self._get_property() # bug fix reported by A. Dentella
        if not (hasattr(prop, "__getitem__") and hasattr(prop, "__setitem__")):
            # before giving up, unregisters itself as an observer
            # TODO also tear down Intermediate instances
            self.relieve_model(model)
            raise TypeError("Property " + self._prop_name +
                            " is not a valid container")


        self._prop_is_map = isinstance(prop, dict) or \
                            isinstance(prop, ObsMapWrapper)
        # contained widgets
        self._idx2wid = {}
        self._wid2idx = {}

        self._widgets = None
        return
Example #4
0
    def __init__(self, model, prop_name,
                 prop_read=None, prop_write=None, value_error=None,
                 spurious=False):

        UserClassAdapter.__init__(self, model, prop_name,
                                  lambda c,i: c.__getitem__(i),
                                  lambda c,v,i: c.__setitem__(i,v),
                                  prop_read, prop_write,
                                  value_error, spurious)

        prop =  Adapter._get_property(self)

        #prop =  self._get_property() # bug fix reported by A. Dentella
        if not (hasattr(prop, "__getitem__") and
                hasattr(prop, "__setitem__")):
            # before giving up, unregisters itself as an observer
            # TODO also tear down Intermediate instances
            self.relieve_model(model)
            raise TypeError("Property " + self._prop_name +
                            " is not a valid container")


        self._prop_is_map = isinstance(prop, dict) or \
                            isinstance(prop, ObsMapWrapper)
        # contained widgets
        self._idx2wid = {}
        self._wid2idx = {}

        self._widgets = None
        return
Example #5
0
    def register_adapters(self):
        # labels
        self.adapt("expan", "label10")

        ad = Adapter(self.model, "toggle")
        ad.connect_widget(self.view["label_t1"], setter=lambda w,v: \
                            w.set_markup("<big><b>%i</b></big>" % v))
        self.adapt(ad)
        self.adapt("toggle", "label_t2")
        self.adapt("color", "label_t3")
        self.adapt("url", "label_t4")
        self.adapt("spin", "label_t5")

        # controls
        self.adapt("expan", "expander1")
        self.adapt("toggle", "togglebutton1")
        self.adapt("toggle", "checkbutton1")
        self.adapt("color", "colorbutton1")
        #self.adapt("url", "linkbutton1") ##This needs glade-3
        self.adapt("spin", "spinbutton1")
        return
Example #6
0
    def testArguments(self):
        errors = []
        def handle(adapter, name, value):
            errors.append((adapter, name, value))
            adapter.update_widget()

        e = Adapter(self.m, "en1",
            prop_read=lambda v: v/2.0,
            prop_write=lambda v: float(v)*2,
            value_error=handle,
            prop_cast=False,
            )
        e.connect_widget(self.v["entry1"])

        l = Adapter(self.m, "en1")
        l.connect_widget(self.v["label1"],
            setter=lambda w, v: w.set_markup("<big><b>%.2f</b></big>" % v))

        self.assertEqual("5.0", self.v["entry1"].get_text())
        self.assertEqual("10.00", self.v["label1"].get_text())

        self.v["entry1"].set_text("1")
        self.assertEqual("2.00", self.v["label1"].get_text())

        self.v["button1"].clicked()
        self.assertEqual("1.5", self.v["entry1"].get_text())
        self.assertEqual("3.00", self.v["label1"].get_text())

        self.v["entry1"].set_text("?")
        self.assertEqual((e, "en1", "?"), errors[-1])
        self.assertEqual("1.5", self.v["entry1"].get_text())
        self.assertEqual("3.00", self.v["label1"].get_text())
Example #7
0
    def register_adapters(self):
        a1 = Adapter(self.model,
                     "en1",
                     prop_read=lambda v: v / 2.0,
                     prop_write=lambda v: v * 2,
                     value_error=self.handle)
        a1.connect_widget(self.view["entry1"])
        self.adapt(a1)

        a2 = Adapter(self.model, "en1")
        a2.connect_widget(
            self.view["label1"],
            setter=lambda w, v: w.set_markup("<big><b>%.2f</b></big>" % v))
        self.adapt(a2)

        self.e = a1
        self.errors = []
Example #8
0
    def register_adapters(self):
        a1 = Adapter(self.model, "en1",
                     prop_read=lambda v: v/2.0, prop_write=lambda v: v*2,
                     value_error=self.handle)
        a1.connect_widget(self.view["entry1"])
        self.adapt(a1)

        a2 = Adapter(self.model, "en1")
        a2.connect_widget(self.view["label1"],
            setter=lambda w,v: w.set_markup("<big><b>%.2f</b></big>" % v))
        self.adapt(a2)

        self.e = a1
        self.errors = []
Example #9
0
    def testArguments(self):
        errors = []

        def handle(adapter, name, value):
            errors.append((adapter, name, value))
            adapter.update_widget()

        e = Adapter(
            self.m,
            "en1",
            prop_read=lambda v: v / 2.0,
            prop_write=lambda v: float(v) * 2,
            value_error=handle,
            prop_cast=False,
        )
        e.connect_widget(self.v["entry1"])

        l = Adapter(self.m, "en1")
        l.connect_widget(
            self.v["label1"],
            setter=lambda w, v: w.set_markup("<big><b>%.2f</b></big>" % v))

        self.assertEqual("5.0", self.v["entry1"].get_text())
        self.assertEqual("10.00", self.v["label1"].get_text())

        self.v["entry1"].set_text("1")
        self.assertEqual("2.00", self.v["label1"].get_text())

        self.v["button1"].clicked()
        self.assertEqual("1.5", self.v["entry1"].get_text())
        self.assertEqual("3.00", self.v["label1"].get_text())

        self.v["entry1"].set_text("?")
        self.assertEqual((e, "en1", "?"), errors[-1])
        self.assertEqual("1.5", self.v["entry1"].get_text())
        self.assertEqual("3.00", self.v["label1"].get_text())
Example #10
0
    def __create_adapters__(self, prop_name, wid_name, flavour=None):
        """
        Private service that looks at property and widgets types,
        and possibly creates one or more (best) fitting adapters
        that are returned as a list.

        ``flavour`` is optionally used when a particular flavour
        must be used when seraching in default adapters.
        """
        res = []

        wid = self.view[wid_name]
        if wid is None:
            raise ValueError("Widget '%s' not found" % wid_name)

        # Decides the type of adapters to be created.
        if isinstance(wid, Gtk.Calendar):
            # calendar creates three adapter for year, month and day
            ad = RoUserClassAdapter(self.model, prop_name,
                                    lambda d: d.year,
                                    lambda d,y: d.replace(year=y),
                                    spurious=self.accepts_spurious_change())
            ad.connect_widget(wid, lambda c: c.get_date()[0],
                              lambda c,y: c.select_month(c.get_date()[1], y),
                              "day-selected", flavour=flavour)
            res.append(ad) # year

            ad = RoUserClassAdapter(self.model, prop_name,
                                    lambda d: d.month,
                                    lambda d,m: d.replace(month=m),
                                    spurious=self.accepts_spurious_change())
            ad.connect_widget(wid, lambda c: c.get_date()[1]+1,
                              lambda c,m: c.select_month(m-1, c.get_date()[0]),
                              "day-selected", flavour=flavour)
            res.append(ad) # month

            ad = RoUserClassAdapter(self.model, prop_name,
                                    lambda d: d.day,
                                    lambda d,v: d.replace(day=v),
                                    spurious=self.accepts_spurious_change())
            ad.connect_widget(wid, lambda c: c.get_date()[2],
                              lambda c,d: c.select_day(d),
                              "day-selected", flavour=flavour)
            res.append(ad) # day
            return res

        try: # tries with StaticContainerAdapter
            if "." in prop_name:
                raise TypeError
            ad = StaticContainerAdapter(self.model, prop_name,
                                        spurious=self.accepts_spurious_change())
            ad.connect_widget(wid, flavours=flavour)
            res.append(ad)

        except TypeError as e:
            # falls back to a simple adapter
            ad = Adapter(self.model, prop_name,
                         spurious=self.accepts_spurious_change())
            ad.connect_widget(wid, flavour=flavour)
            res.append(ad)

        return res
Example #11
0
    def adapt(self, *args, **kwargs):
        """
        There are five ways to call this:

        .. method:: adapt()
           :noindex:

           Take properties from the model for which ``adapt`` has not yet been
           called, match them to the view by name, and create adapters fitting
           for the respective widget type.

           That information comes from :mod:`gtkmvc3.adapters.default`.
           See :meth:`_find_widget_match` for name patterns.

           .. versionchanged:: 1.99.1
              Allow incomplete auto-adaption, meaning properties for which no
              widget is found.

        .. method:: adapt(ad)
           :noindex:

           Keep track of manually created adapters for future ``adapt()``
           calls.

           *ad* is an adapter instance already connected to a widget.

        .. method:: adapt(prop_name)
           :noindex:

           Like ``adapt()`` for a single property.

           *prop_name* is a string.

        .. method:: adapt(prop_name, wid_name)
           :noindex:

           Like ``adapt(prop_name)`` but without widget name matching.

           *wid_name* has to exist in the view.

        .. method:: adapt(prop_name, wid_name, gprop_name)
           :noindex:

           Like ``adapt(prop_name, wid_name)`` but without using default
           adapters. This is useful to adapt secondary properties like
           button sensitivity.

           *gprop_name* is a string naming a property of the widget. No cast
           is attempted, so *prop_name* must match its type exactly.

           .. versionadded:: 1.99.2

        In all cases, optional keyword argument ``flavour=value``
        can be used to specify a particular flavour from those
        available in :mod:`gtkmvc3.adapters.default` adapters.
        """

        # checks arguments
        n = len(args)

        flavour = kwargs.get("flavour", None)

        if n==0:
            adapters = []
            props = self.model.get_properties()
            # matches all properties not previoulsy adapter by the user:
            for prop_name in (p for p in props
                              if p not in self.__user_props):
                try: wid_name = self._find_widget_match(prop_name)
                except TooManyCandidatesError as e:
                    # multiple candidates, gives up
                    raise e
                except ValueError as e:
                    # no widgets found for given property, continue after emitting a warning
                    if e.args:
                        logger.warn(e[0])
                    else:
                        logger.warn("No widget candidates match property '%s'"
                            % prop_name)
                else:
                    logger.debug("Auto-adapting property %s and widget %s" % \
                                     (prop_name, wid_name))
                    adapters += self.__create_adapters__(prop_name, wid_name, flavour)

        elif n == 1: #one argument
            if isinstance(args[0], Adapter): adapters = (args[0],)

            elif isinstance(args[0], str):
                prop_name = args[0]
                wid_name = self._find_widget_match(prop_name)
                adapters = self.__create_adapters__(prop_name, wid_name, flavour)

            else:
                raise TypeError("Argument of adapt() must be either an "
                                "Adapter or a string")

        elif n == 2: # two arguments
            if not (isinstance(args[0], str) and
                    isinstance(args[1], str)):
                raise TypeError("Arguments of adapt() must be two strings")

            # retrieves both property and widget, and creates an adapter
            prop_name, wid_name = args
            adapters = self.__create_adapters__(prop_name, wid_name, flavour)

        elif n == 3:
            for arg in args:
                if not isinstance(arg, str):
                    raise TypeError("names must be strings")

            prop_name, wid_name, gprop_name = args
            ad = Adapter(self.model, prop_name)
            ad.connect_widget(self.view[wid_name],
                              getter=lambda w: w.get_property(gprop_name),
                              setter=lambda w, v: w.set_property(gprop_name, v),
                              signal='notify::%s' % gprop_name,
                              flavour=flavour)
            adapters = [ad]

        else:
            raise TypeError(
                "adapt() takes at most three arguments (%i given)" % n)

        for ad in adapters:
            self.__adapters.append(ad)
            # remember properties added by the user
            if n > 0: self.__user_props.add(ad.get_property_name())