omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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

    Pythonista
    listdatasource
    3
    4
    4368
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Phuket2
      Phuket2 last edited by Phuket2

      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)
      
      1 Reply Last reply Reply Quote 0
      • ccc
        ccc last edited by ccc

        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)
        
        1 Reply Last reply Reply Quote 1
        • abcabc
          abcabc last edited by

          @Phuket2 ideally your code should have worked. I think that it is a bug in pythonista. The attribute "action" seems to be initialized like
          this

                  self.action = None
          

          instead of

                self.action = self.action if hasattr(self, 'action') else None
          
          1 Reply Last reply Reply Quote 1
          • Phuket2
            Phuket2 last edited by

            Thanks guys for the workaround and the explanation. I will add a bug report.

            1 Reply Last reply Reply Quote 0
            • First post
              Last post
            Powered by NodeBB Forums | Contributors