QSortFilterProxyModel not mapping properly

  • I'm having an issue with calls to a QSortFilterProxyModel's mapFromSource function always returning an invalid QModelIndex, regardless of the index provided. In my test case, the model has exactly 1 valid entry, but regardless of what QModelIndex I provide, it always returns invalid. Below is some of the test code I've been using.

                auto src = _sorted_view->sourceModel();
                for (int i = 0; i < src->rowCount(QModelIndex()); ++i) {
                    for (int j = 0; j < src->columnCount(QModelIndex()); ++j) {
                        QModelIndex s = src->index(i, j);
                        QModelIndex m = _meta_model->index(i, j);
                        QModelIndex v = _sorted_view->mapFromSource(s);
                        QModelIndex t = _sorted_view->mapFromSource(m);
                        std::string st = src->data(s).toString().toStdString();
                        std::string mt = _meta_model->data(m).toString().toStdString();
                        if (v.isValid()) { //Always invalid
                            std::string vt = _sorted_view->data(v).toString().toStdString();
                        if (t.isValid()) { //Always invalid
                            std::string tt = _sorted_view->data(t).toString().toStdString();

    In this case, _sorted_view is the QSortFilterProxyModel and _meta_model is a subclass of QAbstractItemModel. Would anyone with a better understanding of QT's model-view setup be able to tell me why the mapping here is not working? As a note, calls to mapToSource generate perfectly valid QModelIndexes, but trying to go the other way does not.

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Why are you using indexes from two different models and map them with _sorted_view ?

  • In this case src and _meta_model point to the same object. It's just some leftover from when I was trying to track down the issue and wanted to make sure that the view was using the model I thought it was.

  • Lifetime Qt Champion

    Are you sure of that ? Because if they point to the same object, then the index returned should be the same. If not, then your custom model does something wrong.

  • Yes, the indexes returned from src and _meta_model are the same. The issue is that none of the indexes returned by _sorted_view->mapFromSource are valid even though I know there is 1 valid entry and I'm iterating over every entry.

  • Lifetime Qt Champion

    Can you show how the source model is implemented ?

  • Yes, here's the top level class. There's a handful of subclasses but I don't believe they do interactions with the Model/View aspects.

    class CxFVariableItemModel : public QAbstractItemModel {
        CxFVariableItemModel () : QAbstractItemModel ()
        virtual ~CxFVariableItemModel () {}
        const QList <QString> &headers () const { return _headers; }
        virtual const QList <QString> &possibleHeaders () const = 0;
        void setHeaders (const QList <QString> &headers) { 
            emit layoutAboutToBeChanged (); 
            _headers = headers; 
            emit layoutChanged (); 
        virtual const bool useLabels (int whichSensor) = 0;
        virtual const QList <LabelReturnType> &getUsefulStrings (bool returnLabels, int whichSensor) = 0;
        virtual const char *getVariableName (int whichSensor) = 0;
        virtual const int getWhichRow (const char *name) = 0;
        virtual const int depVarSize (int whichSensor, int i) = 0;
        virtual const char *getRealDependName (const int whichSensor, const int whichDependSensor) = 0;
    /// Will return a list of all possible timing variable names
        virtual const QList <QString> getListOfTimingVariableNames () = 0;
    /// Will return a list of all possible variable names
        virtual const QList <QString> getListOfVariableNames () = 0;
        QModelIndex index (int row, int column, const QModelIndex &parent = QModelIndex ()) const
            if (!hasIndex (row, column, parent)) {
                return QModelIndex ();
            if (parent == QModelIndex ()) {
                return createIndex(row, column);
            if (_headers [column] == "Other") {
                return createIndex (row, column, reinterpret_cast <void *> (parent.row () + 1));
            return QModelIndex ();
        QModelIndex parent (const QModelIndex &index) const
    // We used to have index.parent ().row () but that causes an issue when we only had one variable in the GUI.
            long parentRow = index.row ();
            if (parentRow == 0) return QModelIndex ();
            else {
                return createIndex (parentRow - 1, 0);
        virtual int rowCount (const QModelIndex &parent) const = 0;
        int columnCount (const QModelIndex &) const { return _headers.size (); }
        virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const = 0;
        QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const
            if (role == Qt::DisplayRole) {
                if (orientation == Qt::Horizontal) {
                    return QVariant (_headers [section]);
                } else { // vertical
                    return (QVariant (section));
            return (QVariant ());
    protected :
        QList <QString> _headers;

    Some of this code is quite old so it may not necessarily be correct according to current Qt Model/View standards which is where I think the problem lies.

  • Lifetime Qt Champion

    You can check you model implementation with the QAbstractItemModelTester. See this wiki entry.