From 61e588bb9433e8f80a23cf6fe4d9a691de50dd89 Mon Sep 17 00:00:00 2001
From: -f <claudio@open-sankore.org>
Date: Thu, 13 Feb 2014 11:58:49 +0100
Subject: [PATCH] Threaded the storage of the scene. Asynchronous reading of
 the previous and next scene to be stored on cache.

---
 src/adaptors/UBSvgSubsetAdaptor.cpp | 495 ++++++++++++++--------------
 src/adaptors/UBSvgSubsetAdaptor.h   |   5 +-
 src/core/UBPersistenceManager.cpp   |  51 ++-
 src/core/UBPersistenceManager.h     |   9 +-
 src/core/UBPersistenceWorker.cpp    |  69 ++++
 src/core/UBPersistenceWorker.h      |  68 ++++
 src/core/core.pri                   |   6 +-
 7 files changed, 450 insertions(+), 253 deletions(-)
 create mode 100644 src/core/UBPersistenceWorker.cpp
 create mode 100644 src/core/UBPersistenceWorker.h

diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp
index 8c465bc3..34ac821c 100644
--- a/src/adaptors/UBSvgSubsetAdaptor.cpp
+++ b/src/adaptors/UBSvgSubsetAdaptor.cpp
@@ -256,6 +256,29 @@ UBGraphicsScene* UBSvgSubsetAdaptor::loadScene(UBDocumentProxy* proxy, const int
 }
 
 
