QtWebkit中浏览器插件的设计

我们都知道浏览器中有一套由Netscape浏览器传承下来的插件接口,包括webkit,firefox都是支持的,但是那个开发起来比较困难,并且是平台相关的,借助于Qt的跨平台的特性,可以方便地为Qt开发出一套跨平台的插件。

QtWebkit中插件可以有两种,一种Mime必须是application/x-qt-plugin或者application/x-qt-styled-widget,而另外一种则无需固定,可以是除了前面的两种以外任意其它Mime类型。

前一种相对来说开发起来比较容易,只需重新实现

QObject * QWebPage::createPlugin ( const QString & classid, const QUrl & url, const QStringList & paramNames, const QStringList &paramValues )

这个函数即可,这个函数会把HTML文件中的参数都传递进来

下面是一个例子:

class PluginPage : public QWebPage

{

public:

PluginPage(QObject *parent = 0)

QWebPage(parent) {}

protected:

virtual QObject *createPlugin(const QString &classid, const QUrl &url,

const QStringList &paramNames,

const QStringList &paramValues)

{

QObject *result = 0;

if (classid == "pushbutton")

result = new QPushButton();

else if (classid == "lineedit")

result = new QLineEdit();

if (result)

result->setObjectName(classid);

//可以进行一些处理

return result;

}

};

 

这样下面的网页就可以一个pushbutton了:

<html><body><object type='application/x-qt-plugin' classid='pushbutton' id='mybutton'/></body></html>

并且还可以在JavaScript访问到QPushbutton,例如:

document.getElementById('mybutton').text将会返回按钮上的字符串。

 ------------------------

    前一节介绍的插件设计方式中虽然方便,但是其Mime类型只能是application/x-qt-plugin或者application/x-qt-styled-widget,这个有时候可能满足不了实际应用需求,那么另一种就没有这种限制,那可以是任意Mime类型的。这种设计需要重新实现QWebPluginFactory这个纯虚基类。先看看他的声明:

前一节介绍的插件设计方式中虽然方便,但是其Mime类型只能是application/x-qt-plugin或者application/x-qt-styled-widget,这个有时候可能满足不了实际应用需求,那么另一种就没有这种限制,那可以是任意Mime类型的。这种设计需要重新实现QWebPluginFactory这个纯虚基类。先看看他的声明:

class QWEBKIT_EXPORT QWebPluginFactory : public QObject {

……

public:

struct Plugin {

QString name;

QString description;

QList<MimeType> mimeTypes;

};

explicit QWebPluginFactory(QObject* parent = 0);

virtual ~QWebPluginFactory();

 

virtual QList<Plugin> plugins() const = 0;

virtual void refreshPlugins();

 

virtual QObject *create(const QString& mimeType,

const QUrl&,

const QStringList& argumentNames,

const QStringList& argumentValues) const = 0;

 

 

virtual bool extension(Extension extension, const ExtensionOption* option = 0, ExtensionReturn* output = 0);

virtual bool supportsExtension(Extension extension) const;

……

};

 

重点要实现的接口是plugins,用于获取plugin的列表,用于webkit内部判断该mime类型是否被支持,如果可以支持,那么就会调用create来创建这个插件,而具体打开哪个文件以及参数都会传递进来。

后两个extensionsupportsExtension接口暂时没有发现有什么用处,暂不考虑。

因此重新实现的WebPluginFactory如下:

class WebPluginFactory: public QWebPluginFactory

{

    public:

        WebPluginFactory(QObject *parent = 0);

        ~WebPluginFactory(){};

        QList<QWebPluginFactory::Plugin> plugins()const ;

        void refreshPlugins();

        QObject *create(const QString &mimeType,

                const QUrl &url,

                const QStringList &argumentNames,

                const QStringList &argumentValues) const ;

        bool extension(QWebPluginFactory::Extension extension, const QWebPluginFactory::ExtensionOption *option = 0, QWebPluginFactory::ExtensionReturn *output = 0);

        bool supportsExtension(QWebPluginFactory::Extension extension) const;

    private:

        // 用于将载入的插件记录下来

        mutable QList<QList<QWebPluginFactory::Plugin> > pluginslist;

        mutable QList<WebKitPluginInteface *> interfaces;

};

 

具体实现主要是create和plugins两个函数:

QList<QWebPluginFactory::Plugin> WebPluginFactory::plugins() const

