Ejemplo n.º 1
0
    def __init__(self, items, **kwargs):
        kwargs['cols'] = 2
        super(MasterDetailView, self).__init__(**kwargs)

        list_item_args_converter = \
                lambda row_index, rec: {'text': rec['name'],
                                        'size_hint_y': None,
                                        'height': 25}

        dict_adapter = DictAdapter(sorted_keys=sorted(fruit_data.keys()),
                                   data=fruit_data,
                                   args_converter=list_item_args_converter,
                                   selection_mode='single',
                                   allow_empty_selection=False,
                                   cls=ListItemButton)

        master_list_view = ListView(adapter=dict_adapter,
                                    size_hint=(.3, 1.0))

        self.add_widget(master_list_view)

        detail_view = FruitDetailView(
                fruit_name=dict_adapter.selection[0].text,
                size_hint=(.7, 1.0))

        dict_adapter.bind(on_selection_change=detail_view.fruit_changed)
        self.add_widget(detail_view)
Ejemplo n.º 2
0
    def test_dict_adapter_selection_cascade(self):

        # Categories of fruits:
        #
        categories = sorted(fruit_categories.keys())
        categories_dict_adapter = \
            DictAdapter(sorted_keys=categories,
                        data=fruit_categories,
                        args_converter=self.args_converter,
                        selection_mode='single',
                        allow_empty_selection=False,
                        cls=ListItemButton)

        fruit_categories_list_view = \
            ListView(adapter=categories_dict_adapter,
                     size_hint=(.2, 1.0))

        # Fruits, for a given category, are shown based on the fruit category
        # selected in the first categories list above. The selected item in
        # the first list is used as the key into a dict of lists of list
        # items to reset the data in FruitsDictAdapter's
        # fruit_category_changed() method.
        #
        # data is initially set to the first list of list items.
        #
        fruits_dict_adapter = \
                FruitsDictAdapter(
                    sorted_keys=fruit_categories[categories[0]]['fruits'],
                    data=fruit_data,
                    args_converter=self.args_converter,
                    selection_mode='single',
                    allow_empty_selection=False,
                    cls=ListItemButton)

        categories_dict_adapter.bind(
            on_selection_change=fruits_dict_adapter.fruit_category_changed)

        fruits_list_view = ListView(adapter=fruits_dict_adapter,
                                    size_hint=(.2, 1.0))

        # List views should have adapters set.
        self.assertEqual(fruit_categories_list_view.adapter,
                         categories_dict_adapter)
        self.assertEqual(fruits_list_view.adapter, fruits_dict_adapter)

        # Each list adapter has allow_empty_selection=False, so each should
        # have one selected item.
        self.assertEqual(len(categories_dict_adapter.selection), 1)
        self.assertEqual(len(fruits_dict_adapter.selection), 1)

        # The selected list items should show is_selected True.
        self.assertEqual(categories_dict_adapter.selection[0].is_selected,
                         True)
        self.assertEqual(fruits_dict_adapter.selection[0].is_selected, True)

        # And they should be red, for background_color.
        self.assertEqual(categories_dict_adapter.selection[0].background_color,
                         [1.0, 0., 0., 1.0])
        self.assertEqual(fruits_dict_adapter.selection[0].background_color,
                         [1.0, 0., 0., 1.0])
Ejemplo n.º 3
0
    def __init__(self, items, **kwargs):
        kwargs['cols'] = 2
        super(MasterDetailView, self).__init__(**kwargs)

        list_item_args_converter = \
                lambda row_index, rec: {'text': rec[1],
                                        'size_hint_y': None,
                                        'height': 25,
										'id' : str(rec[0])}

        dict_adapter = DictAdapter(sorted_keys=[i[0] for i in myquery.query_result],
                                   data=myquery.q_result_dict,
                                   args_converter=list_item_args_converter,
                                   selection_mode='single',
                                   allow_empty_selection=False,
                                   cls=ListItemButton)

        master_list_view = ListView(adapter=dict_adapter,
                                    size_hint=(.3, 1.0))

        self.add_widget(master_list_view)

        detail_view = PageDetailView(
                page_txt=dict_adapter.selection[0].text,
				page_id=dict_adapter.selection[0].id,
                size_hint=(.7, 1.0),
				tname=myquery.q_table)

        dict_adapter.bind(on_selection_change=detail_view.page_changed)
        self.add_widget(detail_view)
Ejemplo n.º 4
0
    def test_dict_adapter_selection_cascade(self):

        # Categories of fruits:
        #
        categories = sorted(fruit_categories.keys())
        categories_dict_adapter = \
            DictAdapter(sorted_keys=categories,
                        data=fruit_categories,
                        args_converter=self.args_converter,
                        selection_mode='single',
                        allow_empty_selection=False,
                        cls=ListItemButton)

        fruit_categories_list_view = \
            ListView(adapter=categories_dict_adapter,
                     size_hint=(.2, 1.0))

        # Fruits, for a given category, are shown based on the fruit category
        # selected in the first categories list above. The selected item in
        # the first list is used as the key into a dict of lists of list
        # items to reset the data in FruitsDictAdapter's
        # fruit_category_changed() method.
        #
        # data is initially set to the first list of list items.
        #
        fruits_dict_adapter = \
                FruitsDictAdapter(
                    sorted_keys=fruit_categories[categories[0]]['fruits'],
                    data=fruit_data,
                    args_converter=self.args_converter,
                    selection_mode='single',
                    allow_empty_selection=False,
                    cls=ListItemButton)

        categories_dict_adapter.bind(
            on_selection_change=fruits_dict_adapter.fruit_category_changed)

        fruits_list_view = ListView(
            adapter=fruits_dict_adapter, size_hint=(.2, 1.0))

        # List views should have adapters set.
        self.assertEqual(fruit_categories_list_view.adapter,
                         categories_dict_adapter)
        self.assertEqual(fruits_list_view.adapter, fruits_dict_adapter)

        # Each list adapter has allow_empty_selection=False, so each should
        # have one selected item.
        self.assertEqual(len(categories_dict_adapter.selection), 1)
        self.assertEqual(len(fruits_dict_adapter.selection), 1)

        # The selected list items should show is_selected True.
        self.assertEqual(categories_dict_adapter.selection[0].is_selected,
                         True)
        self.assertEqual(fruits_dict_adapter.selection[0].is_selected, True)

        # And they should be red, for background_color.
        self.assertEqual(categories_dict_adapter.selection[0].background_color,
                         [1.0, 0., 0., 1.0])
        self.assertEqual(fruits_dict_adapter.selection[0].background_color,
                         [1.0, 0., 0., 1.0])
