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
    13252
    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

      I just wondered if there is some very nice strategy already documented to handle a TableView with sections. I can work it out many different ways, but maybe there is a more correct way. I searched the forum, did not see any example code. I also mean, when in editing mode , dragging from one section to another.
      As data items , I have a list of namedtuples. Includes section and index with my other data. I am thinking I will have to make a list of pointers for each section when I set the data.

      It's not I can't do it question. More, if there is an elegant way to do it.

      1 Reply Last reply Reply Quote 0
      • 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