~adeodato/ code/ minirok/ csl2.blog/ entries/ 2008/ 02/ 21/ Playlist (3): elementos de visualización

Playlist (3): elementos de visualización

La implementación por defecto de las vistas de ítems de Qt4, por ejemplo QTreeView, se limita a obtener los datos a mostrar mediante el método data() del modelo, y a actualizar las filas mostradas cuando el modelo indica que sus datos han cambiado. Dichos datos suelen ser texto o números, y se muestran sin ningún tipo de formato.

Para la lista de reproducción, sin embargo, queremos cambiar esa visualización por defecto en varias cosas:

Para el último punto, la solución idónea es una clase delegada, que son un mecanismo que ofrece la arquitectura modelo/vista de Qt4 para (entre otras cosas) refinar cómo han de mostrarse las celdas en la vista. En su versión más simple, una clase delegada tiene un único método paint(), que recibe un rectángulo de pantalla donde pintar, y los datos a pintar. Estos datos incluyen un puntero al modelo, y el número de fila y columna, por lo que es fácil preguntar al modelo si esta fila tiene una posición en la cola, o es la fila de “stop after”.

En ambos casos, estos elementos gráficos adicionales sólo hay que mostrarlos en la columna con el número de pista. Las clases vista permiten, con el método setItemDelegateForColumn() asignar una clase delegada sólo a cierta columna.

El código para pintar es prácticamente idéntico al presente en la versión anterior de Minirok; únicamente, pasa de estar en la clase PlaylistItem a la clase PlaylistTrackDelegate.


En una vista con celdas, las clases delegadas (por defecto o proporcionadas por el usuario) son invocadas celda a celda, por lo que no son idóneas para elementos visuales que afectan a toda la fila (p.ej. las dos primeras en la lista anterior).

En este caso, se puede proporcionar en la clase de la vista una implementación del método virtual drawRow() que implemente esos elementos. Esta implementación propia tendrá la siguiente forma:

  def drawRow(self, painter, styleoption, index):
      row = index.row()
      model = self.model()

      if model.row_is_playing(row):
          styleopt = QtGui.QStyleOptionViewItem(styleopt) # make a copy
          styleopt.font.setItalic(True)

      QtGui.QTreeView.drawRow(self, painter, styleopt, index)

      if model.row_is_current(row):
          # dibujar el borde...