How to make transparent proxy model : QAbstractProxyModel?

qsortfilterproxymodel
qabstractitemmodel

Since I should make only little modification on the model, transparent proxy would be the best starting point. This proxy will be inserted into model chain.

What is the cleanest way of making proxy model so, that every thing goes unchanged between source and destination model in both directions?

Is there any trivial index(), mapToSource(), mapFromSource(), ... translation using sourceModel()?

All I need to extend are data() with roles and flags().

I know this should be easy to make but I do not want to make it unnecessary complicated making it with learning by doing.

Thanx for your time.

If you're using Qt 4.8 or newer, you can use QIdentityProxyModel, which does exactly that: it maps the source model directly without changing the structure, so you can reimplement data() and/or flags() to modify what's returned.

In Qt 4.7 and older, the easiest way should be to reimplement QSortFilterProxyModel without using anything of the sorting or filtering and just override data() and flags().

Transparent QAbstractProxyModel for tree models, There is no problem to create such a model here is the model and item code. Thread: Transparent QAbstractProxyModel for tree models  Proxy model example code. From Qt Wiki. public QAbstractProxyModel //insert the source model's index and the proxy index into the map mapping. insert

The following works under Qt 4.7, and shows a minimal implementation that retains the semantics of a QAbstractItemModel:

// https://github.com/KubaO/stackoverflown/tree/master/questions/transparent-proxy-19835618
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif

class TransparentProxyModel : public QAbstractProxyModel {
   Q_OBJECT
   struct Helper : QAbstractItemModel {
      using QAbstractItemModel::createIndex;
   };
   struct Op {
      enum Kind { AddRow, RemoveRow, AddCol, RemoveCol, MoveRow, MoveCol } kind;
      QModelIndex parentSrc;
      int first, last;
      QModelIndex parentDst;
      int index;
      bool checkSrc(Kind k, const QModelIndex &i, int f, int l) const {
         return kind == k && parentSrc == i && first == f && last == l;
      }
      bool checkDst(const QModelIndex &i, int n) const {
         return parentDst == i && index == n;
      }
   };
   QVector<Op> m_addsRemoves;
   QModelIndex createSourceIndex(int r, int c, void *data) const {
      return static_cast<Helper *>(sourceModel())->createIndex(r, c, data);
   }
   Q_SLOT void onDataChanged(const QModelIndex &tl, const QModelIndex &br) {
      emit dataChanged(mapFromSource(tl), mapFromSource(br));
   }
   Q_SLOT void onRowsAboutToBeInserted(const QModelIndex &parent, int first, int last) {
      m_addsRemoves.push_back({Op::AddRow, parent, first, last});
      beginInsertRows(mapFromSource(parent), first, last);
   }
   Q_SLOT void onRowsInserted(const QModelIndex &parent, int first, int last) {
      Q_ASSERT(!m_addsRemoves.isEmpty());
      Q_ASSERT(m_addsRemoves.last().checkSrc(Op::AddRow, parent, first, last));
      m_addsRemoves.pop_back();
      endInsertRows();
   }
   Q_SLOT void onRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last) {
      m_addsRemoves.push_back({Op::RemoveRow, parent, first, last});
      beginRemoveRows(mapFromSource(parent), first, last);
   }
   Q_SLOT void onRowsRemoved(const QModelIndex &parent, int first, int last) {
      Q_ASSERT(!m_addsRemoves.isEmpty());
      Q_ASSERT(m_addsRemoves.last().checkSrc(Op::RemoveRow, parent, first, last));
      m_addsRemoves.pop_back();
      endRemoveRows();
   }
   Q_SLOT void onColumnsAboutToBeInserted(const QModelIndex &parent, int first,
                                          int last) {
      m_addsRemoves.push_back({Op::AddCol, parent, first, last});
      beginInsertColumns(parent, first, last);
   }
   Q_SLOT void onColumnsInserted(const QModelIndex &parent, int first, int last) {
      Q_ASSERT(!m_addsRemoves.isEmpty());
      Q_ASSERT(m_addsRemoves.last().checkSrc(Op::AddCol, parent, first, last));
      m_addsRemoves.pop_back();
      endInsertColumns();
   }
   Q_SLOT void onColumnsAboutToBeRemoved(const QModelIndex &parent, int first, int last) {
      m_addsRemoves.push_back({Op::RemoveCol, parent, first, last});
      beginRemoveColumns(mapFromSource(parent), first, last);
   }
   Q_SLOT void onColumnsRemoved(const QModelIndex &parent, int first, int last) {
      Q_ASSERT(!m_addsRemoves.isEmpty());
      Q_ASSERT(m_addsRemoves.last().checkSrc(Op::RemoveCol, parent, first, last));
      m_addsRemoves.pop_back();
      endRemoveColumns();
   }
   Q_SLOT void onRowsAboutToBeMoved(const QModelIndex &srcParent, int start, int end,
                                    const QModelIndex &dstParent, int row) {
      m_addsRemoves.push_back({Op::MoveRow, srcParent, start, end, dstParent, row});
      beginMoveRows(mapFromSource(srcParent), start, end, mapFromSource(dstParent), row);
   }
   Q_SLOT void onRowsMoved(const QModelIndex &srcParent, int start, int end,
                           const QModelIndex &dstParent, int row) {
      Q_ASSERT(!m_addsRemoves.isEmpty());
      auto const &op = m_addsRemoves.last();
      Q_ASSERT(op.checkSrc(Op::MoveRow, srcParent, start, end) &&
               op.checkDst(dstParent, row));
      m_addsRemoves.pop_back();
      endMoveRows();
   }
   Q_SLOT void onColumnsAboutToBeMoved(const QModelIndex &srcParent, int start, int end,
                                       const QModelIndex &dstParent, int col) {
      m_addsRemoves.push_back({Op::MoveCol, srcParent, start, end, dstParent, col});
      beginMoveColumns(mapFromSource(srcParent), start, end, mapFromSource(dstParent),
                       col);
   }
   Q_SLOT void onColumnsMoved(const QModelIndex &srcParent, int start, int end,
                              const QModelIndex &dstParent, int col) {
      Q_ASSERT(!m_addsRemoves.isEmpty());
      auto const &op = m_addsRemoves.last();
      Q_ASSERT(op.checkSrc(Op::MoveRow, srcParent, start, end) &&
               op.checkDst(dstParent, col));
      m_addsRemoves.pop_back();
      endMoveColumns();
   }

  public:
   TransparentProxyModel(QObject *parent = nullptr) : QAbstractProxyModel(parent) {}
   QModelIndex mapFromSource(const QModelIndex &src) const override {
      if (!src.isValid() || !sourceModel()) return {};
      Q_ASSERT(src.model() == sourceModel());
      return createIndex(src.row(), src.column(), src.internalPointer());
   }
   QModelIndex mapToSource(const QModelIndex &prx) const override {
      if (!prx.isValid() || !sourceModel()) return {};
      Q_ASSERT(prx.model() == this);
      return createSourceIndex(prx.row(), prx.column(), prx.internalPointer());
   }
   QModelIndex index(int row, int column, const QModelIndex &parent) const override {
      if (!sourceModel()) return {};
      Q_ASSERT(!parent.isValid() || parent.model() == this);
      return mapFromSource(sourceModel()->index(row, column, mapToSource(parent)));
   }
   int rowCount(const QModelIndex &parent) const override {
      if (!sourceModel()) return 0;
      Q_ASSERT(!parent.isValid() || parent.model() == this);
      return sourceModel()->rowCount(mapToSource(parent));
   }
   int columnCount(const QModelIndex &parent) const override {
      if (!sourceModel()) return 0;
      Q_ASSERT(!parent.isValid() || parent.model() == this);
      return sourceModel()->columnCount(mapToSource(parent));
   }
   QModelIndex parent(const QModelIndex &child) const override {
      if (!child.isValid() || !sourceModel()) return {};
      Q_ASSERT(child.model() == this);
      return mapFromSource(sourceModel()->parent(mapToSource(child)));
   }
   void setSourceModel(QAbstractItemModel *model) override {
      if (sourceModel()) disconnect(sourceModel(), 0, this, 0);
      QAbstractProxyModel::setSourceModel(model);
      if (!sourceModel()) return;
      connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this,
              SLOT(onDataChanged(QModelIndex, QModelIndex)));
      connect(model, SIGNAL(headerDataChanged(Qt::Orientation, int, int)), this,
              SIGNAL(headerDataChanged(Qt::Orientation, int, int)));
      connect(model, SIGNAL(layoutChanged()), this, SIGNAL(layoutChanged()));
      connect(model, SIGNAL(layoutAboutToBeChanged()), this,
              SIGNAL(layoutAboutToBeChanged()));
      connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)), this,
              SLOT(onRowsAboutToBeInserted(QModelIndex, int, int)));
      connect(model, SIGNAL(rowsInserted(QModelIndex, int, int)), this,
              SLOT(onRowsInserted(QModelIndex, int, int)));
      connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), this,
              SLOT(onRowsAboutToBeRemoved(QModelIndex, int, int)));
      connect(model, SIGNAL(rowsRemoved(QModelIndex, int, int)), this,
              SLOT(onRowsRemoved(QModelIndex, int, int)));
      connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int)), this,
              SLOT(onColumnsAboutToBeInserted(QModelIndex, int, int)));
      connect(model, SIGNAL(columnsInserted(QModelIndex, int, int)), this,
              SLOT(onColumnsInserted(QModelIndex, int, int)));
      connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int)), this,
              SLOT(onColumnsAboutToBeRemoved(QModelIndex, int, int)));
      connect(model, SIGNAL(columnsRemoved(QModelIndex, int, int)), this,
              SLOT(onColumnsRemoved(QModelIndex, int, int)));
      connect(model, SIGNAL(modelAboutToBeReset()), this, SIGNAL(modelAboutToBeReset()));
      connect(model, SIGNAL(modelReset()), this, SIGNAL(modelReset()));
      connect(model, SIGNAL(rowsAboutToBeMoved(QModelIndex, int, int, QModelIndex, int)),
              this, SLOT(onRowsAboutToBeMoved(QModelIndex, int, int, QModelIndex, int)));
      connect(model, SIGNAL(rowsMoved(QModelIndex, int, int, QModelIndex, int)), this,
              SLOT(onRowsMoved(QModelIndex, int, int, QModelIndex, int)));
      connect(
          model, SIGNAL(columnsAboutToBeMoved(QModelIndex, int, int, QModelIndex, int)),
          this, SLOT(onColumnsAboutToBeMoved(QModelIndex, int, int, QModelIndex, int)));
      connect(model, SIGNAL(columnsMoved(QModelIndex, int, int, QModelIndex, int)), this,
              SLOT(onColumnsMoved(QModelIndex, int, int, QModelIndex, int)));
   }
};

int main(int argc, char *argv[]) {
   QApplication app(argc, argv);
   QFileSystemModel model;
   TransparentProxyModel proxy;
   proxy.setSourceModel(&model);
   QTreeView view;
   view.setModel(&proxy);
   model.setRootPath(QDir::homePath());
   view.setRootIndex(proxy.mapFromSource(model.index(QDir::homePath())));
   view.show();
   return app.exec();
}
#include "main.moc"

QAbstractProxyModel Class, The QAbstractProxyModel class provides a base class for proxy item models that can do sorting, filtering or other data processing tasks. More. [quote author="winnetou" date="1336659665"]My idea was that the proxy's setData function could use the return value of its source model's setData to decide whether the changes were successful and if so, it could safely emit the dataChanged signal for itself[/quote]But then the dataChanged signal would be emitted twice, once from proxyModel itself and once forwarded through the proxy model from

I have made my own solution. It doesn't make any index change. It should not, actually. Signals are transferred.

The model chain should not be affected if this model is inserted into it.

#ifndef TTRANSPARENTPROXYMODEL_H
#define TTRANSPARENTPROXYMODEL_H

#include <QAbstractProxyModel>

class TTransparentProxyModel :
    public QAbstractProxyModel
{
    Q_OBJECT
public:
    TTransparentProxyModel(QObject *parent = 0);

    void setSourceModel(QAbstractItemModel* newSourceModel);

    /* QAbstractProxyModel methods */
    virtual QModelIndex index( int, int c = 0, const QModelIndex& parent = QModelIndex() ) const;
    virtual QModelIndex parent( const QModelIndex &child ) const;
    virtual int rowCount( const QModelIndex &idx = QModelIndex() ) const;
    virtual int columnCount(const QModelIndex &parent ) const;
    virtual QModelIndex mapToSource( const QModelIndex &index ) const;
    virtual QModelIndex mapFromSource( const QModelIndex &idx ) const;
};

