内容插件示例

演示如何为 QML Live 编写内容插件。

Screenshot of the Plugin in Action

本示例中编写的插件显示图像,类似于 QML Live 内置的 Imageviewer,但它仅对 *.png 文件显示旋转后的内容。

我们将从审查 QML Live 源代码中定义的 contentadapterinterface.h 文件中的接口开始。此接口可用于将新的 ContentAdapter 添加到 QML Live。ContentAdapter 将用于显示 QML Live 运行时不应处理的任何内容,例如显示图像。

class QMLLIVESHARED_EXPORT ContentAdapterInterface
{
public:

    enum Feature {
        QtQuickControls = 0x1
    };
    Q_DECLARE_FLAGS(Features, Feature)

    virtual ~ContentAdapterInterface() {}

    virtual void cleanUp() {}

    virtual bool canPreview(const QString& path) const = 0;
    virtual QImage preview(const QString& path, const QSize &requestedSize) = 0;

    virtual bool canAdapt(const QUrl& url) const = 0;
    virtual bool isFullScreen() const { return false; }

    void setAvailableFeatures(ContentAdapterInterface::Features features) { m_features = features; }
    ContentAdapterInterface::Features availableFeatures() { return m_features; }

    virtual QUrl adapt(const QUrl& url, QQmlContext* context) = 0;

private:
    Features m_features;
};

ContentAdapterInterface 类声明了四个函数。第一个函数 canAdapt(const QUrl&) 返回插件是否可以显示给定的文件或目录。

第二个函数 adapt(const QUrl& url, QDeclarativeContext* context) 返回一个自定义的 QUrl,QML Live 将使用它来显示给定的 QUrl。返回的 QUrl 总是指向用于显示内容的 QML 文件。为了能够控制返回的 QML 文件,可以使用 context 设置自定义属性,这些属性将被导出到 QML 文件中。

canPreview() 和 preview() 用于生成预览缩略图。我们对这两个方法使用了最简单实现。

MyContentAdapterPlugin

class MyContentAdapterPlugin : public QObject, public ContentAdapterInterface
{
    Q_OBJECT
    Q_INTERFACES(ContentAdapterInterface)
    Q_PLUGIN_METADATA(IID "io.qt.QMLLive.ContentPlugin")
public:
    explicit MyContentAdapterPlugin(QObject *parent = 0);

    bool canPreview(const QString& path) const;
    QImage preview(const QString& path, const QSize &requestedSize);

    bool canAdapt(const QUrl& url) const;

    QUrl adapt(const QUrl& url, QQmlContext* context);
};

MyContentAdapterPlugin 实现了 QML Live 的接口。它继承自 QObject 和所需的 ContentAdapterInterface

    Q_INTERFACES(ContentAdapterInterface)

使用 Q_INTERFACES 宏将插件注册到 Qt 的插件系统中。

如果我们想正确地调用它,就必须重载 canAdapt(const QUrl&) 函数:*.png。因此,我们检查给定 url 的文件扩展名,当它是 png 文件时返回 true。

bool MyContentAdapterPlugin::canAdapt(const QUrl &url) const
{
    return url.toLocalFile().endsWith(".png");
}

如果插件接受该文件,adapt(const QUrl& url, QDeclarativeContext* context) 将被调用。在这里,我们将图像路径作为特殊属性导出到上下文中,以便能够在 QML 文件中访问 fileName。之后,我们返回指向我们的 QML 文件(位于 ResourceFile 中)的 QUrl

QUrl MyContentAdapterPlugin::adapt(const QUrl &url, QQmlContext *context)
{
    context->setContextProperty("imageSource", url);

    return QString("qrc:/mycontentadatperplugin/plugin.qml");
}

现在仅缺少 canPreview() 和 preview() 的实现。这里我们仅添加一些示例实现,因为我们不希望添加此功能。

bool MyContentAdapterPlugin::canPreview(const QString &path) const
{
    Q_UNUSED(path)

    return false;
}

QImage MyContentAdapterPlugin::preview(const QString &path, const QSize &requestedSize)
{
    Q_UNUSED(path);
    Q_UNUSED(requestedSize);

    return QImage();
}

plugin.qml

plugin.qml 文件是我们的 ImageViewer。在其中,我们创建一个 Image Element 并将源设置为导出的属性 imageSource。旋转属性将设置为 180。

import QtQuick 1.1

Rectangle {
    width: 300
    height: 300

    Image {
        anchors.centerIn: parent

        rotation: 180
        source: imageSource
    }
}

资源文件

因为我们不希望与路径纠缠,所以我们将我们的 QML 文件包含到资源文件中。在资源文件中使用唯一前缀很重要,以避免与也使用资源文件的 QML Live 冲突。最佳方法是将插件名称用作前缀。

文件

©2019 Luxoft Sweden AB。本文件中包含的文件贡献均为各自所有者的版权。本文件提供的文档遵循自由软件开发基金会发布的GNU自由文档许可证第1.3版的相关条款。Qt及其相关标志为芬兰的Qt公司有限公司及其它国家的商标。所有其他商标均属于各自所有者。