詳解為QT Webkit編寫(xiě)插件案例實(shí)現(xiàn)
為QT Webkit編寫(xiě)插件案例實(shí)現(xiàn)是本文要介紹的內(nèi)容,主要是來(lái)了解QT Webkit中的插件問(wèn)題,為了允許的QWebView加載插件,必須使能QWebView的Javascript和Plugins屬性,使能方法為:
- QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled,true);
 - QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled,true);
 
或者
//這里假設(shè)webView是QWebView的對(duì)象:
- QWebView *webView;webView->settings()->setAttribute(QWebSettings::JavascriptEnabled,true);
 - webView->settings()->setAttribute(QWebSettings::PluginsEnabled,true);
 
然后為QWebView添加插件工廠,這個(gè)插件工廠中包含了QWebView中所有可用的插件庫(kù),當(dāng)然這個(gè)插件工廠中包含哪些插件得由我們程序員來(lái)定。添加插件工廠的方法為:
//為QWebView添加插件工廠,即告訴QWebView有哪些插件可用。//這里的 WebkitPluginFactory 是Qt的虛類 QWebPluginFactory 的實(shí)現(xiàn)類,后面會(huì)講到這個(gè)類。
- webView->page()->setPluginFactory(new WebkitPluginFactory(this));
 
下面我們就來(lái)實(shí)現(xiàn)這個(gè)插件工廠類WebkitPluginFactory, 主要需要實(shí)現(xiàn)的就是 QWebPluginFactory 中的兩個(gè)虛函數(shù):
- virtual QObject *create(
 - const QString &mimeType,
 - const QUrl &url,
 - const QStringList &argumentNames,
 - const QStringList & argumentValues )
 - const = 0;virtual QList<Plugin>
 - plugins () const = 0;
 - plugins() 方法為獲取所有可用的插件列表, create() 方法則根據(jù)mimeType等參數(shù)來(lái)決定創(chuàng)建相應(yīng)的插件。下面給出這個(gè)類的實(shí)現(xiàn)代碼:
 - webkitpluginfactory.h :
 - #ifndef WEBKITPLUGINFACTORY_H
 - #define WEBKITPLUGINFACTORY_H
 - #include <QWebPluginFactory>
 - #include <QUrl>
 - #include "webkitplugininterface.h" class WebkitPluginFactory : public QWebPluginFactory{
 - Q_OBJECTpublic: WebkitPluginFactory(QObject *parent = 0);
 - QObject *create (
 - const QString & mimeType, const QUrl & url,
 - const QStringList & argumentNames, const QStringList & argumentValues )
 - const; QList<QWebPluginFactory::Plugin> plugins () const;
 - private: // 插件列表 mutable QList<QList<QWebPluginFactory::Plugin> > pluginslist;
 - //插件接口,這個(gè)接口是我們自定義的插件的同意接口。 //這個(gè)接口在后面會(huì)講到。
 - mutable QList<WebKitPluginInterface *> interfaces;
 - };
 - #endif // WEBKITPLUGINFACTORY_H
 - webkitpluginfactory.cpp :
 - #include "webkitpluginfactory.h"
 - #include <QPluginLoader>
 - #include <QDebug>
 - #include <QDir>
 - WebkitPluginFactory::WebkitPluginFactory(QObject *parent) :
 - QWebPluginFactory(){
 - qDebug()<<"debug : WebkitPluginFactory";
 - }
 - QList<QWebPluginFactory::Plugin>
 - WebkitPluginFactory::plugins () const{
 - //const char * s=getenv("BROWSER_PLUGIN_DIR");
 - const char *s = "/home/nxx/FlashPlugin-build-desktop";
 - static bool isFirst=true;
 - static QList<QWebPluginFactory::Plugin> plugins;
 - if(!isFirst) {
 - return plugins;
 - }
 - isFirst=false;
 - plugins.clear();
 - QString spath;
 - if(s) sspath=s;
 - else spath=".";
 - QDir dir(spath);
 - QStringList filters;
 - QString abspath=dir.absolutePath();
 - qDebug()<<abspath; //獲取指定目錄下的所有插件,linux下是插件庫(kù)的后綴為so,windows下則是dll
 - filters<<"lib*.so";
 - QStringList files=dir.entryList(filters);
 - qDebug()<<"files: "<<files; foreach(QString file,files) {
 - qDebug()<<QLibrary::isLibrary(file);
 - file=dir.filePath(file);
 - qDebug()<<"path: "<<file;
 - QPluginLoader loader(file);
 - QObject * obj= loader.instance();
 - if(obj==0)
 - qDebug()<<"error: "<<loader.errorString();
 - //下面是載入自定義的接口,只有這樣才能支持動(dòng)態(tài)插件創(chuàng)建,如果固定死了,將不利于擴(kuò)展
 - WebKitPluginInterface * interface= qobject_cast<WebKitPluginInterface*> (obj);
 - if(interface==0) {
 - qDebug()<<"ignore error when loading so" ;
 - continue;
 - }
 - qDebug()<<"load plugins: "<<interface->plugins().at(0).name;
 - plugins.append(interface->plugins());
 - pluginslist.append(interface->plugins());
 - interfaces.append(interface);
 - } if(plugins.isEmpty()){
 - qDebug()<<"no plugins is loaded!";
 - }
 - return plugins;
 - } QObject * WebkitPluginFactory::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(QWebPluginFactory::MimeType mt, pluginslist[i][j].mimeTypes) {
 - if(mt.name == mimeType) //更具M(jìn)IME類型,創(chuàng)建相應(yīng)的插件實(shí)例
 - return interfaces[i]->
 - create( mimeType, url, argumentNames, argumentValues);
 - }
 - }
 - }
 - return NULL; //如果沒(méi)有,直接返回NULL,webkit會(huì)進(jìn)行處理的
 - }
 
