Repository: nomic-ai/gpt4all
File: gpt4all-chat/src/chatmodel.h (C/C++)

Code before:
                changed = true;
            }
        }
        if (changed) emit dataChanged(createIndex(index, 0), createIndex(index, 0), {ThumbsDownStateRole});
    }

    Q_INVOKABLE void updateNewResponse(int index, const QString &newResponse)
    {
        bool changed = false;
        {
            QMutexLocker locker(&m_mutex);
            if (index < 0 || index >= m_chatItems.size()) return;

            ChatItem &item = m_chatItems[index];
            if (item.newResponse != newResponse) {
                item.newResponse = newResponse;
                changed = true;
            }
        }
        if (changed) emit dataChanged(createIndex(index, 0), createIndex(index, 0), {NewResponseRole});
    }

    int count() const { QMutexLocker locker(&m_mutex); return m_chatItems.size(); }

    ChatModelIterator begin() { return ChatModelIterator(this, 0); }
    ChatModelIterator end() { return ChatModelIterator(this, m_chatItems.size()); }
    void lock() { m_mutex.lock(); }
    void unlock() { m_mutex.unlock(); }

    bool serialize(QDataStream &stream, int version) const
    {
        QMutexLocker locker(&m_mutex);
        stream << int(m_chatItems.size());
        for (const auto &c : m_chatItems) {
            stream << c.id;
            stream << c.name;
            stream << c.value;
            stream << c.newResponse;
            stream << c.currentResponse;
            stream << c.stopped;
            stream << c.thumbsUpState;
            stream << c.thumbsDownState;
            if (version > 7) {
                stream << c.sources.size();
                for (const ResultInfo &info : c.sources) {
                    Q_ASSERT(!info.file.isEmpty());
                    stream << info.collection;
                    stream << info.path;
                    stream << info.file;
                    stream << info.title;
                    stream << info.author;

Review comment (suggestion):
This should probably use QList<ChatItem>::iterator and not an index, otherwise it will definitely break if the size changes after calling end():
```suggestion
    ChatModelIterator begin() { return {this, m_chatItems.begin()}; }
    ChatModelIterator end() { return {this, m_chatItems.end()}; }
```

Code after:
            if (index < 0 || index >= m_chatItems.size()) return;

            ChatItem &item = m_chatItems[index];
            if (item.newResponse != newResponse) {
                item.newResponse = newResponse;
                changed = true;
            }
        }
        if (changed) emit dataChanged(createIndex(index, 0), createIndex(index, 0), {NewResponseRole});
    }

    int count() const { QMutexLocker locker(&m_mutex); return m_chatItems.size(); }

    ChatModelIterator begin() const { return m_chatItems.begin(); }
    ChatModelIterator end() const { return m_chatItems.end(); }
    void lock() { m_mutex.lock(); }
    void unlock() { m_mutex.unlock(); }

    bool serialize(QDataStream &stream, int version) const
    {
        QMutexLocker locker(&m_mutex);
        stream << int(m_chatItems.size());
        for (const auto &c : m_chatItems) {
            stream << c.id;
            stream << c.name;
            stream << c.value;
            stream << c.newResponse;
            stream << c.currentResponse;
            stream << c.stopped;
            stream << c.thumbsUpState;
            stream << c.thumbsDownState;
            if (version > 7) {
                stream << c.sources.size();
                for (const ResultInfo &info : c.sources) {
                    Q_ASSERT(!info.file.isEmpty());
                    stream << info.collection;
                    stream << info.path;
                    stream << info.file;
                    stream << info.title;
                    stream << info.author;
                    stream << info.date;
                    stream << info.text;
                    stream << info.page;
                    stream << info.from;
                    stream << info.to;
                }
            } else if (version > 2) {
                QList<QString> references;
                QList<QString> referencesContext;
                int validReferenceNumber = 1;
                for (const ResultInfo &info : c.sources) {