Application rapide avec ListStore comme préférence

10

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.

xubuntix
la source
Pas une réponse à la question, mais pourquoi votre application doit-elle changer de langue? Ne peut-il pas simplement utiliser gettext et les paramètres régionaux définis par l'utilisateur pour déterminer la langue? C'est la façon standard de traiter les traductions d'une application: cela fonctionnerait automatiquement et serait beaucoup moins de travail pour vous.
David Planella
@DavidPlnella: une bonne question. Il ne change pas de langue. L'application recherche des épisodes télévisés dans une base de données. Étant donné que de nombreuses personnes parlent plus d'une langue, les épisodes de chacune d'entre elles peuvent être récupérés. Exemple: je regarde des épisodes télévisés en allemand et en anglais.
xubuntix

Réponses:

2

Avis de non-responsabilité: je ne savais rien sur rapidement jusqu'à ce que j'ai lu 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 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. Implémentez set_widget_from_preferenceet set_preferencedans la sous-classe du projet de PreferencesDialog (la sous-classe est Preferences $ PROJECTNAME $ Dialog), et faites quelque chose de différent lorsque keyou widgetest votre widget TreeView soutenu par ListStore.
  3. Écrivez une sous-classe personnalisée de gtk.TreeView avec un widget personnalisé correspondant pour clairière .

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

En utilisant glade via quickly design(rapidement 11.10, btw) et en suivant ce tutoriel (partie 2) , ajoutez un widget ScrolledWindow aux Préférences $ PROJECTNAME $ Dialog.ui, déposez un TreeView dessus, nommez le 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:

propriétés de la clairière

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

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 projet rapidement (comme spécifié dans quickly create).

HTH!

mwalsh
la source
Cela fonctionne très bien et semble assez clair, donc les deux autres tentatives ne sont pas nécessaires, mais merci encore de les avoir essayées ... Puisque votre réponse est très longue mais toujours claire, vous voudrez peut-être l'étendre en un tutoriel complet ici: developer.ubuntu.com/resources/tutorials/all Quoi qu'il en soit: merci encore!
xubuntix
@xubuntix C'est une idée intéressante, je vais l'examiner. Merci pour le lien et le représentant!
mwalsh
0

Je n'ai pas essayé «rapidement» moi-même, mais avec mon expérience GTK, j'utiliserais des boutons radio pour gérer la sélection de la langue.

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

Alexandre
la source
Suite à votre suggestion, j'ai regardé à nouveau les boutons radio, mais cela ne semble pas idéal: comme la liste des langues possibles est beaucoup plus longue, elle peut être joliment donnée par les boutons radio, la seule alternative serait d'avoir un widget séparé qui ajoute des boutons radio supplémentaires, et tous les boutons radio sont toujours actifs. Cela ne semble pas si agréable.
xubuntix
Assurez-vous que vous utilisez correctement les groupes radio. De plus, l' toggledévénement peut être utilisé à la fois pour les boutons sélectionnés et non sélectionnés, c'est pourquoi il devrait être suffisant.
Alexandre
Ce que je voulais dire, c'est qu'avoir 200 boutons radio n'est pas une bonne interface utilisateur. J'ai besoin d'un moyen de stocker une liste où les éléments peuvent être ajoutés et supprimés à la demande.
xubuntix