下面就可以開(kāi)始編寫(xiě)插件庫(kù)。首先我們定義插件的統(tǒng)一接口,然后每個(gè)插件類只需實(shí)現(xiàn)該接口就行了,這樣有利于擴(kuò)展插件庫(kù)。
自定義的插件接口:
- webkitplugininterface.h :
 - #ifndef WEBKITPLUGININTERFACE_H
 - #define WEBKITPLUGININTERFACE_H
 - #include <QWebPluginFactory>
 - class WebKitPluginInterface{public: virtual
 - WebKitPluginInterface(){};
 - virtual QList<QWebPluginFactory::Plugin> plugins()const =0;
 - virtual QObject *create(
 - const QString &mimeType,
 - const QUrl &url,
 - const QStringList &argumentNames,
 - const QStringList &argumentValues)
 - const =0;}; //聲明WebKitPluginInterface為一個(gè)接口
 - Q_DECLARE_INTERFACE(WebKitPluginInterface, "com.plugin.uvchip.www/1.0")
 - #endif // WEBKITPLUGININTERFACE_H
 
上面的那段代碼中的Q_DECLARE_INTERFACE() 是在定義接口是必須添加聲明。下面是Qt對(duì)這個(gè)宏的說(shuō)明:
- Q_DECLARE_INTERFACE (
 - ClassName, Identifier )This macro associates the given Identifier (a string literal)
 - to the interface class called ClassName. The Identifier must be unique.
 
