詳解為QT Webkit編寫插件案例實現(xiàn)
為QT Webkit編寫插件案例實現(xiàn)是本文要介紹的內(nèi)容,主要是來了解QT Webkit中的插件問題,為了允許的QWebView加載插件,必須使能QWebView的Javascript和Plugins屬性,使能方法為:
- QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled,true);
- QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled,true);
或者
//這里假設(shè)webView是QWebView的對象:
- QWebView *webView;webView->settings()->setAttribute(QWebSettings::JavascriptEnabled,true);
- webView->settings()->setAttribute(QWebSettings::PluginsEnabled,true);
然后為QWebView添加插件工廠,這個插件工廠中包含了QWebView中所有可用的插件庫,當(dāng)然這個插件工廠中包含哪些插件得由我們程序員來定。添加插件工廠的方法為:
//為QWebView添加插件工廠,即告訴QWebView有哪些插件可用。//這里的 WebkitPluginFactory 是Qt的虛類 QWebPluginFactory 的實現(xiàn)類,后面會講到這個類。
- webView->page()->setPluginFactory(new WebkitPluginFactory(this));
下面我們就來實現(xiàn)這個插件工廠類WebkitPluginFactory, 主要需要實現(xiàn)的就是 QWebPluginFactory 中的兩個虛函數(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ù)來決定創(chuàng)建相應(yīng)的插件。下面給出這個類的實現(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;
- //插件接口,這個接口是我們自定義的插件的同意接口。 //這個接口在后面會講到。
- 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下是插件庫的后綴為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();
- //下面是載入自定義的接口,只有這樣才能支持動態(tài)插件創(chuàng)建,如果固定死了,將不利于擴展
- 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) //更具MIME類型,創(chuàng)建相應(yīng)的插件實例
- return interfaces[i]->
- create( mimeType, url, argumentNames, argumentValues);
- }
- }
- }
- return NULL; //如果沒有,直接返回NULL,webkit會進行處理的
- }
下面就可以開始編寫插件庫。首先我們定義插件的統(tǒng)一接口,然后每個插件類只需實現(xiàn)該接口就行了,這樣有利于擴展插件庫。
自定義的插件接口:
- 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為一個接口
- Q_DECLARE_INTERFACE(WebKitPluginInterface, "com.plugin.uvchip.www/1.0")
- #endif // WEBKITPLUGININTERFACE_H
上面的那段代碼中的Q_DECLARE_INTERFACE() 是在定義接口是必須添加聲明。下面是Qt對這個宏的說明:
- 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.
下面我們開始實現(xiàn)這個接口:
我們將flashplugin編譯成庫,這樣就可以供插件工廠WebkitPluginFactory加載訪問了。
- 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是一個接口
- 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("這里本來是需要adobeFlash插件的,")+"\n"
- +QString::fromUtf8("但現(xiàn)在替換成了我們自定義的插件(QTextEdit插件了)。")
- );
- Q_UNUSED(argumentNames);
- Q_UNUSED(argumentValues);
- qDebug()<<"create flash plugin";
- return edit;
- }
//Q_EXPORT_PLUGIN2()必不可少,//只有這樣FlashPlugin插件類才為外部可見,插件名為WebkitPluginFlashQ_EXPORT_PLUGIN2(WebkitPluginFlash,FlashPlugin)
Q_EXPORT_PLUGIN2 在Qt幫助文檔中的說明如下:
- 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為編譯之后生成的庫的名字,這里的生成的庫的完整名字為:libWebkitFlashPlugin.so, FlashPlugin 是插件類名。
現(xiàn)在只要把生成的libWebkitFlashPlugin.so插件庫拷貝到webkitpluginfactory插件工廠能搜到的目錄下就行了(本例中我在webkitpluginfactory.cpp中指定的位置為 const char *s = "/home/nxx/FlashPlugin-build-desktop";)。
上面的插件庫和前面的工廠類,QWebView對象組合在一起就可以實現(xiàn):
當(dāng)用QWebView打開包含了需要 mimeType.name="application/x-shockwave-flash" 類型的插件的網(wǎng)頁的時候,就會調(diào)用到我們自定義的flashplugin插件了。
效果如下:
小結(jié):詳解為QT Webkit編寫插件案例實現(xiàn)的內(nèi)容介紹完了,希望通過本文的學(xué)習(xí)能對你有所幫助!