+QByteArray UBSvgSubsetAdaptor::loadSceneAsText(UBDocumentProxy* proxy, const int pageIndex)
+{
+    QString fileName = proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", pageIndex);
+    qDebug() << fileName;
+    QFile file(fileName);
+
+    if (file.exists())
+    {
+        if (!file.open(QIODevice::ReadOnly))
+        {
+            qWarning() << "Cannot open file " << fileName << " for reading ...";
+            return "";
+        }
+
+        return file.readAll();
+
+        file.close();
+
+    }
+    return "";
+}
+
+
 QUuid UBSvgSubsetAdaptor::sceneUuid(UBDocumentProxy* proxy, const int pageIndex)
 {
     QString fileName = proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", pageIndex);
@@ -1019,307 +1042,299 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::writeSvgElement()
 bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(int pageIndex)
 {
     Q_UNUSED(pageIndex);
-    if (mScene->isModified())
-    {
 
-        //Creating dom structure to store information
-        QDomDocument groupDomDocument;
-        QDomElement groupRoot = groupDomDocument.createElement(tGroups);
-        groupDomDocument.appendChild(groupRoot);
+    //Creating dom structure to store information
+    QDomDocument groupDomDocument;
+    QDomElement groupRoot = groupDomDocument.createElement(tGroups);
+    groupDomDocument.appendChild(groupRoot);
 
-        QBuffer buffer;
-        buffer.open(QBuffer::WriteOnly);
-        mXmlWriter.setDevice(&buffer);
+    QBuffer buffer;
+    buffer.open(QBuffer::WriteOnly);
+    mXmlWriter.setDevice(&buffer);
 
-        mXmlWriter.setAutoFormatting(true);
+    mXmlWriter.setAutoFormatting(true);
 
-        mXmlWriter.writeStartDocument();
-        mXmlWriter.writeDefaultNamespace(nsSvg);
-        mXmlWriter.writeNamespace(nsXLink, "xlink");
-        mXmlWriter.writeNamespace(UBSettings::uniboardDocumentNamespaceUri, "ub");
-        mXmlWriter.writeNamespace(nsXHtml, "xhtml");
+    mXmlWriter.writeStartDocument();
+    mXmlWriter.writeDefaultNamespace(nsSvg);
+    mXmlWriter.writeNamespace(nsXLink, "xlink");
+    mXmlWriter.writeNamespace(UBSettings::uniboardDocumentNamespaceUri, "ub");
+    mXmlWriter.writeNamespace(nsXHtml, "xhtml");
 
-        writeSvgElement();
+    writeSvgElement();
 
-        // Get the items from the scene
-        QList<QGraphicsItem*> items = mScene->items();
+    // Get the items from the scene
+    QList<QGraphicsItem*> items = mScene->items();
 
-        int strokes = 0; int polygons = 0;
-        foreach(QGraphicsItem *item, items) {
-            if (item->type() == UBGraphicsPolygonItem::Type) {
-                polygons++;
-            } else if (item->type() == UBGraphicsStrokesGroup::Type) {
-                strokes++;
-            }
+    int strokes = 0; int polygons = 0;
+    foreach(QGraphicsItem *item, items) {
+        if (item->type() == UBGraphicsPolygonItem::Type) {
+            polygons++;
+        } else if (item->type() == UBGraphicsStrokesGroup::Type) {
+            strokes++;
         }
-        qDebug() << "---Strokes count" << strokes << "Polygons count" << polygons;
+    }
+    qDebug() << "---Strokes count" << strokes << "Polygons count" << polygons;
 
-        qSort(items.begin(), items.end(), itemZIndexComp);
+    qSort(items.begin(), items.end(), itemZIndexComp);
 
-        UBGraphicsStroke *openStroke = 0;
+    UBGraphicsStroke *openStroke = 0;
 
-        bool groupHoldsInfo = false;
+    bool groupHoldsInfo = false;
 
-        while (!items.empty())
-        {
-            QGraphicsItem *item = items.takeFirst();
-
-            // Is the item a strokes group?
-            UBGraphicsStrokesGroup* strokesGroupItem = qgraphicsitem_cast<UBGraphicsStrokesGroup*>(item);
-
-            if(strokesGroupItem && strokesGroupItem->isVisible()){
-                // Add the polygons
-                foreach(QGraphicsItem* item, strokesGroupItem->childItems()){
-                    UBGraphicsPolygonItem* poly = qgraphicsitem_cast<UBGraphicsPolygonItem*>(item);
-                    if(NULL != poly){
-                        polygonItemToSvgPolygon(poly, true);
-                        items.removeOne(poly);
-                    }
+    while (!items.empty())
+    {
+        QGraphicsItem *item = items.takeFirst();
+
+        // Is the item a strokes group?
+        UBGraphicsStrokesGroup* strokesGroupItem = qgraphicsitem_cast<UBGraphicsStrokesGroup*>(item);
+
+        if(strokesGroupItem && strokesGroupItem->isVisible()){
+            // Add the polygons
+            foreach(QGraphicsItem* item, strokesGroupItem->childItems()){
+                UBGraphicsPolygonItem* poly = qgraphicsitem_cast<UBGraphicsPolygonItem*>(item);
+                if(NULL != poly){
+                    polygonItemToSvgPolygon(poly, true);
+                    items.removeOne(poly);
                 }
             }
+        }
 
-            // Is the item a polygon?
-            UBGraphicsPolygonItem *polygonItem = qgraphicsitem_cast<UBGraphicsPolygonItem*> (item);
-            if (polygonItem && polygonItem->isVisible())
+        // Is the item a polygon?
+        UBGraphicsPolygonItem *polygonItem = qgraphicsitem_cast<UBGraphicsPolygonItem*> (item);
+        if (polygonItem && polygonItem->isVisible())
+        {
+            UBGraphicsStroke* currentStroke = polygonItem->stroke();
+            if (openStroke && (currentStroke != openStroke))
             {
-                UBGraphicsStroke* currentStroke = polygonItem->stroke();
-                if (openStroke && (currentStroke != openStroke))
-                {
-                    mXmlWriter.writeEndElement(); //g
-                    openStroke = 0;
-                    groupHoldsInfo = false;
-                }
+                mXmlWriter.writeEndElement(); //g
+                openStroke = 0;
+                groupHoldsInfo = false;
+            }
 
-                bool firstPolygonInStroke = currentStroke  && !openStroke;
+            bool firstPolygonInStroke = currentStroke  && !openStroke;
 
-                if (firstPolygonInStroke)
-                {
-                    mXmlWriter.writeStartElement("g");
-                    openStroke = currentStroke;
+            if (firstPolygonInStroke)
+            {
+                mXmlWriter.writeStartElement("g");
+                openStroke = currentStroke;
 
-                    QMatrix matrix = item->sceneMatrix();
+                QMatrix matrix = item->sceneMatrix();
 
-                    if (!matrix.isIdentity())
-                        mXmlWriter.writeAttribute("transform", toSvgTransform(matrix));
+                if (!matrix.isIdentity())
+                    mXmlWriter.writeAttribute("transform", toSvgTransform(matrix));
 
-                    UBGraphicsStroke* stroke = dynamic_cast<UBGraphicsStroke* >(currentStroke);
+                UBGraphicsStroke* stroke = dynamic_cast<UBGraphicsStroke* >(currentStroke);
 
-                    if (stroke)
-                    {
-                        QColor colorOnDarkBackground = polygonItem->colorOnDarkBackground();
-                        QColor colorOnLightBackground = polygonItem->colorOnLightBackground();
+                if (stroke)
+                {
+                    QColor colorOnDarkBackground = polygonItem->colorOnDarkBackground();
+                    QColor colorOnLightBackground = polygonItem->colorOnLightBackground();
 
-                        if (colorOnDarkBackground.isValid() && colorOnLightBackground.isValid())
-                        {
-                            mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "z-value"
-                                                      , QString("%1").arg(polygonItem->zValue()));
+                    if (colorOnDarkBackground.isValid() && colorOnLightBackground.isValid())
+                    {
+                        mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "z-value"
+                                                  , QString("%1").arg(polygonItem->zValue()));
 
-                            mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri
-                                                      , "fill-on-dark-background", colorOnDarkBackground.name());
-                            mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri
-                                                      , "fill-on-light-background", colorOnLightBackground.name());
+                        mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri
+                                                  , "fill-on-dark-background", colorOnDarkBackground.name());
+                        mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri
+                                                  , "fill-on-light-background", colorOnLightBackground.name());
 
-                            groupHoldsInfo = true;
-                        }
+                        groupHoldsInfo = true;
                     }
+                }
 
-                    if (stroke && !stroke->hasPressure())
-                    {
+                if (stroke && !stroke->hasPressure())
+                {
 
-                        strokeToSvgPolyline(stroke, groupHoldsInfo);
+                    strokeToSvgPolyline(stroke, groupHoldsInfo);
 
-                        //we can dequeue all polygons belonging to that stroke
-                        foreach(UBGraphicsPolygonItem* gi, stroke->polygons())
-                        {
-                            items.removeOne(gi);
-                        }
-                        continue;
+                    //we can dequeue all polygons belonging to that stroke
+                    foreach(UBGraphicsPolygonItem* gi, stroke->polygons())
+                    {
+                        items.removeOne(gi);
                     }
+                    continue;
                 }
-
-                if (polygonItem->isNominalLine())
-                    polygonItemToSvgLine(polygonItem, groupHoldsInfo);
-                else
-                    polygonItemToSvgPolygon(polygonItem, groupHoldsInfo);
-
-                continue;
             }
 
-            if (openStroke)
-            {
-                mXmlWriter.writeEndElement(); //g
-                groupHoldsInfo = false;
-                openStroke = 0;
-            }
+            if (polygonItem->isNominalLine())
+                polygonItemToSvgLine(polygonItem, groupHoldsInfo);
+            else
+                polygonItemToSvgPolygon(polygonItem, groupHoldsInfo);
 
-            // Is the item a picture?
-            UBGraphicsPixmapItem *pixmapItem = qgraphicsitem_cast<UBGraphicsPixmapItem*> (item);
-            if (pixmapItem && pixmapItem->isVisible())
-            {
-                pixmapItemToLinkedImage(pixmapItem);
-                continue;
-            }
+            continue;
+        }
 
-            // Is the item a shape?
-            UBGraphicsSvgItem *svgItem = qgraphicsitem_cast<UBGraphicsSvgItem*> (item);
-            if (svgItem && svgItem->isVisible())
-            {
-                svgItemToLinkedSvg(svgItem);
-                continue;
-            }
+        if (openStroke)
+        {
+            mXmlWriter.writeEndElement(); //g
+            groupHoldsInfo = false;
+            openStroke = 0;
+        }
+
+        // Is the item a picture?
+        UBGraphicsPixmapItem *pixmapItem = qgraphicsitem_cast<UBGraphicsPixmapItem*> (item);
+        if (pixmapItem && pixmapItem->isVisible())
+        {
+            pixmapItemToLinkedImage(pixmapItem);
+            continue;
+        }
 
-            UBGraphicsMediaItem *mediaItem = qgraphicsitem_cast<UBGraphicsMediaItem*> (item);
+        // Is the item a shape?
+        UBGraphicsSvgItem *svgItem = qgraphicsitem_cast<UBGraphicsSvgItem*> (item);
+        if (svgItem && svgItem->isVisible())
+        {
+            svgItemToLinkedSvg(svgItem);
+            continue;
+        }
 
-            if (mediaItem && mediaItem->isVisible())
-            {
-                if (UBGraphicsMediaItem::mediaType_Video == mediaItem->getMediaType())
-                    videoItemToLinkedVideo(mediaItem);
-                else
-                    audioItemToLinkedAudio(mediaItem);
-                continue;
-            }
+        UBGraphicsMediaItem *mediaItem = qgraphicsitem_cast<UBGraphicsMediaItem*> (item);
 
-            // Is the item an app?
-            UBGraphicsAppleWidgetItem *appleWidgetItem = qgraphicsitem_cast<UBGraphicsAppleWidgetItem*> (item);
-            if (appleWidgetItem && appleWidgetItem->isVisible())
-            {
-                graphicsAppleWidgetToSvg(appleWidgetItem);
-                continue;
-            }
+        if (mediaItem && mediaItem->isVisible())
+        {
+            if (UBGraphicsMediaItem::mediaType_Video == mediaItem->getMediaType())
+                videoItemToLinkedVideo(mediaItem);
+            else
+                audioItemToLinkedAudio(mediaItem);
+            continue;
+        }
 
-            // Is the item a W3C?
-            UBGraphicsW3CWidgetItem *w3cWidgetItem = qgraphicsitem_cast<UBGraphicsW3CWidgetItem*> (item);
-            if (w3cWidgetItem && w3cWidgetItem->isVisible())
-            {
-                graphicsW3CWidgetToSvg(w3cWidgetItem);
-                continue;
-            }
+        // Is the item an app?
+        UBGraphicsAppleWidgetItem *appleWidgetItem = qgraphicsitem_cast<UBGraphicsAppleWidgetItem*> (item);
+        if (appleWidgetItem && appleWidgetItem->isVisible())
+        {
+            graphicsAppleWidgetToSvg(appleWidgetItem);
+            continue;
+        }
 
-            // Is the item a PDF?
-            UBGraphicsPDFItem *pdfItem = qgraphicsitem_cast<UBGraphicsPDFItem*> (item);
-            if (pdfItem && pdfItem->isVisible())
-            {
-                pdfItemToLinkedPDF(pdfItem);
-                continue;
-            }
+        // Is the item a W3C?
+        UBGraphicsW3CWidgetItem *w3cWidgetItem = qgraphicsitem_cast<UBGraphicsW3CWidgetItem*> (item);
+        if (w3cWidgetItem && w3cWidgetItem->isVisible())
+        {
+            graphicsW3CWidgetToSvg(w3cWidgetItem);
+            continue;
+        }
 
-            // Is the item a text?
-            UBGraphicsTextItem *textItem = qgraphicsitem_cast<UBGraphicsTextItem*> (item);
-            if (textItem && textItem->isVisible())
-            {
-                textItemToSvg(textItem);
-                continue;
-            }
+        // Is the item a PDF?
+        UBGraphicsPDFItem *pdfItem = qgraphicsitem_cast<UBGraphicsPDFItem*> (item);
+        if (pdfItem && pdfItem->isVisible())
+        {
+            pdfItemToLinkedPDF(pdfItem);
+            continue;
+        }
 
-            // Is the item a curtain?
-            UBGraphicsCurtainItem *curtainItem = qgraphicsitem_cast<UBGraphicsCurtainItem*> (item);
-            if (curtainItem && curtainItem->isVisible())
-            {
-                curtainItemToSvg(curtainItem);
-                continue;
-            }
+        // Is the item a text?
+        UBGraphicsTextItem *textItem = qgraphicsitem_cast<UBGraphicsTextItem*> (item);
+        if (textItem && textItem->isVisible())
+        {
+            textItemToSvg(textItem);
+            continue;
+        }
 
-            // Is the item a ruler?
-            UBGraphicsRuler *ruler = qgraphicsitem_cast<UBGraphicsRuler*> (item);
-            if (ruler && ruler->isVisible())
-            {
-                rulerToSvg(ruler);
-                continue;
-            }
+        // Is the item a curtain?
+        UBGraphicsCurtainItem *curtainItem = qgraphicsitem_cast<UBGraphicsCurtainItem*> (item);
+        if (curtainItem && curtainItem->isVisible())
+        {
+            curtainItemToSvg(curtainItem);
+            continue;
+        }
 
-            // Is the item a cache?
-            UBGraphicsCache* cache = qgraphicsitem_cast<UBGraphicsCache*>(item);
-            if(cache && cache->isVisible())
-            {
-                cacheToSvg(cache);
-                continue;
-            }
+        // Is the item a ruler?
+        UBGraphicsRuler *ruler = qgraphicsitem_cast<UBGraphicsRuler*> (item);
+        if (ruler && ruler->isVisible())
+        {
+            rulerToSvg(ruler);
+            continue;
+        }
 
-            // Is the item a compass
-            UBGraphicsCompass *compass = qgraphicsitem_cast<UBGraphicsCompass*> (item);
-            if (compass && compass->isVisible())
-            {
-                compassToSvg(compass);
-                continue;
-            }
+        // Is the item a cache?
+        UBGraphicsCache* cache = qgraphicsitem_cast<UBGraphicsCache*>(item);
+        if(cache && cache->isVisible())
+        {
+            cacheToSvg(cache);
+            continue;
+        }
 
-            // Is the item a protractor?
-            UBGraphicsProtractor *protractor = qgraphicsitem_cast<UBGraphicsProtractor*> (item);
-            if (protractor && protractor->isVisible())
-            {
-                protractorToSvg(protractor);
-                continue;
-            }
+        // Is the item a compass
+        UBGraphicsCompass *compass = qgraphicsitem_cast<UBGraphicsCompass*> (item);
+        if (compass && compass->isVisible())
+        {
+            compassToSvg(compass);
+            continue;
+        }
 
-            // Is the item a triangle?
-            UBGraphicsTriangle *triangle = qgraphicsitem_cast<UBGraphicsTriangle*> (item);
-            if (triangle && triangle->isVisible())
-            {
-                triangleToSvg(triangle);
-                continue;
-            }
+        // Is the item a protractor?
+        UBGraphicsProtractor *protractor = qgraphicsitem_cast<UBGraphicsProtractor*> (item);
+        if (protractor && protractor->isVisible())
+        {
+            protractorToSvg(protractor);
+            continue;
+        }
 
-            // Is the item a group?
-            UBGraphicsGroupContainerItem *groupItem = qgraphicsitem_cast<UBGraphicsGroupContainerItem*>(item);
-            if (groupItem && groupItem->isVisible())
-            {
-                persistGroupToDom(groupItem, &groupRoot, &groupDomDocument);
-                continue;
-            }
+        // Is the item a triangle?
+        UBGraphicsTriangle *triangle = qgraphicsitem_cast<UBGraphicsTriangle*> (item);
+        if (triangle && triangle->isVisible())
+        {
+            triangleToSvg(triangle);
+            continue;
         }
 
-        if (openStroke)
+        // Is the item a group?
+        UBGraphicsGroupContainerItem *groupItem = qgraphicsitem_cast<UBGraphicsGroupContainerItem*>(item);
+        if (groupItem && groupItem->isVisible())
         {
-            mXmlWriter.writeEndElement();
-            groupHoldsInfo = false;
-            openStroke = 0;
+            persistGroupToDom(groupItem, &groupRoot, &groupDomDocument);
+            continue;
         }
+    }
 
-        //writing group data
-        if (groupRoot.hasChildNodes()) {
-            mXmlWriter.writeStartElement(tGroups);
-            QDomElement curElement = groupRoot.firstChildElement();
-            while (!curElement.isNull()) {
-                if (curElement.hasAttribute(aId)) {
-                    mXmlWriter.writeStartElement(curElement.tagName());
-                    mXmlWriter.writeAttribute(aId, curElement.attribute(aId));
-                    if(curElement.hasAttribute("locked")){
-                        mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri,"locked",curElement.attribute("locked"));
-                    }
-                    QDomElement curSubElement = curElement.firstChildElement();
-                    while (!curSubElement.isNull()) {
-                        if (curSubElement.hasAttribute(aId)) {
-                            mXmlWriter.writeStartElement(curSubElement.tagName());
-                            mXmlWriter.writeAttribute(aId, curSubElement.attribute(aId));
-                            mXmlWriter.writeEndElement();
-                            curSubElement = curSubElement.nextSiblingElement();
-                        }
+    if (openStroke)
+    {
+        mXmlWriter.writeEndElement();
+        groupHoldsInfo = false;
+        openStroke = 0;
+    }
+
+    //writing group data
+    if (groupRoot.hasChildNodes()) {
+        mXmlWriter.writeStartElement(tGroups);
+        QDomElement curElement = groupRoot.firstChildElement();
+        while (!curElement.isNull()) {
+            if (curElement.hasAttribute(aId)) {
+                mXmlWriter.writeStartElement(curElement.tagName());
+                mXmlWriter.writeAttribute(aId, curElement.attribute(aId));
+                if(curElement.hasAttribute("locked")){
+                    mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri,"locked",curElement.attribute("locked"));
+                }
+                QDomElement curSubElement = curElement.firstChildElement();
+                while (!curSubElement.isNull()) {
+                    if (curSubElement.hasAttribute(aId)) {
+                        mXmlWriter.writeStartElement(curSubElement.tagName());
+                        mXmlWriter.writeAttribute(aId, curSubElement.attribute(aId));
+                        mXmlWriter.writeEndElement();
+                        curSubElement = curSubElement.nextSiblingElement();
                     }
-                    mXmlWriter.writeEndElement();
                 }
-                curElement = curElement.nextSiblingElement();
+                mXmlWriter.writeEndElement();
             }
-            mXmlWriter.writeEndElement();
+            curElement = curElement.nextSiblingElement();
         }
+        mXmlWriter.writeEndElement();
+    }
 
-        mXmlWriter.writeEndDocument();
-        QString fileName = mDocumentPath + UBFileSystemUtils::digitFileFormat("/page%1.svg", mPageIndex);
-        QFile file(fileName);
-
-        if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
-        {
-            qCritical() << "cannot open " << fileName << " for writing ...";
-            return false;
-        }
-        file.write(buffer.data());
-        file.flush();
-        file.close();
+    mXmlWriter.writeEndDocument();
+    QString fileName = mDocumentPath + UBFileSystemUtils::digitFileFormat("/page%1.svg", mPageIndex);
+    QFile file(fileName);
 
-    }
-    else
+    if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
     {
-        qDebug() << "ignoring unmodified page" << UBApplication::boardController->pageFromSceneIndex(mPageIndex);
+        qCritical() << "cannot open " << fileName << " for writing ...";
+        return false;
     }
+    file.write(buffer.data());
+    file.flush();
+    file.close();
 
     return true;
 }
diff --git a/src/adaptors/UBSvgSubsetAdaptor.h b/src/adaptors/UBSvgSubsetAdaptor.h
index 5835f8e0..c7a3a2e8 100644
--- a/src/adaptors/UBSvgSubsetAdaptor.h
+++ b/src/adaptors/UBSvgSubsetAdaptor.h
@@ -65,6 +65,9 @@ class UBSvgSubsetAdaptor
     public:
 
         static UBGraphicsScene* loadScene(UBDocumentProxy* proxy, const int pageIndex);
+        static QByteArray loadSceneAsText(UBDocumentProxy* proxy, const int pageIndex);
+        static UBGraphicsScene* loadScene(UBDocumentProxy* proxy, const QByteArray& pArray);
+
         static void persistScene(UBDocumentProxy* proxy, UBGraphicsScene* pScene, const int pageIndex);
         static void upgradeScene(UBDocumentProxy* proxy, const int pageIndex);
 
@@ -88,8 +91,6 @@ class UBSvgSubsetAdaptor
 
     private:
 
-        static UBGraphicsScene* loadScene(UBDocumentProxy* proxy, const QByteArray& pArray);
-
         static QDomDocument loadSceneDocument(UBDocumentProxy* proxy, const int pPageIndex);
 
         static QString uniboardDocumentNamespaceUriFromVersion(int fileVersion);
diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp
index 12c4eba0..2601bcbe 100644
--- a/src/core/UBPersistenceManager.cpp
+++ b/src/core/UBPersistenceManager.cpp
@@ -75,6 +75,17 @@ UBPersistenceManager::UBPersistenceManager(QObject *pParent)
 
     documentProxies = allDocumentProxies();
 
+    mThread = new QThread;
+    mWorker = new UBPersistenceWorker();
+    mWorker->moveToThread(mThread);
+    connect(mWorker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
+    connect(mThread, SIGNAL(started()), mWorker, SLOT(process()));
+    connect(mWorker, SIGNAL(finished()), mThread, SLOT(quit()));
+    connect(mWorker, SIGNAL(finished()), mWorker, SLOT(deleteLater()));
+    connect(mThread, SIGNAL(finished()), mThread, SLOT(deleteLater()));
+    connect(mWorker,SIGNAL(sceneLoaded(QByteArray,UBDocumentProxy*,int)),this,SLOT(onSceneLoaded(QByteArray,UBDocumentProxy*,int)));
+    mThread->start();
+
 }
 
 UBPersistenceManager* UBPersistenceManager::persistenceManager()
@@ -96,11 +107,31 @@ void UBPersistenceManager::destroy()
 
 UBPersistenceManager::~UBPersistenceManager()
 {
+    if(mWorker)
+        mWorker->applicationWillClose();
+
     foreach(QPointer<UBDocumentProxy> proxyGuard, documentProxies)
     {
         if (!proxyGuard.isNull())
             delete proxyGuard.data();
     }
+
+    // to be sure that all the scenes are stored on disk
+    mThread->wait(10*1000);
+}
+
+void UBPersistenceManager::errorString(QString error)
+{
+    qDebug() << "peristence thread return the error " << error;
+}
+
+void UBPersistenceManager::onSceneLoaded(QByteArray scene, UBDocumentProxy* proxy, int sceneIndex)
+{
+    qDebug() << "scene loaded " << sceneIndex;
+    QTime time;
+    time.start();
+    mSceneCache.insert(proxy,sceneIndex,UBSvgSubsetAdaptor::loadScene(proxy,scene));
+    qDebug() << "millisecond for sceneCache " << time.elapsed();
 }
 
 QList<QPointer<UBDocumentProxy> > UBPersistenceManager::allDocumentProxies()
@@ -653,16 +684,24 @@ void UBPersistenceManager::moveSceneToIndex(UBDocumentProxy* proxy, int source,
 
 UBGraphicsScene* UBPersistenceManager::loadDocumentScene(UBDocumentProxy* proxy, int sceneIndex)
 {
+    UBGraphicsScene* scene = NULL;
+
     if (mSceneCache.contains(proxy, sceneIndex))
-        return mSceneCache.value(proxy, sceneIndex);
+        scene = mSceneCache.value(proxy, sceneIndex);
     else {
-        UBGraphicsScene* scene = UBSvgSubsetAdaptor::loadScene(proxy, sceneIndex);
+        scene = UBSvgSubsetAdaptor::loadScene(proxy, sceneIndex);
 
         if (scene)
             mSceneCache.insert(proxy, sceneIndex, scene);
-
-        return scene;
     }
+
+    if(sceneIndex + 1 < proxy->pageCount() &&  !mSceneCache.contains(proxy, sceneIndex + 1))
+        mWorker->readScene(proxy,sceneIndex+1);
+
+    if(sceneIndex - 1 >= 0 &&  !mSceneCache.contains(proxy, sceneIndex - 1))
+        mWorker->readScene(proxy,sceneIndex-1);
+
+    return scene;
 }
 
 void UBPersistenceManager::persistDocumentScene(UBDocumentProxy* pDocumentProxy, UBGraphicsScene* pScene, const int pSceneIndex, bool isAnAutomaticBackup)
@@ -682,10 +721,8 @@ void UBPersistenceManager::persistDocumentScene(UBDocumentProxy* pDocumentProxy,
 
     if (pScene->isModified())
     {
-        UBSvgSubsetAdaptor::persistScene(pDocumentProxy, pScene, pSceneIndex);
-
         UBThumbnailAdaptor::persistScene(pDocumentProxy, pScene, pSceneIndex);
-
+        mWorker->saveScene(pDocumentProxy, pScene, pSceneIndex);
         pScene->setModified(false);
     }
 
diff --git a/src/core/UBPersistenceManager.h b/src/core/UBPersistenceManager.h
index 8336e302..1b297a84 100644
--- a/src/core/UBPersistenceManager.h
+++ b/src/core/UBPersistenceManager.h
@@ -32,6 +32,8 @@
 
 #include "UBSceneCache.h"
 
+#include "UBPersistenceWorker.h"
+
 class UBDocument;
 class UBDocumentProxy;
 class UBGraphicsScene;
@@ -148,11 +150,14 @@ class UBPersistenceManager : public QObject
 
         QString mDocumentRepositoryPath;
 
-        QHash<int,QString>teacherBarNodeString;
+        UBPersistenceWorker* mWorker;
+
+        QThread* mThread;
 
     private slots:
         void documentRepositoryChanged(const QString& path);
-
+        void errorString(QString error);
+        void onSceneLoaded(QByteArray,UBDocumentProxy*,int);
 };
 
 
diff --git a/src/core/UBPersistenceWorker.cpp b/src/core/UBPersistenceWorker.cpp
new file mode 100644
index 00000000..25601870
--- /dev/null
+++ b/src/core/UBPersistenceWorker.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013 Open Education Foundation
+ *
+ *
+ * This file is part of OpenBoard.
+ *
+ * OpenBoard is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License,
+ * with a specific linking exception for the OpenSSL project's
+ * "OpenSSL" library (or with modified versions of it that use the
+ * same license as the "OpenSSL" library).
+ *
+ * OpenBoard is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with OpenBoard. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+
+#include "UBPersistenceWorker.h"
+#include "adaptors/UBSvgSubsetAdaptor.h"
+#include "adaptors/UBThumbnailAdaptor.h"
+
+UBPersistenceWorker::UBPersistenceWorker(QObject *parent) :
+    QObject(parent)
+  , mReceivedApplicationClosing(false)
+{
+}
+
+void UBPersistenceWorker::saveScene(UBDocumentProxy* proxy, UBGraphicsScene* scene, const int pageIndex)
+{
+    saves.append({WriteScene,proxy,scene,pageIndex});
+    mSemaphore.release();
+}
+
+void UBPersistenceWorker::readScene(UBDocumentProxy* proxy, const int pageIndex)
+{
+    saves.append({ReadScene,proxy,0,pageIndex});
+    mSemaphore.release();
+}
+
+void UBPersistenceWorker::applicationWillClose()
+{
+    qDebug() << "applicaiton Will close signal received";
+    mReceivedApplicationClosing = true;
+    mSemaphore.release();
+}
+
+void UBPersistenceWorker::process()
+{
+    qDebug() << "process starts";
+    mSemaphore.acquire();
+    do{
+        PersistenceInformation info = saves.takeFirst();
+        if(info.action == WriteScene)
+            UBSvgSubsetAdaptor::persistScene(info.proxy, info.scene, info.sceneIndex);
+        else{
+            emit sceneLoaded(UBSvgSubsetAdaptor::loadSceneAsText(info.proxy,info.sceneIndex), info.proxy, info.sceneIndex);
+        }
+        mSemaphore.acquire();
+    }while(!mReceivedApplicationClosing);
+    qDebug() << "process will stop";
+    emit finished();
+}
diff --git a/src/core/UBPersistenceWorker.h b/src/core/UBPersistenceWorker.h
new file mode 100644
index 00000000..4078585a
--- /dev/null
+++ b/src/core/UBPersistenceWorker.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013-2014 Open Education Foundation
+ *
+ *
+ * This file is part of OpenBoard.
+ *
+ * OpenBoard is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License,
+ * with a specific linking exception for the OpenSSL project's
+ * "OpenSSL" library (or with modified versions of it that use the
+ * same license as the "OpenSSL" library).
+ *
+ * OpenBoard is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with OpenBoard. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef UBPERSISTENCEWORKER_H
+#define UBPERSISTENCEWORKER_H
+
+#include <QObject>
+#include <QSemaphore>
+#include "document/UBDocumentProxy.h"
+#include "domain/UBGraphicsScene.h"
+
+typedef enum{
+    WriteScene = 0,
+    ReadScene
+}ActionType;
+
+typedef struct{
+    ActionType action;
+    UBDocumentProxy* proxy;
+    UBGraphicsScene* scene;
+    int sceneIndex;
+}PersistenceInformation;
+
+class UBPersistenceWorker : public QObject
+{
+    Q_OBJECT
+public:
+    explicit UBPersistenceWorker(QObject *parent = 0);
+
+    void saveScene(UBDocumentProxy* proxy, UBGraphicsScene* scene, const int pageIndex);
+    void readScene(UBDocumentProxy* proxy, const int pageIndex);
+
+signals:
+   void finished();
+   void error(QString string);
+   void sceneLoaded(QByteArray text,UBDocumentProxy* proxy, const int pageIndex);
+
+public slots:
+   void process();
+   void applicationWillClose();
+
+protected:
+   bool mReceivedApplicationClosing;
+   QSemaphore mSemaphore;
+   QList<PersistenceInformation> saves;
+};
+
+#endif // UBPERSISTENCEWORKER_H
diff --git a/src/core/core.pri b/src/core/core.pri
index 12d752f3..fedfde3f 100644
--- a/src/core/core.pri
+++ b/src/core/core.pri
@@ -14,7 +14,8 @@ HEADERS      += src/core/UB.h \
                 src/core/UBDownloadManager.h \
                 src/core/UBDownloadThread.h \
                 src/core/UBOpenSankoreImporter.h \
-                src/core/UBTextTools.h
+                src/core/UBTextTools.h \
+    src/core/UBPersistenceWorker.h
 
 SOURCES      += src/core/main.cpp \
                 src/core/UBApplication.cpp \
@@ -31,6 +32,7 @@ SOURCES      += src/core/main.cpp \
                 src/core/UBDownloadManager.cpp \
                 src/core/UBDownloadThread.cpp \
                 src/core/UBOpenSankoreImporter.cpp \
-                src/core/UBTextTools.cpp
+                src/core/UBTextTools.cpp \
+    src/core/UBPersistenceWorker.cpp