Ejemplo n.º 5
0
    def __init__(self, items, **kwargs):
        kwargs['cols'] = 2
        kwargs['size_hint'] = (1.0, 1.0)
        super(MasterDetailView, self).__init__(**kwargs)

        list_item_args_converter = \
                lambda row_index, rec: {'text': rec['name'],
                                        'size_hint_y': None,
                                        'height': 25}

        dict_adapter = DictAdapter(sorted_keys=sorted(fruit_data.keys()),
                                   data=fruit_data,
                                   args_converter=list_item_args_converter,
                                   selection_mode='single',
                                   allow_empty_selection=False,
                                   cls=ListItemButton)

        master_list_view = ListView(adapter=dict_adapter, size_hint=(.3, 1.0))

        self.add_widget(master_list_view)

        detail_view = FruitDetailView(
            fruit_name=dict_adapter.selection[0].text, size_hint=(.7, 1.0))

        dict_adapter.bind(on_selection_change=detail_view.fruit_changed)
        self.add_widget(detail_view)
Ejemplo n.º 6
0
class PlayerListView(ModalView):
    player_adapter = ObjectProperty(None)
    match_perf = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(PlayerListView, self).__init__(**kwargs)

        # filled in later with call to reload()
        self.player_adapter = DictAdapter(sorted_keys=[],
                                          data={},
                                          args_converter=self._player_converter,
                                          selection_mode='multiple',
                                          propagate_selection_to_data=True,
                                          template='CustomListItem')

        self.d2rp = None # set by parent

    def _player_converter(self, idx, rec):
        return {'player_label': rec['player_label'],
                'is_selected': rec['is_selected'],
                'size_hint_y': None,
                'height': 25}

    def reload(self):
        if not self.d2rp:
            return

        hero_len = max([len(dotalocal.hero[h['hero']]) for h in self.d2rp.players])

        p_str = {}
        for i,hero in enumerate(self.d2rp.players):
            hero_s = dotalocal.hero[hero['hero']]
            player = dotalocal.player(hero['player'])
            p_str[str(i)] = { 
                'player_label': ' {} | {}'.format(hero_s.ljust(hero_len), player),
                'is_selected': False }

        self.player_adapter = DictAdapter(sorted_keys=[i for i in range(len(p_str))],
                                          data=p_str,
                                          args_converter=self._player_converter,
                                          selection_mode='multiple',
                                          propagate_selection_to_data=True,
                                          template='CustomListItem')

        self.player_adapter.bind(on_selection_change=self.selection_changed)

    def selection_changed(self, *args):
        self.match_perf.redraw()

    def get_selected(self):
        selected = []
        for btn in self.player_adapter.selection:
            hero_s = btn.text.split('|')[0].strip()
            #for pl in self.d2rp.players:
            for pl in self.match_perf.match.all_players():
                if dotalocal.hero[pl['hero']] == hero_s:
                    selected.append(pl)
                    break
        return selected
Ejemplo n.º 7
0
    def __init__(self, **kwargs):
        kwargs['cols'] = 3
        kwargs['size_hint'] = (1.0, 1.0)
        super(CascadingView, self).__init__(**kwargs)

        list_item_args_converter = \
                lambda row_index, rec: {'text': rec['name'],
                                        'size_hint_y': None,
                                        'height': 25}

        # Fruit categories list on the left:
        #
        categories = sorted(fruit_categories.keys())
        fruit_categories_list_adapter = \
            DictAdapter(
                    sorted_keys=categories,
                    data=fruit_categories,
                    args_converter=list_item_args_converter,
                    selection_mode='single',
                    allow_empty_selection=False,
                    cls=ListItemButton)
        fruit_categories_list_view = \
                ListView(adapter=fruit_categories_list_adapter,
                        size_hint=(.2, 1.0))
        self.add_widget(fruit_categories_list_view)

        # Fruits, for a given category, in the middle:
        #
        image_list_item_args_converter = \
                lambda row_index, rec: {'text': rec['name'],
                                        'size_hint_y': None,
                                        'height': 32}
        fruits_list_adapter = \
                FruitsDictAdapter(
                    sorted_keys=fruit_categories[categories[0]]['fruits'],
                    data=fruit_data,
                    args_converter=image_list_item_args_converter,
                    selection_mode='single',
                    allow_empty_selection=False,
                    template='ThumbnailedListItem')
        fruits_list_view = \
                ListView(adapter=fruits_list_adapter,
                    size_hint=(.2, 1.0))

        fruit_categories_list_adapter.bind(
                on_selection_change=fruits_list_adapter.fruit_category_changed)

        self.add_widget(fruits_list_view)

        # Detail view, for a given fruit, on the right:
        #
        detail_view = FruitImageDetailView(
                fruit_name=fruits_list_adapter.selection[0].fruit_name,
                size_hint=(.6, 1.0))

        fruits_list_adapter.bind(
                on_selection_change=detail_view.fruit_changed)
        self.add_widget(detail_view)
    def __init__(self, **kwargs):
        kwargs['cols'] = 3
        super(CascadingView, self).__init__(**kwargs)

        list_item_args_converter = \
                lambda row_index, rec: {'text': rec['name'],
                                        'size_hint_y': None,
                                        'height': 25}

        # Fruit categories list on the left:
        #
        categories = sorted(fruit_categories.keys())
        fruit_categories_list_adapter = \
            DictAdapter(
                    sorted_keys=categories,
                    data=fruit_categories,
                    args_converter=list_item_args_converter,
                    selection_mode='single',
                    allow_empty_selection=False,
                    cls=ListItemButton)
        fruit_categories_list_view = \
                ListView(adapter=fruit_categories_list_adapter,
                        size_hint=(.2, 1.0))
        self.add_widget(fruit_categories_list_view)

        # Fruits, for a given category, in the middle:
        #
        image_list_item_args_converter = \
                lambda row_index, rec: {'text': rec['name'],
                                        'size_hint_y': None,
                                        'height': 32}
        fruits_list_adapter = \
                FruitsDictAdapter(
                    sorted_keys=fruit_categories[categories[0]]['fruits'],
                    data=fruit_data,
                    args_converter=image_list_item_args_converter,
                    selection_mode='single',
                    allow_empty_selection=False,
                    template='ThumbnailedListItem')
        fruits_list_view = \
                ListView(adapter=fruits_list_adapter,
                    size_hint=(.2, 1.0))

        fruit_categories_list_adapter.bind(
                on_selection_change=fruits_list_adapter.fruit_category_changed)

        self.add_widget(fruits_list_view)

        # Detail view, for a given fruit, on the right:
        #
        detail_view = FruitImageDetailView(
                fruit_name=fruits_list_adapter.selection[0].fruit_name,
                size_hint=(.6, 1.0))

        fruits_list_adapter.bind(
                on_selection_change=detail_view.fruit_changed)
        self.add_widget(detail_view)
