diff --git a/examples/declarative/particles/custom/blurparticles.qml b/examples/declarative/particles/custom/blurparticles.qml
index 8a3e9ad80398e2501726379e95fb5c53d4a1998e..15da9ba9dbd74568643e3b7b32c776b819278a53 100644
--- a/examples/declarative/particles/custom/blurparticles.qml
+++ b/examples/declarative/particles/custom/blurparticles.qml
@@ -1,3 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $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$
+**
+****************************************************************************/
+
 import QtQuick 2.0
 import QtQuick.Particles 2.0
 
diff --git a/examples/declarative/particles/custom/content/particle.png b/examples/declarative/particles/custom/content/particle.png
new file mode 100644
index 0000000000000000000000000000000000000000..5c83896d22cdc3c352ff8db97b0b1f2cd2b27125
Binary files /dev/null and b/examples/declarative/particles/custom/content/particle.png differ
diff --git a/examples/declarative/particles/custom/fireworks.qml b/examples/declarative/particles/custom/fireworks.qml
new file mode 100644
index 0000000000000000000000000000000000000000..edd4accfdf44cba532e9a2be4bc4016dc3ce8ee6
--- /dev/null
+++ b/examples/declarative/particles/custom/fireworks.qml
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $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$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Particles 2.0
+
+Rectangle{
+    width: 360
+    height: 600
+    color: "black"
+    ParticleSystem{
+        id: otherSys
+        anchors.fill: parent
+        Emitter{
+            id: emitter
+            emitting: false
+            emitRate: 100
+            lifeSpan: 1000
+            emitCap: 1000
+            speed: AngledDirection{angleVariation:180; magnitudeVariation: 60}
+        }
+
+        ImageParticle{
+            source: "content/particle.png"
+        }
+    }
+    Component{
+        id: firework
+        Item{
+            id: container
+            width: 48
+            height: 48
+            Image{
+                width: 48
+                height: 48
+                id: img
+                source: "content/particle.png"
+            }
+            Timer{
+                interval: 1000 + 4000*Math.random()
+                running: true
+                repeat: false
+                onTriggered: {
+                    img.visible = false;
+                    emitter.burst(100, container.x+24, container.y+24);
+                }
+            }
+        }
+    }
+    ParticleSystem{
+        anchors.fill: parent
+        Emitter{
+            width: parent.width
+            y: parent.height
+            emitRate: 2
+            lifeSpan: 6000
+            speed: PointDirection{y:-100}
+        }
+        ItemParticle{
+            delegate: firework
+        }
+    }
+}
+
diff --git a/src/declarative/particles/qsgitemparticle.cpp b/src/declarative/particles/qsgitemparticle.cpp
index 819c82315538254e075c3e112f719d9231ed5d66..498dd90a8724cc297131a18b5ca4c0cc8241e55b 100644
--- a/src/declarative/particles/qsgitemparticle.cpp
+++ b/src/declarative/particles/qsgitemparticle.cpp
@@ -42,14 +42,22 @@
 #include "qsgitemparticle_p.h"
 #include <QtDeclarative/private/qsgvisualitemmodel_p.h>
 #include <qsgnode.h>
+#include <QTimer>
+#include <QDeclarativeComponent>
 #include <QDebug>
 
 QT_BEGIN_NAMESPACE
 
 QSGItemParticle::QSGItemParticle(QSGItem *parent) :
-    QSGParticlePainter(parent), m_fade(true)
+    QSGParticlePainter(parent), m_fade(true), m_delegate(0)
 {
     setFlag(QSGItem::ItemHasContents);
+    QTimer* manageDelegates = new QTimer(this);//TODO: don't leak
+    connect(manageDelegates, SIGNAL(timeout()),
+            this, SLOT(tick()));
+    manageDelegates->setInterval(16);
+    manageDelegates->setSingleShot(false);
+    manageDelegates->start();
 }
 
 
