Qt with Cascades UI Examples Documentation

ImageModel.cpp Example File

contiguouscache/src/ImageModel.cpp
    /****************************************************************************
     **
     ** Portions Copyright (C) 2012 Research In Motion Limited.
     ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
     ** All rights reserved.
     ** Contact: Research In Motion Ltd. (http://www.rim.com/company/contact/)
     ** Contact: Nokia Corporation (qt-info@nokia.com)
     **
     ** This file is part of the examples of the BB10 Platform and is derived
     ** from a similar file that is part of the Qt Toolkit.
     **
     ** You may use this file under the terms of the BSD license as follows:
     **
     ** "Redistribution and use in source and binary forms, with or without
     ** modification, are permitted provided that the following conditions are
     ** met:
     **   * Redistributions of source code must retain the above copyright
     **     notice, this list of conditions and the following disclaimer.
     **   * Redistributions in binary form must reproduce the above copyright
     **     notice, this list of conditions and the following disclaimer in
     **     the documentation and/or other materials provided with the
     **     distribution.
     **   * Neither the name of Research In Motion, nor the name of Nokia
     **     Corporation and its Subsidiary(-ies), nor the names of its
     **     contributors may be used to endorse or promote products
     **     derived from this software without specific prior written
     **     permission.
     **
     ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
     **
     ****************************************************************************/

    #include "ImageModel.hpp"

    using namespace bb::cascades;

    // The number of Images the cache will keep in memory at a time
    static const int bufferSize(50);

    // The number of Images it will pre-load even if the view has not requested them yet
    static const int lookAhead(10);

    // The number of Images it will pre-load before and after the current element
    static const int halfLookAhead(lookAhead/2);

    ImageModel::ImageModel(QObject *parent)
        : DataModel(parent)
        , m_rows(bufferSize)
        , m_count(10000)
    {
    }

    int ImageModel::childCount(const QVariantList &indexPath)
    {
        if ( indexPath.isEmpty() )
            return m_count;
        else {
            return 0;
        }
    }

    bool ImageModel::hasChildren(const QVariantList &indexPath)
    {
        // We have only one level of items (plain list)
        return indexPath.isEmpty();
    }

    QVariant ImageModel::data(const QVariantList &indexPath)
    {
        if (indexPath.isEmpty())
            return QVariant();

        // Extract the requested row from the index path
        const int row = indexPath.first().toInt();

        // Store the current number of cached items
        const int oldCachedItemCount = m_rows.count();

        if (row > m_rows.lastIndex()) { // If a row after the last valid index in cache is requested ...
            if (row - m_rows.lastIndex() > lookAhead) { // ... and the distance is larger than the look ahead ...
                // ... fill the cache with values around the requested row
                cacheRows(row-halfLookAhead, qMin(m_count, row+halfLookAhead));
            } else {
                // ... otherwise append new values to the cache until the requested row is reached
                while (row > m_rows.lastIndex()) {
                    m_rows.append(fetchRow(m_rows.lastIndex()+1));
                }
            }
        } else if (row < m_rows.firstIndex()) { // If a row before the first valid index in cache is requested ...
            if (m_rows.firstIndex() - row > lookAhead) { // ... and the distance is larger than the look ahead ...
                // ... fill the cache with values around the requested row
                cacheRows(qMax(0, row-halfLookAhead), row+halfLookAhead);
            } else {
                // ... otherwise prepend new values to the cache until the requested row is reached
                while (row < m_rows.firstIndex()) {
                    m_rows.prepend(fetchRow(m_rows.firstIndex()-1));
                }
            }
        }

        // If the number of cached item has changed, emit the signal
        if (oldCachedItemCount != m_rows.count())
            emit cachedItemCountChanged();

        // Return the Image object for the requested row
        return QVariant::fromValue(m_rows.at(row));
    }

    QString ImageModel::itemType(const QVariantList &indexPath)
    {
        Q_UNUSED(indexPath);

        // This model provides only items, no headers
        return QString();
    }

    int ImageModel::cachedItemCount() const
    {
        return m_rows.count();
    }

    void ImageModel::cacheRows(int from, int to) const
    {
        /**
         * We simply fill the cache with new values for the given range, where the
         * construction of the new values is encapsulated in the fetchRow() method.
         */
        for (int i = from; i <= to; ++i)
            m_rows.insert(i, fetchRow(i));
    }

    Image ImageModel::fetchRow(int position) const
    {
        Q_UNUSED(position);

        return Image(QUrl(QString::fromLatin1("asset:///images/text%1.png").arg(position%10)));
    }