在 QT 目錄中開啟下面的檔案:
/src/3rdparty/webkit/JavaScriptCore/bindings/runtime.cpp
有下面幾行:
view plaincopy to clipboardprint?
- #if PLATFORM(QT)
- case Instance::QtLanguage: {
- newInstance = Bindings::QtInstance::getQtInstance((QObject *)nativeInstance, rootObject);
- break;
- }
- #endif
#if PLATFORM(QT) case Instance::QtLanguage: { newInstance = Bindings::QtInstance::getQtInstance((QObject *)nativeInstance, rootObject); break; }#endif
這就表明,可以用 QtLanguage 來編寫自訂的 javascript 對象。這裡也有幾個別的 Language,也就是說可以用它們來編寫擴充 javascript 對象,應該也能自訂自己的 Language。既然是用 qt 的 GUI,使用 QtLanguage 應該是最合適的。
先開啟它的例子檔案:
/src/3rdparty/webkit/JavaScriptCore/bindings/testqtbindings.cpp
可以看到其中有這樣幾行:
view plaincopy to clipboardprint?
- static char code[] =
- "myInterface.foo();/n"
- "myInterface.testString = /"Hello/";/n"
- "str = myInterface.testString;/n"
- "myInterface.testInt = 10;/n"
- "i = myInterface.testInt;/n";
static char code[] = "myInterface.foo();/n" "myInterface.testString = /"Hello/";/n" "str = myInterface.testString;/n" "myInterface.testInt = 10;/n" "i = myInterface.testInt;/n";
這就是說,testqtbindings.cpp 的內容可以對下面的 javascript 進行解析:
view plaincopy to clipboardprint?
- myInterface.foo();
- myInterface.testString = "Hello";
- var str = myInterface.testString;
- myInterface.testInt = 10;
- var i = myInterface.testInt;
myInterface.foo();myInterface.testString = "Hello";var str = myInterface.testString;myInterface.testInt = 10;var i = myInterface.testInt;
我想定義自己的 javascript,比如在 myInterface 對象前面加上一個 CSDN 對象:
view plaincopy to clipboardprint?
- CSDN.myInterface.foo();
- CSDN.myInterface.testString = "Hello";
- var str = CSDN.myInterface.testString;
CSDN.myInterface.foo();CSDN.myInterface.testString = "Hello";var str = CSDN.myInterface.testString;
這件事情本來很簡單,可是就象 CSDN.myInterface.foo() 這樣,串連 CSDN 和 myInterface 兩個對象的事情,在網上(中文和英文網站)找了半天沒找著,結果還是我自己想到的。
1. 在原來的檔案中再添加一個 MyCSDNObject 對象:
view plaincopy to clipboardprint?
- class MyCSDNObject : public QObject
- {
- Q_OBJECT
- Q_PROPERTY(QString testString READ testString WRITE setTestString)
- Q_PROPERTY(int testInt READ testInt WRITE setTestInt)
- // 添加 QObject 成員作為 CSDN 對象的屬性,映射到 testMyInterface 函數上
- Q_PROPERTY(QObject* myInterface READ testMyInterface)
-
- public:
- MyCSDNObject() : QObject(0), integer(0), m_myObject(NULL){}
-
- void setTestString(const QString &str) {
- qDebug() << "called setTestString" << str;
- string = str;
- }
- void setTestInt(int i) {
- qDebug() << "called setTestInt" << i;
- integer = i;
- }
- QString testString() const {
- qDebug() << "called testString" << string;
- return string;
- }
- int testInt() const {
- qDebug() << "called testInt" << integer;
- return integer;
- }
- // 在這裡返回一個 QObject 對象
- QObject *testMyInterface()
- {
- if (m_myObject == NULL)
- m_myObject = new MyObject();
- return m_myObject;
- }
- QString string;
- int integer;
- // 聲名一個 QObject 對象
- MyObject *m_myObject;
-
- public slots:
- void foo() { qDebug() << "foo invoked"; }
- };
class MyCSDNObject : public QObject{ Q_OBJECT Q_PROPERTY(QString testString READ testString WRITE setTestString) Q_PROPERTY(int testInt READ testInt WRITE setTestInt) // 添加 QObject 成員作為 CSDN 對象的屬性,映射到 testMyInterface 函數上 Q_PROPERTY(QObject* myInterface READ testMyInterface)public: MyCSDNObject() : QObject(0), integer(0), m_myObject(NULL){} void setTestString(const QString &str) { qDebug() << "called setTestString" << str; string = str; } void setTestInt(int i) { qDebug() << "called setTestInt" << i; integer = i; } QString testString() const { qDebug() << "called testString" << string; return string; } int testInt() const { qDebug() << "called testInt" << integer; return integer; } // 在這裡返回一個 QObject 對象 QObject *testMyInterface() { if (m_myObject == NULL) m_myObject = new MyObject(); return m_myObject; } QString string; int integer; // 聲名一個 QObject 對象 MyObject *m_myObject;public slots: void foo() { qDebug() << "foo invoked"; }};
這樣 MyCSDNObject 和 MyObject 這樣兩個對象就可以連起來了,成為 CSDN.testMyInterface
2. 修改一下建立的根對象的名字
view plaincopy to clipboardprint?
- global->put(exec, Identifier("CSDN"), Instance::createRuntimeObject(Instance::QtLanguage, (void*)myObject));
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?
- class MyObject : public QObject
- {
- Q_OBJECT
- // 省略 ...
- };
-
- class MyCSDNObject : public QObject
- {
- Q_OBJECT
- // 省略 ...
- };
-
- class QWEBKIT_EXPORT QWebFrame : public QObject
- {
- Q_OBJECT
- Q_PROPERTY(qreal textSizeMultiplier READ textSizeMultiplier WRITE setTextSizeMultiplier)
- Q_PROPERTY(QString title READ title)
- Q_PROPERTY(QUrl url READ url WRITE setUrl)
- Q_PROPERTY(QIcon icon READ icon)
- Q_PROPERTY(QSize contentsSize READ contentsSize)
- private:
- QWebFrame(QWebPage *parent, QWebFrameData *frameData);
- QWebFrame(QWebFrame *parent, QWebFrameData *frameData);
- ~QWebFrame();
-
- // 聲名 CSDN 根對象
- MyCSDNObject *m_csdn;
-
- public:
- // 以下省略 ...
- };
class MyObject : public QObject{ Q_OBJECT // 省略 ...};class MyCSDNObject : public QObject{ Q_OBJECT // 省略 ...};class QWEBKIT_EXPORT QWebFrame : public QObject{ Q_OBJECT Q_PROPERTY(qreal textSizeMultiplier READ textSizeMultiplier WRITE setTextSizeMultiplier) Q_PROPERTY(QString title READ title) Q_PROPERTY(QUrl url READ url WRITE setUrl) Q_PROPERTY(QIcon icon READ icon) Q_PROPERTY(QSize contentsSize READ contentsSize)private: QWebFrame(QWebPage *parent, QWebFrameData *frameData); QWebFrame(QWebFrame *parent, QWebFrameData *frameData); ~QWebFrame(); // 聲名 CSDN 根對象 MyCSDNObject *m_csdn; public: // 以下省略 ...};
開啟 qwebframe.cpp 檔案,在 QWebFrame 的建構函式中建立 CSDN 根對象。
view plaincopy to clipboardprint?
- QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData)
- : QObject(parent)
- , d(new QWebFramePrivate)
- {
- d->page = parent;
- d->init(this, parent->d->page, frameData);
-
- // 在這裡建立 CSDN 根對象
- {
- KJS::Bindings::RootObject *root = d->frame->bindingRootObject();
- KJS::ExecState *exec = root->interpreter()->globalExec();
- KJS::JSObject *global = root->interpreter()->globalObject();
-
- m_csdn = new MyCSDNObject();
- global->put(exec, KJS::Identifier("CSDN"), KJS::Bindings::Instance::createRuntimeObject(KJS::Bindings::Instance::QtLanguage, (void *)m_csdn, root));
- }
-
- if (!frameData->url.isEmpty()) {
- ResourceRequest request(frameData->url, frameData->referrer);
- d->frame->loader()->load(request, frameData->name);
- }
- }
QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData) : QObject(parent) , d(new QWebFramePrivate){ d->page = parent; d->init(this, parent->d->page, frameData); // 在這裡建立 CSDN 根對象 { KJS::Bindings::RootObject *root = d->frame->bindingRootObject(); KJS::ExecState *exec = root->interpreter()->globalExec(); KJS::JSObject *global = root->interpreter()->globalObject(); m_csdn = new MyCSDNObject(); global->put(exec, KJS::Identifier("CSDN"), KJS::Bindings::Instance::createRuntimeObject(KJS::Bindings::Instance::QtLanguage, (void *)m_csdn, root)); } if (!frameData->url.isEmpty()) { ResourceRequest request(frameData->url, frameData->referrer); d->frame->loader()->load(request, frameData->name); }}
在 QWebFrame 的解構函式中刪除 CSDN 根對象
view plaincopy to clipboardprint?
- QWebFrame::~QWebFrame()
- {
- if (d->frame && d->frame->loader() && d->frame->loader()->client())
- static_cast(d->frame->loader()->client())->m_webFrame = 0;
-
- if (m_csdn)
- {
- delete m_csdn;
- m_csdn = NULL;
- }
- delete d;
- }
QWebFrame::~QWebFrame(){ if (d->frame && d->frame->loader() && d->frame->loader()->client()) static_cast(d->frame->loader()->client())->m_webFrame = 0;if (m_csdn){delete m_csdn;m_csdn = NULL;} delete d;}
再手工編寫一個 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 內容。