Search code examples
c++qtiteratoriterationqabstractitemmodel

Implementing a QAbstractItemModel Iterator


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


Solution

  • 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; });