Пример #1
0
void EnginioBaseModelPrivate::fullQueryReset(const QJsonArray &data)
{
    delete _replyConnectionConntext;
    _replyConnectionConntext = new QObject();
    q->beginResetModel();
    _data = data;
    _attachedData.initFromArray(_data);
    syncRoles();
    _canFetchMore = _canFetchMore && _data.count() && (queryData(QtCloudServicesConstants::limit).toDouble() <= _data.count());
    q->endResetModel();
}
Пример #2
0
void EnginioBaseModelPrivate::receivedUpdateNotification(const QJsonObject &object, const QString &idHint, int row)
{
    // update an existing object
    if (row == NoHintRow) {
        QString id = idHint.isEmpty() ? object[QtCloudServicesConstants::id].toString() : idHint;
        Q_ASSERT(_attachedData.contains(id));
        row = _attachedData.rowFromObjectId(id);
    }

    if (Q_UNLIKELY(row == DeletedRow)) {
        return;
    }

    // FIXME Sometimes it may happen that we get an update about an object that was created just after
    // the full query and before notifications are setup. For now we inore such situation in future
    // we should create a createNotification.
    if (Q_UNLIKELY(row < 0)) {
        return;
    }

    QJsonObject current = _data[row].toObject();
    QDateTime currentUpdateAt = QDateTime::fromString(current[QtCloudServicesConstants::updatedAt].toString(), Qt::ISODate);
    QDateTime newUpdateAt = QDateTime::fromString(object[QtCloudServicesConstants::updatedAt].toString(), Qt::ISODate);

    if (newUpdateAt < currentUpdateAt) {
        // we already have a newer version
        return;
    }

    if (_data[row].toObject()[QtCloudServicesConstants::id].toString().isEmpty()) {
        // Create and update may go through the same code path because
        // the model already have a dummy item. No id means that it
        // is a dummy item.
        const QString newId = object[QtCloudServicesConstants::id].toString();
        AttachedData newData(row, newId);
        _attachedData.insert(newData);
    }

    if (_data.count() == 1) {
        q->beginResetModel();
        _data.replace(row, object);
        syncRoles();
        q->endResetModel();
    } else {
        _data.replace(row, object);
        emit q->dataChanged(q->index(row), q->index(row));
    }
}
Пример #3
0
 EnginioReply *append(const QJsonObject &value)
 {
     QJsonObject object(value);
     object[EnginioString::objectType] = _query[EnginioString::objectType]; // TODO think about it, it means that not all queries are valid
     EnginioReply* id = _enginio->create(object, _operation);
     const int row = _data.count();
     if (!row) { // the first item need to update roles
         q->beginResetModel();
         _rowsToSync.insert(row);
         _data.append(value);
         syncRoles();
         _dataChanged.insert(id, qMakePair(row, object));
         q->endResetModel();
     } else {
         q->beginInsertRows(QModelIndex(), _data.count(), _data.count());
         _rowsToSync.insert(row);
         _data.append(value);
         _dataChanged.insert(id, qMakePair(row, object));
         q->endInsertRows();
     }
     return id;
 }
Пример #4
0
    void finishedRequest(const EnginioReply *response)
    {
        // We get all finished requests, check if we started this one
        if (!_dataChanged.contains(response))
            return;

        // ### TODO proper error handling
        // this kind of response happens when the backend id/secret is missing
        if (!response->data()[EnginioString::message].isNull())
            qWarning() << "Enginio: " << response->data()[EnginioString::message].toString();

        QPair<int, QJsonObject> requestInfo = _dataChanged.take(response);
        int row = requestInfo.first;
        if (row == FullModelReset) {
            q->beginResetModel();
            _rowsToSync.clear();
            _data = response->data()[EnginioString::results].toArray();
            syncRoles();
            _canFetchMore = _canFetchMore && _data.count() && (_query[EnginioString::limit].toDouble() <= _data.count());
            q->endResetModel();
        } else if (row == IncrementalModelUpdate) {
            Q_ASSERT(_canFetchMore);
            QJsonArray data(response->data()[EnginioString::results].toArray());
            QJsonObject query(requestInfo.second);
            int offset = query[EnginioString::offset].toDouble();
            int limit = query[EnginioString::limit].toDouble();
            int dataCount = data.count();

            int startingOffset = qMax(offset, _data.count());

            q->beginInsertRows(QModelIndex(), startingOffset, startingOffset + dataCount -1);
            for (int i = 0; i < dataCount; ++i) {
                _data.append(data[i]);
            }

            _canFetchMore = limit <= dataCount;
            q->endInsertRows();
        } else {
            _rowsToSync.remove(row); // FIXME the row is may not be right
            QJsonObject newValue(response->data());
            QJsonObject oldValue = requestInfo.second;

            const bool removeOperation = newValue.isEmpty();
            // update the row number
            row = findId(oldValue[EnginioString::id].toString(), row);
            if (row == -1) {
                // The object is not in the cache, which means that it was deleted already
                if (removeOperation)
                    qWarning() << "The same row was removed twice, removed object was:"
                               << QJsonDocument(oldValue).toJson();
                else
                    qWarning() << "Trying to update a removed object:\nOldValue: "
                               << QJsonDocument(oldValue).toJson()
                               << "\nNewValue: " << QJsonDocument(newValue).toJson();
                return; // nothing to do
            }
            Q_ASSERT(row >= 0 && row < _data.count());

            if (response->networkError() != QNetworkReply::NoError) {
                _data.replace(row, oldValue); // FIXME do we have to do more here?
                return;
            }

            if (removeOperation) {
                q->beginRemoveRows(QModelIndex(), row, row);
                _data.removeAt(row);
                q->endRemoveRows();
            } else {
                QJsonObject current = _data[row].toObject();
                QDateTime currentUpdateAt = QDateTime::fromString(current[EnginioString::updatedAt].toString(), Qt::ISODate);
                QDateTime newUpdateAt = QDateTime::fromString(newValue[EnginioString::updatedAt].toString(), Qt::ISODate);
                if (newUpdateAt < currentUpdateAt) {
                    // we already have a newer version
                    return;
                }
                if (_data.count() == 1) {
                    q->beginResetModel();
                    _data.replace(row, newValue);
                    syncRoles();
                    q->endResetModel();
                } else {
                    _data.replace(row, newValue);
                    emit q->dataChanged(q->index(row), q->index(row));
                }
            }
        }
    }