Ver Mensaje Individual
  #12 (permalink)  
Antiguo 18/03/2015, 01:50
eferion
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 2 meses
Puntos: 204
Respuesta: Qt. Delegados. Usar diferente widget para editar y para mostrar

Cita:
Iniciado por dehm Ver Mensaje
1.- ¿Usar delegados es la mejor forma (mas correcta) de formatear un número para que aparezca el punto como separador de miles y la coma como separador de decimales?
Los delegados lo que te permiten es utilizar widgets diferentes al usado por defecto para visualizar (QLabel) / editar(QLineEdit) los datos de la vista.

Si simplemente necesitas que, en visualización, un número aparezca formateado con separador de miles y de decimales, te puedes ahorrar el delegado y conseguir esta salida en el data correspondiente:

Código C++:
Ver original
  1. QVariant Model::data( ... )
  2. {
  3.   if ( model.colum( ) == 0 && role == Qt::DisplayRole )
  4.   {
  5.     // Creo que es esta la secuencia correcta
  6.     return QString( "%L1" ).arg( lista_elements[ model.row( ) ].numero );
  7.   }
  8. }

Cita:
Iniciado por dehm Ver Mensaje
2.- ¿Qué hago cuando necesito más información que el propio data() para formatear o mostrar un valor? Es decir, en mi caso concreto, yo quiero que el fondo de mi celda de la tabla sea de un color u otro dependiendo del valor en sí, pero también del nivel del grafo en el que se encuentra ese valor. Pero el delegado no tiene información a eso último, sólo al propio valor. Entonces, ¿cómo se puede resolver eso?
Los modelos te permiten crear tus propios roles para usos personales. El único requisito es que el identificador de dichos roles sea igual o superior a Qt::UserRole. De esta forma puedes aprovechar toda la lógica programada en el modelo para devolver la información que necesitas:

Código C++:
Ver original
  1. class Model : public QAbstractTableModel
  2. {
  3.   public:
  4.     static const int CustomRole = Qt::UserRole + 1;
  5.  
  6.     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole ) const override
  7.     {
  8.       if ( index.isValid( ) && role == CustomRole )
  9.         return "Test";
  10.  
  11.       return QVariant( );
  12.     }
  13. };
  14.  
  15. int main( )
  16. {
  17.   Model model;
  18.  
  19.   QModelIndex index = model->index( 0, 0 );
  20.   qDebug( ) << model->data( index, Model::CustomRole );
  21. }


Otra posibilidad es aprovechar los QModelIndex. Los modelos tienen un método sobrecargable llamado "index". Este método, junto con "parent" son los encargados de crear el mapeado de datos. Por otro lado, QModelIndex pone a tu disposición un puntero que puedes usar para que apunte a la clase que contiene la información correspondiente a la fila a la que pertenece el index (son muchos conceptos, ahora los aclaro). La idea entonces es sobrecargar "index" y "parent" para componer a mano el mapeo de datos y aprovechar esta sobrecarga para que cada "QModelIndex" apunte a la instancia correcta. Un simple cast sobre ese puntero te permite acceder a toda la información que necesites:

Código C++:
Ver original
  1. struct ModelData
  2. {
  3.   int numero;
  4.   QString texto;
  5. };
  6.  
  7. class Model : public QAbstractTableModel
  8. {
  9.   public:
  10.     QModelIndex index(int row, int column, const QModelIndex& /*parent*/ = QModelIndex()) const override
  11.     {
  12.       if( row >= 0 && row < _data.size( ) && column >= 0 && column < 2 )
  13.         return createIndex( row, column, &_data[ row ] );
  14.       else
  15.         return QAbstractTableModel::index( row, column, parent );
  16.     }
  17.  
  18.     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole ) const override
  19.     {
  20.       if ( index.isValid( ) )
  21.       {
  22.         ModelData* data = reinterpret_cast< ModelData* >( index.internalPointer( ) );
  23.         if ( index.column( ) == 0 )
  24.           return data->numero;
  25.         else
  26.           return data->texto;
  27.       }
  28.  
  29.       return QVariant( );
  30.     }
  31.  
  32.   private:
  33.  
  34.     std::vector< ModelData > _data;
  35. };

Queda de tu parte completar el modelo, no lo he hecho para que quedase clara la idea sobre cómo usar el puntero de QModelIndex.

Al igual que el QModelIndex que recibe "data" tiene su puntero apuntando a un elemento de "_data", el QModelIndex que recibirá el delegado también. Con esto ya deberías disponer de toda la información disponible.