WebKit -- qt javascript

来源:互联网 发布:淘宝仓库奖惩制度 编辑:程序博客网 时间:2024/04/27 22:53
 

在 QT 目录中打开下面的文件:
/src/3rdparty/webkit/JavaScriptCore/bindings/runtime.cpp

有下面几行:

view plaincopy to clipboardprint?
  1. #if PLATFORM(QT)   
  2.         case Instance::QtLanguage: {  
  3.             newInstance = Bindings::QtInstance::getQtInstance((QObject *)nativeInstance, rootObject);  
  4.             break;  
  5.         }  
  6. #endif  

这就表明,可以用 QtLanguage 来编写自定义的 javascript 对象。这里也有几个别的 Language,也就是说可以用它们来编写扩展 javascript 对象,应该也能自定义自己的 Language。既然是用 qt 的 GUI,使用 QtLanguage 应该是最合适的。

先打开它的例子文件:
/src/3rdparty/webkit/JavaScriptCore/bindings/testqtbindings.cpp

可以看到其中有这样几行:

view plaincopy to clipboardprint?
  1. static char code[] =  
  2.     "myInterface.foo();/n"  
  3.     "myInterface.testString = /"Hello/";/n"  
  4.     "str = myInterface.testString;/n"  
  5.     "myInterface.testInt = 10;/n"  
  6.     "i = myInterface.testInt;/n";  

这就是说,testqtbindings.cpp 的内容可以对下面的 javascript 进行解析:

view plaincopy to clipboardprint?
  1. myInterface.foo();  
  2. myInterface.testString = "Hello";  
  3. var str = myInterface.testString;  
  4. myInterface.testInt = 10;  
  5. var i = myInterface.testInt;  

我想定义自己的 javascript,比如在 myInterface 对象前面加上一个 CSDN 对象:

view plaincopy to clipboardprint?
  1. CSDN.myInterface.foo();  
  2. CSDN.myInterface.testString = "Hello";  
  3. var str = CSDN.myInterface.testString;  

这件事情本来很简单,可是就象 CSDN.myInterface.foo() 这样,连接 CSDN 和 myInterface 两个对象的事情,在网上(中文和英文网站)找了半天没找着,结果还是我自己想到的。

1. 在原来的文件中再添加一个 MyCSDNObject 对象:

view plaincopy to clipboardprint?
  1. class MyCSDNObject : public QObject  
  2. {  
  3.     Q_OBJECT  
  4.     Q_PROPERTY(QString testString READ testString WRITE setTestString)  
  5.     Q_PROPERTY(int testInt READ testInt WRITE setTestInt)  
  6.  // 添加 QObject 成员作为 CSDN 对象的属性,映射到 testMyInterface 函数上   
  7.  Q_PROPERTY(QObject* myInterface READ testMyInterface)  
  8.   
  9. public:  
  10.     MyCSDNObject() : QObject(0), integer(0), m_myObject(NULL){}  
  11.   
  12.     void setTestString(const QString &str) {  
  13.         qDebug() << "called setTestString" << str;  
  14.         string = str;  
  15.     }  
  16.     void setTestInt(int i) {  
  17.         qDebug() << "called setTestInt" << i;  
  18.         integer = i;  
  19.     }  
  20.     QString testString() const {  
  21.         qDebug() << "called testString" << string;  
  22.         return string;  
  23.     }  
  24.     int testInt() const {  
  25.         qDebug() << "called testInt" << integer;  
  26.         return integer;  
  27.     }  
  28.  // 在这里返回一个 QObject 对象   
  29.  QObject *testMyInterface()  
  30.  {  
  31.   if (m_myObject == NULL)  
  32.    m_myObject = new MyObject();  
  33.   return m_myObject;  
  34.  }  
  35.     QString string;  
  36.     int integer;  
  37.  // 声名一个 QObject 对象   
  38.  MyObject *m_myObject;  
  39.   
  40. public slots:  
  41.     void foo() { qDebug() << "foo invoked"; }  
  42. };  


这样 MyCSDNObject 和 MyObject 这样两个对象就可以连起来了,成为 CSDN.testMyInterface


2. 修改一下创建的根对象的名字

view plaincopy to clipboardprint?
  1. global->put(exec, Identifier("CSDN"), Instance::createRuntimeObject(Instance::QtLanguage, (void*)myObject));  

 
