← Back to team overview

ubuntu-touch-coreapps-reviewers team mailing list archive

[Merge] lp:~mrqtros/ubuntu-docviewer-app/ubuntu-docviewer-app-more-oop into lp:ubuntu-docviewer-app/reboot

 

Roman Shchekin has proposed merging lp:~mrqtros/ubuntu-docviewer-app/ubuntu-docviewer-app-more-oop into lp:ubuntu-docviewer-app/reboot.

Commit message:
More OOP in RenderEngine (preparations for migration of PDF plugin to tile rendering).

Requested reviews:
  Ubuntu Document Viewer Developers (ubuntu-docviewer-dev)

For more details, see:
https://code.launchpad.net/~mrqtros/ubuntu-docviewer-app/ubuntu-docviewer-app-more-oop/+merge/274833

More OOP in RenderEngine (preparations for migration of PDF plugin to tile rendering).
-- 
Your team Ubuntu Document Viewer Developers is requested to review the proposed merge of lp:~mrqtros/ubuntu-docviewer-app/ubuntu-docviewer-app-more-oop into lp:ubuntu-docviewer-app/reboot.
=== modified file 'po/com.ubuntu.docviewer.pot'
--- po/com.ubuntu.docviewer.pot	2015-10-11 11:32:00 +0000
+++ po/com.ubuntu.docviewer.pot	2015-10-18 22:08:02 +0000
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-10-11 13:31+0200\n"
+"POT-Creation-Date: 2015-10-19 00:19+0300\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@xxxxxx>\n"
@@ -19,12 +19,12 @@
 "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
 
 #: ../src/app/docviewer-application.cpp:162
-#: /tmp/build-reboot-qsg-impress-support-Desktop-Default/po/com.ubuntu.docviewer.desktop.in.in.h:1
+#: /home/qtros/dev/build-ubuntu-docviewer-app-more-oop-Desktop-Default/po/com.ubuntu.docviewer.desktop.in.in.h:1
 msgid "Document Viewer"
 msgstr ""
 
 #: ../src/app/qml/common/DetailsPage.qml:27
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:114
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:106
 #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:97
 #: ../src/app/qml/textView/TextViewDefaultHeader.qml:83
 msgid "Details"
@@ -63,7 +63,7 @@
 #: ../src/app/qml/common/RejectedImportDialog.qml:38
 #: ../src/app/qml/documentPage/DocumentPageSelectionModeHeader.qml:32
 #: ../src/app/qml/documentPage/SortSettingsDialog.qml:53
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:78
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:70
 #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:61
 #: ../src/app/qml/textView/TextViewDefaultHeader.qml:61
 msgid "Close"
@@ -254,7 +254,7 @@
 msgstr ""
 
 #: ../src/app/qml/documentPage/DocumentPageSearchHeader.qml:27
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:78
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:70
 #: ../src/app/qml/loView/LOViewPage.qml:191
 #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:61
 #: ../src/app/qml/textView/TextViewDefaultHeader.qml:61
@@ -306,50 +306,50 @@
 msgid "Reverse order"
 msgstr ""
 
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:55
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:47
 #: ../src/app/qml/textView/TextView.qml:42
 msgid "Loading..."
 msgstr ""
 
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:59
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:51
 msgid "LibreOffice text document"
 msgstr ""
 
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:61
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:53
 msgid "LibreOffice spread sheet"
 msgstr ""
 
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:63
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:55
 msgid "LibreOffice presentation"
 msgstr ""
 
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:65
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:57
 msgid "LibreOffice Draw document"
 msgstr ""
 
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:67
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:59
 msgid "Unknown LibreOffice document"
 msgstr ""
 
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:69
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:61
 msgid "Unknown type document"
 msgstr ""
 
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:94
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:86
 msgid "Show zoom controls"
 msgstr ""
 
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:101
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:93
 msgid "Go to position..."
 msgstr ""
 
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:108
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:100
 #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:91
 #: ../src/app/qml/textView/TextViewDefaultHeader.qml:77
 msgid "Disable night mode"
 msgstr ""
 
-#: ../src/app/qml/loView/LOViewDefaultHeader.qml:108
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:100
 #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:91
 #: ../src/app/qml/textView/TextViewDefaultHeader.qml:77
 msgid "Enable night mode"
@@ -448,6 +448,6 @@
 msgid "copy %1"
 msgstr ""
 
-#: /tmp/build-reboot-qsg-impress-support-Desktop-Default/po/com.ubuntu.docviewer.desktop.in.in.h:2
+#: /home/qtros/dev/build-ubuntu-docviewer-app-more-oop-Desktop-Default/po/com.ubuntu.docviewer.desktop.in.in.h:2
 msgid "documents;viewer;pdf;reader;"
 msgstr ""

=== modified file 'src/plugin/libreofficetoolkit-qml-plugin/CMakeLists.txt'
--- src/plugin/libreofficetoolkit-qml-plugin/CMakeLists.txt	2015-09-22 19:02:46 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/CMakeLists.txt	2015-10-18 22:08:02 +0000
@@ -20,6 +20,7 @@
     lopartsimageprovider.cpp
     lopartsmodel.cpp
     renderengine.cpp
+    rendertask.cpp
     ${QML_SRCS}
 )
 

=== modified file 'src/plugin/libreofficetoolkit-qml-plugin/lopartsimageprovider.cpp'
--- src/plugin/libreofficetoolkit-qml-plugin/lopartsimageprovider.cpp	2015-10-08 20:53:25 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/lopartsimageprovider.cpp	2015-10-18 22:08:02 +0000
@@ -43,7 +43,7 @@
 
     const int defaultSize = 256;
 
-    RenderEngine::instance()->enqueueTask(m_document, partNumber, defaultSize, itemId);
+    RenderEngine::instance()->enqueueThumbnailTask(m_document, partNumber, defaultSize, itemId);
 
     // Return default image (empty).
     static QImage defaultImage;

=== modified file 'src/plugin/libreofficetoolkit-qml-plugin/loview.cpp'
--- src/plugin/libreofficetoolkit-qml-plugin/loview.cpp	2015-10-12 23:07:23 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/loview.cpp	2015-10-18 22:08:02 +0000
@@ -49,7 +49,7 @@
     connect(this, SIGNAL(cacheBufferChanged()), this, SLOT(updateVisibleRect()));
     connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateVisibleRect()));
 
