← Back to team overview

ubuntu-touch-coreapps-reviewers team mailing list archive

[Merge] lp:~verzegnassi-stefano/ubuntu-docviewer-app/reboot-update-emptystate-string-sdcard into lp:ubuntu-docviewer-app

 

Stefano Verzegnassi has proposed merging lp:~verzegnassi-stefano/ubuntu-docviewer-app/reboot-update-emptystate-string-sdcard into lp:ubuntu-docviewer-app.

Commit message:
Updated documents list empty state

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

For more details, see:
https://code.launchpad.net/~verzegnassi-stefano/ubuntu-docviewer-app/reboot-update-emptystate-string-sdcard/+merge/270534

Updated documents list empty state
-- 
Your team Ubuntu Document Viewer Developers is requested to review the proposed merge of lp:~verzegnassi-stefano/ubuntu-docviewer-app/reboot-update-emptystate-string-sdcard into lp:ubuntu-docviewer-app.
=== modified file 'README'
--- README	2015-01-30 19:20:39 +0000
+++ README	2015-09-09 13:32:03 +0000
@@ -8,13 +8,32 @@
 =========
 
 Install poppler's development files:
-sudo apt-get install libpoppler-qt5-dev
+    sudo apt install libpoppler-qt5-dev
 
 Install Qt5 private development files:
-sudo apt-get install qtdeclarative5-private-dev qtbase5-private-dev
-
-If you want to compile an arm click package, you need to install that package to the arm compilation environment. For example when using QtCreator for Ubuntu Touch, open Options -> Ubuntu -> Maintain, and then enter:
-
-apt-get install libpoppler-qt5-dev:armhf qtdeclarative5-private-dev:armhf qtbase5-private-dev:armhf
-
-
+    sudo apt install qtdeclarative5-private-dev qtbase5-private-dev
+
+If you want to compile an arm click package, you need to install that package
+to the arm compilation environment. For example when using QtCreator for
+Ubuntu Touch, open Options -> Ubuntu -> Maintain, and then enter:
+
+    apt install libpoppler-qt5-dev:armhf qtdeclarative5-private-dev:armhf qtbase5-private-dev:armhf
+
+LibreOffice viewer support
+==========================
+
+If you want to enable the LibreOffice viewer feature, you'll need to have a
+LibreOffice 5.0 installation on your development environment. At the time of
+writing, LibreOffice 5.0 is not yet in the archive, but you can easily install
+it from the pre-releases PPA. To do so, type the following commands on a
+terminal:
+
+    sudo apt-get purge libreoffice-core
+    sudo add-apt-repository ppa:libreoffice/libreoffice-prereleases
+    sudo apt-get update
+    sudo apt-get install libreoffice
+
+Then to compile the LibreOffice viewer plugin you'll simply need to install
+the LibreOffice Kit development files:
+
+    sudo apt install libreofficekit-dev

=== modified file 'po/com.ubuntu.docviewer.pot'
--- po/com.ubuntu.docviewer.pot	2015-07-24 09:12:38 +0000
+++ po/com.ubuntu.docviewer.pot	2015-09-09 13:32:03 +0000
@@ -8,7 +8,11 @@
 msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
+<<<<<<< TREE
 "POT-Creation-Date: 2015-07-24 11:10+0200\n"
+=======
+"POT-Creation-Date: 2015-08-30 18:02+0200\n"
+>>>>>>> MERGE-SOURCE
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@xxxxxx>\n"
@@ -33,11 +37,16 @@
 msgstr ""
 
 #: ../src/app/docviewer-application.cpp:171
+<<<<<<< TREE
 #: /home/stefano/Progetti/docviewer/build-ubuntu-docviewer-app-Desktop-Default/po/com.ubuntu.docviewer.desktop.in.in.h:1
+=======
+#: /home/stefano/Progetti/docviewer/Libreoffice/build-reboot-update-emptystate-string-sdcard-Desktop-Default/po/com.ubuntu.docviewer.desktop.in.in.h:1
+>>>>>>> MERGE-SOURCE
 msgid "Document Viewer"
 msgstr ""
 
 #: ../src/app/qml/common/DetailsPage.qml:27
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:112
 #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:97
 #: ../src/app/qml/textView/TextViewDefaultHeader.qml:83
 msgid "Details"
@@ -76,6 +85,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:76
 #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:61
 #: ../src/app/qml/textView/TextViewDefaultHeader.qml:61
 msgid "Close"
@@ -167,6 +177,7 @@
 
 #: ../src/app/qml/documentPage/DeleteFileDialog.qml:44
 #: ../src/app/qml/documentPage/DocumentPagePickModeHeader.qml:27
+#: ../src/app/qml/loView/LOViewGotoDialog.qml:52
 #: ../src/app/qml/pdfView/PdfViewGotoDialog.qml:52
 msgid "Cancel"
 msgstr ""
@@ -181,10 +192,10 @@
 msgid "No document found"
 msgstr ""
 
-#: ../src/app/qml/documentPage/DocumentEmptyState.qml:28
+#: ../src/app/qml/documentPage/DocumentEmptyState.qml:25
 msgid ""
 "Connect your device to any computer and simply drag files to the Documents "
-"folder."
+"folder or insert removable media with documents."
 msgstr ""
 
 #. TRANSLATORS: %1 refers to a time formatted as Locale.ShortFormat (e.g. hh:mm). It depends on system settings.
@@ -265,6 +276,7 @@
 msgstr ""
 
 #: ../src/app/qml/documentPage/DocumentPageSearchHeader.qml:27
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:76
 #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:61
 #: ../src/app/qml/textView/TextViewDefaultHeader.qml:61
 msgid "Back"
@@ -311,50 +323,80 @@
 msgid "Reverse order"
 msgstr ""
 
-#. TRANSLATORS: "Contents" refers to the "Table of Contents" of a PDF document.
-#: ../src/app/qml/pdfView/PdfContentsPage.qml:32
-#: ../src/app/qml/pdfView/PdfView.qml:37
-msgid "Contents"
-msgstr ""
-
-#: ../src/app/qml/pdfView/PdfContentsPage.qml:38
-msgid "Hide table of contents"
-msgstr ""
-
 #. TRANSLATORS: the first argument (%1) refers to the page currently shown on the screen,
 #. while the second one (%2) refers to the total pages count.
-#: ../src/app/qml/pdfView/PdfView.qml:34
+#: ../src/app/qml/loView/LOView.qml:34 ../src/app/qml/pdfView/PdfView.qml:34
 #, qt-format
 msgid "Page %1 of %2"
 msgstr ""
 
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:57
+msgid "LibreOffice text document"
+msgstr ""
+
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:59
+msgid "LibreOffice spread sheet"
+msgstr ""
+
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:61
+msgid "LibreOffice presentation"
+msgstr ""
+
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:63
+msgid "LibreOffice Draw document"
+msgstr ""
+
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:65
+msgid "Unknown LibreOffice document"
+msgstr ""
+
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:67
+msgid "Unknown type document"
+msgstr ""
+
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:100
 #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:85
 msgid "Go to page..."
 msgstr ""
 
+#: ../src/app/qml/loView/LOViewDefaultHeader.qml:106
 #: ../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:106
 #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:91
 #: ../src/app/qml/textView/TextViewDefaultHeader.qml:77
 msgid "Enable night mode"
 msgstr ""
 
+#: ../src/app/qml/loView/LOViewGotoDialog.qml:25
 #: ../src/app/qml/pdfView/PdfViewGotoDialog.qml:25
 msgid "Go to page"
 msgstr ""
 
+#: ../src/app/qml/loView/LOViewGotoDialog.qml:26
 #: ../src/app/qml/pdfView/PdfViewGotoDialog.qml:26
 #, qt-format
 msgid "Choose a page between 1 and %1"
 msgstr ""
 
+#: ../src/app/qml/loView/LOViewGotoDialog.qml:44
 #: ../src/app/qml/pdfView/PdfViewGotoDialog.qml:44
 msgid "GO!"
 msgstr ""
 
+#. TRANSLATORS: "Contents" refers to the "Table of Contents" of a PDF document.
+#: ../src/app/qml/pdfView/PdfContentsPage.qml:32
+#: ../src/app/qml/pdfView/PdfView.qml:37
+msgid "Contents"
+msgstr ""
+
+#: ../src/app/qml/pdfView/PdfContentsPage.qml:38
+msgid "Hide table of contents"
+msgstr ""
+
 #: ../src/app/qml/textView/TextView.qml:42
 msgid "Loading..."
 msgstr ""
@@ -369,6 +411,10 @@
 msgid "Open"
 msgstr ""
 
+<<<<<<< TREE
 #: /home/stefano/Progetti/docviewer/build-ubuntu-docviewer-app-Desktop-Default/po/com.ubuntu.docviewer.desktop.in.in.h:2
+=======
+#: /home/stefano/Progetti/docviewer/Libreoffice/build-reboot-update-emptystate-string-sdcard-Desktop-Default/po/com.ubuntu.docviewer.desktop.in.in.h:2
+>>>>>>> MERGE-SOURCE
 msgid "documents;viewer;pdf;reader;"
 msgstr ""

=== modified file 'src/app/content-communicator.cpp'
--- src/app/content-communicator.cpp	2015-04-27 15:58:12 +0000
+++ src/app/content-communicator.cpp	2015-09-09 13:32:03 +0000
@@ -241,11 +241,17 @@
  */
 bool ContentCommunicator::isSupportedMimetype(QString mimetype)
 {
-    if (mimetype.startsWith("text/"))
-        return true;
-
-    if (mimetype == "application/pdf")
-        return true;
-
-    return false;
+    // TODO: We should use a common shared code for DocumentViewer.DocumentsModel
+    // QML component and ContentHub. That will happen when we'll switch to
+    // QML ContentHub APIs.
+    return (mimetype.startsWith("text/")
+            || mimetype == "application/pdf"
+            || mimetype.startsWith("application/vnd.oasis.opendocument")
+            || mimetype == "application/msword")
+            || mimetype == "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
+            || mimetype == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+            || mimetype == "application/vnd.openxmlformats-officedocument.presentationml.presentation"
+            || mimetype == "application/msword"
+            || mimetype == "application/vnd.ms-excel"
+            || mimetype == "application/vnd.ms-powerpoint";
 }

=== modified file 'src/app/qml/common/loadComponent.js'
--- src/app/qml/common/loadComponent.js	2015-02-13 15:30:01 +0000
+++ src/app/qml/common/loadComponent.js	2015-09-09 13:32:03 +0000
@@ -27,6 +27,16 @@
     if (mimetype === "application/pdf")
         qmlToLoad = Qt.resolvedUrl("../pdfView/PdfView.qml");
 
