Implementing a QAbstractItemModel Iterator

643 views Asked by At

I have been trying to get my head around how to develop a standard style iterator for a QAbstractItemModel, and am getting fairly stuck. I can search the model using depth first or breadth first algorithms, but when it comes to applying these modes to an iterator I'm not sure how to proceed. Could some on point me in the right direct (possibly with pseudo code), or they have an example they are willing to share i would be very grateful.

Thanks

1

There are 1 answers

0
Julien-L On BEST ANSWER

C++14 iterator over the rows of a QAbstractItemModel for a given role. It only iterates over the rows of the model, the column remains unchanged.

class ModelRowIterator : public std::iterator
    <
        std::input_iterator_tag,    // iterator_category
        QVariant,                   // value_type
        int,                        // difference_type
        const QVariant*,            // pointer
        QVariant                    // reference
    >
{
    QModelIndex index_;
    int role_ = 0;
public:
    ModelRowIterator() {}
    ModelRowIterator(const QModelIndex& index, int role) : index_(index), role_(role) {}
    ModelRowIterator& operator++()
    {
        if (index_.isValid())
            index_ = index_.model()->index(index_.row()+1, index_.column());
        return *this;
    }
    ModelRowIterator operator++(int)
    {
        ModelRowIterator ret = *this;
        ++(*this);
        return ret;
    }
    bool operator==(const ModelRowIterator& other) const
    {
        return (!other.index_.isValid() && !index_.isValid()) // ending condition
            || (other.index_ == index_ && other.role_ == role_);
    }
    bool operator!=(const ModelRowIterator& other) const
    {
        return !(other == *this);
    }
    reference operator*() const
    {
        return index_.isValid() ? index_.data(role_) : QVariant{};
    }
};

Note: std::iterator is deprecated in C++17.

Usage:

QAbstractItemModel model;
int role = ...;

ModelRowIterator begin { model.index(0,0), role };
ModelRowIterator end {};
std::for_each(begin, end, [](const QVariant& v) { qDebug() << v; });

auto range = boost::make_range(begin, end);
boost::range::equal(range, [](const QVariant& v) { qDebug() << v; });