qtqmlqt-quick

Text gets misaligned when using Qt TextTable with TextArea using QtQuick.Controls 1.12


I have a problem where I am using a TextArea in Qml. A C++ Model holds a reference to that TextArea.

When I insert a QTextTable in the C++ model it all fine until the user enters some text. After the user manually edits a few cells and writes some text in it, it gets all messed up. Does anyone know anything on how to solve it?

I also have other functions with are working perfectly. So I would guess there is nothing wrong with the connection between the c++ model and the textarea.

Here is the Documenthandler.h

#include <QQuickTextDocument>

#include <QtGui/QTextCharFormat>
#include <QtCore/QTextCodec>

#include <qqmlfile.h>

QT_BEGIN_NAMESPACE
class QTextDocument;
QT_END_NAMESPACE

class DocumentHandler : public QObject
{
    Q_OBJECT

    Q_ENUMS(HAlignment)

    Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
    Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)

public:
    DocumentHandler();

    Q_INVOKABLE void createTable(int columns ,int rows);

    QQuickItem *target() { return m_target; }

    void setTarget(QQuickItem *target);

    QString text() const;


public Q_SLOTS:

    void setText(const QString &arg);


Q_SIGNALS:
    void targetChanged();

    void textChanged();
    void error(QString message);

private:
    QTextCursor textCursor() const;

    QQuickItem *m_target;
    QTextDocument *m_doc;

    QString m_text;
};

Here is the documenthandler.cpp in the "createTable" function I create the table

#include "documenthandler.h"

#include <QtGui/QTextDocument>
#include <QtGui/QTextList>
#include <QtGui/QTextTable>
#include <QtGui/QTextCursor>
#include <QtGui/QFontDatabase>
#include <QtCore/QFileInfo>

DocumentHandler::DocumentHandler()
    : m_target(0)
    , m_doc(0)
{
}

void DocumentHandler::setTarget(QQuickItem *target)
{
    m_doc = 0;
    m_target = target;
    if (!m_target)
        return;

    QVariant doc = m_target->property("textDocument");
    if (doc.canConvert<QQuickTextDocument*>()) {
        QQuickTextDocument *qqdoc = doc.value<QQuickTextDocument*>();
        if (qqdoc)
            m_doc = qqdoc->textDocument();
    }
    emit targetChanged();
}

void DocumentHandler::setText(const QString &arg)
{
    if (m_text != arg) {
        m_text = arg;
        emit textChanged();
    }
}

QString DocumentHandler::text() const
{
    return m_text;
}

QTextCursor DocumentHandler::textCursor() const
{
    if (!m_doc)
        return QTextCursor();

    QTextCursor cursor = QTextCursor(m_doc);

    return cursor;
}

void DocumentHandler::createTable(int columns , int rows)
{
    QTextCursor cursor = textCursor();
    if (cursor.isNull())
        return;

    cursor.insertTable(rows,columns);


}

Here is the main qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 1.6
import DocumentHandler 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    Button
    {
        id:btn
        text:"test"
        onClicked: document.createTable(5,5);
    }


    TextArea {
        Accessible.name: "document"
        id: tooltip_area

        selectByMouse: true

        anchors.left:parent.left
        anchors.right:parent.right
        anchors.top: btn.bottom
        anchors.bottom: parent.bottom

        baseUrl: "qrc:/"
        text: document.text
        textFormat: Qt.RichText
        wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
        Component.onCompleted: forceActiveFocus()
           }
    DocumentHandler{
        id: document
        target: tooltip_area



    }

}

here is the main function, there is nothing special except I register the QML Type

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "documenthandler.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    qmlRegisterType<DocumentHandler>("DocumentHandler",1,0,"DocumentHandler");
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
                         if (!obj && url == objUrl)
                             QCoreApplication::exit(-1);
                     }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

This is how it looks after filling up some cells

messed up table


Solution

  • So I solved it by just selecting everything and deselecting when the text changes. Theoretically I only need to do it when I am in a Table Block.

    onTextChanged:
    {
        if(recoursionlock)
        {
            recoursionlock =false;
    
            var curpos = tooltip_area.cursorPosition;
            var select_start = tooltip_area.selectionStart;
            var select_end = tooltip_area.selectionEnd;
    
    
            selectAll();
            deselect();
            if(curpos !== -1 && curpos >= tooltip_area.text.lenght)
                tooltip_area.cursorPosition = curpos;
            else
                tooltip_area.select(select_start,select_end)
    
            recoursionlock = true;
    
        }
    
    }