0
votes

Let's say I have a QML Text or TextArea that contains a very long HTML page. I want to make it easier to read by splitting it into pages.

More specifically, every time I press the down key, I want it to scroll down until none of the current text on the screen is still there.

I already know how to make the entire TextArea scrollable; that's not what I'm looking for. What I'm looking for is more like the kind of behavior you'd expect in an ebook reader.

Is there any way to do something like that, preferably in pure QML (though C++ is also fine).

1

1 Answers

1
votes

You can measure the TextArea height after loading, divide it to the container height and so get the count of pages. Then you just move the TextArea relative to its container according to the current page.

The simple illustration of my idea:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3

Window {
    id: main
    visible: true
    width: 640
    height: 800  

    property int currentPage: 1
    property int pageCount: 1

    ColumnLayout
    {
        anchors.fill: parent
        anchors.margins: 5
        RowLayout {
            Layout.preferredHeight: 40
            Layout.alignment: Qt.AlignHCenter
            Button {
                text: "<"
                onClicked: {
                    if(main.currentPage > 1)
                        main.currentPage --;
                }
            }
            Text {
                text: main.currentPage + " / " + main.pageCount
            }
            Button {
                text: ">"
                onClicked: {
                    if(main.currentPage < main.pageCount)
                        main.currentPage ++;
                }
            }
        }
        Rectangle {
            id: container
            clip: true
            Layout.fillHeight: true
            Layout.fillWidth: true
            TextArea {
                id: msg
                text: "Loading ..."
                width: container.width
                height: container.height
                y: -(main.currentPage - 1) * container.height
                textFormat: TextEdit.RichText
                wrapMode: TextEdit.Wrap
                Component.onCompleted: {
                    msg.makeRequest();
                }
                onContentHeightChanged: {
                    msg.height = msg.contentHeight;
                    if(msg.contentHeight >= container.height && container.height > 0)
                    {
                        main.pageCount = msg.contentHeight / container.height;
                        loader.running = false;
                    }
                }
                function makeRequest()
                {
                    var doc = new XMLHttpRequest();
                    msg.text = "";
                    doc.onreadystatechange = function() {
                        if (doc.readyState === XMLHttpRequest.DONE) {
                            msg.text = doc.responseText;
                        }
                    }
                    doc.open("GET", "http://www.gutenberg.org/files/730/730-h/730-h.htm");
                    doc.send();
                }
            }
        }
    }
    BusyIndicator {
        id: loader
        running: true
        anchors.centerIn: parent
    }
}

Of course you have to process margins, the last line on a page, recalculate the values on resizing etc.