Schnelle Anwendung mit ListStore als Präferenz

10

Ich fange an, ein Programm mit 'schnell' zu schreiben. Eine Liste der gewünschten Sprachen ist eine Präferenz. Beispiel:

languages = ["en", "de"]

Der (automatisch erstellte) Schnellcode, der den Voreinstellungsteil verarbeitet, sieht folgendermaßen aus:

# 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 der GUI scheint es, als ob das Widget der Wahl in gtk für eine Liste ein ListStore ist (das kein Widget, sondern ein Modell ist, aber in der Glade-Datei definiert ist ...). Kann mir jemand sagen , was für ein ListStor für die funktionieren würde 'getter', 'setter'und 'changed'in dem obigen Code?

Der Ansatz sieht für einfache Eintrags-Widgets und dergleichen einfach aus, aber ich weiß nicht, wie ich ihn mit Listen verwenden soll.

Alternativ würde ich natürlich jede andere Möglichkeit akzeptieren, mit Listen als Präferenzen umzugehen, vorausgesetzt, die Länge der Liste ist nicht festgelegt.

xubuntix
quelle
Keine Antwort auf die Frage, aber warum muss Ihre App die Sprache wechseln? Kann es nicht einfach gettext und das vom Benutzer definierte Gebietsschema verwenden, um die Sprache zu bestimmen? Dies ist die Standardmethode für den Umgang mit den Übersetzungen einer Anwendung: Sie würde automatisch funktionieren und für Sie viel weniger Arbeit bedeuten.
David Planella
@ DavidPlnella: eine gute Frage. Es wechselt nicht die Sprache. Die App sucht nach TV-Folgen in einer Datenbank. Da viele Menschen mehr als eine Sprache sprechen, können Episoden in allen von ihnen abgerufen werden. Beispiel: Ich schaue deutsche und englische TV-Folgen.
Xubuntix

Antworten:

2

Haftungsausschluss: Ich wusste nichts schnelles, bis ich Ihren Beitrag gelesen habe, oder über GUI-Programmierung im Allgemeinen. Daher habe ich ehrlich gesagt nichts damit zu tun, diese Frage zu beantworten :)

Das heißt, schnell ist ein ordentliches Projekt. Ich habe die Boilerplate-Quelle kurz gescannt und die folgenden möglichen Ansätze zum Hinzufügen einer ListStore-gestützten Listenstilpräferenz identifiziert:

  1. 'Monkey-Patch' ruft Widget_Methods ab und setzt sie auf ein TreeView-Widget (mit ListStore-Modell), wie in data / ui / Preferences $ PROJECTNAME $ Dialog.ui with glade definiert.
  2. Implementieren Sie set_widget_from_preferenceund set_preferencein der Unterklasse von PreferencesDialog des Projekts (die Unterklasse ist Preferences $ PROJECTNAME $ Dialog) und führen Sie etwas anderes aus, wenn keyoder wenn widgetIhr von ListStore unterstütztes TreeView-Widget verwendet wird.
  3. Schreiben Sie eine benutzerdefinierte Unterklasse von gtk.TreeView mit einem passenden benutzerdefinierten Widget für glade .

Um sie zu testen, habe ich alle drei dieser Ideen umgesetzt - jede funktionierte wie beabsichtigt und AFAICT identisch. Am Ende schien mir der dritte (insbesondere) der sauberste zu sein und näher an den Konventionen zu sein, die auf der gesamten Kesselplatte angewendet wurden, obwohl zunächst das Gegenteil erwartet wurde.


Hier sind die Schritte, die ich für Nummer drei befolgt habe ...

quickly designFügen Sie mit Glade via (schnell 11.10, übrigens) und nach diesem Tutorial (Teil 2) ein ScrolledWindow-Widget zu den Einstellungen $ PROJECTNAME $ Dialog.ui hinzu, legen Sie eine TreeView darauf ab und benennen Sie die TreeView language_treeview. Erstellen Sie ein neues ListStore-Modell für die TreeView, wenn Sie dazu aufgefordert werden, und nennen Sie es language_liststore usw. Am Ende hatte ich Folgendes:

Lichtungseigenschaften

Fügen Sie als Nächstes einen Glade-Katalog (data / ui / settings_ $ PROJECTNAME $ _treeview.xml) mit den folgenden Inhalten hinzu:

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

Bearbeiten Sie dann die Einstellungen $ PROJECTNAME $ Dialog.ui und fügen Sie ...

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

... nach oben unter dem Tag "require". Ändern Sie das Klassenattribut language_treeview in Preferences $ PROJECTNAME $ TreeView, um sich auf einen späteren Schritt vorzubereiten.

Fügen Sie abschließend das folgende Element zur Liste widget_methods in den Einstellungen $ PROJECTNAME $ Dialog.py hinzu

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

Und fügen Sie am Ende derselben Datei (Einstellungen $ PROJECTNAME $ Dialog.py) hinzu

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

Wenn Sie daran interessiert sind, meine Versuche für eins und zwei zu sehen, bin ich gerne bereit, dies zu tun.

Bearbeiten: Ersetzen Sie für den Gelegenheitsleser jedes Vorkommen von $ PROJECTNAME $ durch den tatsächlichen Namen Ihres schnellen Projekts (wie in angegeben quickly create).

HTH!

mwalsh
quelle
Dies funktioniert sehr gut und scheint ziemlich klar zu sein, so dass die beiden anderen Versuche nicht erforderlich sind. Vielen Dank noch einmal, dass Sie sie ausprobiert haben. Da Ihre Antwort sehr lang, aber immer noch klar ist, möchten Sie sie möglicherweise hier zu einem vollständigen Tutorial erweitern: developer.ubuntu.com/resources/tutorials/all Wie auch immer: Nochmals vielen Dank!
Xubuntix
@xubuntix Das ist eine interessante Idee, ich werde sie untersuchen. Danke für den Link und den Repräsentanten!
Mwalsh
0

Ich habe nicht ‚schnell‘ selber ausprobiert, aber mit meiner GTK Erfahrung würde ich verwenden Radiobuttons zur Sprachauswahl zu behandeln.

Das Beobachten des toggledEreignisses zusammen mit der button.get_active()Methode sollte ausreichen, um zu überprüfen, was der Benutzer ausgewählt hat.

Alexandre
quelle
Auf Ihren Vorschlag hin habe ich mir die Optionsfelder noch einmal angesehen, aber das scheint nicht ideal zu sein: Da die Liste der möglichen Sprachen viel länger ist als die Optionsfelder, kann die einzige Alternative darin bestehen, ein separates Widget zu haben, das zusätzliche Radiobuttons hinzufügt. und alle Radiobuttons sind immer aktiv. Das scheint nicht so schön.
Xubuntix
Stellen Sie sicher, dass Sie die Funkgruppen ordnungsgemäß verwenden. Das toggledEreignis kann auch sowohl für ausgewählte als auch für nicht ausgewählte Schaltflächen verwendet werden. Deshalb sollte es ausreichen.
Alexandre
Was ich damit gemeint habe ist: 200 Optionsfelder zu haben ist keine gute Benutzeroberfläche. Was ich brauche, ist eine Möglichkeit, eine Liste zu speichern, in der Elemente bei Bedarf hinzugefügt und entfernt werden können.
Xubuntix