#endif // TTRANSPARENTPROXYMODEL_H

and cpp file:

#include "TransparentProxyModel.h"

TTransparentProxyModel::TTransparentProxyModel(QObject *parent)
    : QAbstractProxyModel(parent)
{
}

void TTransparentProxyModel::setSourceModel(QAbstractItemModel* newSourceModel)
{
    beginResetModel();

    if (sourceModel()) {
    disconnect(sourceModel(), SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
               this, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)));
    disconnect(sourceModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),
               this, SIGNAL(rowsInserted(const QModelIndex &, int, int)));
    disconnect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
               this, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)));
    disconnect(sourceModel(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
               this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)));
    disconnect(sourceModel(), SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
               this, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
    disconnect(sourceModel(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
               this, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
    disconnect(sourceModel(), SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)),
               this, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)));
    disconnect(sourceModel(), SIGNAL(columnsInserted(const QModelIndex &, int, int)),
               this, SIGNAL(columnsInserted(const QModelIndex &, int, int)));
    disconnect(sourceModel(), SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
               this, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)));
    disconnect(sourceModel(), SIGNAL(columnsRemoved(const QModelIndex &, int, int)),
               this, SIGNAL(columnsRemoved(const QModelIndex &, int, int)));
    disconnect(sourceModel(), SIGNAL(columnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
               this, SIGNAL(columnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
    disconnect(sourceModel(), SIGNAL(columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
               this, SIGNAL(columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
    disconnect(sourceModel(), SIGNAL(modelAboutToBeReset()),
               this, SIGNAL(modelAboutToBeReset()));
    disconnect(sourceModel(), SIGNAL(modelReset()),
               this, SIGNAL(modelReset()));
    disconnect(sourceModel(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
               this, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)));
    disconnect(sourceModel(), SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
               this, SIGNAL(headerDataChanged(Qt::Orientation,int,int)));
    disconnect(sourceModel(), SIGNAL(layoutAboutToBeChanged()),
               this, SIGNAL(layoutAboutToBeChanged()));
    disconnect(sourceModel(), SIGNAL(layoutChanged()),
               this, SIGNAL(layoutChanged()));
    }

    QAbstractProxyModel::setSourceModel(newSourceModel);

    if (sourceModel()) {
    connect(sourceModel(), SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
            this, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)));
    connect(sourceModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),
            this, SIGNAL(rowsInserted(const QModelIndex &, int, int)));
    connect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
            this, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)));
    connect(sourceModel(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
            this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)));
    connect(sourceModel(), SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
            this, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
    connect(sourceModel(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
            this, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
    connect(sourceModel(), SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)),
            this, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)));
    connect(sourceModel(), SIGNAL(columnsInserted(const QModelIndex &, int, int)),
            this, SIGNAL(columnsInserted(const QModelIndex &, int, int)));
    connect(sourceModel(), SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
            this, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)));
    connect(sourceModel(), SIGNAL(columnsRemoved(const QModelIndex &, int, int)),
            this, SIGNAL(columnsRemoved(const QModelIndex &, int, int)));
    connect(sourceModel(), SIGNAL(columnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
            this, SIGNAL(columnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
    connect(sourceModel(), SIGNAL(columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
            this, SIGNAL(columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
    connect(sourceModel(), SIGNAL(modelAboutToBeReset()),
            this, SIGNAL(modelAboutToBeReset()));
    connect(sourceModel(), SIGNAL(modelReset()),
            this, SIGNAL(modelReset()));
    connect(sourceModel(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
            this, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)));
    connect(sourceModel(), SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
            this, SIGNAL(headerDataChanged(Qt::Orientation,int,int)));
    connect(sourceModel(), SIGNAL(layoutAboutToBeChanged()),
            this, SIGNAL(layoutAboutToBeChanged()));
    connect(sourceModel(), SIGNAL(layoutChanged()),
            this, SIGNAL(layoutChanged()));
    }
    endResetModel();
}

//virtual int rowCount( const QModelIndex &idx = QModelIndex() ) const;
int TTransparentProxyModel::rowCount(const QModelIndex &parent) const
{
    if(!sourceModel())
    {
    return 0;
    }
    return this->sourceModel()->rowCount(parent);
}

//virtual int columnCount( const QModelIndex &idx ) const;
int TTransparentProxyModel::columnCount(const QModelIndex &parent) const
{
    if(!sourceModel())
    {
    return 0;
    }
    return this->sourceModel()->columnCount(parent);
}

//virtual QModelIndex index( int, int c = 0, const QModelIndex& parent = QModelIndex() ) const;
QModelIndex TTransparentProxyModel::index(int row, int column, const QModelIndex &parent) const
{
    if(!this->sourceModel())
    {
    return QModelIndex();
    }
    return this->sourceModel()->index(row,column,parent);
}

//virtual QModelIndex parent( const QModelIndex &idx ) const;
QModelIndex TTransparentProxyModel::parent(const QModelIndex &child) const
{
//  TODO: check if this is valid.
    QModelIndex mi =  mapFromSource(child);
    if (mi.isValid())
    {
    return mi.parent();
    }
    return QModelIndex();
}

//virtual QModelIndex mapToSource( const QModelIndex &idx ) const;
QModelIndex TTransparentProxyModel::mapToSource(const QModelIndex &index) const
{
    if(!this->sourceModel())
    {
    return QModelIndex();
    }
    return this->sourceModel()->index(index.row(),index.column());
}


//virtual QModelIndex mapFromSource( const QModelIndex &idx ) const;
QModelIndex TTransparentProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
    if(sourceIndex.isValid())
    if(!this->sourceModel())
    {
    return QModelIndex();
    }
    return this->sourceModel()->index(sourceIndex.row(),sourceIndex.column());
}

I tried to catch all of the signals from the source and signal the same way to next model.

The only method, I am not sure if it is properly implemented, is parent().

I hope this is helpful.

Proxy model example code, SortProxy : public QAbstractProxyModel { Q_OBJECT public: SortProxy(​QObject startsWith("A") || !si->parent()) continue; //means that we have internalPointer()); //insert the source model's index and the proxy index into  The WSA can be configured for "transparent" or "forward". This is slightly misleading, as this is really "transparent" or "explicit" mode, both of which are forward proxy deployments. Reverse proxy is where the proxy is intended to be on the same network as the HTTP servers and its purpose is to serve up content for these HTTP servers.

QAbstractProxyModel, All standard proxy models are derived from the QAbstractProxyModel class. If you need to create a new proxy model class, it is usually better to subclass an  Note also that the order of results in the list may not correspond to the order in the model, if for example a proxy model is used. The order of the results cannot be relied upon. The search begins from the start index, and continues until the number of matching data items equals hits , the search reaches the last row, or the search reaches

Qyoto: QtGui.QSortFilterProxyModel Class Reference, The QSortFilterProxyModel class provides support for sorting and filtering data However, reset() returns the proxy model to its original state, losing selection  However, beginResetModel() / endResetModel() returns the proxy model to its original state, losing selection information, and will cause the proxy model to be repopulated. Subclassing. Since QAbstractProxyModel and its subclasses are derived from QAbstractItemModel, much of the same advice about subclassing normal models also applies to proxy

Qt Application Programming with C++ - Part 2, This workshop is ideal for anyone who want to get starte… opaque (75% transparent) QColor("#FF0000"); // red in web-notation QColor("red"); Proxy Model • QSortFilterProxyModel • Transforms structure of source model  This approach allows a given source model to be restructured as far as views are concerned, without requiring any transformations on the underlying data and without duplicating the data in memory. The Custom Sort/Filter Model example consists of two classes: The MySortFilterProxyModel class provides a custom proxy model.

Comments
  • If you need to extend only data and flags, why do you need QAbstractProxyModel at all?
  • @vahancho What is the alternative? I do not want to change upper software (delegate, view) since is some general solution.
  • Can't you change the data and flags of the original model? If not, can't you simply inherit the existing model and override data() and flags() functions? I don't see the reason of using a proxy model unless you want to sort/filter it.
  • @vahancho Tahat is not wanted since also source model is included into some api (factory) and used as abstract model. Also some signals are masked and should stay so for better maintainability.
  • This code has two issues: 1. It returns invalid indices: its index and mapFromSource methods return an index where model() isn't the instance of the proxy model. 2. The SIGNAL signatures are not normalized, and incur normalization overhead. The signatures should look like SIGNAL(QModelIndex,int,int) - const and references are dropped, spaces are removed.