Chris K
Chris K

Reputation: 12351

Having an issue with custom Qt ItemModel

I'm trying to create a model to store data about photos, icons and pathnames.

class PhotoListItemModel : public QAbstractItemModel {
    struct ItemModelType {
        std::string fileName;
        QImage      image;
        boost::shared_ptr<char> unique_id;
    };
    std::map<string, ItemModelType> ItemMap;
    std::map<char*, string>         ItemPointerMap;
    std::deque<char*>               ItemIndexMap;

public:
    PhotoListItemModel(QObject* parent);
    virtual bool         clear();
    virtual int          rowCount  ( const QModelIndex & parent = QModelIndex() ) const;
    virtual QVariant     data  ( const QModelIndex & index, int role = Qt::DisplayRole ) const;
    virtual QModelIndex  parent  ( const QModelIndex & index ) const;
    virtual QModelIndex  index  ( int row, int column, const QModelIndex & parent  = QModelIndex() ) const;
    virtual int          columnCount  ( const QModelIndex & parent = QModelIndex() ) const;
    //virtual QMap<int, QVariant>   itemData  ( const QModelIndex & index ) const
    virtual bool    removeColumns  ( int column, int count, const QModelIndex & parent  = QModelIndex() );
    virtual bool    removeRows  ( int row, int count, const QModelIndex & parent  = QModelIndex() );

    //index(), parent(), rowCount(), columnCount(), and data()
    int addFile( const string& str, const QImage& img);
    bool removeItem(const QModelIndex&);
};

PhotoListItemModel::PhotoListItemModel(QObject* parent) :     QAbstractItemModel(parent) {

}
bool PhotoListItemModel::removeItem(const QModelIndex& idx) {
    return(false);
}
bool PhotoListItemModel::removeColumns  ( int column, int count, const QModelIndex & parent) {
    return false;
}
bool PhotoListItemModel::removeRows  ( int row, int count, const QModelIndex & parent) {
    return false;
}
int PhotoListItemModel::rowCount  ( const QModelIndex & parent) const {
    return 1;
}
bool PhotoListItemModel::clear() {
    return true;
}
QVariant     PhotoListItemModel::data  ( const QModelIndex & index, int role) const {
    if (!index.isValid())
        return QVariant();

    if (role == Qt::TextAlignmentRole) {
        return int(Qt::AlignCenter);
    } else if (role == Qt::DisplayRole) {
        char* val = ItemIndexMap[index.column()];
        const map<char*, string>::const_iterator iterPtr    = ItemPointerMap.find(val);
        const map<string, ItemModelType>::const_iterator iterImg   = ItemMap.find(iterPtr->second);
        const QImage &img = iterImg->second.image;

        return img;
    }
    return QVariant();
}
QModelIndex  PhotoListItemModel::parent  ( const QModelIndex & index ) const {
    return QModelIndex();
}
QModelIndex  PhotoListItemModel::index  ( int row, int column, const QModelIndex & parent ) const {
    char* ptr = ItemIndexMap[column];
    return createIndex(row, column, ptr);
}
int PhotoListItemModel::columnCount  ( const QModelIndex & parent) const {
    int colCount = ItemMap.size();
//  if ( colCount < 3 )
//      colCount = 3;

    return colCount;
}

int PhotoListItemModel::addFile( const string& str, const QImage& img) {
    ItemModelType itype;
      itype.fileName = str;
      itype.image = img;
      itype.unique_id = boost::make_shared<char>();

    ItemMap[str] = itype;
    ItemPointerMap[itype.unique_id.get()] = str;
    ItemIndexMap.push_back( itype.unique_id.get() );

    int column = ItemIndexMap.size() - 1;
    QModelIndex mIndex = createIndex(0, column, ItemIndexMap[column]);
    emit dataChanged(mIndex, mIndex);

    beginInsertColumns(QModelIndex(), columnCount()-1 , columnCount()-1);
    bool ret = this->insertColumn(columnCount()-1);
    endInsertColumns();
}

The Qt engine calls columnCount() a number of times, rowCount a number of times. My widget classes call addFile() 6 times.

PhotoListItemModel::data() never gets called, so either Qt isn't listening to the changes I'm making, or I'm missing something. If I set columnCount to 6, for example, ::data does get called (and I haven't verified that my QImages display. One thing at time.

Ultimately I'm tying this into a ListView to display photo thumbnails.

Upvotes: 0

Views: 1228

Answers (2)

Matt
Matt

Reputation: 1

Did you try calling insertRows(0, rowCount()); in the constructor of the model? That always seems to work well for me.

Upvotes: 0

Gianni
Gianni

Reputation: 4390

Firstly, I think you should try inheriting QAbstractTableModel, instead of QAbstractItemModel. That change alone might solve all your problems. You can then get rid of your parent() and index() implementations, and it will take care automatically of all the basic stuff for your. I've found that Qt would behave like that is the QModelIndex I passed to it had its invalid property set to true, which seems to be your case.

Upvotes: 1

Related Questions