summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/extra/qmlxmllistmodel.cpp407
-rw-r--r--src/declarative/extra/qmlxmllistmodel.h5
-rw-r--r--src/declarative/fx/qfxgridview.cpp158
-rw-r--r--src/declarative/fx/qfxgridview.h2
-rw-r--r--src/declarative/fx/qfxlistview.cpp181
-rw-r--r--src/declarative/fx/qfxlistview.h2
-rw-r--r--src/declarative/fx/qfxpathview.cpp14
-rw-r--r--src/declarative/fx/qfxpathview.h2
-rw-r--r--src/declarative/fx/qfxpathview_p.h3
-rw-r--r--src/declarative/fx/qfxvisualitemmodel.cpp178
-rw-r--r--src/declarative/fx/qfxvisualitemmodel.h13
-rw-r--r--src/declarative/util/qmlpackage.cpp5
12 files changed, 603 insertions, 367 deletions
diff --git a/src/declarative/extra/qmlxmllistmodel.cpp b/src/declarative/extra/qmlxmllistmodel.cpp
index bba817d..3732323 100644
--- a/src/declarative/extra/qmlxmllistmodel.cpp
+++ b/src/declarative/extra/qmlxmllistmodel.cpp
@@ -45,6 +45,10 @@
#include <QtDeclarative/qmlcontext.h>
#include <QtDeclarative/qmlengine.h>
#include <QDebug>
+#include <QApplication>
+#include <QThread>
+#include <QMutex>
+#include <QWaitCondition>
#include <QXmlQuery>
#include <QXmlResultItems>
#include <QXmlNodeModelIndex>
@@ -57,6 +61,197 @@ QT_BEGIN_NAMESPACE
QML_DEFINE_TYPE(XmlListModelRole, Role);
QML_DEFINE_TYPE(QmlXmlListModel, XmlListModel);
+
+class QmlXmlListModelPrivate;
+struct QmlXmlRoleList : public QmlConcreteList<XmlListModelRole *>
+{
+ QmlXmlRoleList(QmlXmlListModelPrivate *p)
+ : model(p) {}
+ virtual void append(XmlListModelRole *role);
+ //XXX clear, removeAt, and insert need to invalidate any cached data (in data table) as well
+ // (and the model should emit the appropriate signals)
+ virtual void clear();
+ virtual void removeAt(int i);
+ virtual void insert(int i, XmlListModelRole *role);
+
+ QmlXmlListModelPrivate *model;
+};
+
+
+
+class QmlXmlQuery : public QThread
+{
+ Q_OBJECT
+public:
+ QmlXmlQuery(QObject *parent=0)
+ : QThread(parent), m_quit(false), m_restart(false), m_abort(false), m_queryId(0) {
+ }
+ ~QmlXmlQuery() {
+ m_mutex.lock();
+ m_quit = true;
+ m_condition.wakeOne();
+ m_mutex.unlock();
+
+ wait();
+ }
+
+ void abort() {
+ QMutexLocker locker(&m_mutex);
+ m_abort = true;
+ }
+
+ int doQuery(QString query, QString namespaces, QByteArray data, QmlXmlRoleList *roleObjects) {
+ QMutexLocker locker(&m_mutex);
+ m_modelData.clear();
+ m_size = 0;
+ m_data = data;
+ m_query = query;
+ m_namespaces = namespaces;
+ m_roleObjects = roleObjects;
+ if (!isRunning()) {
+ m_abort = false;
+ start();
+ } else {
+ m_restart = true;
+ m_condition.wakeOne();
+ }
+ m_queryId++;
+ return m_queryId;
+ }
+
+ QList<QList<QVariant> > modelData() {
+ QMutexLocker locker(&m_mutex);
+ return m_modelData;
+ }
+
+signals:
+ void queryCompleted(int queryId, int size);
+
+protected:
+ void run() {
+ while (!m_quit) {
+ m_mutex.lock();
+ int queryId = m_queryId;
+ doQueryJob();
+ if (m_size > 0)
+ doSubQueryJob();
+ m_data.clear(); // no longer needed
+ m_mutex.unlock();
+
+ m_mutex.lock();
+ if (!m_abort && m_size > 0)
+ emit queryCompleted(queryId, m_size);
+ if (!m_restart)
+ m_condition.wait(&m_mutex);
+ m_abort = false;
+ m_restart = false;
+ m_mutex.unlock();
+ }
+ }
+
+private:
+ void doQueryJob();
+ void doSubQueryJob();
+
+private:
+ QMutex m_mutex;
+ QWaitCondition m_condition;
+ bool m_quit;
+ bool m_restart;
+ bool m_abort;
+ QByteArray m_data;
+ QString m_query;
+ QString m_namespaces;
+ QString m_prefix;
+ int m_size;
+ int m_queryId;
+ const QmlXmlRoleList *m_roleObjects;
+ QList<QList<QVariant> > m_modelData;
+};
+
+void QmlXmlQuery::doQueryJob()
+{
+ QString r;
+ QXmlQuery query;
+ QBuffer buffer(&m_data);
+ buffer.open(QIODevice::ReadOnly);
+ query.bindVariable(QLatin1String("src"), &buffer);
+ query.setQuery(m_namespaces + m_query);
+ query.evaluateTo(&r);
+
+ //qDebug() << r;
+
+ //always need a single root element
+ QByteArray xml = "<dummy:items xmlns:dummy=\"http://qtsotware.com/dummy\">\n" + r.toUtf8() + "</dummy:items>";
+ QBuffer b(&xml);
+ b.open(QIODevice::ReadOnly);
+ //qDebug() << xml;
+
+ QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + m_namespaces;
+ QString prefix = QLatin1String("doc($inputDocument)/dummy:items") +
+ m_query.mid(m_query.lastIndexOf(QLatin1Char('/')));
+
+ //figure out how many items we are dealing with
+ int count = -1;
+ {
+ QXmlResultItems result;
+ QXmlQuery countquery;
+ countquery.bindVariable(QLatin1String("inputDocument"), &b);
+ countquery.setQuery(namespaces + QLatin1String("count(") + prefix + QLatin1String(")"));
+ countquery.evaluateTo(&result);
+ QXmlItem item(result.next());
+ if (item.isAtomicValue())
+ count = item.toAtomicValue().toInt();
+ prefix += QLatin1String("[%1]/");
+ }
+ //qDebug() << count;
+
+ m_prefix = namespaces + prefix;
+ m_data = xml;
+ if (count > 0)
+ m_size = count;
+}
+
+void QmlXmlQuery::doSubQueryJob()
+{
+ m_modelData.clear();
+
+ QBuffer b(&m_data);
+ b.open(QIODevice::ReadOnly);
+
+ QXmlQuery subquery;
+ subquery.bindVariable(QLatin1String("inputDocument"), &b);
+
+ //XXX should we use an array of objects or something else rather than a table?
+ for (int j = 0; j < m_size; ++j) {
+ QList<QVariant> resultList;
+ for (int i = 0; i < m_roleObjects->size(); ++i) {
+ XmlListModelRole *role = m_roleObjects->at(i);
+ subquery.setQuery(m_prefix.arg(j+1) + role->query());
+ if (role->isStringList()) {
+ QStringList data;
+ subquery.evaluateTo(&data);
+ resultList << QVariant(data);
+ //qDebug() << data;
+ } else {
+ QString s;
+ subquery.evaluateTo(&s);
+ if (role->isCData()) {
+ //un-escape
+ s.replace(QLatin1String("&lt;"), QLatin1String("<"));
+ s.replace(QLatin1String("&gt;"), QLatin1String(">"));
+ s.replace(QLatin1String("&amp;"), QLatin1String("&"));
+ }
+ resultList << s.trimmed();
+ //qDebug() << s;
+ }
+ b.seek(0);
+ }
+ m_modelData << resultList;
+ }
+}
+
+
//TODO: do something smart while waiting for data to load
// error handling (currently quite fragile)
// profile doQuery and doSubquery
@@ -64,6 +259,59 @@ QML_DEFINE_TYPE(QmlXmlListModel, XmlListModel);
// support complex/nested objects?
// how do we handle data updates (like rss feed -- usually items inserted at beginning)
+
+class QmlXmlListModelPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlXmlListModel)
+public:
+ QmlXmlListModelPrivate()
+ : isClassComplete(false), size(-1), highestRole(Qt::UserRole)
+ , reply(0), queryId(-1), roleObjects(this) {}
+
+ bool isClassComplete;
+ QString src;
+ QString query;
+ QString namespaces;
+ int size;
+ QList<int> roles;
+ QStringList roleNames;
+ int highestRole;
+ QNetworkReply *reply;
+ QmlXmlQuery qmlXmlQuery;
+ int queryId;
+ QmlXmlRoleList roleObjects;
+ QList<QList<QVariant> > data;
+};
+
+
+void QmlXmlRoleList::append(XmlListModelRole *role) {
+ QmlConcreteList<XmlListModelRole *>::append(role);
+ model->roles << model->highestRole;
+ model->roleNames << role->name();
+ ++model->highestRole;
+}
+//XXX clear, removeAt, and insert need to invalidate any cached data (in data table) as well
+// (and the model should emit the appropriate signals)
+void QmlXmlRoleList::clear()
+{
+ model->roles.clear();
+ model->roleNames.clear();
+ QmlConcreteList<XmlListModelRole *>::clear();
+}
+void QmlXmlRoleList::removeAt(int i)
+{
+ model->roles.removeAt(i);
+ model->roleNames.removeAt(i);
+ QmlConcreteList<XmlListModelRole *>::removeAt(i);
+}
+void QmlXmlRoleList::insert(int i, XmlListModelRole *role)
+{
+ QmlConcreteList<XmlListModelRole *>::insert(i, role);
+ model->roles.insert(i, model->highestRole);
+ model->roleNames.insert(i, role->name());
+ ++model->highestRole;
+}
+
/*!
\qmlclass XmlListModel
\brief The XmlListModel class allows you to specify a model using XQuery.
@@ -86,71 +334,17 @@ QML_DEFINE_TYPE(QmlXmlListModel, XmlListModel);
\note The model is currently static, so the above is really just a snapshot of an RSS feed.
*/
-class QmlXmlListModelPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QmlXmlListModel)
-public:
- QmlXmlListModelPrivate() : isClassComplete(false), size(-1), highestRole(Qt::UserRole), reply(0), roleObjects(this) {}
-
- bool isClassComplete;
- QString src;
- QString query;
- QString namespaces;
- QList<int> roles;
- QStringList roleNames;
- mutable QList<QList<QVariant> > data;
- int size;
- int highestRole;
- QNetworkReply *reply;
- mutable QByteArray xml;
- QString prefix;
-
- struct RoleList : public QmlConcreteList<XmlListModelRole *>
- {
- RoleList(QmlXmlListModelPrivate *p)
- : model(p) {}
- virtual void append(XmlListModelRole *role) {
- QmlConcreteList<XmlListModelRole *>::append(role);
- model->roles << model->highestRole;
- model->roleNames << role->name();
- ++model->highestRole;
- }
- //XXX clear, removeAt, and insert need to invalidate any cached data (in data table) as well
- // (and the model should emit the appropriate signals)
- virtual void clear()
- {
- model->roles.clear();
- model->roleNames.clear();
- QmlConcreteList<XmlListModelRole *>::clear();
- }
- virtual void removeAt(int i)
- {
- model->roles.removeAt(i);
- model->roleNames.removeAt(i);
- QmlConcreteList<XmlListModelRole *>::removeAt(i);
- }
- virtual void insert(int i, XmlListModelRole *role)
- {
- QmlConcreteList<XmlListModelRole *>::insert(i, role);
- model->roles.insert(i, model->highestRole);
- model->roleNames.insert(i, role->name());
- ++model->highestRole;
- }
-
- QmlXmlListModelPrivate *model;
- };
-
- RoleList roleObjects;
-};
-
QmlXmlListModel::QmlXmlListModel(QObject *parent)
: QListModelInterface(*(new QmlXmlListModelPrivate), parent)
{
Q_D(QmlXmlListModel);
+ connect(&d->qmlXmlQuery, SIGNAL(queryCompleted(int,int)),
+ this, SLOT(queryCompleted(int,int)));
}
QmlXmlListModel::~QmlXmlListModel()
{
+ Q_D(QmlXmlListModel);
}
QmlList<XmlListModelRole *> *QmlXmlListModel::roleObjects()
@@ -163,10 +357,6 @@ QHash<int,QVariant> QmlXmlListModel::data(int index, const QList<int> &roles) co
{
Q_D(const QmlXmlListModel);
QHash<int, QVariant> rv;
-
- if (index > d->data.count() - 1)
- doSubquery(index);
-
for (int i = 0; i < roles.size(); ++i) {
int role = roles.at(i);
int roleIndex = d->roles.indexOf(role);
@@ -255,6 +445,9 @@ void QmlXmlListModel::reload()
if (!d->isClassComplete)
return;
+ d->qmlXmlQuery.abort();
+ d->queryId = -1;
+
//clear existing data
d->size = 0;
int count = d->data.count();
@@ -288,98 +481,24 @@ void QmlXmlListModel::requestFinished()
d->reply = 0;
} else {
QByteArray data = d->reply->readAll();
- doQuery(data);
+ d->queryId = d->qmlXmlQuery.doQuery(d->query, d->namespaces, data, &d->roleObjects);
d->reply->deleteLater();
d->reply = 0;
}
}
-void QmlXmlListModel::doQuery(QByteArray &rawData)
+void QmlXmlListModel::queryCompleted(int id, int size)
{
Q_D(QmlXmlListModel);
- QString r;
- QXmlQuery query;
- QBuffer rawBuffer(&rawData);
- rawBuffer.open(QIODevice::ReadOnly);
- query.bindVariable(QLatin1String("src"), &rawBuffer);
- query.setQuery(d->namespaces + d->query);
- query.evaluateTo(&r);
- //qDebug() << r;
-
- //always need a single root element
- QByteArray xml = "<dummy:items xmlns:dummy=\"http://qtsotware.com/dummy\">\n" + r.toUtf8() + "</dummy:items>";
- QBuffer b(&xml);
- b.open(QIODevice::ReadOnly);
- //qDebug() << xml;
-
- QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + d->namespaces;
- QString prefix = QLatin1String("doc($inputDocument)/dummy:items") +
- d->query.mid(d->query.lastIndexOf(QLatin1Char('/')));
-
- //figure out how many items we are dealing with
- int count = -1;
- {
- QXmlResultItems result;
- QXmlQuery countquery;
- countquery.bindVariable(QLatin1String("inputDocument"), &b);
- countquery.setQuery(namespaces + QLatin1String("count(") + prefix + QLatin1String(")"));
- countquery.evaluateTo(&result);
- QXmlItem item(result.next());
- if (item.isAtomicValue())
- count = item.toAtomicValue().toInt();
- b.seek(0);
- prefix += QLatin1String("[%1]/");
+ if (id != d->queryId)
+ return;
+ d->size = size;
+ if (size > 0) {
+ d->data = d->qmlXmlQuery.modelData();
+ emit itemsInserted(0, d->size);
}
- //qDebug() << count;
-
- QXmlQuery subquery;
- subquery.bindVariable(QLatin1String("inputDocument"), &b);
- d->prefix = namespaces + prefix;
- d->xml = xml;
-
- d->size = count;
-
- if (count > 0)
- emit itemsInserted(0, count);
}
-void QmlXmlListModel::doSubquery(int index) const
-{
- Q_D(const QmlXmlListModel);
- //qDebug() << "doSubQuery" << index;
- QBuffer b(&d->xml);
- b.open(QIODevice::ReadOnly);
-
- QXmlQuery subquery;
- subquery.bindVariable(QLatin1String("inputDocument"), &b);
-
- //XXX should we use an array of objects or something else rather than a table?
- for (int j = d->data.count(); j <= index; ++j) {
- QList<QVariant> resultList;
- for (int i = 0; i < d->roleObjects.size(); ++i) {
- XmlListModelRole *role = d->roleObjects.at(i);
- subquery.setQuery(d->prefix.arg(j+1) + role->query());
- if (role->isStringList()) {
- QStringList data;
- subquery.evaluateTo(&data);
- resultList << QVariant(data);
- //qDebug() << data;
- } else {
- QString s;
- subquery.evaluateTo(&s);
- if (role->isCData()) {
- //un-escape
- s.replace(QLatin1String("&lt;"), QLatin1String("<"));
- s.replace(QLatin1String("&gt;"), QLatin1String(">"));
- s.replace(QLatin1String("&amp;"), QLatin1String("&"));
- }
- resultList << s.trimmed();
- //qDebug() << s;
- }
- b.seek(0);
- }
- d->data << resultList;
- }
-}
+#include "qmlxmllistmodel.moc"
QT_END_NAMESPACE
diff --git a/src/declarative/extra/qmlxmllistmodel.h b/src/declarative/extra/qmlxmllistmodel.h
index 9371448..f837040 100644
--- a/src/declarative/extra/qmlxmllistmodel.h
+++ b/src/declarative/extra/qmlxmllistmodel.h
@@ -120,12 +120,9 @@ public:
public Q_SLOTS:
void reload();
-protected:
- void doQuery(QByteArray &rawData);
- void doSubquery(int index) const;
-
private Q_SLOTS:
void requestFinished();
+ void queryCompleted(int,int);
private:
Q_DECLARE_PRIVATE(QmlXmlListModel)
diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp
index 876172d..c14408a 100644
--- a/src/declarative/fx/qfxgridview.cpp
+++ b/src/declarative/fx/qfxgridview.cpp
@@ -121,9 +121,9 @@ public:
qreal rowPos() const { return (view->flow() == QFxGridView::LeftToRight ? item->y() : item->x()); }
qreal colPos() const { return (view->flow() == QFxGridView::LeftToRight ? item->x() : item->y()); }
qreal endRowPos() const {
- return (view->flow() == QFxGridView::LeftToRight
- ? item->y() + (item->height() > 0 ? item->height() : 1)
- : item->x() + (item->width() > 0 ? item->width() : 1)) - 1;
+ return view->flow() == QFxGridView::LeftToRight
+ ? item->y() + view->cellHeight() - 1
+ : item->x() + view->cellWidth() - 1;
}
void setPosition(qreal col, qreal row) {
if (view->flow() == QFxGridView::LeftToRight) {
@@ -149,7 +149,7 @@ public:
QFxGridViewPrivate()
: model(0), currentItem(0), tmpCurrent(0), flow(QFxGridView::LeftToRight)
, visiblePos(0), visibleIndex(0) , currentIndex(-1)
- , cellWidth(100), cellHeight(100), columns(1)
+ , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1)
, highlightComponent(0), highlight(0), trackedItem(0)
, moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0)
, keyPressed(false), ownModel(false), wrap(false), autoHighlight(true)
@@ -157,13 +157,14 @@ public:
void init();
void clear();
- FxGridItem *getItem(int modelIndex);
FxGridItem *createItem(int modelIndex);
void releaseItem(FxGridItem *item);
void refill(qreal from, qreal to);
void updateGrid();
void layout(bool removed=false);
+ void updateUnrequestedIndexes();
+ void updateUnrequestedPositions();
void updateTrackedItem();
void createHighlight();
void updateHighlight();
@@ -290,6 +291,7 @@ public:
QFxVisualItemModel *model;
QVariant modelVariant;
QList<FxGridItem*> visibleItems;
+ QHash<QFxItem*,int> unrequestedItems;
FxGridItem *currentItem;
QFxItem *tmpCurrent;
QFxGridView::Flow flow;
@@ -299,6 +301,7 @@ public:
int cellWidth;
int cellHeight;
int columns;
+ int requestedIndex;
QmlComponent *highlightComponent;
FxGridItem *highlight;
FxGridItem *trackedItem;
@@ -330,29 +333,18 @@ void QFxGridViewPrivate::clear()
visibleItems.clear();
visiblePos = 0;
visibleIndex = 0;
- if (currentItem) {
- FxGridItem *tmpItem = currentItem;
- currentItem = 0;
- currentIndex = -1;
- releaseItem(tmpItem);
- }
+ releaseItem(currentItem);
+ currentItem = 0;
+ currentIndex = -1;
createHighlight();
trackedItem = 0;
}
-FxGridItem *QFxGridViewPrivate::getItem(int modelIndex)
-{
- if (currentItem && modelIndex == currentIndex)
- return currentItem;
- if (FxGridItem *listItem = visibleItem(modelIndex))
- return listItem;
- return createItem(modelIndex);
-}
-
FxGridItem *QFxGridViewPrivate::createItem(int modelIndex)
{
Q_Q(QFxGridView);
// create object
+ requestedIndex = modelIndex;
FxGridItem *listItem = 0;
if (QFxItem *item = model->item(modelIndex, false)) {
listItem = new FxGridItem(item, q);
@@ -362,6 +354,7 @@ FxGridItem *QFxGridViewPrivate::createItem(int modelIndex)
listItem->item->setZ(modelIndex + 1);
listItem->item->setParent(q->viewport());
}
+ requestedIndex = 0;
return listItem;
}
@@ -369,15 +362,18 @@ FxGridItem *QFxGridViewPrivate::createItem(int modelIndex)
void QFxGridViewPrivate::releaseItem(FxGridItem *item)
{
Q_Q(QFxGridView);
- if (item != currentItem) {
- if (trackedItem == item) {
- QObject::disconnect(trackedItem->item, SIGNAL(topChanged()), q, SLOT(trackedPositionChanged()));
- QObject::disconnect(trackedItem->item, SIGNAL(leftChanged()), q, SLOT(trackedPositionChanged()));
- trackedItem = 0;
- }
- model->release(item->item);
- delete item;
+ if (!item)
+ return;
+ if (trackedItem == item) {
+ QObject::disconnect(trackedItem->item, SIGNAL(topChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, SIGNAL(leftChanged()), q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
}
+ if (model->release(item->item) == 0) {
+ // item was not destroyed, and we no longer reference it.
+ unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+ }
+ delete item;
}
void QFxGridViewPrivate::refill(qreal from, qreal to)
@@ -409,7 +405,7 @@ void QFxGridViewPrivate::refill(qreal from, qreal to)
FxGridItem *item = 0;
while (modelIndex < model->count() && rowPos <= to) {
//qDebug() << "refill: append item" << modelIndex;
- if (!(item = getItem(modelIndex)))
+ if (!(item = createItem(modelIndex)))
break;
item->setPosition(colPos, rowPos);
visibleItems.append(item);
@@ -432,7 +428,7 @@ void QFxGridViewPrivate::refill(qreal from, qreal to)
}
while (visibleIndex > 0 && rowPos + rowSize() - 1 >= from){
//qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
- if (!(item = getItem(visibleIndex-1)))
+ if (!(item = createItem(visibleIndex-1)))
break;
--visibleIndex;
item->setPosition(colPos, rowPos);
@@ -518,6 +514,28 @@ void QFxGridViewPrivate::layout(bool removed)
q->setViewportWidth(endPosition() - startPosition());
fixupX();
}
+ updateUnrequestedPositions();
+}
+
+void QFxGridViewPrivate::updateUnrequestedIndexes()
+{
+ Q_Q(QFxGridView);
+ QHash<QFxItem*,int>::iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
+ *it = model->indexOf(it.key(), q);
+}
+
+void QFxGridViewPrivate::updateUnrequestedPositions()
+{
+ QHash<QFxItem*,int>::const_iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
+ qDebug() << "pos of" << (*it) << colPosAt(*it) << rowPosAt(*it);
+ if (flow == QFxGridView::LeftToRight) {
+ it.key()->setPos(QPointF(colPosAt(*it), rowPosAt(*it)));
+ } else {
+ it.key()->setPos(QPointF(rowPosAt(*it), colPosAt(*it)));
+ }
+ }
}
void QFxGridViewPrivate::updateTrackedItem()
@@ -606,11 +624,11 @@ void QFxGridViewPrivate::updateCurrent(int modelIndex)
Q_Q(QFxGridView);
if (!isValid() || modelIndex < 0 || modelIndex >= model->count()) {
if (currentItem) {
- FxGridItem *item = currentItem;
+ currentItem->attached->setIsCurrentItem(false);
+ releaseItem(currentItem);
currentItem = 0;
- currentIndex = 0;
+ currentIndex = -1;
updateHighlight();
- releaseItem(item);
emit q->currentIndexChanged();
}
return;
@@ -625,28 +643,21 @@ void QFxGridViewPrivate::updateCurrent(int modelIndex)
delete tmpCurrent;
tmpCurrent = 0;
}
- int oldCurrentIndex = currentIndex;
FxGridItem *oldCurrentItem = currentItem;
- currentIndex = -1;
- currentItem = visibleItem(modelIndex);
- if (!currentItem) {
- currentItem = getItem(modelIndex);
- if (currentItem)
- currentItem->setPosition(colPosAt(modelIndex), rowPosAt(modelIndex));
- }
currentIndex = modelIndex;
+ currentItem = createItem(modelIndex);
+ qDebug() << "got current" << currentItem->item;
fixCurrentVisibility = true;
if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
oldCurrentItem->attached->setIsCurrentItem(false);
if (currentItem) {
+ currentItem->setPosition(colPosAt(modelIndex), rowPosAt(modelIndex));
currentItem->item->setFocus(true);
currentItem->attached->setIsCurrentItem(true);
}
updateHighlight();
emit q->currentIndexChanged();
- // Release the old current item
- if (oldCurrentItem && !visibleItem(oldCurrentIndex))
- releaseItem(oldCurrentItem);
+ releaseItem(oldCurrentItem);
}
//----------------------------------------------------------------------------
@@ -711,6 +722,8 @@ void QFxGridView::setModel(const QVariant &model)
if (d->model) {
disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*)));
+ disconnect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*)));
}
d->clear();
d->modelVariant = model;
@@ -736,6 +749,8 @@ void QFxGridView::setModel(const QVariant &model)
d->updateCurrent(d->currentIndex);
connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*)));
+ connect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*)));
refill();
emit countChanged();
}
@@ -1182,7 +1197,7 @@ void QFxGridView::itemsInserted(int modelIndex, int count)
d->visibleIndex += count;
for (int i = 0; i < d->visibleItems.count(); ++i) {
FxGridItem *listItem = d->visibleItems.at(i);
- if (listItem->index != -1 && listItem != d->currentItem)
+ if (listItem->index != -1)
listItem->index += count;
}
}
@@ -1258,10 +1273,8 @@ void QFxGridView::itemsInserted(int modelIndex, int count)
// Update the indexes of the following visible items.
for (; index < d->visibleItems.count(); ++index) {
FxGridItem *listItem = d->visibleItems.at(index);
- if (listItem != d->currentItem) {
- if (listItem->index != -1)
- listItem->index += count;
- }
+ if (listItem->index != -1)
+ listItem->index += count;
}
}
// everything is in order now - emit add() signal
@@ -1274,7 +1287,7 @@ void QFxGridView::itemsInserted(int modelIndex, int count)
void QFxGridView::itemsRemoved(int modelIndex, int count)
{
Q_D(QFxGridView);
-
+ qDebug() << "QFxGridView::itemsRemoved";
int index = d->mapFromModel(modelIndex);
if (index == -1) {
if (modelIndex + count - 1 < d->visibleIndex) {
@@ -1282,7 +1295,7 @@ void QFxGridView::itemsRemoved(int modelIndex, int count)
d->visibleIndex -= count;
for (int i = 0; i < d->visibleItems.count(); ++i) {
FxGridItem *listItem = d->visibleItems.at(i);
- if (listItem->index != -1 && listItem != d->currentItem)
+ if (listItem->index != -1)
listItem->index -= count;
}
}
@@ -1292,11 +1305,8 @@ void QFxGridView::itemsRemoved(int modelIndex, int count)
d->currentItem->index -= count;
} else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
// current item has been removed.
- if (d->currentItem) {
- FxGridItem *item = d->currentItem;
- d->currentItem = 0;
- d->releaseItem(item);
- }
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
d->currentIndex = -1;
d->updateCurrent(qMin(modelIndex, d->model->count()-1));
}
@@ -1305,6 +1315,8 @@ void QFxGridView::itemsRemoved(int modelIndex, int count)
return;
}
+ qDebug() << "release gridview";
+
// Remove the items from the visible list, skipping anything already marked for removal
QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
while (it != d->visibleItems.end()) {
@@ -1314,8 +1326,7 @@ void QFxGridView::itemsRemoved(int modelIndex, int count)
++it;
} else if (item->index >= modelIndex + count) {
// after removed items
- if (item != d->currentItem)
- item->index -= count;
+ item->index -= count;
++it;
} else {
// removed item
@@ -1338,11 +1349,9 @@ void QFxGridView::itemsRemoved(int modelIndex, int count)
d->currentItem->index -= count;
} else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
// current item has been removed.
- if (d->currentItem && !d->currentItem->attached->delayRemove()) {
- FxGridItem *item = d->currentItem;
- d->currentItem = 0;
- d->releaseItem(item);
- }
+ qDebug() << "release current" << d->currentItem;
+ d->releaseItem(d->currentItem);
+ qDebug() << "done";
d->currentItem = 0;
d->currentIndex = -1;
d->updateCurrent(qMin(modelIndex, d->model->count()-1));
@@ -1385,6 +1394,29 @@ void QFxGridView::destroyRemoved()
d->layout();
}
+void QFxGridView::createdItem(int index, QFxItem *item)
+{
+ Q_D(QFxGridView);
+ item->setItemParent(this);
+ if (d->requestedIndex != index) {
+ qDebug() << "Added unrequested" << index;
+ item->setItemParent(this);
+ d->unrequestedItems.insert(item, index);
+ if (d->flow == QFxGridView::LeftToRight) {
+ item->setPos(QPointF(d->colPosAt(index), d->rowPosAt(index)));
+ } else {
+ item->setPos(QPointF(d->rowPosAt(index), d->colPosAt(index)));
+ }
+ }
+}
+
+void QFxGridView::destroyingItem(QFxItem *item)
+{
+ Q_D(QFxGridView);
+ d->unrequestedItems.remove(item);
+}
+
+
void QFxGridView::refill()
{
Q_D(QFxGridView);
diff --git a/src/declarative/fx/qfxgridview.h b/src/declarative/fx/qfxgridview.h
index ff08831..99c7cff 100644
--- a/src/declarative/fx/qfxgridview.h
+++ b/src/declarative/fx/qfxgridview.h
@@ -131,6 +131,8 @@ private Q_SLOTS:
void itemsInserted(int index, int count);
void itemsRemoved(int index, int count);
void destroyRemoved();
+ void createdItem(int index, QFxItem *item);
+ void destroyingItem(QFxItem *item);
void sizeChange();
private:
diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp
index 46166e2..27f7ff1 100644
--- a/src/declarative/fx/qfxlistview.cpp
+++ b/src/declarative/fx/qfxlistview.cpp
@@ -171,15 +171,14 @@ public:
QFxListViewPrivate()
: model(0), currentItem(0), tmpCurrent(0), orient(Qt::Vertical)
, visiblePos(0), visibleIndex(0)
- , averageSize(100), currentIndex(-1), currItemMode(QFxListView::Free)
- , snapPos(0), highlightComponent(0), highlight(0), trackedItem(0)
+ , averageSize(100), currentIndex(-1), requestedIndex(-1)
+ , currItemMode(QFxListView::Free), snapPos(0), highlightComponent(0), highlight(0), trackedItem(0)
, moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0)
, keyPressed(false), ownModel(false), wrap(false), autoHighlight(true)
, fixCurrentVisibility(false) {}
void init();
void clear();
- FxListItem *getItem(int modelIndex);
FxListItem *createItem(int modelIndex);
void releaseItem(FxListItem *item);
@@ -333,6 +332,8 @@ public:
void refill(qreal from, qreal to);
void layout();
+ void updateUnrequestedIndexes();
+ void updateUnrequestedPositions();
void updateTrackedItem();
void createHighlight();
void updateHighlight();
@@ -347,6 +348,7 @@ public:
QFxVisualItemModel *model;
QVariant modelVariant;
QList<FxListItem*> visibleItems;
+ QHash<QFxItem*,int> unrequestedItems;
FxListItem *currentItem;
QFxItem *tmpCurrent;
Qt::Orientation orient;
@@ -354,6 +356,7 @@ public:
int visibleIndex;
qreal averageSize;
int currentIndex;
+ int requestedIndex;
QFxListView::CurrentItemPositioning currItemMode;
int snapPos;
QmlComponent *highlightComponent;
@@ -390,29 +393,18 @@ void QFxListViewPrivate::clear()
visibleItems.clear();
visiblePos = 0;
visibleIndex = 0;
- if (currentItem) {
- FxListItem *tmpItem = currentItem;
- currentItem = 0;
- currentIndex = -1;
- releaseItem(tmpItem);
- }
+ releaseItem(currentItem);
+ currentItem = 0;
+ currentIndex = -1;
createHighlight();
trackedItem = 0;
}
-FxListItem *QFxListViewPrivate::getItem(int modelIndex)
-{
- if (currentItem && modelIndex == currentIndex)
- return currentItem;
- if (FxListItem *listItem = visibleItem(modelIndex))
- return listItem;
- return createItem(modelIndex);
-}
-
FxListItem *QFxListViewPrivate::createItem(int modelIndex)
{
Q_Q(QFxListView);
// create object
+ requestedIndex = modelIndex;
FxListItem *listItem = 0;
if (QFxItem *item = model->item(modelIndex, false)) {
listItem = new FxListItem(item, q);
@@ -438,6 +430,7 @@ FxListItem *QFxListViewPrivate::createItem(int modelIndex)
else
QObject::connect(listItem->item, SIGNAL(widthChanged()), q, SLOT(itemResized()));
}
+ requestedIndex = -1;
return listItem;
}
@@ -445,21 +438,24 @@ FxListItem *QFxListViewPrivate::createItem(int modelIndex)
void QFxListViewPrivate::releaseItem(FxListItem *item)
{
Q_Q(QFxListView);
- if (item != currentItem) {
- if (orient == Qt::Vertical)
- QObject::disconnect(item->item, SIGNAL(heightChanged()), q, SLOT(itemResized()));
- else
- QObject::disconnect(item->item, SIGNAL(widthChanged()), q, SLOT(itemResized()));
- if (trackedItem == item) {
- const char *notifier1 = orient == Qt::Vertical ? SIGNAL(topChanged()) : SIGNAL(leftChanged());
- const char *notifier2 = orient == Qt::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
- QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
- QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
- trackedItem = 0;
- }
- model->release(item->item);
- delete item;
+ if (!item)
+ return;
+ if (orient == Qt::Vertical)
+ QObject::disconnect(item->item, SIGNAL(heightChanged()), q, SLOT(itemResized()));
+ else
+ QObject::disconnect(item->item, SIGNAL(widthChanged()), q, SLOT(itemResized()));
+ if (trackedItem == item) {
+ const char *notifier1 = orient == Qt::Vertical ? SIGNAL(topChanged()) : SIGNAL(leftChanged());
+ const char *notifier2 = orient == Qt::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
+ QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
}
+ if (model->release(item->item) == 0) {
+ // item was not destroyed, and we no longer reference it.
+ unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+ }
+ delete item;
}
void QFxListViewPrivate::refill(qreal from, qreal to)
@@ -485,7 +481,7 @@ void QFxListViewPrivate::refill(qreal from, qreal to)
int pos = itemEnd + 1;
while (modelIndex < model->count() && pos <= to) {
//qDebug() << "refill: append item" << modelIndex;
- if (!(item = getItem(modelIndex)))
+ if (!(item = createItem(modelIndex)))
break;
item->setPosition(pos);
pos += item->size();
@@ -495,7 +491,7 @@ void QFxListViewPrivate::refill(qreal from, qreal to)
}
while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > from) {
//qDebug() << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos;
- if (!(item = getItem(visibleIndex-1)))
+ if (!(item = createItem(visibleIndex-1)))
break;
--visibleIndex;
visiblePos -= item->size();
@@ -562,6 +558,29 @@ void QFxListViewPrivate::layout()
fixupX();
q->setViewportWidth(endPosition() - startPosition());
}
+ updateUnrequestedPositions();
+}
+
+void QFxListViewPrivate::updateUnrequestedIndexes()
+{
+ Q_Q(QFxListView);
+ QHash<QFxItem*,int>::iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
+ *it = model->indexOf(it.key(), q);
+}
+
+void QFxListViewPrivate::updateUnrequestedPositions()
+{
+ QHash<QFxItem*,int>::const_iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
+ qDebug() << "pos of" << (*it) << positionAt(*it);
+ if (visibleItem(*it))
+ continue;
+ if (orient == Qt::Vertical)
+ it.key()->setY(positionAt(*it));
+ else
+ it.key()->setX(positionAt(*it));
+ }
}
void QFxListViewPrivate::updateTrackedItem()
@@ -695,13 +714,11 @@ void QFxListViewPrivate::updateCurrent(int modelIndex)
Q_Q(QFxListView);
if (!isValid() || modelIndex < 0 || modelIndex >= model->count()) {
if (currentItem) {
- FxListItem *item = currentItem;
- int index = currentIndex;
+ currentItem->attached->setIsCurrentItem(false);
+ releaseItem(currentItem);
currentItem = 0;
- currentIndex = 0;
+ currentIndex = -1;
updateHighlight();
- if (!visibleItem(index))
- releaseItem(item);
emit q->currentIndexChanged();
}
return;
@@ -716,40 +733,28 @@ void QFxListViewPrivate::updateCurrent(int modelIndex)
delete tmpCurrent;
tmpCurrent = 0;
}
- int oldCurrentIndex = currentIndex;
FxListItem *oldCurrentItem = currentItem;
- currentIndex = -1;
- currentItem = visibleItem(modelIndex);
- if (!currentItem) {
- currentItem = getItem(modelIndex);
- if (currentItem) {
- if (modelIndex == visibleIndex - 1) {
- // We can calculate exact postion in this case
- currentItem->setPosition(visibleItems.first()->position() - currentItem->size());
- } else {
- // Create current item now and position as best we can.
- // Its position will be corrected when it becomes visible.
- currentItem->setPosition(positionAt(modelIndex));
- }
- }
- }
currentIndex = modelIndex;
+ currentItem = createItem(modelIndex);
fixCurrentVisibility = true;
if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
oldCurrentItem->attached->setIsCurrentItem(false);
if (currentItem) {
+ if (modelIndex == visibleIndex - 1) {
+ // We can calculate exact postion in this case
+ currentItem->setPosition(visibleItems.first()->position() - currentItem->size());
+ } else {
+ // Create current item now and position as best we can.
+ // Its position will be corrected when it becomes visible.
+ currentItem->setPosition(positionAt(modelIndex));
+ }
currentItem->item->setFocus(true);
currentItem->attached->setIsCurrentItem(true);
}
updateHighlight();
emit q->currentIndexChanged();
// Release the old current item
- if (oldCurrentItem && !visibleItem(oldCurrentIndex)) {
- if (!currentItem || oldCurrentItem->item == currentItem->item)
- delete oldCurrentItem;
- else
- releaseItem(oldCurrentItem);
- }
+ releaseItem(oldCurrentItem);
}
void QFxListViewPrivate::updateAverage()
@@ -884,6 +889,8 @@ void QFxListView::setModel(const QVariant &model)
if (d->model) {
disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*)));
+ disconnect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*)));
}
d->clear();
d->modelVariant = model;
@@ -909,6 +916,8 @@ void QFxListView::setModel(const QVariant &model)
d->updateCurrent(d->currentIndex);
connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*)));
+ connect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*)));
refill();
emit countChanged();
}
@@ -1417,6 +1426,7 @@ void QFxListView::itemResized()
void QFxListView::itemsInserted(int modelIndex, int count)
{
Q_D(QFxListView);
+ d->updateUnrequestedIndexes();
if (!d->visibleItems.count() || d->model->count() <= 1) {
d->layout();
d->updateCurrent(qMax(0, qMin(d->currentIndex, d->model->count()-1)));
@@ -1437,7 +1447,7 @@ void QFxListView::itemsInserted(int modelIndex, int count)
d->visibleIndex += count;
for (int i = 0; i < d->visibleItems.count(); ++i) {
FxListItem *listItem = d->visibleItems.at(i);
- if (listItem->index != -1 && listItem != d->currentItem)
+ if (listItem->index != -1)
listItem->index += count;
}
}
@@ -1487,29 +1497,29 @@ void QFxListView::itemsInserted(int modelIndex, int count)
// Update the indexes of the following visible items.
for (; index < d->visibleItems.count(); ++index) {
FxListItem *listItem = d->visibleItems.at(index);
- if (listItem != d->currentItem) {
- listItem->setPosition(listItem->position() + (pos - initialPos));
- if (listItem->index != -1)
- listItem->index += count;
- }
+ listItem->setPosition(listItem->position() + (pos - initialPos));
+ if (listItem->index != -1)
+ listItem->index += count;
}
}
// everything is in order now - emit add() signal
for (int j = 0; j < added.count(); ++j)
added.at(j)->attached->emitAdd();
+ d->updateUnrequestedPositions();
emit countChanged();
}
void QFxListView::itemsRemoved(int modelIndex, int count)
{
Q_D(QFxListView);
+ d->updateUnrequestedIndexes();
if (!d->mapRangeFromModel(modelIndex, count)) {
if (modelIndex + count - 1 < d->visibleIndex) {
// Items removed before our visible items.
d->visibleIndex -= count;
for (int i = 0; i < d->visibleItems.count(); ++i) {
FxListItem *listItem = d->visibleItems.at(i);
- if (listItem->index != -1 && listItem != d->currentItem)
+ if (listItem->index != -1)
listItem->index -= count;
}
}
@@ -1519,11 +1529,8 @@ void QFxListView::itemsRemoved(int modelIndex, int count)
d->currentItem->index -= count;
} else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
// current item has been removed.
- if (d->currentItem) {
- FxListItem *item = d->currentItem;
- d->currentItem = 0;
- d->releaseItem(item);
- }
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
d->currentIndex = -1;
d->updateCurrent(qMin(modelIndex, d->model->count()-1));
}
@@ -1541,8 +1548,7 @@ void QFxListView::itemsRemoved(int modelIndex, int count)
++it;
} else if (item->index >= modelIndex + count) {
// after removed items
- if (item != d->currentItem)
- item->index -= count;
+ item->index -= count;
++it;
} else {
// removed item
@@ -1565,11 +1571,7 @@ void QFxListView::itemsRemoved(int modelIndex, int count)
d->currentItem->index -= count;
} else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
// current item has been removed.
- if (d->currentItem && !d->currentItem->attached->delayRemove()) {
- FxListItem *item = d->currentItem;
- d->currentItem = 0;
- d->releaseItem(item);
- }
+ d->releaseItem(d->currentItem);
d->currentItem = 0;
d->currentIndex = -1;
d->updateCurrent(qMin(modelIndex, d->model->count()-1));
@@ -1618,6 +1620,25 @@ void QFxListView::destroyRemoved()
d->layout();
}
+void QFxListView::createdItem(int index, QFxItem *item)
+{
+ Q_D(QFxListView);
+ if (d->requestedIndex != index) {
+ item->setItemParent(viewport());
+ d->unrequestedItems.insert(item, index);
+ if (d->orient == Qt::Vertical)
+ item->setY(d->positionAt(index));
+ else
+ item->setX(d->positionAt(index));
+ }
+}
+
+void QFxListView::destroyingItem(QFxItem *item)
+{
+ Q_D(QFxListView);
+ d->unrequestedItems.remove(item);
+}
+
QObject *QFxListView::qmlAttachedProperties(QObject *obj)
{
return QFxListViewAttached::properties(obj);
diff --git a/src/declarative/fx/qfxlistview.h b/src/declarative/fx/qfxlistview.h
index 6bf2b54..87a851b 100644
--- a/src/declarative/fx/qfxlistview.h
+++ b/src/declarative/fx/qfxlistview.h
@@ -141,6 +141,8 @@ private Q_SLOTS:
void itemsInserted(int index, int count);
void itemsRemoved(int index, int count);
void destroyRemoved();
+ void createdItem(int index, QFxItem *item);
+ void destroyingItem(QFxItem *item);
};
QML_DECLARE_TYPE(QFxListView);
diff --git a/src/declarative/fx/qfxpathview.cpp b/src/declarative/fx/qfxpathview.cpp
index b7215cf..b1c78e9 100644
--- a/src/declarative/fx/qfxpathview.cpp
+++ b/src/declarative/fx/qfxpathview.cpp
@@ -159,7 +159,7 @@ void QFxPathView::setModel(const QVariant &model)
if (d->model) {
disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
- disconnect(d->model, SIGNAL(itemCreated(int, QFxItem*)), this, SLOT(itemCreated(int,QFxItem*)));
+ disconnect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*)));
for (int i=0; i<d->items.count(); i++){
QFxItem *p = d->items[i];
d->model->release(p);
@@ -186,7 +186,7 @@ void QFxPathView::setModel(const QVariant &model)
if (d->model) {
connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
- connect(d->model, SIGNAL(itemCreated(int, QFxItem*)), this, SLOT(itemCreated(int,QFxItem*)));
+ connect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*)));
}
d->firstIndex = 0;
d->pathOffset = 0;
@@ -559,9 +559,10 @@ bool QFxPathView::mouseFilter(QGraphicsSceneMouseEvent *e)
void QFxPathViewPrivate::regenerate()
{
Q_Q(QFxPathView);
+ qDebug() << "relaease all pathview";
for (int i=0; i<items.count(); i++){
QFxItem *p = items[i];
- model->release(p);
+ releaseItem(p);
}
items.clear();
@@ -634,7 +635,7 @@ void QFxPathView::refill()
while(wrapIndex-- >= 0){
QFxItem* p = d->items.takeFirst();
d->updateItem(p, 0.0);
- d->model->release(p);
+ d->releaseItem(p);
d->firstIndex++;
d->firstIndex %= d->model->count();
int index = (d->firstIndex + d->items.count())%d->model->count();
@@ -647,7 +648,7 @@ void QFxPathView::refill()
while(wrapIndex++ < d->items.count()-1){
QFxItem* p = d->items.takeLast();
d->updateItem(p, 1.0);
- d->model->release(p);
+ d->releaseItem(p);
d->firstIndex--;
if (d->firstIndex < 0)
d->firstIndex = d->model->count() - 1;
@@ -698,6 +699,7 @@ void QFxPathView::itemsInserted(int modelIndex, int count)
void QFxPathView::itemsRemoved(int modelIndex, int count)
{
+ qDebug() << "QFxPathView::itemsRemoved";
//XXX support animated removal
Q_D(QFxPathView);
if (!d->isValid())
@@ -733,7 +735,7 @@ void QFxPathView::itemsRemoved(int modelIndex, int count)
d->moveOffset.setValue(targetOffset);
}
-void QFxPathView::itemCreated(int index, QFxItem *item)
+void QFxPathView::createdItem(int index, QFxItem *item)
{
Q_D(QFxPathView);
if (d->requestedIndex != index) {
diff --git a/src/declarative/fx/qfxpathview.h b/src/declarative/fx/qfxpathview.h
index 32e03b8..33db566 100644
--- a/src/declarative/fx/qfxpathview.h
+++ b/src/declarative/fx/qfxpathview.h
@@ -115,7 +115,7 @@ private Q_SLOTS:
void ticked();
void itemsInserted(int index, int count);
void itemsRemoved(int index, int count);
- void itemCreated(int index, QFxItem *item);
+ void createdItem(int index, QFxItem *item);
void destroyingItem(QFxItem *item);
protected:
diff --git a/src/declarative/fx/qfxpathview_p.h b/src/declarative/fx/qfxpathview_p.h
index 358daf6..b5c5ba2 100644
--- a/src/declarative/fx/qfxpathview_p.h
+++ b/src/declarative/fx/qfxpathview_p.h
@@ -101,6 +101,9 @@ public:
requestedIndex = -1;
return item;
}
+ void releaseItem(QFxItem *item) {
+ model->release(item);
+ }
bool isValid() const {
return model && model->count() > 0 && model->delegate() && path;
diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp
index 533917e..c631d33 100644
--- a/src/declarative/fx/qfxvisualitemmodel.cpp
+++ b/src/declarative/fx/qfxvisualitemmodel.cpp
@@ -73,9 +73,53 @@ public:
QList<int> m_roles;
QHash<int,QString> m_roleNames;
- QHash<int, QObject *> m_cache;
+ struct ObjectRef {
+ ObjectRef(QObject *object=0) : obj(object), ref(1) {}
+ QObject *obj;
+ int ref;
+ };
+ class Cache : public QHash<int, ObjectRef> {
+ public:
+ QObject *getItem(int index) {
+ QObject *item = 0;
+ QHash<int,ObjectRef>::iterator it = find(index);
+ if (it != end()) {
+ (*it).ref++;
+ item = (*it).obj;
+ qDebug() << "ref" << item << (*it).ref;
+ }
+ return item;
+ }
+ QObject *item(int index) {
+ QObject *item = 0;
+ QHash<int, ObjectRef>::const_iterator it = find(index);
+ if (it != end())
+ item = (*it).obj;
+ return item;
+ }
+ void insertItem(int index, QObject *obj) {
+ insert(index, ObjectRef(obj));
+ }
+ bool releaseItem(QObject *obj) {
+ QHash<int, ObjectRef>::iterator it = begin();
+ for (; it != end(); ++it) {
+ ObjectRef &objRef = *it;
+ if (objRef.obj == obj) {
+ if (--objRef.ref == 0) {
+ erase(it);
+ qDebug() << "released item" << obj << "item count" << count();
+ return true;
+ }
+ qDebug() << "not releasing" << obj << "ref" << objRef.ref;
+ break;
+ }
+ }
+ return false;
+ }
+ };
+
+ Cache m_cache;
QHash<QObject *, QmlPackage*> m_packaged;
- QHash<QmlPackage*, int> m_packageRef;
QFxVisualItemModelParts *m_parts;
friend class QFxVisualItemParts;
@@ -337,8 +381,8 @@ void QFxVisualItemModel::setModel(const QVariant &model)
this, SIGNAL(itemsRemoved(int,int)));
QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
this, SIGNAL(itemsMoved(int,int,int)));
- QObject::disconnect(d->m_visualItemModel, SIGNAL(packageCreated(int,QmlPackage*)),
- this, SLOT(_q_packageCreated(int,QmlPackage*)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(createdPackage(int,QmlPackage*)),
+ this, SLOT(_q_createdPackage(int,QmlPackage*)));
QObject::disconnect(d->m_visualItemModel, SIGNAL(destroyingPackage(QmlPackage*)),
this, SLOT(_q_destroyingPackage(QmlPackage*)));
d->m_visualItemModel = 0;
@@ -390,8 +434,8 @@ void QFxVisualItemModel::setModel(const QVariant &model)
this, SIGNAL(itemsRemoved(int,int)));
QObject::connect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
this, SIGNAL(itemsMoved(int,int,int)));
- QObject::connect(d->m_visualItemModel, SIGNAL(packageCreated(int,QmlPackage*)),
- this, SLOT(_q_packageCreated(int,QmlPackage*)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(createdPackage(int,QmlPackage*)),
+ this, SLOT(_q_createdPackage(int,QmlPackage*)));
QObject::connect(d->m_visualItemModel, SIGNAL(destroyingPackage(QmlPackage*)),
this, SLOT(_q_destroyingPackage(QmlPackage*)));
return;
@@ -445,41 +489,39 @@ QFxItem *QFxVisualItemModel::item(int index, bool complete)
return item(index, QByteArray(), complete);
}
-void QFxVisualItemModel::release(QFxItem *item)
+/*
+ Returns ReleaseStatus flags.
+*/
+QFxVisualItemModel::ReleaseFlags QFxVisualItemModel::release(QFxItem *item)
{
Q_D(QFxVisualItemModel);
- if (d->m_visualItemModel) {
- d->m_visualItemModel->release(item);
- return;
- }
- item->setItemParent(0);
- QObject *obj = item;
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->release(item);
+ ReleaseFlags stat = 0;
+ QObject *obj = item;
bool inPackage = false;
- if (QmlPackage *package = d->m_packaged.value(item)) {
- static_cast<QObject*>(item)->setParent(package);
- d->m_packaged.remove(item);
- //XXX Inefficient
- for (QHash<QObject *, QmlPackage *>::Iterator iter = d->m_packaged.begin();
- iter != d->m_packaged.end(); ++iter) {
- if (*iter == package)
- return;
- }
+
+ QHash<QObject*,QmlPackage*>::iterator it = d->m_packaged.find(item);
+ if (it != d->m_packaged.end()) {
+ QmlPackage *package = *it;
+ d->m_packaged.erase(it);
+ if (d->m_packaged.contains(item))
+ stat |= Referenced;
inPackage = true;
obj = package; // fall through and delete
}
- //XXX Inefficient
- for (QHash<int, QObject *>::Iterator iter = d->m_cache.begin();
- iter != d->m_cache.end(); ++iter) {
- if (*iter == obj) {
- if (inPackage)
- emit destroyingPackage(qobject_cast<QmlPackage*>(obj));
- delete obj;
- d->m_cache.erase(iter);
- return;
- }
+ if (d->m_cache.releaseItem(obj)) {
+ if (inPackage)
+ emit destroyingPackage(qobject_cast<QmlPackage*>(obj));
+ stat |= Destroyed;
+ delete obj;
+ } else if (!inPackage) {
+ stat |= Referenced;
}
+
+ return stat;
}
QObject *QFxVisualItemModel::parts()
@@ -499,10 +541,8 @@ QFxItem *QFxVisualItemModel::item(int index, const QByteArray &viewId, bool comp
if (d->modelCount() <= 0 || !d->m_delegate)
return 0;
- QObject *nobj = 0;
- if (d->m_cache.contains(index)) {
- nobj = d->m_cache[index];
- } else {
+ QObject *nobj = d->m_cache.getItem(index);
+ if (!nobj) {
QmlContext *ccontext = d->m_context;
if (!ccontext) ccontext = qmlContext(this);
QmlContext *ctxt = new QmlContext(ccontext);
@@ -515,8 +555,9 @@ QFxItem *QFxVisualItemModel::item(int index, const QByteArray &viewId, bool comp
if (nobj) {
ctxt->setParent(nobj);
data->setParent(nobj);
-
- d->m_cache.insert(index, nobj);
+ d->m_cache.insertItem(index, nobj);
+ if (QmlPackage *package = qobject_cast<QmlPackage *>(nobj))
+ emit createdPackage(index, package);
} else {
delete data;
delete ctxt;
@@ -529,8 +570,7 @@ QFxItem *QFxVisualItemModel::item(int index, const QByteArray &viewId, bool comp
if (package) {
QObject *o = package->part(QLatin1String(viewId));
item = qobject_cast<QFxItem *>(o);
- d->m_packaged[o] = package;
- emit packageCreated(index, package);
+ d->m_packaged.insertMulti(item, package);
}
}
@@ -558,8 +598,8 @@ QVariant QFxVisualItemModel::evaluate(int index, const QString &expression, QObj
return QVariant();
QVariant value;
- if (d->m_cache.contains(index)) {
- QObject *nobj = d->m_cache[index];
+ QObject *nobj = d->m_cache.item(index);
+ if (nobj) {
QFxItem *item = qobject_cast<QFxItem *>(nobj);
if (item) {
QmlExpression e(qmlContext(item), expression, objectContext);
@@ -582,6 +622,16 @@ QVariant QFxVisualItemModel::evaluate(int index, const QString &expression, QObj
return value;
}
+int QFxVisualItemModel::indexOf(QFxItem *item, QObject *objectContext) const
+{
+ QmlExpression e(qmlContext(item), "index", objectContext);
+ e.setTrackChange(false);
+ QVariant value = e.value();
+ if (value.isValid())
+ return value.toInt();
+ return -1;
+}
+
void QFxVisualItemModel::_q_itemsChanged(int index, int count,
const QList<int> &roles)
{
@@ -589,9 +639,7 @@ void QFxVisualItemModel::_q_itemsChanged(int index, int count,
// XXX - highly inefficient
for (int ii = index; ii < index + count; ++ii) {
- if (d->m_cache.contains(ii)) {
-
- QObject *item = d->m_cache[ii];
+ if (QObject *item = d->m_cache.item(ii)) {
QFxVisualItemModelData *data = d->data(item);
for (int prop = 0; prop < data->count(); ++prop) {
@@ -615,18 +663,18 @@ void QFxVisualItemModel::_q_itemsInserted(int index, int count)
{
Q_D(QFxVisualItemModel);
// XXX - highly inefficient
- QHash<int, QObject *> items;
- for (QHash<int, QObject *>::Iterator iter = d->m_cache.begin();
+ QHash<int,QFxVisualItemModelPrivate::ObjectRef> items;
+ for (QHash<int,QFxVisualItemModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
iter != d->m_cache.end(); ) {
if (iter.key() >= index) {
- QObject *item = *iter;
+ QFxVisualItemModelPrivate::ObjectRef objRef = *iter;
int index = iter.key() + count;
iter = d->m_cache.erase(iter);
- items.insert(index, item);
+ items.insert(index, objRef);
- QFxVisualItemModelData *data = d->data(item);
+ QFxVisualItemModelData *data = d->data(objRef.obj);
data->setIndex(index);
} else {
++iter;
@@ -641,21 +689,21 @@ void QFxVisualItemModel::_q_itemsRemoved(int index, int count)
{
Q_D(QFxVisualItemModel);
// XXX - highly inefficient
- QHash<int, QObject *> items;
- for (QHash<int, QObject *>::Iterator iter = d->m_cache.begin();
+ QHash<int, QFxVisualItemModelPrivate::ObjectRef> items;
+ for (QHash<int, QFxVisualItemModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
iter != d->m_cache.end(); ) {
if (iter.key() >= index && iter.key() < index + count) {
- QObject *item = *iter;
+ QFxVisualItemModelPrivate::ObjectRef objRef = *iter;
iter = d->m_cache.erase(iter);
- items.insertMulti(-1, item); //XXX perhaps better to maintain separately
- QFxVisualItemModelData *data = d->data(item);
+ items.insertMulti(-1, objRef); //XXX perhaps better to maintain separately
+ QFxVisualItemModelData *data = d->data(objRef.obj);
data->setIndex(-1);
} else if (iter.key() >= index + count) {
- QObject *item = *iter;
+ QFxVisualItemModelPrivate::ObjectRef objRef = *iter;
int index = iter.key() - count;
iter = d->m_cache.erase(iter);
- items.insert(index, item);
- QFxVisualItemModelData *data = d->data(item);
+ items.insert(index, objRef);
+ QFxVisualItemModelData *data = d->data(objRef.obj);
data->setIndex(index);
} else {
++iter;
@@ -670,18 +718,18 @@ void QFxVisualItemModel::_q_itemsMoved(int from, int to, int count)
{
Q_D(QFxVisualItemModel);
// XXX - highly inefficient
- QHash<int, QObject *> items;
- for (QHash<int, QObject *>::Iterator iter = d->m_cache.begin();
+ QHash<int,QFxVisualItemModelPrivate::ObjectRef> items;
+ for (QHash<int,QFxVisualItemModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
iter != d->m_cache.end(); ) {
if (iter.key() >= from && iter.key() < from + count) {
- QObject *item = *iter;
+ QFxVisualItemModelPrivate::ObjectRef objRef = *iter;
int index = iter.key() - from + to;
iter = d->m_cache.erase(iter);
- items.insert(index, item);
+ items.insert(index, objRef);
- QFxVisualItemModelData *data = d->data(item);
+ QFxVisualItemModelData *data = d->data(objRef.obj);
data->setIndex(index);
} else {
++iter;
@@ -708,10 +756,10 @@ void QFxVisualItemModel::_q_dataChanged(const QModelIndex &begin, const QModelIn
_q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
}
-void QFxVisualItemModel::_q_packageCreated(int index, QmlPackage *package)
+void QFxVisualItemModel::_q_createdPackage(int index, QmlPackage *package)
{
Q_D(QFxVisualItemModel);
- emit itemCreated(index, qobject_cast<QFxItem*>(package->part(d->m_part)));
+ emit createdItem(index, qobject_cast<QFxItem*>(package->part(d->m_part)));
}
void QFxVisualItemModel::_q_destroyingPackage(QmlPackage *package)
diff --git a/src/declarative/fx/qfxvisualitemmodel.h b/src/declarative/fx/qfxvisualitemmodel.h
index 586d837..622065c 100644
--- a/src/declarative/fx/qfxvisualitemmodel.h
+++ b/src/declarative/fx/qfxvisualitemmodel.h
@@ -86,21 +86,26 @@ public:
QString part() const;
void setPart(const QString &);
+ enum ReleaseFlag { Referenced = 0x01, Destroyed = 0x02 };
+ Q_DECLARE_FLAGS(ReleaseFlags, ReleaseFlag)
+
int count() const;
QFxItem *item(int index, bool complete=true);
QFxItem *item(int index, const QByteArray &, bool complete=true);
- void release(QFxItem *item);
+ ReleaseFlags release(QFxItem *item);
void completeItem();
QVariant evaluate(int index, const QString &expression, QObject *objectContext);
+ int indexOf(QFxItem *item, QObject *objectContext) const;
+
QObject *parts();
Q_SIGNALS:
void itemsInserted(int index, int count);
void itemsRemoved(int index, int count);
void itemsMoved(int from, int to, int count);
- void itemCreated(int index, QFxItem *item);
- void packageCreated(int index, QmlPackage *package);
+ void createdItem(int index, QFxItem *item);
+ void createdPackage(int index, QmlPackage *package);
void destroyingItem(QFxItem *item);
void destroyingPackage(QmlPackage *package);
@@ -112,7 +117,7 @@ private Q_SLOTS:
void _q_rowsInserted(const QModelIndex &,int,int);
void _q_rowsRemoved(const QModelIndex &,int,int);
void _q_dataChanged(const QModelIndex&,const QModelIndex&);
- void _q_packageCreated(int index, QmlPackage *package);
+ void _q_createdPackage(int index, QmlPackage *package);
void _q_destroyingPackage(QmlPackage *package);
private:
diff --git a/src/declarative/util/qmlpackage.cpp b/src/declarative/util/qmlpackage.cpp
index aa7ed38..bfad44c 100644
--- a/src/declarative/util/qmlpackage.cpp
+++ b/src/declarative/util/qmlpackage.cpp
@@ -98,6 +98,11 @@ QmlPackage::QmlPackage(QObject *parent)
QmlPackage::~QmlPackage()
{
+ Q_D(QmlPackage);
+ for (int ii = 0; ii < d->dataList.count(); ++ii) {
+ QObject *obj = d->dataList.at(ii);
+ delete obj;
+ }
}
QmlList<QObject *> *QmlPackage::data()