Develop own QQmlExtensionPlugin: module not installed when trying to use in a sample-project

363 views Asked by At

I am trying to create a QQmlExtensionPlugin to use it in another application as a qml-module.

The problem I have is, that when I compile the project and try to use it in a sample-project the qml-compiler says, that the module "Clock 1.0" is not installed and cannot be loaded. Does anyone know what to do in this situation? You can find the full source-code here: https://github.com/MhouneyLH/qml_cpp_examples on the branch "feat/model_adjustments".

In Summary, what did I do to compile the plugin:

  1. Add qml-files (in the repository under example_transformation/qml/Clock), which should be part of the plugin.
  2. Add a qmldir-file
module Clock
plugin clockplugin
  1. Create Plugin.h (and the corresponding Plugin.cpp-file -> in my case it is not needed, since for now I don't want to create a cpp-backend) for the meta-information of the plugin.
#ifndef CLOCKPLUGIN_H
#define CLOCKPLUGIN_H

#include <QQmlExtensionPlugin>

class ClockPlugin : public QQmlExtensionPlugin
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)

public:
    void registerTypes(const char* uri);
};

#endif // CLOCKPLUGIN_H
  1. Adjust the .pro-file of the project
TEMPLATE = lib
CONFIG += plugin
QT += quick qml

DESTDIR = ../Clock
TARGET = clockplugin

SOURCES += \
        src/ClockPlugin.cpp \
        src/main.cpp

HEADERS += \
    src/ClockPlugin.h

RESOURCES += qml/qml.qrc

DISTFILES += \
    qml/Clock/qmldir

DESTPATH = qml/Clock

target.path = $$DESTPATH
qmldir.files = $$DESTPATH/qmldir
qmldir.path = $$DESTPATH
INSTALLS += target qmldir

CONFIG += install_ok  # Do not cargo-cult this!

# Copy the qmldir file to the same folder as the plugin binary
QML_DIR = qml/Clock
resource.files += \
    $$QML_DIR/qmldir \
    $$QML_DIR/Clock.qml \
    $$QML_DIR/ClockBackground.qml \
    $$QML_DIR/GenericClockHand.qml \
    $$QML_DIR/HourClockHand.qml \
    $$QML_DIR/MinuteClockHand.qml \
    $$QML_DIR/SecondClockHand.qml
resource.path = $$DESTDIR
COPIES += resource
INSTALLS += resource
  1. Compile the project.

But how do I bring the compiled plugin into the sample-project? (sry, I have to few reputation to show images directly)

  1. All needed qml-files, the qmldir and the .dll is in the plugin-folder "Clock" (see here: https://i.stack.imgur.com/B3P0Q.jpg)
  2. Copy this folder to sample-project/build/ after the sample-project compiled 1 time (so the directory is created) (see here: https://i.stack.imgur.com/MuhZ0.jpg)
  3. In the qml-file I just want to use the module like that
import QtQuick 2.15
import QtQuick.Window 2.15
import Clock 1.0

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Clock {
        id: clock
    }
}

As it is documented it is enough to have this folder next to the .exe of my sample-project.

I already tried to set QML_IMPORT_PATH and QML2_IMPORT_PATH in the sample-project .pro-file. This unfortunately did not work as expected.

Besides that I tried some things from this thread.

2

There are 2 answers

0
Mhouney On BEST ANSWER

I finally got it. The hints of @Stephen Quan are pretty good. I ended up cleaning my whole .pro-file an rewrite it but this time only with the for me relevant stuff:

QT += qml
TEMPLATE = lib
CONFIG += qt plugin qmltypes

QML_IMPORT_NAME = ClockPlugin
QML_IMPORT_MAJOR_VERSION = 1

DESTDIR = imports/$$QML_IMPORT_NAME
TARGET  = clockplugin

RESOURCES += qml/plugin_qml.qrc

SOURCES += \
    src/ClockPlugin.cpp

HEADERS += \
    src/ClockPlugin.h

# copying dependecies of the plugin in the output-folder
PLUGIN_DEPENDENCY_DIRECTORY = $$PWD/qml/Clock
PluginDependencies.commands = $(COPY_DIR) $$shell_path($$PLUGIN_DEPENDENCY_DIRECTORY) $$shell_path($$DESTDIR)

first.depends = $(first) PluginDependencies
export(first.depends)
export(PluginDependencies)
QMAKE_EXTRA_TARGETS += first PluginDependencies

So with this I can then import the module with import ClockPlugin 1.0. The other things I mentioned in my question are still the same. (qmldir-file, etc.)

0
Stephen Quan On

As a good practice, the QML_DIR is pointing to the QML directory, not a subdirectory within. In your case, it should be qml, not qml/Clock. This also applies to QML2_IMPORT_PATH for Qt5.15.x and QML_IMPORT_PATH for Qt6.x.

Note that your statement:

I already tried to set QML_IMPORT_PATH and QML2_IMPORT_PATH in the sample-project .pro-file.

Does not make sense, since QML2_IMPORT_PATH refers to a runtime deployment of your app, NOT a developer-compile time requirement. So for this to work, you need to pay attention to where you app is being deployed, and, that the qml/Clock directory is correctly deployed there, and, then, QML2_IMPORT_PATH is set appropriately. The last point probably is not essential, since, I believe Qt should be checking there implicitly.

When you do import Clock 1.0 it will search ${QML2_IMPORT_PATH}/Clock for qmldir and from there it pulls in the required files. Assuming that qmldir contains the correct contents, everything should load.