-    connect(RenderEngine::instance(), SIGNAL(renderFinished(int,QImage)),
+    connect(RenderEngine::instance(), SIGNAL(tileRenderFinished(int,QImage)),
             this, SLOT(slotTileRenderFinished(int,QImage)));
     connect(RenderEngine::instance(), SIGNAL(thumbnailRenderFinished(int,QImage)),
             this, SLOT(slotThumbnailRenderFinished(int,QImage)));
@@ -332,7 +332,7 @@
 
         auto tile = new SGTileItem(rect, m_zoomFactor, RenderEngine::getNextId(), this);
         m_tiles.insert(index, tile);
-        RenderEngine::instance()->enqueueTask(m_document, m_document->currentPart(), rect, m_zoomFactor, tile->id());
+        RenderEngine::instance()->enqueueTileTask(m_document, m_document->currentPart(), rect, m_zoomFactor, tile->id());
     }
 #ifdef DEBUG_VERBOSE
     else {
@@ -385,7 +385,7 @@
 {
     delete m_partsModel;
 
-    disconnect(RenderEngine::instance(), SIGNAL(renderFinished(int,QImage)),
+    disconnect(RenderEngine::instance(), SIGNAL(tileRenderFinished(int,QImage)),
                this, SLOT(slotTileRenderFinished(int,QImage)));
     disconnect(RenderEngine::instance(), SIGNAL(thumbnailRenderFinished(int,QImage)),
                this, SLOT(slotThumbnailRenderFinished(int,QImage)));

=== modified file 'src/plugin/libreofficetoolkit-qml-plugin/renderengine.cpp'
--- src/plugin/libreofficetoolkit-qml-plugin/renderengine.cpp	2015-10-11 11:27:29 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/renderengine.cpp	2015-10-18 22:08:02 +0000
@@ -7,51 +7,84 @@
 RenderEngine::RenderEngine():
     QObject(nullptr),
     m_activeTaskCount(0),
-    m_enabled(true),
     m_lastPart(-1)
 {
     int itc = QThread::idealThreadCount();
     m_idealThreadCount = itc == -1 ? DefaultIdealThreadCount : itc;
 
-    connect(this, SIGNAL(enabledChanged()), this, SLOT(doNextTask()));
-}
-
-void RenderEngine::enqueueTask(const QSharedPointer<LODocument>& doc, int part, const QRect& area, const qreal &zoom, int id)
-{
-    Q_ASSERT(doc != nullptr);
-
-    m_queue.enqueue(EngineTask(doc, part, area, zoom, id));
-
-    doNextTask();
-}
-
-void RenderEngine::enqueueTask(const QSharedPointer<LODocument> &doc, int part, qreal size, int id)
-{
-    Q_ASSERT(doc != nullptr);
-
-    m_queue.enqueue(EngineTask(doc, part, size, id));
-
+    // For QMetaObject::invoke.
+    qRegisterMetaType<AbstractRenderTask*>();
+}
+
+void RenderEngine::enqueueTileTask(const QSharedPointer<LODocument>& doc, int part, const QRect& area, qreal zoom, int id)
+{
+    Q_ASSERT(doc != nullptr);
+
+    TileRenderTask* task = new TileRenderTask();
+    task->setId(id);
+    task->setPart(part);
+    task->setDocument(doc);
+    task->setArea(area);
+    task->setZoom(zoom);
+
+    enqueueTask(task);
+}
+
+void RenderEngine::enqueueThumbnailTask(const QSharedPointer<LODocument> &doc, int part, qreal size, int id)
+{
+    Q_ASSERT(doc != nullptr);
+
+    ThumbnailRenderTask* task = new ThumbnailRenderTask();
+    task->setId(id);
+    task->setPart(part);
+    task->setDocument(doc);
+    task->setSize(size);
+
+    enqueueTask(task);
+}
+
+void RenderEngine::enqueueTask(AbstractRenderTask *task)
+{
+    m_queue.enqueue(task);
     doNextTask();
 }
 
 void RenderEngine::dequeueTask(int id)
 {
-    for (int i = 0; i < m_queue.size(); i++)
-        if (m_queue.at(i).id == id) {
+    for (int i = 0; i < m_queue.size(); i++) {
+        auto task = m_queue.at(i);
+        if (task->id() == id) {
             m_queue.removeAt(i);
+            disposeTask(task);
             break;
         }
+    }
 }
 
-void RenderEngine::internalRenderCallback(int id, QImage img, bool isThumbnail)
+void RenderEngine::internalRenderCallback(AbstractRenderTask* task, QImage img)
 {
     m_activeTaskCount--;
-    if (isThumbnail)
-        Q_EMIT thumbnailRenderFinished(id, img);
-    else Q_EMIT renderFinished(id, img);
+
+    switch (task->type())
+    {
+    case RttTile:
+        Q_EMIT tileRenderFinished(task->id(), img);
+        break;
+    case RttImpressThumbnail:
+        Q_EMIT thumbnailRenderFinished(task->id(), img);
+        break;
+    }
+
+    disposeTask(task);
+
     doNextTask();
 }
 
+void RenderEngine::disposeTask(AbstractRenderTask *task)
+{
+    delete task;
+}
+
 void RenderEngine::doNextTask()
 {
 #ifdef DEBUG_VERBOSE
@@ -59,29 +92,29 @@
 #endif
 
     // Check for too much threads or empty queue.
-    if (m_activeTaskCount >= m_idealThreadCount || !m_queue.count() || !m_enabled)
-        return;
-
-    // We should avoid different part rendering in the same time.
-    if (m_activeTaskCount && m_queue.head().part != m_lastPart)
-        return;
+    if (m_activeTaskCount >= m_idealThreadCount || !m_queue.count())
+        return;
+
+    AbstractRenderTask* task = m_queue.head();
+
+    // LoRenderTask requires special check.
+    if (task->type() == RttTile || task->type() == RttImpressThumbnail) {
+        LoRenderTask* loTask = static_cast<LoRenderTask*>(task);
+
+        if (m_activeTaskCount && loTask->part() != m_lastPart)
+            return;
+
+        // Set correct part.
+        m_lastPart = loTask->part();
+        loTask->document()->setDocumentPart(m_lastPart);
+    }
 
     m_activeTaskCount++;
-    EngineTask task = m_queue.dequeue();
-
-    // Set correct part.
-    m_lastPart = task.part;
-    task.document->setDocumentPart(m_lastPart);
+    m_queue.dequeue();
 
     QtConcurrent::run( [=] {
-        if (task.isThumbnail) {
-            QImage img = task.document->paintThumbnail(task.size);
-            QMetaObject::invokeMethod(this, "internalRenderCallback",
-                                      Q_ARG(int, task.id), Q_ARG(QImage, img), Q_ARG(bool, task.isThumbnail));
-        } else {
-            QImage img = task.document->paintTile(task.area.size(), task.area, task.zoom);
-            QMetaObject::invokeMethod(this, "internalRenderCallback",
-                                      Q_ARG(int, task.id), Q_ARG(QImage, img), Q_ARG(bool, task.isThumbnail));
-        }
+        QImage img = task->doWork();
+        QMetaObject::invokeMethod(this, "internalRenderCallback",
+                                  Q_ARG(AbstractRenderTask*, task), Q_ARG(QImage, img));
     });
 }

=== modified file 'src/plugin/libreofficetoolkit-qml-plugin/renderengine.h'
--- src/plugin/libreofficetoolkit-qml-plugin/renderengine.h	2015-10-08 20:53:25 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/renderengine.h	2015-10-18 22:08:02 +0000
@@ -9,45 +9,7 @@
 #include <QAtomicInt>
 
 #include "lodocument.h"
-
-// TODO replace with class.
-
-
-// TODO Need more OOP here.
-struct EngineTask
-{
-    int id;
-    int part;
-    QSharedPointer<LODocument> document;
-    // Used in thumbnail rendering.
-    qreal size;
-    // Used in tile rendering.
-    QRect area;
-    qreal zoom;
-    // Internal.
-    bool isThumbnail;
-public:
-
-    EngineTask(const QSharedPointer<LODocument>& d, int p, const QRect& a, const qreal& z, int i):
-        id(i),
-        part(p),
-        document(d),
-        size(0),
-        area(a),
-        zoom(z),
-        isThumbnail(false)
-    { }
-
-    EngineTask(const QSharedPointer<LODocument>& d, int p, qreal s, int i):
-        id(i),
-        part(p),
-        document(d),
-        size(s),
-        area(),
-        zoom(0),
-        isThumbnail(true)
-    { }
-};
+#include "rendertask.h"
 
 class RenderEngine : public QObject
 {
@@ -60,8 +22,9 @@
     const int DefaultIdealThreadCount = 2;
 
 public:
-    void enqueueTask(const QSharedPointer<LODocument>& doc, int part, const QRect& area, const qreal& zoom, int id);
-    void enqueueTask(const QSharedPointer<LODocument>& doc, int part, qreal size, int id);
+    void enqueueTileTask(const QSharedPointer<LODocument>& doc, int part, const QRect& area, qreal zoom, int id);
+    void enqueueThumbnailTask(const QSharedPointer<LODocument>& doc, int part, qreal size, int id);
+    void enqueueTask(AbstractRenderTask* task);
     void dequeueTask(int id);
 
     static RenderEngine* instance() {
@@ -76,23 +39,20 @@
     }
 
 Q_SIGNALS:
-    void renderFinished(int id, QImage img);
+    void tileRenderFinished(int id, QImage img);
     void thumbnailRenderFinished(int id, QImage img);
     void enabledChanged();
 
 private:
-    Q_INVOKABLE void internalRenderCallback(int id, QImage img, bool isThumbnail);
-
-private slots:
+    Q_INVOKABLE void internalRenderCallback(AbstractRenderTask* task, QImage img);
+    void disposeTask(AbstractRenderTask* task);
     void doNextTask();
 
 private:
-    QQueue<EngineTask> m_queue;
+    QQueue<AbstractRenderTask*> m_queue;
     int m_activeTaskCount;
     int m_idealThreadCount;
     int m_lastPart;
-
-    QAtomicInt m_enabled;
 };
 
 #endif // RENDERENGINE_H

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/rendertask.cpp'
--- src/plugin/libreofficetoolkit-qml-plugin/rendertask.cpp	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/rendertask.cpp	2015-10-18 22:08:02 +0000
@@ -0,0 +1,1 @@
+#include "rendertask.h"

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/rendertask.h'
--- src/plugin/libreofficetoolkit-qml-plugin/rendertask.h	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/rendertask.h	2015-10-18 22:08:02 +0000
@@ -0,0 +1,81 @@
+#ifndef RENDERTASK_H
+#define RENDERTASK_H
+
+#include <QObject>
+#include <QImage>
+#include <QSharedPointer>
+#include <QHash>
+#include <QQueue>
+#include <QAtomicInt>
+
+#include "lodocument.h"
+
+enum RenderTaskType
+{
+    RttUnknown = 0x0,
+    RttTile = 0x1,
+    RttImpressThumbnail = 0x2,
+    RttPdfPage = 0x3 // TODO
+};
+
+class AbstractRenderTask
+{
+
+public:
+    virtual RenderTaskType type() { return RttUnknown; }
+    virtual QImage doWork() = 0 ;
+    virtual ~AbstractRenderTask() { }
+
+    int id() { return m_id; }
+    void setId(int i) { m_id = i; }
+protected:
+    int m_id;
+};
+
+Q_DECLARE_METATYPE(AbstractRenderTask*)
+
+class LoRenderTask : public AbstractRenderTask
+{
+public:
+    int part() { return m_part; }
+    void setPart(int p) { m_part = p; }
+
+    QSharedPointer<LODocument> document() { return m_document; }
+    void setDocument(QSharedPointer<LODocument> d) { m_document = d; }
+protected:
+    int m_part;
+    QSharedPointer<LODocument> m_document;
+};
+
+class TileRenderTask : public LoRenderTask
+{
+public:
+    virtual RenderTaskType type() { return RttTile; }
+    virtual QImage doWork()
+    {
+        return m_document->paintTile(m_area.size(), m_area, m_zoom);
+    }
+    QRect area() { return m_area; }
+    void setArea(const QRect& a) { m_area = a; }
+    qreal zoom() { return m_zoom; }
+    void setZoom(qreal z) { m_zoom = z; }
+protected:
+    QRect m_area;
+    qreal m_zoom;
+};
+
+class ThumbnailRenderTask : public LoRenderTask
+{
+public:
+    virtual RenderTaskType type() { return RttImpressThumbnail; }
+    virtual QImage doWork()
+    {
+        return m_document->paintThumbnail(m_size);
+    }
+    qreal size() { return m_size; }
+    void setSize(qreal s) { m_size = s; }
+protected:
+    qreal m_size;
+};
+
+#endif // RENDERTASK_H


Follow ups