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.


    Strategy for TableViews with sections

    Pythonista
    1.6 section tableview
    4
    13
    13258
    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.
    • smath
      smath last edited by ccc

      I'm working on this right now. My understanding is that the trick is making the right data source class as ListDataSource isn't made for multi section data. There is an example in the docs for this that I'm trying to work with, but for some reason my code is not working. I've been able to make a hard coded list that has multiple sections, but I'm trying to make a class to which I can feed a dictionary of the type shown in the code below and have it populate a tableview. Any ideas?

      # coding: utf-8
      
      import ui
      
      class MyTableViewDataSource (object):
          def tableview_number_of_sections(self, tableview):
              # Return the number of sections (defaults to 1)
              return 0
      
          def tableview_number_of_rows(self, tableview, section):
              # Return the number of rows in the section
              #print section
              return 0
      
          def tableview_cell_for_row(self, tableview, section, row):
              # Create and return a cell for the given section/row
              cell = ui.TableViewCell()
              print 'cell name: ', row
              cell.text_label.text = row
              return cell
      
          def tableview_title_for_header(self, tableview, section):
              # Return a title for the given section.
              # If this is not implemented, no section headers will be shown.
              print 'section: ', section
              return section
      
          def tableview_can_delete(self, tableview, section, row):
              # Return True if the user should be able to delete the given row.
              return False
      
          def tableview_can_move(self, tableview, section, row):
              # Return True if a reordering control should be shown for the given row (in editing mode).
              return False
              
          def fill_data(self, tableview, data):
              for section in data:
                  self.tableview_title_for_header(tableview, section)
                  for row in data[section]:
                      self.tableview_cell_for_row(tableview, section, row)
      
      
      multi_section = ui.TableView()
      multi_section.width = 400
      multi_section.height = 400
      
      list = {'Header1': ['element1', 'element2', 'element3'], 'Header2': ['element3', 'element4', 'element5'], 'Header3': ['element6', 'element7', 'element8'], 'Header4': ['element9', 'element10']}
      
      data = MyTableViewDataSource()
      
      multi_section.data_source = data
      data.fill_data(multi_section, list)
      
      multi_section.present('sheet')
      
      1 Reply Last reply Reply Quote 0
      • JonB
        JonB last edited by JonB

        Instead of calling the tableview delegate methods yourself, your class needs to use tableview.data to properly fill out those methods when called by the system. For instance

        def tableview_number_of_sections(self,tableview):
           return len(tableview.data.keys())
        def tableview_title_for_header(self,tableview,section):
           return tableview.data.keys()[section]
        def tableview_number_of_rows(self,tableview,section):
           key = tableview.data.keys()[section]
           return len(tableview.data[key])
        

        and so on. the system will call these methods for you, and set up your tableview based on what is returned. Look at the source for ListDataSource in ui.py for more info.

        I vaguely recall that section and row might be one based rather than zero based, so you kight need to use section-1 in the code above for indexing. I don't have the app open right now to check, but it should be easy to add a print to see.

        1 Reply Last reply Reply Quote 1
        • smath
          smath last edited by ccc

          @JonB, Thanks for the help. I admit I still don't totally understand how this is works. I haven't been able to find the source code for the ui module. Below is my working code. As with most of my code, I'm sure there's many ways to improve it. I had to change to using an OrderedDict so the order of elements would be preserved.

          import ui
          from collections import OrderedDict
          
          class MyTableViewDataSource (object):
              def tableview_number_of_sections(self,tableview):
                  return len(self.data.keys())
                  
              def tableview_title_for_header(self,tableview,section):
                  return self.data.keys()[section]
                  
              def tableview_number_of_rows(self,tableview,section):
                  key = self.data.keys()[section]
                  return len(self.data[key])
                 
              def tableview_cell_for_row(self, tableview, section, row):
                  # Create and return a cell for the given section/row
                  key = self.data.keys()[section]
                  cell = ui.TableViewCell()
                  cell.text_label.text = self.data[key][row]
                  return cell
                  
              def fill_data(self, tableview, data):
                  self.data = data
                  
          multi_section = ui.TableView()
          multi_section.width = 400
          multi_section.height = 400
          
          table = OrderedDict([('Header1', ['element1', 'element2', 'element3']),
                               ('Header2', ['element3', 'element4', 'element5']),
                               ('Header3', ['element6', 'element7', 'element8']),
                               ('Header4', ['element9', 'element10'])])
          
          data = MyTableViewDataSource()
          
          multi_section.data_source = data
          data.fill_data(multi_section, table)
          
          multi_section.present('sheet')
          
          1 Reply Last reply Reply Quote 0
          • JonB
            JonB last edited by

            You can enable Standard Library view in settings, then if you go to Standard Library-> site-packages, the pythonista module sources are there (see ui.py)

            1 Reply Last reply Reply Quote 0
            • ccc
              ccc last edited by ccc

              @smath list is probably not the best variable name for your ordered dict... The code above overrides the definition of a builtin type.

              print(list((0, 1, 2)))  # works
              list = 'a b c'.split()
              print(list((0, 1, 2)))  # throws an exception
              
              1 Reply Last reply Reply Quote 0
              • smath
                smath last edited by

                @JonB Just have to know where to look. II guess I haven't poked around the new version yet.

                @ccc Good point. Fixed.

                1 Reply Last reply Reply Quote 0
                • Phuket2
                  Phuket2 last edited by

                  This simple thing still drives me crazy. I am sure it's just me and my lack of experience. But as it turns out, I have been looking at this again the last few days. Then I seen this old question I asked before started getting some feedback.
                  Actually the feedback is very nice.
                  But unrelated to this threat, I was looking at iOS development , in Flipboard (which I never do). And I come across this article.
                  http://nshipster.com/uisplitviewcontroller/

                  uisplitviewcontroller, sounds super cool in name alone. After reading , seems like it would be perfect addition to the ui suite.

                  I really have no idea how deep objc_utils can go in creating native objects and incorporating them into Pythonista , but this would be a fantastic addition.
                  Whist, it seems that it should be so easy to create a split view of your own , it is. But then, you start to implement stuff, all of a sudden it can get complicated and ugly. Granted, skill helps a lot here. But I find I am always painting my self into a corner. But I do have a lack of skill.

                  Anyway, maybe some of you guys ofay with objc_utils could help add this as a customview. Just asking 😛😛😛

                  1 Reply Last reply Reply Quote 0
                  • JonB
                    JonB last edited by JonB

                    I spent a while implementing somethng very much like this for an improved version of gitview... essentially trying to emulate the little side panels that pop out in pythonista for the file view, etc, then you can swipe to dismiss. This was all in standard puthonista ui.

                    Sadly, I lost all of my in work work when switching to the new version, because I tried to get fancy (I thought I could just share the files to email, then just save a draft, and would be able to open it again.... but that didnt work unbeknownst to me, and i lost weeks of work when ai uninstalled).

                    Phuket2 1 Reply Last reply Reply Quote 0
                    • ccc
                      ccc last edited by ccc

                      A slightly different formulation that implements an __init__() method in place of fill_data() so you can multi_section.data_source = MyTableViewDataSource(data_dict) in a single line of code.

                      import ui
                      from collections import OrderedDict
                      
                      class MyTableViewDataSource (object):
                          def __init__(self, data_dict=None):
                              self.data = data_dict
                      
                          def section_key(self, section):
                              return self.data.keys()[section]
                              
                          def tableview_number_of_sections(self, tableview):
                              return len(self.data)
                              
                          def tableview_title_for_header(self, tableview, section):
                              return self.section_key(section)
                              
                          def tableview_number_of_rows(self, tableview, section):
                              return len(self.data[self.section_key(section)])
                             
                          def tableview_cell_for_row(self, tableview, section, row):
                              # Create and return a cell for the given section/row
                              cell = ui.TableViewCell()
                              cell.text_label.text = self.data[self.section_key(section)][row]
                              return cell
                              
                      multi_section = ui.TableView()
                      multi_section.width = multi_section.height = 400
                      
                      data_dict = OrderedDict((('Header1', ('element0', 'element1', 'element2')),
                                               ('Header2', ('element3', 'element4', 'element5')),
                                               ('Header3', ('element6', 'element7', 'element8')),
                                               ('Header4', ('element9', 'element10'))))
                      
                      multi_section.data_source = MyTableViewDataSource(data_dict)
                      multi_section.present('sheet')
                      
                      1 Reply Last reply Reply Quote 0
                      • Phuket2
                        Phuket2 @JonB last edited by

                        @JonB , that's a bummer. So many Real world ui"s are based around this simple master detail concept on iPhones and iPads. I mentioned before in another thread, I have really been over thinking the whole ui thing. Just need to get a solid master detail class in place, then a few tweaks from there, such as status bars etc.
                        but I was looking how to handle section data all wrong also. After seeing it in this thread, it appears more obvious. I think the TableView is one of those ui elements that deserve a lot more documentation.
                        But it's great to see the buzz around the version 2.0 release. It's got a lot of people's creative juices flowing

                        1 Reply Last reply Reply Quote 0
                        • Phuket2
                          Phuket2 last edited by

                          I looked up this example of using a OrderDict to easily provide section/data in a uiTableView. The version that @ccc does turns out to be forward thinking. This version does not work in py3.5, but because of the section_key method, only one change is required to get it to work in py3.5
                          Maybe there is a more efficient or effective way to do it. But one change will get it to work in 3.5.

                          def section_key(self, section):
                                  #return self.data.keys()[section] --> works in 2.7, not 3.5
                                  return list(self.data.keys())[section]
                          

                          Thought it was worth posting.

                          1 Reply Last reply Reply Quote 0
                          • Phuket2
                            Phuket2 last edited by

                            Ok here is a gist that just adds a class subclassed from OrderedDict to help assemble the OrderedDict. It also adds the section_key method. It's trivial, but I think helpful. Just building on @ccc idea. This one only works with py3

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