Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I'm starting to write a program with 'quickly'. A list of desired languages will be one prefereces. Example:

languages = ["en", "de"]

The (automaticly created) quickly code that handles the preference part looks like this:

# Define your preferences dictionary in the __init__.main() function.
# The widget names in the PreferencesTestProjectDialog.ui
# file need to correspond to the keys in the preferences dictionary.
#
# Each preference also need to be defined in the 'widget_methods' map below
# to show up in the dialog itself.  Provide three bits of information:
#  1) The first entry is the method on the widget that grabs a value from the
#     widget.
#  2) The second entry is the method on the widget that sets the widgets value
#      from a stored preference.
#  3) The third entry is a signal the widget will send when the contents have
#     been changed by the user. The preferences dictionary is always up to
# date and will signal the rest of the application about these changes.
# The values will be saved to desktopcouch when the application closes.
#
# TODO: replace widget_methods with your own values


widget_methods = {
    'languages': ['getter', 'setter', 'changed'],
}

In the GUI, it seems as if the widget of choice in gtk for a list is a ListStore (which isn't a widget, but a model, but it's defined in the Glade file...). Can someone tell me what would work for a ListStore for the'getter', 'setter' and 'changed' in the code above?

The approach looks easy for simple entry widgets and such, but I don't know how to use it with lists.

Alternatively, I would of course accept any other way to deal with lists as preferences, provided that the length of the list is not fixed.

share|improve this question
    
Not an answer to the question, but why does your app need to switch languages? Can it not simply use gettext and the user's defined locale to determine the language? That's the standard way to deal with an application's translations: it would work automatically and would be much less work for you. –  David Planella Oct 14 '11 at 7:26
    
@DavidPlnella: a good question. It does not switch languages. The app looks up TV episodes in a database. Since many people speak more then one language, episodes in all of them can be retrieved. Example: I watch German and English TV episodes. –  xubuntix Oct 14 '11 at 8:02

2 Answers 2

up vote 2 down vote accepted
+100

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!

share|improve this answer
    
This works very well and seems quite clear, so the other two attempts are not needed, but thanks you again for trying them... Since your answer is very long but still clear, you might want to extend it into a complete tutorial here: developer.ubuntu.com/resources/tutorials/all Anyway: thanks again! –  xubuntix Oct 20 '11 at 8:41
    
@xubuntix That's an interesting idea, I'll look into it. Thanks for the link and the rep! –  mwalsh Oct 20 '11 at 16:10

I haven't tried 'quickly' myself, but with my GTK experience I'd use Radio Buttons to handle language selection.

Watching the toggled event along with the button.get_active() method should be enough to check what the user has selected.

share|improve this answer
    
Following your suggestion, I looked again at the Radio Buttons but that seems not ideal: Since the list of possible languages is much longer then can be nicely given by Radio Buttons, the only alternative would be to have a separate widget that adds additional radiobuttons, and all radiobuttons are always active. That seems not so nice. –  xubuntix Oct 17 '11 at 9:23
    
Make sure you are using the radio groups properly. Also, the toggled event can be used both for selected and unselected buttons, that is why it should be enough. –  Alexandre Oct 18 '11 at 2:18
    
What I meant is: having 200 radio buttons is not a good user interface. What I need is a way to store a list where items can be added and removed on demand. –  xubuntix Oct 18 '11 at 8:33

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.