Szybka aplikacja z ListStore jako preferencją

10

Zaczynam pisać program „szybko”. Lista pożądanych języków będzie jedną preferencją. Przykład:

languages = ["en", "de"]

(Automatycznie utworzony) szybki kod, który obsługuje część preferencji, wygląda następująco:

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

W GUI wygląda na to, że widgetem z listy w gtk dla listy jest ListStore (który nie jest widżetem, ale modelem, ale jest zdefiniowany w pliku Glade ...). Czy ktoś może mi powiedzieć, co będzie działać na ListStore dla osób 'getter', 'setter'a 'changed'w powyższym kodzie?

Podejście to wygląda na proste widżety wprowadzania i tym podobne, ale nie wiem, jak go używać z listami.

Alternatywnie, oczywiście zaakceptowałbym każdy inny sposób traktowania list jako preferencje, pod warunkiem, że długość listy nie jest stała.

xubuntix
źródło
Nie jest to odpowiedź na pytanie, ale dlaczego Twoja aplikacja musi zmieniać języki? Czy nie można po prostu użyć gettext i ustawień regionalnych użytkownika do określenia języka? Jest to standardowy sposób radzenia sobie z tłumaczeniami aplikacji: działałoby to automatycznie i byłoby dla Ciebie znacznie mniej pracy.
David Planella
@DavidPlnella: dobre pytanie. Nie zmienia języków. Aplikacja wyszukuje odcinki programów telewizyjnych w bazie danych. Ponieważ wiele osób mówi więcej niż jednym językiem, wszystkie epizody można odzyskać. Przykład: oglądam odcinki telewizji niemieckiej i angielskiej.
xubuntix

Odpowiedzi:

2

Oświadczenie: Nie wiedziałem nic o szybkim czasie, dopóki nie przeczytałem twojego postu, ani ogólnie o programowaniu GUI. Dlatego szczerze mówiąc nie mam biznesu, który próbuje odpowiedzieć na to pytanie :)

To powiedziawszy, szybko jest zgrabnym projektem. Zeskanowałem krótko źródło płyty kotła i zidentyfikowałem następujące potencjalne podejścia do dodawania preferencji stylu listy opartej na ListStore:

  1. „Monkey-patch” pobiera i ustawia widget_methods na zapasowym widżecie TreeView (w / Model ListStore) zgodnie z definicją w data / ui / Preferencje $ PROJECTNAME $ Dialog.ui z polaną.
  2. Zaimplementuj set_widget_from_preferencei set_preferencew podklasie projektu PreferencesDialog (podklasą są Preferencje $ PROJECTNAME $ Dialog) i zrób coś innego, gdy keylub widgetjest twoją widżetem TreeView w oparciu o ListStore.
  3. Napisz niestandardową podklasę gtk.TreeView z pasującym niestandardowym widgetem dla polany .

Aby je przetestować, wdrożyłem wszystkie trzy z tych pomysłów - każdy działał zgodnie z przeznaczeniem, i AFAICT identycznie. Ostatecznie trzeci (w szczególności) wydawał mi się najczystszy i bliższy konwencjom stosowanym na całej płycie kotła, choć początkowo spodziewałam się czegoś przeciwnego.


Oto kroki, które wykonałem dla numeru trzy ...

Używając polany przez quickly design(szybko 11.10, btw) i swobodnie postępując zgodnie z tym samouczkiem (część 2) , dodaj widżet ScrolledWindow do Preferencji $ PROJECTNAME $ Dialog.ui, upuść na niego TreeView, nazwij TreeView language_treeview. Po wyświetleniu monitu utwórz nowy model ListStore dla TreeView i nazwij go language_liststore itp. W końcu otrzymałem coś takiego:

właściwości polany

Następnie dodaj katalog polany (data / ui / preferences_ $ PROJECTNAME $ _treeview.xml) z następującą zawartością:

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

Następnie edytuj Preferencje $ PROJECTNAME $ Dialog.ui, dodając ...

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

... na górę, pod tagiem wymaga. I zmień atrybut klasy language_treeview na Preferencje $ PROJECTNAME $ TreeView, przygotowując się do kolejnego kroku.

Na koniec dodaj następujący element do listy widget_methods w Preferencjach $ PROJECTNAME $ Dialog.py

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

I na końcu tego samego pliku (Preferencje $ PROJECTNAME $ Dialog.py) dodaj

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

Jeśli jesteś zainteresowany zobaczeniem moich prób dla pierwszego i drugiego, z przyjemnością to zrobię.

Edycja: Dla zwykłego czytelnika zamień każde wystąpienie $ PROJECTNAME $ na rzeczywistą nazwę twojego szybkiego projektu (jak określono w quickly create).

HTH!

mwalsh
źródło
Działa to bardzo dobrze i wydaje się dość jasne, więc pozostałe dwie próby nie są potrzebne, ale dziękuję jeszcze raz za ich wypróbowanie ... Ponieważ twoja odpowiedź jest bardzo długa, ale nadal jasna, możesz chcieć rozszerzyć ją na kompletny samouczek tutaj: developer.ubuntu.com/resources/tutorials/all W każdym razie: jeszcze raz dziękuję!
xubuntix,
@xubuntix To ciekawy pomysł, przyjrzę mu się. Dzięki za link i przedstawiciel!
mwalsh,
0

Sam nie próbowałem „szybko”, ale z doświadczeniem GTK korzystałem z Przycisków Radiowych do obsługi wyboru języka.

Obejrzenie toggledzdarzenia wraz z button.get_active()metodą powinno wystarczyć, aby sprawdzić, co wybrał użytkownik.

Alexandre
źródło
Zgodnie z twoją sugestią ponownie spojrzałem na przyciski radiowe, ale to nie wydaje się idealne: ponieważ lista możliwych języków jest znacznie dłuższa niż można ją ładnie podać za pomocą przycisków radiowych, jedyną alternatywą byłoby posiadanie osobnego widżetu, który dodaje dodatkowe przyciski radiowe, i wszystkie przyciski radiowe są zawsze aktywne. To nie wydaje się takie miłe.
xubuntix 17.10.11
Upewnij się, że prawidłowo używasz grup radiowych. Również toggledzdarzenie może być stosowany zarówno dla wybranych i nie wybranych przycisków, dlatego powinno wystarczyć.
Alexandre
Miałem na myśli: posiadanie 200 przycisków opcji nie jest dobrym interfejsem użytkownika. Potrzebuję sposobu na przechowywanie listy, w której elementy można dodawać i usuwać na żądanie.
xubuntix 18.10.11