{

    const char * s=getenv("BROWSER_PLUGIN_DIR");

    static bool isFirst=true;

    if(!isFirst)

    {

        return pluginslist;

    }

    isFirst=false;

    QString spath;

    if(s)

    spath=s;

    else

{

spath=".";

}

    QDir dir(spath);

    QStringList filters;

    QString abspath=dir.absolutePath();

filters<<"libqtweb*.so"; //查找下面的扩张,linux下是so,windows下则应该是dll,

    QStringList files=dir.entryList(filters);

    foreach(QString file,files)

    {

        file=dir.filePath(file);

        QPluginLoader loader(file,0);

        QObject * obj= loader.instance();

//下面是载入自定义的接口,只有这样才能支持动态插件创建,如果固定死了,将不利于扩展,后一节会介绍这部分内容

        WebKitPluginInteface * interface= qobject_cast<WebKitPluginInteface*> (obj);

        if(interface==0)

        {

            //ignore error when loading so ;

            continue;

        }

        interface->plugins();

        plugins.append(interface->plugins());

        pluginslist.append(interface->plugins());

        interfaces.append(interface);

    }

    return plugins;

}

void WebPluginFactory::refreshPlugins()

{

    Reload();

}

QObject * WebPluginFactory::create(const QString &mimeType,

        const QUrl &url,

        const QStringList &argumentNames,

        const QStringList &argumentValues) const

{

    for(int i=0;i<pluginslist.size();i++)

    {

        for( int j=0;j< pluginslist[i].size();j++)

        {

            foreach(WebPluginFactory::MimeType mt, pluginslist[i][j].mimeTypes)

            {

                if(mt.name == mimeType) //查找到,创建实例

                    return interfaces[i]->create( mimeType, url, argumentNames, argumentValues);

            }

        }

    }

    return NULL; //如果没有,直接返回NULL,webkit会进行处理的

}

 

这两个最主要的接口都是围绕着mimetype进行的,通过返回的列表告诉webkit插件支持什么类型的文件,而create则根据mimetype来识别文件类型,然后创建相应的插件。

下一节会简单的创建一个插件来演示如何创建一个插件。

--------------------

上一篇讲到可以通过扩展QWebPage接口进行动态载入插件,但是插件的接口并没有明确,这一篇通过介绍自定义的接口来实现插件的动态载入。

首先是接口的定义:

class WebKitPluginInteface

{

    public:

        virtual ~WebKitPluginInteface(){};

        virtual QList<QWebPluginFactory::Plugin> plugins()const =0;

        virtual QObject *create(const QString &mimeType,

                const QUrl &url,

                const QStringList &argumentNames,

                const QStringList &argumentValues) const =0;

};

 

Q_DECLARE_INTERFACE(WebKitPluginInteface, "baizx.cnblogs.com/1.0")

 

这样自定义的插件就可以通过实现这个接口来实现定制的插件。下面是一个例子:

class TestPlugin :public QObject,public WebKitPluginInteface

{

Q_OBJECT

Q_INTERFACES(WebKitPluginInteface)

    public:

        TestPlugin(QObject * parent=0): WebkitPlugin(parent){};

        virtual ~TestPlugin(){};

        virtual QList<QWebPluginFactory::Plugin> plugins()const ;

        virtual QObject *create(const QString &mimeType,

                const QUrl &url,

                const QStringList &argumentNames,

                const QStringList &argumentValues) const ;

};

 

QList<QWebPluginFactory::Plugin> TestPlugin::plugins()const

{

    QList<QWebPluginFactory::Plugin> plugins ;

    QWebPluginFactory::Plugin plugin;

    QWebPluginFactory::MimeType mimeType;

    QStringList strings;

    plugin.name="testplugin";

    plugin.description="testplugin !!!";

    mimeType.name="application/x-textedit";

    mimeType.description="test textedit";

    strings.append(".etxt");

    mimeType.fileExtensions=strings;

    QList<QWebPluginFactory::MimeType> mimeTypes;

    mimeTypes.append(mimeType);

    plugin.mimeTypes=mimeTypes;

    plugins.append(plugin);

    return plugins;

}

QObject *TestPlugin::create(const QString &mimeType,

                const QUrl &url,

                const QStringList &argumentNames,

                const QStringList &argumentValues) const

{

    QTextEdit * edit= new QTextEdit();

edit->setObjectName("我是插件");

    edit->setPlainText(mimeType + url.toString() );

    Q_UNUSED(argumentNames);

    Q_UNUSED(argumentValues);

    return edit;

}

 

这样一个简单的插件就创建完毕了,具体实际应用中可能会用到很到参数,并且会载入实际的内容,这里只是一个演示


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值