Using QAbstractProxyModel to invert order of a QAbstractListModel
-
Hi,
I have an LayerModel implementation derived from QAbstractListModel. The model is ordered and the ordering determines rendering order of different graphics layers in a graphics view. However, in the ListView GUI I'd like to reverse the order so that the first graphics layer in the model is at the bottom in the view. Changing the order of layers in the list view will consequently change the order of rendering in the graphics view. For this I wrote a proxy class derived from QAbstractProxyModel, which successfully reverts/inverts the order of the list.
The problem: When the selecting and item in the view, the selection is made according to the original model and not the proxy model (i.e. selected it is not the item clicked). Any idea's on how to fix this? The current proxy implementation is listed below.
Best regards,
John@
class InvertListProxyModel : public QAbstractProxyModel
{
public:
InvertListProxyModel(QObject* parent = 0) : QAbstractProxyModel(parent) {}
virtual ~ InvertListProxyModel() {}
QModelIndex mapFromSource ( const QModelIndex & sourceIndex ) const
{
if (!sourceIndex.isValid())
return QModelIndex();
if (sourceIndex.model() != sourceModel())
{
std::cerr<<"InvertListProxyModel:: mapFromSource(): index from wrong model"<<std::endl;
return QModelIndex();
}int proxy_col = sourceIndex.column(); int proxy_row = sourceModel()->rowCount() - 1 - sourceIndex.row(); return createIndex(proxy_row, proxy_col, (int)(sourceIndex.internalId()));
}
QModelIndex mapToSource ( const QModelIndex & proxyIndex ) const
{
if (!proxyIndex.isValid())
return QModelIndex();
if (proxyIndex.model() != this)
{
std::cerr<<"InvertListProxyModel:: mapToSource(): index from wrong model"<<std::endl;
return QModelIndex();
}int source_col = proxyIndex.column(); int source_row = sourceModel()->rowCount() - 1 - proxyIndex.row(); // Invert row return sourceModel()->index(source_row, source_col);
}
QItemSelection mapSelectionFromSource(const QItemSelection& sourceSelection) const
{
QItemSelection proxySelection;
QItemSelection::const_iterator it = sourceSelection.constBegin();
for(; it!=sourceSelection.constEnd(); it++)
{
QModelIndex proxyTopLeft(mapFromSource(sourceModel()->index(it->bottom(), it->left())));
QModelIndex proxyBottomRight(mapFromSource(sourceModel()->index(it->top(), it->right())));proxySelection.append(QItemSelectionRange(proxyTopLeft, proxyBottomRight));
}
return proxySelection;
}
QItemSelection mapSelectionToSource(const QItemSelection& proxySelection) const
{
QItemSelection sourceSelection;
QItemSelection::const_iterator it = proxySelection.constBegin();
for(; it!=proxySelection.constEnd(); it++)
{
QModelIndex sourceTopLeft(mapToSource(index(it->bottom(), it->left())));
QModelIndex sourceBottomRight(mapToSource(index(it->top(), it->right())));
sourceSelection.append(QItemSelectionRange(sourceTopLeft, sourceBottomRight));
}
return sourceSelection;
}QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const
{
if (row >= sourceModel()->rowCount())
return QModelIndex();if (column >= sourceModel()->columnCount())
return QModelIndex();
return mapFromSource(sourceModel()->index(row, column));
}
QModelIndex parent(const QModelIndex& /*index*/) const { return QModelIndex(); } int rowCount(const QModelIndex& parent = QModelIndex()) const { return sourceModel()->rowCount(); } int columnCount(const QModelIndex& parent = QModelIndex()) const { return sourceModel()->columnCount(); }
};
@ -
Hi Ed,
I haven't found a fix for the InvertListProxyModel selection issues, but I found a work-around: I ditched the InvertListProxyModel class and incorporated the index invertion between the data model and the data store instead. An inverting proxy would be a cleaner solution though, so if you have gained any insights to how the selection issue could be solved, then please share it here.
Kind regards,
John