QT Webkit的插件Plugin设计实现

 

    Qt Webkit中浏览器插件Plugin设计实现是我们要介绍的内容,我们都知道浏览器中有一套由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这个纯虚基类。先看看他的声明:

 

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来创建这个插件,而具体打开哪个文件以及参数都会传递进来。

 

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

因此重新实现的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; 
}


 

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

小结:Qt Webkit浏览器插件设计实现的内容介绍完了,希望通过本文的学习能对你有所帮助!

 

 

 

 

 


 


 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值