@@ -79,33 +87,54 @@ void QSGItemParticle::give(QSGItem *item)
 
 void QSGItemParticle::load(QSGParticleData* d)
 {
-    if(m_pendingItems.isEmpty())
-        return;
     int pos = particleTypeIndex(d);
-    if(m_items[pos]){
-        if(m_stasis.contains(m_items[pos]))
-            qWarning() << "Current model particles prefers overwrite:false";
-        //remove old item from the particle that is dying to make room for this one
-        m_items[pos]->setOpacity(0.);
+    m_data[pos] = d;
+    m_loadables << pos;
+}
+
+void QSGItemParticle::tick()
+{
+    foreach(QSGItem* item, m_deletables){
+        if(m_fade)
+            item->setOpacity(0.);
         QSGItemParticleAttached* mpa;
-        if((mpa = qobject_cast<QSGItemParticleAttached*>(qmlAttachedPropertiesObject<QSGItemParticle>(m_items[pos], false))))
+        if((mpa = qobject_cast<QSGItemParticleAttached*>(qmlAttachedPropertiesObject<QSGItemParticle>(item))))
             mpa->detach();//reparent as well?
-        m_items[pos] = 0;
-        m_data[pos] = 0;
+        //TODO: Delete iff we created it
         m_activeCount--;
+        m_deletables.removeAll(item);
     }
-    m_items[pos] = m_pendingItems.front();
-    m_pendingItems.pop_front();
-    m_items[pos]->setX(d->curX() - m_items[pos]->width()/2);
-    m_items[pos]->setY(d->curY() - m_items[pos]->height()/2);
-    QSGItemParticleAttached* mpa = qobject_cast<QSGItemParticleAttached*>(qmlAttachedPropertiesObject<QSGItemParticle>(m_items[pos]));
-    if(mpa){
-        mpa->m_mp = this;
-        mpa->attach();
+
+    foreach(int pos, m_loadables){
+        if(m_stasis.contains(m_items[pos]))
+            qWarning() << "Current model particles prefers overwrite:false";
+        //remove old item from the particle that is dying to make room for this one
+        if(m_items[pos]){
+            m_deletables << m_items[pos];
+            m_activeCount--;
+        }
+        m_items[pos] = 0;
+        if(!m_pendingItems.isEmpty()){
+            m_items[pos] = m_pendingItems.front();
+            m_pendingItems.pop_front();
+        }else if(m_delegate){
+            m_items[pos] = qobject_cast<QSGItem*>(m_delegate->create(qmlContext(this)));
+        }
+        if(m_items[pos]){
+            m_items[pos]->setX(m_data[pos]->curX() - m_items[pos]->width()/2);//TODO: adjust for system?
+            m_items[pos]->setY(m_data[pos]->curY() - m_items[pos]->height()/2);
+            QSGItemParticleAttached* mpa = qobject_cast<QSGItemParticleAttached*>(qmlAttachedPropertiesObject<QSGItemParticle>(m_items[pos]));
+            if(mpa){
+                mpa->m_mp = this;
+                mpa->attach();
+            }
+            m_items[pos]->setParentItem(this);
+            if(m_fade)
+                m_items[pos]->setOpacity(0.);
+            m_activeCount++;
+        }
+        m_loadables.removeAll(pos);
     }
-    m_items[pos]->setParentItem(this);
-    m_data[pos] = d;
-    m_activeCount++;
 }
 
 void QSGItemParticle::reload(QSGParticleData* d)
@@ -173,10 +202,7 @@ void QSGItemParticle::prepareNextFrame()
             continue;
         }
         if(t >= 1.0){//Usually happens from load
-            item->setOpacity(0.);
-            QSGItemParticleAttached* mpa;
-            if((mpa = qobject_cast<QSGItemParticleAttached*>(qmlAttachedPropertiesObject<QSGItemParticle>(m_items[i]))))
-                mpa->detach();//reparent as well?
+            m_deletables << item;
             m_items[i] = 0;
             m_data[i] = 0;
             m_activeCount--;
diff --git a/src/declarative/particles/qsgitemparticle_p.h b/src/declarative/particles/qsgitemparticle_p.h
index fa3516b63166ea2341f196df8b8373ff74319fdb..3b7db519deb4d39a8c87101703649cf3ada16bcd 100644
--- a/src/declarative/particles/qsgitemparticle_p.h
+++ b/src/declarative/particles/qsgitemparticle_p.h
@@ -55,8 +55,8 @@ class QSGItemParticleAttached;
 class QSGItemParticle : public QSGParticlePainter
 {
     Q_OBJECT
-
     Q_PROPERTY(bool fade READ fade WRITE setFade NOTIFY fadeChanged)
+    Q_PROPERTY(QDeclarativeComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
 public:
     explicit QSGItemParticle(QSGItem *parent = 0);
 
@@ -69,9 +69,16 @@ public:
     virtual int count();
 
     static QSGItemParticleAttached *qmlAttachedProperties(QObject *object);
+    QDeclarativeComponent* delegate() const
+    {
+        return m_delegate;
+    }
+
 signals:
     void fadeChanged();
 
+    void delegateChanged(QDeclarativeComponent* arg);
+
 public slots:
     //TODO: Add a follow mode, where moving the delegate causes the logical particle to go with it?
     void freeze(QSGItem* item);
@@ -80,11 +87,22 @@ public slots:
     void give(QSGItem* item);//give from modelparticle
 
     void setFade(bool arg){if(arg == m_fade) return; m_fade = arg; emit fadeChanged();}
+    void setDelegate(QDeclarativeComponent* arg)
+    {
+        if (m_delegate != arg) {
+            m_delegate = arg;
+            emit delegateChanged(arg);
+        }
+    }
+
 protected:
     virtual void reset();
     void prepareNextFrame();
+private slots:
+    void tick();
 private:
-    QList<QPointer<QSGItem> > m_deletables;
+    QList<QSGItem* > m_deletables;
+    QList< int > m_loadables;
     int m_particleCount;
     bool m_fade;
 
@@ -96,6 +114,7 @@ private:
     QSet<QSGItem*> m_stasis;
     qreal m_lastT;
     int m_activeCount;
+    QDeclarativeComponent* m_delegate;
 };
 
 class QSGItemParticleAttached : public QObject
diff --git a/src/declarative/particles/qsgmodelparticle.cpp b/src/declarative/particles/qsgmodelparticle.cpp
index 704b9a298cd521bed02219c714317791a25212ac..b0b4fa4ad2d30c44ea633fc0f68f66b5f4d98f6c 100644
--- a/src/declarative/particles/qsgmodelparticle.cpp
+++ b/src/declarative/particles/qsgmodelparticle.cpp
@@ -177,6 +177,7 @@ void QSGModelParticle::processPending()
     foreach(QSGItem* item, m_deletables){
         item->setOpacity(0.);
         m_model->release(item);
+        m_deletables.removeAll(item);
     }
 
     foreach(int pos, m_requests){
@@ -189,6 +190,7 @@ void QSGModelParticle::processPending()
             mpa->attach();
         }
         m_items[pos]->setParentItem(this);
+        m_requests.removeAll(pos);
     }
 }
 
diff --git a/src/declarative/particles/qsgparticleemitter.cpp b/src/declarative/particles/qsgparticleemitter.cpp
index 20f3c6bb4b4af602cd0228e2b9dc4c08f7712e15..143338f798ab67fb11762a1bac7c169fa9bc5968 100644
--- a/src/declarative/particles/qsgparticleemitter.cpp
+++ b/src/declarative/particles/qsgparticleemitter.cpp
@@ -121,6 +121,13 @@ void QSGParticleEmitter::burst(int num)
     m_burstQueue << qMakePair(num, QPointF(x(), y()));
 }
 
+void QSGParticleEmitter::burst(int num, qreal x, qreal y)
+{
+    if(!particleCount())
+        qWarning() << "burst called on an emitter with a particle count of zero";
+    m_burstQueue << qMakePair(num, QPointF(x, y));
+}
+
 void QSGParticleEmitter::setMaxParticleCount(int arg)
 {
     if (m_maxParticleCount != arg) {
diff --git a/src/declarative/particles/qsgparticleemitter_p.h b/src/declarative/particles/qsgparticleemitter_p.h
index 9fafd9d43d46bba4309fae80fe545a8d86156c35..65aca0c83e22c9f5985b05cfcbfecad3a5c7bbe2 100644
--- a/src/declarative/particles/qsgparticleemitter_p.h
+++ b/src/declarative/particles/qsgparticleemitter_p.h
@@ -142,6 +142,7 @@ signals:
 public slots:
     void pulse(qreal seconds);
     void burst(int num);
+    void burst(int num, qreal x, qreal y);
 
     void setEmitting(bool arg);