/*!
    \internal
*/
void QDeclarativePlaceContentModel::initializeCollection(int totalCount, const QPlaceContent::Collection &collection)
{
    beginResetModel();

    int initialCount = m_contentCount;
    clearData();

    QMapIterator<int, QPlaceContent> i(collection);
    while (i.hasNext()) {
        i.next();

        const QPlaceContent &content = i.value();
        if (content.type() != m_type)
            continue;

        m_content.insert(i.key(), content);
        if (!m_suppliers.contains(content.supplier().supplierId())) {
            m_suppliers.insert(content.supplier().supplierId(),
                               new QDeclarativeSupplier(content.supplier(), m_place->plugin(), this));
        }
        if (!m_users.contains(content.user().userId())) {
            m_users.insert(content.user().userId(),
                               new QDeclarativePlaceUser(content.user(), this));
        }
    }

    m_contentCount = totalCount;

    if (initialCount != totalCount)
        emit totalCountChanged();

    endResetModel();
}
/*!
    \internal
*/
void QDeclarativePlaceContentModel::setPlace(QDeclarativePlace *place)
{
    if (m_place != place) {
        beginResetModel();

        int initialCount = m_contentCount;
        clearData();
        m_place = place;
        endResetModel();

        emit placeChanged();
        if (initialCount != -1)
            emit totalCountChanged();

        fetchMore(QModelIndex());
    }
}
void
UnitySortFilterProxyModelQML::setModel(QAbstractItemModel *itemModel)
{
    if (itemModel == nullptr) {
        return;
    }

    if (itemModel != sourceModel()) {
        if (sourceModel() != nullptr) {
            sourceModel()->disconnect(this);
        }

        setSourceModel(itemModel);

        connect(itemModel, &QAbstractItemModel::modelReset, this, &UnitySortFilterProxyModelQML::totalCountChanged);
        connect(itemModel, &QAbstractItemModel::rowsInserted, this, &UnitySortFilterProxyModelQML::totalCountChanged);
        connect(itemModel, &QAbstractItemModel::rowsRemoved, this, &UnitySortFilterProxyModelQML::totalCountChanged);

        Q_EMIT totalCountChanged();
        Q_EMIT modelChanged();
    }
}
/*!
    \internal
*/
void QDeclarativePlaceContentModel::fetchFinished()
{
    if (!m_reply)
        return;

    QPlaceContentReply *reply = m_reply;
    m_reply = 0;

    if (m_contentCount != reply->totalCount()) {
        m_contentCount = reply->totalCount();
        emit totalCountChanged();
    }

    if (!reply->content().isEmpty()) {
        QPlaceContent::Collection contents = reply->content();

        //find out which indexes are new and which ones have changed.
        QMapIterator<int, QPlaceContent> it(contents);
        QList<int> changedIndexes;
        QList<int> newIndexes;
        while (it.hasNext()) {
            it.next();
            if (!m_content.contains(it.key()))
                newIndexes.append(it.key());
            else if (it.value() != m_content.value(it.key()))
                changedIndexes.append(it.key());
        }

        //insert new indexes in blocks where within each
        //block, the indexes are consecutive.
        QListIterator<int> newIndexesIter(newIndexes);
        int startIndex = -1;
        while (newIndexesIter.hasNext()) {
            int currentIndex = newIndexesIter.next();
            if (startIndex == -1)
                startIndex = currentIndex;

            if (!newIndexesIter.hasNext() || (newIndexesIter.hasNext() && (newIndexesIter.peekNext() > (currentIndex + 1)))) {
                beginInsertRows(QModelIndex(),startIndex,currentIndex);
                for (int i = startIndex; i <= currentIndex; ++i) {
                    const QPlaceContent &content = contents.value(i);

                    m_content.insert(i, content);
                    if (!m_suppliers.contains(content.supplier().supplierId())) {
                        m_suppliers.insert(content.supplier().supplierId(),
                                           new QDeclarativeSupplier(content.supplier(), m_place->plugin(), this));
                    }
                    if (!m_users.contains(content.user().userId())) {
                        m_users.insert(content.user().userId(),
                                           new QDeclarativePlaceUser(content.user(), this));
                    }
                }
                endInsertRows();
                startIndex = -1;
            }
        }

        //modify changed indexes in blocks where within each
        //block, the indexes are consecutive.
        startIndex = -1;
        QListIterator<int> changedIndexesIter(changedIndexes);
        while (changedIndexesIter.hasNext()) {
            int currentIndex = changedIndexesIter.next();
            if (startIndex == -1)
                startIndex = currentIndex;

            if (!changedIndexesIter.hasNext() || (changedIndexesIter.hasNext() && changedIndexesIter.peekNext() > (currentIndex + 1))) {
                for (int i = startIndex; i <= currentIndex; ++i) {
                    const QPlaceContent &content = contents.value(i);
                    m_content.insert(i, content);
                    if (!m_suppliers.contains(content.supplier().supplierId())) {
                        m_suppliers.insert(content.supplier().supplierId(),
                                           new QDeclarativeSupplier(content.supplier(), m_place->plugin(), this));
                    }
                    if (!m_users.contains(content.user().userId())) {
                        m_users.insert(content.user().userId(),
                                           new QDeclarativePlaceUser(content.user(), this));
                    }
                }
                emit dataChanged(index(startIndex),index(currentIndex));
                startIndex = -1;
            }
        }
    }

    reply->deleteLater();
}