Ejemplo n.º 9
0
    def on_enter(self):
        """ Repopulate the listview """
        info = self.playlist.get_info
        data = {
            str(i): {
                'text': item[0],
                'source': item[1],
                'album': info(item[0])["album"],
                'track': info(item[0])["file"],
                'is_selected': bool(i == self.playlist.current)
            }
            for i, item in enumerate(self.playlist.queue)
        }

        def args_converter(row_index, item):
            return {
                'text':
                item['text'],
                'size_hint_y':
                None,
                'height':
                "50dp",
                'cls_dicts': [{
                    'cls': ZenListImage,
                    'kwargs': {
                        'source': item['source'],
                        'size_hint_x': 0.1,
                        'row_index': row_index
                    }
                }, {
                    'cls': ZenListButton,
                    'kwargs': {
                        'text': item['track'],
                        'is_representing_cls': True,
                        'size_hint_x': 0.55,
                        'row_index': row_index
                    }
                }, {
                    'cls': ZenListButton,
                    'kwargs': {
                        'text': item['album'],
                        'size_hint_x': 0.35,
                        'row_index': row_index
                    }
                }]
            }

        dict_adapter = DictAdapter(
            sorted_keys=[str(i) for i in range(len(self.playlist.queue))],
            data=data,
            selection_mode='single',
            args_converter=args_converter,
            propagate_selection_to_data=True,
            cls=ZenListItem)

        self.listview.adapter = dict_adapter
        dict_adapter.bind(on_selection_change=self.selection_changed)
Ejemplo n.º 10
0
    def __init__(self, **kwargs):

        super(PlaylistLayout, self).__init__(**kwargs)

        integers_dict = {
            str(i): {
                'source': basename(self.playlist[i][0]),
                'size': '%dx%d' % tuple(self.playlist[i][3]) \
                        if self.playlist[i][0].lower().endswith('.yuv') else '',
                'format': self.playlist[i][1].upper() \
                          if self.playlist[i][0].lower().endswith('.yuv') else '',
                'playlist': self.playlist[i],
                'is_selected': False
            } for i in xrange(len(self.playlist))
        }
        args_converter = lambda row_index, rec: {
            'text':
            rec['source'],
            'size_hint_y':
            None,
            'height':
            25,
            'cls_dicts': [{
                'cls': ListItemButton,
                'kwargs': {
                    'text': rec['source']
                }
            }, {
                'cls': ListItemButton,
                'kwargs': {
                    'text': rec['size'],
                    'size_hint_x': None,
                    'width': 100
                }
            }, {
                'cls': ListItemButton,
                'kwargs': {
                    'text': rec['format'],
                    'size_hint_x': None,
                    'width': 70
                }
            }]
        }
        item_strings = [
            "{0}".format(index) for index in xrange(len(self.playlist))
        ]
        dict_adapter = DictAdapter(sorted_keys=item_strings,
                                   data=integers_dict,
                                   args_converter=args_converter,
                                   selection_mode='single',
                                   allow_empty_selection=False,
                                   cls=CompositeListItem)
        dict_adapter.bind(selection=self.setter('selection'))
        list_view = ListView(adapter=dict_adapter)
        self.layout.add_widget(list_view)
Ejemplo n.º 11
0
    def fill_er_up(self, unused=None):
        dc = "deselected_color"
        sc = "selected_color"
        args_converter = \
            lambda row_index, rec: \
                {"size_hint_y": None,
                 "height": 25,
                 #"height": rec["height"],
                 #"background_color": rec["status_colour"],
                 "cls_dicts": [
                       {"cls": MyListItemButton,
                           "kwargs": {"text": rec["id"]}}, #, dc: rec[dc]}},
                       {"cls": MyListItemButton,
                           "kwargs": {"text": rec["black"]}},
                       {"cls": MyListItemButton,
                           "kwargs": {"text": rec["white"]}},
                       {"cls": MyListItemButton,
                           "kwargs": {"text": rec["date"]}},
                       {"cls": MyListItemButton,
                           "kwargs": {"text": rec["size"]}},
                       {"cls": MyListItemButton,
                           "kwargs": {"text": rec["rules"]}},
                       ]}

        # TODO: Another hack - parent.parent
        gm = self.parent.parent.gm
        pm = gm.get_players_mgr()
        if self.screen.show_finished:
            games = gm.get_recently_finished()
        else:
            games = gm.get_all_unfinished_preserved()

        # TODO: The "if" is a hack
        games_dict = { g.game_id: game_data(g, pm) for g in games if g }

        self.item_strings = ["{0}".format(g_id) for g_id in games_dict.iterkeys() ]

        dict_adapter = DictAdapter(data=games_dict,
                                   args_converter=args_converter,
                                   selection_mode="single",
                                   allow_empty_selection=False, # Not working?
                                   cls=TwoLevelCompositeListItem)

        dict_adapter.bind(
            on_selection_change=self.changed_selection)

        self.adapter = dict_adapter

        # Use the adapter in our ListView:
        list_view = ListView(adapter=dict_adapter)

        self.add_widget(list_view)
        self.view = list_view
