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.


    [Share] Poor man's list dialog - Playing around

    Pythonista
    share list dialog
    3
    8
    5419
    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 was just playing around. Just thought I would share what I was doing. I was trying to basically make a checkmark list. I was trying to keep it simple and small. I might look a little on the large size, its mainly the comments, there is not much to it though.
      Basically its just me thinking out aloud. The dialogs package is great, but still is hard to override it's behaviour easily. I am using multiple inheritance, which some may say is bad form. I am not sure. But I put some notes above the class about what I was doing. It's not supposed to be a finished class. More like just a test before going further.
      Maybe useful for new Pythonista members new to the ui module. However, as i say, some may take exception to the use of the multiple inheritance.

      import ui
      '''
      poor mans list dialog... Just playing around. Wanted to see how the
      multiple inheritance would workout.  It seems to have worked ok!
      I was hoping to make it a bit smaller in code lines than it is,
      but the logic is the logic. Could probably shave off a few lines,
      but not that many I think.
      Besides playing around I was thinking of having a number of these
      classes just specfic to a single pupose like a checkmark list etc...
      But keeping them small and managable.
      
      The dialogs module is good. But it is a bit inflexible. Sometimes
      you have to fight hard to override some behaviour you may want/need
      
      Anyway, this is just a start or thinking out aloud.  I will make some mods,
      to handle sections and ui.TableViewCell's
      
      I also included the image in the dict but not doing anthing with it as yet.
      
      I think its still a good example if you are new to Pythonista to see
      how easily you can make your own list.  HOWEVER, not sure what the seasoned
      Python programmers here will think of me using multiple inheitance.
      What i have done maybe be considered bad form, I am not sure.
      I was trying to get a small footprint.  I couldn't see any reason why this
      should be bad.  The base classes and there params dont overlap.
      '''
      
      
      class CheckMarkTable(ui.View, ui.ListDataSource):
          def __init__(self, items=None, selection=None, *args, **kwargs):
              # call the base init methods explicitly. I know there is a way
              # to call with super and it works it out, but I have had problems
              # with that past. This seems more straight fwd to me.
              ui.View.__init__(self, *args, **kwargs)
              ui.ListDataSource.__init__(self, [])
              # setup up the ui.TableView, pointing data_source and delegate to self
              tbl = ui.TableView(frame=self.bounds, flex='WH')
              tbl.data_source = tbl.delegate = self
              self.action = self._action
      
              items = items or []
              self.items = [{'title': str(item), 'image': None, 'accessory_type': ''}
                            for item in items]
              self.selected = selection
              self.set_checkmark(selection)
      
              self.add_subview(tbl)
      
          def _action(self, sender):
              # called when a cell is tapped
              self.set_checkmark(sender.selected_row)
      
          def set_checkmark(self, row):
              if row is None:
                  return
      
              # if the same row is selected, toggle the value
              if self.selected == row:
                  if self.items[row]['accessory_type'] == 'checkmark':
                      self.items[row]['accessory_type'] = ''
                  else:
                      self.items[row]['accessory_type'] = 'checkmark'
              else:
                  # clear the previous selections and set the new selection
                  self.clear_selection()
                  self.items[row]['accessory_type'] = 'checkmark'
              self.selected = row
              self.reload()
      
          def get_selected_item(self):
              # get the data item of the selected row
              if self.selected is not None:
                  return self.items[self.selected]
      
          def clear_selection(self):
              # set all the item['accessory_type'] = ''
              for item in self.items:
                  item['accessory_type'] = ''
      
      
      if __name__ == '__main__':
          f = (0, 0, 320, 480)
          items = ['Red', 'Green', 'Blue', 'Black', 'Orange', 'Yellow']
          t = CheckMarkTable(frame=f, items=items, selection=None, name='List')
          t.present('sheet', animated=False)
          t.wait_modal()
          print(t.get_selected_item())
      
      1 Reply Last reply Reply Quote 0
      • Phuket2
        Phuket2 last edited by

        Back again :) I started to try to make a storage object for the table using shelve. Was a first try, my idea was to try to make the storage a more of a generic class, so you overwrite the read/write methods also the file creation.
        But I had a bit of a epiphany at least in my mind. I have always struggled with how to implement a persistent class into the class I want to persist certain attrs with. It may be clear for you guys, but I has always done my head in(the egg before the chicken thing
        ). I can do it, but It never seems elegant , feels wrong.
        So my epiphany was to create the storage file first and populate it, and pass the storage class to the class I want to persist attrs. Then use the storage file to populate the classes data. Look, this may be crap way to do things, but the workflow to me seems a lot more natural. Please if you have the time comment on this approach, good or bad/scathing does not matter, would love to hear thoughts on this approach.

        Anyway, I have a problem I cant seem to solve. It's to do with writing the contents of self.items back to the shelve file. The simple int self.selected works fine. But the list of dicts contained in self.Items generates at Type Error "can't pickle CheckMarkTable objects". The start of the call chain occurs in the CheckMarkTable method "will_close". I have add comments above the line saying what I have tried etc. I am sure its something simple, but now I feel like my head is going to explode. I just cant see the problem. Also I haven't done much with shelve and pickling. The trace back is listed below.
        To make things a little easier I created a repo here.

        So to Summarise

        1. I would love to hear any feedback on the idea of first creating and populating a storage class, and passing it to target class instead of data params.
        2. If anyone can see why I am getting the error when trying to write the self.items attr, I would be great full to get a solution.

        Note: I have just used shelve here as a starting point. I am hoping to make the storage class more generic so you can choose to write your own and just overwrite a few methods.

        Traceback (most recent call last):
        File "/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents/nested_dict/porrmansdialog2.py", line 138, in will_close
        self.storage.write('items', self.items)
        File "/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents/nested_dict/porrmansdialog2.py", line 50, in write
        db[k] = v
        File "/var/containers/Bundle/Application/F132DFB7-BD77-4096-ADA6-D8CA8F4468F2/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/shelve.py", line 125, in setitem
        p.dump(value)
        TypeError: can't pickle CheckMarkTable objects

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

          This post is deleted!
          1 Reply Last reply Reply Quote 0
          • mikael
            mikael last edited by

            Your self.items is actually a ui.ListDataSourceList, which probably refers back to the table class. Store list(self.items) instead?

            Phuket2 2 Replies Last reply Reply Quote 1
            • Phuket2
              Phuket2 @mikael last edited by

              @mikael , thanks. Will try. I actually didn't think of that, but in the back of my head I thought something like that was going on even though what you say escaped me,but now you point it out it makes sense. I thought when i did the copy.copy and copy.deepcopy would detach something like this (even though I didn't know what I was looking for). But I think I understand now why that would not have worked.
              Again thanks, I should be able to solve it now.

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

                @mikael , thanks. Your solution, it was 100% correct. Anyone interested, I updated the repo.
                I am going to play some more to see if can get this better. Maybe it's fools errand, but it keeps me out of trouble :)

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

                  Regarding your question on separating the storage class from the display class: separating the two concerns of display and storage is a traditional and sensible approach, leading to more modular and pluggable design, so I am all for it.

                  What I am less sure is your approach of hiding the shelf class behind an API that essentially duplicates the shelf API, just changing the names. If all you want is a key-value store, why not use the standard dict semantics that shelf offers? If you then need another storage class, you can provide an identical interface with dunder methods like __setitem__and __delitem__.

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

                    @mikael , thanks for your reply. The more I think about it, when I was a programmer, should never have coded in the workflow like I do here. I always got the data pretty well sorted out very early in the process. Even if I had to use something as crude as a csv file to get started (more often was resource files, c structs or a database or combination of these persistent storage types). Mind you this was not for web deployment, whilst there was a web, without dedicated isdn lines, you had no chance to transmit what we would have called large datasets at the time.
                    Of course the data storage building/processing was a totally different process development from your end user application.
                    So i think I will try and be more mindful of that in the future. In my little attempts here, i mix all this in together. In hind sight its no wonder I end up chasing my tail so much. In my opinion, I should be basically writing a presentation app that displays and manipulates my data. Not sure how others think about that. But I am going to do it anyway in the hope it will help me focus more.

                    Regards to how I used shelve, basically I didn't know what I was doing from a object design perspective. It was just to get something going. I really dont like the whole pickle thing. A few reasons, first I am ignorant about pickling, also version problems with pickling. I also dont like shelve uses 3 files, it drives me crazy. But I used it to get started because everyone could run the code.
                    I would have preferred to use TinyDB. But ultimately I would like to have a have a base strorage system that you can subclass. The subclass would inherit the ability to handle a key,value storage. But you could change/extend the underlying storage engine say from shelve to TinyDB with very little work. Hmmmm, well that's what I think I want, at least to start with. For locally run apps, It appears to mean you can do a lot with simple key,value storage systems.
                    Also keeps the complexity to data you are likely to be dealing with in a local Pythonista App.

                    So i will try a few different things. It's a good learning exercise, even if I do go down the wrong track for a while. I will also try to get my head around your comments about using the dunder methods, setitem & getitem. I used them a long time ago. But got myself in trouble with side effects that can occur if you are not using them properly. Maybe I am a bit better equipped today to use them in a more informed way, maybe not :).

                    Again, thanks for your feedback. I really appreciate it. Unfortunately for me to have a in person conversation with a Python programmer, its approx 2 hr travel into Bangkok for meetup's they have there. 2hr's is a very modest estimate, once in Bangkok, then have to get to the venue. Depending on traffic & time you could easily double that. Through the network of Thai's I know, I have come across a few that can program a little in Python, but the language barrier makes it very difficult to have very meaningful conversations. Oh well, thats my life history :). Sorry, just in the mood for typing.

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