Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Subclassing ui.ListDataSource dealing with events
-
The below code should be so simple. But it's been sometime since I have done it. I feel I am am right in what I have done, but history tells me, I am normally wrong. The docs say you can set a ui.ListDataSource item as the delegate to a TableView. Which is what I have done. But I am not getting called back. Ok, I have subclassed ui.ListDataSource, but from what I can see it should work. @omz sorry to ask, but am I just doing something stupid or is it broken?
Edit: had to edit, otherwise I would be having coding nightmares of @ccc tracking me down in Pokemon and capturing me 😱😱
import ui, editor ''' Pythonista Forum - @Phuket2 ''' def dataset(nb=12, acc_type = 'detail_button'): # stupid helper test func. # make a list of dicts for ui.ListDataSource # no list[dict] comprehension. This is clearer for this purpose lst = [] for i in range(1, nb+1): d = dict(title = str(i), image= 'None', accessory_type = acc_type) lst.append(d) return lst class MyData(ui.ListDataSource): def __init__(self, items = None, *args, **kwargs): items = items or [] # edited super().__init__(items, *args, **kwargs) self.items = dataset() # as far as i can tell, given this is the delegate if should be, # called. But its not called when a different row is selected. # the same with other callbacks. def action(self, sender): print('in action') def accessory_action(self, sender): print('in accessory_action') class MyClass(ui.View): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.tbl = None self.make_view() def make_view(self): self.tbl = ui.TableView(name = 'table', frame = self.bounds) self.tbl.flex = 'wh' ds = MyData() self.tbl.data_source = ds self.tbl.delegate = ds self.add_subview(self.tbl) if __name__ == '__main__': _use_theme = True w, h = 300, 400 f = (0, 0, w, h) mc = MyClass(frame=f, bg_color='white', name ='I am Broken 😱') if not _use_theme: mc.present('sheet', animated=False) else: editor.present_themed(mc, theme_name='Oceanic', style='sheet', animated=False)
-
My "pull request"...
import editor, ui ''' Pythonista Forum - @Phuket2, @ccc ''' def dataset(nb=12, acc_type='detail_button'): return [{'title': str(i+1), 'accessory_type': acc_type} for i in range(nb)] class MyData(ui.ListDataSource): def __init__(self, items=None, *args, **kwargs): super().__init__(items or [], *args, **kwargs) self.items = dataset() self.action = self._action self.accessory_action = self._accessory_action def _action(self, sender): assert self is sender, 'Just a curious fact.' item = sender.items[sender.selected_row] print('in action {title}'.format(**item)) def _accessory_action(self, sender): assert self is sender, 'Just a curious fact.' item = sender.items[sender.tapped_accessory_row] print('in accessory_action {title}'.format(**item)) class MyClass(ui.View): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.add_subview(self.make_table()) def make_table(self): table = ui.TableView(name='table', frame=self.bounds) table.flex = 'wh' table.data_source = table.delegate = MyData() return table if __name__ == '__main__': _use_theme = True frame = (0, 0, 300, 400) mc = MyClass(frame=frame, bg_color='white', name='I am NOT Broken 😱') if _use_theme: editor.present_themed(mc, theme_name='Oceanic', style='sheet', animated=False) else: mc.present('sheet', animated=False)
-
@Phuket2 ideally your code should have worked. I think that it is a bug in pythonista. The attribute "action" seems to be initialized like
thisself.action = None
instead of
self.action = self.action if hasattr(self, 'action') else None
-
Thanks guys for the workaround and the explanation. I will add a bug report.