Ejemplo n.º 12
0
    def dump_data(self, **kwargs):
        from lvargsconv import args_convertor
        items = {str(i): kwargs['data'][i] for i in range(len(kwargs['data']))}
        print items
        dict_adapter = DictAdapter(
            data=items,
            args_converter=args_convertor,
            selection_mode='single',
            allow_empty_selection=True,
            cls=CustomListItem)

        dict_adapter.bind(on_selection_change=self.on_select)

        self.clear_widgets()
        self.add_widget(ListView(adapter=dict_adapter))
        pass
Ejemplo n.º 13
0
    def __init__(self, **kwargs):
        kwargs["cols"] = 3
        super(CascadingView, self).__init__(**kwargs)

        list_item_args_converter = lambda row_index, rec: {"text": rec["name"], "size_hint_y": None, "height": 25}

        # Fruit categories list on the left:
        #
        categories = sorted(fruit_categories.keys())
        fruit_categories_list_adapter = DictAdapter(
            sorted_keys=categories,
            data=fruit_categories,
            args_converter=list_item_args_converter,
            selection_mode="single",
            allow_empty_selection=False,
            cls=ListItemButton,
        )
        fruit_categories_list_view = ListView(adapter=fruit_categories_list_adapter, size_hint=(0.2, 1.0))
        self.add_widget(fruit_categories_list_view)

        # Fruits, for a given category, in the middle:
        #
        image_list_item_args_converter = lambda row_index, rec: {"text": rec["name"], "size_hint_y": None, "height": 32}
        fruits_list_adapter = FruitsDictAdapter(
            sorted_keys=fruit_categories[categories[0]]["fruits"],
            data=fruit_data,
            args_converter=image_list_item_args_converter,
            selection_mode="single",
            allow_empty_selection=False,
            template="ThumbnailedListItem",
        )
        fruits_list_view = ListView(adapter=fruits_list_adapter, size_hint=(0.2, 1.0))

        fruit_categories_list_adapter.bind(on_selection_change=fruits_list_adapter.fruit_category_changed)

        self.add_widget(fruits_list_view)

        # Detail view, for a given fruit, on the right:
        #
        detail_view = FruitImageDetailView(fruit_name=fruits_list_adapter.selection[0].fruit_name, size_hint=(0.6, 1.0))

        fruits_list_adapter.bind(on_selection_change=detail_view.fruit_changed)
        self.add_widget(detail_view)
Ejemplo n.º 14
0
 def __init__(self, **kwargs):
     self.level = self.level+ 1
     subdirs={}
     if self.level <= 2:
         for subfolder in os.listdir(self.datadir):
             if os.path.isdir(os.path.join(self.datadir,subfolder)):
                 subdirs[os.path.join(self.datadir,subfolder)] = {'text': subfolder,'is_selected': False}
     else:
         for subfolder in os.listdir(self.datadir):
             subdirs[os.path.join(self.datadir,subfolder)] = {'text': subfolder,'is_selected': False}
     args_converter = \
         lambda row_index, rec: {'text': rec['text'],
                                 'is_selected': rec['is_selected'],
                                 'size_hint_y': 10,
                                 'height': 40}
     f_adapter = DictAdapter(data=subdirs,
                              args_converter=args_converter,
                              sorted_keys=subdirs.keys(),
                              template='FListItem')
     super(FView, self).__init__(adapter=f_adapter)
     f_adapter.bind(on_selection_change=self.callback)
Ejemplo n.º 15
0
    def __init__(self, **kwargs):

        super(PlaylistLayout, self).__init__(**kwargs)

        integers_dict = {
            str(i): {
                'source': basename(self.playlist[i][0]),
                'size': '%dx%d' % tuple(self.playlist[i][3]) \
                        if self.playlist[i][0].lower().endswith('.yuv') else '',
                'format': self.playlist[i][1].upper() \
                          if self.playlist[i][0].lower().endswith('.yuv') else '',
                'playlist': self.playlist[i],
                'is_selected': False
            } for i in xrange(len(self.playlist))
        }
        args_converter = lambda row_index, rec: {
            'text': rec['source'],
            'size_hint_y': None,
            'height': 25,
            'cls_dicts': [
                {'cls': ListItemButton,
                 'kwargs': {'text': rec['source']}},
                {'cls': ListItemButton,
                 'kwargs': {'text': rec['size'],
                            'size_hint_x': None, 'width': 100}},
                {'cls': ListItemButton,
                 'kwargs': {'text': rec['format'],
                            'size_hint_x': None, 'width': 70}}
            ]
        }
        item_strings = ["{0}".format(index) for index in xrange(len(self.playlist))]
        dict_adapter = DictAdapter(sorted_keys=item_strings,
                                   data=integers_dict,
                                   args_converter=args_converter,
                                   selection_mode='single',
                                   allow_empty_selection=False,
                                   cls=CompositeListItem)
        dict_adapter.bind(selection=self.setter('selection'))
        list_view = ListView(adapter=dict_adapter)
        self.layout.add_widget(list_view)
Ejemplo n.º 16
0
    def __init__(self, **kwargs):
        kwargs['cols'] = 3
        kwargs['size_hint'] = (1.0, 1.0)
        super(TwoUpView, self).__init__(**kwargs)

        list_item_args_converter = \
                lambda row_index, rec: {'text': rec['name'],
                                        'size_hint_y': None,
                                        'height': 25}

        fruits_dict_adapter = \
                DictAdapter(
                    sorted_keys=sorted(fruit_data.keys()),
                    data=fruit_data,
                    args_converter=list_item_args_converter,
                    selection_mode='multiple',
                    allow_empty_selection=False,
                    cls=ListItemButton)

        fruits_list_view = ListView(adapter=fruits_dict_adapter,
                                    size_hint=(.2, 1.0))

        self.add_widget(fruits_list_view)

        fruits_dict_adapter2 = \
                ReceivingFruitsDictAdapter(
                    sorted_keys=[],
                    data={},
                    args_converter=list_item_args_converter,
                    selection_mode='single',
                    allow_empty_selection=True,
                    cls=ListItemButton)

        fruits_list_view2 = ListView(adapter=fruits_dict_adapter2,
                                     size_hint=(.2, 1.0))

        fruits_dict_adapter.bind(
                on_selection_change=fruits_dict_adapter2.fruits_changed)

        self.add_widget(fruits_list_view2)
