summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2010-08-26 10:04:08 +1000
committerMichael Brasser <michael.brasser@nokia.com>2010-08-26 10:04:08 +1000
commit2960b5d0d1ea21c3a716962329e02a1a44198505 (patch)
treef3623b6531cc8c6397f90433efa516a9938cf55a
Initial commit of QObjectListModel.
-rw-r--r--qobjectlistmodel.cpp351
-rw-r--r--qobjectlistmodel.h106
2 files changed, 457 insertions, 0 deletions
diff --git a/qobjectlistmodel.cpp b/qobjectlistmodel.cpp
new file mode 100644
index 0000000..d438ef0
--- /dev/null
+++ b/qobjectlistmodel.cpp
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML project on Qt Labs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 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."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qobjectlistmodel.h"
+
+/*!
+ \class QObjectListModel
+ \brief The QObjectListModel class provides a model that supplies objects to QML views.
+
+ QObjectListModel provides a more powerful, but still easy to use, alternative to using
+ QObjectList lists as models for QML views. As a QAbstractListModel, it has the ability to
+ automatically notify the view of specific changes to the list, such as adding or removing
+ items. At the same time it provides QList-like convenience functions such as append, at,
+ and removeAt for easily working with the model from C++.
+
+ \code
+ QObjectListModel model;
+ model.setObjectList(myQList);
+ model.append(myNewObject);
+ ...
+ int pos = model.indexOf(myObject);
+ model.insert(pos, myOtherNewObject);
+ ...
+ model.removeAt(0);
+ \endcode
+
+ QObjectListModel exposes a single \c object role to QML,
+ as well as a \c count property, and a \c get(int i) function.
+
+ \qml
+ ListView {
+ ...
+ delegate: Text { text: object.someProperty }
+ }
+ \endqml
+*/
+
+/*!
+ Constructs an object list model with the given \a parent.
+*/
+QObjectListModel::QObjectListModel(QObject *parent) :
+ QAbstractListModel(parent)
+{
+ QHash<int, QByteArray> roles;
+ roles[ObjectRole] = "object";
+ setRoleNames(roles);
+}
+
+/*!
+ Constructs an object list model containing the specified \a objects
+ with the given \a parent.
+*/
+QObjectListModel::QObjectListModel(QObjectList objects, QObject *parent) :
+ QAbstractListModel(parent), m_objects(objects)
+{
+ QHash<int, QByteArray> roles;
+ roles[ObjectRole] = "object";
+ setRoleNames(roles);
+}
+
+/*!
+ Returns data for the specified \a role, from the item with the
+ given \a index. The only valid role is \c ObjectRole.
+
+ If the view requests an invalid index or role, an invalid variant
+ is returned.
+*/
+QVariant QObjectListModel::data(const QModelIndex &index, int role) const
+{
+ if (index.row() < 0 || index.row() >= m_objects.size())
+ return QVariant();
+
+ if (role == ObjectRole)
+ return QVariant::fromValue(m_objects.at(index.row()));
+
+ return QVariant();
+}
+
+/*!
+ Returns the number of rows in the model. This value corresponds to the
+ number of items in the model's internal object list.
+*/
+int QObjectListModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return count();
+}
+
+/*!
+ Returns the object list used by the model to store data.
+*/
+QObjectList QObjectListModel::objectList() const
+{
+ return m_objects;
+}
+
+/*!
+ Sets the model's internal objects list to \a objects. The model will
+ notify any attached views that its underlying data has changed.
+*/
+void QObjectListModel::setObjectList(QObjectList objects)
+{
+ int oldCount = m_objects.count();
+ beginResetModel();
+ m_objects = objects;
+ endResetModel();
+ emit dataChanged(index(0), index(m_objects.count()));
+ if (m_objects.count() != oldCount)
+ emit countChanged();
+}
+
+/*!
+ Inserts \a object at the end of the model and notifies any views.
+
+ This is the same as model.insert(size(), \a object).
+
+ \sa insert()
+*/
+void QObjectListModel::append(QObject *object)
+{
+ beginInsertRows(QModelIndex(), m_objects.count(), m_objects.count());
+ m_objects.append(object);
+ endInsertRows();
+ emit countChanged();
+}
+
+/*!
+ \overload
+ Appends the items of the \a objects list to this model and notifies any views.
+*/
+void QObjectListModel::append(const QObjectList &objects)
+{
+ beginInsertRows(QModelIndex(), m_objects.count(), m_objects.count()+objects.count());
+ m_objects.append(objects);
+ endInsertRows();
+ emit countChanged();
+}
+
+/*!
+ Inserts \a object at index position \a i in the model and notifies
+ any views. If \a i is 0, the object is prepended to the model. If \a i
+ is size(), the object is appended to the list.
+
+ \sa append(), replace(), removeAt()
+*/
+void QObjectListModel::insert(int i, QObject *object)
+{
+ beginInsertRows(QModelIndex(), i, i);
+ m_objects.insert(i, object);
+ endInsertRows();
+ emit countChanged();
+}
+
+/*!
+ \overload
+ Inserts the items of the \a objects list at index position \a i in the model
+ and notifies any views. If \a i is 0, the items are prepended to the model. If \a i
+ is size(), the items are appended to the list.
+*/
+void QObjectListModel::insert(int i, const QObjectList &objects)
+{
+ beginInsertRows(QModelIndex(), i, i+objects.count());
+ for (int j = objects.count() - 1; j > -1; --j)
+ m_objects.insert(i, objects.at(j));
+ endInsertRows();
+ emit countChanged();
+}
+
+/*!
+ Replaces the item at index position \a i with \a object and
+ notifies any views. \a i must be a valid index position in the list
+ (i.e., 0 <= \a i < size()).
+
+ \sa removeAt()
+*/
+void QObjectListModel::replace(int i, QObject *object)
+{
+ m_objects.replace(i, object);
+ emit dataChanged(index(i), index(i));
+}
+
+/*!
+ Moves the item at index position \a from to index position \a to
+ and notifies any views.
+
+ This function
+ assumes that both \a from and \a to are at least 0 but less than
+ size(). To avoid failure, test that both \a from and \a to are at
+ least 0 and less than size().
+*/
+
+void QObjectListModel::move(int from, int to)
+{
+ beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
+ m_objects.move(from, to);
+ endMoveRows();
+}
+
+/*!
+ Removes \a count number of items from index position \a i and notifies any views.
+ \a i must be a valid index position in the model (i.e., 0 <= \a i < size()), as
+ must \c{i + count}.
+
+ \sa takeAt()
+*/
+void QObjectListModel::removeAt(int i, int count)
+{
+ beginRemoveRows(QModelIndex(), i, i + count);
+ for (int j = 0; j < count; ++j)
+ m_objects.removeAt(i);
+ endRemoveRows();
+ emit countChanged();
+}
+
+/*!
+ Removes the item at index position \a i (notifying any views) and returns it.
+ \a i must be a valid index position in the model (i.e., 0 <= \a i < size()).
+
+ \sa removeAt()
+*/
+QObject *QObjectListModel::takeAt(int i)
+{
+ beginRemoveRows(QModelIndex(), i, i);
+ QObject *obj = m_objects.takeAt(i);
+ endRemoveRows();
+ emit countChanged();
+ return obj;
+}
+
+/*!
+ Removes all items from the model and notifies any views.
+*/
+void QObjectListModel::clear()
+{
+ beginRemoveRows(QModelIndex(), 0, m_objects.count());
+ m_objects.clear();
+ endRemoveRows();
+ emit countChanged();
+}
+
+/*!
+ \internal
+ For usage from QML.
+*/
+QObject *QObjectListModel::get(int i) const
+{
+ return m_objects.at(i);
+}
+
+/*!
+ \fn int QObjectListModel::size() const
+
+ Returns the number of items in the model.
+
+ \sa isEmpty(), count()
+*/
+
+/*! \fn int QObjectListModel::count() const
+
+ Returns the number of items in the model. This is effectively the
+ same as size().
+*/
+
+/*! \fn bool QObjectListModel::isEmpty() const
+
+ Returns true if the model contains no items; otherwise returns
+ false.
+
+ \sa size()
+*/
+
+/*! \fn QObject *QObjectListModel::at(int i) const
+
+ Returns the object at index position \a i in the list. \a i must be
+ a valid index position in the model (i.e., 0 <= \a i < size()).
+
+ \sa operator[]()
+*/
+
+/*! \fn QObject *QObjectListModel::operator[](int i) const
+
+ \overload
+
+ Same as at().
+*/
+
+/*! \fn int QObjectListModel::indexOf(QObject *object, int from = 0) const
+
+ Returns the index position of the first occurrence of \a object in
+ the model, searching forward from index position \a from. Returns
+ -1 if no item matched.
+
+ \sa lastIndexOf(), contains()
+*/
+
+/*! \fn int QObjectListModel::lastIndexOf(QObject *object, int from = -1) const
+
+ Returns the index position of the last occurrence of \a object in
+ the list, searching backward from index position \a from. If \a
+ from is -1 (the default), the search starts at the last item.
+ Returns -1 if no item matched.
+
+ \sa indexOf()
+*/
+
+/*! \fn bool QObjectListModel::contains(Object *object) const
+
+ Returns true if the list contains an occurrence of \a object;
+ otherwise returns false.
+
+ \sa indexOf(), count()
+*/
+
+
diff --git a/qobjectlistmodel.h b/qobjectlistmodel.h
new file mode 100644
index 0000000..9e8a24c
--- /dev/null
+++ b/qobjectlistmodel.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML project on Qt Labs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 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."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOBJECTLISTMODEL_H
+#define QOBJECTLISTMODEL_H
+
+#include <QAbstractListModel>
+
+/*
+ Open issues:
+ object ownership: is it helpful for the model to own the objects?
+ can we guard the objects so they are automatically removed
+ from the model when deleted?
+ add additional QList convenience functions (operator<<, etc.)
+*/
+
+class QObjectListModel : public QAbstractListModel
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+public:
+ explicit QObjectListModel(QObject *parent = 0);
+ QObjectListModel(QObjectList objects, QObject *parent = 0);
+
+ //model API
+ enum Roles { ObjectRole = Qt::UserRole+1 };
+
+ int rowCount(const QModelIndex &parent) const;
+ QVariant data(const QModelIndex &index, int role) const;
+
+ QObjectList objectList() const;
+ void setObjectList(QObjectList objects);
+
+ //list API
+ void append(QObject *object);
+ void append(const QObjectList &objects);
+ void insert(int i, QObject *object);
+ void insert(int i, const QObjectList &objects);
+
+ inline QObject *at(int i) const { return m_objects.at(i); }
+ inline QObject *operator[](int i) const { return m_objects[i]; }
+ void replace(int i, QObject *object);
+
+ void move(int from, int to);
+
+ void removeAt(int i, int count = 1);
+ QObject *takeAt(int i);
+ void clear();
+
+ inline bool contains(QObject *object) const { return m_objects.contains(object); }
+ inline int indexOf (QObject *object, int from = 0) const { return m_objects.indexOf(object, from); }
+ inline int lastIndexOf (QObject *object, int from = -1) const { return m_objects.lastIndexOf(object, from); }
+
+ inline int count() const { return m_objects.count(); }
+ inline int size() const { return m_objects.size(); }
+ inline bool isEmpty() const { return m_objects.isEmpty(); }
+
+ //additional QML API
+ Q_INVOKABLE QObject *get(int i) const;
+
+Q_SIGNALS:
+ void countChanged();
+
+private:
+ Q_DISABLE_COPY(QObjectListModel)
+ QObjectList m_objects;
+};
+
+#endif // QOBJECTMODEL_H