下面我們開(kāi)始實(shí)現(xiàn)這個(gè)接口:
我們將flashplugin編譯成庫(kù),這樣就可以供插件工廠WebkitPluginFactory加載訪問(wèn)了。
- flashplugin.h :
 - #ifndef FLASHPLUGIN_H
 - #define FLASHPLUGIN_H
 - #if defined(FLASHPLUGIN_LIBRARY)
 - # define FLASHPLUGINSHARED_EXPORT Q_DECL_EXPORT#else
 - # define FLASHPLUGINSHARED_EXPORT Q_DECL_IMPORT#endif
 - #include "webkitplugininterface.h"
 - #include <QtPlugin>
 - class FLASHPLUGINSHARED_EXPORT FlashPlugin : public QObject, public WebKitPluginInterface {
 - Q_OBJECT
 - Q_INTERFACES(WebKitPluginInterface) //聲明WebKitPluginInterface是一個(gè)接口
 - public:
 - FlashPlugin(): WebKitPluginInterface(){};
 - ~FlashPlugin(){};
 - QList<QWebPluginFactory::Plugin> plugins()const ;
 - QObject *create(const QString &mimeType,
 - const QUrl &url,
 - const QStringList &argumentNames,
 - const QStringList &argumentValues) const ;
 - };
 - #endif // FLASHPLUGIN_H
 - flashplugin.cpp :
 - #include "flashplugin.h"
 - #include <QTextEdit>
 - #include <QUrl>
 - #include <QDebug>
 - QList<QWebPluginFactory::Plugin> FlashPlugin::plugins()const{
 - QWebPluginFactory::MimeType mimeType;
 - mimeType.name="application/x-shockwave-flash";
 - mimeType.description=QObject::tr("flash");
 - mimeType.fileExtensions.append(".flv");
 - mimeType.fileExtensions.append(".f4v");
 - mimeType.fileExtensions.append(".swf");
 - QList<QWebPluginFactory::MimeType> mimeTypes;
 - mimeTypes.append(mimeType);
 - QWebPluginFactory::Plugin plugin;
 - plugin.name=QObject::tr("External Video viewer plugin");
 - plugin.description=QObject::tr("Use vlc to open video files !!!");
 - plugin.mimeTypes=mimeTypes;
 - QList<QWebPluginFactory::Plugin> plugins ;
 - plugins.append(plugin);
 - return plugins;
 - }
 - QObject *FlashPlugin::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() +"\n\n"
 - +QString::fromUtf8("這里本來(lái)是需要adobeFlash插件的,")+"\n"
 - +QString::fromUtf8("但現(xiàn)在替換成了我們自定義的插件(QTextEdit插件了)。")
 - );
 - Q_UNUSED(argumentNames);
 - Q_UNUSED(argumentValues);
 - qDebug()<<"create flash plugin";
 - return edit;
 - }
 
//Q_EXPORT_PLUGIN2()必不可少,//只有這樣FlashPlugin插件類才為外部可見(jiàn),插件名為WebkitPluginFlashQ_EXPORT_PLUGIN2(WebkitPluginFlash,FlashPlugin)
Q_EXPORT_PLUGIN2 在Qt幫助文檔中的說(shuō)明如下:
- Q_EXPORT_PLUGIN2 ( PluginName, ClassName )
 - This macro exports the plugin class ClassName for the plugin specified by PluginName.
 - The value of PluginName should correspond to the TARGET specified in the plugin's project file.
 - There should be exactly one occurrence of this macro in the source code for a Qt plugin,
 - and it should be used where the implementation is written rather than in a header file.
 
Q_EXPORT_PLUGIN2(WebkitPluginFlash, FlashPlugin) 中的WebkitPluginFlash為編譯之后生成的庫(kù)的名字,這里的生成的庫(kù)的完整名字為:libWebkitFlashPlugin.so, FlashPlugin 是插件類名。
現(xiàn)在只要把生成的libWebkitFlashPlugin.so插件庫(kù)拷貝到webkitpluginfactory插件工廠能搜到的目錄下就行了(本例中我在webkitpluginfactory.cpp中指定的位置為 const char *s = "/home/nxx/FlashPlugin-build-desktop";)。
上面的插件庫(kù)和前面的工廠類,QWebView對(duì)象組合在一起就可以實(shí)現(xiàn):
當(dāng)用QWebView打開(kāi)包含了需要 mimeType.name="application/x-shockwave-flash" 類型的插件的網(wǎng)頁(yè)的時(shí)候,就會(huì)調(diào)用到我們自定義的flashplugin插件了。
效果如下:
小結(jié):詳解為QT Webkit編寫(xiě)插件案例實(shí)現(xiàn)的內(nèi)容介紹完了,希望通過(guò)本文的學(xué)習(xí)能對(duì)你有所幫助!
















 
 
 
 
 
 
 