Qt Webkit中瀏覽器插件設計實現(xiàn)
Qt Webkit中瀏覽器插件設計實現(xiàn)是我們要介紹的內容,我們都知道瀏覽器中有一套由Netscape瀏覽器傳承下來的插件接口,包括webkit,firefox都是支持的,但是那個開發(fā)起來比較困難,并且是平臺相關的,借助于Qt的跨平臺的特性,可以方便地為Qt開發(fā)出一套跨平臺的插件。
QtWebkit中插件可以有兩種,一種Mime必須是application/x-qt-plugin或者application/x-qt-styled-widget,而另外一種則無需固定,可以是除了前面的兩種以外任意其它Mime類型。
前一種相對來說開發(fā)起來比較容易,只需重新實現(xiàn)
- QObject * QWebPage::createPlugin (
- const QString
- & classid, const QUrl
- & url, const QStringList
- & paramNames, const QStringList ¶mValues
- )
這個函數(shù)即可,這個函數(shù)會把HTML文件中的參數(shù)都傳遞進來
下面是一個例子:
- 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將會返回按鈕上的字符串。
前一節(jié)介紹的插件設計方式中雖然方便,但是其Mime類型只能是application/x-qt-plugin或者application/x-qt-styled-widget,這個有時候可能滿足不了實際應用需求,那么另一種就沒有這種限制,那可以是任意Mime類型的。這種設計需要重新實現(xiàn)QWebPluginFactory這個純虛基類。先看看他的聲明:
前一節(jié)介紹的插件設計方式中雖然方便,但是其Mime類型只能是application/x-qt-plugin或者application/x-qt-styled-widget,這個有時候可能滿足不了實際應用需求,那么另一種就沒有這種限制,那可以是任意Mime類型的。這種設計需要重新實現(xiàn)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;
- ……
- };
重點要實現(xiàn)的接口是plugins,用于獲取plugin的列表,用于webkit內部判斷該mime類型是否被支持,如果可以支持,那么就會調用create來創(chuàng)建這個插件,而具體打開哪個文件以及參數(shù)都會傳遞進來。
后兩個extension和supportsExtension接口暫時沒有發(fā)現(xiàn)有什么用處,暫不考慮。
因此重新實現(xiàn)的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;
- };
具體實現(xiàn)主要是create和plugins兩個函數(shù):
- 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();
- //下面是載入自定義的接口,只有這樣才能支持動態(tài)插件創(chuàng)建,如果固定死了,將不利于擴展,后一節(jié)會介紹這部分內容
- 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) //查找到,創(chuàng)建實例
- return interfaces[i]->create( mimeType, url, argumentNames, argumentValues);
- }
- }
- }
- return NULL; //如果沒有,直接返回NULL,webkit會進行處理的
- }
這兩個最主要的接口都是圍繞著mimetype進行的,通過返回的列表告訴webkit插件支持什么類型的文件,而create則根據(jù)mimetype來識別文件類型,然后創(chuàng)建相應的插件。
下一節(jié)會簡單的創(chuàng)建一個插件來演示如何創(chuàng)建一個插件。
上一篇講到可以通過擴展QWebPage接口進行動態(tài)載入插件,但是插件的接口并沒有明確,這一篇通過介紹自定義的接口來實現(xiàn)插件的動態(tài)載入。
首先是接口的定義:
- 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")
這樣自定義的插件就可以通過實現(xiàn)這個接口來實現(xiàn)定制的插件。下面是一個例子:
- 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;
- }
這樣一個簡單的插件就創(chuàng)建完畢了,具體實際應用中可能會用到很到參數(shù),并且會載入實際的內容,這里只是一個演示。
小結:Qt Webkit中瀏覽器插件設計實現(xiàn)的內容介紹完了,希望通過本文的學習能對你有所幫助!