Aplicación rápida con ListStore como preferencia


10

Estoy empezando a escribir un programa con 'rápidamente'. Una lista de idiomas deseados será una preferencia. Ejemplo:

languages = ["en", "de"]

El código (creado automáticamente) rápidamente que maneja la parte de preferencia se ve así:

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

En la GUI, parece que el widget de elección en gtk para una lista es un ListStore (que no es un widget, sino un modelo, pero está definido en el archivo Glade ...). ¿Alguien puede decirme qué funcionaría para un ListStore para 'getter', 'setter'y 'changed'en el código anterior?

El enfoque parece fácil para widgets de entrada simples y demás, pero no sé cómo usarlo con listas.

Alternativamente, por supuesto, aceptaría cualquier otra forma de tratar las listas como preferencias, siempre que la longitud de la lista no sea fija.


No es una respuesta a la pregunta, pero ¿por qué su aplicación necesita cambiar de idioma? ¿No puede simplemente usar gettext y la configuración regional definida por el usuario para determinar el idioma? Esa es la forma estándar de manejar las traducciones de una aplicación: funcionaría automáticamente y sería mucho menos trabajo para usted.
David Planella

@DavidPlnella: una buena pregunta. No cambia idiomas. La aplicación busca episodios de TV en una base de datos. Como muchas personas hablan más de un idioma, se pueden recuperar episodios en todos ellos. Ejemplo: veo episodios de televisión en alemán e inglés.
xubuntix

Respuestas:


2

Descargo de responsabilidad: no supe nada rápidamente hasta que leí tu publicación, o sobre la programación gui en general para el caso. Por lo tanto, sinceramente, no tengo nada que tratar de responder esta pregunta :)

Dicho esto, rápidamente es un proyecto ordenado. Escaneé brevemente la fuente repetitiva e identifiqué los siguientes enfoques potenciales para agregar una preferencia de estilo de lista respaldada por ListStore:

  1. 'Monkey-patch' obtiene y establece widget_methods en un widget TreeView estándar (con el modelo ListStore) como se define en data / ui / Preferences $ PROJECTNAME $ Dialog.ui with glade.
  2. Implemente set_widget_from_preferencey set_preferenceen la subclase de PreferencesDialog del proyecto (la subclase es Preferences $ PROJECTNAME $ Dialog), y haga algo diferente cuando keyo widgetsea ​​su widget TreeView respaldado por ListStore.
  3. Escriba una subclase personalizada de gtk.TreeView con un widget personalizado correspondiente para glade .

Para probarlos, implementé las tres ideas: cada una funcionó según lo previsto y AFAICT, de forma idéntica. Al final, el tercero (en particular) me pareció el más limpio y más cercano a las convenciones utilizadas en toda la repetitiva, a pesar de que inicialmente esperaba lo contrario.


Aquí están los pasos que seguí para el número tres ...

Usando glade via quickly design(rápidamente 11.10, por cierto), y siguiendo libremente este tutorial (parte 2) , agregue un widget ScrolledWindow a las Preferencias $ PROJECTNAME $ Dialog.ui, suelte un TreeView sobre él, nombre TreeView language_treeview. Cree un nuevo modelo ListStore para TreeView cuando se le solicite, y asígnele el nombre language_liststore, etc. Finalmente terminé con algo como esto:

propiedades de glade

A continuación, agregue un catálogo glade (data / ui / preferencias_ $ PROJECTNAME $ _treeview.xml) con el siguiente contenido:

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

Luego, edite Preferencias $ PROJECTNAME $ Dialog.ui, agregando ...

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

... hacia arriba, debajo de la etiqueta require. Y cambie el atributo de clase de language_treeview a Preferencias $ PROJECTNAME $ TreeView, en preparación para un paso posterior.

Finalmente, agregue el siguiente elemento a la lista widget_methods en Preferencias $ PROJECTNAME $ Dialog.py

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

Y al final del mismo archivo (Preferencias $ PROJECTNAME $ Dialog.py), agregue

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 está interesado en ver mis intentos de uno y dos, estoy feliz de hacerlo.

Editar: para el lector casual, reemplace cualquier aparición de $ PROJECTNAME $ con el nombre real de su proyecto rápido (como se especifica en quickly create).

HTH!


Esto funciona muy bien y parece bastante claro, por lo que los otros dos intentos no son necesarios, pero gracias de nuevo por intentarlos ... Dado que su respuesta es muy larga pero aún clara, es posible que desee extenderlo a un tutorial completo aquí: developer.ubuntu.com/resources/tutorials/all De todos modos: ¡gracias de nuevo!
xubuntix

@xubuntix Esa es una idea interesante, lo investigaré. Gracias por el enlace y el representante!
mwalsh

0

No lo he intentado 'rápidamente', pero con mi experiencia GTK usaría botones de radio para manejar la selección de idioma.

Mirar el toggledevento junto con el button.get_active()método debería ser suficiente para verificar lo que el usuario ha seleccionado.


Siguiendo su sugerencia, volví a mirar los botones de radio, pero parece que no es lo ideal: dado que la lista de idiomas posibles es mucho más larga que los botones de radio, la única alternativa sería tener un widget separado que agregue botones de radio adicionales, y todos los botones de radio siempre están activos. Eso no parece tan bueno.
xubuntix

Asegúrese de estar utilizando los grupos de radio correctamente. Además, el toggledevento se puede usar tanto para botones seleccionados como no seleccionados, por eso debería ser suficiente.
Alexandre

Lo que quise decir es: tener 200 botones de radio no es una buena interfaz de usuario. Lo que necesito es una forma de almacenar una lista donde los artículos se pueden agregar y quitar a pedido.
xubuntix
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.