1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
|
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<!-- qtbrowserplugin.qdoc -->
<head>
<title>Developing Plugins</title>
<link href="classic.css" rel="stylesheet" type="text/css" />
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td align="left" valign="top" width="32"><img src="images/qt-logo.png" align="left" width="57" height="67" border="0" /></td>
<td width="1"> </td><td class="postheader" valign="center"><a href="index.html"><font color="#004faf">Home</font></a></td>
</tr></table><h1 class="title">Developing Plugins<br /><span class="subtitle"></span>
</h1>
<p>The QtBrowserPlugin solution makes it easy to write browser plugins that can be used in Mozilla FireFox, Safari, Opera, Google Chrome, <a href="http://qt.nokia.com/doc/4.6/qtwebkit.html">QtWebKit</a> and any other web browser that supports the "Netscape Plugin API", NPAPI:</p>
<p><a href="http://en.wikipedia.org/wiki/NPAPI">http://en.wikipedia.org/wiki/NPAPI</a></p>
<p><a href="http://developer.mozilla.org/en/Plugins">http://developer.mozilla.org/en/Plugins</a></p>
<p>Microsoft Internet Explorer does not support this API. However, you can use the <a href="http://qt.nokia.com/doc/4.6/activeqt.html">ActiveQt</a> framework to turn your plugin into an ActiveX control, that will work as an IE plugin. Thus, QtBrowserPlugin makes it possible to create a single plugin DLL that will work with all popular browsers on Windows.</p>
<ul><li><a href="#implementing-plugins">Implementing plugins</a></li>
<ul><li><a href="#windows-specific-notes">Windows specific notes</a></li>
<ul><li><a href="#enabling-activex-support">Enabling ActiveX support</a></li>
</ul>
<li><a href="#unix-specific-notes">Unix specific notes</a></li>
<ul><li><a href="#known-issues-on-unix-linux">Known Issues on Unix/Linux</a></li>
</ul>
<li><a href="#mac-osx-specific-notes">Mac OSX specific notes</a></li>
<ul><li><a href="#known-issues-on-mac">Known Issues on Mac</a></li>
</ul>
</ul>
<li><a href="#installing-and-using-plugins">Installing and using Plugins</a></li>
<ul><li><a href="#embedding-the-plugin-on-a-web-page">Embedding the plugin on a web page.</a></li>
<ul><li><a href="#plugins-with-data">Plugins with data:</a></li>
<li><a href="#plugins-without-data">Plugins without data:</a></li>
<li><a href="#tags-not-working-equally-with-all-browsers">Tags not working equally with all browsers</a></li>
</ul>
<li><a href="#browser-full-page-view-of-a-plugin">Browser full-page view of a plugin</a></li>
<li><a href="#scripting">Scripting</a></li>
<ul><li><a href="#javascript-calling-slots-and-properties">JavaScript calling slots and properties</a></li>
<li><a href="#the-plugin-calling-javascript">The plugin calling JavaScript</a></li>
<li><a href="#using-plugins-in-forms">Using plugins in forms</a></li>
</ul>
</ul>
</ul>
<a name="implementing-plugins"></a>
<h2>Implementing plugins</h2>
<p>Since any <a href="http://qt.nokia.com/doc/4.6/qwidget.html">QWidget</a> or <a href="http://qt.nokia.com/doc/4.6/qobject.html">QObject</a> subclass can be turned into a plugin with little effort it is usually easiest to do the development as a stand-alone Qt application - debugging plugins can be cumbersome.</p>
<p>Make sure that the subclass(es) you want to export use the <a href="http://qt.nokia.com/doc/4.6/qobject.html#Q_OBJECT">Q_OBJECT</a> macro and provide a default constructor. Use the Q_CLASSINFO macro to specify a semicolon-delimited list of the MIME types each of your classes supports, and export the classes through the QTNPFACTORY macros:</p>
<pre> QTNPFACTORY_BEGIN("Qt-based Graph Plugin", "A Qt-based NSAPI plug-in that graphs numeric data");
QTNPCLASS(Graph)
QTNPFACTORY_END()</pre>
<p>This should be done only once, in one of the source files. If your plugin needs to export multiple classes (i.e. to handle different sets of MIME types), make one QTNPCLASS line for each of them.</p>
<p>Include the <tt>qtbrowserplugin.pri</tt> in your .pro file, and regenerate the makefile with qmake. The resulting makefile will generate a shared library that the browsers will be able to load as a plugin.</p>
<a name="windows-specific-notes"></a>
<h3>Windows specific notes</h3>
<p>On Windows, the DLL will have <tt>"np"</tt> prepended to its name - this is required by all browsers to recognize the library as a plugin.</p>
<p>On Windows it is required to link a version resource into the plugin library. To do that, create an .rc file (a plain-text file) and add it to the <tt>RC_FILE</tt> variable of your project. The .rc file needs to contain a version description like here:</p>
<pre> 1 VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904e4"
BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "Nokia\0"
VALUE "FileDescription", "grapher\0"
VALUE "FileExtents", "g1n\0"
VALUE "FileOpenName", "Graphable data (*.g1n)\0"
VALUE "FileVersion", "1, 0, 0, 1\0"
VALUE "InternalName", "grapher\0"
VALUE "LegalTrademarks", "\0"
VALUE "MIMEType", "application/x-graphable\0"
VALUE "OriginalFilename", "grapher.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "Nokia grapher QtBrowserPlugin example\0"
VALUE "ProductVersion", "1, 0, 0, 1\0"
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END</pre>
<a name="enabling-activex-support"></a>
<h4>Enabling ActiveX support</h4>
<p>To build a plugin project with ActiveX support, use <a href="http://qt.nokia.com/doc/4.6/activeqt.html">ActiveQt</a>'s <a href="http://qt.nokia.com/doc/4.6/qaxserver.html">QAxServer</a> module by adding the following line to your project:</p>
<p>CONFIG += qaxserver</p>
<p>Also, add the following line to your resource file</p>
<p><tt>1 TYPELIB "thisfile.rc"</tt></p>
<p>In your plugin code, use Q_CLASSINFO and the <a href="http://qt.nokia.com/doc/4.6/qaxfactory.html">QAxFactory</a> macros as usual; refer to the <a href="http://qt.nokia.com/doc/4.6/activeqt.html">ActiveQt</a> documentation.</p>
<p>When you build the plugin, then <a href="http://qt.nokia.com/doc/4.6/activeqt.html">ActiveQt</a> will perform the build steps required to turn the plugin library into an ActiveX control server which provides your plugin classes not only to browsers supporting the npruntime API, but also to browsers supporting ActiveX controls (i.e. Internet Explorer).</p>
<p>However, note that calling <a href="qtnpbindable.html">QtNPBindable</a> APIs will not do anything when the browser does not support the npruntime API. In some cases, <a href="http://qt.nokia.com/doc/4.6/qaxbindable.html">QAxBindable</a> provides equivalent APIs (i.e. for reading incoming data).</p>
<a name="unix-specific-notes"></a>
<h3>Unix specific notes</h3>
<p>On Unix/Linux, QtBrowserPlugin uses the XEmbed protocol. Hence, plugins will only work for browsers that support this protocol. This is true for the recent versions of all the most popular browsers. For Opera, it requires at least version 9.6, <a href="http://qt.nokia.com/doc/4.6/qtwebkit.html">QtWebKit</a> requires at least Qt version 4.5.</p>
<a name="known-issues-on-unix-linux"></a>
<h4>Known Issues on Unix/Linux</h4>
<p>In some rare cases, symbol clash with other instances of the Qt libraries may occur. That is, if the browser itself uses Qt, or other plugins do, and these are loaded into the same address space, your plugin's calls to the Qt API may end up in a different version of the Qt library than what was intended, leading to undefined results.</p>
<p>If you should hit this problem, it is easily worked around by linking your plugin to Qt libraries that are either statically built, or that is built to use a separate namespace (by adding the <tt>-qtnamespace=SomeNamespace</tt> option to Qt's <tt>configure</tt> command).</p>
<a name="mac-osx-specific-notes"></a>
<h3>Mac OSX specific notes</h3>
<p>NOTE: Mac support is experimental only! Expect failure with recent versions of Qt!</p>
<p>To build a browser plugin on Mac, two plain-text resource files are needed: an <tt>Info.plist</tt> file and a <tt>.r</tt> file. To create these files, it is easiest to use the ones provided with the QtBrowserPlugin examples as templates, editing as necessary. Then add them to your project (<tt>.pro</tt> file) like this:</p>
<pre> QMAKE_INFO_PLIST = Info.plist
REZ_FILES += grapher.r
rsrc_files.files = grapher.rsrc
rsrc_files.path = Contents/Resources
QMAKE_BUNDLE_DATA += rsrc_files</pre>
<a name="known-issues-on-mac"></a>
<h4>Known Issues on Mac</h4>
<ul>
<li>After navigating away from the webpage with the plugin, and then back again, the plugin no longer shows up or runs. No workaround currently known.</li>
</ul>
<a name="installing-and-using-plugins"></a>
<h2>Installing and using Plugins</h2>
<p>Most browsers provide a UI to display all loaded plugins, either as a menu choice, and/or by navigating to the url <tt>about:plugins</tt>. Use this functionality to diagnose problems.</p>
<p>The plugin will need to load the Qt libraries at runtime (unless they are statically linked into the plugin). Hence, the required Qt dynamic libraries (at least <a href="http://qt.nokia.com/doc/4.6/qtcore.html">QtCore</a>, <a href="http://qt.nokia.com/doc/4.6/qtgui.html">QtGui</a>, and <a href="http://qt.nokia.com/doc/4.6/qtnetwork.html">QtNetwork</a>) must be located in a directory which the system searches for DLLs. This may or may not include the directory where the plugin itself is located, depending on the OS and browser.</p>
<p>Windows, Netscape-style browsers: To install the plugin, copy the plugin library in the "plugins" directory of the browser. See <tt>src/qtbrowserplugin.pri</tt> for some typical paths. Typically, it is sufficient to install it for one browser, and the others will find it. Ref. <a href="http://developer.mozilla.org/en/Plugins/The_First_Install_Problem">http://developer.mozilla.org/en/Plugins/The_First_Install_Problem</a></p>
<p>Windows, Internet Explorer: The Makefile generated by qmake by default runs the necessary commands to register the plugin as an ActiveX server (if <tt>CONFIG</tt> includes <tt>qaxserver</tt>). To unregister, use the following command:</p>
<pre> c:\Qt-x.y.z\bin\idc.exe path\to\myplugin.dll /unregserver</pre>
<p>Mac: The build will result in a directory called <tt>myplugin.plugin</tt>. To install, copy this directory with all contents to <tt>/Library/Internet Plugins</tt>.</p>
<p>Unix: Copy the file <tt>myplugin.so</tt> to the browser or system plugin directory, typically <tt>/usr/lib/browser-plugins</tt>. The path to the Qt libraries may be set in the LD_LIBRARY_PATH environment variable of the browser process.</p>
<a name="embedding-the-plugin-on-a-web-page"></a>
<h3>Embedding the plugin on a web page.</h3>
<p>Browsers vary slightly in their support for different plugin-embedding HTML tags. The following should work for most popular browsers.</p>
<a name="plugins-with-data"></a>
<h4>Plugins with data:</h4>
<p>Plugins can be initialized with a data file, which will be delivered at some point after plugin creation to the plugin through the <a href="qtnpbindable.html#readData">QtNPBindable::readData</a>() virtual function. (This applies to <a href="http://qt.nokia.com/doc/4.6/activeqt.html">ActiveQt</a>-based plugins in IE as well).</p>
<p>Assuming the MIME type is <tt>application/x-graphable</tt>, with the extension <tt>g1n</tt>:</p>
<pre> <object type="application/x-graphable" data="graph.g1n" width=50% height=300>
Plugin not installed!
</object></pre>
<p>or</p>
<pre> <object data="http:<span class="comment">//qt.nokia.com/doc/3.3/graph.g1n" width=50% height=300></span>
Plugin not installed!
</object></pre>
<p>Note that some browsers will not display or immediately unload the plugin if the data file does not exist, while other browsers will display the plugin without ever calling readData().</p>
<p>If the plugin has declared a Q_PROPERTY called <tt>src</tt>, the setter function for this property will be called at instantiation time with the data URL as parameter.</p>
<a name="plugins-without-data"></a>
<h4>Plugins without data:</h4>
<p>Assuming the (dummy) MIME type is <tt>trivial/very</tt>:</p>
<pre> <embed type="trivial/very" [property]=[value]></pre>
<a name="tags-not-working-equally-with-all-browsers"></a>
<h4>Tags not working equally with all browsers</h4>
<ul>
<li><tt><object classid=...></tt> Only IE supports this.</li>
<li><tt><embed src=...></tt> IE will not call readData(), but the <tt>src</tt> property will be set, so manual data loading is possible.</li>
<li><tt><object type=... data=...><param ...></tt> Ditto.</li>
<li><tt><object type=...></tt> Some browsers do not display plugins without <tt>data</tt> attribute</li>
</ul>
<p>For additional information, see <a href="http://developer.mozilla.org/en/Gecko_Plugin_API_Reference/Plug-in_Basics#Using_HTML_to_Display_Plug-ins">http://developer.mozilla.org/en/Gecko_Plugin_API_Reference/Plug-in_Basics#Using_HTML_to_Display_Plug-ins</a></p>
<a name="browser-full-page-view-of-a-plugin"></a>
<h3>Browser full-page view of a plugin</h3>
<p>If files viewed by a plugin are provided by an HTTP server (using a <tt>http:<span class="comment">//...</span></tt> URL) then the server must be configured to send the correct MIME type for the file, e.g. by editing Apache's <tt>mime.types</tt> file. (Not required for IE).</p>
<p>If the files are viewed via a <tt>file:<span class="comment">//...</span></tt> URL (e.g. by the user opening the data file with <tt>File->Open</tt>), then the browser will use the filename extension to decide the file type (and hence the plugin to load).</p>
<p>In the full-page case, IE will not call readData(), but the <tt>src</tt> property will be set, so manual data loading is possible. See the <tt>grapher</tt> example.</p>
<a name="scripting"></a>
<h3>Scripting</h3>
<p>Plugins embedded into browsers that support the respecive NPAPI extensions as well as ActiveX controls can be accessed from JavaScript in the HTML page.</p>
<pre> <object id="ScriptableObject" TYPE=trivial/very WIDTH=200 HEIGHT=100 text="Very Scriptable!"> </object>
<script language=JavaScript></pre>
<p>Before the object can be accessed, some browsers require it to be located based on the <tt>id</tt> in the <tt>object</tt> tag.</p>
<a name="javascript-calling-slots-and-properties"></a>
<h4>JavaScript calling slots and properties</h4>
<pre> var ScriptableObject = document.getElementById('ScriptableObject');</pre>
<p>Object properties and public slots can then be accessed as usual. The QtBrowserPlugin implementation supports properties and slots that have parameters and types that <a href="http://qt.nokia.com/doc/4.6/qvariant.html">QVariant</a> can be convert to and from strings, or that are QObjects. Only public slots and scriptable properties are exposed. If the <a href="http://qt.nokia.com/doc/4.6/qobject.html">QObject</a> class sets a "ToSuperClass" Q_CLASSINFO, then only slots and properties up to the specified superclass are exposed. See the <a href="http://qt.nokia.com/doc/4.6/qaxserver.html">QAxServer</a> documentation provided with Qt for more information.</p>
<a name="the-plugin-calling-javascript"></a>
<h4>The plugin calling JavaScript</h4>
<p>JavaScript functions can be connected to Qt signals emitted by the Qt plugin object.</p>
<pre> ScriptableObject.text = 'This is some text'
var oldText
ScriptableObject.mouseDown = function()
{
oldText = ScriptableObject.text
ScriptableObject.text = 'Mouse Down'
}
ScriptableObject.mouseMove = function(x, y)
{
ScriptableObject.text = 'Mouse at ' + x + ',' + y
}
ScriptableObject.mouseUp = function()
{
ScriptableObject.text = oldText
}
</script></pre>
<p>Assign a function to a property of the object with the same name as the signal. Overloads (i.e. two signal with the same name, but different parameters) are not possible.</p>
<pre> <!-- Special hookup code required for Internet Explorer -->
<!--[if IE]>
<script language=JScript>
function ScriptableObject::mouseDown() { ScriptableObject.mouseDown() }
function ScriptableObject::mouseMove(x, y) { ScriptableObject.mouseMove(x, y) }
function ScriptableObject::mouseUp() { ScriptableObject.mouseUp() }
</script></pre>
<p>Internet Explorer requires a special syntax that is not compatible with other browsers, but the IE-specific function can just call the other functions.</p>
<a name="using-plugins-in-forms"></a>
<h4>Using plugins in forms</h4>
<p>Plugin objects can be embedded as form elements. To specify which property value the plugin should report to the form upon submission, specify the name of the property as the DefaultProperty using a Q_CLASSINFO entry:</p>
<pre> Q_OBJECT
Q_CLASSINFO("MIME", "trivial/very:xxx:Trivial and useless")
Q_CLASSINFO("DefaultProperty", "text")</pre>
<p>In the HTML page, embed the object as usual:</p>
<pre> <form method="get" action="http:<span class="comment">//www.server.com/search.asp"></span>
<table>
<tr>
<td>Search:</td>
<td><object type="trivial/very" name="text" WIDTH=100 HEIGHT=20></object></td>
<td><input type="submit" value="Check"></td>
</tr>
</table>
</form></pre>
<p>Clicking the button will make the browser request a URL</p>
<p><tt>http:<span class="comment">//www.server.com/search.asp?text=[value from object]</span></tt></p>
<p>The property type needs to be convertible to a string.</p>
<p /><address><hr /><div align="center">
<table width="100%" cellspacing="0" border="0"><tr class="address">
<td width="30%" align="left">Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)</td>
<td width="40%" align="center"><a href="http://qt.nokia.com/doc/trademarks.html">Trademarks</a></td>
<td width="30%" align="right"><div align="right">Qt Solutions</div></td>
</tr></table></div></address></body>
</html>
|