+    // Check if LibreOffice document
+    if (mimetype.indexOf("application/vnd.oasis.opendocument") > -1
+            || mimetype === "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
+            || mimetype === "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+            || mimetype === "application/vnd.openxmlformats-officedocument.presentationml.presentation"
+            || mimetype === "application/msword"
+            || mimetype === "application/vnd.ms-excel"
+            || mimetype === "application/vnd.ms-powerpoint")
+        qmlToLoad = Qt.resolvedUrl("../loView/LOView.qml")
+
     if (qmlToLoad != "") {
        pageStack.push(qmlToLoad);
     } else {

=== modified file 'src/app/qml/documentPage/DocumentEmptyState.qml'
--- src/app/qml/documentPage/DocumentEmptyState.qml	2015-02-26 20:16:32 +0000
+++ src/app/qml/documentPage/DocumentEmptyState.qml	2015-09-09 13:32:03 +0000
@@ -22,10 +22,7 @@
 
     EmptyState {
         title: i18n.tr("No document found")
-
-        // TODO: Add "or insert removable media with documents." to subTitle when
-        // the support for SD card will be implemented.
-        subTitle: i18n.tr("Connect your device to any computer and simply drag files to the Documents folder.")
+        subTitle: i18n.tr("Connect your device to any computer and simply drag files to the Documents folder or insert removable media with documents.")
         iconName: "edit-copy"
 
         anchors.centerIn: parent

=== modified file 'src/app/qml/documentPage/DocumentGridDelegate.qml'
--- src/app/qml/documentPage/DocumentGridDelegate.qml	2015-07-14 13:43:17 +0000
+++ src/app/qml/documentPage/DocumentGridDelegate.qml	2015-09-09 13:32:03 +0000
@@ -46,6 +46,7 @@
         return Qt.formatDateTime(date, i18n.tr("dd-MM-yyyy hh:mm"))
     }
 
+<<<<<<< TREE
     title: model.name
     text: formattedDateTime()
     subText: Utils.printSize(i18n, model.size)
@@ -110,4 +111,171 @@
     }*/
 
     DocumentDelegateActions { id: documentDelegateActions }
+=======
+    Rectangle {
+        anchors { fill: parent; margins: units.gu(0.5) }
+
+        color: Qt.lighter(UbuntuColors.lightGrey)
+        clip: true
+
+        Loader {
+            id: selectionIcon
+
+            anchors {
+                right: parent.right
+                top: parent.top
+            }
+
+            z: 10
+
+            width: (status === Loader.Ready) ? item.implicitWidth : 0
+            visible: (status === Loader.Ready) && (item.width === item.implicitWidth)
+            Behavior on opacity {
+                NumberAnimation {
+                    duration: UbuntuAnimation.SnapDuration
+                }
+            }
+        }
+
+        Icon {
+            id: extStorageIcon
+
+            width: units.gu(4)
+            height: units.gu(4)
+            anchors {
+                left: parent.left
+                top: parent.top
+                margins: units.gu(0.5)
+            }
+
+            visible: model.isFromExternalStorage
+            source: Qt.resolvedUrl("../../graphics/sd-card-symbolic.png")
+        }
+
+        // Document mimetype icon
+        Icon {
+            anchors.centerIn: parent
+            anchors.verticalCenterOffset: - infoColumn.height * 0.3
+
+            width: units.gu(8); height: width
+
+            // At the moment the suru icon theme doesn't have much icons.
+            // Just some note for the future:
+            // TODO: Add icons for Office/ODF documents
+            // TODO: Whenever there will be icons for source code files, add them.
+            name: {
+                if (model.mimetype.substring(0, 5) === "text/")
+                    return "text-x-generic-symbolic"
+
+                if (model.mimetype.substring(0, 5) === "image")
+                    return "image-x-generic-symbolic"
+
+                if (model.mimetype === "application/pdf")
+                    return "application-pdf-symbolic"
+
+                if (model.mimetype === "application/vnd.oasis.opendocument.text"
+                        || model.mimetype === "application/msword"
+                        || model.mimetype === "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
+                    return "x-office-document-symbolic"
+
+                if (model.mimetype === "application/vnd.oasis.opendocument.spreadsheet"
+                        || model.mimetype === "application/vnd.ms-excel"
+                        || model.mimetype === "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
+                    return "x-office-spreadsheet-symbolic"
+
+                if (model.mimetype === "application/vnd.oasis.opendocument.presentation"
+                        || model.mimetype === "application/vnd.ms-powerpoint"
+                        || model.mimetype === "application/vnd.openxmlformats-officedocument.presentationml.presentation")
+                    return "x-office-presentation-symbolic"
+
+                return "package-x-generic-symbolic"
+            }
+        }
+
+        // Cover
+       /* Image {
+            anchors.fill: parent
+
+            source: {
+                if (model.cover !== "" && typeof model.cover !== "undefined")
+                    return model.cover
+
+                if (model.mimetype.toString().indexOf("image") !== -1)
+                    return model.path
+
+                return ""
+            }
+
+            sourceSize.width: width
+            fillMode: Image.PreserveAspectCrop
+        }*/
+
+        // Document info overlay
+        Rectangle {
+            id: overlay
+
+            anchors {
+                left: parent.left
+                right: parent.right
+                bottom: parent.bottom
+            }
+
+            height: infoColumn.height + units.gu(1)
+
+            color: UbuntuColors.darkGrey
+            opacity: 0.75
+            layer.enabled: true
+
+            // Document info
+            Column {
+                id: infoColumn
+                anchors {
+                    left: parent.left;
+                    right: parent.right
+                    verticalCenter: parent.verticalCenter
+                    margins: units.gu(0.5)
+                }
+
+                Label {
+                    text: model.name
+                    color: "white"
+
+                    elide: Text.ElideRight
+                    font.weight: Font.DemiBold
+                    fontSize: "small"
+
+                    anchors { left: parent.left; right: parent.right }
+                }
+
+                Label {
+                    text: formattedDateTime()
+                    color: "white"
+                    fontSize: "small"
+
+                    anchors { left: parent.left; right: parent.right }
+                }
+
+                Label {
+                    text: Utils.printSize(i18n, model.size)
+                    color: "white"
+                    fontSize: "small"
+
+                    anchors { left: parent.left; right: parent.right }
+                }
+            }   // Document info end
+        }
+
+        states: [
+            State {
+                name: "select"
+                when: selectionMode || selected
+                PropertyChanges {
+                    target: selectionIcon
+                    source: Qt.resolvedUrl("../upstreamComponents/ListItemWithActionsCheckBox.qml")
+                    anchors.margins: units.gu(1)
+                }
+            }
+        ]
+    }
+>>>>>>> MERGE-SOURCE
 }

=== modified file 'src/app/qml/documentPage/DocumentListDelegate.qml'
--- src/app/qml/documentPage/DocumentListDelegate.qml	2015-07-24 09:12:38 +0000
+++ src/app/qml/documentPage/DocumentListDelegate.qml	2015-09-09 13:32:03 +0000
@@ -92,6 +92,21 @@
                 if (model.mimetype === "application/pdf")
                     return "application-pdf-symbolic"
 
+                if (model.mimetype === "application/vnd.oasis.opendocument.text"
+                        || model.mimetype === "application/msword"
+                        || model.mimetype === "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
+                    return "x-office-document-symbolic"
+
+                if (model.mimetype === "application/vnd.oasis.opendocument.spreadsheet"
+                        || model.mimetype === "application/vnd.ms-excel"
+                        || model.mimetype === "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
+                    return "x-office-spreadsheet-symbolic"
+
+                if (model.mimetype === "application/vnd.oasis.opendocument.presentation"
+                        || model.mimetype === "application/vnd.ms-powerpoint"
+                        || model.mimetype === "application/vnd.openxmlformats-officedocument.presentationml.presentation")
+                    return "x-office-presentation-symbolic"
+
                 return "package-x-generic-symbolic"
             }
 

=== added directory 'src/app/qml/loView'
=== added file 'src/app/qml/loView/LOView.qml'
--- src/app/qml/loView/LOView.qml	1970-01-01 00:00:00 +0000
+++ src/app/qml/loView/LOView.qml	2015-09-09 13:32:03 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2013-2015 Canonical, Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import QtQuick 2.3
+import Ubuntu.Components 1.1
+import DocumentViewer.LibreOffice 1.0 as LO
+
+import "../common/utils.js" as Utils
+import "../upstreamComponents"
+
+Page {
+    id: loPage
+    title: Utils.getNameOfFile(file.path);
+
+    // Disable header auto-hide.
+    // TODO: Show/hide header if a user taps the page
+    flickable: null
+
+    // TRANSLATORS: the first argument (%1) refers to the page currently shown on the screen,
+    // while the second one (%2) refers to the total pages count.
+    property string currentPage: i18n.tr("Page %1 of %2").arg(loView.currentPageIndex + 1).arg(loView.count)
+
+    // Reset night mode shader settings when closing the page
+    // Component.onDestruction: mainView.nightModeEnabled = false
+
+    LO.Viewer {
+        id: loView
+        objectName: "loView"
+        anchors.fill: parent
+
+        clip: true
+        document: loDocument
+
+        Component.onCompleted: {
+            // WORKAROUND: Fix for wrong grid unit size
+            flickDeceleration = 1500 * units.gridUnit / 8
+            maximumFlickVelocity = 2500 * units.gridUnit / 8
+        }
+    }
+
+    Scrollbar { flickableItem: loView }
+    Scrollbar { flickableItem: loView; align: Qt.AlignBottom }
+
+    LO.Document {
+        id: loDocument
+
+        property bool isLoading: true
+        path: file.path
+
+       /* onPagesLoaded: {
+            isLoading = false;
+
+            var title = getDocumentInfo("Title")
+            if (title !== "")
+                loPage.title = title;
+
+            // Hide header when the document is ready
+            mainView.setHeaderVisibility(false);
+        }*/
+    }
+
+    // *** HEADER ***
+    state: "default"
+    states: LOViewDefaultHeader {
+        name: "default"
+        targetPage: loPage
+        //activityRunning: loView.currentPageItem.status == Image.Loading || loDocument.isLoading
+    }
+}

=== added file 'src/app/qml/loView/LOViewDefaultHeader.qml'
--- src/app/qml/loView/LOViewDefaultHeader.qml	1970-01-01 00:00:00 +0000
+++ src/app/qml/loView/LOViewDefaultHeader.qml	2015-09-09 13:32:03 +0000
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2014-2015 Canonical, Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import QtQuick 2.3
+import Ubuntu.Components 1.1
+import QtQuick.Layouts 1.1
+import Ubuntu.Components.Popups 1.0
+
+PageHeadState {
+    id: rootItem
+
+    property Page targetPage
+    property alias activityRunning: activity.running
+
+    head: targetPage.head
+
+    contents: RowLayout {
+        anchors.fill: parent
+        spacing: units.gu(1)
+
+        ActivityIndicator { id: activity }
+
+        Column {
+            id: layout
+            Layout.fillWidth: true
+
+            Label {
+                width: parent.width
+                //horizontalAlignment: Text.AlignHCenter
+                elide: Text.ElideMiddle
+
+                font.weight: Font.DemiBold
+                text: targetPage.title
+            }
+            Label {
+                width: parent.width
+                //horizontalAlignment: Text.AlignHCenter
+                elide: Text.ElideMiddle
+
+                fontSize: "small"
+                text: {
+                    switch(loDocument.documentType) {
+                    case 0:
+                        return i18n.tr("LibreOffice text document")
+                    case 1:
+                        return i18n.tr("LibreOffice spread sheet")
+                    case 2:
+                        return i18n.tr("LibreOffice presentation")
+                    case 3:
+                        return i18n.tr("LibreOffice Draw document")
+                    case 4:
+                        return i18n.tr("Unknown LibreOffice document")
+                    default:
+                        return i18n.tr("Unknown type document")
+                    }
+                }
+            }
+        }
+    }
+
+    backAction: Action {
+        iconName: "back"
+        text: (pageStack.depth > 1) ? i18n.tr("Back") : i18n.tr("Close")
+        onTriggered: {
+            if (pageStack.depth > 1) {
+                // Go back to Welcome page
+                pageStack.pop();
+            } else {
+                // File has been imported through Content Hub (or was not chosen through WelcomePage)
+                // Close the application and show our source app (e.g. ubuntu-filemanager-app, if used to open a document)
+                Qt.quit()
+            }
+        }
+    }
+
+    actions: [
+        Action {
+            iconName: "search"
+            // onTriggered: pageMain.state = "search"
+            //Disable it until we provide search in Poppler plugin.
+            enabled: false
+        },
+
+        Action {
+            objectName:"gotopage"
+            iconName: "browser-tabs"
+            text: i18n.tr("Go to page...")
+            onTriggered: PopupUtils.open(Qt.resolvedUrl("LOViewGotoDialog.qml"), targetPage)
+        },
+
+        Action {
+            iconName: "night-mode"
+            text: mainView.nightModeEnabled ? i18n.tr("Disable night mode") : i18n.tr("Enable night mode")
+            onTriggered: mainView.nightModeEnabled = !mainView.nightModeEnabled
+        },
+
+        Action {
+            objectName: "detailsAction"
+            text: i18n.tr("Details")
+            iconName: "info"
+            onTriggered: pageStack.push(Qt.resolvedUrl("../common/DetailsPage.qml"))
+        }
+    ]
+}

=== added file 'src/app/qml/loView/LOViewDelegate.qml'
--- src/app/qml/loView/LOViewDelegate.qml	1970-01-01 00:00:00 +0000
+++ src/app/qml/loView/LOViewDelegate.qml	2015-09-09 13:32:03 +0000
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2013-2015 Canonical, Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+import QtQuick 2.3
+import Ubuntu.Components 1.1
+
+Rectangle {
+    id: loPage
+
+    property int index: model.index
+    property bool _previewFetched: false
+
+    property alias status: pageImg.status
+
+    width: parent.width
+    height: width * (model.height / model.width)
+    color: "#E6E6E6"
+
+    // Preview page rendering. Used as placeholder while zooming the page.
+    // We generate the low resolution preview from the texture of the PDF page,
+    // so that we can keep page rendering as fast as possible.
+    ShaderEffectSource {
+        id: previewImg
+        anchors.fill: parent
+
+        // We cannot change its opacity or visibility, otherwise the texture will be refreshed,
+        // even if live is false.
+        live: false
+        textureSize: Qt.size(256, 256 * (model.height / model.width))
+    }
+
+    Image {
+        id: pageImg
+        anchors.fill: parent
+
+        source: "image://libreoffice/page/" + index;
+        sourceSize.width: loPage.width
+
+        onStatusChanged: {
+            // This is supposed to run the first time PdfViewDelegate gets the page rendering.
+            if (!_previewFetched) {
+                if (status == Image.Ready) {
+                    previewImg.sourceItem = pageImg
+                    // Re-assign sourceItem property, so the texture is not updated when Image status changes.
+                    previewImg.sourceItem = loPage
+                }
+            }
+        }
+
+        // Request a new page rendering. The order, which pages are requested with, depends on the distance from the currentPage
+        Timer {
+            id: _zoomTimer
+            interval: {
+                var diff = Math.abs(loView.currentPageIndex - model.index)
+                var prov = loDocument.providersNumber * 0.5
+
+                if (diff < prov)
+                    return 0
+                else
+                    return (diff - prov) * 10
+            }
+
+            onTriggered: {
+                pageImg.sourceSize.width = loPage.width;
+            }
+        }
+    }
+
+    // Page rendering depends on the width of PdfViewDelegate.
+    // Because of this, we have multiple callings to ImageProvider while zooming.
+    // Just avoid it.
+    Connections {
+        target: pinchy
+
+        onPinchStarted: _zoomTimer.stop();
+        onPinchUpdated: {
+            // This ensures that page image is not reloaded when the maximumScale or minimumScale has already been reached.
+            if ( !(_zoomHelper.scale >= 2.5 && pinch.scale > 1.0) && !(_zoomHelper.scale <= 1.0 && pinch.scale < 1.0) )
+                pageImg.sourceSize.width = 0;
+        }
+        onPinchFinished: _zoomTimer.restart();
+    }
+}

=== added file 'src/app/qml/loView/LOViewGotoDialog.qml'
--- src/app/qml/loView/LOViewGotoDialog.qml	1970-01-01 00:00:00 +0000
+++ src/app/qml/loView/LOViewGotoDialog.qml	2015-09-09 13:32:03 +0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014-2015 Canonical, Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import QtQuick 2.3
+import Ubuntu.Components 1.1
+import Ubuntu.Components.Popups 1.0
+
+Dialog {
+    id: goToPageDialog
+    objectName:"LOViewGotoDialog"
+
+    title: i18n.tr("Go to page")
+    text: i18n.tr("Choose a page between 1 and %1").arg(loView.count)
+
+    TextField {
+        id: goToPageTextField
+        objectName:"goToPageTextField"
+
+        width: parent.width
+
+        hasClearButton: true
+        inputMethodHints: Qt.ImhFormattedNumbersOnly
+        validator: IntValidator{ bottom: 1; top: loView.count }
+
+        Keys.onReturnPressed: goToPage()
+        Component.onCompleted: forceActiveFocus()
+    }
+
+    Button {
+        objectName:"GOButton"
+        text: i18n.tr("GO!")
+        color: UbuntuColors.green
+
+        enabled: goToPageTextField.acceptableInput
+        onClicked: goToPage()
+    }
+
+    Button {
+        text: i18n.tr("Cancel")
+        onClicked: PopupUtils.close(goToPageDialog)
+    }
+
+    function goToPage() {
+        loView.positionAtIndex((goToPageTextField.text - 1))
+        PopupUtils.close(goToPageDialog)
+    }
+}

=== modified file 'src/plugin/CMakeLists.txt'
--- src/plugin/CMakeLists.txt	2014-10-20 21:38:36 +0000
+++ src/plugin/CMakeLists.txt	2015-09-09 13:32:03 +0000
@@ -1,2 +1,3 @@
 add_subdirectory(file-qml-plugin)
 add_subdirectory(poppler-qml-plugin)
+add_subdirectory(libreofficetoolkit-qml-plugin)

=== modified file 'src/plugin/file-qml-plugin/documentmodel.cpp'
--- src/plugin/file-qml-plugin/documentmodel.cpp	2015-07-30 11:06:22 +0000
+++ src/plugin/file-qml-plugin/documentmodel.cpp	2015-09-09 13:32:03 +0000
@@ -118,7 +118,16 @@
     QMimeDatabase db;
     QString mimetype = db.mimeTypeForFile(path).name();
 
-    return (mimetype.startsWith("text/") || mimetype == "application/pdf");
+    return (mimetype.startsWith("text/")
+            || mimetype == "application/pdf"
+            || mimetype.startsWith("application/vnd.oasis.opendocument")
+            || mimetype == "application/msword")
+            || mimetype == "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
+            || mimetype == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+            || mimetype == "application/vnd.openxmlformats-officedocument.presentationml.presentation"
+            || mimetype == "application/msword"
+            || mimetype == "application/vnd.ms-excel"
+            || mimetype == "application/vnd.ms-powerpoint";
 }
 
 QHash<int, QByteArray> DocumentModel::roleNames() const

=== added directory 'src/plugin/libreofficetoolkit-qml-plugin'
=== added file 'src/plugin/libreofficetoolkit-qml-plugin/CMakeLists.txt'
--- src/plugin/libreofficetoolkit-qml-plugin/CMakeLists.txt	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/CMakeLists.txt	2015-09-09 13:32:03 +0000
@@ -0,0 +1,46 @@
+set(PLUGIN_DIR DocumentViewer/LibreOffice)
+
+file(GLOB_RECURSE QML_SRCS *.qml *.js)
+include_directories(
+	${CMAKE_CURRENT_SOURCE_DIR}
+	${CMAKE_CURRENT_BINARY_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/LibreOfficeKit/
+)
+
+#add the sources to compile
+set(libreofficetoolkitqmlplugin_SRCS
+    plugin.cpp
+    lodocument.cpp
+    loview.cpp
+    tileitem.cpp
+    ${QML_SRCS}
+)
+
+#add the headers to compile
+set(libreofficetoolkitqmlplugin_HDRS
+    twips.h
+    config.h
+)
+
+add_library(libreofficetoolkitqmlplugin MODULE
+    ${libreofficetoolkitqmlplugin_SRCS}
+    ${libreofficetoolkitqmlplugin_HDRS}
+)
+
+#target_link_libraries(libreofficetoolkitqmlplugin dl)
+qt5_use_modules(libreofficetoolkitqmlplugin Gui Qml Quick)
+
+# Copy the plugin, the qmldir file and other assets to the build dir for running in QtCreator
+if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
+add_custom_command(TARGET libreofficetoolkitqmlplugin POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR}
+    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/qmldir ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR}
+    COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:libreofficetoolkitqmlplugin> ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR}
+    COMMAND ${CMAKE_COMMAND} -E copy ${QML_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR}
+)
+endif(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
+
+# Install plugin file
+install(TARGETS libreofficetoolkitqmlplugin DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR})
+install(FILES qmldir DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR})
+install(FILES ${QML_SRCS} DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR})

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/LOViewer.qml'
--- src/plugin/libreofficetoolkit-qml-plugin/LOViewer.qml	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/LOViewer.qml	2015-09-09 13:32:03 +0000
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 Canonical, Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import QtQuick 2.4
+import DocumentViewer.LibreOffice 1.0 as LibreOffice
+
+Flickable {
+    id: rootFlickable
+
+    property alias document:    view.document
+    property alias zoomFactor:  view.zoomFactor
+    property alias cacheBuffer: view.cacheBuffer
+
+    contentHeight: view.height * view.zoomFactor
+    contentWidth: view.width * view.zoomFactor
+
+    boundsBehavior: Flickable.StopAtBounds
+
+    LibreOffice.View {
+        id: view
+
+        parentFlickable: rootFlickable
+    }
+}

