Quickly application with ListStore as preference

Solution 1:

Disclaimer: I didn't know anything about quickly until I read your post, or about gui programming in general for that matter. Therefore I honestly have no business attempting to answer this question :)

That said, quickly is a neat project. I scanned the boilerplate source briefly and identified the following potential approaches for adding a ListStore backed list-style preference:

  1. 'Monkey-patch' get and set widget_methods onto a stock TreeView widget (w/ ListStore model) as defined in data/ui/Preferences$PROJECTNAME$Dialog.ui with glade.
  2. Implement set_widget_from_preference and set_preference in the project's subclass of PreferencesDialog (the subclass is Preferences$PROJECTNAME$Dialog), and do something different when key or widget is your ListStore backed TreeView widget.
  3. Write a custom subclass of gtk.TreeView with a matching custom widget for glade.

To test them out, I implemented all three of these ideas -- each worked as intended, and AFAICT, identically. In the end, the third (in particular) seemed the cleanest to me, and closer to conventions used throughout the boilerplate, despite initially expecting the opposite.


Here are the steps I followed for number three ...

Using glade via quickly design (quickly 11.10, btw), and loosely following this tutorial (part 2), add a ScrolledWindow widget to the Preferences$PROJECTNAME$Dialog.ui, drop a TreeView onto it, name the TreeView language_treeview. Create a new ListStore model for the TreeView when prompted, and name it language_liststore, etc ... eventually I ended up with something like this:

glade-properties

Next, add a glade catalog (data/ui/preferences_$PROJECTNAME$_treeview.xml) with the following contents:

<glade-catalog name="preferences_$PROJECTNAME$_treeview" domain="glade-3"
               depends="gtk+" version="1.0">
  <glade-widget-classes>
    <glade-widget-class title="$PROJECTNAME$ Preferences TreeView" name="Preferences$PROJECTNAME$TreeView"
                        generic-name="Preference$PROJECTNAME$TreeView" parent="GtkTreeView"
                        icon-name="widget-gtk-treeview"/>
  </glade-widget-classes>
</glade-catalog>

Then, edit Preferences$PROJECTNAME$Dialog.ui, adding ...

<!-- interface-requires preferences_$PROJECTNAME$_treeview 1.0 -->

... to the top, under the requires tag. And change the class attribute of language_treeview to Preferences$PROJECTNAME$TreeView, in preparation for a later step.

Finally, add the following element to widget_methods list in Preferences$PROJECTNAME$Dialog.py

'language_treeview': ['get_languages', 'set_languages', 'button-release-event']

And at the end of the same file (Preferences$PROJECTNAME$Dialog.py), add

import gtk

ALL_LANGUAGES = [
  'en', 'uk', 'de', 'fr', # ... much longer list
]

class Preferences$PROJECTNAME$TreeView(gtk.TreeView):
    __gtype_name__ = "Preferences$PROJECTNAME$TreeView"

    def __init__(self, *args):
        super(Preferences$PROJECTNAME$TreeView, self).__init__(*args)
        self.get_selection().set_mode(gtk.SELECTION_MULTIPLE)

    # loads the liststore with all languages, 
    # selecting/highlighting in the treeview those 
    # already retrieved from previously saved preferences
    def set_languages(self, preferred_languages):
        model = self.get_model()
        for row, lang in enumerate(ALL_LANGUAGES):
            model.append([lang])
            if lang in preferred_languages:
                self.get_selection().select_iter(model.get_iter(row))

    # collects only the selected languages in the treeview
    # to save in the preferences database
    def get_languages(self):
        model, rows = self.get_selection().get_selected_rows()
        result = [model.get_value(model.get_iter(row), 0) for row in rows]
        return result

If you're interested in seeing my attempts for one and two, I'm happy to oblige.

Edit: For the casual reader, replace any occurrence of $PROJECTNAME$ with the actual name of your quickly project (as specified in quickly create).

HTH!