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

文本编辑器 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 编辑 模式。

  • Right-click a folder, and select Add New .
  • Follow the wizard and create a new C++ Class .
  • Create a class called DocumentHandler 并选择 继承 QObject 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 .

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 及其 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() 函数被调用。

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() 函数:

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 关键词。

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;
					

实现为 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 数据存储 文档编制。

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() 函数在 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
					

注意: 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.

范例文件

The accompanying examples files are found in the following page: