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
|
<html>
<head>
<style type="text/css">
<!--
h1 {
background-color: #ccccee;
text-align: center;
}
h3 {
background-color: #ccccee;
}
li {
padding: 4px;
}
pre {
background-color: #CCCCCC;
margin-right: 16px;
margin-left: 16px;
padding: 6px;
}
.imgcaption {
font-weight: bold;
text-align: center;
}
.precaption {
font-weight: bold;
text-align: center;
}
-->
</style>
</head>
<body>
<h1> KJSEmbed</h1>
<h3>Introduction</h3>
<p>KJSEmbed is a library for embedding the KJS Javascript (ECMAScript) interpreter
in KDE applications. It provides developers with an easy way to allow users
to extend application, and can even be used with applications that have not
been designed with this in mind thanks to a KParts plugin. In addition, KJSEmbed
provides a command line tool for running scripts so users can easily create
simple applications of their own in Javascript. KJSEmbed scripts are surprisingly
powerful because they access the properties and slots of QObjects, and can even
load widgets and dialogs created with Qt's graphical dialog editor.</p>
<h3>Features</h3>
<p>To give you an idea of what KJSEmbed provides, here is a brief summary of the
more interesting features:</p>
<ul>
<li>KParts plugin for extending existing KDE applications with scripts. </li>
<li>KPart for embedding Javascript in your own applications.</li>
<li>Console dialog that can be used to execute Javascript interactively.</li>
<li>Command line tool for running scripts (this can even operate without an
X server if you don't need to display a GUI).</li>
<li>Define new KActions using XML.</li>
<li>Scripts can access the properties and slots of QObjects as if they were
normal Javascript properties and methods.</li>
<li>Scripts can load dialogs and widgets created with Qt Designer.</li>
<li>Scripts can create instances of anu QWidget subclass supported by QWidgetFactory.</li>
<li>Making your own QObjects/QWidgets available for scripting is one-liner.</li>
<li>Scripts can traverse the widget tree, so your entire application can be
made scriptable without explicitly binding every object.</li>
</ul>
<h3>First Steps - The Console Dialog</h3>
<p>The quickest way to see what KJSEmbed can do is with kjscmd, a tool for running
scripts from the command line. To begin, we'll run kjscmd without any parameters
which brings up the KJSEmbed console dialog. The console provides an easy way
to run short (one line) scripts, as you can see in figure 1 the scripts have
full access to the core Javascript language, and to standard objects such as
Math. In addition to the standard Javascript operations, this screenshot also
demonstrates the global function print() provided by KJSEmbed.</p>
<pre>
-- Enter a JS expression and press enter --
kjs> 10+20
30
kjs> print(&quot;Hello World!&quot;)
Hello World!
undefined
kjs> Math.sin(0)
0
kjs> Math.cos(0)
1
</pre>
<p class="imgcaption">Figure 1: The KJSEmbed Console Dialog</p>
<p>Things get more interesting when you realise that we also have access to the
widgets that make up the dialog, as you can in figure 2:</p>
<pre>
kjs> console
JSConsoleWidget (KJSEmbed::JSConsoleWidget)
kjs> console.childCount()
4
kjs> console.childAt(1)
CmdEdit (QComboBox)
kjs> console.childAt(2)
RunButton (QPushButton)
kjs> console.child(&quot;RunButton&quot;)
RunButton (QPushButton)
kjs> console.child(&quot;RunButton&quot;).text = &quot;Go!&quot;
Go!
kjs> console.caption = &quot;Different Title&quot;
Different Title
kjs&gt; console.child(&quot;Title&quot;).hide()
undefined
</pre>
<p class="imgcaption">Figure 2: Modifying the Console Dialog</p>
<p>As you can see, the console dialog has been made available to scripts as the
global variable 'console'. We can access the child widgets that make up the
dialog either by index using the childCount() and childAt() methods, or by name
using the child() method. As well as being able to see the widgets, we can modify
them by setting properties - in this example, we modify the caption property
of the widget 'console' (changing the window title) and the text property of
the widget 'RunButton' (changing the label it displays). For the sake of completeness,
the final command illustrates the other way of modifying widgets available to
us - it calls hide() slot of the widget 'Title' (what this does is left as an
exercise for the reader).</p>
<h3>Displaying A Grep Dialog</h3>
<p>Now that we've seen how to use kjscmd interactively, lets take a look at a
more complex example that displays a dialog for running grep. The complete script
is shown in listing 1 and as you'll see, is very simple. Loading and displaying
the dialog takes only two lines of code because KJSEmbed provides a built-in
Factory object that supports Designer files, most of the work is getting the
values out of the dialog and building the command line.</p>
<pre>
// Create and show the dialog
var dlg = Factory.loadui('grepdlg.ui');
dlg.exec();
// Extract the parameters
var search = dlg.child('search_edit').text;
var files = dlg.child('files_edit').text;
var matchcase = dlg.child('case_check').checked;
var invert = dlg.child('invert_check').checked;
// Build the command line
var options;
if ( matchcase ) {
options = '-i';
}
if ( invert ) {
options += ' -v';
}
cmd = 'grep '+options+&quot;'&quot;+search+&quot;' &quot;+files;
// Print the command line
print( cmd );
</pre>
<p class="precaption">Listing 1: A Script That Displays the Grep Dialog</p>
<p>In order to find out what the user asked us to search for we need to extract
the contents of the various fields in our dialog. We know that the field for
entering the text to be searched for is a QLineEdit called 'search_edit', so
we can use the child() method to get hold of it (this method searches through
the children of an object until it finds one with a matching name). Once we've
found the right object getting hold of the text is easy because all QLineEdits
make their contents available as a property called 'text'. The code that gets
the value of the check boxes is almost identical, except that these are QCheckBoxes
so it's the 'checked' property we're interested in.</p>
<p align="center"><img src="grepdlg.png" alt="Grep Dialog Screenshot" width="327" height="241"></p>
<p class="imgcaption">Figure 3: The Grep Dialog</p>
<p>When this script is run you'll see a dialog like the one shown in figure 3.</p>
<h3>Extending Applications with Javascript Plugins</h3>
<p>As its name implies KJSEmbed is not just a tool for writing standalone Javascript
tools, it also provides facilities for extending existing applications, these
facilities being with a KParts plugin for running scripts. The next example
uses the plugin to add a simple HTML-to-text action to Kate, the standard KDE
editor. </p>
<pre>
function html2text( html )
{
var text = html.replace( /&lt;[^&gt;]*&gt;/g, '' );
text = text.replace( /&amp;quot;/g, '&quot;' );
text = text.replace( /&amp;lt;/g, '&lt;' );
text = text.replace( /&amp;amp;/g, '&amp;' );
return text;
}
function text2html( text )
{
var html = text.replace( /&amp;/g,&quot;&amp;amp;&quot;);
html = html.replace( /&quot;/g,&quot;&amp;quot;&quot;);
html = html.replace( /&lt;/g,&quot;&amp;lt;&quot;);
return html;
}
</pre>
<p>The details...</p>
<pre>&lt;!DOCTYPE actionset&gt;<br>&lt;actionset&gt;<br>&lt;header&gt;<br> &lt;name&gt;html2text_actions&lt;/name&gt;<br> &lt;label&gt;HTML To Text Actions&lt;/label&gt;<br> &lt;script type=&quot;js&quot; src=&quot;html2text_plugin.js&quot;&gt;&lt;/script&gt;<br>&lt;/header&gt;<br>&lt;action&gt;<br> &lt;name&gt;html_to_text&lt;/name&gt;<br> &lt;type&gt;KAction&lt;/type&gt;<br> &lt;icons&gt;text&lt;/icons&gt;<br> &lt;label&gt;&lt;text&gt;Convert HTML To Text&lt;/text&gt;&lt;/label&gt;<br> &lt;statustext&gt;Converts the selected text from HTML to text.&lt;/statustext&gt;<br> &lt;script type=&quot;js&quot;&gt;kpart.selectedText = html2text( kpart.selectedText )&lt;/script&gt;<br>&lt;/action&gt;<br>&lt;action&gt;<br> &lt;name&gt;text_to_html&lt;/name&gt;<br> &lt;type&gt;KAction&lt;/type&gt;<br> &lt;icons&gt;html&lt;/icons&gt;<br> &lt;label&gt;&lt;text&gt;Quote For HTML&lt;/text&gt;&lt;/label&gt;<br> &lt;statustext&gt;Quotes the selected text for inclusion in an HTML document.&lt;/statustext&gt;<br> &lt;script type=&quot;js&quot;&gt;kpart.selectedText = text2html( kpart.selectedText )&lt;/script&gt;<br>&lt;/action&gt;<br>&lt;/actionset&gt;<br></pre>
<p><br>
The xmlgui:</p>
<pre>
&lt;!DOCTYPE kpartgui&gt;<br>&lt;kpartplugin name=&quot;html2text_plugin&quot; library=&quot;libkjsembedplugin&quot;&gt;<br>&lt;MenuBar&gt;<br> &lt;Menu name=&quot;tools&quot;&gt;&lt;Text&gt;&amp;amp;Tools&lt;/Text&gt;<br> &lt;Action name=&quot;html_to_text&quot;/&gt;<br> &lt;Action name=&quot;text_to_html&quot;/&gt;<br> &lt;Action name=&quot;jsconsole&quot;/&gt;<br> &lt;/Menu&gt;<br>&lt;/MenuBar&gt;<br>&lt;/kpartplugin&gt;<br> </pre>
<h3>Missing</h3>
<ul>
<li>XMLActions</li>
<li>Plugin</li>
<li>MainWindow</li>
</ul>
<h3>References</h3>
<dl>
<dt><a href="http://www.mozilla.org/js/language/">http://www.mozilla.org/js/language/</a></dt>
<dd>Javascript (ECMAScript) language information.</dd>
</dl>
<h3>To Do</h3>
<ul>
<li>Replace figures 1 and 2 with images</li>
<li></li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
</body>
</html>
|