=== added directory 'src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit'
=== added file 'src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKit.h'
--- src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKit.h	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKit.h	2015-09-09 13:32:03 +0000
@@ -0,0 +1,171 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_H
+#define INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_H
+
+#include <stddef.h>
+
+#include <LibreOfficeKit/LibreOfficeKitTypes.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct _LibreOfficeKit LibreOfficeKit;
+typedef struct _LibreOfficeKitClass LibreOfficeKitClass;
+
+typedef struct _LibreOfficeKitDocument LibreOfficeKitDocument;
+typedef struct _LibreOfficeKitDocumentClass LibreOfficeKitDocumentClass;
+
+// Do we have an extended member in this struct ?
+#define LIBREOFFICEKIT_HAS_MEMBER(strct,member,nSize) \
+    (offsetof(strct, member) < (nSize))
+
+#define LIBREOFFICEKIT_HAS(pKit,member) LIBREOFFICEKIT_HAS_MEMBER(LibreOfficeKitClass,member,(pKit)->pClass->nSize)
+
+struct _LibreOfficeKit
+{
+    LibreOfficeKitClass* pClass;
+};
+
+struct _LibreOfficeKitClass
+{
+    size_t  nSize;
+
+    void (*destroy) (LibreOfficeKit* pThis);
+
+    LibreOfficeKitDocument* (*documentLoad) (LibreOfficeKit* pThis,
+                                             const char* pURL);
+
+    char* (*getError) (LibreOfficeKit* pThis);
+
+    LibreOfficeKitDocument* (*documentLoadWithOptions) (LibreOfficeKit* pThis,
+                                                        const char* pURL,
+                                                        const char* pOptions);
+#ifdef LOK_USE_UNSTABLE_API
+    void (*registerCallback) (LibreOfficeKit* pThis,
+                              LibreOfficeKitCallback pCallback,
+                              void* pData);
+#endif
+};
+
+#define LIBREOFFICEKIT_DOCUMENT_HAS(pDoc,member) LIBREOFFICEKIT_HAS_MEMBER(LibreOfficeKitDocumentClass,member,(pDoc)->pClass->nSize)
+
+struct _LibreOfficeKitDocument
+{
+    LibreOfficeKitDocumentClass* pClass;
+};
+
+struct _LibreOfficeKitDocumentClass
+{
+    size_t  nSize;
+
+    void (*destroy) (LibreOfficeKitDocument* pThis);
+
+    int (*saveAs) (LibreOfficeKitDocument* pThis,
+                   const char* pUrl,
+                   const char* pFormat,
+                   const char* pFilterOptions);
+
+#ifdef LOK_USE_UNSTABLE_API
+    /// @see lok::Document::getDocumentType().
+    int (*getDocumentType) (LibreOfficeKitDocument* pThis);
+
+    /// @see lok::Document::getParts().
+    int (*getParts) (LibreOfficeKitDocument* pThis);
+
+    /// @see lok::Document::getPart().
+    int (*getPart) (LibreOfficeKitDocument* pThis);
+
+    /// @see lok::Document::setPart().
+    void (*setPart) (LibreOfficeKitDocument* pThis,
+                     int nPart);
+
+    /// @see lok::Document::getPartName().
+    char* (*getPartName) (LibreOfficeKitDocument* pThis,
+                          int nPart);
+
+    /** Sets mode of the current part.
+     *
+     * @param nMode - element from the LibreOfficeKitPartMode enum.
+     */
+    void (*setPartMode) (LibreOfficeKitDocument* pThis,
+                         int nMode);
+
+    /// @see lok::Document::paintTile().
+    void (*paintTile) (LibreOfficeKitDocument* pThis,
+                       unsigned char* pBuffer,
+                       const int nCanvasWidth,
+                       const int nCanvasHeight,
+                       const int nTilePosX,
+                       const int nTilePosY,
+                       const int nTileWidth,
+                       const int nTileHeight);
+
+    /// @see lok::Document::getDocumentSize().
+    void (*getDocumentSize) (LibreOfficeKitDocument* pThis,
+                             long* pWidth,
+                             long* pHeight);
+
+    /// @see lok::Document::initializeForRendering().
+    void (*initializeForRendering) (LibreOfficeKitDocument* pThis);
+
+    void (*registerCallback) (LibreOfficeKitDocument* pThis,
+                              LibreOfficeKitCallback pCallback,
+                              void* pData);
+
+    /// @see lok::Document::postKeyEvent
+    void (*postKeyEvent) (LibreOfficeKitDocument* pThis,
+                          int nType,
+                          int nCharCode,
+                          int nKeyCode);
+
+    /// @see lok::Document::postMouseEvent
+    void (*postMouseEvent) (LibreOfficeKitDocument* pThis,
+                            int nType,
+                            int nX,
+                            int nY,
+                            int nCount);
+
+    /// @see lok::Document::postUnoCommand
+    void (*postUnoCommand) (LibreOfficeKitDocument* pThis,
+                            const char* pCommand,
+                            const char* pArguments);
+
+    /// @see lok::Document::setTextSelection
+    void (*setTextSelection) (LibreOfficeKitDocument* pThis,
+                              int nType,
+                              int nX,
+                              int nY);
+
+    /// @see lok::Document::getTextSelection
+    char* (*getTextSelection) (LibreOfficeKitDocument* pThis,
+                               const char* pMimeType,
+                               char** pUsedMimeType);
+
+    /// @see lok::Document::setGraphicSelection
+    void (*setGraphicSelection) (LibreOfficeKitDocument* pThis,
+                                 int nType,
+                                 int nX,
+                                 int nY);
+
+    /// @see lok::Document::resetSelection
+    void (*resetSelection) (LibreOfficeKitDocument* pThis);
+#endif // LOK_USE_UNSTABLE_API
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKit.hxx'
--- src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKit.hxx	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKit.hxx	2015-09-09 13:32:03 +0000
@@ -0,0 +1,310 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_HXX
+#define INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_HXX
+
+#include "LibreOfficeKit.h"
+
+/*
+ * The reasons this C++ code is not as pretty as it could be are:
+ *  a) provide a pure C API - that's useful for some people
+ *  b) allow ABI stability - C++ vtables are not good for that.
+ *  c) avoid C++ types as part of the API.
+ */
+namespace lok
+{
+
+/// The lok::Document class represents one loaded document instance.
+class Document
+{
+private:
+    LibreOfficeKitDocument* mpDoc;
+
+public:
+    /// A lok::Document is typically created by the lok::Office::documentLoad() method.
+    inline Document(LibreOfficeKitDocument* pDoc) :
+        mpDoc(pDoc)
+    {}
+
+    inline ~Document()
+    {
+        mpDoc->pClass->destroy(mpDoc);
+    }
+
+    /**
+     * Stores the document's persistent data to a URL and
+     * continues to be a representation of the old URL.
+     *
+     * @param pUrl the location where to store the document
+     * @param pFormat the format to use while exporting, when omitted, then deducted from pURL's extension
+     * @param pFilterOptions options for the export filter, e.g. SkipImages.
+     */
+    inline bool saveAs(const char* pUrl, const char* pFormat = NULL, const char* pFilterOptions = NULL)
+    {
+        return mpDoc->pClass->saveAs(mpDoc, pUrl, pFormat, pFilterOptions) != 0;
+    }
+
+    /// Gives access to the underlying C pointer.
+    inline LibreOfficeKitDocument *get() { return mpDoc; }
+
+#ifdef LOK_USE_UNSTABLE_API
+    /**
+     * Get document type.
+     *
+     * @return an element of the LibreOfficeKitDocumentType enum.
+     */
+    inline int getDocumentType()
+    {
+        return mpDoc->pClass->getDocumentType(mpDoc);
+    }
+
+    /**
+     * Get number of part that the document contains.
+     *
+     * Part refers to either indivual sheets in a Calc, or slides in Impress,
+     * and has no relevance for Writer.
+     */
+    inline int getParts()
+    {
+        return mpDoc->pClass->getParts(mpDoc);
+    }
+
+    /// Get the current part of the document.
+    inline int getPart()
+    {
+        return mpDoc->pClass->getPart(mpDoc);
+    }
+
+    /// Set the current part of the document.
+    inline void setPart(int nPart)
+    {
+        mpDoc->pClass->setPart(mpDoc, nPart);
+    }
+
+    /// Get the current part's name.
+    inline char* getPartName(int nPart)
+    {
+        return mpDoc->pClass->getPartName(mpDoc, nPart);
+    }
+
+    /**
+     * Renders a subset of the document to a pre-allocated buffer.
+     *
+     * Note that the buffer size and the tile size implicitly supports
+     * rendering at different zoom levels, as the number of rendered pixels and
+     * the rendered rectangle of the document are independent.
+     *
+     * @param pBuffer pointer to the buffer, its size is determined by nCanvasWidth and nCanvasHeight.
+     * @param nCanvasWidth number of pixels in a row of pBuffer.
+     * @param nCanvasHeight number of pixels in a column of pBuffer.
+     * @param nTilePosX logical X position of the top left corner of the rendered rectangle, in TWIPs.
+     * @param nTilePosY logical Y position of the top left corner of the rendered rectangle, in TWIPs.
+     * @param nTileWidth logical width of the rendered rectangle, in TWIPs.
+     * @param nTileHeight logical height of the rendered rectangle, in TWIPs.
+     */
+    inline void paintTile(
+                          unsigned char* pBuffer,
+                          const int nCanvasWidth,
+                          const int nCanvasHeight,
+                          const int nTilePosX,
+                          const int nTilePosY,
+                          const int nTileWidth,
+                          const int nTileHeight)
+    {
+        return mpDoc->pClass->paintTile(mpDoc, pBuffer, nCanvasWidth, nCanvasHeight,
+                                nTilePosX, nTilePosY, nTileWidth, nTileHeight);
+    }
+
+    /// Get the document sizes in TWIPs.
+    inline void getDocumentSize(long* pWidth, long* pHeight)
+    {
+        mpDoc->pClass->getDocumentSize(mpDoc, pWidth, pHeight);
+    }
+
+    /**
+     * Initialize document for rendering.
+     *
+     * Sets the rendering and document parameters to default values that are
+     * needed to render the document correctly using tiled rendering. This
+     * method has to be called right after documentLoad() in case any of the
+     * tiled rendering methods are to be used later.
+     */
+    inline void initializeForRendering()
+    {
+        mpDoc->pClass->initializeForRendering(mpDoc);
+    }
+
+    /**
+     * Registers a callback. LOK will invoke this function when it wants to
+     * inform the client about events.
+     *
+     * @param pCallback the callback to invoke
+     * @param pData the user data, will be passed to the callback on invocation
+     */
+    inline void registerCallback(LibreOfficeKitCallback pCallback, void* pData)
+    {
+        mpDoc->pClass->registerCallback(mpDoc, pCallback, pData);
+    }
+
+    /**
+     * Posts a keyboard event to the focused frame.
+     *
+     * @param nType Event type, like press or release.
+     * @param nCharCode contains the Unicode character generated by this event or 0
+     * @param nKeyCode contains the integer code representing the key of the event (non-zero for control keys)
+     */
+    inline void postKeyEvent(int nType, int nCharCode, int nKeyCode)
+    {
+        mpDoc->pClass->postKeyEvent(mpDoc, nType, nCharCode, nKeyCode);
+    }
+
+    /**
+     * Posts a mouse event to the document.
+     *
+     * @param nType Event type, like down, move or up.
+     * @param nX horizontal position in document coordinates
+     * @param nY vertical position in document coordinates
+     * @param nCount number of clicks: 1 for single click, 2 for double click
+     */
+    inline void postMouseEvent(int nType, int nX, int nY, int nCount)
+    {
+        mpDoc->pClass->postMouseEvent(mpDoc, nType, nX, nY, nCount);
+    }
+
+    /**
+     * Posts an UNO command to the document.
+     *
+     * Example argument string:
+     *
+     * {
+     *     "SearchItem.SearchString":
+     *     {
+     *         "type": "string",
+     *         "value": "foobar"
+     *     },
+     *     "SearchItem.Backward":
+     *     {
+     *         "type": "boolean",
+     *         "value": "false"
+     *     }
+     * }
+     *
+     * @param pCommand uno command to be posted to the document, like ".uno:Bold"
+     * @param pArguments arguments of the uno command.
+     */
+    inline void postUnoCommand(const char* pCommand, const char* pArguments = 0)
+    {
+        mpDoc->pClass->postUnoCommand(mpDoc, pCommand, pArguments);
+    }
+
+    /**
+     * Sets the start or end of a text selection.
+     *
+     * @param nType @see LibreOfficeKitSetTextSelectionType
+     * @param nX horizontal position in document coordinates
+     * @param nY vertical position in document coordinates
+     */
+    inline void setTextSelection(int nType, int nX, int nY)
+    {
+        mpDoc->pClass->setTextSelection(mpDoc, nType, nX, nY);
+    }
+
+    /**
+     * Gets the currently selected text.
+     *
+     * @param pMimeType suggests the return format, for example text/plain;charset=utf-8.
+     * @param pUsedMimeType output parameter to inform about the determined format (suggested one or plain text).
+     */
+    inline char* getTextSelection(const char* pMimeType, char** pUsedMimeType = 0)
+    {
+        return mpDoc->pClass->getTextSelection(mpDoc, pMimeType, pUsedMimeType);
+    }
+
+    /**
+     * Adjusts the graphic selection.
+     *
+     * @param nType @see LibreOfficeKitSetGraphicSelectionType
+     * @param nX horizontal position in document coordinates
+     * @param nY vertical position in document coordinates
+     */
+    inline void setGraphicSelection(int nType, int nX, int nY)
+    {
+        mpDoc->pClass->setGraphicSelection(mpDoc, nType, nX, nY);
+    }
+
+    /**
+     * Gets rid of any text or graphic selection.
+     */
+    inline void resetSelection()
+    {
+        mpDoc->pClass->resetSelection(mpDoc);
+    }
+#endif // LOK_USE_UNSTABLE_API
+};
+
+/// The lok::Office class represents one started LibreOfficeKit instance.
+class Office
+{
+private:
+    LibreOfficeKit* mpThis;
+
+public:
+    /// A lok::Office is typically created by the lok_cpp_init() function.
+    inline Office(LibreOfficeKit* pThis) :
+        mpThis(pThis)
+    {}
+
+    inline ~Office()
+    {
+        mpThis->pClass->destroy(mpThis);
+    }
+
+    /**
+     * Loads a document from an URL.
+     *
+     * @param pUrl the URL of the document to load
+     * @param pFilterOptions options for the import filter, e.g. SkipImages.
+     */
+    inline Document* documentLoad(const char* pUrl, const char* pFilterOptions = NULL)
+    {
+        LibreOfficeKitDocument* pDoc = NULL;
+
+        if (LIBREOFFICEKIT_HAS(mpThis, documentLoadWithOptions))
+            pDoc = mpThis->pClass->documentLoadWithOptions(mpThis, pUrl, pFilterOptions);
+        else
+            pDoc = mpThis->pClass->documentLoad(mpThis, pUrl);
+
+        if (pDoc == NULL)
+            return NULL;
+
+        return new Document(pDoc);
+    }
+
+    /// Returns the last error as a string, the returned pointer has to be freed by the caller.
+    inline char* getError()
+    {
+        return mpThis->pClass->getError(mpThis);
+    }
+};
+
+/// Factory method to create a lok::Office instance.
+inline Office* lok_cpp_init(const char* pInstallPath, const char* pUserProfilePath = NULL)
+{
+    LibreOfficeKit* pThis = lok_init_2(pInstallPath, pUserProfilePath);
+    if (pThis == NULL || pThis->pClass->nSize == 0)
+        return NULL;
+    return new ::lok::Office(pThis);
+}
+
+}
+
+#endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKitEnums.h'
--- src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKitEnums.h	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKitEnums.h	2015-09-09 13:32:03 +0000
@@ -0,0 +1,229 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITENUMS_H
+#define INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITENUMS_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef LOK_USE_UNSTABLE_API
+typedef enum
+{
+  LOK_DOCTYPE_TEXT,
+  LOK_DOCTYPE_SPREADSHEET,
+  LOK_DOCTYPE_PRESENTATION,
+  LOK_DOCTYPE_DRAWING,
+  LOK_DOCTYPE_OTHER
+}
+LibreOfficeKitDocumentType;
+
+typedef enum
+{
+    LOK_PARTMODE_DEFAULT,
+    LOK_PARTMODE_SLIDE,
+    LOK_PARTMODE_NOTES,
+    LOK_PARTMODE_SLIDENOTES,
+    LOK_PARTMODE_EMBEDDEDOBJ
+}
+LibreOfficeKitPartMode;
+
+typedef enum
+{
+    /**
+     * Any tiles which are over the rectangle described in the payload are no
+     * longer valid.
+     *
+     * Rectangle format: "width, height, x, y", where all numbers are document
+     * coordinates, in twips. When all tiles are supposed to be dropped, the
+     * format is the "EMPTY" string.
+     */
+    LOK_CALLBACK_INVALIDATE_TILES,
+    /**
+     * The size and/or the position of the visible cursor changed.
+     *
+     * Rectangle format is the same as LOK_CALLBACK_INVALIDATE_TILES.
+     */
+    LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR,
+    /**
+     * The list of rectangles representing the current text selection changed.
+     *
+     * List format is "rectangle1[; rectangle2[; ...]]" (without quotes and
+     * brackets), where rectangleN has the same format as
+     * LOK_CALLBACK_INVALIDATE_TILES. When there is no selection, an empty
+     * string is provided.
+     */
+    LOK_CALLBACK_TEXT_SELECTION,
+    /**
+     * The position and size of the cursor rectangle at the text
+     * selection start. It is used to draw the selection handles.
+     *
+     * This callback must be called prior to LOK_CALLBACK_TEXT_SELECTION every
+     * time the selection is updated.
+     *
+     * Rectangle format is the same as LOK_CALLBACK_INVALIDATE_TILES.
+     */
+    LOK_CALLBACK_TEXT_SELECTION_START,
+    /**
+     * The position and size of the cursor rectangle at the text
+     * selection end. It is used to draw the selection handles.
+     *
+     * This callback must be called prior to LOK_CALLBACK_TEXT_SELECTION every
+     * time the selection is updated.
+     *
+     * Rectangle format is the same as LOK_CALLBACK_INVALIDATE_TILES.
+     */
+    LOK_CALLBACK_TEXT_SELECTION_END,
+    /**
+     * The blinking text cursor is now visible or not.
+     *
+     * Clients should assume that this is true initially and are expected to
+     * hide the blinking cursor at the rectangle described by
+     * LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR once it becomes false. Payload is
+     * either the "true" or the "false" string.
+     */
+    LOK_CALLBACK_CURSOR_VISIBLE,
+    /**
+     * The size and/or the position of the graphic selection changed.
+     *
+     * Rectangle format is the same as LOK_CALLBACK_INVALIDATE_TILES.
+     */
+    LOK_CALLBACK_GRAPHIC_SELECTION,
+
+    /**
+     * User clicked on an hyperlink that should be handled by other
+     * applications accordingly.
+     */
+    LOK_CALLBACK_HYPERLINK_CLICKED,
+
+    /**
+     * Emit state update to the client.
+     * For example, when cursor is on bold text, this callback is triggered
+     * with payload: ".uno:Bold=true"
+     */
+    LOK_CALLBACK_STATE_CHANGED,
+
+    /**
+     * Start a "status indicator" (here restricted to a progress bar type
+     * indicator). The payload is the descriptive text (or empty). Even if
+     * there is no documentation that would promise so, we assume that de facto
+     * for a document being viewed or edited, there will be at most one status
+     * indicator, and its descriptive text will not change.
+     *
+     * Note that for the case of the progress indication during loading of a
+     * document, the status indicator callbacks will arrive to the callback
+     * registered for the LibreOfficeKit (singleton) object, not a
+     * LibreOfficeKitDocument one, because we are in the very progress of
+     * loading a docuemnt and then constructing a LibreOfficeKitDocument
+     * object.
+     */
+    LOK_CALLBACK_STATUS_INDICATOR_START,
+
+    /**
+     * Sets the numeric value of the status indicator.
+     * The payload should be a percentage, an integer between 0 and 100.
+     */
+    LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE,
+
+    /**
+     * Ends the status indicator.
+     *
+     * Not necessarily ever emitted.
+     */
+    LOK_CALLBACK_STATUS_INDICATOR_FINISH,
+
+    /**
+     * No match was found for the search input
+     */
+    LOK_CALLBACK_SEARCH_NOT_FOUND,
+
+    /**
+     * Size of the document changed.
+     *
+     * Payload format is "width, height", i.e. clients get the new size without
+     * having to do an explicit lok::Document::getDocumentSize() call.
+     */
+    LOK_CALLBACK_DOCUMENT_SIZE_CHANGED,
+
+    /**
+     * The current part number is changed.
+     *
+     * Payload is a single 0-based integer.
+     */
+    LOK_CALLBACK_SET_PART
+}
+LibreOfficeKitCallbackType;
+
+typedef enum
+{
+    /// A key on the keyboard is pressed.
+    LOK_KEYEVENT_KEYINPUT,
+    /// A key on the keyboard is released.
+    LOK_KEYEVENT_KEYUP
+}
+LibreOfficeKitKeyEventType;
+
+typedef enum
+{
+    /// A pressed gesture has started.
+    LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+    /// A pressed gesture has finished.
+    LOK_MOUSEEVENT_MOUSEBUTTONUP,
+    /// A change has happened during a press gesture.
+    LOK_MOUSEEVENT_MOUSEMOVE
+}
+LibreOfficeKitMouseEventType;
+
+typedef enum
+{
+    /// The start of selection is to be adjusted.
+    LOK_SETTEXTSELECTION_START,
+    /// The end of selection is to be adjusted.
+    LOK_SETTEXTSELECTION_END,
+    /// Both the start and the end of selection is to be adjusted.
+    LOK_SETTEXTSELECTION_RESET
+}
+LibreOfficeKitSetTextSelectionType;
+
+typedef enum
+{
+    /**
+     * A move or a resize action starts. It is assumed that there is a valid
+     * graphic selection (see LOK_CALLBACK_GRAPHIC_SELECTION) and the supplied
+     * coordinates are the ones the user tapped on.
+     *
+     * The type of the action is move by default, unless the coordinates are
+     * the position of a handle (see below), in which case it's a resize.
+     *
+     * There are 8 handles for a graphic selection:
+     * - top-left, top-center, top-right
+     * - middle-left, middle-right
+     * - bottom-left, bottom-center, bottom-right
+     */
+    LOK_SETGRAPHICSELECTION_START,
+    /**
+     * A move or resize action stops. It is assumed that this is always used
+     * only after a LOK_SETTEXTSELECTION_START. The supplied coordinates are
+     * the ones where the user released the screen.
+     */
+    LOK_SETGRAPHICSELECTION_END
+}
+LibreOfficeKitSetGraphicSelectionType;
+
+#endif // LOK_USE_UNSTABLE_API
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITENUMS_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKitGtk.h'
--- src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKitGtk.h	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKitGtk.h	2015-09-09 13:32:03 +0000
@@ -0,0 +1,86 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITGTK_H
+#define INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITGTK_H
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#define LOK_USE_UNSTABLE_API
+#include <LibreOfficeKit/LibreOfficeKit.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define LOK_DOCVIEW(obj)          GTK_CHECK_CAST (obj, lok_docview_get_type(), LOKDocView)
+#define LOK_DOCVIEW_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, lok_docview_get_type(), LOKDocViewClass)
+#define IS_LOK_DOCVIEW(obj)       GTK_CHECK_TYPE (obj, lok_docview_get_type())
+
+typedef struct _LOKDocView       LOKDocView;
+typedef struct _LOKDocViewClass  LOKDocViewClass;
+
+struct _LOKDocView
+{
+    GtkScrolledWindow aScrollWindow;
+    struct LOKDocView_Impl* m_pImpl;
+};
+
+struct _LOKDocViewClass
+{
+  GtkScrolledWindowClass parent_class;
+  void (* edit_changed)  (LOKDocView* pView, gboolean was_edit);
+  void (* command_changed) (LOKDocView* pView, char* new_state);
+  void (* search_not_found) (LOKDocView* pView, char* new_state);
+  void (* part_changed) (LOKDocView* pView, int new_part);
+};
+
+guint           lok_docview_get_type        (void);
+GtkWidget*      lok_docview_new             ( LibreOfficeKit* pOffice );
+gboolean        lok_docview_open_document   (LOKDocView* pDocView,
+                                             char* pPath);
+
+/// Gets the document the viewer displays.
+LibreOfficeKitDocument* lok_docview_get_document(LOKDocView* pDocView);
+
+void            lok_docview_set_zoom        (LOKDocView* pDocView,
+                                             float fZoom);
+float           lok_docview_get_zoom        (LOKDocView* pDocView);
+
+int             lok_docview_get_parts       (LOKDocView* pDocView);
+int             lok_docview_get_part        (LOKDocView* pDocView);
+void            lok_docview_set_part        (LOKDocView* pDocView,
+                                             int nPart);
+char*           lok_docview_get_part_name   (LOKDocView* pDocView,
+                                             int nPart);
+void            lok_docview_set_partmode    (LOKDocView* pDocView,
+                                             int nPartMode);
+/// Sets if the viewer is actually an editor or not.
+void            lok_docview_set_edit        (LOKDocView* pDocView,
+                                             gboolean bEdit);
+/// Gets if the viewer is actually an editor or not.
+gboolean        lok_docview_get_edit        (LOKDocView* pDocView);
+
+/// Posts the .uno: command to the LibreOfficeKit.
+void            lok_docview_post_command    (LOKDocView* pDocView, const char* pCommand, const char* pArguments);
+
+/// Posts a keyboard event to LibreOfficeKit.
+void            lok_docview_post_key    (GtkWidget* pWidget, GdkEventKey* pEvent, gpointer pData);
+
+/// Get the visible area of the document (in twips).
+void lok_docview_get_visarea(LOKDocView* pThis, GdkRectangle* pArea);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITGTK_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKitInit.h'
--- src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKitInit.h	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKitInit.h	2015-09-09 13:32:03 +0000
@@ -0,0 +1,257 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
+#define INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
+
+#include "LibreOfficeKit.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if defined(__linux__) || defined (__FreeBSD_kernel__) || defined(_AIX) || defined(_WIN32) || defined(__APPLE__)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#ifndef _WIN32
+
+    #include "dlfcn.h"
+
+    #ifdef  _AIX
+    #  include <sys/ldr.h>
+    #endif
+    #ifdef __APPLE__
+        #define TARGET_LIB        "lib" "sofficeapp" ".dylib"
+        #define TARGET_MERGED_LIB "lib" "mergedlo" ".dylib"
+    #else
+        #define TARGET_LIB        "lib" "sofficeapp" ".so"
+        #define TARGET_MERGED_LIB "lib" "mergedlo" ".so"
+    #endif
+    #define SEPARATOR         '/'
+
+    void *_dlopen(const char *pFN)
+    {
+        return dlopen(pFN, RTLD_LAZY
+#if defined __clang__ && defined __linux__ \
+    && defined ENABLE_RUNTIME_OPTIMIZATIONS
+#if !ENABLE_RUNTIME_OPTIMIZATIONS
+                      | RTLD_GLOBAL
+#endif
+#endif
+                      );
+    }
+
+    char *_dlerror(void)
+    {
+        return dlerror();
+    }
+
+    void *_dlsym(void *Hnd, const char *pName)
+    {
+        return dlsym(Hnd, pName);
+    }
+
+    int _dlclose(void *Hnd)
+    {
+        return dlclose(Hnd);
+    }
+
+    void extendUnoPath(const char *pPath)
+    {
+        (void)pPath;
+    }
+
+#else
+
+    #include <windows.h>
+    #define TARGET_LIB        "sofficeapp" ".dll"
+    #define TARGET_MERGED_LIB "mergedlo" ".dll"
+    #define SEPARATOR         '\\'
+    #define UNOPATH           "\\..\\URE\\bin"
+
+    void *_dlopen(const char *pFN)
+    {
+        return (void *) LoadLibrary(pFN);
+    }
+
+    char *_dlerror(void)
+    {
+        LPSTR buf = NULL;
+        FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, reinterpret_cast<LPSTR>(&buf), 0, NULL);
+        return buf;
+    }
+
+    void *_dlsym(void *Hnd, const char *pName)
+    {
+        return GetProcAddress((HINSTANCE) Hnd, pName);
+    }
+
+    int _dlclose(void *Hnd)
+    {
+        return FreeLibrary((HINSTANCE) Hnd);
+    }
+
+    void extendUnoPath(const char *pPath)
+    {
+        if (!pPath)
+            return;
+
+        char* sEnvPath = NULL;
+        DWORD  cChars = GetEnvironmentVariable("PATH", sEnvPath, 0);
+        if (cChars > 0)
+        {
+            sEnvPath = new char[cChars];
+            cChars = GetEnvironmentVariable("PATH", sEnvPath, cChars);
+            //If PATH is not set then it is no error
+            if (cChars == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND)
+            {
+                delete[] sEnvPath;
+                return;
+            }
+        }
+        //prepare the new PATH. Add the Ure/bin directory at the front.
+        //note also adding ';'
+        char * sNewPath = new char[strlen(sEnvPath) + strlen(pPath) + strlen(UNOPATH) + 2];
+        sNewPath[0] = L'\0';
+        strcat(sNewPath, pPath);
+        strcat(sNewPath, UNOPATH);
+        if (strlen(sEnvPath))
+        {
+            strcat(sNewPath, ";");
+            strcat(sNewPath, sEnvPath);
+        }
+
+        SetEnvironmentVariable("PATH", sNewPath);
+
+        delete[] sEnvPath;
+        delete[] sNewPath;
+    }
+#endif
+
+typedef LibreOfficeKit *(HookFunction)( const char *install_path);
+
+typedef LibreOfficeKit *(HookFunction2)( const char *install_path, const char *user_profile_path );
+
+static LibreOfficeKit *lok_init_2( const char *install_path,  const char *user_profile_path )
+{
+    char *imp_lib;
+    void *dlhandle;
+    HookFunction *pSym;
+    HookFunction2 *pSym2;
+
+#if !(defined(__APPLE__) && defined(__arm__))
+    size_t partial_length;
+
+    if (!install_path)
+        return NULL;
+
+    // allocate large enough buffer
+    partial_length = strlen(install_path);
+    imp_lib = (char *) malloc(partial_length + sizeof(TARGET_LIB) + sizeof(TARGET_MERGED_LIB) + 2);
+    if (!imp_lib)
+    {
+        fprintf( stderr, "failed to open library : not enough memory\n");
+        return NULL;
+    }
+
+    strcpy(imp_lib, install_path);
+
+    extendUnoPath(install_path);
+
+    imp_lib[partial_length++] = SEPARATOR;
+    strcpy(imp_lib + partial_length, TARGET_LIB);
+
+    dlhandle = _dlopen(imp_lib);
+    if (!dlhandle)
+    {
+        // If TARGET_LIB exists, and likely is a real library (not a
+        // small one-line text stub as in the --enable-mergedlib
+        // case), but dlopen failed for some reason, don't try
+        // TARGET_MERGED_LIB.
+        struct stat st;
+        if (stat(imp_lib, &st) == 0 && st.st_size > 100)
+        {
+            fprintf(stderr, "failed to open library '%s': %s\n",
+                    imp_lib, _dlerror());
+            free(imp_lib);
+            return NULL;
+        }
+
+        strcpy(imp_lib + partial_length, TARGET_MERGED_LIB);
+
+        dlhandle = _dlopen(imp_lib);
+        if (!dlhandle)
+        {
+            fprintf(stderr, "failed to open library '%s': %s\n",
+                    imp_lib, _dlerror());
+            free(imp_lib);
+            return NULL;
+        }
+    }
+#else
+    imp_lib = strdup("the app executable");
+    dlhandle = RTLD_MAIN_ONLY;
+#endif
+
+    pSym2 = (HookFunction2 *) _dlsym( dlhandle, "libreofficekit_hook_2" );
+    if (!pSym2)
+    {
+        if (user_profile_path != NULL)
+        {
+            fprintf( stderr, "the LibreOffice version in '%s' does not support passing a user profile to the hook function\n",
+                     imp_lib );
+            _dlclose( dlhandle );
+            free( imp_lib );
+            return NULL;
+        }
+        pSym = (HookFunction *) _dlsym( dlhandle, "libreofficekit_hook" );
+        if (!pSym)
+        {
+            fprintf( stderr, "failed to find hook in library '%s'\n", imp_lib );
+            _dlclose( dlhandle );
+            free( imp_lib );
+            return NULL;
+        }
+        free( imp_lib );
+        // dlhandle is "leaked"
+        // coverity[leaked_storage]
+        return pSym( install_path );
+    }
+
+    free( imp_lib );
+    // dlhandle is "leaked"
+    // coverity[leaked_storage]
+    return pSym2( install_path, user_profile_path );
+}
+
+static
+#ifdef __GNUC__
+__attribute__((used))
+#endif
+LibreOfficeKit *lok_init( const char *install_path )
+{
+    return lok_init_2( install_path, NULL );
+}
+
+#undef SEPARATOR // It is used at least in enum class MenuItemType
+
+#endif // defined(__linux__) || defined (__FreeBSD_kernel__) || defined(_AIX) || defined(_WIN32) || defined(__APPLE__)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKitTypes.h'
--- src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKitTypes.h	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/LibreOfficeKit/LibreOfficeKitTypes.h	2015-09-09 13:32:03 +0000
@@ -0,0 +1,30 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_TYPES_H
+#define INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_TYPES_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef LOK_USE_UNSTABLE_API
+typedef void (*LibreOfficeKitCallback)(int nType, const char* pPayload, void* pData);
+#endif // LOK_USE_UNSTABLE_API
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_TYPES_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/config.h'
--- src/plugin/libreofficetoolkit-qml-plugin/config.h	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/config.h	2015-09-09 13:32:03 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 Canonical, Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+// This is the hardcoded Ubuntu/Debian paths to find the LibreOffice
+// installation. If you want to use a parallel installation, change the path
+// in the following line.
+#define LO_PATH "/usr/lib/libreoffice/program/"
+
+// FIXME: Perhaps we want to use smaller tiles on mobile devices?
+#define TILE_SIZE 256.0
+
+// Uncomment it if you want to see tiles boundaries
+//#define DEBUG_SHOW_TILE_BORDER
+
+// Uncomment for benchmarking tile rendering performance
+//#define DEBUG_TILE_BENCHMARK
+
+// Uncomment if you want more verbose application output
+//#define DEBUG_VERBOSE
+
+#endif // CONFIG_H

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/lodocument.cpp'
--- src/plugin/libreofficetoolkit-qml-plugin/lodocument.cpp	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/lodocument.cpp	2015-09-09 13:32:03 +0000
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2013-2015 Canonical, Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "lodocument.h"
+#include "twips.h"
+#include "config.h"
+
+#include <QImage>
+#include <QDebug>
+
+#define LOK_USE_UNSTABLE_API
+#include <LibreOfficeKit/LibreOfficeKitInit.h>
+#include <LibreOfficeKit/LibreOfficeKit.hxx>
+
+// TODO: Error management
+
+lok::Office *LODocument::s_office = nullptr;
+
+LODocument::LODocument()
+  : m_path("")
+  , m_document(nullptr)
+{
+    // This space is intentionally empty.
+}
+
+// Return the path of the loaded document
+QString LODocument::path() const
+{
+    return m_path;
+}
+
+// Set the path of the document, then it tries to load it.
+void LODocument::setPath(QString &pathName)
+{
+    if (pathName.isEmpty())
+        return;
+
+    m_path = pathName;
+    Q_EMIT pathChanged();
+
+    // Load the new document
+    this->loadDocument(m_path);
+}
+
+// Load the document
+bool LODocument::loadDocument(QString &pathName)
+{
+    qDebug() << "Loading document...";
+
+    if (pathName.isEmpty()) {
+        qDebug() << "Can't load the document, path is empty.";
+        return false;
+    }
+
+    if (!s_office)
+        s_office = lok::lok_cpp_init(LO_PATH);
+
+    m_document = s_office->documentLoad(m_path.toUtf8().constData());
+
+    m_docType = DocumentType(m_document->getDocumentType());
+    Q_EMIT documentTypeChanged();
+
+    m_document->initializeForRendering();
+    qDebug() << "Document loaded successfully !";
+
+    return true;
+}
+
+// Return the type of the loaded document (e.g. text document,
+// spreadsheet or presentation).
+LODocument::DocumentType LODocument::documentType() const
+{
+    return m_docType;
+}
+
+// Return the size of the document, in TWIPs
+QSize LODocument::documentSize() const
+{
+    if (!m_document)
+        return QSize(0, 0);
+
+    long pWidth(0);
+    long pHeight(0);
+    m_document->getDocumentSize(&pWidth, &pHeight);
+
+    return QSize(pWidth, pHeight);
+}
+
+// Paint a tile, with size=canvasSize, of the part of the document defined by
+// the rect tileSize.
+QImage LODocument::paintTile(QSize canvasSize, QRect tileSize)
+{
+    QImage result = QImage(canvasSize.width(), canvasSize.height(),  QImage::Format_RGB32);
+    m_document->paintTile(result.bits(),
+                          canvasSize.width(), canvasSize.height(),
+                          Twips::convertPixelsToTwips(tileSize.x()),
+                          Twips::convertPixelsToTwips(tileSize.y()),
+                          Twips::convertPixelsToTwips(tileSize.width()),
+                          Twips::convertPixelsToTwips(tileSize.height()));
+
+    return result.rgbSwapped();
+}
+
+/* Export the file in a given format:
+ *  - url is a mandatory argument.
+ *  - format is optional. If not specified, lok will try to get it from the file
+ *    extension given at the 'url' argument.
+ *  - filerOptions is also optional.
+ */
+// TODO: Is there some documentation on safe formats or filterOptions that can
+// be used?
+bool LODocument::saveAs(QString url, QString format = QString(), QString filterOptions = QString())
+{
+    if (!m_document) {
+        qDebug() << "No loaded document. It's not possible to save this file.";
+        return false;
+    }
+
+    return m_document->saveAs(url.toLatin1().constData(),
+                              format.toLatin1().constData(),
+                              filterOptions.toLatin1().constData());
+}
+
+LODocument::~LODocument()
+{
+    delete m_document;
+}

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/lodocument.h'
--- src/plugin/libreofficetoolkit-qml-plugin/lodocument.h	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/lodocument.h	2015-09-09 13:32:03 +0000
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013-2015 Canonical, Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef LODOCUMENT_H
+#define LODOCUMENT_H
+
+#include <QObject>
+
+namespace lok {
+class Office;
+class Document;
+}
+
+class LODocument : public QObject
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(LODocument)
+
+    Q_PROPERTY(QString      path         READ path         WRITE setPath        NOTIFY pathChanged)
+    Q_PROPERTY(DocumentType documentType READ documentType                      NOTIFY documentTypeChanged)
+    Q_ENUMS(DocumentType)
+
+public:
+    explicit LODocument();
+    virtual ~LODocument();
+
+    enum DocumentType {
+        TextDocument = 0,
+        SpreadsheetDocument = 1,
+        PresentationDocument = 2,
+        DrawingDocument = 3,
+        OtherDocument = 4
+    };
+
+    QString path() const;
+    void setPath(QString &pathName);
+
+    DocumentType documentType() const;
+
+    QSize documentSize() const;
+    QImage paintTile(QSize canvasSize, QRect tileSize);
+
+    Q_INVOKABLE bool saveAs(QString url, QString format, QString filterOptions);
+
+Q_SIGNALS:
+    void pathChanged();
+    void documentTypeChanged();
+
+private:
+    QString m_path;
+    DocumentType m_docType;
+
+    bool loadDocument(QString &pathNAme);
+
+    lok::Document *m_document;
+
+    static lok::Office *s_office;
+};
+
+#endif // LODOCUMENT_H

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/loview.cpp'
--- src/plugin/libreofficetoolkit-qml-plugin/loview.cpp	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/loview.cpp	2015-09-09 13:32:03 +0000
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2015 Canonical, Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "loview.h"
+#include "lodocument.h"
+#include "tileitem.h"
+#include "twips.h"
+#include "config.h"
+
+#include <QPainter>
+#include <QImage>
+#include <QTimer>
+#include <QtCore/qmath.h>
+
+// TODO: Use a QQuickItem and implement painting through
+// updatePaintNode(QSGNode * oldNode, UpdatePaintNodeData * data)
+
+LOView::LOView(QQuickItem *parent)
+    : QQuickPaintedItem(parent)
+    , m_parentFlickable(nullptr)
+    , m_document(nullptr)
+    , m_zoomFactor(1.0)
+    , m_cacheBuffer(TILE_SIZE * 3)
+    , m_visibleArea(0, 0, 0, 0)
+    , m_bufferArea(0, 0, 0, 0)
+{
+    Q_UNUSED(parent)   
+
+    connect(this, SIGNAL(documentChanged()), this, SLOT(updateViewSize()));
+    connect(this, SIGNAL(zoomFactorChanged()), this, SLOT(updateViewSize()));
+    connect(this, SIGNAL(parentFlickableChanged()), this, SLOT(updateVisibleRect()));
+    connect(this, SIGNAL(cacheBufferChanged()), this, SLOT(updateVisibleRect()));
+    connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateVisibleRect()));
+}
+
+void LOView::paint(QPainter *painter)
+{
+    Q_FOREACH(TileItem* tile, m_tiles) {
+        painter->drawImage(tile->area(), tile->texture());
+        tile->setPainted(true);
+
+#ifdef DEBUG_SHOW_TILE_BORDER
+        painter->drawRect(tile->area());
+#endif
+    }
+}
+
+// Returns the parent QML Flickable
+QQuickItem* LOView::parentFlickable() const
+{
+    return m_parentFlickable;
+}
+
+// Set the parent QML Flickable
+void LOView::setParentFlickable(QQuickItem *flickable)
+{
+    if (m_parentFlickable == flickable)
+        return;
+
+    if (m_parentFlickable)
+        m_parentFlickable->disconnect(this);
+
+    m_parentFlickable = flickable;
+
+    connect(m_parentFlickable, SIGNAL(widthChanged()), this, SLOT(updateVisibleRect()));
+    connect(m_parentFlickable, SIGNAL(heightChanged()), this, SLOT(updateVisibleRect()));
+
+    connect(m_parentFlickable, SIGNAL(contentXChanged()), this, SLOT(scheduleVisibleRectUpdate()));
+    connect(m_parentFlickable, SIGNAL(contentYChanged()), this, SLOT(scheduleVisibleRectUpdate()));
+
+    Q_EMIT parentFlickableChanged();
+}
+
+// Return the LODocument rendered by this class
+LODocument* LOView::document() const
+{
+    return m_document;
+}
+
+// Set the LODocument
+void LOView::setDocument(LODocument *doc)
+{
+    if (m_document == doc)
+        return;
+
+    m_document = doc;
+    Q_EMIT documentChanged();
+}
+
+// Not used yet.
+qreal LOView::zoomFactor() const
+{
+    return m_zoomFactor;
+}
+
+// Not used yet.
+void LOView::setZoomFactor(qreal zoom)
+{
+    if (m_zoomFactor == zoom)
+        return;
+
+    m_zoomFactor = zoom;
+    Q_EMIT zoomFactorChanged();
+}
+
+int LOView::cacheBuffer() const
+{
+    return m_cacheBuffer;
+}
+
+void LOView::setCacheBuffer(int cacheBuffer)
+{
+    if (m_cacheBuffer == cacheBuffer)
+        return;
+
+    m_cacheBuffer = cacheBuffer;
+    Q_EMIT cacheBufferChanged();
+}
+
+// Update the size of LOView, according to the size of the loaded document.
+void LOView::updateViewSize()
+{
+    if (!m_document)
+        return;
+
+    QSize docSize = m_document->documentSize();
+
+    // FIXME: Area may become too large, resulting in a black texture.
+    this->setWidth(Twips::convertTwipsToPixels(docSize.width()) * m_zoomFactor);
+    this->setHeight(Twips::convertTwipsToPixels(docSize.height()) * m_zoomFactor);
+
+    // TODO: Consider to use connections to widthChanged and heightChanged
+    this->updateVisibleRect();
+}
+
+// Update the informations of the currently visible area of the parent
+// Flickable, then generate/delete all the required tiles, according to these
+// informations.
+void LOView::updateVisibleRect()
+{
+    if (!m_parentFlickable)
+        return;
+
+    // Update information about the visible area
+    m_visibleArea.setRect(m_parentFlickable->property("contentX").toInt(),
+                          m_parentFlickable->property("contentY").toInt(),
+                          m_parentFlickable->width(),
+                          m_parentFlickable->height());
+
+    // Update information about the buffer area
+    m_bufferArea.setRect(qMax(0, m_visibleArea.x() - this->cacheBuffer()),
+                         qMax(0, m_visibleArea.y() - this->cacheBuffer()),
+                         qMin(int(this->width() - m_bufferArea.x()), m_visibleArea.width() + (this->cacheBuffer() * 2)),
+                         qMin(int(this->height() - m_bufferArea.y()), m_visibleArea.height() + (this->cacheBuffer() * 2)));
+
+    // Delete tiles that are outside the loading area
+    if (!m_tiles.isEmpty()) {
+        auto i = m_tiles.begin();
+        while (i != m_tiles.end()) {
+            TileItem* tile = i.value();
+
+            if (!m_bufferArea.intersects(tile->area())) {
+                tile->releaseTexture();
+                i = m_tiles.erase(i);
+
+#ifdef DEBUG_VERBOSE
+                qDebug() << "Removing tile indexed as" << i.key();
+#endif
+            } else {
+                ++i;
+            }
+        }
+    }
+
+    // Number of tiles per row
+    int tilesPerWidth           = qCeil(this->width() / TILE_SIZE);
+
+    // Get indexes for visible tiles
+    int visiblesFromWidth       = int(m_visibleArea.left() / TILE_SIZE);
+    int visiblesFromHeight      = int(m_visibleArea.top() / TILE_SIZE);
+    int visiblesToWidth         = qCeil(qreal(m_visibleArea.right()) / TILE_SIZE);
+    int visiblesToHeight        = qCeil(qreal(m_visibleArea.bottom()) / TILE_SIZE);
+
+    // Get indexes for tiles in the visible area
+    int bufferFromWidth         = int(m_bufferArea.left() / TILE_SIZE);
+    int bufferFromHeight        = int(m_bufferArea.top() / TILE_SIZE);
+    int bufferToWidth           = qCeil(qreal(m_bufferArea.right()) / TILE_SIZE);
+    int bufferToHeight          = qCeil(qreal(m_bufferArea.bottom()) / TILE_SIZE);
+
+    this->generateTiles(visiblesFromWidth, visiblesFromHeight, visiblesToWidth, visiblesToHeight, tilesPerWidth);
+    this->generateTiles(bufferFromWidth, bufferFromHeight, bufferToWidth, bufferToHeight, tilesPerWidth);
+}
+
+void LOView::generateTiles(int x1, int y1, int x2, int y2, int tilesPerWidth)
+{
+    for (int x = x1; x < x2; x++) {
+        for (int y = y1; y < y2; y++) {
+            QRect tileRect(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
+            int index = y * tilesPerWidth + x;
+
+            this->createTile(index, tileRect);
+        }
+    }
+}
+
+void LOView::createTile(int index, QRect rect)
+{
+    if (!m_tiles.contains(index)) {
+#ifdef DEBUG_VERBOSE
+        qDebug() << "Creating tile indexed as" << index;
+#endif
+
+        auto tile = new TileItem(rect, m_document);
+        connect(tile, SIGNAL(textureChanged()), this, SLOT(update()));
+        tile->requestTexture();
+
+        // Append the tile in the map
+        m_tiles.insert(index, tile);
+    }
+#ifdef DEBUG_VERBOSE
+    else {
+        qDebug() << "tile" << x << "x" << y << "already exists";
+    }
+#endif
+}
+
+void LOView::scheduleVisibleRectUpdate()
+{
+    if (!m_updateTimer.isActive())
+        m_updateTimer.start(20);
+}
+
+LOView::~LOView()
+{
+    //
+}

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/loview.h'
--- src/plugin/libreofficetoolkit-qml-plugin/loview.h	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/loview.h	2015-09-09 13:32:03 +0000
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015 Canonical, Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LOVIEW_H
+#define LOVIEW_H
+
+#include <QQuickPaintedItem>
+#include <QTimer>
+
+class LODocument;
+class TileItem;
+
+class LOView : public QQuickPaintedItem
+{
+    Q_OBJECT
+    Q_PROPERTY(QQuickItem* parentFlickable READ parentFlickable WRITE setParentFlickable NOTIFY parentFlickableChanged)
+    Q_PROPERTY(LODocument* document        READ document        WRITE setDocument        NOTIFY documentChanged)
+
+    // TODO: Implement zoom!
+    Q_PROPERTY(qreal       zoomFactor      READ zoomFactor      WRITE setZoomFactor      NOTIFY zoomFactorChanged)
+    Q_PROPERTY(int         cacheBuffer     READ cacheBuffer     WRITE setCacheBuffer     NOTIFY cacheBufferChanged)
+
+public:
+    LOView(QQuickItem *parent = 0);
+    ~LOView();
+
+    void        paint(QPainter *painter);
+
+    QQuickItem* parentFlickable() const;
+    void        setParentFlickable(QQuickItem* flickable);
+
+    LODocument* document() const;
+    void        setDocument(LODocument* doc);
+
+    qreal       zoomFactor() const;
+    void        setZoomFactor(qreal zoom);
+
+    int         cacheBuffer() const;
+    void        setCacheBuffer(int cacheBuffer);
+
+Q_SIGNALS:
+    void parentFlickableChanged();
+    void documentChanged();
+    void zoomFactorChanged();
+    void cacheBufferChanged();
+
+private Q_SLOTS:
+    void updateViewSize();
+    void updateVisibleRect();
+    void scheduleVisibleRectUpdate();
+
+private:
+    QQuickItem*             m_parentFlickable;
+    LODocument*             m_document;
+
+    qreal                   m_zoomFactor;
+    int                     m_cacheBuffer;
+
+    QRect                   m_visibleArea;
+    QRect                   m_bufferArea;
+
+    QTimer                  m_updateTimer;
+
+    QMap<int, TileItem*>    m_tiles;
+
+    void                    generateTiles(int x1, int y1, int x2, int y2, int tilesPerWidth);
+    void                    createTile(int index, QRect rect);
+};
+
+#endif // LOVIEW_H

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/plugin.cpp'
--- src/plugin/libreofficetoolkit-qml-plugin/plugin.cpp	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/plugin.cpp	2015-09-09 13:32:03 +0000
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 Canonical, Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtQml>
+#include <QtQml/QQmlContext>
+
+#include "plugin.h"
+#include "lodocument.h"
+#include "loview.h"
+
+void LOPlugin::registerTypes(const char *uri)
+{
+    Q_ASSERT(uri == QLatin1String("DocumentViewer.LibreOffice"));
+    
+    //@uri DocumentViewer.LibreOffice
+    qmlRegisterType<LODocument>(uri, 1, 0, "Document");
+    qmlRegisterType<LOView>(uri, 1, 0, "View");
+}
+
+void LOPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
+{
+    QQmlExtensionPlugin::initializeEngine(engine, uri);
+}

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/plugin.h'
--- src/plugin/libreofficetoolkit-qml-plugin/plugin.h	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/plugin.h	2015-09-09 13:32:03 +0000
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 Canonical, Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef LOPLUGIN_H
+#define LOPLUGIN_H
+
+#include <QQmlExtensionPlugin>
+
+class LOPlugin : public QQmlExtensionPlugin
+{
+    Q_OBJECT
+    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+
+public:
+    void registerTypes(const char *uri);
+    void initializeEngine(QQmlEngine *engine, const char *uri);
+};
+
+#endif // LO_H

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/qmldir'
--- src/plugin/libreofficetoolkit-qml-plugin/qmldir	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/qmldir	2015-09-09 13:32:03 +0000
@@ -0,0 +1,4 @@
+module DocumentViewer.LibreOffice
+plugin libreofficetoolkitqmlplugin
+
+Viewer 1.0 LOViewer.qml

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/tileitem.cpp'
--- src/plugin/libreofficetoolkit-qml-plugin/tileitem.cpp	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/tileitem.cpp	2015-09-09 13:32:03 +0000
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2015 Canonical, Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Stefano Verzegnassi <stefano92.100@xxxxxxxxx>
+ */
+
+#include "tileitem.h"
+#include "lodocument.h"
+#include "config.h"
+
+#include <QThreadPool>
+#include <QDebug>
+
+#ifdef DEBUG_TILE_BENCHMARK
+#include <QElapsedTimer>
+#endif
+
+/* ****************
+ * TileItem class *
+ ******************/
+
+TileItem::TileItem(const QRect &area, LODocument *document)
+    : m_painted(false)
+    , m_document(nullptr)
+{
+    this->setArea(area);
+    this->setDocument(document);
+}
+
+// Destructor
+TileItem::~TileItem()
+{
+    this->releaseTexture();
+}
+
+QRect TileItem::area() const
+{
+    return m_area;
+}
+
+void TileItem::setArea(const QRect &area)
+{
+    if (m_area == area)
+        return;
+
+    m_area = area;
+    Q_EMIT areaChanged();
+}
+
+QImage TileItem::texture() const
+{
+    return m_texture;
+}
+
+bool TileItem::isPainted() const
+{
+    return m_painted;
+}
+
+void TileItem::setPainted(bool isPainted)
+{
+    if (m_painted == isPainted)
+        return;
+
+    m_painted = isPainted;
+    Q_EMIT isPaintedChanged();
+}
+
+LODocument* TileItem::document() const
+{
+    return m_document;
+}
+
+void TileItem::setDocument(LODocument* document)
+{
+    if (m_document == document)
+        return;
+
+    m_document = document;
+    Q_EMIT documentChanged();
+}
+
+void TileItem::requestTexture()
+{
+    auto task = new RenderTask(this->area(), this->document());
+    connect(task, SIGNAL(renderCompleted(QImage)), this, SLOT(updateTexture(QImage)));
+
+    task->setAutoDelete(true);
+    QThreadPool::globalInstance()->start(task);
+}
+
+// Free memory used by the texture
+void TileItem::releaseTexture()
+{
+    if (m_texture.isNull())
+        return;
+
+    m_texture = QImage();
+    Q_EMIT textureChanged();
+}
+
+// This is a slot, connect to renderCompleted() signal from RenderTask class.
+void TileItem::updateTexture(QImage t)
+{
+    m_texture = t;
+    Q_EMIT textureChanged();
+}
+
+/* ******************
+ * RenderTask class *
+ ********************/
+
+RenderTask::RenderTask(const QRect &area, LODocument* document)
+{
+    this->setArea(area);
+    this->setDocument(document);
+}
+
+
+QRect RenderTask::area() const
+{
+    return m_area;
+}
+
+void RenderTask::setArea(const QRect &area)
+{
+    if (m_area == area)
+        return;
+
+    m_area = area;
+    Q_EMIT areaChanged();
+}
+
+LODocument* RenderTask::document() const
+{
+    return m_document;
+}
+
+void RenderTask::setDocument(LODocument* document)
+{
+    if (m_document == document)
+        return;
+
+    m_document = document;
+    Q_EMIT documentChanged();
+}
+
+// Render the texture for this tile.
+void RenderTask::run()
+{
+#ifdef DEBUG_TILE_BENCHMARK
+    QElapsedTimer renderTimer;
+    renderTimer.start();
+#endif
+
+    QImage render = this->document()->paintTile(this->area().size(),
+                                                this->area());
+
+    Q_EMIT renderCompleted(render);
+
+#ifdef DEBUG_TILE_BENCHMARK
+    qDebug() << "Time to render the tile:" << renderTimer.elapsed() << "ms";
+#endif
+}

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/tileitem.h'
--- src/plugin/libreofficetoolkit-qml-plugin/tileitem.h	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/tileitem.h	2015-09-09 13:32:03 +0000
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2015 Canonical, Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Stefano Verzegnassi <stefano92.100@xxxxxxxxx>
+ */
+
+#ifndef TILEITEM_H
+#define TILEITEM_H
+
+#include <QRunnable>
+#include <QImage>
+
+class LODocument;
+
+class TileItem : public QObject
+{
+    Q_OBJECT
+
+public:
+    TileItem(const QRect &area, LODocument* document);
+    ~TileItem();
+
+    QRect area() const;
+    void setArea(const QRect &area);
+
+    QImage texture() const;
+
+    bool isPainted() const;
+    void setPainted(bool isPainted);
+
+    LODocument* document() const;
+    void setDocument(LODocument* document);
+
+public Q_SLOTS:
+    void requestTexture();
+    void releaseTexture();
+
+Q_SIGNALS:
+    void areaChanged();
+    void textureChanged();
+    void isPaintedChanged();
+    void documentChanged();
+
+private Q_SLOTS:
+    void updateTexture(QImage t);
+
+private:
+    QRect m_area;
+    QImage m_texture;
+    bool m_painted;
+
+    LODocument* m_document;
+};
+
+class RenderTask : public QObject, public QRunnable
+{
+    Q_OBJECT
+
+public:
+    RenderTask(const QRect &area, LODocument* document);
+
+    QRect area() const;
+    void setArea(const QRect &area);
+
+    LODocument* document() const;
+    void setDocument(LODocument* document);
+
+    void run();
+
+Q_SIGNALS:
+    void areaChanged();
+    void documentChanged();
+    void renderCompleted(QImage t);
+
+private:
+    QRect m_area;
+    LODocument* m_document;
+};
+
+#endif // TILEITEM_H

=== added file 'src/plugin/libreofficetoolkit-qml-plugin/twips.h'
--- src/plugin/libreofficetoolkit-qml-plugin/twips.h	1970-01-01 00:00:00 +0000
+++ src/plugin/libreofficetoolkit-qml-plugin/twips.h	2015-09-09 13:32:03 +0000
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 Canonical, Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Stefano Verzegnassi <stefano92.100@xxxxxxxxx>
+ */
+
+#ifndef TWIPS_H
+#define TWIPS_H
+
+// FIXME: Should we check for the real DPI of the screen, since we'll have in
+// future to support HiDPI devices and Full/Ultra-HD smartphones/tablet?
+// FIXME: Not common, but DPI on the X axis, and DPI on the Y axis may be
+// different.
+#define VIRTUAL_DPI 96.0
+
+#include <QtGlobal>
+
+class Twips
+{
+public:
+    static inline int convertTwipsToPixels(int twips, qreal zoom = 1.0) {
+        return int(twips / 1440.0 * VIRTUAL_DPI * zoom);
+    }
+
+    static inline int convertPixelsToTwips(int pixels, qreal zoom = 1.0) {
+        return int(pixels * 1440.0 / VIRTUAL_DPI / zoom);
+    }
+};
+
+#endif // TWIPS_H