为QT Webkit编写插件案例实现是本文要介绍的内容,主要是来了解QT Webkit中的插件问题,为了允许的QWebView加载插件,必须使能QWebView的Javascript和Plugins属性,使能方法为:
- QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled,true);
- QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled,true);
或者
//这里假设webView是QWebView的对象:
- QWebView *webView;webView->settings()->setAttribute(QWebSettings::JavascriptEnabled,true);
- webView->settings()->setAttribute(QWebSettings::PluginsEnabled,true);
然后为QWebView添加插件工厂,这个插件工厂中包含了QWebView中所有可用的插件库,当然这个插件工厂中包含哪些插件得由我们程序员来定。添加插件工厂的方法为:
//为QWebView添加插件工厂,即告诉QWebView有哪些插件可用。//这里的 WebkitPluginFactory 是Qt的虚类 QWebPluginFactory 的实现类,后面会讲到这个类。
- webView->page()->setPluginFactory(new WebkitPluginFactory(this));
下面我们就来实现这个插件工厂类WebkitPluginFactory, 主要需要实现的就是 QWebPluginFactory 中的两个虚函数:
- 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() 方法则根据mimeType等参数来决定创建相应的插件。下面给出这个类的实现代码:
- 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();
- //下面是载入自定义的接口,只有这样才能支持动态插件创建,如果固定死了,将不利于扩展
- 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类型,创建相应的插件实例
- return interfaces[i]->
- create( mimeType, url, argumentNames, argumentValues);
- }
- }
- }
- return NULL; //如果没有,直接返回NULL,webkit会进行处理的
- }
下面就可以开始编写插件库。首先我们定义插件的统一接口,然后每个插件类只需实现该接口就行了,这样有利于扩展插件库。
自定义的插件接口:
- 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.
下面我们开始实现这个接口:
我们将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("但现在替换成了我们自定义的插件(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 是插件类名。
现在只要把生成的libWebkitFlashPlugin.so插件库拷贝到webkitpluginfactory插件工厂能搜到的目录下就行了(本例中我在webkitpluginfactory.cpp中指定的位置为 const char *s = "/home/nxx/FlashPlugin-build-desktop";)。
上面的插件库和前面的工厂类,QWebView对象组合在一起就可以实现:
当用QWebView打开包含了需要 mimeType.name="application/x-shockwave-flash" 类型的插件的网页的时候,就会调用到我们自定义的flashplugin插件了。
效果如下:
小结:详解为QT Webkit编写插件案例实现的内容介绍完了,希望通过本文的学习能对你有所帮助!