5 votes

Dans QT, l'enchaînement des modèles ne fonctionne pas comme prévu

D'accord, j'ai une question très basique QStandardItemModel rempli de quelques chiffres. J'ai réussi à l'afficher dans un QTableView c'est bon. J'ai créé un nouveau modèle ( sous-classe soit de QAbstractItemModel o QAbstractProxyModel ), qui est une sorte de couche d'un modèle existant - il est nécessaire de définir le modèle source, et cette nouvelle couche devrait effectuer certaines transformations sur le modèle réel.

Mon problème est que, dans la couche supérieure, disons "modèle de couche", le data( const QModelIndex & index, int role ) La fonction membre n'est jamais appelée, mais je voudrais modifier les méthodes d'affichage en fonction du paramètre "rôle".

Voici un exemple de code, qui démontre que le modèle original du data(index,role) est toujours appelé, tandis que le modèle de couche data(index,role) jamais. Pourquoi ? Comment l'objet QTableView peut-il "sauter" la couche supérieure de l'objet QTableView ? data(index,role) ?

#include <QtGui/QApplication>
#include <QtGui>
#include <QStandardItemModel>

class MyModel : public QStandardItemModel
{
public:
    MyModel(const int r, const int c, QObject\* parent = 0) : QStandardItemModel(r,c,parent) {}
    QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const {
        qDebug() << "mymodel data";
        return this->itemFromIndex(index)->data(role);
    }
};

class MyProxyModel : public QAbstractProxyModel
{
public:

    MyProxyModel(QObject\* parent = 0) : QAbstractProxyModel(parent) {}
    QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const {
        return this->sourceModel()->index(row,column,parent);
    }
    QModelIndex parent ( const QModelIndex & index ) const {
        return this->sourceModel()->parent(index);
    }
    QModelIndex mapFromSource ( const QModelIndex & sourceIndex ) const
    {
        return sourceIndex;
    }
    QModelIndex mapToSource ( const QModelIndex & proxyIndex ) const
    {
        return proxyIndex;
    }
    QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const {
        qDebug() << "myproxymodel data";
        return this->sourceModel()->data(index,role);
    }

    int rowCount ( const QModelIndex & parent = QModelIndex() ) const {
        return this->sourceModel()->rowCount(parent);
    }
    int columnCount ( const QModelIndex & parent = QModelIndex() ) const {
        return this->sourceModel()->columnCount(parent);
    }
};

int main(int argc, char \*argv\[\])
{
    QApplication app(argc,argv);
    MyModel model(8, 2);
    MyProxyModel mymodel;
    mymodel.setSourceModel(&model);

    QTableView tableView;
    tableView.setModel(&mymodel);

    tableView.horizontalHeader()->setStretchLastSection(true);
    for (int row = 0; row < 8; ++row) {
        for (int column = 0; column < 2; ++column) {
            QModelIndex index = model.index(row, column, QModelIndex());
            model.setData(index, QVariant((row+1) \* (column+1)));
        }

    }
    tableView.show();
    return app.exec();
}

6voto

TimW Points 5715

Parce que QTableView utilise l'index du modèle pour récupérer les données, probablement quelque chose comme ceci.

QModelIndex index = model->index(row, column, parentIndex); 
index.data(Qt::DisplayRole);

Et vous renvoyez l'index du modèle source au lieu d'un index de votre modèle proxy :

QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const {
    return this->sourceModel()->index(row,column,parent);
}

Essayez de convertir l'index du modèle en un index de votre modèle proxy.

QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const {
    return this->createIndex(row,column,row);
}

N'oubliez pas de réécrire les fonctions map to source et map from source.


Solution

class MyTableProxyModel : public QAbstractProxyModel
{
    Q_OBJECT
public:
    MyTableProxyModel (QObject* parent = 0) 
        : QAbstractProxyModel(parent) {
    }

    QModelIndex index(int row, int column, const QModelIndex& parent=QModelIndex()) const {
        return createIndex(row,column,row);
    }

    QModelIndex parent(const QModelIndex &index) const {
        //Works only for non-tree models
        return QModelIndex();
    }

    QModelIndex mapFromSource(const QModelIndex &source) const {
        return index(source.row(), source.column(), source.parent());
    }

    QModelIndex mapToSource(const QModelIndex &proxy) const {
        return (sourceModel()&&proxy.isValid())
            ? sourceModel()->index(proxy.row(), proxy.column(), proxy.parent()) 
            : QModelIndex();
    }

    QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
        qDebug() << "myproxymodel data";
        return mapToSource(index).data(role);
    }

    int rowCount ( const QModelIndex & parent = QModelIndex() ) const {
        return sourceModel() ? sourceModel()->rowCount(parent) : 0;
    }

    int columnCount ( const QModelIndex & parent = QModelIndex() ) const {
        return sourceModel() ? sourceModel()->columnCount(parent) : 0;
    }
};

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X