Unfortunately, the API model does not provide a good way to do this. The simplest solution is to make your model return different headerDatadepending on the root index used. However, this means that the model must know the state of the view (more precisely, the root index), which is not what you usually want.
I think installing a proxy model might be an elegant solution to this problem. Here's how to do it:
class ChildHeadersProxy : public QSortFilterProxyModel {
public:
static const int HorizontalHeaderRole = Qt::UserRole + 1;
static const int VerticalHeaderRole = Qt::UserRole + 2;
void setRootIndex(const QModelIndex& index) {
m_rootIndex = index;
if (sourceModel()) {
emit headerDataChanged(Qt::Horizontal, 0, sourceModel()->columnCount(m_rootIndex));
emit headerDataChanged(Qt::Vertical, 0, sourceModel()->rowCount(m_rootIndex));
}
}
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const {
if (sourceModel() && m_rootIndex.isValid()) {
int role = orientation == Qt::Horizontal ? HorizontalHeaderRole : VerticalHeaderRole;
QStringList headers = sourceModel()->data(m_rootIndex, role).toStringList();
if (section >= 0 && section < headers.count()) {
return headers[section];
}
}
return QSortFilterProxyModel::headerData(section, orientation, role);
}
private:
QModelIndex m_rootIndex;
};
This proxy model uses the headers provided by the source model through two user roles. For example, if you use QStandardItemModel, the header settings are simple:
model.item(0, 1)->setData(QStringList() << "h1" << "h2",
ChildHeadersProxy::HorizontalHeaderRole);
model.item(0, 1)->setData(QStringList() << "vh1" << "vh2",
ChildHeadersProxy::VerticalHeaderRole);
where model.item(0, 1)is the corresponding root element. The view setup will look like this:
QTableView view;
ChildHeadersProxy proxy;
proxy.setSourceModel(&model);
view.setModel(&proxy);
:
view.setRootIndex(proxy.mapFromSource(model.index(0, 1)));
proxy.setRootIndex(model.index(0, 1));