这样就可以了。这是个测试程序,需要把这些测试代码添加到 WebKit 浏览器中。打开文件:
./src/3rdparty/webkit/WebKit/qt/Api/qwebframe.h
把刚才的 MyObject 类和 MyCSDNObject 类在其中声名一下,然后添加 CSDN 根对象作为 QWebFrame 类的私有成员,如下所示:

view plaincopy to clipboardprint?
  1. class MyObject : public QObject  
  2. {  
  3.     Q_OBJECT  
  4.    // 省略 ...   
  5. };  
  6.   
  7. class MyCSDNObject : public QObject  
  8. {  
  9.     Q_OBJECT     
  10.     // 省略 ...   
  11. };  
  12.   
  13. class QWEBKIT_EXPORT QWebFrame : public QObject  
  14. {  
  15.     Q_OBJECT  
  16.     Q_PROPERTY(qreal textSizeMultiplier READ textSizeMultiplier WRITE setTextSizeMultiplier)  
  17.     Q_PROPERTY(QString title READ title)  
  18.     Q_PROPERTY(QUrl url READ url WRITE setUrl)  
  19.     Q_PROPERTY(QIcon icon READ icon)  
  20.     Q_PROPERTY(QSize contentsSize READ contentsSize)  
  21. private:  
  22.     QWebFrame(QWebPage *parent, QWebFrameData *frameData);  
  23.     QWebFrame(QWebFrame *parent, QWebFrameData *frameData);  
  24.     ~QWebFrame();  
  25.   
  26.     // 声名 CSDN 根对象   
  27.     MyCSDNObject *m_csdn;  
  28.   
  29.     public:  
  30.   // 以下省略 ...   
  31. };  


打开 qwebframe.cpp 文件,在 QWebFrame 的构造函数中创建 CSDN 根对象。

view plaincopy to clipboardprint?
  1. QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData)  
  2.     : QObject(parent)  
  3.     , d(new QWebFramePrivate)  
  4. {  
  5.     d->page = parent;  
  6.     d->init(this, parent->d->page, frameData);  
  7.   
  8.     // 在这里创建 CSDN 根对象   
  9.     {  
  10.     KJS::Bindings::RootObject *root = d->frame->bindingRootObject();  
  11.     KJS::ExecState *exec = root->interpreter()->globalExec();  
  12.     KJS::JSObject *global = root->interpreter()->globalObject();  
  13.   
  14.     m_csdn = new MyCSDNObject();  
  15.     global->put(exec, KJS::Identifier("CSDN"), KJS::Bindings::Instance::createRuntimeObject(KJS::Bindings::Instance::QtLanguage, (void *)m_csdn, root));  
  16.     }  
  17.   
  18.     if (!frameData->url.isEmpty()) {  
  19.         ResourceRequest request(frameData->url, frameData->referrer);  
  20.         d->frame->loader()->load(request, frameData->name);  
  21.     }  
  22. }  

 在 QWebFrame 的析构函数中删除 CSDN 根对象

view plaincopy to clipboardprint?
  1. QWebFrame::~QWebFrame()  
  2. {  
  3.     if (d->frame && d->frame->loader() && d->frame->loader()->client())  
  4.         static_cast(d->frame->loader()->client())->m_webFrame = 0;  
  5.   
  6.     if (m_csdn)  
  7.     {  
  8.         delete m_csdn;  
  9.         m_csdn = NULL;  
  10.     }  
  11.     delete d;  
  12. }  

再手工编写一个 HTML 测试页 csdn1.htm,内容如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title> New Document </title>
<script language="JavaScript">
<!--
function test()
{
 CSDN.myInterface.foo();
 CSDN.myInterface.testString = "Hello QtWebKit JavaScript";
 var str = CSDN.myInterface.testString;
 document.getElementById("txtMessage").innerHTML = str;
}
//-->
</script>
</head>

<body>
<p><a href="javascript:test();">test qt-webkit javascript</a></p>
<p id="txtMessage"></p>
</body>
</html>

编译并运行 WebKit 浏览器,让它打开刚才的测试页 csdn1.htm,点击上面的 test qt-webkit javascript 链接,可以得到下面的效果:

上面的 Hello QtWebKit JavaScript 就是 javascript 设置的 CSDN.myInterface.testString 内容。