Ejemplo n.º 17
0
    def on_enter(self):
        """ Repopulate the listview """
        info = self.playlist.get_info
        data = {str(i): {'text': item[0],
                         'source': item[1],
                         'album': info(item[0])["album"],
                         'track': info(item[0])["file"],
                         'is_selected': bool(i == self.playlist.current)}
                for i, item in enumerate(self.playlist.queue)}

        def args_converter(row_index, item):
            return {'text': item['text'],
                    'size_hint_y': None,
                    'height': "60sp",
                    'cls_dicts': [{'cls': ZenListImage,
                                   'kwargs': {'source': item['source'],
                                              'size_hint_x': 0.1,
                                              'row_index': row_index}},
                                  {'cls': ZenListButton,
                                   'kwargs': {'text': item['track'],
                                              'is_representing_cls': True,
                                              'size_hint_x': 0.55,
                                              'row_index': row_index}},
                                  {'cls': ZenListButton,
                                   'kwargs': {'text': item['album'],
                                              'size_hint_x': 0.35,
                                              'row_index': row_index}}]}

        dict_adapter = DictAdapter(
            sorted_keys=[str(i) for i in range(len(self.playlist.queue))],
            data=data,
            selection_mode='single',
            args_converter=args_converter,
            propagate_selection_to_data=True,
            cls=ZenListItem)

        self.listview.adapter = dict_adapter
        dict_adapter.bind(on_selection_change=self.selection_changed)
Ejemplo n.º 18
0
class ObjectGraphRenderer(FloatLayout):

    # So far has no capability to handle window/editor rescaling.
    # Maybe fold into CropObjectRenderer?

    views_mask = DictProperty(dict())
    '''If an edge is in the views mask and its entry is False,
    it will not be passed to the adapter for rendering.'''

    redraw = NumericProperty(0)
    '''Change this property to force redraw.'''
    def __init__(self, annot_model, graph, editor_widget, **kwargs):

        super(ObjectGraphRenderer, self).__init__(**kwargs)
        logging.info('ObjectGraphRenderer: initializing, with {0} edges'
                     ' in the graph.'.format(len(graph.edges)))

        self.model = annot_model
        self.graph = graph

        self.size = editor_widget.size
        self.pos = editor_widget.pos

        editor_widget.bind(size=self._update_size)
        editor_widget.bind(pos=self._update_pos)

        self.edge_adapter = DictAdapter(
            data=self.graph.edges,
            args_converter=self.edge_converter,
            selection_mode='multiple',
            cls=EdgeView,
        )

        self.view = EdgeListView(adapter=self.edge_adapter,
                                 size_hint=(None, None),
                                 size=self.size,
                                 pos=self.pos)
        self.edge_adapter.bind(
            on_selection_change=self.view.broadcast_selection)

        self.views_mask = dict()

        # Hacking the ListView
        # logging.debug('View children: {0}'.format(self.view.children))
        self.view.remove_widget(self.view.children[0])
        self.view.container = FloatLayout(pos=self.pos, size=self.size)
        self.view.add_widget(self.view.container)

        Window.bind(on_key_down=self.view.on_key_down)
        Window.bind(on_key_up=self.view.on_key_up)

        # Automating the redraw pipeline:
        #  - when edge data changes, fill in adapter data,
        self.graph.bind(edges=self.update_edge_adapter_data)
        #  - once adapter data changes, redraw
        self.edge_adapter.bind(data=self.do_redraw)

        self.add_widget(self.view)

    def update_edge_adapter_data(self, instance, edges):
        """Copy the graph's edges to adapter data.

        Also updates the mask.
        """
        self._update_views_mask(edges)

        self.edge_adapter.cached_views = dict()
        new_data = {}

        for e, e_class in edges.items():
            if (e in self.views_mask) and (self.views_mask[e] is False):
                logging.debug('ObjGraphRenderer: edge {0} masked out.'
                              ''.format(e))
                continue
            # The adapter creates its Views from the *values* of
            # its `data` dict. So, we must supply the edge as a part
            # of the dict value, not just the key.
            new_data[e] = (e, e_class)
        # This fires self.do_redraw():
        self.edge_adapter.data = new_data

    def _update_views_mask(self, edges, show_new=True):
        """

        All edges that were previously not in the mask are added,
        with the ``show_new`` argument controlling whether they will
        be shown or hidden by default.

        All edges that were in the mask and are not in the data anymore
        will be removed from the mask.

        All edges that were already in the mask have their status unchanged.
        """
        new_mask = dict()
        for e, e_class in edges.items():
            if e in self.views_mask:
                new_mask[e] = self.views_mask[e]
            else:
                new_mask[e] = show_new
        self.views_mask = new_mask

    def on_redraw(self, instance, pos):
        self.do_redraw()

    def do_redraw(self, *args, **kwargs):
        # Args and kwargs given so that it can be fired by an on_edges
        # event from the graph.
        logging.debug('ObjGraphRenderer: requested do_redraw, renderer'
                      ' size: {0}'
                      ''.format(self.redraw, self.size))
        self.view.populate()
        # self.view.log_rendered_edges()

    def edge_converter(self, row_index, rec):
        """Interface between the edge and the EdgeView."""
        # logging.info('EdgeRenderer: Requesting EdgeView kwargs for edge: {0}'
        #              ''.format(rec))

        e = rec[0]
        e_class = rec[1]

        # Get the connected CropObjects
        obj_from = self.model.cropobjects[e[0]]
        e_obj_from = self._cropobject_to_editor_world(obj_from)

        obj_to = self.model.cropobjects[e[1]]
        e_obj_to = self._cropobject_to_editor_world(obj_to)

        # Return the recomputed objects as kwargs for the EdgeView
        output = {
            'is_selected': False,
            'cropobject_from': e_obj_from,
            'cropobject_to': e_obj_to,
            'edge_label': e_class,
        }
        # logging.info('EdgeRenderer: edge_converter fired, output: {0},'
        #              ' class: {1}'
        #              ''.format(output, self.edge_adapter.get_cls()))
        return output

    def _cropobject_to_editor_world(self, obj):
        """Creates an equivalent of the given CropObject with coordinates
        in the current editor world (uses the App's scaler)."""

        # Recompute a counterpart of theirs to editor world
        mt, ml, mb, mr = obj.bounding_box
        et, el, eb, er = self.scaler.bbox_model2widget(mt, ml, mb, mr)

        obj_updated = copy.deepcopy(obj)
        # Editor world counts X from the *bottom*
        obj_updated.x = eb
        obj_updated.y = el
        obj_updated.width = er - el
        obj_updated.height = et - eb

        return obj_updated

    @property
    def rendered_views(self):
        """The list of actual rendered CropObjectViews that
        the CropObjectListView holds."""
        return [cv for cv in self.view.container.children[:]]

    @property
    def scaler(self):
        return App.get_running_app().image_scaler

    def _update_size(self, instance, size):
        self.size = size
        logging.debug('ObjectGraphRenderer: setting size to {0}'.format(
            self.size))

    def _update_pos(self, instance, pos):
        self.pos = pos
        logging.debug('ObjectGraphRenderer: setting pos to {0}'.format(
            self.pos))

    def mask_all(self, label=None):
        if label is None:
            new_mask = {e: False for e in self.graph.edges}
        else:
            new_mask = {}
            for e, l in list(self.graph.edges.items()):
                if l == label:
                    new_mask[e] = False
                else:
                    new_mask[e] = self.views_mask[e]

        self.views_mask = new_mask
        self.update_edge_adapter_data(instance=None, edges=self.graph.edges)

    def mask(self, edges):
        """Only acts on the given set of edges, doesn't change masking
        for others."""
        new_mask = {e: self.views_mask[e] for e in self.graph.edges}
        for e in edges:
            new_mask[e] = False
        self.views_mask = new_mask
        self.update_edge_adapter_data(instance=None, edges=self.graph.edges)

    def unmask_all(self, label=None):
        if label is None:
            new_mask = {e: True for e in self.graph.edges}
        else:
            new_mask = {}
            for e, l in list(self.graph.edges.items()):
                if l == label:
                    new_mask[e] = True
                else:
                    new_mask[e] = self.views_mask[e]

        self.views_mask = new_mask
        self.update_edge_adapter_data(instance=None, edges=self.graph.edges)

    def unmask(self, edges):
        """Only acts on the given set of edges, doesn't change masking
        for others."""
        new_mask = {e: self.views_mask[e] for e in self.graph.edges}
        for e in edges:
            new_mask[e] = True
        self.views_mask = new_mask
        self.update_edge_adapter_data(instance=None, edges=self.graph.edges)

    def are_all_masked(self, edges=None):
        if edges is None:
            edges = self.graph.edges

        masked = [
            e for e in edges
            if ((e in self.views_mask) and (self.views_mask[e] is False))
        ]
        logging.debug('GraphRenderer: {0} masked, {1} total in mask'
                      ''.format(len(masked), len(self.views_mask)))
        output = (len(masked) == len(edges))
        return output
Ejemplo n.º 19
0
class CropObjectRenderer(FloatLayout):
    """The CropObjectRenderer class is responsible for listening to
    the cropobject dict in the model and rendering it upon itself.
    Its place is attached as an overlay of the editor widget (the image)
    with the same size and position.

    In order to force rendering the annotations, add 1 to the
    ``rendnerer.redraw`` property, which fires redrawing.
    """
    # Maybe the ObjectGraphRenderer could be folded into this?
    # To work above the selectable_cropobjects?

    selectable_cropobjects = DictProperty()

    adapter = ObjectProperty()
    view = ObjectProperty()
    editor_widget = ObjectProperty()

    cropobject_keys = ListProperty()
    cropobject_keys_mask = DictProperty(None)

    mlclasses_colors = DictProperty()

    # The following properties are used to correctly resize
    # the intermediate CropObject structures.
    model_image_height = NumericProperty()
    model_image_width = NumericProperty()

    height_ratio_in = NumericProperty(1)
    old_height_ratio_in = NumericProperty(1)
    width_ratio_in = NumericProperty(1)
    old_width_ratio_in = NumericProperty(1)

    redraw = NumericProperty(0)
    '''Signals that the CropObjects need to be redrawn.'''
    def __init__(self, annot_model, editor_widget, **kwargs):
        super(CropObjectRenderer, self).__init__(**kwargs)

        # Bindings for model changes.
        # These bindings are what causes changes in the model to propagate
        # to the view. However, the DictProperty in the model does not
        # signal changes to the dicts it contains, only insert/delete states.
        # This implies that e.g. moving a CropObject does not trigger the
        # self.update_cropobject_data() binding.
        annot_model.bind(cropobjects=self.update_cropobject_data)

        # This is just a misc operation, to keep the renderer
        # in a valid state when the user loads a different MLClassList.
        annot_model.bind(mlclasses=self.recompute_mlclasses_color_dict)

        # Bindings for view changes
        editor_widget.bind(height=self.editor_height_changed)
        editor_widget.bind(width=self.editor_width_changed)

        self.size = editor_widget.size
        self.pos = editor_widget.pos

        # The self.selectable_cropobjects level of indirection only
        # handles numpy to kivy world conversion. This can be handled
        # in the adapter conversion method, maybe?
        self.adapter = DictAdapter(
            data=self.selectable_cropobjects,
            args_converter=self.selectable_cropobject_converter,
            selection_mode='multiple',
            cls=CropObjectView,
        )

        self.view = CropObjectListView(
            adapter=self.adapter,
            size_hint=(None, None),
            size=self.size,  #(self.size[0] / 2, self.size[1] / 2),
            pos=self.pos)
        self.adapter.bind(on_selection_change=self.view.broadcast_selection)

        # Keyboard event trapping implemented there.
        Window.bind(on_key_down=self.view.on_key_down)
        Window.bind(on_key_up=self.view.on_key_up)

        self.model_image_height = annot_model.image.shape[0]
        self.height_ratio_in = float(
            editor_widget.height) / annot_model.image.shape[0]
        self.model_image_width = annot_model.image.shape[1]
        self.width_ratio_in = float(
            editor_widget.width) / annot_model.image.shape[1]

        annot_model.bind(image=self.update_image_size)

        # self.view = ListView(item_strings=map(str, range(100)))
        self.add_widget(self.view)
        # The Renderer gets added to the editor externally, though, during
        # app build. That enables us to add or remove the renderer from
        # the active widget tree.

        self.redraw += 1
        logging.info('Render: Initialized CropObjectRenderer, with size {0}'
                     ' and position {1}, ratios {2}. Total keys: {3}'
                     ''.format(self.size, self.pos,
                               (self.height_ratio_in, self.width_ratio_in),
                               len(self.cropobject_keys)))

    def on_redraw(self, instance, pos):
        """This signals that the CropObjects need to be re-drawn. For example,
        adding a CropObject necessitates this, or resizing the window."""
        self.view.adapter.cached_views = dict()
        if self.cropobject_keys_mask is None:
            self.view.adapter.data = self.selectable_cropobjects
        else:
            self.view.adapter.data = {
                objid: c
                for objid, c in self.selectable_cropobjects.iteritems()
                if self.cropobject_keys_mask[objid]
            }
            logging.info(
                'Render: After masking: {0} of {1} cropobjects remaining.'
                ''.format(len(self.view.adapter.data),
                          len(self.selectable_cropobjects)))

        # self.view.slow_populate()
        self.view.populate()
        logging.info('Render: Redrawn {0} times'.format(self.redraw))

    def update_image_size(self, instance, pos):
        prev_editor_height = self.height_ratio_in * self.model_image_height
        self.model_image_height = pos.shape[0]
        self.height_ratio_in = prev_editor_height / self.model_image_height

        prev_editor_width = self.width_ratio_in * self.model_image_width
        self.model_image_width = pos.shape[1]
        self.width_ratio_in = prev_editor_width / self.model_image_width

    def on_height_ratio_in(self, instance, pos):
        _n_items_changed = 0
        if self.height_ratio_in == 0:
            return
        for objid, c in self.selectable_cropobjects.iteritems():
            orig_c = copy.deepcopy(c)
            c.height *= self.height_ratio_in / self.old_height_ratio_in
            c.x *= self.height_ratio_in / self.old_height_ratio_in
            self.selectable_cropobjects[objid] = c
            if _n_items_changed < 0:
                logging.info(
                    'Render: resizing\n{0}\nto\n{1}'
                    ''.format(
                        ' | '.join(
                            str(orig_c).replace('\t', '').split('\n')[1:-1]),
                        ' | '.join(str(c).replace('\t',
                                                  '').split('\n')[1:-1])))
            _n_items_changed += 1
        logging.info(
            'Render: Redraw from on_height_ratio_in: ratio {0}, changed {1} items'
            ''.format(self.height_ratio_in / self.old_height_ratio_in,
                      _n_items_changed))
        self.old_height_ratio_in = self.height_ratio_in
        self.redraw += 1

    def on_width_ratio_in(self, instance, pos):
        _n_items_changed = 0
        if self.width_ratio_in == 0:
            return
        for objid, c in self.selectable_cropobjects.iteritems():
            orig_c = copy.deepcopy(c)
            c.width *= self.width_ratio_in / self.old_width_ratio_in
            c.y *= self.width_ratio_in / self.old_width_ratio_in
            self.selectable_cropobjects[objid] = c
            if _n_items_changed < 0:
                logging.info(
                    'Render: resizing\n{0}\nto\n{1}'
                    ''.format(
                        ' | '.join(
                            str(orig_c).replace('\t', '').split('\n')[1:-1]),
                        ' | '.join(str(c).replace('\t',
                                                  '').split('\n')[1:-1])))
            _n_items_changed += 1
        logging.info(
            'Render: Redraw from on_width_ratio_in: ratio {0}, changed {1} items'
            ''.format(self.width_ratio_in / self.old_width_ratio_in,
                      _n_items_changed))
        self.old_width_ratio_in = self.width_ratio_in
        self.redraw += 1

    def editor_height_changed(self, instance, pos):
        logging.info('Render: Editor height changed to {0}'.format(pos))
        self.height_ratio_in = float(pos) / self.model_image_height

    def editor_width_changed(self, instance, pos):
        logging.info('Render: Editor width changed to {0}'.format(pos))
        self.width_ratio_in = float(pos) / self.model_image_width

    def update_cropobject_data(self, instance, pos):
        """Fired on change in the current CropObject list: make sure
        the data structures underlying the CropObjectViews are in sync
        with the model.

        This is where the positioning magic happens. Once we fit
        the original CropObject to the widget, we're done.

        However, in the future, we need to re-do the positioning magic
        on CropObjectList import. Let's do it here now for testing
        the concepts...
        """
        # Placeholder operation: just copy this for now.
        logging.info('Render: Updating CropObject data, {0} cropobjects'
                     ' and {1} currently selectable.'
                     ''.format(len(pos), len(self.selectable_cropobjects)))

        # Clear current cropobjects. Since ``pos`` is the entire
        # CropObject dictionary from the model and the CropObjects
        # will all be re-drawn anyway, we want selectable_cropobjects
        # to match it exactly.
        self.selectable_cropobjects = {}

        for objid in pos:

            corrected_position_cropobject = copy.deepcopy(pos[objid])
            # X is vertical, Y is horizontal.
            # X is the upper left corner relative to the image. We need the
            # bottom left corner to be X. We first need to get the top-down
            # coordinate for the bottom corner (x + height), then flip it
            # around relative to the current editor height
            # (self.model_image_height - ...) then scale it down
            # (* self.height_ratio_in).
            corrected_position_cropobject.x = (self.model_image_height -
                                               (pos[objid].x + pos[objid].height)) *\
                                              self.height_ratio_in
            corrected_position_cropobject.y = pos[objid].y * self.width_ratio_in
            corrected_position_cropobject.height = corrected_position_cropobject.height *\
                                                   self.height_ratio_in
            corrected_position_cropobject.width = corrected_position_cropobject.width *\
                                                  self.width_ratio_in

            self.selectable_cropobjects[objid] = corrected_position_cropobject
            # Inversion!
            # self.selectable_cropobjects[objid].y = self.height - pos[objid].y
            self.cropobject_keys_mask[objid] = True

        self.cropobject_keys = map(str, self.selectable_cropobjects.keys())

        # The adapter data doesn't change automagically
        # when the DictProperty it was bound to changes.
        # Force redraw.
        logging.info('Render: Redrawing from update_cropobject_data')
        self.redraw += 1

    def model_coords_to_editor_coords(self, x, y, height, width):
        """Converts coordinates of a model CropObject into the corresponding
        CropObjectView coordinates."""
        x_out = (self.model_image_height - (x + height)) * self.height_ratio_in
        y_out = y * self.width_ratio_in
        height_out = height * self.height_ratio_in
        width_out = width * self.width_ratio_in
        return x_out, y_out, height_out, width_out

    def recompute_mlclasses_color_dict(self, instance, pos):
        """On MLClassList change, the color dictionary needs to be updated."""
        logging.info('Render: Recomputing mlclasses color dict...')
        for clsid in pos:
            self.mlclasses_colors[clsid] = pos[clsid].color

    def selectable_cropobject_converter(self, row_index, rec):
        """Interfacing the CropObjectView and the intermediate data structure.
        Note that as it currently stands, this intermediate structure is
        also a CropObject, although the position params X and Y have been
        switched around."""
        if max(self.mlclasses_colors[rec.clsid]) > 1.0:
            rgb = tuple(
                [float(x) / 255.0 for x in self.mlclasses_colors[rec.clsid]])
        else:
            rgb = tuple([float(x) for x in self.mlclasses_colors[rec.clsid]])
        output = {
            #'text': str(rec.objid),
            #'size_hint': (None, None),
            'is_selected': False,
            'selectable_cropobject': rec,
            'rgb': rgb,
        }
        logging.debug(
            'Render: Converter fired, input object {0}/{1}, with output:\n{2}'
            ''.format(row_index, rec, output))
        return output

    def clear(self, instance, pos):
        logging.info('Render: clear() called with instance {0}, pos {1}'
                     ''.format(instance, pos))
        self.selectable_cropobjects = {}
        self.cropobject_keys = []
        self.cropobject_keys_mask = {}

        self.redraw += 1

    def mask_all(self):
        logging.info('Render: mask() called')
        self.view.unselect_all()  # ...but they disappear anyway?
        self.cropobject_keys_mask = {
            objid: False
            for objid in self.selectable_cropobjects
        }
        self.redraw += 1

    def unmask_all(self):
        logging.info('Render: mask() called')
        self.cropobject_keys_mask = {
            objid: True
            for objid in self.selectable_cropobjects
        }
        self.redraw += 1

    def on_adapter(self, instance, pos):
        # logging.info('Render: Selectable cropobjects changed, populating view.')
        logging.info('Render: Something changed in the adapter!')
Ejemplo n.º 20
0
class PartnerUpdateView(GridLayout):

    partner_data = {'Child 1' : {'name' : 'Child 1',
                             'street' : None,
                             'street2' : None,
                             'type' : 'Unknown',
                             'zip' : None,
                             'city' : 'Some Village',
                             'phone' : '22 55 55 55'}}

    def __init__(self, **kwargs):
        kwargs['cols'] = 2
        super(PartnerUpdateView, self).__init__(**kwargs)


        self.list_item_args_converter = \
                lambda row_index, rec: {'text': rec['name'],
                                        'size_hint_y': None,
                                        'height': 25}

        self.dict_adapter = DictAdapter(sorted_keys=sorted(self.partner_data.keys()),
                                   data=self.partner_data,
                                   args_converter=self.list_item_args_converter,
                                   selection_mode='single',
                                   allow_empty_selection=False,
                                   cls=ListItemButton)

        self.master_list_view = ListView(adapter=self.dict_adapter,
                                    size_hint=(.3, 1.0))

        self.add_widget(self.master_list_view)

        self.popup = self.make_comm_popup()

        detail_container = AnchorLayout()
        detail_view = PartnerDetailView(self,
                fruit_name=self.dict_adapter.selection[0].text,
                size_hint=(.7, None))
        detail_container.add_widget(detail_view)

        self.dict_adapter.bind(on_selection_change=detail_view.partner_changed)

        communicate_button_layout = AnchorLayout(anchor_y = 'bottom', size_hint = (.7, None))
        communicate_button = Button(text = 'Communication', size_hint_y=None,height=25)
        communicate_button.bind(on_press = self.popup.open)
        communicate_button_layout.add_widget(communicate_button)
        self.add_widget(detail_container)
        self.add_widget(communicate_button_layout)

    def make_comm_popup(self):

        prms = {} # TODO add server parameters from DB
        cont = BoxLayout(orientation = 'vertical')
        cont.add_widget(CommunicateContent(self, prms))

        gl = GridLayout(cols=2)
        fetch_button = Button(text = 'Fetch data', size_hint_y=None, height=25)
        fetch_button.bind(on_press = self.fetch_data)
        send_button = Button(text = 'Send data', size_hint_y=None, height=25)
        send_button.bind(on_press = self.send_data)
        gl.add_widget(fetch_button)
        gl.add_widget(send_button)
        cont.add_widget(gl)


        return Popup(title = 'Communicate', content = cont, size_hint=(0.6, None), height=200)

    def fetch_data(self, instance):
        self.popup.dismiss()
        communicate.fetch_partners(self.server, self.user, self.password)
        self.partner_data = communicate.get_partners_from_db()
        print "DATA", self.dict_adapter.data.keys()
        for d in self.dict_adapter.data.items():
            print "HEI", d


        #self.partner_data = {'hei' : {'name': 'hei'}}
        self.dict_adapter.sorted_keys = sorted(self.partner_data.keys())
        #self.dict_adapter.data = [('hei', {'name' : 'hei'})]
        self.dict_adapter.data = self.partner_data

        #self.dict_adapter = DictAdapter(sorted_keys=sorted(partner_data.keys()),
        #                           data=partner_data,
        #                           args_converter=self.list_item_args_converter,
        #                           selection_mode='single',
        #                           allow_empty_selection=False,
        #                           cls=ListItemButton)
        #self.master_list_view = self.dict_adapter
        #self.dict_adapter.sorted_keys = sorted(partner_data.keys())
        #self.dict_adapter.data = partner_data

        #self.add_widget(self.master_list_view)


    def send_data(self, instance):
        self.popup.dismiss()
        communicate.send_partners(self.server, self.user, self.password)