def test___setitem___for_child(self): "A child can be set (changed) with __setitem__" source = TreeSource( data={ ('first', 111): None, ('second', 222): [], ('third', 333): [ ('third.one', 331), ('third.two', 332) ] }, accessors=['val1', 'val2'] ) self.assertEqual(len(source), 3) self.assertEqual(len(source[2]), 2) listener = Mock() source.add_listener(listener) # Re-assign the first root source[2][0] = ('third.one_new', -331) self.assertEqual(len(source), 3) self.assertEqual(source[2][0].val1, 'third.one_new') self.assertEqual(source[2][0].val2, -331) listener.change.assert_called_once_with(item=source[2][0])
def test_prepend_child(self): "A new child can be prepended" source = TreeSource(data={ ('first', 111): None, ('second', 222): [], ('third', 333): [('third.one', 331), ('third.two', 332)] }, accessors=['val1', 'val2']) self.assertEqual(len(source), 3) self.assertEqual(len(source[2]), 2) listener = Mock() source.add_listener(listener) # Insert the new element node = source.prepend(source[2], val1='new element', val2=999) self.assertEqual(len(source), 3) self.assertEqual(len(source[2]), 3) self.assertEqual(source[2][0], node) self.assertEqual(node.val1, 'new element') self.assertEqual(node.val2, 999) listener.insert.assert_called_once_with(parent=source[2], index=0, item=node)
def test_remove_root(self): "A root can be removed" source = TreeSource(data={ ('first', 111): None, ('second', 222): [], ('third', 333): [('third.one', 331), ('third.two', 332)] }, accessors=['val1', 'val2']) self.assertEqual(len(source), 3) self.assertEqual(len(source[2]), 2) listener = Mock() source.add_listener(listener) # Remove the root element node = source.remove(source[1]) self.assertEqual(len(source), 2) self.assertEqual(len(source[1]), 2) listener.remove.assert_called_once_with(item=node, index=1, parent=None)
def test_insert_root_kwargs(self): "A new root can be inserted using kwargs" source = TreeSource(data={ ('first', 111): None, ('second', 222): [], ('third', 333): [('third.one', 331), ('third.two', 332)] }, accessors=['val1', 'val2']) self.assertEqual(len(source), 3) listener = Mock() source.add_listener(listener) # Insert the new element node = source.insert(None, 1, val1='new element', val2=999) self.assertEqual(len(source), 4) self.assertEqual(source[1], node) self.assertEqual(node.val1, 'new element') self.assertEqual(node.val2, 999) listener.insert.assert_called_once_with(parent=None, index=1, item=node)
def test_insert_first_child(self): "If a node previously didn't allow children, inserting changes this" source = TreeSource(data={ ('first', 111): None, ('second', 222): [], ('third', 333): [('third.one', 331), ('third.two', 332)] }, accessors=['val1', 'val2']) self.assertEqual(len(source), 3) self.assertFalse(source[0].can_have_children()) self.assertEqual(len(source[0]), 0) listener = Mock() source.add_listener(listener) # Insert the new element node = source.insert(source[0], 0, val1='new element', val2=999) self.assertEqual(len(source), 3) self.assertTrue(source[0].can_have_children()) self.assertEqual(len(source[0]), 1) self.assertEqual(source[0][0], node) self.assertEqual(node.val1, 'new element') self.assertEqual(node.val2, 999) listener.insert.assert_called_once_with(parent=source[0], index=0, item=node)
def test_prepend_child(self): "A new child can be prepended" source = TreeSource( data={ ('first', 111): None, ('second', 222): [], ('third', 333): [ ('third.one', 331), ('third.two', 332) ] }, accessors=['val1', 'val2'] ) self.assertEqual(len(source), 3) self.assertEqual(len(source[2]), 2) listener = Mock() source.add_listener(listener) # Insert the new element node = source.prepend(source[2], val1='new element', val2=999) self.assertEqual(len(source), 3) self.assertEqual(len(source[2]), 3) self.assertEqual(source[2][0], node) self.assertEqual(node.val1, 'new element') self.assertEqual(node.val2, 999) listener.insert.assert_called_once_with(parent=source[2], index=0, item=node)
def test_init_with_list_of_tuples(self): "TreeSources can be instantiated from lists of tuples" source = TreeSource(data=[ ('first', 111), ('second', 222), ('third', 333), ], accessors=['val1', 'val2']) self.assertEqual(len(source), 3) self.assertEqual(source[0].val1, 'first') self.assertEqual(source[0].val2, 111) self.assertFalse(source[0].can_have_children()) self.assertEqual(len(source[0]), 0) self.assertEqual(source[1].val1, 'second') self.assertEqual(source[1].val2, 222) self.assertFalse(source[1].can_have_children()) self.assertEqual(len(source[1]), 0) listener = Mock() source.add_listener(listener) # Set element 1 source[1] = ('new element', 999) self.assertEqual(len(source), 3) self.assertEqual(source[1].val1, 'new element') self.assertEqual(source[1].val2, 999) self.assertFalse(source[1].can_have_children()) self.assertEqual(len(source[1]), 0) listener.change.assert_called_once_with(item=source[1])
def test_remove_child(self): "A child can be removed" source = TreeSource(data={ ('first', 111): None, ('second', 222): [], ('third', 333): [('third.one', 331), ('third.two', 332)] }, accessors=['val1', 'val2']) self.assertEqual(len(source), 3) self.assertEqual(len(source[2]), 2) listener = Mock() source.add_listener(listener) # Remove "third.two" node = source.remove(source[2][1]) self.assertEqual(len(source), 3) self.assertEqual(len(source[2]), 1) listener.remove.assert_called_once_with(item=node, index=1, parent=source[2]) # Remove "third.one" node = source.remove(source[2][0]) self.assertEqual(len(source), 3) self.assertEqual(len(source[2]), 0) listener.remove.assert_any_call(item=node, index=0, parent=source[2])
def test_remove_child(self): "A child can be removed" source = TreeSource( data={ ('first', 111): None, ('second', 222): [], ('third', 333): [ ('third.one', 331), ('third.two', 332) ] }, accessors=['val1', 'val2'] ) self.assertEqual(len(source), 3) self.assertEqual(len(source[2]), 2) listener = Mock() source.add_listener(listener) # Remove the child element node = source.remove(source[2][1]) self.assertEqual(len(source), 3) self.assertEqual(len(source[2]), 1) listener.remove.assert_called_once_with(item=node)
def test_insert_first_child(self): "If a node previously didn't allow children, inserting changes this" source = TreeSource( data={ ('first', 111): None, ('second', 222): [], ('third', 333): [ ('third.one', 331), ('third.two', 332) ] }, accessors=['val1', 'val2'] ) self.assertEqual(len(source), 3) self.assertFalse(source[0].can_have_children()) self.assertEqual(len(source[0]), 0) listener = Mock() source.add_listener(listener) # Insert the new element node = source.insert(source[0], 0, val1='new element', val2=999) self.assertEqual(len(source), 3) self.assertTrue(source[0].can_have_children()) self.assertEqual(len(source[0]), 1) self.assertEqual(source[0][0], node) self.assertEqual(node.val1, 'new element') self.assertEqual(node.val2, 999) listener.insert.assert_called_once_with(parent=source[0], index=0, item=node)
def test_insert_root_kwargs(self): "A new root can be inserted using kwargs" source = TreeSource( data={ ('first', 111): None, ('second', 222): [], ('third', 333): [ ('third.one', 331), ('third.two', 332) ] }, accessors=['val1', 'val2'] ) self.assertEqual(len(source), 3) listener = Mock() source.add_listener(listener) # Insert the new element node = source.insert(None, 1, val1='new element', val2=999) self.assertEqual(len(source), 4) self.assertEqual(source[1], node) self.assertEqual(node.val1, 'new element') self.assertEqual(node.val2, 999) listener.insert.assert_called_once_with(parent=None, index=1, item=node)
def test_init_with_dict_of_lists(self): "TreeSource nodes can be instantiated from dicts of lists" source = TreeSource( data={ ('first', 111): None, ('second', 222): [], ('third', 333): [ ('third.one', 331), {'val1': 'third.two', 'val2': 332} ] }, accessors=['val1', 'val2'] ) self.assertEqual(len(source), 3) self.assertEqual(source[0].val1, 'first') self.assertEqual(source[0].val2, 111) self.assertFalse(source[0].can_have_children()) self.assertEqual(len(source[0]), 0) self.assertEqual(source[1].val1, 'second') self.assertEqual(source[1].val2, 222) self.assertTrue(source[1].can_have_children()) self.assertEqual(len(source[1]), 0) self.assertEqual(source[2].val1, 'third') self.assertEqual(source[2].val2, 333) self.assertTrue(source[2].can_have_children()) self.assertEqual(len(source[2]), 2) self.assertEqual(source[2].val1, 'third') self.assertEqual(source[2].val2, 333) self.assertTrue(source[2].can_have_children()) self.assertEqual(len(source[2]), 2) self.assertEqual(source[2][0].val1, 'third.one') self.assertEqual(source[2][0].val2, 331) self.assertFalse(source[2][0].can_have_children()) self.assertEqual(len(source[2][0]), 0) self.assertEqual(source[2][1].val1, 'third.two') self.assertEqual(source[2][1].val2, 332) self.assertFalse(source[2][1].can_have_children()) self.assertEqual(len(source[2][1]), 0) listener = Mock() source.add_listener(listener) # Set element 2 source[2] = {'val1': 'new element', 'val2': 999} self.assertEqual(len(source), 3) self.assertEqual(source[2].val1, 'new element') self.assertEqual(source[2].val2, 999) listener.change.assert_called_once_with(item=source[2])
def test_init_with_dict_of_lists(self): "TreeSource nodes can be instantiated from dicts of lists" source = TreeSource(data={ ('first', 111): None, ('second', 222): [], ('third', 333): [('third.one', 331), { 'val1': 'third.two', 'val2': 332 }] }, accessors=['val1', 'val2']) self.assertEqual(len(source), 3) self.assertEqual(source[0].val1, 'first') self.assertEqual(source[0].val2, 111) self.assertFalse(source[0].can_have_children()) self.assertEqual(len(source[0]), 0) self.assertEqual(source[1].val1, 'second') self.assertEqual(source[1].val2, 222) self.assertTrue(source[1].can_have_children()) self.assertEqual(len(source[1]), 0) self.assertEqual(source[2].val1, 'third') self.assertEqual(source[2].val2, 333) self.assertTrue(source[2].can_have_children()) self.assertEqual(len(source[2]), 2) self.assertEqual(source[2].val1, 'third') self.assertEqual(source[2].val2, 333) self.assertTrue(source[2].can_have_children()) self.assertEqual(len(source[2]), 2) self.assertEqual(source[2][0].val1, 'third.one') self.assertEqual(source[2][0].val2, 331) self.assertFalse(source[2][0].can_have_children()) self.assertEqual(len(source[2][0]), 0) self.assertEqual(source[2][1].val1, 'third.two') self.assertEqual(source[2][1].val2, 332) self.assertFalse(source[2][1].can_have_children()) self.assertEqual(len(source[2][1]), 0) listener = Mock() source.add_listener(listener) # Set element 2 source[2] = {'val1': 'new element', 'val2': 999} self.assertEqual(len(source), 3) self.assertEqual(source[2].val1, 'new element') self.assertEqual(source[2].val2, 999) listener.change.assert_called_once_with(item=source[2])
def test_init_with_list_of_dicts(self): "TreeSource nodes can be instantiated from lists of dicts" source = TreeSource(data=[ { 'val1': 'first', 'val2': 111 }, { 'val1': 'second', 'val2': 222 }, { 'val1': 'third', 'val2': 333 }, ], accessors=['val1', 'val2']) self.assertEqual(len(source), 3) self.assertEqual(source[0].val1, 'first') self.assertEqual(source[0].val2, 111) self.assertFalse(source[0].can_have_children()) self.assertEqual(len(source[0]), 0) self.assertEqual(source[1].val1, 'second') self.assertEqual(source[1].val2, 222) self.assertFalse(source[1].can_have_children()) self.assertEqual(len(source[1]), 0) listener = Mock() source.add_listener(listener) # Set element 1 source[1] = {'val1': 'new element', 'val2': 999} self.assertEqual(len(source), 3) self.assertEqual(source[1].val1, 'new element') self.assertEqual(source[1].val2, 999) self.assertFalse(source[1].can_have_children()) self.assertEqual(len(source[1]), 0) listener.change.assert_called_once_with(item=source[1])
def test_init_with_list_of_dicts(self): "TreeSource nodes can be instantiated from lists of dicts" source = TreeSource( data=[ {'val1': 'first', 'val2': 111}, {'val1': 'second', 'val2': 222}, {'val1': 'third', 'val2': 333}, ], accessors=['val1', 'val2'] ) self.assertEqual(len(source), 3) self.assertEqual(source[0].val1, 'first') self.assertEqual(source[0].val2, 111) self.assertFalse(source[0].can_have_children()) self.assertEqual(len(source[0]), 0) self.assertEqual(source[1].val1, 'second') self.assertEqual(source[1].val2, 222) self.assertFalse(source[1].can_have_children()) self.assertEqual(len(source[1]), 0) listener = Mock() source.add_listener(listener) # Set element 1 source[1] = {'val1': 'new element', 'val2': 999} self.assertEqual(len(source), 3) self.assertEqual(source[1].val1, 'new element') self.assertEqual(source[1].val2, 999) self.assertFalse(source[1].can_have_children()) self.assertEqual(len(source[1]), 0) listener.change.assert_called_once_with(item=source[1])
def test_init_with_list_of_tuples(self): "TreeSources can be instantiated from lists of tuples" source = TreeSource( data=[ ('first', 111), ('second', 222), ('third', 333), ], accessors=['val1', 'val2'] ) self.assertEqual(len(source), 3) self.assertEqual(source[0].val1, 'first') self.assertEqual(source[0].val2, 111) self.assertFalse(source[0].can_have_children()) self.assertEqual(len(source[0]), 0) self.assertEqual(source[1].val1, 'second') self.assertEqual(source[1].val2, 222) self.assertFalse(source[1].can_have_children()) self.assertEqual(len(source[1]), 0) listener = Mock() source.add_listener(listener) # Set element 1 source[1] = ('new element', 999) self.assertEqual(len(source), 3) self.assertEqual(source[1].val1, 'new element') self.assertEqual(source[1].val2, 999) self.assertFalse(source[1].can_have_children()) self.assertEqual(len(source[1]), 0) listener.change.assert_called_once_with(item=source[1])
def test___setitem___for_child(self): "A child can be set (changed) with __setitem__" source = TreeSource(data={ ('first', 111): None, ('second', 222): [], ('third', 333): [('third.one', 331), ('third.two', 332)] }, accessors=['val1', 'val2']) self.assertEqual(len(source), 3) self.assertEqual(len(source[2]), 2) listener = Mock() source.add_listener(listener) # Re-assign the first root source[2][0] = ('third.one_new', -331) self.assertEqual(len(source), 3) self.assertEqual(source[2][0].val1, 'third.one_new') self.assertEqual(source[2][0].val2, -331) listener.change.assert_called_once_with(item=source[2][0])
class Tree(Widget): """ Tree Widget Args: headings (``list`` of ``str``): The list of headings for the interface. id (str): An identifier for this widget. style (:obj:`Style`): An optional style object. If no style is provided then a new one will be created for the widget. factory (:obj:`module`): A python module that is capable to return a implementation of this class with the same name. (optional & normally not needed) """ MIN_WIDTH = 100 MIN_HEIGHT = 100 def __init__(self, headings, id=None, style=None, data=None, accessors=None, multiple_select=False, on_select=None, factory=None): super().__init__(id=id, style=style, factory=factory) self.headings = headings self._accessors = build_accessors(headings, accessors) self._multiple_select = multiple_select self._selection = None self._data = None self._on_select = None self._impl = self.factory.Tree(interface=self) self.data = data self.on_select = on_select @property def data(self): ''' :returns: The data source of the tree :rtype: ``dict`` ''' return self._data @data.setter def data(self, data): ''' Set the data source of the data :param data: Data source :type data: ``dict`` or ``class`` ''' if data is None: self._data = TreeSource(accessors=self._accessors, data=[]) elif isinstance(data, (list, tuple, dict)): self._data = TreeSource(accessors=self._accessors, data=data) else: self._data = data self._data.add_listener(self._impl) self._impl.change_source(source=self._data) @property def multiple_select(self): """Does the table allow multiple rows to be selected?""" return self._multiple_select @property def selection(self): """The current selection of the table. A value of None indicates no selection. If the table allows multiple selection, returns a list of selected data nodes. Otherwise, returns a single data node. """ return self._selection @property def on_select(self): """ The callable function for when a node on the Tree is selected :rtype: ``callable`` """ return self._on_select @on_select.setter def on_select(self, handler): """ Set the function to be executed on node select :param handler: callback function :type handler: ``callable`` """ self._on_select = wrapped_handler(self, handler) self._impl.set_on_select(self._on_select)
class Tree(Widget): """ Tree Widget Args: headings (``list`` of ``str``): The list of headings for the interface. id (str): An identifier for this widget. style (:obj:`Style`): An optional style object. If no style is provided then a new one will be created for the widget. Kwargs: data: The data to display in the widget. Can be an instance of :class:`toga.sources.TreeSource`, a list, dict or tuple with data to display in the tree widget, or a class instance which implements the interface of :class:`toga.sources.TreeSource`. Entries can be given as follows: - Any Python object ``value`` with a string represntation. This string will be shown in the widget. If ``value`` has an attribute ``icon``, instance of (:class:`toga.Icon`), the icon will be shown in front of the text. - A tuple ``(icon, value)`` where again the string represnation of ``value`` will be used as text. accessors (``list`` of ``str``): Optional: a list of attributes to access the value in the columns. If not given, the headings will be taken. multiple_select (``bool``): If ``True``, allows for the selection of multiple rows. Defaults to ``False``. on_select: A function to be called when the user selects one or multiple rows. factory (:obj:`module`): A python module that is capable to return a implementation of this class with the same name. (optional & normally not needed) """ MIN_WIDTH = 100 MIN_HEIGHT = 100 def __init__(self, headings, id=None, style=None, data=None, accessors=None, multiple_select=False, on_select=None, factory=None): super().__init__(id=id, style=style, factory=factory) self.headings = headings self._accessors = build_accessors(headings, accessors) self._multiple_select = multiple_select self._selection = None self._data = None self._on_select = None self._impl = self.factory.Tree(interface=self) self.data = data self.on_select = on_select @property def data(self): ''' :returns: The data source of the tree :rtype: ``dict`` ''' return self._data @data.setter def data(self, data): ''' Set the data source of the data :param data: Data source :type data: ``dict`` or ``class`` ''' if data is None: self._data = TreeSource(accessors=self._accessors, data=[]) elif isinstance(data, (list, tuple, dict)): self._data = TreeSource(accessors=self._accessors, data=data) else: self._data = data self._data.add_listener(self._impl) self._impl.change_source(source=self._data) @property def multiple_select(self): """Does the table allow multiple rows to be selected?""" return self._multiple_select @property def selection(self): """The current selection of the table. A value of None indicates no selection. If the table allows multiple selection, returns a list of selected data nodes. Otherwise, returns a single data node. """ return self._selection @property def on_select(self): """ The callable function for when a node on the Tree is selected :rtype: ``callable`` """ return self._on_select @on_select.setter def on_select(self, handler): """ Set the function to be executed on node select :param handler: callback function :type handler: ``callable`` """ self._on_select = wrapped_handler(self, handler) self._impl.set_on_select(self._on_select)