您的位置:首页 > 编程语言 > Qt开发

Qt Webkit中浏览器插件设计实现

2013-07-02 14:23 281 查看
Qt Webkit浏览器插件设计实现是我们要介绍的内容,我们都知道浏览器中有一套由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 ¶mValues
)

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

下面是一个例子:

class PluginPage : public QWebPage
{
public:
PluginPage(QObject *parent = 0)
: QWebPage(parent) {}
protected:
virtual QObject *createPlugin(const QString &classid, const QUrl &url,
const QStringList ¶mNames,
const QStringList ¶mValues)
{
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来创建这个插件,而具体打开哪个文件以及参数都会传递进来。

后两个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)
sspath=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浏览器插件设计实现的内容介绍完了,希望通过本文的学习能对你有所帮助!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: