Qt implementa su propia versión del patrón Model-View-Controller (MVC), donde el Modelo gestiona los datos y su lógica, la Vista presenta la información y el Delegado controla la renderización y edición. Este artículo se centra en las clases de modelo disponiblse en Qt y sus fundamentos de uso.
Estructura de herencia de clases
Todas las clases de modelo en Qt derivan de QAbstractItemModel, que establece la interfaz fundamental. Esta clase abstracta no debe instanciarse directamente; en su lugar, se utilizan sus implementaciones concretas.
QStringListModel
Para listas simples de cadenas de texto, QStringListModel ofrece una solución directa. Es ideal para poblar componentes como QListView o QComboBox.
// Inicialización de un modelo de lista
QStringListModel* modeloLista = new QStringListModel();
QStringList datos = {"Elemento A", "Elemento B", "Elemento C", "Elemento D"};
modeloLista->setStringList(datos);
// Asignación a una vista
miListView->setModel(modeloLista);
Moddelos proxy
Los modelos proxy interceptan y transforman datos de un modelo fuente sin alterarlo, permitiendo diferentes perspectivas de los mismos datos en múltiples vistas.
QSortFilterProxyModel
Proporciona ordenación y filtrado dinámico. Transforma la estructura del modelo fuente mediatne mapeo de índices.
// Configuración con ordenación
QStandardItemModel* modeloOriginal = new QStandardItemModel();
// ... (población de datos)
QSortFilterProxyModel* proxyOrden = new QSortFilterProxyModel();
proxyOrden->setSourceModel(modeloOriginal);
proxyOrden->setSortCaseSensitivity(Qt::CaseInsensitive);
QTableView* tabla = new QTableView();
tabla->setModel(proxyOrden);
tabla->setSortingEnabled(true);
// Ordenación programática
tabla->sortByColumn(0, Qt::AscendingOrder);
Para filtrado personalizado, establezca una expresión regular, patrón comodín o cadena fija:
proxyOrden->setFilterRegularExpression(QRegularExpression("^Archivo_"));
QTransposeProxyModel
Intercambia filas y columnas del modelo fuente. Un índice (i, j) en el modelo original se convierte en (j, i) en el proxy.
QTransposeProxyModel* proxyTransposicion = new QTransposeProxyModel();
proxyTransposicion->setSourceModel(miModeloDatos);
miTableView->setModel(proxyTransposicion);
QIdentityProxyModel
Proporciona una copia exacta del modelo fuente sin transformaciones. Es útil como base para proxies que personalizan solo la visualización mediante la sobrescritura de data().
class FormatoFechaProxy : public QIdentityProxyModel
{
public:
QVariant data(const QModelIndex &indice, int rol) const override
{
if (rol == Qt::DisplayRole && indice.column() == 0) {
QVariant valorOriginal = sourceModel()->data(indice, FechaPersonalizadaRole);
return valorOriginal.toDateTime().toString("dd/MM/yyyy");
}
return QIdentityProxyModel::data(indice, rol);
}
};
Modelos para bases de datos
QSqlQueryModel
Proporciona acceso de solo lectura a resultados de consultas SQL. Se puede usar independientemente de una vista.
QSqlQueryModel* modeloConsulta = new QSqlQueryModel();
modeloConsulta->setQuery("SELECT nombre, puesto FROM empleados");
modeloConsulta->setHeaderData(0, Qt::Horizontal, "Nombre");
modeloConsulta->setHeaderData(1, Qt::Horizontal, "Cargo");
// Uso sin vista
int salario = modeloConsulta->record(2).value("salario").toInt();
QSqlTableModel
Extiende QSqlQueryModel con capacidades CRUD para una tabla específica. Controla estrategias de edición y aplicaciones de cambios.
QSqlTableModel* modeloTabla = new QSqlTableModel(this);
modeloTabla->setTable("productos");
modeloTabla->setEditStrategy(QSqlTableModel::OnManualSubmit);
modeloTabla->setFilter("precio > 100");
modeloTabla->setSort(2, Qt::DescendingOrder);
modeloTabla->select();
// Para aplicar todos los cambios pendientes
if (modeloTabla->submitAll()) {
qDebug() << "Cambios confirmados";
} else {
modeloTabla->revertAll();
}
Modelos compuestos y especializados
QConcatenateTablesProxyModel
Fusiona múltiples modelos verticalmente. El número de columnas visibles se determina por el modelo con menos columnas.
QConcatenateTablesProxyModel* modeloConcatenado = new QConcatenateTablesProxyModel();
modeloConcatenado->addSourceModel(miModeloListas);
modeloConcatenado->addSourceModel(miModeloSQL);
tablaPrincipal->setModel(modeloConcatenado);
QFileSystemModel
Representa la estructura del sistema de archivos local. Ofrece operaciones de directorio y metadatos de archivos.
QFileSystemModel* modeloFS = new QFileSystemModel();
modeloFS->setRootPath("/ruta/directorio");
QTreeView* arbol = new QTreeView();
arbol->setModel(modeloFS);
arbol->setRootIndex(modeloFS->index("/ruta/directorio"));
// Crear nuevo directorio
QModelIndex padre = modeloFS->index("/ruta/existente");
modeloFS->mkdir(padre, "nueva_carpeta");
QStandardItemModel
Implementa un modelo genérico basado en items para estructuras de lista, tabla o árbol. Cada item se representa mediante QStandardItem.
QStandardItemModel* modeloItems = new QStandardItemModel(5, 3);
for (int fila = 0; fila < 5; ++fila) {
for (int col = 0; col < 3; ++col) {
QStandardItem* item = new QStandardItem(QString("F%1C%2").arg(fila).arg(col));
modeloItems->setItem(fila, col, item);
}
}
modeloItems->setHorizontalHeaderLabels({"ID", "Nombre", "Valor"});
miTableView->setModel(modeloItems);
Implementación de modelos personalizados
Para lógica de presentación compleja, derive de un modelo existente y sobrescriba data(). Esto permite personalizaciones por celda basadas en roles.
class ModeloEstilizado : public QStandardItemModel
{
protected:
QVariant data(const QModelIndex &idx, int role) const override {
// Resaltar columna 0 con fondo azul
if (idx.column() == 0 && role == Qt::BackgroundRole)
return QColor(220, 230, 255);
// Alinear texto de columna 2 a la derecha
if (idx.column() == 2 && role == Qt::TextAlignmentRole)
return static_cast<int>(Qt::AlignRight | Qt::AlignVCenter);
// Fuente específica para columna 1
if (idx.column() == 1 && role == Qt::FontRole) {
QFont fuente("Monospace", 10);
fuente.setBold(true);
return fuente;
}
return QStandardItemModel::data(idx, role);
}
};
</int>