web-dev-qa-db-fra.com

Application rapide avec ListStore comme préférence

Je commence à écrire un programme avec "rapidement". Une liste des langues souhaitées sera une préférence. Exemple:

languages = ["en", "de"]

Le code (créé automatiquement) rapidement qui gère la partie des préférences ressemble à ceci:

# 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'],
}

Dans l'interface graphique, il semble que le widget de choix dans gtk pour une liste soit un ListStore (qui n'est pas un widget, mais un modèle, mais il est défini dans le fichier Glade ...). Quelqu'un peut-il me dire ce qui fonctionnerait pour un ListStore pour le'getter', 'setter' et 'changed' dans le code ci-dessus?

L'approche semble facile pour les widgets d'entrée simples et autres, mais je ne sais pas comment l'utiliser avec des listes.

Alternativement, j'accepterais bien entendu toute autre manière de traiter les listes en tant que préférences, à condition que la longueur de la liste ne soit pas fixe.

10
xubuntix

Avertissement: je ne savais rien sur - rapidement jusqu'à ce que je lise votre message, ou sur la programmation gui en général d'ailleurs. Par conséquent, je n'ai honnêtement aucune entreprise tentant de répondre à cette question :)

Cela dit, rapidement est un projet soigné. J'ai analysé brièvement la source passe-partout et identifié les approches potentielles suivantes pour ajouter une préférence de style de liste soutenue par ListStore:

  1. 'Monkey-patch' récupère et définit widget_methods sur un widget TreeView stock (avec le modèle ListStore) comme défini dans data/ui/Preferences $ PROJECTNAME $ Dialog.ui avec glade.
  2. Mettre en place set_widget_from_preference et set_preference dans la sous-classe du projet PreferencesDialog (la sous-classe est Preferences $ PROJECTNAME $ Dialog) et faites quelque chose de différent lorsque key ou widget est votre widget TreeView soutenu par ListStore.
  3. Écrivez une sous-classe personnalisée de gtk.TreeView avec une correspondance widget personnalisé pour glade .

Pour les tester, j'ai mis en œuvre ces trois idées - chacune fonctionnait comme prévu, et AFAICT, à l'identique. Au final, le troisième (en particulier) m'a paru le plus propre, et le plus proche des conventions utilisées tout au long du passe-partout, malgré l'attente initiale du contraire.


Voici les étapes que j'ai suivies pour le numéro trois ...

Utiliser glade via quickly design (rapidement 11.10, btw), et en suivant vaguement ce tutoriel (partie 2) , ajoutez un widget ScrolledWindow aux Préférences $ PROJECTNAME $ Dialog.ui, déposez un TreeView dessus, nommez TreeView language_treeview. Créez un nouveau modèle ListStore pour TreeView lorsque vous y êtes invité, et nommez-le language_liststore, etc ... finalement, je me suis retrouvé avec quelque chose comme ceci:

glade-properties

Ensuite, ajoutez un catalogue de clairières (data/ui/preferences_ $ PROJECTNAME $ _treeview.xml) avec le contenu suivant:

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

Ensuite, modifiez les préférences $ PROJECTNAME $ Dialog.ui, en ajoutant ...

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

... en haut, sous la balise require. Et changez l'attribut de classe de language_treeview en Preferences $ PROJECTNAME $ TreeView, en préparation pour une étape ultérieure.

Enfin, ajoutez l'élément suivant à la liste widget_methods dans les préférences $ PROJECTNAME $ Dialog.py

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

Et à la fin du même fichier (Préférences $ PROJECTNAME $ Dialog.py), ajoutez

import gtk

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

class Preferences$PROJECTNAME$TreeView(gtk.TreeView):
    __gtype_= "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

Si vous êtes intéressé à voir mes tentatives pour un et deux, je suis heureux d'obliger.

Modifier: Pour le lecteur occasionnel, remplacez toute occurrence de $ PROJECTNAME $ par le nom réel de votre quickly projet (comme spécifié dans quickly create).

HTH!

2
mwalsh

Je n'ai pas essayé "rapidement" moi-même, mais avec mon expérience GTK, j'utiliserais Radio Buttons pour gérer la sélection de la langue.

Regarder l'événement toggled avec la méthode button.get_active() devrait être suffisant pour vérifier ce que l'utilisateur a sélectionné.

0
Alexandre