views:

57

answers:

2

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.

+1  A: 

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.

Gianni
made changes as you recommended: here was the calltree: columnCount(), columnCount(), columnCount(), rowCount(), addFile(), rowCount(), columnCount(), rowCount(), columnCount() x 4. No call to data().
Chris Kaminski
Am I maybe better off passing a pointer to my datatype ItemModelType to QStandardItem::setData?
Chris Kaminski
I don't think setData is the answer. Try updating the code you posted with the most recent changes and I'll take a look here.
Gianni
@chris If you post your most recent code (subclassing QAbastractTableModel) we can offer some more input.Also, you don't return anything from addFile.
Casey
@Casey Yup. I think you've nailed it: the addFile should return something!
Gianni
A: 

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

Matt