- Qt 5.15
- Qt Quick Text Editor Guide - Logic
- Qt 5.15.17 Reference Documentation

Qt Quick Text Editor Guide - UI ◦ Qt Quick Text Editor - Connecting Actions

# Qt Quick Text Editor Guide - Logic

This part of the guide is about adding logic and backend to the text editor example. At this stage, the user interface is set up from the previous stage.

## Implementing the Logic and C++ Backend

Text Editor has a QML user interface and a C++ backend to implement the document handling. To connect QML and C++, we need to create actions associated to the tool buttons, which will call the document handling logic in C++.

## Creating the Document Handler

The document handler implements the file loading and file saving logic with Qt's C++ APIs. First, we need to create the header file and the implementation file in Qt Creator's Edit mode.

- Right-click a folder, and select Add New.
- Follow the wizard and create a new C++ Class.
- Create a class called DocumentHandler and select Inherits QObject in the Type information.
- You can use default values for the rest and finish the wizard.

The wizard creates a DocumentHandler class in two files, documenthandler.h and documenthandler.cpp.

There are two functionalities we can expose to QML, the file loading and saving. We can do this by creating properties and binding them to C++ functions through the Qt Property System.

In the documenthandler.h header file, add the following functions with their respective access modifier:

         Q_PROPERTY(QUrl fileUrl READ fileUrl WRITE setFileUrl NOTIFY fileUrlChanged)
         Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
         Q_PROPERTY(QString documentTitle READ documentTitle WRITE setDocumentTitle NOTIFY documentTitleChanged)

     public:
         QUrl fileUrl() const;
         QString text() const;
         QString documentTitle() const;

     public slots:
         void setFileUrl(const QUrl &arg);
         void setText(const QString &arg);
         void setDocumentTitle(QString arg);

     signals:
         void fileUrlChanged();
         void textChanged();
         void documentTitleChanged();

The lines with `Q_PROPERTY()` macro declares the property and its write and read methods as well as its notify signal. For example, setting the `fileUrl` property calls `setFileUrl()` and reading the property calls the `fileUrl()` function. Similarly, when the value of fileUrl changes the `fileUrlChanged()` function is called.

Internally, the properties are represented by private member variables. For our needs, here are the three variables in documenthandler.h which correspond to the properties:

     private:
         QUrl m_fileUrl;
         QString m_text;
         QString m_documentTitle;

Implementing the read functions is straightforward. They simply return the private member variables. For example, the implementation of `documentTitle()` in documenthandler.cpp is:

     QString DocumentHandler::documentTitle() const
     {
         return m_documentTitle;
     }

Implementing the write (`setText()`, for example) functions is also straightforward as they simply assign a value to a private member variable. They also handle basic error handling and they emit their respective notify signals. For example, the `setDocumentTitle()` function is implemented in documenthandler.cpp as:

     void DocumentHandler::setDocumentTitle(QString arg)
     {
         if (m_documentTitle != arg) {
             m_documentTitle = arg;
             emit documentTitleChanged();
         }
     }

The opening of the file is done in the `setFileUrl()` function:

     void DocumentHandler::setFileUrl(const QUrl &arg)
     {
         if (m_fileUrl != arg) {
             m_fileUrl = arg;
             QString fileName = arg.fileName();
             QFile file(arg.toLocalFile());
             if (file.open(QFile::ReadOnly)) {
                 setText(QString(file.readAll()));
                 if (fileName.isEmpty())
                     m_documentTitle = QStringLiteral("untitled");
                 else
                     m_documentTitle = fileName;
                 emit textChanged();
                 emit documentTitleChanged();
             }
             emit fileUrlChanged();
         }
     }

Note how the function emits the notify signals with the `emit` keyword.

Similarly, we use QFile and text streams to save files. The function signature in documenthandler.h is placed under `public slots` because that is one way to expose functions to the QML engine. `saveFile()` is called from the QML file during saving.

     public slots:

         Q_INVOKABLE void saveFile(const QUrl &arg) const;

The implementation of `saveFile()` is in documenthandler.cpp:

     void DocumentHandler::saveFile(const QUrl &arg) const
     {
         QFile file(arg.toLocalFile());
         if (file.open(QFile::WriteOnly | QFile::Truncate)) {
             QTextStream out(&file);
             out << text();
         }
     }

For information about reading files and data storage, visit the QFile and the Data Storage documentation.

## Registering the DocumentHandler Class

We now need to let the QML engine know about the `DocumentHandler` and its type. The `qmlRegisterType()` function is called in the application's `main()` function in main.cpp:

     qmlRegisterType<DocumentHandler>("org.qtproject.example", 1, 0, "DocumentHandler");

The `org.qtproject.example` is the library with the version `1.0` and the QML type registered is `DocumentHandler`. The import statement for the DocumentHandler QML type is then

     import org.qtproject.example 1.0

Note: The `qmlRegisterType()` function should be called before the engine loads the QML file.

## Using the DocumentHandler QML type

With the basic loading implemented, we can use the functionalities in the QML file by creating an instance of the DocumentHandler class and by accessing its properties.

The next page is about using these C++ functions in QML files.

## Example Files

The accompanying examples files are found in the following page:

- Qt Quick Controls 1 - Text Editor Example