~ubuntu-branches/debian/sid/kdevelop/sid

« back to all changes in this revision

Viewing changes to doc/addendum/index.docbook

  • Committer: Bazaar Package Importer
  • Author(s): Fathi Boudra
  • Date: 2010-07-23 20:08:00 UTC
  • mfrom: (5.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100723200800-fh72fo2fhlxb16ud
Tags: 4:4.0.1-1
* New upstream release.
* Add localization packages: Finnish (fi), Dutch (nl), Slovenian (sl) and
  Thai (th).
* Update debian/control:
  - bump Standards-Version to 3.9.0 (no changes needed).
  - bump kdevplatform-dev and kdebase-workspace-dev build dependency version.
  - add shared-mime-info build dependency.
  - comment turkish localization package, not shipped in this release.
* Update debian/rules: remove workaround for FindKDE4Internal.cmake default
  rpath value, fixed in kdelibs5-dev 4.4.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook V3.1-Based Variant V1.0//EN" [
 
2
 <!ENTITY kdevelop "<application>kdevelop</application>">
 
3
 <!ENTITY % addindex "IGNORE">
 
4
 <![ %addindex; [ <!ENTITY docindex SYSTEM "docindex.docbook"> ]]>
 
5
]>
 
6
 
 
7
<book lang="en">
 
8
<bookinfo>
 
9
<title>The KDE 2 Developer's Guide</title>
 
10
<subtitle>The KDE 2 information guide to development, I/O slaves and KOM/OpenParts</subtitle>
 
11
<authorgroup>
 
12
<author>
 
13
<firstname>Ralf</firstname>
 
14
<surname>Nolden</surname>
 
15
</author>
 
16
<author>
 
17
<firstname>Kurt</firstname>
 
18
<surname>Granroth</surname>
 
19
</author>
 
20
<author>
 
21
<firstname>Simon</firstname>
 
22
<surname>Hausmann</surname>
 
23
</author>
 
24
<author>
 
25
<firstname>David</firstname>
 
26
<surname>Sweet</surname>
 
27
</author>
 
28
<author>
 
29
<firstname>Preston</firstname>
 
30
<surname>Brown</surname>
 
31
</author>
 
32
<author>
 
33
<firstname>Torben</firstname>
 
34
<surname>Weis</surname>
 
35
</author>
 
36
<author>
 
37
<firstname>Bern</firstname>
 
38
<surname>Wuebben</surname>
 
39
</author>
 
40
</authorgroup>
 
41
<date>21/03/2000</date>
 
42
<releaseinfo>1.02.00</releaseinfo>
 
43
<abstract>
 
44
<para>This Handbook is a collection of various documentation about KDE 2 development. Each chapter remains the copyright of the original
 
45
author mentioned at the beginnig of the chapters and in section <link linkend="Copyright">Copyright</link>.</para>
 
46
</abstract>
 
47
<keywordset>
 
48
<keyword>KDE</keyword>
 
49
<keyword>KDevelop</keyword>
 
50
<keyword>I/O slaves</keyword>
 
51
<keyword>KOM</keyword>
 
52
<keyword>OpenParts</keyword>
 
53
</keywordset>
 
54
</bookinfo>
 
55
 
 
56
<chapter id="preface">
 
57
<title>Preface</title>
 
58
 
 
59
<para>This handbook has been assembled to provide KDE developers the information they will need when porting their applications to KDE 2,
 
60
currently under development. KDE 2 is based on the Qt 2.x and KDE 1.1.x libraries, whereby the KDE libraries are ported to work with
 
61
the current Qt library. Further, the KDE libraries will introduce a component technology based on the MICO CORBA implementation which
 
62
is developed and tested with the KOffice suite.</para>
 
63
 
 
64
<para>As KDE application developers not involved in implementing for the KDE core team will probably want to port their applications, they
 
65
will not only have to watch out for the changes in Qt, but also for KDE's improvements and additions. As KDE 1.x applications will not
 
66
only be binary incompatible but also sourcecode incompatible, we want to provide enough information that can be used by developers that
 
67
are using the currently stable KDE 1.x implementation for applications that are suitable for production use, so transitioning will be
 
68
made less complicated and further implementations in current projects can be reviewed for possible problems that will arise when
 
69
porting.</para>
 
70
 
 
71
<para>Also the usual KDE developer does not have too much information about CORBA, not to speak of KOM. Therefore, this handbook tries to
 
72
give an insight where to get information and how the current implementation works in general. This will enable you to find out where
 
73
your applications can probably take advantage of distributed component technology where needed. In conjunction with the latest
 
74
development, this version of the KDE 2 Developer's Guide also contains a short HOWTO for the new DCOP (Desktop COmmunications
 
75
Protocol), which was created due to performance problems of local desktop applications using CORBA. Therefore, a few things mentioned
 
76
and explained in the documents relying on CORBA technology can be out of date and reading yourself into the dcop library reference and
 
77
reviewing current KDE CVS sourcecode will give you probably more up-to-date information on IPC (Inter-Process-Communication) between
 
78
local desktop applications using DCOP.</para>
 
79
 
 
80
<para>I want to thank all authors that were willing to contribute their current documentation to this handbook and hope this collection will
 
81
be of good use to those who want to stay on the bleeding edge of KDE development.</para>
 
82
 
 
83
<para>Ralf Nolden</para>
 
84
</chapter>
 
85
 
 
86
<chapter id="mini-howto">
 
87
<title>The KDE Developer's mini-HOWTO</title>
 
88
 
 
89
<para>David Sweet &&lt;;dsweet@chaos.umd.edu&&gt;;</para>
 
90
 
 
91
<para>March, 11, 2000</para>
 
92
 
 
93
<para><emphasis>To help develop KDE or a KDE application you need to know
 
94
how to (i) find KDE information and code, (ii) use CVS, and (iii)
 
95
compile. This document aims to help to you do these things without
 
96
losing too much hair. This HOWTO is geared toward new developers, occasional
 
97
developers, and anyone considering contributing the the most excellent
 
98
free software project that is KDE.  It addresses questions that I and
 
99
others have been asking on the <emphasis remap="bf">kde-devel</emphasis> mailing list recently
 
100
along with some more general information.
 
101
You can find a current version of this document at the
 
102
<ulink url="http://www-chaos.umd.edu/~dsweet/KDE/DeveloperHOWTO">KDE Developer's HOWTO homepage</ulink>.
 
103
To contribute, comment, or correct, please email me at
 
104
<ulink url="mailto:dsweet@chaos.umd.edu">dsweet@chaos.umd.edu</ulink></emphasis></para>
 
105
 
 
106
<sect1 id="information-and-source-code">
 
107
<title>Information and Source Code</title>
 
108
 
 
109
<sect2 id="general-information">
 
110
<title>General Information</title>
 
111
 
 
112
<para>The K Desktop Environment is an open source Unix desktop created by volunteers from around the world.  There are many ways to
 
113
contribute to the project.  You can write new code, improve old code, write documentation, translate to other languages, create
 
114
artwork, sounds, & music, report bugs, and suggest new features.  If you would like to develop code, read on.  If you would like to
 
115
contribute in another way, please visit the KDE web site (<ulink url="http://www.kde.org">\|\|</ulink> name="http://www.kde.org"&gt;) for more information.</para>
 
116
 
 
117
<para>KDE uses the Qt toolkit which is developed by Troll Tech (<ulink url="http://www.troll.no">http://www.troll.no</ulink>). The main
 
118
components of the desktop are a file manager (kfm), window manager (kwm), and panel (kpanel).  There are many more utilities and
 
119
applications which are included in the base distribution and available elsewhere. The primary programming language used for development
 
120
is C++, although bindings are available for Python (pyKDE).  The KDE code consists of libraries containing classes for, for example:
 
121
(libkdecore) an application base (KApplication), accessing configuration files (KConfig), launching external processs (KProcess);
 
122
(libkdeui) widgets (KEdit, KFontDialog, KToolBar, etc.); and other utility classes like KFileDialog (a file dialog) and KSpell (a
 
123
spellchecker).</para>
 
124
 
 
125
<para>Various desktop, configuration, and system administration utilities are also included in the distribution.  These are
 
126
some of the things KDE developers work on.  A more recent creation is KOffice, a productivity suite which includes a word processor,
 
127
spreadsheet, and presentation tool The currently released version of KDE is 1.1.2.</para>
 
128
 
 
129
<para>KDE 2.0, which is, perhaps, the main focus of development right now, will include rewrites or major updates of kfm, khtmlw (an HTML
 
130
widget), kpanel, kmail, and maybe kwm, unicode support, Inter-Process-Communication protocols and much more.</para>
 
131
</sect2>
 
132
 
 
133
<sect2 id="urls">
 
134
<title>URLs</title>
 
135
 
 
136
<para><itemizedlist><listitem>
 
137
<para>The main KDE web site is at:  <ulink url="http://www.kde.org">http://www.kde.org</ulink>.</para>
 
138
</listitem>
 
139
<listitem>
 
140
<para>The developer's library is at:   <ulink url="http://developer.kde.org">http://developer.kde.org</ulink>.</para>
 
141
</listitem>
 
142
<listitem>
 
143
<para> Bug reports can be found at (and sent to):  <ulink url="http://bugs.kde.org">http://bugs.kde.org</ulink>.</para>
 
144
</listitem>
 
145
<listitem>
 
146
<para> Troll Tech (makers of the Qt toolkit) main site:   <ulink url="http://www.troll.no">http://www.troll.no</ulink>.</para>
 
147
</listitem>
 
148
<listitem>
 
149
<para> KDE Source Code and binaries:   <ulink url="ftp://ftp.kde.org">ftp://ftp.kde.org</ulink>  (or mirrors)</para>
 
150
</listitem>
 
151
<listitem>
 
152
<para> Qt Source Code and binaries:  <ulink url="ftp://ftp.troll.no">ftp://ftp.troll.no</ulink></para>
 
153
</listitem>
 
154
</itemizedlist></para>
 
155
</sect2>
 
156
 
 
157
<sect2 id="mailing-lists">
 
158
<title>Mailing lists</title>
 
159
 
 
160
<para>The list <emphasis remap="bf">kde-devel</emphasis> is for KDE developers in general.  The <emphasis remap="bf">kde-koffice</emphasis> mailing list is for developers interested in koffice,
 
161
and <emphasis remap="bf">kfm-devel</emphasis> is for kfm (the file manager) developers.</para>
 
162
 
 
163
<para>Send a message to either <emphasis remap="bf">kde-devel-request</emphasis> or <emphasis remap="bf">koffice-request</emphasis> with the message "subscribe myid@myserver" (where myid@myserver
 
164
stands for your email address).  Go to the KDE mail page a click on "Mailing Lists" for more information about other KDE mailing lists
 
165
and the mailing list archive.</para>
 
166
 
 
167
<para>Toll Tech provides a list for users of the Qt 2.1 snapshots (discussed below).  You may subscribe to this by sending an email to
 
168
snapshot-users-request@troll.no with the <emphasis>message</emphasis> "subscribe".</para>
 
169
 
 
170
<para>As a KDE developer you may want or need a kde email address, like joedeveloper@kde.org.  To obtain one, send an email with a polite
 
171
request to Martin Konold at konold@kde.org.</para>
 
172
 
 
173
<para>To gain access to the KDE CVS respository (discussed below), you firsly need to have a good reason for wanting access.  For example,
 
174
you may be maintaining a CVS module.  If you think you have a good reason, send a polite email request to Stephan Kulow
 
175
&&lt;;coolo@kde.org&&gt;;.</para>
 
176
 
 
177
<para>You'll also need to send him an encrypted password to get the account set up. To create your encrpyted password, type:
 
178
<screen>        perl -e print\ crypt\('passwd','sa'\)\.\"\\n\"
 
179
</screen>
 
180
 
 
181
where <literal remap="tt">passwd</literal> is your choice of password and <literal remap="tt">sa</literal> is two random
 
182
characters from the set (a-zA-Z0-9./). The output is your encrypted
 
183
password.</para>
 
184
</sect2>
 
185
</sect1>
 
186
 
 
187
<sect1 id="kde-cvs">
 
188
<title>KDE CVS</title>
 
189
 
 
190
<sect2 id="introduction">
 
191
<title>Introduction</title>
 
192
 
 
193
<para>The KDE CVS (Concurrent Versions System) is the source code repository for the KDE project.  You can access it via (i) WWW:
 
194
http://www., (ii) cvs utility, (iii) cvsup utility, or (iv) snapshots. You will need CVS access only for (ii); (i), (iii), and (iv) are
 
195
read-only methods and available to the public.</para>
 
196
 
 
197
<para>The web page for method (i) explains its usage.  I haven't an explanation for method (iii), cvsup, yet.  Please see
 
198
http://www.kde.org/cvsup.html  &&lcub;; -- Perhaps someone who uses it will contribute a short explanation of usage and information
 
199
on obtaining it. -- &&rcub;;</para>
 
200
 
 
201
<para>The snapshots, (iv), are .tar.bz2 files which contain a section of KDE code (called "modules"; ex, kdelibs, kdeutils) as it looked on
 
202
some specified day (specified in the filename: ex, kdelibs990517.tar.bz2). The snapshots are posted daily
 
203
in ftp://ftp.kde.org/pub/kde/unstable/CVS/snapshots. &&lcub;; (ii) is described below. &&rcub;;</para>
 
204
 
 
205
<para>The repository (or, just "CVS") stores all of the changes made to the source code by all of the contributors so that changes may be
 
206
undone.  Each time a user makes a change (s)he includes a comment so that the devlopment of code can be more easily followed.  These
 
207
comments are sent to the kde-cvs mailing list.  The CVS splits into &&lowbar;;branches&&lowbar;; which may contain different versions of the KDE project.
 
208
For example, the two branches being developed now are KDE&&lowbar;;1&&lowbar;;1&&lowbar;;BRANCH and HEAD.  They both are derived from the same code (i.e., if you
 
209
"undid" enough of the changes made to either branch you'd reveal identical source code) but used for different purposes.  Here are some
 
210
branches and descriptions for your reference:</para>
 
211
 
 
212
<para><itemizedlist>
 
213
<listitem>
 
214
<para> KDE&&lowbar;;1&&lowbar;;1&&lowbar;;2&&lowbar;;RELEASE - code that was considered stable, released,
 
215
and distributed as KDE 1.1.2
 
216
</para>
 
217
</listitem>
 
218
<listitem>
 
219
<para> HEAD - code which will become KDE 2.0.  It is based on Qt 2.1, has a new kwm, kpanel, etc.  LOTS of changes.</para>
 
220
</listitem>
 
221
</itemizedlist>
 
222
</para>
 
223
</sect2>
 
224
 
 
225
<sect2 id="using-cvs">
 
226
<title>Using <literal remap="tt">cvs</literal></title>
 
227
 
 
228
<para>The cvs utility is probably on your system.  If not, you should visit <ulink url="http://www.cyclic.com/cyclic-pages/howget.html">http://www.cyclic.com/cyclic-pages/howget.html</ulink> To learn to use it I would recommend reading the man page!  But, I've included
 
229
explanations of some common functions below.</para>
 
230
 
 
231
<para>Let's assume for this section that your username is <literal remap="tt">joedeveloper</literal>. As written below you should enter all of these commands from
 
232
some base directory.  (KDE/CVS is not a bad choice!)</para>
 
233
 
 
234
<para>Set the environment variable <literal remap="tt">CVSROOT</literal> to</para>
 
235
 
 
236
<para><literal remap="tt">:pserver:joedeveloper@cvs.kde.org:/home/kde.</literal></para>
 
237
 
 
238
<para><emphasis remap="bf">Listing CVS modules</emphasis> You can't do this directly unfortunately.  You can, however, view the contents of the file /home/kde/modules
 
239
with
 
240
<screen>cvs -z6 co -c
 
241
</screen>
 
242
</para>
 
243
 
 
244
<para>The <literal remap="tt">-z6</literal> option tells the server to compress the code at "level 6" before sending it to you.  This may speed things up for you.
 
245
(In this case, since the module listing is small, it may not matter.)</para>
 
246
 
 
247
<para><emphasis remap="bf">Checking out a module</emphasis>, e.g. kdelibs from HEAD
 
248
<screen>cvs -z6 checkout -r HEAD kdelibs
 
249
cvs -z6 checkout kdelibs
 
250
</screen>
 
251
</para>
 
252
 
 
253
<para>The -r options tells cvs which branch you want to checkout from.  The
 
254
default is the HEAD branch.</para>
 
255
 
 
256
<para><emphasis remap="bf">Checking out a module</emphasis>, ex. kdelibs, from KDE&&lowbar;;1&&lowbar;;1&&lowbar;;2&&lowbar;;RELEASE
 
257
<screen>cvs -z6 checkout -r KDE_1_1_2_RELEASE kdelibs
 
258
</screen>
 
259
</para>
 
260
 
 
261
<para><emphasis>Note</emphasis>: you could use co as an abbreviation for checkout.</para>
 
262
 
 
263
<para><emphasis remap="bf">Checking out an application from within a module</emphasis> (ex kjots, which
 
264
is in the kdeutils module) from the HEAD branch
 
265
<screen>(1)     cvs -z6 co -l kdeutils
 
266
(2)     cvs -z6 co -l admin
 
267
(3)     cvs -z6 co -l kdeutils/kjots
 
268
(4)     cd kdeutils; ln -s ../admin
 
269
</screen>
 
270
</para>
 
271
 
 
272
<para>The <literal remap="tt">-l</literal> in line (1) tells cvs not to recurse the subdirectories of kdeutils.  This means will get the configure script and its
 
273
companions (discussed below), but none of the application source code.</para>
 
274
 
 
275
<para>Line (2) gets the admin directory which contains support files for autoconf and friends.  (This directory is retrieved automatically
 
276
when checking out an entire module.)</para>
 
277
 
 
278
<para>Line (3) gets the kjots source.</para>
 
279
 
 
280
<para>Line (4) makes a link to the admin directory.  (This is better than copying or moving the directory here.  If you leave admin where cvs
 
281
put if then you can easily update the admin directory with cvs.  You could also make links to admin from any other modules you check
 
282
out this way and thus have only one, up-to-date copy of admin.)</para>
 
283
 
 
284
<para><emphasis remap="bf">Updating source code you've previously checked out</emphasis> (ex. kdeutils/kjots)
 
285
<screen>        cvs -z6 update -P -d kdeutils/kjots
 
286
</screen>
 
287
</para>
 
288
 
 
289
<para>The source code for kjots on your hard drive will be updated to match the code in the CVS.  You don't need to specify the branch here.
 
290
The correct branch is stored in <literal remap="tt">kdeutils/kjots/CVS/Tag</literal>.</para>
 
291
 
 
292
<para><emphasis remap="bf">Commiting changes</emphasis> (putting them into CVS) (ex. kdeutils/kjots)
 
293
<screen>cvs -z6 commit kdeutils/jots
 
294
</screen>
 
295
</para>
 
296
 
 
297
<para>You'll be prompted to edit a comment.  Enter a short one which desribes the changes you're making with this commmit.  (You can use
 
298
your editor of choice by setting the EDITOR or CVSEDITOR environment variable.)</para>
 
299
 
 
300
<para><emphasis remap="bf">Adding a file</emphasis> (ex. kdeutils/kmyapp/greatnewcode.cpp)
 
301
<screen>(create the file first!)
 
302
cd kdeutils/kmyapp
 
303
cvs add greatnewcode.cpp
 
304
cvs commit
 
305
</screen>
 
306
</para>
 
307
 
 
308
<para><emphasis remap="bf">Deleting a file</emphasis> (ex. kdeutils/kmyapp/badoldcode.cpp)
 
309
<screen>cd kdeutils/kmyapp
 
310
rm badoldcode.cpp
 
311
cvs remove badoldcode.cpp
 
312
cvs commit
 
313
</screen>
 
314
</para>
 
315
 
 
316
<para><emphasis remap="bf">Adding a directory</emphasis> (a module, like a new app) (ex. kdeutils/kmyapp, with the source file kmysource.cpp)
 
317
<screen>cd kdeutils
 
318
mkdir kmyapp
 
319
(create the kmyapp/kmysource.cpp file)
 
320
cvs add kmyapp
 
321
cvs add kmyapp/kmysource.cpp
 
322
cvs commit    (actually puts the directory and file in the CVS)
 
323
</screen>
 
324
</para>
 
325
 
 
326
<para><emphasis>Note</emphasis>: You need to have files in a directory to commit it.
 
327
<emphasis remap="bf">Removing a directory</emphasis> (a module, like a new app) (ex. kdeutils/kmyapp)
 
328
<screen>cd kdeutils/kmyapp
 
329
(delete all files, as described above in "Deleting a file")
 
330
cd ..
 
331
cvs -P update  (will remove the local kmyapp automatically)
 
332
</screen>
 
333
</para>
 
334
</sect2>
 
335
</sect1>
 
336
 
 
337
<sect1 id="compiling-and-safe-development-practices-wit">
 
338
<title>Compiling and Safe Development Practices (with configure)</title>
 
339
 
 
340
<para>Before you start downloading and compiling the latest sources you should be aware that there's a good chance they won't work!  They are
 
341
in a state of constant development so they could very well have bugs.</para>
 
342
 
 
343
<para>Knowing this, you should find a way to compile and run new KDE stuff without interfering with your existing stable KDE setup.  Here's
 
344
one way, using the HEAD branch as an example.  We, again, assume your login is joedeveloper.  We also assume that your home directory
 
345
is in /home/joedeveloper.  (This would be the case for Red Hat systems.)</para>
 
346
 
 
347
<sect2 id="organizing">
 
348
<title>Organizing</title>
 
349
 
 
350
<para>Make a directory called KDE in the home directory of your *user* account.  You should not be doing any of this as root!  Make another
 
351
called KDE/CVS-HEAD.  cd into that directory and get the KDE sources from the HEAD branch that you want.  The (minumum) modules needed
 
352
to use an application are: kdesupport, kdelibs.  You should compile and install them in that order (see below for compiling).  Others
 
353
you might want are: kdebase, kdeutils, kdegraphics, etc. Now, make a directory called KDE/kde-HEAD.  This is where you'll store the
 
354
compiled code from the HEAD branch -- as well as Qt 2.1!</para>
 
355
</sect2>
 
356
 
 
357
<sect2 id="compiling-qt-2.1">
 
358
<title>Compiling Qt 2.1</title>
 
359
 
 
360
<para>Let's get Qt 2.1. Take the KDE copy of the current Qt library from the KDE CVS with</para>
 
361
 
 
362
<para><screen>cvs -z6 co qt-copy
 
363
cd qt-copy
 
364
setenv QTDIR $PWD     (if you use csh/tcsh)
 
365
OR
 
366
export QTDIR=`pwd`    (if you use bash)
 
367
make -f Makefile.cvs (creates symlinks -without that, qt will not compile !)
 
368
./configure   (-gif optionally)
 
369
make
 
370
</screen>
 
371
</para>
 
372
</sect2>
 
373
 
 
374
<sect2 id="compiling-kde-head">
 
375
<title>Compiling KDE (HEAD)</title>
 
376
 
 
377
<para>Now, for the KDE code.  <literal remap="tt">cd</literal> to KDE/CVS-HEAD/kdesupport.  Type</para>
 
378
 
 
379
<para><screen>make -f Makefile.cvs
 
380
./configure --prefix=/home/joedeveloper/KDE/kde-HEAD
 
381
--with-qt-dir=/home/joedeveloper/KDE/kde-HEAD/qt-copy
 
382
--with-qt-libs=/home/joedeveloper/KDE/kde-HEAD/qt-copy/lib
 
383
make
 
384
 
 
385
If all goes well, then
 
386
 
 
387
make install
 
388
 
 
389
If not, try to fix things, then type
 
390
 
 
391
make install
 
392
 
 
393
Repeat this process for the other modules.  You should alter the
 
394
./configure line to read
 
395
        ./configure --prefix=/home/joedeveloper/KDE/kde-HEAD
 
396
  --with-qt-dir=/home/joedeveloper/KDE/kde-HEAD/qt-copy
 
397
  --with-qt-libs=/home/joedeveloper/KDE/kde-HEAD/qt-copy/lib
 
398
</screen>
 
399
</para>
 
400
</sect2>
 
401
 
 
402
<sect2 id="compiling-tips">
 
403
<title>Compiling tips</title>
 
404
 
 
405
<para><itemizedlist>
 
406
<listitem>
 
407
<para> I usually put that long configure command into a file called <literal remap="tt">conf</literal> and leave it in my CVS-HEAD directory.  Then I can do a
 
408
<literal remap="tt">../conf</literal> from any module and get a good configure.</para>
 
409
</listitem>
 
410
<listitem>
 
411
<para> It seems that you need to compile and install qimageio (part of Qt) separately.  Just
 
412
<literal remap="tt">cd</literal> to <literal remap="tt">/$QTDIR/extensions/imageio/src</literal> and type <literal remap="tt">make install</literal></para>
 
413
</listitem>
 
414
</itemizedlist>
 
415
</para>
 
416
</sect2>
 
417
</sect1>
 
418
 
 
419
<sect1 id="documentation">
 
420
<title>Documentation</title>
 
421
 
 
422
<para>It's important to document your application so that end-users can make the most of it.  You should be clear and concise.  Describe any
 
423
non-standard installation, usage and UI features.  There's no need to talk about how to use the <emphasis>File</emphasis> menu, for example, unless
 
424
you've put some special entry on it.  Include contact and bug-reporting information as well as a hyperlink to the application's home
 
425
page. Writing documentation for KDE 2 should be done in docbook-sgml. Look at <ulink url="http://developer.kde.org">http://developer.kde.org</ulink> for more details how to get the needed packages for installing the docbook tools. KDE extends these
 
426
tools by the module kdesdk/ksgmltools. This module also contains information where to get the docbook tools, additional documentation
 
427
as well as how to use docbook and KDE.</para>
 
428
 
 
429
<para>You should also document your widgets and other classes.  You can include comments in your header ( <literal remap="tt">.h</literal>) files which describe
 
430
each <literal remap="tt">public</literal> or <literal remap="tt">protected</literal> method.  It you do this as you write the methods it will make the documentation proceSss seem
 
431
easier. (It may also help you be certain about what function(s) that method is to perform.)  The script <literal remap="tt">kdoc</literal> will turn your header
 
432
files into beautiful class documentation.  You can see examples of <literal remap="tt">kdoc</literal> output if you look at <ulink url="http://www.ph.unimelb.edu.au/~ssk/kde/srcdoc/kdecore/index-long.html">http://www.ph.unimelb.edu.au/~ssk/kde/srcdoc/kdecore/index-long.html</ulink>. This is the annotated list of the core KDE classes.</para>
 
433
 
 
434
<para>You can find <literal remap="tt">ksgmltools</literal> in the KDE SDK which is available in the kdesdk module of CVS, <literal remap="tt">kdoc</literal> in the kdoc module.  (Methods for
 
435
getting things from CVS are described above.)</para>
 
436
 
 
437
<sect2 id="kdoc-the-kde-class-documentation-tool-for-c">
 
438
<title>KDOC:  The KDE Class Documentation Tool for C++</title>
 
439
 
 
440
<para>It's called <literal remap="tt">kdoc</literal> and is in the kdedoc subdirectory of the CVS
 
441
module kdesdk.</para>
 
442
 
 
443
<para>If you mark up your header files like this:
 
444
<screen>  /**
 
445
   * Short description of this class
 
446
   *
 
447
   * This is a longer description of my class.  It does the following
 
448
   * @li Some bulleted thing
 
449
   * @li Some other bulleted thing
 
450
   *  You should use it when ...  It's not appropriate for ...
 
451
   *
 
452
   * @author My Name &lt;myemail@wherever.edu&gt;
 
453
   * @version 0.0.1
 
454
   **/
 
455
 
 
456
class KMyClass
 
457
{
 
458
        .
 
459
  /**
 
460
   * Describe method.  It takes &&lt;;i&&gt;;argument&&lt;;/i&&gt;; to mean ...
 
461
   *
 
462
   * @return A pointer to another class
 
463
   * @see KOtherClass
 
464
   **/
 
465
   KOtherClass *method (int argument);
 
466
}
 
467
</screen>
 
468
</para>
 
469
 
 
470
<para>The text in the comments beginning with <literal remap="tt">/**</literal> (two asterisks,
 
471
mind you!) will be taken by <literal remap="tt">kdoc</literal> as class documentation and
 
472
formatted appropriately.  You can use some HTML tags (like the
 
473
&&lt;;i&&gt;; above).  The <literal remap="tt">@author</literal> and other tags are meaningful
 
474
to <literal remap="tt">kdoc</literal> and used for formatting.</para>
 
475
 
 
476
<para>To run <literal remap="tt">kdoc</literal>, use the following command
 
477
<screen> kdoc -dhtml -L$KDEDIR/share/kdoc -a Title header1.h header2.h ...
 
478
</screen>
 
479
</para>
 
480
 
 
481
<para>This instructs <literal remap="tt">kdoc</literal> to generate HTML output (the default) in the
 
482
<literal remap="tt">html</literal> directory (by the <literal remap="tt">-d</literal> option) from the specified header
 
483
files.  It uses <literal remap="tt">Title</literal> as the title for the documentation. ( <literal remap="tt">-a</literal>
 
484
says to do work on all header files, even if they don't "ask for it".  I
 
485
haven't told you how to "ask for it."  The <literal remap="tt">-L</literal> tells kdoc where
 
486
its libraries are.)  Type <literal remap="tt">kdoc -h</literal> for more information.</para>
 
487
</sect2>
 
488
</sect1>
 
489
 
 
490
<sect1 id="packaging-and-submitting-code-to-kde">
 
491
<title>Packaging and Submitting Code to KDE</title>
 
492
 
 
493
<sect2 id="packaging">
 
494
<title>Packaging</title>
 
495
 
 
496
<para>'Packing' means putting your (in this case source) code into some
 
497
format that is
 
498
<itemizedlist>
 
499
<listitem>
 
500
<para> easy for others to configure and install, and</para>
 
501
</listitem>
 
502
<listitem>
 
503
<para> easy to transfer,</para>
 
504
</listitem>
 
505
<listitem>
 
506
<para> can be indexed so that it is easy to find.</para>
 
507
</listitem>
 
508
</itemizedlist>
 
509
</para>
 
510
 
 
511
<para>These three concepts are expanded upon in the next three subsections.</para>
 
512
 
 
513
<sect3 id="gnu-configure">
 
514
<title>GNU Configure</title>
 
515
 
 
516
<para>The standard KDE application (or other code) source code package includes the GNU <literal remap="tt">configure</literal> script which determines some
 
517
information about the user's system and provides it to your source code as <literal remap="tt">&&num;;define</literal> statements in a header file called
 
518
<literal remap="tt">config.h</literal>.</para>
 
519
 
 
520
<para>To get started with this, get the kdesdk from CVS using a method described above.  Then prepare kexample, an example package, for your
 
521
application</para>
 
522
 
 
523
<para><screen>   cd kdesdk
 
524
   cd kexample
 
525
   make -f Makefile.cvs
 
526
   cd ..; cp -r kexample ~/KDE/kmyapp-0.0.1
 
527
</screen>
 
528
</para>
 
529
 
 
530
<para>(That last directory is just an example.  Replace kmyapp with your application's (or widget's) name, and replace 0.0.1 with its version
 
531
number.)</para>
 
532
 
 
533
<para>Now, we'll put your source code into the example package.  Let's say your source code was in the directory &&nbsp;;/KDE/KMyApp:</para>
 
534
 
 
535
<para><screen>   cd ~/KDE/kmyapp-0.0.1
 
536
   mkdir kmyapp
 
537
   cp ~/KDE/KMyApp/*.cpp kmyapp
 
538
   cp ~/KDE/KMyApp/*.h kmyapp
 
539
   (There may be other files to copy, but leave your old Makefile behind!)
 
540
</screen>
 
541
 
 
542
Now, edit kmyapp-0.0.1/Makefile.am and change the line
 
543
<screen>   SUBDIRS = kexample
 
544
</screen>
 
545
 
 
546
to
 
547
<screen>   SUBDIRS = kmyapp
 
548
</screen>
 
549
</para>
 
550
 
 
551
<para><emphasis>Note</emphasis>:  kmyapp here refers to the subdirectory by that name.  You could include more subdirectories to be compiled.  For example:
 
552
<screen>   SUBDIRS = kmyapp kmysupportclass
 
553
</screen>
 
554
</para>
 
555
 
 
556
<para>Also edit the last line of configure.in to read</para>
 
557
 
 
558
<para><screen>AC_OUTPUT(Makefile \
 
559
          kmyapp/Makefile \
 
560
          po/Makefile)
 
561
</screen>
 
562
</para>
 
563
 
 
564
<para>The <literal remap="tt">po</literal> directory contains translations of strings that you used in your code (this is about i18n(), which is not covered in this
 
565
HOWTO). We'll get to that it a minute.</para>
 
566
 
 
567
<para>Now we want to set up the Makefile for the kmyapp subdirectory.  Edit <literal remap="tt">kmyapp/Makefile.am</literal> according to the instructions given
 
568
in the comments.  They should be clear enough.</para>
 
569
 
 
570
<para>Now <literal remap="tt">cd &&tilde;;/KDE/kmyapp</literal> and type
 
571
<screen>   ./configure
 
572
</screen>
 
573
 
 
574
This should create:
 
575
<itemizedlist>
 
576
<listitem>
 
577
<para> Makefile</para>
 
578
</listitem>
 
579
<listitem>
 
580
<para> kmyapp/Makfile</para>
 
581
</listitem>
 
582
<listitem>
 
583
<para> config.h</para>
 
584
</listitem>
 
585
</itemizedlist>
 
586
</para>
 
587
 
 
588
<para>You can now include config.h in your source code with <literal remap="tt">&&num;;include "../config.h"</literal> and have your code compile differently on
 
589
different systems based on the <literal remap="tt">&&num;;define</literal>s.  Eh?  Well, different systems have slightly differnent ideas about implementing
 
590
standards and such, and your code my need take this into account to be portable, i.e. to work on various Unices.  Take a look inside
 
591
<literal remap="tt">config.h</literal> for descriptions of the <literal remap="tt">&&num;;define</literal>s.</para>
 
592
 
 
593
<para><emphasis remap="bf">Shared Libraries!</emphasis>  If you are packaging a widget or other class you should be compiling a shared library.  Luckily, this is
 
594
easy to do within the kexample packge.  You only need to change the Makefile.am that resides in your code's sudirectory.  Unluckily,
 
595
now example for a shared-library Makefile.am is included. So, I've included one in the next section. <emphasis>Note</emphasis>:  If you distribute a
 
596
widget, you should also distribute a small program which tests the widget.  Put  that program in the same package in another
 
597
subdirectory and have it compile along with the widget.</para>
 
598
 
 
599
<para>Next, make a compressed archive.  You can do it this way
 
600
<screen>   cd ~/KDE/kmyapp
 
601
   make dist
 
602
   OR
 
603
   tar -cvf kmyapp-0.1.1.tgz kmyapp-0.1.1
 
604
</screen>
 
605
 
 
606
or however you like.  Just be sure that the archive expands to <emphasis>one</emphasis> directory containing all of the files.  This is neater and
 
607
easier for the user to deal with.</para>
 
608
</sect3>
 
609
 
 
610
<sect3 id="example-makfile.am-for-a-shared-library">
 
611
<title>Example Makfile.am for a Shared Library</title>
 
612
 
 
613
<para><screen># Example Makefile.am for a shared library.  It makes a library
 
614
#  called "example" as libexample.so.2.1.2
 
615
# This Makefile.am was taken from the kdelibs distribution and modified
 
616
#  to serve as an example.
 
617
#
 
618
# David Sweet
 
619
#
 
620
 
 
621
INCLUDES=  $(all_includes)
 
622
 
 
623
lib_LTLIBRARIES  = libexample.la
 
624
 
 
625
# Note:  If you specify a:b:c as the version in the next line,
 
626
#  the library that is made has version (a-c).c.b.  In this
 
627
#  example, the version is 2.1.2.
 
628
libexample_la_LDFLAGS = -version-info 3:2:1 $(all_libraries)
 
629
 
 
630
include_HEADERS = header1.h header2.h\
 
631
                  header3.h
 
632
 
 
633
# Which headers shouldn't be installed when a   make install  is done?
 
634
noinst_HEADERS = version.h
 
635
 
 
636
libexample_la_SOURCES = code1.cpp code2.cpp
 
637
                        code3.cpp
 
638
 
 
639
#  AUTO is great.  This takes care of all of your  moc'ing
 
640
#   dependencies.
 
641
#  (You still need to include, for example, header1.moc in code1.cpp.)
 
642
libexample_la_METASOURCES = AUTO
 
643
</screen>
 
644
</para>
 
645
</sect3>
 
646
 
 
647
<sect3 id="lsm-file">
 
648
<title>LSM file</title>
 
649
 
 
650
<para>Next, you need and LSM file.  You can keep a copy in kmyapp-0.1.1
 
651
for distribution.</para>
 
652
 
 
653
<para>Here's a sample <literal remap="tt">.lsm</literal>:</para>
 
654
 
 
655
<para><screen>
 
656
Begin3
 
657
Title:          KLab
 
658
Version:        0.1.0
 
659
Entered-date:   3/1/99
 
660
Description:    GUI and more for RLab
 
661
Keywords:       kde rlab math plot plotting
 
662
Author:         David Sweet &&lt;;dsweet@chaos.umd.edu&&gt;;
 
663
Maintained-by:  David Sweet &&lt;;'dsweet@chaos.umd.edu&&gt;;
 
664
Home-page:      http://www.glue.umd.edu/~dsweet/KDE/KLab
 
665
Primary-site:   ftp://ftp.kde.org/pub/kde/unstable/apps/scientific
 
666
Alternate-site: http://www.glue.umd.edu/~dsweet/KDE/KLab/
 
667
Original-site:  ftp://upload.kde.org/pub/kde/Incoming
 
668
Platform:       unix
 
669
Copying-policy: GPL
 
670
End
 
671
 
 
672
</screen>
 
673
</para>
 
674
 
 
675
<para>You can copy and paste this text into a file called "kmyapp.lsm" and make the appropriate changes.</para>
 
676
</sect3>
 
677
</sect2>
 
678
 
 
679
<sect2 id="submitting">
 
680
<title>Submitting</title>
 
681
 
 
682
<para>If you are hacking at CVS, you should follow the commit procedure outlined above.  If you want to submit changes to code
 
683
that you are not maintaining, you should first check with the maintainer of the application.  You can usually find his/her email
 
684
address in the directory containing the source.  Also check the program's "About" box if it has one.  If no maintainer is specifically
 
685
listed, you should contact the author.</para>
 
686
 
 
687
<para>If you are developing outside of CVS, you can submit your code (widgets, applications, etc.) via FTP to
 
688
<ulink url="ftp://upload.kde.org/pub/kde/Incoming">ftp://upload.kde.org/pub/kde/Incoming</ulink></para>
 
689
 
 
690
<para>When you do this be sure to include an <literal remap="tt">.lsm</literal> (Linux Software Map) file. This way your code can be automatically placed in the
 
691
appropriate spot on ftp.kde.org and its mirrors and an announcement can be automatically sent to the kde-announce mailing list.</para>
 
692
 
 
693
<para><emphasis>Note</emphasis>: The <literal remap="tt">.lsm</literal> file should be uploaded separately from the source code (as a plain ASCII file).  The source code should be
 
694
packaged as a .tar.gz (or .tgz) or .tar.bz2.  This archive should expand to a single directory with all of your stuff in it.</para>
 
695
</sect2>
 
696
</sect1>
 
697
 
 
698
<sect1 id="acknowledgements">
 
699
<title>Acknowledgements</title>
 
700
 
 
701
<para>I'd like to thank the following people for their suggestions (in no particular order): Roberto Alsina, Waldo Bastian, Harri Porten,
 
702
Samuel Wuethrich, Richard Moore, Daniel Naber, Ralf Nolden, Martin Konold, and Pietro Iglio, Stephan Kulow, Junji Takagi.</para>
 
703
</sect1>
 
704
 
 
705
<sect1 id="about-this-document">
 
706
<title>About this document</title>
 
707
 
 
708
<sect2 id="finding">
 
709
<title>Finding</title>
 
710
 
 
711
<para>The current version of this document is available at <ulink url="http://www.chaos.umd.edu/~dsweet/KDE/MiniHOWTO">http://www.chaos.umd.edu/~dsweet/KDE/MiniHOWTO</ulink>.</para>
 
712
 
 
713
<para>A Japanese language version is available at <ulink url="http://www.asahi-net.or.jp/~hc3j-tkg/kde-jp/DevelMiniHOWTO-jp.txt">http://www.asahi-net.or.jp/~hc3j-tkg/kde-jp/DevelMiniHOWTO-jp.txt</ulink> thanks to Junji Takagi.</para>
 
714
 
 
715
<para>This document is included in the KDE Developer's Web Site (<ulink url="http://developer.kde.org">http://developer.kde.org</ulink>)
 
716
and is part of the KDevelop (<ulink url="http://www.kdevelop.org">http://www.kdevelop.org</ulink>) programming manuals.</para>
 
717
</sect2>
 
718
 
 
719
<sect2 id="changes">
 
720
<title>Changes</title>
 
721
 
 
722
<sect3 id="changes-from-version-july-1-1999-to-version-">
 
723
<title>Changes from version &&lt;;July 1, 1999&&gt;; to version &&lt;;March, 11, 2000&&gt;;:</title>
 
724
 
 
725
<para><itemizedlist>
 
726
<listitem>
 
727
<para> Added "About this document" section</para>
 
728
</listitem>
 
729
<listitem>
 
730
<para> Added more acknowledgements</para>
 
731
</listitem>
 
732
<listitem>
 
733
<para> Multiple formatting changes (thanks Ralf!)</para>
 
734
</listitem>
 
735
<listitem>
 
736
<para> Fixed instructions for getting CVS access</para>
 
737
</listitem>
 
738
<listitem>
 
739
<para> updated contents for current KDE 2 development state (March, 11, 2000)</para>
 
740
</listitem>
 
741
</itemizedlist>
 
742
</para>
 
743
</sect3>
 
744
</sect2>
 
745
</sect1>
 
746
</chapter>
 
747
 
 
748
<chapter id="using-kde-io-slaves">
 
749
<title>Using KDE I/O Slaves</title>
 
750
 
 
751
<para>Kurt Granroth <ulink url="mailto:granroth@kde.org">\|&lt;\|granroth@kde.org\|&gt;\|</ulink></para>
 
752
 
 
753
<para>v0.1, 15, June 1999</para>
 
754
 
 
755
<para><emphasis>This HOWTO describes how the KDE I/O slaves (ioslaves) work.  It is
 
756
intended for both ioslave implementers as well as users.  In this
 
757
document, I will attempt to describe both how ioslaves work as well
 
758
as how to use them.</emphasis></para>
 
759
 
 
760
<sect1 id="introduction-0">
 
761
<title>Introduction</title>
 
762
 
 
763
<sect2 id="what-are-io-slaves">
 
764
<title>What Are I/O Slaves?</title>
 
765
 
 
766
<para>The K Desktop Environment (KDE) I/O slaves (ioslaves) are a series of
 
767
small programs that have intimate knowledge on working with a very
 
768
specific protocol.  For instance, the HTTP ioslave (<literal remap="tt"><indexterm remap="cdx"><primary><literal>kio&&lowbar;;http</literal></primary></indexterm>kio&&lowbar;;http</literal>)
 
769
knows all about sending and receiving data to and from a web server <indexterm remap="idx"><primary>web server</primary></indexterm>.  It
 
770
knows all about SSL <indexterm remap="idx"><primary>SSL</primary></indexterm>, encoding, and what all of the different header fields
 
771
mean.  It knows this so that KDE developers won't have to -- if they want
 
772
a web page, they merely have to use <literal remap="tt"><indexterm remap="cdx"><primary><literal>kio&&lowbar;;http</literal></primary></indexterm>kio&&lowbar;;http</literal> for it and it will
 
773
take care of everything for them.</para>
 
774
 
 
775
<para>The ioslaves are based on the KIO library (<literal remap="tt"><indexterm remap="cdx"><primary><literal>libkio</literal></primary></indexterm>libkio</literal>).  This library
 
776
implements a method of asynchronous communication between
 
777
applications as well as provides a "protocol registry" of sorts.
 
778
This has many advantages.  Two of the major ones are:</para>
 
779
 
 
780
<para><itemizedlist>
 
781
<listitem>
 
782
<para>The client does not need to know anything about the ioslave that
 
783
it is calling.  It merely specifies the protocol and <literal remap="tt">cdx/libkio/</literal> will
 
784
automatically determine the proper ioslave to use.
 
785
        </para>
 
786
</listitem>
 
787
<listitem>
 
788
<para>All communication is done asynchronously.  All <literal remap="tt"><indexterm remap="cdx"><primary><literal>libkio</literal></primary></indexterm>libkio</literal> calls will
 
789
return immediately.  Whenever events occur, <literal remap="tt"><indexterm remap="cdx"><primary><literal>libkio</literal></primary></indexterm>libkio</literal> will send
 
790
signals altering the client to that fact.  This means that the
 
791
client does not have to engage in any "busy waiting."</para>
 
792
</listitem>
 
793
</itemizedlist>
 
794
</para>
 
795
 
 
796
<para>Here is a fully working snippet of code to download a web page:<indexterm remap="ncdx"><primary><literal>KIOJob</literal></primary></indexterm><indexterm remap="ncdx"><primary><literal>sigData()</literal></primary></indexterm></para>
 
797
 
 
798
<para><programlisting> KIOJob *job = new KIOJob;
 
799
 connect(job, SIGNAL(sigData(int, const char*, int)),
 
800
         this, SIGNAL(slotData(int, const char*, int)));
 
801
 job-&gt;get("http://www.kde.org/news_dyn.html");
 
802
 </programlisting>
 
803
</para>
 
804
 
 
805
<para>That's it!  When the ioslave is done getting the KDE news page, it
 
806
will call your application's slotData() function with the page.</para>
 
807
</sect2>
 
808
 
 
809
<sect2 id="copyright">
 
810
<title>Copyright</title>
 
811
 
 
812
<para>Copyright (c) 1999 Kurt Granroth, All rights reserved.  This is free
 
813
documentware; you can redistribute it and/or modify it under the
 
814
terms of version 2 or later of the
 
815
<ulink url="http://www.gnu.org/copyleft/gpl.html">GNU General Public  License</ulink></para>
 
816
</sect2>
 
817
</sect1>
 
818
 
 
819
<sect1 id="setting-up-ioslaves">
 
820
<title>Setting Up IOSlaves
 
821
 </title>
 
822
 
 
823
<para>Using the KDE ioslaves is very easy once the framework is in place.
 
824
This section will describe getting the "back-end" stuff setup.</para>
 
825
 
 
826
<sect2 id="the-kio-library">
 
827
<title>The KIO Library
 
828
 </title>
 
829
 
 
830
<para>The first part that needs to be installed is the KDE IO library
 
831
(<literal remap="tt"><indexterm remap="cdx"><primary><literal>libkio</literal></primary></indexterm>libkio</literal>).  This library is part of the KDE 2.x <literal remap="tt"><indexterm remap="cdx"><primary><literal>kdelibs</literal></primary></indexterm>kdelibs</literal>
 
832
package.  It
 
833
will be installed by default on all KDE 2.x systems when 2.x is
 
834
finally released.  In the meantime, you will need to get it through
 
835
either CVSUP or the snapshots.  See www.kde.org (or a later appendix
 
836
when I get around to it later) for details on that.</para>
 
837
 
 
838
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>libkio</literal></primary></indexterm>libkio</literal> depends on the KDE UI library (<literal remap="tt"><indexterm remap="cdx"><primary><literal>libkdeui</literal></primary></indexterm>libkdeui</literal>), the KDE
 
839
Core library (<literal remap="tt"><indexterm remap="cdx"><primary><literal>libkdecore</literal></primary></indexterm>libkdecore</literal>), and Qt (<literal remap="tt"><indexterm remap="cdx"><primary><literal>libqt</literal></primary></indexterm>libqt</literal>).  These are
 
840
the "standard" KDE libraries so there shouldn't be any problems, there.</para>
 
841
</sect2>
 
842
 
 
843
<sect2 id="the-ioslaves">
 
844
<title>The IOSlaves
 
845
 </title>
 
846
 
 
847
<para>There are ioslaves for <literal remap="tt"><indexterm remap="cdx"><primary><literal>http</literal></primary></indexterm>http</literal>, <literal remap="tt"><indexterm remap="cdx"><primary><literal>file</literal></primary></indexterm>file</literal>, <literal remap="tt"><indexterm remap="cdx"><primary><literal>gzip</literal></primary></indexterm>gzip</literal>,
 
848
<literal remap="tt"><indexterm remap="cdx"><primary><literal>tar</literal></primary></indexterm>tar</literal>, <literal remap="tt"><indexterm remap="cdx"><primary><literal>file</literal></primary></indexterm>file</literal>, <literal remap="tt"><indexterm remap="cdx"><primary><literal>smb</literal></primary></indexterm>smb</literal>, <literal remap="tt"><indexterm remap="cdx"><primary><literal>pop3</literal></primary></indexterm>pop3</literal>, and
 
849
<literal remap="tt"><indexterm remap="cdx"><primary><literal>imap4</literal></primary></indexterm>imap4</literal> as of the time of this writing.  They are all found in the
 
850
<literal remap="tt"><indexterm remap="cdx"><primary><literal>kdebase</literal></primary></indexterm>kdebase</literal> package under <literal remap="tt"><indexterm remap="cdx"><primary><literal>kioslaves</literal></primary></indexterm>kioslaves</literal>.  Again, these are
 
851
available only from the KDE development CVS so you'll need to use CVSUP or
 
852
the snapshots to retrieve them.</para>
 
853
</sect2>
 
854
</sect1>
 
855
 
 
856
<sect1 id="using-ioslaves-in-your-application">
 
857
<title>Using ioslaves in your Application
 
858
 </title>
 
859
 
 
860
<para>Now that you have the backend stuff all setup, you can start setting
 
861
up your application to use them.  This requires adding the <literal remap="tt"><indexterm remap="cdx"><primary><literal>libkio</literal></primary></indexterm>libkio</literal>
 
862
library to your linking and including the proper header files.</para>
 
863
 
 
864
<sect2 id="modifying-your-makefile">
 
865
<title>Modifying your Makefile
 
866
 </title>
 
867
 
 
868
<para>If you are using the standard KDE automake/autoconf system for your
 
869
application, then you are in luck!  Adding another library is
 
870
trivial:</para>
 
871
 
 
872
<para><itemizedlist>
 
873
<listitem>
 
874
<para>Edit Makefile.am <indexterm remap="idx"><primary>Makefile.am</primary></indexterm></para>
 
875
</listitem>
 
876
<listitem>
 
877
<para>Change the line &&lt;;yourapp&&gt;;<indexterm remap="cdx"><primary><literal>&&lowbar;;LDADD</literal></primary></indexterm>&&lowbar;;LDADD to look something like:
 
878
 
 
879
<programlisting>     myapp_LDADD = $(LIB_KIO)
 
880
   </programlisting>
 
881
</para>
 
882
</listitem>
 
883
</itemizedlist>
 
884
</para>
 
885
 
 
886
<para>That's it!  If you are not using the KDE setup, then just make sure
 
887
that you are including the following in your link stage:</para>
 
888
 
 
889
<para><programlisting>    -lkio -lkdeui -lkdecore -lqt
 
890
 </programlisting>
 
891
</para>
 
892
</sect2>
 
893
 
 
894
<sect2 id="adding-the-proper-headers">
 
895
<title>Adding the Proper Headers
 
896
 </title>
 
897
 
 
898
<para>This is also simple:</para>
 
899
 
 
900
<para><programlisting>   #include &lt;kio_job.h&gt;
 
901
 </programlisting>
 
902
</para>
 
903
 
 
904
<para>Will take care of everything.</para>
 
905
</sect2>
 
906
</sect1>
 
907
 
 
908
<sect1 id="using-ioslaves-via-kiojob">
 
909
<title>Using IOSlaves via KIOJob
 
910
 </title>
 
911
 
 
912
<para>Now that your application is all prepped for using ioslaves, you can
 
913
actually start using them!</para>
 
914
 
 
915
<para>The only class you need to deal with at a client level is the KIOJob
 
916
class.  You will use it to "call" the ioslaves and it will send you
 
917
signals when it received events from them.</para>
 
918
 
 
919
<para>The basic procedure is something like this:</para>
 
920
 
 
921
<para><itemizedlist>
 
922
<listitem>
 
923
<para>Create a KIOJob <indexterm remap="idx"><primary>KIOJob</primary></indexterm> instance</para>
 
924
</listitem>
 
925
<listitem>
 
926
<para>Connect all of the signals (events) that you are interested in to
 
927
some local slots (callbacks).</para>
 
928
</listitem>
 
929
<listitem>
 
930
<para>Send the actual request</para>
 
931
</listitem>
 
932
<listitem>
 
933
<para>Process the resulting response in your slots.</para>
 
934
</listitem>
 
935
</itemizedlist>
 
936
</para>
 
937
 
 
938
<sect2 id="typical-example">
 
939
<title>Typical Example
 
940
 </title>
 
941
 
 
942
<para>An example looks like so:<indexterm remap="ncdx"><primary><literal>sigData()</literal></primary></indexterm><indexterm remap="ncdx"><primary><literal>sigError()</literal></primary></indexterm><indexterm remap="ncdx"><primary><literal>sigDataEnd()</literal></primary></indexterm><indexterm remap="ncdx"><primary><literal>sigFinished()</literal></primary></indexterm></para>
 
943
 
 
944
<para><programlisting> KIOJob *job = new KIOJob;
 
945
 connect(job, SIGNAL(sigData(int, const char*, int)),
 
946
         this, SLOT(slotData(int, const char*, int)));
 
947
 connect(job, SIGNAL(sigError(int, int, const char*)),
 
948
         this, SLOT(slotError(int, int, const char*)));
 
949
 connect(job, SIGNAL(sigDataEnd(int)),
 
950
         this, SLOT(slotDataEnd(int)));
 
951
 connect(job, SIGNAL(sigFinished(int)),
 
952
         this, SLOT(slotFinished(int)));
 
953
 job-&gt;get("http://www.pobox.com/~kurt_granroth/index.html");
 
954
 </programlisting>
 
955
</para>
 
956
 
 
957
<para>This will get the web page at the above URL.  When the ioslave is done
 
958
receiving the page, it will send it to you with your <literal remap="tt"><indexterm remap="cdx"><primary><literal>slotData()</literal></primary></indexterm>slotData()</literal>
 
959
function.  If there was an error, then you receive it in
 
960
<literal remap="tt">slotError()</literal>.  If the page was large, then it will be sent in
 
961
chunks.  You know that you are done receiving data when
 
962
<literal remap="tt">slotDataEnd()</literal> is called.  The <literal remap="tt">slotFinished()</literal> function is
 
963
called when the ioslave is completely done.</para>
 
964
</sect2>
 
965
</sect1>
 
966
 
 
967
<sect1 id="kiojob-calls">
 
968
<title>KIOJob Calls
 
969
 </title>
 
970
 
 
971
<para>There are numerous operations that you can do with KIOJob.  Some of them
 
972
are: <literal remap="tt"><indexterm remap="cdx"><primary><literal>put</literal></primary></indexterm>put</literal>, <literal remap="tt"><indexterm remap="cdx"><primary><literal>get</literal></primary></indexterm>get</literal>, <literal remap="tt"><indexterm remap="cdx"><primary><literal>mkdir</literal></primary></indexterm>mkdir</literal>, <literal remap="tt"><indexterm remap="cdx"><primary><literal>copy</literal></primary></indexterm>copy</literal>,
 
973
<literal remap="tt"><indexterm remap="cdx"><primary><literal>move</literal></primary></indexterm>move</literal>, <literal remap="tt"><indexterm remap="cdx"><primary><literal>del</literal></primary></indexterm>del</literal>, <literal remap="tt"><indexterm remap="cdx"><primary><literal>unmount</literal></primary></indexterm>unmount</literal>, and <literal remap="tt"><indexterm remap="cdx"><primary><literal>mount</literal></primary></indexterm>mount</literal>.  I will
 
974
refer only to <literal remap="tt"><indexterm remap="cdx"><primary><literal>put()</literal></primary></indexterm>put()</literal> and <literal remap="tt"><indexterm remap="cdx"><primary><literal>get()</literal></primary></indexterm>get()</literal> in this HOWTO.  The others
 
975
follow similar patterns.</para>
 
976
 
 
977
<sect2 id="getconst-char-url">
 
978
<title>get(const char* url)
 
979
 </title>
 
980
 
 
981
<para>This is probably the most common operation.  It tells the ioslave to
 
982
"get" the resource described in the URL.  This may be a web page, a
 
983
POP3 message, or a local file -- it all depends on your URL.</para>
 
984
 
 
985
<para>This operation is not very interactive.  You tell the ioslave what
 
986
you want and it gets it for you.  Period.</para>
 
987
 
 
988
<para>Specifically, it will send back your data with the <literal remap="tt"><indexterm remap="cdx"><primary><literal>sigData(int id,
 
989
char char* data, int length)</literal></primary></indexterm>sigData(int id,
 
990
char char* data, int length)</literal> signal.</para>
 
991
 
 
992
<para>Parameters:</para>
 
993
 
 
994
<para>const char *url - The URL of the resource that you wish to get</para>
 
995
</sect2>
 
996
 
 
997
<sect2 id="putconst-char-url-int-mode-bool-overwrite-bo">
 
998
<title>put(const char* url, int mode, bool overwrite, bool resume, int size)
 
999
 </title>
 
1000
 
 
1001
<para>This operation will start the process of "putting" or sending data to
 
1002
the location specified in the URL.  This is used, for instance, to
 
1003
send files to a remote FTP server or do do a PUT or POST request with
 
1004
HTTP.  It is not quite a straight-forward as a <literal remap="tt"><indexterm remap="cdx"><primary><literal>get()</literal></primary></indexterm>get()</literal> operation.</para>
 
1005
 
 
1006
<para>The basic procedure looks like:</para>
 
1007
 
 
1008
<para><itemizedlist>
 
1009
<listitem>
 
1010
<para>Connect <literal remap="tt"><indexterm remap="cdx"><primary><literal>sigReady(int)</literal></primary></indexterm>sigReady(int)</literal> to a local slot (e.g., <literal remap="tt">slotReady(int)</literal>)</para>
 
1011
</listitem>
 
1012
<listitem>
 
1013
<para>Send a <literal remap="tt"><indexterm remap="cdx"><primary><literal>KIOJob::put(..)</literal></primary></indexterm>KIOJob::put(..)</literal> request</para>
 
1014
</listitem>
 
1015
<listitem>
 
1016
<para>When <literal remap="tt">slotReady(..)</literal> is called, you know that the ioslave is ready
 
1017
to relay your data to its final destination.</para>
 
1018
</listitem>
 
1019
<listitem>
 
1020
<para>Send all of your data using the <literal remap="tt"><indexterm remap="cdx"><primary><literal>KIOJob::data(const char*, int)</literal></primary></indexterm>KIOJob::data(const char*, int)</literal>
 
1021
operation.  When you are done, notify the ioslave of this by
 
1022
sending a <literal remap="tt"><indexterm remap="cdx"><primary><literal>KIOJob::dataEnd()</literal></primary></indexterm>KIOJob::dataEnd()</literal></para>
 
1023
</listitem>
 
1024
</itemizedlist>
 
1025
</para>
 
1026
 
 
1027
<para>Some sample code looks like so:</para>
 
1028
 
 
1029
<para><programlisting> KIOJob *job;
 
1030
 char *data = "My message";
 
1031
 Client::Client()
 
1032
 {
 
1033
        job = new KIOJob;
 
1034
        connect(job, SIGNAL(sigReady(int)), this, SLOT(slotReady(int)));
 
1035
        connect(job, SIGNAL(sigData(int, const char*, int)),
 
1036
                this, SLOT(slotData(int, const char*, int)));
 
1037
        connect(job, SIGNAL(sigDataEnd(int)),
 
1038
                this, SLOT(slotDataEnd(int)));
 
1039
        job-&gt;put("http://server.com/cgi-bin/post.cgi", -1, true, false, strlen(data));
 
1040
 }
 
1041
 
 
1042
 void Client::sigReady(int id)
 
1043
 {
 
1044
    job-&gt;data(data, strlen(data));
 
1045
        job-&gt;dataEnd();
 
1046
 }
 
1047
 </programlisting>
 
1048
</para>
 
1049
 
 
1050
<para>Parameters:</para>
 
1051
 
 
1052
<para>const char* url - The end location for your data
 
1053
int mode        - Special permissions for your data.  This should be set
 
1054
to -1 if there are no special permissions
 
1055
bool overwrite  - Instructs the ioslave to overwrite anything that
 
1056
may already be there.
 
1057
bool resume     - Instructs the ioslave to resume a previously aborted
 
1058
transaction.
 
1059
int size        - This is the size of the data that you will be sending</para>
 
1060
 
 
1061
<para>Beyond that, everything else is identical to the 'get' method.</para>
 
1062
</sect2>
 
1063
 
 
1064
<sect2 id="datavoid-data-int-size">
 
1065
<title>data(void *data, int size)
 
1066
 </title>
 
1067
 
 
1068
<para>This is used to send data to an ioslave.  It is used in conjunction with
 
1069
the <literal remap="tt"><indexterm remap="cdx"><primary><literal>KIOJob::put(..)</literal></primary></indexterm>KIOJob::put(..)</literal> operation.  It is almost always called from
 
1070
your object's <literal remap="tt">slotReady()</literal> slot as you must wait for the
 
1071
<literal remap="tt"><indexterm remap="cdx"><primary><literal>sigReady(int)</literal></primary></indexterm>sigReady(int)</literal> signal before sending any data.  If your data is
 
1072
greater than 2048 bytes, then you must break it up into many chunks and
 
1073
send each chunk individually.</para>
 
1074
 
 
1075
<para>Parameters:</para>
 
1076
 
 
1077
<para>void *data - Your data that needs to go to the ioslave.  This should be no
 
1078
more than 2048 bytes.
 
1079
int size   - The size of this data</para>
 
1080
</sect2>
 
1081
 
 
1082
<sect2 id="dataend">
 
1083
<title>dataEnd()
 
1084
 </title>
 
1085
 
 
1086
<para>This is used along with <literal remap="tt"><indexterm remap="cdx"><primary><literal>KIOJob::data(..)</literal></primary></indexterm>KIOJob::data(..)</literal> and
 
1087
<literal remap="tt"><indexterm remap="cdx"><primary><literal>KIOJob::put(..)</literal></primary></indexterm>KIOJob::put(..)</literal>.  It signals the ioslave that you are done
 
1088
sending it data.  If you do not send this signal, then the ioslave will
 
1089
essentially hang.  You do not need to use this if you are using
 
1090
<literal remap="tt"><indexterm remap="cdx"><primary><literal>KIOJob::get(..)</literal></primary></indexterm>KIOJob::get(..)</literal>.</para>
 
1091
 
 
1092
<para>Parameters:</para>
 
1093
 
 
1094
<para>None</para>
 
1095
</sect2>
 
1096
</sect1>
 
1097
 
 
1098
<sect1 id="kiojob-signals">
 
1099
<title>KIOJob Signals
 
1100
 </title>
 
1101
 
 
1102
<para>All communication from the ioslaves come through KIOJob in the form of
 
1103
signals.  There are quite a few of them (see <literal remap="tt"><indexterm remap="cdx"><primary><literal>kio&&lowbar;;job.h</literal></primary></indexterm>kio&&lowbar;;job.h</literal> for a complete
 
1104
listing), but I'll only discuss the "essential" ones.</para>
 
1105
 
 
1106
<sect2 id="sigerrorint-id-int-errid-const-char-text">
 
1107
<title>sigError(int id, int errid, const char* text)
 
1108
 </title>
 
1109
 
 
1110
<para>This signal is emitted whenever an error occurs.  You should always connect a
 
1111
slot to this signal unless you really don't care if there is an error or not.</para>
 
1112
 
 
1113
<para>Parameters:</para>
 
1114
 
 
1115
<para>int id           - The job id
 
1116
int errid        - The error code.  This corresponds to the list of errors
 
1117
defined in kio&&lowbar;;interface.h
 
1118
const char* text - A textual description of the error</para>
 
1119
</sect2>
 
1120
 
 
1121
<sect2 id="sigreadyint-id">
 
1122
<title>sigReady(int id)
 
1123
 </title>
 
1124
 
 
1125
<para><indexterm remap="ncdx"><primary><literal>sigReady()</literal></primary></indexterm>
 
1126
This signal occurs when the ioslave is ready to accept data.  If you are
 
1127
using only <literal remap="tt"><indexterm remap="cdx"><primary><literal>get(..)</literal></primary></indexterm>get(..)</literal> methods, then you should not have to connect to this
 
1128
signal.  If you are using a <literal remap="tt"><indexterm remap="cdx"><primary><literal>put(..)</literal></primary></indexterm>put(..)</literal> method, then you must connect to this
 
1129
signal and begin sending data from there.</para>
 
1130
 
 
1131
<para>Parameters:</para>
 
1132
 
 
1133
<para>int id - The job id</para>
 
1134
</sect2>
 
1135
 
 
1136
<sect2 id="sigdataint-id-const-char-data-int-size">
 
1137
<title>sigData(int id, const char *data, int size)
 
1138
 </title>
 
1139
 
 
1140
<para><indexterm remap="ncdx"><primary><literal>sigData()</literal></primary></indexterm>
 
1141
This signal happens whenever the ioslave is sending you data.  This is
 
1142
typically the data that it just downloaded.  It will never be more than 2048
 
1143
bytes, so plan on having it called several times.  You are responsible for
 
1144
collecting all of the data.  You will know that the ioslave is done sending
 
1145
you data when you get the <literal remap="tt"><indexterm remap="cdx"><primary><literal>sigDataEnd(int)</literal></primary></indexterm>sigDataEnd(int)</literal> signal.</para>
 
1146
 
 
1147
<para>Parameters:</para>
 
1148
 
 
1149
<para>int id           - The job id
 
1150
const char *data - The data that the ioslave just downloaded
 
1151
int size         - The size of this data chunk</para>
 
1152
</sect2>
 
1153
 
 
1154
<sect2 id="sigdataendint-id">
 
1155
<title>sigDataEnd(int id)
 
1156
 </title>
 
1157
 
 
1158
<para><indexterm remap="ncdx"><primary><literal>sigDataEnd()</literal></primary></indexterm>
 
1159
This signal is sent to signify that the ioslave is done sending you data.
 
1160
You should use this signal as an assurance that you can use the data as
 
1161
<literal remap="tt"><indexterm remap="cdx"><primary><literal>sigData(..)</literal></primary></indexterm>sigData(..)</literal> will never again be called.</para>
 
1162
 
 
1163
<para>Parameters:</para>
 
1164
 
 
1165
<para>int id - The job id</para>
 
1166
</sect2>
 
1167
 
 
1168
<sect2 id="sigfinishedint-id">
 
1169
<title>sigFinished(int id)
 
1170
 </title>
 
1171
 
 
1172
<para><indexterm remap="ncdx"><primary><literal>sigFinished()</literal></primary></indexterm>
 
1173
This signal indicates the the ioslave is completely done.</para>
 
1174
 
 
1175
<para>Parameters:</para>
 
1176
 
 
1177
<para>int id - The job id</para>
 
1178
</sect2>
 
1179
</sect1>
 
1180
</chapter>
 
1181
 
 
1182
<chapter id="komop">
 
1183
<title>KDE KOM/Open Parts</title>
 
1184
 
 
1185
<para>Torben Weis <literal remap="tt">weis@kde.org</literal>, Bernd Wuebben <literal remap="tt">wuebben@kde.org</literal></para>
 
1186
 
 
1187
<para>v 1.0 August 1998</para>
 
1188
 
 
1189
<para><emphasis>A free Object Model for Unix</emphasis></para>
 
1190
 
 
1191
<sect1 id="introduction-1">
 
1192
<title>Introduction</title>
 
1193
 
 
1194
<para>Although it is nice to have applications like StarOffice and
 
1195
ApplixWare available for Unix/Linux, it is a sad fact that they do not
 
1196
interact with other applications. In fact user is expected to use the
 
1197
supplied e-mail-client only, the StarOffice spreadsheet cannot be
 
1198
embedded into an Applix document, and users cannot use the WWW
 
1199
browser of their choice.</para>
 
1200
 
 
1201
<para>Even a rather simple component-based approach like COM (Component
 
1202
Object Model) can do lots of magic. Take a glimpse into Bill Gates'
 
1203
world to convince yourself. The spread sheet of one software house can
 
1204
be used in a word processor of another and many applications support
 
1205
scripting interfaces. A veritable industry of OCX/ActiveX component
 
1206
writers has cropped up. Using easy to learn languages such as Visual
 
1207
Basic, users with a minimal programming background can glue separate
 
1208
components together with ease in order to create new applications
 
1209
exhibiting previously unavailable functionality. As Aristotle put it:
 
1210
The whole is more than the sum of its parts.</para>
 
1211
 
 
1212
<para>Even the most faithful of all Unix supporters had to recognize that
 
1213
the Unix community had technologically fallen far behind the windows as
 
1214
well as Macintosh worlds with regard to GUI and desktop technologies.
 
1215
Fortunately, distributed objects make sense beyond a the realm of
 
1216
desktop and GUI applications. The development of distributed databases
 
1217
may serve as an example and component technology in general fits
 
1218
nicely into the strategy of major software companies which in turn
 
1219
helped to push CORBA development on the UNIX platform. Consequently,
 
1220
there is a standardized, network transparent, platform- and
 
1221
language-independent solution to the IPC-problem available, that is
 
1222
based on an object-oriented approach and that offers exception
 
1223
handling as well as support for management of complex data structures.</para>
 
1224
 
 
1225
<para>While initially only available commercially, free implementations of
 
1226
the CORBA 2.0 standard object request broker (ORB) became available as
 
1227
well.  A particularly well done free implementation of the CORBA
 
1228
standard, that will soon cover the full CORBA-2.1 standard, was
 
1229
developed at the university of Frankfurt, Germany.  This GNU GPL'd ORB
 
1230
named MICO, can compete with commercial implementations with respect to
 
1231
completeness and stability.</para>
 
1232
</sect1>
 
1233
 
 
1234
<sect1 id="corba-based-kde-object-model">
 
1235
<title>CORBA-based KDE Object Model</title>
 
1236
 
 
1237
<para>However, CORBA alone is not enough, as the standard only describes how
 
1238
distributed objects communicate; the COSS (CORBA Standard Services)
 
1239
define interfaces for a whole range of so called services, such as
 
1240
trading services, security services, transactions sercies and license
 
1241
management services and others. As is apparent, desktop development or
 
1242
even GUI application development did not play an important role when
 
1243
designing CORBA. The nearly indispensable event service does not
 
1244
support event filtering, furthermore it lacks a mechanism for so
 
1245
called 'callbacks'. Thus, in order for X11 and CORBA to work well
 
1246
together, CORBA�s well done industry standard object model had to be
 
1247
enhanced in order to be suitable as the underlying distributed object
 
1248
broker on which to build the all important compound document
 
1249
framework.  Of course all this had to be undertaking within the limits
 
1250
of the accepted CORBA industry standards.</para>
 
1251
 
 
1252
<para>The KDE Object Model (KOM) addresses these issues and makes life
 
1253
easier for a programmer by automatically giving each object a base set
 
1254
of functionalities. This includes first and foremost event
 
1255
handling. Each KOM object is capable of receiving events. An event
 
1256
consists of an arbitrary data structure (<literal remap="tt">CORBA::Any</literal>) as well
 
1257
as a string, describing the type of the event, for example
 
1258
Desktop/Font/ChangeFont or Desktop/Color. By reading this string, an
 
1259
object can decide whether it is interested in that event, and will
 
1260
know how the unknown data structure is to be interpreted semantically.</para>
 
1261
</sect1>
 
1262
 
 
1263
<sect1 id="flexibility-with-events-and-filters">
 
1264
<title>Flexibility with events and filters</title>
 
1265
 
 
1266
<para>An important aspect when processing events is filtering. It allows the
 
1267
developer to enhance the functionality of a program without having to
 
1268
change the sources.  There are three types of filters: those which
 
1269
merely recognize events, those which are allowed to change or discard
 
1270
events, and finally those which finally process them.  This model can
 
1271
be illustrated with a simple WWW browser example: If a program wants
 
1272
the browser to open a new URL, it has to send it an event. To enhance
 
1273
the browser with a history function and the user only has to plug in a
 
1274
filter of the first category into the browser. This filter can record
 
1275
all URLs, thereby managing a history function. A tool for blocking
 
1276
certain pages (in order to protect minors for example) belongs to
 
1277
category two: If the URL is rated unsuitable for minors, the filter
 
1278
discards the event or replaces the URL in it with a different one. If
 
1279
the Browser does not support mailto, we need a third category filter:
 
1280
upon arrival of a URLOpen event with mailto:joe@doe in it, the event
 
1281
is discarded from the browser's point of view, but the filter offers
 
1282
an alternative implementation.</para>
 
1283
 
 
1284
<para>The filter principle is of great importance, as in CORBA only
 
1285
interfaces are inherited, not implementations.  It would not be
 
1286
possible to derive from the browser object and to just overload the
 
1287
function that opens a new URL. The event model does not just solve
 
1288
this problem, it enables developers to install several enhancements at
 
1289
the same time. A second filter, filtering FTP URLs for example, can be
 
1290
easily installed in addition. It is important that an user can plug-in
 
1291
an arbitrary number of such filters at run-time. A filter is installed
 
1292
this way:</para>
 
1293
 
 
1294
<para><screen>
 
1295
      KOM::EventTypeSeq types;
 
1296
 
 
1297
      types.length (1);
 
1298
 
 
1299
      types [0] = CORBA::string_dup ("OpenURL");
 
1300
 
 
1301
      browser-&gt;installEventFilter ( this, "eventFilter", types);
 
1302
 
 
1303
 
 
1304
</screen>
 
1305
</para>
 
1306
 
 
1307
<para>Now, all you have to do is wait for events:</para>
 
1308
 
 
1309
<para><screen>
 
1310
boolean MailFilter::eventFilter (in Object obj, in EventType type, in any value)
 
1311
{
 
1312
 
 
1313
    if ( type == "OpenURL" )
 
1314
    {
 
1315
 
 
1316
        char *p;
 
1317
 
 
1318
        if (( value &gt;&gt;=p ) && strcmp (type, "mailto:", 7) == 0)
 
1319
        {
 
1320
 
 
1321
            // open mail app
 
1322
 
 
1323
            CORBA::string_free (p);
 
1324
 
 
1325
            return true;
 
1326
 
 
1327
        }
 
1328
    }
 
1329
 
 
1330
     return false;
 
1331
}
 
1332
 
 
1333
 
 
1334
</screen>
 
1335
</para>
 
1336
 
 
1337
<para>When a user enters a URL in the example above, the browser sends an
 
1338
event to itself. This concept can also serve for a macro recorder,
 
1339
because events can be filtered, saved and re-send later. As event
 
1340
handling works the same way for all KOM objects, there is now - at
 
1341
last - the possibility of creating a supra-component macro recording.</para>
 
1342
 
 
1343
<para>To avoid performance loss, filters can be installed in a way that they
 
1344
only receive events whose type matches a certain
 
1345
expression. Desktop/Font/* would filter all events that have to do
 
1346
with the font settings of the whole desktop.</para>
 
1347
</sect1>
 
1348
 
 
1349
<sect1 id="callbacks-with-signal-and-slots">
 
1350
<title>Callbacks with signal and slots</title>
 
1351
 
 
1352
<para>In an event-driven environment, programmers have to deal with so
 
1353
called callbacks. A callback is a mechanism by which a button for
 
1354
example activates a procedure that is supposed to be called once the
 
1355
button is pressed. C offers pointers to functions for that, under C++
 
1356
we can use elegant signals and slots. A wonderful implementation of
 
1357
this idea is offered by the QT toolkit. KOM offers this technique for
 
1358
distributed objects as well, it uses CORBA�s DII (Dynamic Invocation
 
1359
Interface) for that purpose. An object can be target and sender of
 
1360
signals at the same time. To receive a signal, an object must have a
 
1361
slot with a matching list of parameters. Such a slot is not different
 
1362
from a usual CORBA method without return value. The lines</para>
 
1363
 
 
1364
<para><screen>
 
1365
      MySender_var s = new MySender;
 
1366
 
 
1367
      MyReceiver_var r = new MyReceiver;
 
1368
 
 
1369
      r.connect ( "selected", s, "myslot" );
 
1370
 
 
1371
 
 
1372
</screen>
 
1373
</para>
 
1374
 
 
1375
<para>connect two objects with each other. As soon as <literal remap="tt">s</literal> emits the
 
1376
selected signal, the function myslot of object <literal remap="tt">r</literal> is
 
1377
called. If one of the objects is destroyed, the connection between the
 
1378
two is released automatically. It is possible to connect one signal to
 
1379
different slots and one slot to different signals. Theoretically, it
 
1380
would also be possible to work with events here. Signals and slots
 
1381
however work a lot faster and are easier to handle for the programmer,
 
1382
because he/she does not have to deal with event
 
1383
processing. Furthermore they are type-safe. On the other hand, you
 
1384
have to work without the advantages of filtering.</para>
 
1385
 
 
1386
<para>As already mentioned, interface inheritance does not solve all
 
1387
problems. The browser example shows that installing multiple
 
1388
enhancements at run-time works only because filters are loaded which
 
1389
can plug into the browser. The principle behind this mechanism is
 
1390
called dynamic aggregation. You take a core object (the browser) and
 
1391
enhance it by other objects (plug-ins). The interface of the browser
 
1392
is expanded with the sum of the plug-ins' interfaces. KOM support
 
1393
run-time installation and uninstallation of those plug-ins. Neither is
 
1394
required to run within the same process or even the same computer.</para>
 
1395
 
 
1396
<para>An object that communicates with the browser does not notice which
 
1397
interface was implemented by the core object and which by the
 
1398
plug-ins. If a client wants to know whether a component supports a
 
1399
special interface, a simple</para>
 
1400
 
 
1401
<para><screen>
 
1402
CORBA::Object_var obj = browser-&gt;getInterface ('IDL:/foo/bar:1.0');
 
1403
 
 
1404
 
 
1405
</screen>
 
1406
</para>
 
1407
 
 
1408
<para>is enough to get a reference to that interface. It is even possible to
 
1409
load the plug-in with the required interface at run-time. This saves a
 
1410
lot of memory, because the plug-ins allocate resources only then when
 
1411
they are really needed.</para>
 
1412
</sect1>
 
1413
 
 
1414
<sect1 id="openparts-kom-meets-gui">
 
1415
<title>OpenParts: KOM meets GUI</title>
 
1416
 
 
1417
<para>Until now, the word GUI has not been mentioned a single time. Indeed,
 
1418
KOM is solely based on CORBA. There are in effect quite a number of
 
1419
applications which do not have or do not need a GUI. It would not make
 
1420
sense to burden those applications with GUI code; we better leave that
 
1421
to the supporters of the Redmond doctrine. OpenParts form a layer on
 
1422
top of CORBA, KOM, and X11. Embedding GUI components in own programs
 
1423
has become widely known since introduction of MS Internet Explorer
 
1424
4.0. In the windows world, a lot of controls have been created, a
 
1425
whole industry has formed around the creation of controls and nearly
 
1426
everything, from a simple push-button to a complete WWW browser, can
 
1427
be realized as a control.</para>
 
1428
 
 
1429
<para>The idea behind controls is actualized in KDE's OpenParts. This is
 
1430
done using window objects that export a well-defined interface. The
 
1431
CORBA Implementation Repository registers the implementation of those
 
1432
components.</para>
 
1433
 
 
1434
<para>When an application needs a specific control, it relays a request to
 
1435
the repository. In the OpenParts framework, separate server processes
 
1436
handle these requests. Thus, a high level of toolkit, compiler,
 
1437
language and multi threading-support independence is achieved. The
 
1438
repository returns a reference to a factory. CORBA does not support
 
1439
the creation of new objects with a special construct. Because of that,
 
1440
factories have been introduced, which serve the purpose of creating a
 
1441
new object and returning a reference to it.</para>
 
1442
 
 
1443
<para>The actual embedding is done via X11 swallowing. The element that is
 
1444
to be embedded (a X11 window) is assigned a new parent using the X11
 
1445
Xlib call <literal remap="tt">XReparentWindow</literal>. In order to keep developers away
 
1446
from messing around with pure X11, there exist so called control
 
1447
frames. This class depends on the used toolkit and (viewed from
 
1448
outside) looks like a normal window implemented using a specific GUI
 
1449
toolkit. The control frame is made the new father of the control. Is
 
1450
it moved or resized, the control is moved or resized as well.</para>
 
1451
</sect1>
 
1452
 
 
1453
<sect1 id="dynamic-elements-realized-easily">
 
1454
<title>Dynamic Elements realized easily</title>
 
1455
 
 
1456
<para>Some elements of a window are subject to restrictions. There can only
 
1457
be one menu bar as well as one status bar. Great confusion would ensue
 
1458
if controls were allowed to take control of these restricted
 
1459
elements. One way to avoid this confusion is offered by an enhancement
 
1460
of controls: Parts. A part can be in three different modes: inactive,
 
1461
marked, or active. In a top-level window only one can be active. This
 
1462
part gains control over the restricted elements. The top-level window
 
1463
is called PartShell; it owns menu bar, tool bars, status bar etc. Each
 
1464
part can register its menus and toolbars with the Shell. The Shell,
 
1465
however, only displays the restricted elements of the active Part.</para>
 
1466
 
 
1467
<para>Using Parts, one can build the basic structure of an integrated office
 
1468
suite. Text processing, spread sheet, drawing application and all the
 
1469
rest is put into such structures. As Parts can contain Parts, a
 
1470
spread-sheet Part can be embedded into a text-Part with no
 
1471
problems. Instead of ControlFrames, the developer can use the mightier
 
1472
PartFrames as well. A single click on a part creates a window frame,
 
1473
the user can move and resize the frame now; another click makes it
 
1474
active. The window frame is changed automatically to show the user,
 
1475
that the part has been made active. The Shell changes menu bar and
 
1476
tool bar to the needs of the Part that has become active.</para>
 
1477
 
 
1478
<para>What is missing is a common file menu: it is the Shell's privilege to
 
1479
provide a menu and a toolbar of its own for that purpose. Via these
 
1480
widgets, the user can access the document as a whole, for example to
 
1481
save or print it.</para>
 
1482
</sect1>
 
1483
 
 
1484
<sect1 id="the-document-view-architecture">
 
1485
<title>The Document View Architecture</title>
 
1486
 
 
1487
<para>OpenParts support the Document View Model, known from Smalltalk and
 
1488
popularized in Microsoft's MFC. A view displays the document on the
 
1489
screen and is derived from the Parts class. The document contains data
 
1490
as well as the associated algorithms. The advantage of this solution is
 
1491
that users can have several views of the document. It is, for example,
 
1492
possible to display two paragraphs of a longer article in two windows
 
1493
or to display an image in a separate window when manipulating it. When
 
1494
zooming in on this picture, the rest of the document does not have to
 
1495
be enlarged as well.</para>
 
1496
 
 
1497
<para>For reasons of performance, document and view run within the same
 
1498
process. In order to achieve a clean design, the developer has to
 
1499
strictly follow the principle of separating data and belonging
 
1500
manipulating algorithms on one side and viewing algorithms on the
 
1501
other side. Every user action first affects the view. This view must
 
1502
then signal the Document to change the data basis accordingly. After
 
1503
that, the Document must inform all views to update their windows
 
1504
in order to correctly reflect the new data state.</para>
 
1505
 
 
1506
<para>An important aspect is using a Document without a View. This allows to
 
1507
make use of an office suite's functionality in a batch job, for
 
1508
example. The Document should export methods for manipulating data. A
 
1509
CORBA-aware scripting language could make use of those methods. At
 
1510
this time, CORBA-binding for Perl, Tcl, and CORBA-Script exist, a
 
1511
Python binding is being worked on.</para>
 
1512
 
 
1513
<para>Object models, and operating systems are alike in that they are of
 
1514
mere academic value as long as there are no applications making use of
 
1515
their qualities. KOffice is, at the moment, the largest and most
 
1516
widely known application using OpenParts technology. As the KDE
 
1517
project makes wider use of CORBA, and KOM and OpenParts respectively,
 
1518
there is reason to hope that Unix will soon have a free implementation
 
1519
of a object model that transfers the advantages of contemporary
 
1520
compound document framework technology to the user.</para>
 
1521
</sect1>
 
1522
 
 
1523
<sect1 id="using-openparts-koffice">
 
1524
<title>Using OpenParts: KOffice</title>
 
1525
 
 
1526
<para>Based on OpenParts technology, the KOffice project aims at offering a
 
1527
free and easily extendible office suite for KDE.</para>
 
1528
 
 
1529
<para>The 'mother' of all KOffice components (called Parts) is the spread
 
1530
sheet KSpread. Although officially still declared 'alpha', it is
 
1531
already working very well.. Its mathematical functions can be easily
 
1532
enhanced by means of an embedded Python language interpreter.</para>
 
1533
 
 
1534
<para>KPresenter is a presentation application written by Reginald
 
1535
Stadlbauer, which convincingly demonstrated its usability at the Linux
 
1536
Congress in Cologne where a talk about KDE was given using
 
1537
KPresenter. In the future, Linus Torvalds will no longer have use
 
1538
Windows applications when giving presentations.</para>
 
1539
 
 
1540
<para>KChart is an application to create diagrams. It supports different
 
1541
modes (bars, lines, etc.) and can be embedded into other KOffice
 
1542
application without problems. When data is changed in, for example,
 
1543
KSpread, the chart automatically changes itself accordingly.</para>
 
1544
 
 
1545
<para>There is a component for displaying graphics, and work is being done
 
1546
adapting a formula editor and a vector-oriented painting application
 
1547
(KIllustrator). For the future, adaptation of KLyx is planned to embed
 
1548
Parts in LaTeX documents. Other KDE applications like KOrganizer,
 
1549
KAddressbook and KMail will be enhanced with CORBA interfaces to
 
1550
provide seamless integration in the KOffice suite.</para>
 
1551
 
 
1552
<para>If possible, components save their data in XML format. To save an
 
1553
aggregate document in a file, the MIME multi-part format is used. XML
 
1554
and MIME multi-part share the advantage that import and exports filters
 
1555
can easily be written in scripting languages like Python and
 
1556
Perl. Ever since a WinWord filter attracted attention on
 
1557
c.o.l.a. (comp.os.linux.announce), developers began writing import
 
1558
filters for the most important MS applications.</para>
 
1559
 
 
1560
<para>KOffice runs quite stably for a alpha release. To compile it, a fast
 
1561
CPU and a reasonable amount of RAM ( 64 MByte) should be available;
 
1562
for using KOffice, 32 MByte and a Pentium 133 MHz will
 
1563
suffice. KOffice is reported to work on DEC Alpha and Sun Sparcs as
 
1564
well. The sources for KOffice, KOM and OpenParts are available on
 
1565
<ulink url="http://www.kde.org">http://www.kde.org</ulink></para>
 
1566
</sect1>
 
1567
 
 
1568
<sect1 id="code-re-use-with-corba">
 
1569
<title>Code Re-use with CORBA</title>
 
1570
 
 
1571
<para>A developer, sitting in front of his editor and trying to build new
 
1572
software components out of old ones, might sadly remember the good old
 
1573
Lego pieces from his/her childhood. Those always fit together nicely,
 
1574
and from a great number of primitive elements, great buildings could be
 
1575
constructed. From the software developer's point of view, software
 
1576
pieces do not fit at all, and each new building requires a lot of work
 
1577
to make it usable. Many developers therefore choose to rewrite the
 
1578
sources rather than to re-use code.</para>
 
1579
 
 
1580
<para>Under Unix, the usual method concerning code re-use is putting code
 
1581
into libraries and linking the application against them. However,
 
1582
sometimes it happens that those libraries use different GUI toolkits,
 
1583
or that some support multi-threading and some do not. Additionally,
 
1584
all libraries should have been compiled with the same compiler,
 
1585
otherwise you will be subject to problems at the linking stage.</para>
 
1586
 
 
1587
<para>One solution is to split an application into several processes. One
 
1588
process might, for example, offer database functionality with
 
1589
multi-threading, another one might offer the X11-GUI
 
1590
single-threaded. Now, the problem of Interprocess Communication (IPC)
 
1591
remains to be solved. CORBA (Common Object Request Broker
 
1592
Architecture) offers a modern and object-oriented solution, but the
 
1593
developer is tied to the CORBA object model, what is somewhat limited
 
1594
in contrast to the C++, Python or Smalltalk object model. First of all
 
1595
one can derive only from interfaces, not from implementations. If
 
1596
there is a text editor as a CORBA object, it usually is impossible to
 
1597
derive from this editor and overload just a few of its functions. The
 
1598
derivation of implementations works only if the sources of the editor
 
1599
are available, or if it is available as a library. But that was what
 
1600
we wanted to avoid.</para>
 
1601
 
 
1602
<para>As the main article describes, the KDE Object Model (KOM) offers a
 
1603
solution for this problem; it is based on events and event
 
1604
filters. Instead of calling a function directly, it is possible to
 
1605
send an event. By filtering events, function overloading can be
 
1606
simulated.</para>
 
1607
 
 
1608
<para>There are other obstacles when re-using code: According to Murphy's
 
1609
laws, the desperately needed module is always written in a different
 
1610
programming language than expected. Mixing different languages in one
 
1611
application is always a problem for programmers. Even semi-automatic
 
1612
wrapper generators like SWIG expect a certain amount of refining from
 
1613
the programmer. Further, a look at the KDE bindings in Python, Perl
 
1614
and Tcl shows that this wrapper code can easily grow huge. As
 
1615
OpenParts is CORBA-based, objects can be implemented in any of the
 
1616
languages for which CORBA bindings are available for. For interpreter
 
1617
languages, in most cases no special wrapper code is necessary, for
 
1618
compiler languages like C/C++, wrapper code generation is done
 
1619
automatically.</para>
 
1620
</sect1>
 
1621
 
 
1622
<sect1 id="credits">
 
1623
<title>Credits</title>
 
1624
 
 
1625
<para>Most of this document was written by Torben Weis
 
1626
<ulink url="email:weis@kde.org">weis@kde.org</ulink>.
 
1627
Additions, corrections as well as the editorial work was done by
 
1628
Bernd Johannes Wuebben <ulink url="email:wuebben@kde.org">wuebben@kde.org</ulink>.</para>
 
1629
</sect1>
 
1630
</chapter>
 
1631
 
 
1632
<chapter id="komhowto">
 
1633
<title>Using KOM / OpenParts HOWTO</title>
 
1634
 
 
1635
<para>Simon Hausmann <ulink url="mailto:hausmann@kde.org">&lt;hausmann@kde.org&gt;</ulink></para>
 
1636
 
 
1637
<para>v1.0 18, June 1999</para>
 
1638
 
 
1639
<para><emphasis>This documentation is meant to help programmers who are already familiar
 
1640
with the standard Qt/KDE application framework and who are interested in using
 
1641
the KDE component technology, the KDE Object Model (KOM) and OpenParts, for
 
1642
their application.  It covers both "why" you should use KOM/OP
 
1643
and "how" to do so.</emphasis></para>
 
1644
 
 
1645
<sect1 id="introduction-2">
 
1646
<title>Introduction</title>
 
1647
 
 
1648
<para>This documentation is meant to help programmers who are already familiar with
 
1649
the standard Qt/KDE application framework and who are interested in using the
 
1650
KDE component technology, the KDE Object Model (KOM) and OpenParts, for their
 
1651
application. The goals of using components in case of standard KDE
 
1652
applications might be:</para>
 
1653
 
 
1654
<para><itemizedlist>
 
1655
<listitem>
 
1656
<para>make several modules of the application re-usable components, being
 
1657
available for other applications, not matter in what language they are
 
1658
written or on what platform/machine they're running.</para>
 
1659
</listitem>
 
1660
<listitem>
 
1661
<para>make use of OpenPart's embedding facility and its way to manage shared
 
1662
GUI elements to provide seamless graphical integration of components in
 
1663
applications.</para>
 
1664
</listitem>
 
1665
<listitem>
 
1666
<para>use CORBA and KOM as an easy way of inter-process communication</para>
 
1667
</listitem>
 
1668
</itemizedlist>
 
1669
</para>
 
1670
 
 
1671
<para>I recommend reading the
 
1672
<ulink url="http://developer.kde.org/openparts/html/openparts.html">article by Torben Weis about KOM/Openparts</ulink>
 
1673
<ulink url="mailto:weis@kde.org">Torben Weis</ulink> is the
 
1674
author/creator/master/god of KOM/OpenParts.</para>
 
1675
</sect1>
 
1676
 
 
1677
<sect1 id="the-kde-object-model-kom">
 
1678
<title>The KDE Object Model (KOM)</title>
 
1679
 
 
1680
<sect2 id="first-ways-of-communication-the-kombase-inte">
 
1681
<title>First ways of communication - the KOM::Base interface <indexterm remap="idx"><primary>KOM::Base interface</primary></indexterm></title>
 
1682
 
 
1683
<para>The Base interface and its implementation in <literal remap="tt"><indexterm remap="cdx"><primary><literal>libkom</literal></primary></indexterm>libkom</literal> provide the basic
 
1684
functionality for a standardized communication between CORBA objects using
 
1685
KOM. This includes</para>
 
1686
 
 
1687
<para><itemizedlist>
 
1688
<listitem>
 
1689
<para>signals and slots, similar to the mechanism used in the Qt toolkit</para>
 
1690
</listitem>
 
1691
<listitem>
 
1692
<para>event handling, including filtering</para>
 
1693
</listitem>
 
1694
<listitem>
 
1695
<para>relatives management</para>
 
1696
</listitem>
 
1697
<listitem>
 
1698
<para>reference counting</para>
 
1699
</listitem>
 
1700
</itemizedlist>
 
1701
</para>
 
1702
</sect2>
 
1703
 
 
1704
<sect2 id="signals-and-slots-signals-and-slots">
 
1705
<title>Signals and Slots <indexterm remap="idx"><primary>Signals and Slots</primary></indexterm></title>
 
1706
 
 
1707
<para>KOM supports signals and slots just like in the Qt toolkit, with a few
 
1708
differences in usage and implementation. The first and biggest difference is
 
1709
that signals and slots are no more typesafe again, meaning there's no moc
 
1710
compiler generating meta data for KOM signals/slots to enable type checking at
 
1711
run-time, when connecting.</para>
 
1712
 
 
1713
<para>Another difference is the way you declare signal and slot functions. Signals
 
1714
have to be declared with the <literal remap="tt"><indexterm remap="cdx"><primary><literal>SIGNAL&&lowbar;;IMPL</literal></primary></indexterm>SIGNAL&&lowbar;;IMPL</literal> macro from <literal remap="tt"><indexterm remap="cdx"><primary><literal>komBase.h</literal></primary></indexterm>komBase.h</literal>,
 
1715
without  specifying any signal arguments. Slot methods have to be defined in
 
1716
your CORBA  interface description.</para>
 
1717
 
 
1718
<para>For KOM signals the equivalent to the "emit" keyword from Qt is the
 
1719
<literal remap="tt"><indexterm remap="cdx"><primary><literal>SIGNAL&&lowbar;;CALL</literal></primary></indexterm>SIGNAL&&lowbar;;CALLx</literal> macro, were "x" is one of 0, 1, 2, depending on the
 
1720
number of arguments.
 
1721
<indexterm><primary>KOM::Base</primary></indexterm>
 
1722
Example:</para>
 
1723
 
 
1724
<para>In your CORBA interface description:
 
1725
<programlisting>  #include &&lt;;kom.idl&&gt;;
 
1726
 
 
1727
  interface FooSender : KOM::Base
 
1728
  {
 
1729
    signal void mySignal( in long foobaz );
 
1730
  };
 
1731
 
 
1732
  interface FooReceiver : KOM::Base
 
1733
  {
 
1734
    slot void mySlot( in long gosh );
 
1735
  };</programlisting>
 
1736
</para>
 
1737
 
 
1738
<para>In the implementation of FooSender:
 
1739
<programlisting>  FooSender_Impl::FooSender_Impl( ... )
 
1740
  {
 
1741
    ...
 
1742
    SIGNAL_IMPL( "mySignal" );
 
1743
    ...
 
1744
  }
 
1745
 
 
1746
  FooSender_Impl::mySignal( CORBA::Long foobaz )
 
1747
  {
 
1748
    SIGNAL_CALL1( "mySignal", foobaz );
 
1749
  }</programlisting>
 
1750
</para>
 
1751
 
 
1752
<para>In the implementation of FooReceiver:
 
1753
<programlisting>  FooReceiver_Impl::mySlot( CORBA::Long gosh )
 
1754
  {
 
1755
    ...
 
1756
  }</programlisting>
 
1757
</para>
 
1758
 
 
1759
<para>First some words about the sender: It is not required to define the signal
 
1760
in the interface description and to provide an implementation which simply
 
1761
emits the signal. However in many cases this is recommended, because this makes
 
1762
it easier for other developers to use your interface because they aren't required
 
1763
to seek in the implementation sources just to find out about the signals this
 
1764
object emits. Another way is to simply document the existence of the signal
 
1765
in the interface description, without defining a method. From the technical
 
1766
point only the <literal remap="tt"><indexterm remap="cdx"><primary><literal>SIGNAL&&lowbar;;CALL</literal></primary></indexterm>SIGNAL&&lowbar;;CALLx</literal> macro counts when emitting the signal.</para>
 
1767
 
 
1768
<para>What's left is connecting and disconnecting. In the above described example it
 
1769
could like this:
 
1770
<programlisting>  ...
 
1771
  SenderObject-&gt;connect( "mySignal", ReceiverObject, "mySlot" );
 
1772
  ...
 
1773
  SenderObject-&gt;disconnect( "mySignal", ReceiverObject", "mySlot");</programlisting>
 
1774
</para>
 
1775
 
 
1776
<para>Well, this is quite self-explaining I think. Just make sure to always disconnect
 
1777
from your object upon destruction.</para>
 
1778
</sect2>
 
1779
 
 
1780
<sect2 id="events">
 
1781
<title>Events</title>
 
1782
 
 
1783
<para>An event consists of two elements, the event name, being a string, and an
 
1784
event argument, being a CORBA::Any value and therefore freely choosable by the
 
1785
developer.</para>
 
1786
 
 
1787
<para>Events, sent to a specified object, can be imagined as being put through a
 
1788
pipe until they reach the destination object. This "pipe" is filled with
 
1789
installed  event filters. There are three kinds of filters.
 
1790
<itemizedlist>
 
1791
<listitem>
 
1792
<para>reading filters ( <literal remap="tt"><indexterm remap="cdx"><primary><literal>FM&&lowbar;;READ</literal></primary></indexterm>FM&&lowbar;;READ</literal> )</para>
 
1793
</listitem>
 
1794
<listitem>
 
1795
<para>writing filters ( <literal remap="tt"><indexterm remap="cdx"><primary><literal>FM&&lowbar;;WRITE</literal></primary></indexterm>FM&&lowbar;;WRITE</literal> )</para>
 
1796
</listitem>
 
1797
<listitem>
 
1798
<para>implementing filters ( <literal remap="tt"><indexterm remap="cdx"><primary><literal>FM&&lowbar;;IMPLEMENT</literal></primary></indexterm>FM&&lowbar;;IMPLEMENT</literal> )</para>
 
1799
</listitem>
 
1800
</itemizedlist>
 
1801
</para>
 
1802
 
 
1803
<para>In the current implementation in KOM these filter modes only specify the order
 
1804
how the event is processed. When an event is emitted it gets first filtered by
 
1805
all event filters with the filter mode <literal remap="tt"><indexterm remap="cdx"><primary><literal>FM&&lowbar;;WRITE</literal></primary></indexterm>FM&&lowbar;;WRITE</literal>, then followed by
 
1806
<literal remap="tt"><indexterm remap="cdx"><primary><literal>FM&&lowbar;;IMPLEMENT</literal></primary></indexterm>FM&&lowbar;;IMPLEMENT</literal> and finally by <literal remap="tt"><indexterm remap="cdx"><primary><literal>FM&&lowbar;;READ</literal></primary></indexterm>FM&&lowbar;;READ</literal>. Event filters have two
 
1807
possibilities what they can do with the actual event: They can just
 
1808
<emphasis remap="bf">read</emphasis> it or they can <emphasis remap="bf">discard</emphasis>  it, which means the event is
 
1809
discarded and will never receive its destination  object.</para>
 
1810
 
 
1811
<para>The actual event name has a special meaning in regard to event filters.  When
 
1812
installing an event filter to an object you have to specify, beside a
 
1813
reference to the filter object and the name of the filter mapping function, a
 
1814
sequence of so called event type patterns. An event type pattern can be the
 
1815
name of a  single event as well as a special pattern (see <literal remap="tt"><indexterm remap="cdx"><primary><literal>kom.idl</literal></primary></indexterm>kom.idl</literal> for more
 
1816
information about event type patterns) .</para>
 
1817
 
 
1818
<para>When an event is meant to be processed by a filter, the specified filter
 
1819
function gets called, with the event name and the event value as arguments.
 
1820
This filter function has to return (through a boolean value) whether the event
 
1821
should be discarded or not.</para>
 
1822
 
 
1823
<para>When all filtering is done and none of the installed filters discarded the
 
1824
event, it is finally received by the destination object, by calling the
 
1825
object's <literal remap="tt"><indexterm remap="cdx"><primary><literal>event()</literal></primary></indexterm>event()</literal> method, defined in the KOM::Base <indexterm remap="idx"><primary>KOM::Base</primary></indexterm> interface. The default
 
1826
implementation does actually nothing, so you may want to re-implement this
 
1827
virtual function.</para>
 
1828
 
 
1829
<para>The very low-level usage of events is to call the receive/receiveASync methods
 
1830
of an object for sending an event and to re-implement <indexterm remap="cdx"><primary><literal>KOMBase::event</literal></primary></indexterm>KOMBase::event for
 
1831
mapping an event. But KOM provides some nice macros which simplify the
 
1832
processing of events.</para>
 
1833
 
 
1834
<sect3 id="sending-events">
 
1835
<title>Sending Events</title>
 
1836
 
 
1837
<para>For sending komBase.h defines some useful <literal remap="tt"><indexterm remap="cdx"><primary><literal>EMIT&&lowbar;;EVENT</literal></primary></indexterm>EMIT&&lowbar;;EVENT</literal> macros, all
 
1838
using the same syntax:
 
1839
<literal remap="verb">EMIT_EVENT_x( destination_object, event_name, event_argument)</literal></para>
 
1840
 
 
1841
<para>"destination&&lowbar;;object" is a reference to the object which is meant to
 
1842
receive/process the event. The event will be filtered through all event
 
1843
filters which are installed in this destination object. "event&&lowbar;;name" is
 
1844
self-explaining ;-) . The event argument depends on the specific macro, which
 
1845
are in particular:</para>
 
1846
 
 
1847
<para><itemizedlist>
 
1848
<listitem>
 
1849
<para><literal remap="tt">EMIT&&lowbar;;EVENT</literal>, the general macro for sending. The event argument is
 
1850
required to have a <literal remap="tt">&lt;&lt;=</literal> operator for CORBA::Any defined. You
 
1851
will want to use this macro whenever the event argument is a structure
 
1852
for example. (and don't forget to compile your idl file with the "--any"
 
1853
option, so that the idl compiler generates the necessary operator
 
1854
methods)</para>
 
1855
</listitem>
 
1856
<listitem>
 
1857
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>EMIT&&lowbar;;EVENT&&lowbar;;BOOLEAN</literal></primary></indexterm>EMIT&&lowbar;;EVENT&&lowbar;;BOOLEAN</literal>, useful for boolean event arguments. The
 
1858
only difference to the <literal remap="tt">EMIT&&lowbar;;EVENT</literal> macro is that it uses
 
1859
CORBA::Any::from&&lowbar;;boolean for you to convert the boolean value. So it
 
1860
doesn't really matter whether you use:
 
1861
 
 
1862
<literal remap="verb">    EMIT_EVENT( receiver, name, CORBA::Any::from_boolean( value ) );</literal>
 
1863
or
 
1864
<literal remap="verb">    EMIT_EVENT_BOOLEAN( receiver, name, value );</literal>
 
1865
</para>
 
1866
</listitem>
 
1867
<listitem>
 
1868
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>EMIT&&lowbar;;EVENT&&lowbar;;OCTET</literal></primary></indexterm>EMIT&&lowbar;;EVENT&&lowbar;;OCTET</literal>, similar to EMIT&&lowbar;;EVENT&&lowbar;;BOOLEAN, useable for
 
1869
<indexterm remap="cdx"><primary><literal>CORBA::Octet</literal></primary></indexterm>CORBA::Octet values.</para>
 
1870
</listitem>
 
1871
<listitem>
 
1872
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>EMIT&&lowbar;;EVENT&&lowbar;;CHAR</literal></primary></indexterm>EMIT&&lowbar;;EVENT&&lowbar;;CHAR</literal>, similar to EMIT&&lowbar;;EVENT&&lowbar;;BOOLEAN, useable for char
 
1873
(<indexterm remap="cdx"><primary><literal>CORBA::Char</literal></primary></indexterm>CORBA::Char) values.</para>
 
1874
</listitem>
 
1875
<listitem>
 
1876
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>EMIT&&lowbar;;EVENT&&lowbar;;WCHAR</literal></primary></indexterm>EMIT&&lowbar;;EVENT&&lowbar;;WCHAR</literal>, similar to EMIT&&lowbar;;EVENT&&lowbar;;BOOLEAN, useable for
 
1877
<indexterm remap="cdx"><primary><literal>CORBA::WChar</literal></primary></indexterm>CORBA::WChar values.</para>
 
1878
</listitem>
 
1879
<listitem>
 
1880
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>EMIT&&lowbar;;EVENT&&lowbar;;STRING</literal></primary></indexterm>EMIT&&lowbar;;EVENT&&lowbar;;STRING</literal>, similar to EMIT&&lowbar;;EVENT&&lowbar;;BOOLEAN, useable for
 
1881
char * (<indexterm remap="cdx"><primary><literal>CORBA::Char*</literal></primary></indexterm>CORBA::Char*) values.</para>
 
1882
</listitem>
 
1883
<listitem>
 
1884
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>EMIT&&lowbar;;EVENT&&lowbar;;WSTRING</literal></primary></indexterm>EMIT&&lowbar;;EVENT&&lowbar;;WSTRING</literal>, similar to EMIT&&lowbar;;EVENT&&lowbar;;BOOLEAN, useable for
 
1885
<indexterm remap="cdx"><primary><literal>CORBA::WChar*</literal></primary></indexterm>CORBA::WChar* values.</para>
 
1886
</listitem>
 
1887
<listitem>
 
1888
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>EMIT&&lowbar;;EVENT&&lowbar;;OBJECT</literal></primary></indexterm>EMIT&&lowbar;;EVENT&&lowbar;;OBJECT</literal>, similar to EMIT&&lowbar;;EVENT&&lowbar;;BOOLEAN, useable for
 
1889
CORBA objects (<indexterm remap="cdx"><primary><literal>CORBA::Object</literal></primary></indexterm>CORBA::Object).</para>
 
1890
</listitem>
 
1891
</itemizedlist>
 
1892
</para>
 
1893
</sect3>
 
1894
 
 
1895
<sect3 id="receiving-events">
 
1896
<title>Receiving Events</title>
 
1897
 
 
1898
<para>The process of receiving events is a little bit more difficult, compared
 
1899
to sending, since we have to process all kinds of events an object can receive
 
1900
in one handler method, KOM::Base <indexterm remap="idx"><primary>KOM::Base</primary></indexterm>::event (IDL <indexterm remap="idx"><primary>IDL</primary></indexterm>) / KOMBase::event (C++) . Just
 
1901
like with sending events you can again do everything on low CORBA level, but
 
1902
why should we go the hard way? KOM again provides very nice and easy-to-use
 
1903
macros for this (defined in komBase.h) :-) . Usually all this looks like the
 
1904
following example:<indexterm><primary>KOM::Base</primary></indexterm>
 
1905
<programlisting>#include &&lt;;kom.idl&&gt;;
 
1906
 
 
1907
module MyModule
 
1908
{
 
1909
  // we say: the event argument is a string
 
1910
  const string eventFirstFoo = "MyFooEventNameOrWhateverYouNameIt";
 
1911
 
 
1912
  struct MyStruct
 
1913
  {
 
1914
    boolean kde_rules;
 
1915
  };
 
1916
 
 
1917
  const string eventSecondFoo = "Blaafooo";
 
1918
  typedef MyStruct EventSecondFoo;
 
1919
 
 
1920
  interface SomethingElse
 
1921
  {
 
1922
    //..
 
1923
  };
 
1924
 
 
1925
  const string eventThirdFoo = "KOMIsCool";
 
1926
  typedef SomethingElse EventThirdFoo;
 
1927
 
 
1928
  interface Foo : KOM::Base
 
1929
  {
 
1930
    //...
 
1931
  };
 
1932
 
 
1933
};
 
1934
 
 
1935
bool FooImpl::event( const char *event, const CORBA::Any &&amp;;value )
 
1936
{
 
1937
  EVENT_MAPPER( event, value );
 
1938
 
 
1939
  MAPPING_STRING( MyModule::eventFirstFoo, mappingFirstFoo );
 
1940
 
 
1941
  MAPPING( MyModule::eventSecondFoo, MyModule::EventSecondFoo, mappingSecondFoo );
 
1942
 
 
1943
  MAPPING( MyModule::eventThirdFoo, MyModule::EventThirdFoo_ptr, mappingThirdFoo );
 
1944
 
 
1945
  END_EVENT_MAPPER; //the macro executes "return false;" for us, to indicate that
 
1946
                    //we did not handle the event if we reach this point
 
1947
}
 
1948
 
 
1949
bool FooImpl::mappingFirstFoo( const char *myArgument )
 
1950
{
 
1951
  ...
 
1952
  //don't forget to return with a boolean value, indicating whether you sucessfully
 
1953
  //processed the event or not.
 
1954
}
 
1955
 
 
1956
bool FooImpl::mappingSecondFoo( MyModule::MyString anotherArg )
 
1957
{
 
1958
  //...
 
1959
}
 
1960
 
 
1961
bool FooImpl::mappingThirdFoo( MyModule::SomethingElse_ptr whaaboo )
 
1962
{
 
1963
  //...
 
1964
}
 
1965
</programlisting>
 
1966
</para>
 
1967
 
 
1968
<para>As you can see an event handler usually begins with the <literal remap="tt">EVENT&&lowbar;;MAPPER</literal>
 
1969
macro and ends with <literal remap="tt">END&&lowbar;;EVENT&&lowbar;;MAPPER</literal> . Similar to the
 
1970
<literal remap="tt">EMIT&&lowbar;;EVENT&&lowbar;;x</literal> macros, the <literal remap="tt">MAPPING</literal> macros consist of a general
 
1971
<literal remap="tt">MAPPING</literal> macro and the following friends:
 
1972
<itemizedlist>
 
1973
<listitem>
 
1974
<para><literal remap="tt">MAPPING&&lowbar;;BOOLEAN</literal></para>
 
1975
</listitem>
 
1976
<listitem>
 
1977
<para><literal remap="tt">MAPPING&&lowbar;;OCTET</literal></para>
 
1978
</listitem>
 
1979
<listitem>
 
1980
<para><literal remap="tt">MAPPING&&lowbar;;CHAR</literal></para>
 
1981
</listitem>
 
1982
<listitem>
 
1983
<para><literal remap="tt">MAPPING&&lowbar;;WCHAR</literal></para>
 
1984
</listitem>
 
1985
<listitem>
 
1986
<para><literal remap="tt">MAPPING&&lowbar;;STRING</literal></para>
 
1987
</listitem>
 
1988
<listitem>
 
1989
<para><literal remap="tt">MAPPING&&lowbar;;WSTRING</literal></para>
 
1990
</listitem>
 
1991
<listitem>
 
1992
<para><literal remap="tt">MAPPING&&lowbar;;OBJECT</literal></para>
 
1993
</listitem>
 
1994
</itemizedlist>
 
1995
</para>
 
1996
 
 
1997
<para>In order to structurize the process of event handling a little bit, every
 
1998
event  gets its own event handling function. These functions are called by the
 
1999
mapping  macros (last argument) . The above used naming scheme is not a
 
2000
requirement,  however it is used in most applications using KOM.</para>
 
2001
</sect3>
 
2002
</sect2>
 
2003
 
 
2004
<sect2 id="adopting">
 
2005
<title>Adopting</title>
 
2006
 
 
2007
<para>You should use adopting whenever you want to hold a reference to an object and
 
2008
want to be informed when the object dies in order to free all your references
 
2009
to this object. But this should only be used when you're not the parent
 
2010
object, meaning you didn't reference the object directly via the KOM reference
 
2011
counter.  When using adopting you should re-implement the <literal remap="tt">leaveNotify</literal>
 
2012
(and perhaps <literal remap="tt">adoptNotify</literal>) methods of your  object (and don't forget
 
2013
to call the original KOMBase method!) .</para>
 
2014
</sect2>
 
2015
 
 
2016
<sect2 id="kom-referencing">
 
2017
<title>KOM referencing</title>
 
2018
 
 
2019
<para>KOM reference counting should be used to "express" that you possess the
 
2020
object. This gives you direct control over the lifecycle of the object by
 
2021
letting the reference counter act directly on the server object, in contrary
 
2022
to CORBA reference counting, where the reference counter only acts on the stub
 
2023
object, in case of remote objects (this is different for local objects, where
 
2024
stub = server object) . When the KOM reference counter drops down to zero the
 
2025
object gets destroyed. This destruction is done by calling <literal remap="tt">cleanUp()</literal>,
 
2026
which closes all connections to other objects and leaves all relatives.  After
 
2027
this call is finished the object truly gets released. You might want to
 
2028
re-implement the <literal remap="tt">cleanUp()</literal> method. In this case make sure that you
 
2029
don't forget two things:</para>
 
2030
 
 
2031
<para><itemizedlist>
 
2032
<listitem>
 
2033
<para>only execute if the boolean variable <literal remap="tt">m&&lowbar;;bIsClean</literal> is false,
 
2034
otherwise simply return</para>
 
2035
</listitem>
 
2036
<listitem>
 
2037
<para>make sure you call the previous implementation!</para>
 
2038
</listitem>
 
2039
</itemizedlist>
 
2040
</para>
 
2041
 
 
2042
<para>As a short summary to this KOM reference stuff just keep in mind, that
 
2043
there are three ways to hold a reference to an object:
 
2044
<itemizedlist>
 
2045
<listitem>
 
2046
<para>you're connected to the object via signals/slots or via event filters</para>
 
2047
</listitem>
 
2048
<listitem>
 
2049
<para>you're the parent object, meaning you hold a reference through the KOM
 
2050
reference counter</para>
 
2051
</listitem>
 
2052
<listitem>
 
2053
<para>otherwise you should use adopting to get informed whenever the object wants
 
2054
to die, in order to free all references to the object which are not of
 
2055
one of the above kinds. The idea behind all this is that all
 
2056
connections/references between objects are symmetric, meaning
 
2057
<emphasis remap="bf">both</emphasis> sides know about the connection and <emphasis remap="bf">both</emphasis> sides
 
2058
clean up all connections between each other whenever one of the two
 
2059
objects wants to die. In case of signal/slot connections this is done
 
2060
automatically by KOM. In case of KOM reference counters you have the
 
2061
direct control over the lifecylcle for the object. Adopting, as third
 
2062
way, can be used to keep other connections symmetric, connections which
 
2063
are neither signal/slot connections nor direct references via the KOM
 
2064
reference counter.</para>
 
2065
</listitem>
 
2066
</itemizedlist>
 
2067
</para>
 
2068
 
 
2069
<para>Hint: Using the <literal remap="tt">KOMVar</literal> template makes handling KOM references much
 
2070
easier, they can be used similar to the CORBA &&lowbar;;var types.</para>
 
2071
</sect2>
 
2072
 
 
2073
<sect2 id="the-component-the-komcomponent-komcomponent-">
 
2074
<title>THE component - the KOM::Component <indexterm remap="idx"><primary>KOM::Component</primary></indexterm> interface</title>
 
2075
 
 
2076
<para>The Component interface, being derived from the Base interface, additionally
 
2077
provides a kind of small interface repository for only this component,
 
2078
combined with the possibility to provide new interfaces by dynamic aggregation
 
2079
and a standard way to add plugin components. This gives CORBA objects the
 
2080
possibility to enhance their functionality at run-time.</para>
 
2081
 
 
2082
<para>There are five kinds of interfaces:
 
2083
<itemizedlist>
 
2084
<listitem>
 
2085
<para>Builtin Interfaces (derived Interfaces)</para>
 
2086
</listitem>
 
2087
<listitem>
 
2088
<para>Builtin Aggregate Interfaces</para>
 
2089
</listitem>
 
2090
<listitem>
 
2091
<para>Dynamic Aggregate Interfaces</para>
 
2092
</listitem>
 
2093
<listitem>
 
2094
<para>Builtin Plugin Interfaces</para>
 
2095
</listitem>
 
2096
<listitem>
 
2097
<para>Dynamic Plugin Interfaces</para>
 
2098
</listitem>
 
2099
</itemizedlist>
 
2100
</para>
 
2101
 
 
2102
<para>Builtin interfaces are all interfaces the object directly implements. This
 
2103
means they are part of the actual object implementation and can be specified
 
2104
via the <literal remap="tt"><indexterm remap="cdx"><primary><literal>ADD&&lowbar;;INTERFACE</literal></primary></indexterm>ADD&&lowbar;;INTERFACE</literal> macro (in <indexterm remap="cdx"><primary><literal>komComponent.h</literal></primary></indexterm>komComponent.h) . So for example if
 
2105
your interface description looks like this:
 
2106
<programlisting>module Foo
 
2107
{
 
2108
  interface MyInterface : AnotherInterface
 
2109
  {
 
2110
    ...
 
2111
  };
 
2112
};</programlisting>
 
2113
</para>
 
2114
 
 
2115
<para>You should add the following line into the constructor of an implementation of
 
2116
this interface:
 
2117
<indexterm><primary>IDL</primary></indexterm>
 
2118
<programlisting>ConstructorNameOfMyInterface::ConstructorNameOfMyInterface( ... )
 
2119
{
 
2120
  ...
 
2121
  ADD_INTERFACE( "IDL:Foo/MyInterface:1.0" );
 
2122
  ...
 
2123
}</programlisting>
 
2124
</para>
 
2125
 
 
2126
<para>This way you tell your component that it supports the interface
 
2127
"Foo/Interface" and therefore makes it available through the three functions
 
2128
<literal remap="tt">getInterface()</literal>, <literal remap="tt">interfaces()</literal> and
 
2129
<literal remap="tt">supportsInterface()</literal> .</para>
 
2130
</sect2>
 
2131
 
 
2132
<sect2 id="extend-your-component-by-aggregation-komaggr">
 
2133
<title>Extend your component by aggregation - KOM::Aggregate <indexterm remap="idx"><primary>KOM::Aggregate</primary></indexterm></title>
 
2134
 
 
2135
<para>Aggregates solve a problem with distributed objects, the problem of
 
2136
derivation.  Since the implementation of an interface is completely
 
2137
encapsulated there has to be another way to extend the functionality of an
 
2138
already existing  object.  By using aggregate components you can add new
 
2139
interfaces to an object,  at run-time. This means you extend the functionality
 
2140
but you do not change the behaviour of the object itself.</para>
 
2141
 
 
2142
<sect3 id="builtin-aggregates">
 
2143
<title>Builtin Aggregates</title>
 
2144
 
 
2145
<para>Builtin aggregate interfaces are the interfaces of aggregate implementations
 
2146
which run in the same process as our component. See in komComponent.h the four
 
2147
functions of the <literal remap="tt"><indexterm remap="cdx"><primary><literal>KOMComponent</literal></primary></indexterm>KOMComponent</literal> class for adding builtin aggregates,  it's easy.</para>
 
2148
</sect3>
 
2149
 
 
2150
<sect3 id="dynamic-aggregates">
 
2151
<title>Dynamic Aggregates</title>
 
2152
 
 
2153
<para>Dynamic aggregates are similar to builtin aggregates, with two differences:</para>
 
2154
 
 
2155
<para><itemizedlist>
 
2156
<listitem>
 
2157
<para>They can (are) be installed from "outside" of the component,
 
2158
using  AggregateFactories (see kom.idl <indexterm remap="idx"><primary>kom.idl</primary></indexterm>) . This way they do neither have
 
2159
to run  within the same process nor on the same computer.</para>
 
2160
</listitem>
 
2161
<listitem>
 
2162
<para>They can depend on other available interfaces. KOM does the job of resolving
 
2163
these dependencies for you.</para>
 
2164
</listitem>
 
2165
</itemizedlist>
 
2166
</para>
 
2167
</sect3>
 
2168
</sect2>
 
2169
 
 
2170
<sect2 id="plugins-the-komplugin-komplugin-interface">
 
2171
<title>Plugins - the KOM::Plugin <indexterm remap="idx"><primary>KOM::Plugin</primary></indexterm> interface</title>
 
2172
 
 
2173
<para>Plugins are the kind of counterpart to aggregates. They do not extend the
 
2174
functionality of an object by providing new interfaces, but instead usually
 
2175
change the behaviour of it, by
 
2176
<orderedlist><listitem>
 
2177
<para>doing things like installing event filters to the object, etc.</para>
 
2178
</listitem>
 
2179
<listitem>
 
2180
<para>providing special plugin interfaces</para>
 
2181
</listitem>
 
2182
</orderedlist>
 
2183
</para>
 
2184
</sect2>
 
2185
 
 
2186
<sect2 id="collect-your-components-the-komcontainer-kom">
 
2187
<title>Collect your components - the KOM::Container <indexterm remap="idx"><primary>KOM::Container</primary></indexterm> interface</title>
 
2188
 
 
2189
<para>Containers do something simple but extremly useful: They act as repository for
 
2190
Container members. A container member structure consists of two elements:</para>
 
2191
 
 
2192
<para><itemizedlist>
 
2193
<listitem>
 
2194
<para>the member name, a freely chooseable and unique string identifier</para>
 
2195
</listitem>
 
2196
<listitem>
 
2197
<para>the member object, a KOM::Base <indexterm remap="idx"><primary>KOM::Base</primary></indexterm> type You can add, remove, replace, list
 
2198
and lookup container members or just clear  the whole container. In
 
2199
addition the container emits signals whenever a  member has been added
 
2200
or removed.</para>
 
2201
</listitem>
 
2202
</itemizedlist>
 
2203
</para>
 
2204
</sect2>
 
2205
 
 
2206
<sect2 id="factories">
 
2207
<title>Factories</title>
 
2208
 
 
2209
<para>KOM contains two abstract factory interfaces:
 
2210
<orderedlist><listitem>
 
2211
<para>KOM::AggregateFactory <indexterm remap="idx"><primary>KOM::AggregateFactory</primary></indexterm></para>
 
2212
</listitem>
 
2213
<listitem>
 
2214
<para>KOM::PluginFactory <indexterm remap="idx"><primary>KOM::PluginFactory</primary></indexterm></para>
 
2215
</listitem>
 
2216
</orderedlist>
 
2217
</para>
 
2218
 
 
2219
<para>They both serve the job of creating objects and are needed for the creation of
 
2220
dynamic plugin and aggregate components. Whenever you want to install a such a
 
2221
dynamically created object to a component you have to provide an
 
2222
implementation of a factory interface.</para>
 
2223
</sect2>
 
2224
 
 
2225
<sect2 id="komapplication-komapplication">
 
2226
<title>KOMApplication <indexterm remap="idx"><primary>KOMApplication</primary></indexterm></title>
 
2227
 
 
2228
<para>KOMApplication <indexterm remap="idx"><primary>KOMApplication</primary></indexterm> is the drop-in replacement for KApplication <indexterm remap="idx"><primary>KApplication</primary></indexterm>, required when
 
2229
using CORBA in your KDE Application. It, internally, combines CORBA event
 
2230
handling with Qt event handling and initializes the ORB <indexterm remap="idx"><primary>ORB</primary></indexterm> and the BOA <indexterm remap="idx"><primary>BOA</primary></indexterm> on
 
2231
startup.  komApplication.h defines two smart macros to get a reference to the
 
2232
ORB/BOA: <literal remap="tt">komapp&&lowbar;;orb</literal> and <literal remap="tt">komapp&&lowbar;;boa</literal> . Usually you will want
 
2233
to use your own application class, derived from KOMApplication, and
 
2234
re-implement <literal remap="tt">start()</literal> and/or <literal remap="tt">restore()</literal> , which will be called
 
2235
&gt;from <literal remap="tt"><indexterm remap="cdx"><primary><literal>KOMApplication::exec()</literal></primary></indexterm>KOMApplication::exec()</literal>, depending on the BOA's state about
 
2236
restoring objects. For further information about KOMApplication's API see
 
2237
<indexterm remap="cdx"><primary><literal>komApplication.h</literal></primary></indexterm>komApplication.h .</para>
 
2238
</sect2>
 
2239
</sect1>
 
2240
 
 
2241
<sect1 id="openparts">
 
2242
<title>OpenParts</title>
 
2243
 
 
2244
<sect2 id="introduction-3">
 
2245
<title>Introduction</title>
 
2246
 
 
2247
<para>The goals of the OpenParts technology, based upon KOM, are:
 
2248
<itemizedlist>
 
2249
<listitem>
 
2250
<para>provide an easy way to graphically embed other application's "widgets"</para>
 
2251
</listitem>
 
2252
<listitem>
 
2253
<para>provide an clever way to manage shared GUI elements and provide a CORBA/KOM
 
2254
interface/implementation of these</para>
 
2255
</listitem>
 
2256
<listitem>
 
2257
<para>implement the basic support for the document view model</para>
 
2258
</listitem>
 
2259
</itemizedlist>
 
2260
</para>
 
2261
 
 
2262
<para>To simplify the act of understanding OpenParts I will give a short example
 
2263
situation:</para>
 
2264
 
 
2265
<para>Imagine you have an a word processor and a formula editor, both being separate
 
2266
applications. If you now want to insert a formula into your word processor
 
2267
document by using your formula editor application this arises several
 
2268
problems: You can of course embed the formula editor's main widget window via
 
2269
swallowing by using XReparentWindow and friends, or easier by using QXEmbed.
 
2270
But then how do you want to edit your formula without having access to the
 
2271
formula editor's menubar / toolbar? In any way it would look ugly if these are
 
2272
part of the formula window. Wouldn't it be nice if the menus / toolbars of
 
2273
your word processor application would get replaced by the formula editor ones,
 
2274
except for some general menu /toolbar items? And when you go back to your text
 
2275
document the old menus / toolbars come back again.</para>
 
2276
 
 
2277
<para>Well, this is a perfect job for OpenParts :-) .</para>
 
2278
 
 
2279
<para>OpenParts solves the above described problem by introducing a new sytem of
 
2280
visual components and a new way of creating shared GUI elements, such as menus
 
2281
or toolbars, dynamically on demand.</para>
 
2282
 
 
2283
<para>In the implementation of OpenParts every element consists usually of two
 
2284
classes, the interface implementation, where the class name ends with "If",
 
2285
and the Qt/KDE object. So for example the OpenParts StatusBar element is
 
2286
represented by two classes: <literal remap="tt"><indexterm remap="cdx"><primary><literal>OPStatusBar</literal></primary></indexterm>OPStatusBar</literal>, being derived from
 
2287
<indexterm remap="cdx"><primary><literal>KStatusBar</literal></primary></indexterm>KStatusBar,  handles the Qt/KDE specific extensions, and
 
2288
<literal remap="tt"><indexterm remap="cdx"><primary><literal>OPStatusBarIf</literal></primary></indexterm>OPStatusBarIf</literal> which is  responsible for providing an implementation
 
2289
of the actual <indexterm remap="cdx"><primary><literal>OpenPartsUI::StatusBar</literal></primary></indexterm>OpenPartsUI::StatusBar  interface by "translating" the interface
 
2290
functionality into Qt/KDE function  calls.</para>
 
2291
 
 
2292
<para>Since every Qt/KDE object in OpenParts is most often bound to such an
 
2293
interface, like described above, there is usually an interface() function
 
2294
which returns a reference to the OpenParts interface of the element. In case
 
2295
of the above example <literal remap="tt"><indexterm remap="cdx"><primary><literal>OPStatusBar::interface()</literal></primary></indexterm>OPStatusBar::interface()</literal> returns a reference to
 
2296
an <literal remap="tt"><indexterm remap="cdx"><primary><literal>OPStatusBarIf</literal></primary></indexterm>OPStatusBarIf</literal> object which is directly bound to this
 
2297
<literal remap="tt"><indexterm remap="cdx"><primary><literal>OPStatusBar</literal></primary></indexterm>OPStatusBar</literal> object.</para>
 
2298
</sect2>
 
2299
 
 
2300
<sect2 id="opapplication-opapplication">
 
2301
<title>OPApplication <indexterm remap="idx"><primary>OPApplication</primary></indexterm></title>
 
2302
 
 
2303
<para>Similar to <indexterm remap="cdx"><primary><literal>KOMApplication</literal></primary></indexterm>KOMApplication, the class <indexterm remap="cdx"><primary><literal>OPApplication</literal></primary></indexterm>OPApplication (derived from
 
2304
KOMApplication) is required when using OpenParts.</para>
 
2305
</sect2>
 
2306
 
 
2307
<sect2 id="qwidgetqwidget-as-component-the-openpartspar">
 
2308
<title><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget as Component? - the OpenParts::Part interface</title>
 
2309
 
 
2310
<para>In OpenParts every window which has its own GUI and which is meant to be
 
2311
displayed in a MainWindow is called a Part (just like the formula editor view
 
2312
or the word processor document view in the above described example) , and
 
2313
implements the <indexterm remap="cdx"><primary><literal>OpenParts::Part</literal></primary></indexterm>OpenParts::Part interface by deriving from the class
 
2314
<literal remap="tt">OPPartIf</literal>.</para>
 
2315
 
 
2316
<para>If you want to make a widget class a full-featured Part component then you
 
2317
have to handle some things different than you might be used to, in regard to
 
2318
the standard Qt/KDE widget framework. In fact now a widget is no more a simple
 
2319
window in which you display some data, no, a Part is much more than this. In
 
2320
particular a Part has, beside it's window (widget, which may of course contain
 
2321
sub-windows or even other Parts (see <literal remap="tt"><indexterm remap="cdx"><primary><literal>OPFrame</literal></primary></indexterm>OPFrame</literal> documentation) ) a
 
2322
full-featured GUI, consisting of a menubar with menus, toolbar(s) and a
 
2323
statusbar.</para>
 
2324
 
 
2325
<para>The special thing with the GUI is the way it is created, handled/used and
 
2326
"destroyed" . All this has to be highly dynamic because now the user decides
 
2327
about which Part he wants to have active. OpenParts provides the basic
 
2328
framework for this:
 
2329
<itemizedlist>
 
2330
<listitem>
 
2331
<para>it tells you when you have to create your GUI and provides you the necessary
 
2332
references to the GUI related objects of OpenParts.</para>
 
2333
</listitem>
 
2334
<listitem>
 
2335
<para>it also tells you when the GUI is destructed.</para>
 
2336
</listitem>
 
2337
<listitem>
 
2338
<para>in addition you are notified when your Part gets the focus and gives you
 
2339
the choice whether to accept or reject the focus.</para>
 
2340
</listitem>
 
2341
<listitem>
 
2342
<para>you are also notified when your Part gets registered to a MainWindow, in
 
2343
order to register your component at several GUI servant objects, just
 
2344
like the menubar manager for example.</para>
 
2345
</listitem>
 
2346
</itemizedlist>
 
2347
</para>
 
2348
 
 
2349
<para>The very first step you have to make is to tell the OpenParts Part Interface
 
2350
(<literal remap="tt"><indexterm remap="cdx"><primary><literal>OPPartIf</literal></primary></indexterm>OPPartIf</literal>) , the class you have to inherit from, what the actual
 
2351
widget is, because <literal remap="tt"><indexterm remap="cdx"><primary><literal>OPartIf</literal></primary></indexterm>OPartIf</literal> does not inherit from QWidget. This gives
 
2352
you the  flexibility to separate your Part component from your actualy widget,
 
2353
but you  don't have to do this. You can simply multiply inherit from
 
2354
<literal remap="tt">OPPartIf</literal> and <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal> or the appropriate widget class. In any way you
 
2355
specify your Part  widget by calling <literal remap="tt">setWidget( your&&lowbar;;widget&&lowbar;;here )</literal> .
 
2356
In most cases, when  the Part component is the widget at the same time, you
 
2357
simply call <literal remap="tt">setWidget( this )</literal> :-) . Make sure this call is done in
 
2358
the constructor of your class!</para>
 
2359
 
 
2360
<para>The next important point is that you will want to re-implement the virtual
 
2361
<literal remap="tt">init()</literal> function of <literal remap="tt"><indexterm remap="cdx"><primary><literal>OPPartIf</literal></primary></indexterm>OPPartIf</literal> . This is highly recommended
 
2362
since this function is called after your Part got registered by a MainWindow.
 
2363
The idea  behind this function is that at the time the constructor of a Part
 
2364
gets executed, the Part itself is definitely not registered to a MainWindow,
 
2365
yet. But in fact you need to know when your Part gets registered, in order to
 
2366
register your Part at the GUI servant objects, which are only available via
 
2367
the MainWindow's interface. A reference to the MainWindow is available through
 
2368
the <literal remap="tt"><indexterm remap="cdx"><primary><literal>m&&lowbar;;vMainWindow</literal></primary></indexterm>m&&lowbar;;vMainWindow</literal> variable, which will be automatically initialized
 
2369
when the MainWindow  registration is done, so don't use this variable before
 
2370
your <literal remap="tt">init()</literal> function gets called (<literal remap="tt">m&&lowbar;;vMainWindow</literal> will be nil
 
2371
anyway) .</para>
 
2372
 
 
2373
<para>Now over to the details of the <literal remap="tt"><indexterm remap="cdx"><primary><literal>init()</literal></primary></indexterm>init()</literal> function. Here you should place
 
2374
all initialisation stuff which depends on being registered to a MainWindow.
 
2375
In addition you can do the above mentioned registration at the GUI managing
 
2376
objects. Usually this looks like the following example:
 
2377
<programlisting>void MyPart::init()
 
2378
{
 
2379
  //register at the menubar manager if you want to use/display a menubar
 
2380
  OpenParts::MenuBarManager_var menuBarManager = m_vMainWindow-&gt;menuBarManager();
 
2381
  if ( !CORBA::is_nil( menuBarManager ) ) //check whether the shell window allows us to have a menubar
 
2382
    menuBarManager-&gt;registerClient( id(), this ); //see chapter about the
 
2383
              //*barManager objects
 
2384
              //for further explanations
 
2385
 
 
2386
  //...the same with the toolbar
 
2387
  OpenParts::ToolBarManager_var toolBarManager = m_vMainWindow-&gt;toolBarManager();
 
2388
  if ( !CORBA::is_nil( toolBarManager ) )
 
2389
    toolBarManager-&gt;registerClient( id(), this );
 
2390
 
 
2391
  //better define a class wide variable, of course
 
2392
  OpenPartsUI::StatusBar_var m_vMyStatusBar;
 
2393
 
 
2394
  OpenParts::StatusBarManager_var statusBarManager = m_vMainWindow-&gt;statusBarManager();
 
2395
  if ( !CORBA::is_nil( statusBarManager ) )
 
2396
    m_vMyStatusBar = statusBarManager-&gt;registerClient( id() );
 
2397
}</programlisting>
 
2398
</para>
 
2399
 
 
2400
<para>Note that the registration calls for these three GUI element types are only
 
2401
necessary if you really want to use them. For example if your Part does not
 
2402
want to display any toolbar you should leave out the corresponding call.  In
 
2403
addition you might come up with the situation that for example the
 
2404
<literal remap="tt"><indexterm remap="cdx"><primary><literal>toolBarManager()</literal></primary></indexterm>toolBarManager()</literal> call returns a nil reference, which indicates that
 
2405
the MainWindow does not allow its Parts to have a toolbar. Obviously the same
 
2406
applies for the menubar and the statusbar.</para>
 
2407
 
 
2408
<para>OpenParts makes use of KOM events to tell a Part about the
 
2409
construction/destruction of it's GUI. These are in particular:
 
2410
<itemizedlist>
 
2411
<listitem>
 
2412
<para><literal remap="tt">OpenPartsUI::eventCreateMenuBar</literal> ("OpenPartsUI/CreateMenuBar")</para>
 
2413
</listitem>
 
2414
</itemizedlist>
 
2415
 
 
2416
The attached argument is a <literal remap="tt">OpenPartsUI::MenuBar</literal></para>
 
2417
 
 
2418
<para><itemizedlist>
 
2419
<listitem>
 
2420
<para><literal remap="tt">OpenPartsUI::eventCreateToolBar</literal> ("OpenPartsUI/CreateToolBar")</para>
 
2421
</listitem>
 
2422
</itemizedlist>
 
2423
 
 
2424
The attached argument is a <literal remap="tt">OpenPartsUI::ToolBarFactory</literal></para>
 
2425
 
 
2426
<para>Depending on whether a Part wants to display a menubar and/or toolbar, the
 
2427
managing objects emit these two events to it. In regard to your implementation
 
2428
this means that you have to re-implement the <literal remap="tt"><indexterm remap="cdx"><primary><literal>event()</literal></primary></indexterm>event()</literal> function
 
2429
(remember: A Part is a full-featured KOM Component) .</para>
 
2430
 
 
2431
<para>The attached event arguments indicate whether the toolbar(s) or the menubar
 
2432
are to be created or cleared. Check these arguments against
 
2433
<literal remap="tt">CORBA::is&&lowbar;;nil()</literal> and you know :-) .</para>
 
2434
 
 
2435
<para>The OpenParts StatusBar is handled different compared to the
 
2436
MenuBar/ToolBar(s) . In fact it is easier: When registering at the OpenParts
 
2437
StatusBarManager you receive your <literal remap="tt"><indexterm remap="cdx"><primary><literal>OpenParts::StatusBar</literal></primary></indexterm>OpenParts::StatusBar</literal> as return
 
2438
value. You can then use the StatusBar everywhere in your Part, independend
 
2439
from whether it is visible (active) or not.</para>
 
2440
 
 
2441
<para>In the <literal remap="tt"><indexterm remap="cdx"><primary><literal>init()</literal></primary></indexterm>init()</literal> function a lot of registration stuff is done, and
 
2442
corresponding to this in the <literal remap="tt"><indexterm remap="cdx"><primary><literal>cleanUp()</literal></primary></indexterm>cleanUp()</literal> function (see chapter about
 
2443
KOM::Base <indexterm remap="idx"><primary>KOM::Base</primary></indexterm>) you have to unregister from the GUI servant objects and free all
 
2444
appropriate references, following KOM's model of symmetric references and
 
2445
connections. Usually the code looks like this:
 
2446
<programlisting>void MyPart::cleanUp()
 
2447
{
 
2448
  if ( m_bIsClean )
 
2449
    return;
 
2450
 
 
2451
  //unregister our menubar
 
2452
  OpenParts::MenuBarManager_var menuBarManager = m_vMainWindow-&gt;menuBarManager();
 
2453
  if ( !CORBA::is_nil( menuBarManager ) )
 
2454
    menuBarManager-&gt;unregisterClient( id() );
 
2455
 
 
2456
  //...the same with the toolbar
 
2457
  OpenParts::ToolBarManager_var toolBarManager = m_vMainWindow-&gt;toolBarManager();
 
2458
  if ( !CORBA::is_nil( toolBarManager ) )
 
2459
    toolBarManager-&gt;unregisterClient( id() );
 
2460
 
 
2461
  OpenParts::StatusBarManager_var statusBarManager = m_vMainWindow-&gt;statusBarManager();
 
2462
  if ( !CORBA::is_nil( statusBarManager ) )
 
2463
    statusBarManager-&gt;unregisterClient( id() );
 
2464
 
 
2465
  //free other references here
 
2466
  //...
 
2467
 
 
2468
  //this is IMPORTANT!!!
 
2469
  //Always call the cleanUp() method of the base class when you're done!
 
2470
  OPPartIf::cleanUp();
 
2471
}</programlisting>
 
2472
</para>
 
2473
</sect2>
 
2474
 
 
2475
<sect2 id="part-children">
 
2476
<title>Part Children</title>
 
2477
 
 
2478
<para>A Part Child is a usual Part with three extra features:
 
2479
<orderedlist><listitem>
 
2480
<para>A Part Child has a Parent Part assigned.</para>
 
2481
</listitem>
 
2482
<listitem>
 
2483
<para>It does not have a GUI and it therefore does not receive any GUI creation
 
2484
events.</para>
 
2485
</listitem>
 
2486
<listitem>
 
2487
<para>The Parent Child receives events whenever there are any child related focus
 
2488
changes. Since the Part Child functionality is integrated in the
 
2489
<literal remap="tt"><indexterm remap="cdx"><primary><literal>OpenParts::Part</literal></primary></indexterm>OpenParts::Part</literal> interface and it's implementation,
 
2490
<literal remap="tt"><indexterm remap="cdx"><primary><literal>OPPartIf</literal></primary></indexterm>OPPartIf</literal>, you don't have to deal  with additional classes when
 
2491
using Child Parts. Simply leave out the mapping of the OpenParts GUI
 
2492
events in the Child Part and instead map the Child Part events described
 
2493
below and assign the Parent Part via <literal remap="tt"><indexterm remap="cdx"><primary><literal>setParent()</literal></primary></indexterm>setParent()</literal>. See the
 
2494
interface description of <literal remap="tt"><indexterm remap="cdx"><primary><literal>OpenParts::Part</literal></primary></indexterm>OpenParts::Part</literal> , in <indexterm remap="cdx"><primary><literal>openparts.idl</literal></primary></indexterm>openparts.idl,
 
2495
for further information about the events and the API in general.</para>
 
2496
</listitem>
 
2497
</orderedlist>
 
2498
</para>
 
2499
</sect2>
 
2500
 
 
2501
<sect2 id="how-to-embed-a-part-the-opframeopframe-class">
 
2502
<title>How to embed a Part - the <indexterm remap="cdx"><primary><literal>OPFrame</literal></primary></indexterm>OPFrame class</title>
 
2503
 
 
2504
<para>Now that you know how to create full-featured Part components it is still
 
2505
unexplained how Parts are really displayed/shown. Since Parts are no simple
 
2506
QWidgets but CORBA objects we need a helping hand here, which is the
 
2507
<literal remap="tt">OPFrame</literal> class. In fact <literal remap="tt"><indexterm remap="cdx"><primary><literal>OPFrame</literal></primary></indexterm>OPFrame</literal> is a <indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget, but in
 
2508
conjuction with Qt's <indexterm remap="cdx"><primary><literal>QXEmbed</literal></primary></indexterm>QXEmbed it embeds the Part's widget window. The usage of
 
2509
<literal remap="tt">OPFrame</literal> is really easy, usually the code looks like this:</para>
 
2510
 
 
2511
<para><programlisting>... somewhere in an application's widget ...
 
2512
myFrame = new OPFrame( the_parent_widget );
 
2513
myFrame-&gt;attach( a_reference_to_the_part_we_want_to_embed );
 
2514
myFrame-&gt;show();</programlisting>
 
2515
</para>
 
2516
 
 
2517
<para>In addition to the above example you can <literal remap="tt"><indexterm remap="cdx"><primary><literal>detach()</literal></primary></indexterm>detach()</literal> your Part, which
 
2518
you should usually do on exit. Just have a look at <indexterm remap="cdx"><primary><literal>opFrame.h</literal></primary></indexterm>opFrame.h, it is
 
2519
documented.</para>
 
2520
 
 
2521
<para>One last important thing you have to know about <literal remap="tt"><indexterm remap="cdx"><primary><literal>OPFrame</literal></primary></indexterm>OPFrame</literal> is that this
 
2522
class internally uses KOM referencing (using a <literal remap="tt">KOMVar</literal> variable) to
 
2523
hold the Part.  This means that there are two possible situations when using
 
2524
<literal remap="tt">OPFrame</literal> :</para>
 
2525
 
 
2526
<para><itemizedlist>
 
2527
<listitem>
 
2528
<para>If the embedding Widget/Object uses KOM referencing as well to keep a
 
2529
reference to the Part then there are two objects influencing the Part's
 
2530
lifecycle. On the one hand there's the <literal remap="tt">OPFrame</literal> which
 
2531
increases/decreases the Part's KOM reference counter when it gets
 
2532
attached/detached, and on the other hand there's the embedding
 
2533
Widget/Object. So make sure that you know when you free your KOM
 
2534
reference to the Part in regard to detaching the Part!</para>
 
2535
</listitem>
 
2536
<listitem>
 
2537
<para>If the embedding Widget/Object does not use KOM referencing then you have
 
2538
to know that when detaching the Part it automatically gets destroyed,
 
2539
since usually the <literal remap="tt">OPFrame</literal> is the only object holding a KOM
 
2540
reference  to the Part and the KOM reference counter therefore drops
 
2541
down to zero and issues the complete destruction of the object.</para>
 
2542
</listitem>
 
2543
</itemizedlist>
 
2544
</para>
 
2545
</sect2>
 
2546
 
 
2547
<sect2 id="the-center-of-openparts-the-openpartsmainwin">
 
2548
<title>The center of OpenParts - the OpenParts::MainWindow interface</title>
 
2549
 
 
2550
<para>Another important component is the so called <indexterm remap="cdx"><primary><literal>OpenParts::MainWindow</literal></primary></indexterm>OpenParts::MainWindow, being
 
2551
derived from a <indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow in the implementation (and therefore the top-level
 
2552
window of your application) and being the shell around visible sub-windows and
 
2553
shared GUI elements.</para>
 
2554
 
 
2555
<para>The MainWindow's functionality is extended by some builtin aggregates, the
 
2556
managing objects for the menu-/tool-/statusbar. These objects are either
 
2557
available directly via the <literal remap="tt">*barManager()</literal> methods of the MainWindow's
 
2558
interface or indirectly by being aggregates and therefore available via the
 
2559
components interface repository (<literal remap="tt"><indexterm remap="cdx"><primary><literal>getInterface()</literal></primary></indexterm>getInterface()</literal>,
 
2560
<literal remap="tt"><indexterm remap="cdx"><primary><literal>supportsInterface()</literal></primary></indexterm>supportsInterface()</literal>, ...) .</para>
 
2561
 
 
2562
<para>A Part can only be displayed in a MainWindow and the MainWindow has to know
 
2563
about this. So before you can display a Part you have to register it to the
 
2564
MainWindow. This is done by calling the Part Interface's
 
2565
<literal remap="tt"><indexterm remap="cdx"><primary><literal>setMainWindow()</literal></primary></indexterm>setMainWindow()</literal> method (see previous chapter for further information
 
2566
about the process of registration) and this will give the Part a unique ID
 
2567
(which is for example used when addressing the part's GUI via the *bar manager
 
2568
objects) .</para>
 
2569
 
 
2570
<para>The MainWindow, as shell, has full control over all shared GUI elements.  This
 
2571
means that it is responsible for
 
2572
<itemizedlist>
 
2573
<listitem>
 
2574
<para>creating the appropriate *bar managing objects</para>
 
2575
</listitem>
 
2576
<listitem>
 
2577
<para>providing a skeleton/standard GUI which is meant to be always present,
 
2578
no matter what Part is active</para>
 
2579
</listitem>
 
2580
<listitem>
 
2581
<para>telling the GUI managing objects to activate/deactivate a Part's GUI</para>
 
2582
</listitem>
 
2583
</itemizedlist>
 
2584
</para>
 
2585
 
 
2586
<para>The creation of the *bar managers can be easily done by simply performing a
 
2587
dummy call to <literal remap="tt">*barManager()</literal> which usually returns a pointer to the
 
2588
appropriate manager and also creates a new one if it does not exist yet. It is
 
2589
recommended to perform these calls in the constructor of your MainWindow.</para>
 
2590
 
 
2591
<para>The creation/handling of the skeleton GUI is explained later in the chapters
 
2592
about <indexterm remap="cdx"><primary><literal>OPMenu</literal></primary></indexterm>OPMenu(Bar)/<indexterm remap="cdx"><primary><literal>OPToolBar</literal></primary></indexterm>OPToolBar .</para>
 
2593
 
 
2594
<para>Your MainWindow emits a Qt signal (<literal remap="tt"><indexterm remap="cdx"><primary><literal>activePartChanged</literal></primary></indexterm>activePartChanged</literal>) which informs
 
2595
you about a focus change of the active part, meaning whenever the user clicks
 
2596
on a non-active Part and it accepts the focus. Beside the pure informative
 
2597
sense  of this signal it is recommended to connect to this signal and perform
 
2598
the  following two steps in the slot implementation:</para>
 
2599
 
 
2600
<para><orderedlist><listitem>
 
2601
<para>deactivate the previous active Part's GUI by calling the *bar managers
 
2602
<literal remap="tt"><indexterm remap="cdx"><primary><literal>clear()</literal></primary></indexterm>clear()</literal> function, which will do the job and, beside some
 
2603
internal stuff, emit the GUI events (see previous chapter) to the Part.</para>
 
2604
</listitem>
 
2605
<listitem>
 
2606
<para>activate the new active Part's GUI by calling the *bar managers
 
2607
<literal remap="tt"><indexterm remap="cdx"><primary><literal>create()</literal></primary></indexterm>create()</literal> function, which will, similar to the activation, emit
 
2608
events to the Part. This is not really required but it is highly
 
2609
recommended. The following code is usually used for this:
 
2610
 
 
2611
<programlisting>      void NameOfYourMainWindow::slotActivePartChanged( unsigned long old_id,
 
2612
                                                        unsigned long new_id )
 
2613
      {
 
2614
        // clear the menu/tool/statusbar(s)
 
2615
        menuBarManager()-&gt;clear();
 
2616
        toolBarManager()-&gt;clear();
 
2617
        statusBarManager()-&gt;clear();
 
2618
        // create the new Part's GUI
 
2619
        menuBarManager()-&gt;create( new_id );
 
2620
        toolBarManager()-&gt;create( new_id );
 
2621
        statusBarManager()-&gt;create( new_id );
 
2622
      }
 
2623
      </programlisting>
 
2624
</para>
 
2625
</listitem>
 
2626
</orderedlist>
 
2627
</para>
 
2628
 
 
2629
<para>Now that the MainWindow handles all the shared "stuff" there is one thing
 
2630
which was not mentioned in this documentation, yet: What about the
 
2631
MainWindow's caption? The OpenParts MainWindow interface allows parts to have
 
2632
their own window captions, but how does OpenParts handle this?</para>
 
2633
 
 
2634
<para>Well, there are two ways:
 
2635
<orderedlist><listitem>
 
2636
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>OPMainWindow</literal></primary></indexterm>OPMainWindow</literal> provides you a so called <literal remap="tt"><indexterm remap="cdx"><primary><literal>AutoCaption</literal></primary></indexterm>AutoCaption</literal> mode
 
2637
which automatically changes the MainWindow's caption whenever the active
 
2638
part changes. This is enabled by default.</para>
 
2639
</listitem>
 
2640
<listitem>
 
2641
<para>But sometimes the shell wants to have full control over the window's
 
2642
caption, and this is accomplished by disabling the <literal remap="tt">AutoCaption</literal>
 
2643
mode, which  leads to the situation that the window's caption is not
 
2644
changed by OpenParts  in any way but instead gives you control over it.</para>
 
2645
</listitem>
 
2646
</orderedlist>
 
2647
</para>
 
2648
</sect2>
 
2649
 
 
2650
<sect2 id="access-shared-gui-elements-through-corba-ope">
 
2651
<title>Access shared GUI elements through CORBA - OpenPartsUI and its interfaces</title>
 
2652
 
 
2653
<para>Well, now that we know when we have to construct/destruct a Part's GUI,
 
2654
via the <indexterm remap="cdx"><primary><literal>OpenPartsUI</literal></primary></indexterm>OpenPartsUI events, we have to learn how to really create it, because
 
2655
we don't have the common <indexterm remap="cdx"><primary><literal>KMenuBar</literal></primary></indexterm>KMenuBar, <indexterm remap="cdx"><primary><literal>KToolBar</literal></primary></indexterm>KToolBar, etc. classes anymore available.
 
2656
The replacement for them are CORBA Objects, described in openparts&&lowbar;;ui.idl which
 
2657
is, together with the corresponding implementations, a part of the partsui
 
2658
module. The interfaces are 98&&percnt;;; similar to the KDE/Qt classes, so they're
 
2659
quite easy to use. Instead of bloating up this documentation with example code
 
2660
I rather suggest reading the tutorials in kdelibs/corba/tutorials .</para>
 
2661
</sect2>
 
2662
 
 
2663
<sect2 id="pixmaps-pixmaps-and-strings-strings-in-openp">
 
2664
<title>Pixmaps <indexterm remap="idx"><primary>Pixmaps</primary></indexterm> and Strings <indexterm remap="idx"><primary>Strings</primary></indexterm> in OpenParts - <indexterm remap="cdx"><primary><literal>OPUIUtils</literal></primary></indexterm>OPUIUtils</title>
 
2665
 
 
2666
<para>Toolbars and menus are usually beautified with pixmaps, using QPixmap classes.
 
2667
As we now use a CORBA interface to access our GUI elements, <indexterm remap="cdx"><primary><literal>QPixmap</literal></primary></indexterm>QPixmap has become
 
2668
<indexterm remap="cdx"><primary><literal>OpenPartsUI::Pixmap</literal></primary></indexterm>OpenPartsUI::Pixmap for OpenParts applications. OpenPartsUI::Pixmap is just
 
2669
a "stringified" QPixmap, and opUIUtils.(h,cc) contains some easy
 
2670
to use conversion routines.</para>
 
2671
 
 
2672
<para>In addition OPUIUtils contains string conversion routines between CORBA::WChar*
 
2673
and <indexterm remap="cdx"><primary><literal>QString</literal></primary></indexterm>QString. This is necessary since Qt version &gt;=2.0 supports <indexterm remap="cdx"><primary><literal>Unicode</literal></primary></indexterm>Unicode,
 
2674
via QString, all over the place, and obviously GUI elements like menus or
 
2675
toolbars have been converted to support this. OpenParts has been converted,
 
2676
too, by using "wstring" (<indexterm remap="cdx"><primary><literal>CORBA::WChar *</literal></primary></indexterm>CORBA::WChar *) in the interfaces and by
 
2677
using and providing conversion routines. These routines are static member
 
2678
functions of the OPUIUtils  class, just like with the pixmap conversion. To
 
2679
simplify the usage, two macros have been defined: <literal remap="tt"><indexterm remap="cdx"><primary><literal>Q2C</literal></primary></indexterm>Q2C</literal> and
 
2680
<literal remap="tt"><indexterm remap="cdx"><primary><literal>C2Q</literal></primary></indexterm>C2Q</literal> . The first one converts a QString into a CORBA::WChar * string
 
2681
and the second one vice-versa.</para>
 
2682
 
 
2683
<para>When converting from QString to CORBA::WChar * the conversion routine
 
2684
allocates memory. To avoid memory leaks <indexterm remap="idx"><primary>memory leaks</primary></indexterm> it is highly recommended to use
 
2685
CORBA::WString&&lowbar;;var variables. Exactly the same applies for QPixmap -&gt;
 
2686
OpenPartsUI::Pixmap conversions: Use <indexterm remap="cdx"><primary><literal>OpenPartsUI::Pixmap&&lowbar;;var</literal></primary></indexterm>OpenPartsUI::Pixmap&&lowbar;;var , and you don't
 
2687
have to worry about leaks :-) .</para>
 
2688
 
 
2689
<para>Here's some example code, to show how to do it right:
 
2690
<programlisting>    ...
 
2691
    OpenPartsUI::Pixmap_var pm = OPUIUtils::convertPixmap( QPixmap_variable_here );
 
2692
    someToolBar-&gt;insertButton( pm, ... );
 
2693
    ...
 
2694
    //use the same pm variable again
 
2695
    pm = OPUIUtils::convertPixmap( another_qpixmap );
 
2696
    ...</programlisting>
 
2697
</para>
 
2698
 
 
2699
<para>Similar things have to be done with QString's:</para>
 
2700
 
 
2701
<para><programlisting>    ...
 
2702
    CORBA::WString_var text = Q2C( QString_here );
 
2703
    someMenuBar-&gt;insertItem7( text, ... );
 
2704
    ...
 
2705
    // or you can write:
 
2706
    someMenuBar-&gt;insertItem7( ( text = Q2C( QString_here ) ) , ...);
 
2707
    ...</programlisting>
 
2708
</para>
 
2709
 
 
2710
<para>One note left: When you return a "wide string" (CORBA::WChar *) as
 
2711
a function result by using <literal remap="tt">Q2C</literal>, make sure not to use
 
2712
<literal remap="tt"><indexterm remap="cdx"><primary><literal>CORBA::wstring&&lowbar;;dup()</literal></primary></indexterm>CORBA::wstring&&lowbar;;dup()</literal>.</para>
 
2713
 
 
2714
<para>Example:
 
2715
<programlisting>  return CORBA::string_dup( Q2C( QString_here ) ); //!!!! WRONG!!!!!
 
2716
  ...
 
2717
  return Q2C( QString_here ); // RIGHT! because Q2C already allocates the string</programlisting>
 
2718
</para>
 
2719
 
 
2720
<para>That's it! Have fun using KOM/OpenParts :-)</para>
 
2721
 
 
2722
<para>TODO:
 
2723
<itemizedlist>
 
2724
<listitem>
 
2725
<para>KOMShutdownManager</para>
 
2726
</listitem>
 
2727
<listitem>
 
2728
<para>AutoLoader template classes</para>
 
2729
</listitem>
 
2730
<listitem>
 
2731
<para>OPApplication Interface + Factories</para>
 
2732
</listitem>
 
2733
</itemizedlist>
 
2734
</para>
 
2735
</sect2>
 
2736
</sect1>
 
2737
</chapter>
 
2738
 
 
2739
<chapter id="kdedaemon">
 
2740
<title>The KDE Daemon</title>
 
2741
 
 
2742
<para>Simon Hausmann <ulink url="mailto:hausmann@kde.org">&lt;hausmann@kde.org&gt;</ulink></para>
 
2743
 
 
2744
<para>v1.0 26, June 1999</para>
 
2745
 
 
2746
<para><emphasis>This documentation describes the KDE Daemon, the services it provides and
 
2747
how to use it. So if you're dealing with CORBA server <indexterm remap="idx"><primary>CORBA server</primary></indexterm>s in the KDE or if you're
 
2748
interested in a smart way of accessing KService <indexterm remap="idx"><primary>KService</primary></indexterm> data in your application then
 
2749
you might want to read this and use <indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded</emphasis></para>
 
2750
 
 
2751
<sect1 id="introduction-4">
 
2752
<title>Introduction</title>
 
2753
 
 
2754
<para>The KDE Daemon, herein simply named <indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded, is a central daemon in the KDE Desktop
 
2755
Environment. It provides three services:</para>
 
2756
 
 
2757
<para><itemizedlist>
 
2758
<listitem>
 
2759
<para>The KDE Trader (<indexterm remap="cdx"><primary><literal>KTrader</literal></primary></indexterm>KTrader) , which provides an easy-to-use but still extremly
 
2760
powerful interface to the KDE Registry.</para>
 
2761
</listitem>
 
2762
<listitem>
 
2763
<para>The KDE Activator (<indexterm remap="cdx"><primary><literal>KActivator</literal></primary></indexterm>KActivator) , which makes accessing CORBA based services
 
2764
in KDE the easiest thing of the world ;-) .</para>
 
2765
</listitem>
 
2766
<listitem>
 
2767
<para>The KDE Naming Service (<indexterm remap="cdx"><primary><literal>KNaming</literal></primary></indexterm>KNaming) , which provides a simple but useful
 
2768
naming service for CORBA Objects.</para>
 
2769
</listitem>
 
2770
</itemizedlist>
 
2771
</para>
 
2772
</sect1>
 
2773
 
 
2774
<sect1 id="using-the-kde-daemon-in-your-application">
 
2775
<title>Using The KDE Daemon In Your Application</title>
 
2776
 
 
2777
<para>Before we can use any of <indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded's services, we have to know something about it's
 
2778
"position" in the KDE and the way it itself and the services can be accessed.</para>
 
2779
 
 
2780
<para>As <indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded uses CORBA to communicate with it's clients, your application (as client),
 
2781
has to
 
2782
<itemizedlist>
 
2783
<listitem>
 
2784
<para>link to the <indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded library, <indexterm remap="cdx"><primary><literal>libkded</literal></primary></indexterm>libkded.</para>
 
2785
</listitem>
 
2786
<listitem>
 
2787
<para>link to libmico</para>
 
2788
</listitem>
 
2789
<listitem>
 
2790
<para>initialize the MICO <indexterm remap="idx"><primary>MICO</primary></indexterm> ORB <indexterm remap="idx"><primary>ORB</primary></indexterm></para>
 
2791
</listitem>
 
2792
</itemizedlist>
 
2793
</para>
 
2794
 
 
2795
<para>The first two points are fixed for all clients, the third one depends on the
 
2796
specific client. In general you have to choices:</para>
 
2797
 
 
2798
<para><itemizedlist>
 
2799
<listitem>
 
2800
<para>If your application already uses KOM <indexterm remap="idx"><primary>KOM</primary></indexterm>, then you're fine with using
 
2801
<indexterm remap="cdx"><primary><literal>KOMApplication</literal></primary></indexterm>KOMApplication (as you need it anyway) .</para>
 
2802
</listitem>
 
2803
<listitem>
 
2804
<para>If you don't want to use KOM <indexterm remap="idx"><primary>KOM</primary></indexterm>, then you can initialize the ORBA "manually":
 
2805
<literal remap="verb">CORBA::ORB_ptr orb = CORBA::ORB_init( argc, argv, "mico-local-orb" );</literal>
 
2806
Please note that when using this construct or similar ones, your application is
 
2807
<emphasis remap="bf">not</emphasis> able to act as CORBA server <indexterm remap="idx"><primary>CORBA server</primary></indexterm> if you are using KDE/Qt classes at the
 
2808
same time. This is due to the fact that the ORB <indexterm remap="idx"><primary>ORB</primary></indexterm> needs it's own event loop, beside
 
2809
the main Qt event loop. Currently only <indexterm remap="cdx"><primary><literal>KOMApplication</literal></primary></indexterm>KOMApplication, as part of the KDE Object
 
2810
Model, implements the needed functionality to combine both event loops and thus
 
2811
making KDE apps able to serve CORBA Objects.</para>
 
2812
</listitem>
 
2813
</itemizedlist>
 
2814
</para>
 
2815
 
 
2816
<para>Although <indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded uses CORBA extensively, the API is kept simple and free from
 
2817
complicated CORBA stuff. In fact when talking about <indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded and it's API not the
 
2818
<indexterm remap="cdx"><primary><literal>kded server</literal></primary></indexterm>kded server is meant but the KDE Daemon library. This library contains the
 
2819
interface to the server (for the clients) as well as the whole server functionality.
 
2820
The reason for this is based on the idea that an application using <indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded should
 
2821
not be forced to rely on an existing <indexterm remap="cdx"><primary><literal>kded server</literal></primary></indexterm>kded server binary nor a running server at
 
2822
all. The following three situations may exist when a client app gets started:</para>
 
2823
 
 
2824
<para><itemizedlist>
 
2825
<listitem>
 
2826
<para>No <indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded is running and there's no <indexterm remap="cdx"><primary><literal>kded server</literal></primary></indexterm>kded server binary in the path. In this
 
2827
situation <indexterm remap="cdx"><primary><literal>libkded</literal></primary></indexterm>libkded will automatically start a local instance of <indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded in
 
2828
the application's process.</para>
 
2829
</listitem>
 
2830
<listitem>
 
2831
<para>No <indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded is running but there's a <indexterm remap="cdx"><primary><literal>kded server</literal></primary></indexterm>kded server binary available. Here <indexterm remap="cdx"><primary><literal>libkded</literal></primary></indexterm>libkded
 
2832
will start the kded executable and connect to it.</para>
 
2833
</listitem>
 
2834
<listitem>
 
2835
<para><indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded is already running :-) . The fact that a <indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded is running is indicated
 
2836
by a special property on the X Root Window. <indexterm remap="cdx"><primary><literal>kded</literal></primary></indexterm>kded publishes it's IOR <indexterm remap="idx"><primary>IOR</primary></indexterm>
 
2837
(Interoperable Object Reference) in this property. This also ensures that
 
2838
a kded <indexterm remap="idx"><primary>kded</primary></indexterm> instance is specific to a X display and therefore to your KDE session.</para>
 
2839
</listitem>
 
2840
</itemizedlist>
 
2841
</para>
 
2842
 
 
2843
<para>To sum it up: libkded <indexterm remap="idx"><primary>libkded</primary></indexterm> will always make sure that the services of kded <indexterm remap="idx"><primary>kded</primary></indexterm> are available
 
2844
for your client application, no matter in what alien environment the app is
 
2845
running :-) . And, although you don't have to care about this, you can optionally
 
2846
control this behaviour of libkded <indexterm remap="idx"><primary>libkded</primary></indexterm> by adding one of the following three commandline arguments <indexterm remap="idx"><primary>commandline arguments</primary></indexterm>
 
2847
to your app:
 
2848
<itemizedlist>
 
2849
<listitem>
 
2850
<para>"-kdedlocal" , which will make libkded <indexterm remap="idx"><primary>libkded</primary></indexterm> <emphasis remap="bf">always</emphasis> start a process-local
 
2851
instance of kded and it's services.</para>
 
2852
</listitem>
 
2853
<listitem>
 
2854
<para>"-kdedremote" , which will make libkded <indexterm remap="idx"><primary>libkded</primary></indexterm> try to look for a running kded <indexterm remap="idx"><primary>kded</primary></indexterm>
 
2855
instance before starting a local one.</para>
 
2856
</listitem>
 
2857
<listitem>
 
2858
<para>"-kdedior ior&&lowbar;;here" , which will make libkded <indexterm remap="idx"><primary>libkded</primary></indexterm> connect to the kded server <indexterm remap="idx"><primary>kded server</primary></indexterm>
 
2859
specified by the given IOR <indexterm remap="idx"><primary>IOR</primary></indexterm>.</para>
 
2860
</listitem>
 
2861
</itemizedlist>
 
2862
</para>
 
2863
 
 
2864
<para>Your actual interface to kded <indexterm remap="idx"><primary>kded</primary></indexterm> and it's services is the <literal remap="tt"><indexterm remap="cdx"><primary><literal>KdedInstance</literal></primary></indexterm>KdedInstance</literal> class,
 
2865
defined in kded&&lowbar;;instance.h . So if you want to use kded <indexterm remap="idx"><primary>kded</primary></indexterm> (I guess that's why you're
 
2866
reading this shit ;) ) then make sure to create <emphasis remap="bf">one</emphasis> single instance
 
2867
of it, preferably by adding the following line somewhere in the beginning of
 
2868
your <literal remap="tt">main()</literal> :
 
2869
<literal remap="verb">KdedInstance( argc, argv, _a_reference_to_the_orb_here_ );</literal>
 
2870
If you're using KOMApplication <indexterm remap="idx"><primary>KOMApplication</primary></indexterm> as application object (make sure to create the
 
2871
instance before this line) , then you're fine by specifying <literal remap="tt">komapp&&lowbar;;orb</literal> as
 
2872
reference to the ORB <indexterm remap="idx"><primary>ORB</primary></indexterm>.</para>
 
2873
 
 
2874
<para>As there is always only one single instance of this class, you can simply access
 
2875
it by the static <literal remap="tt"><indexterm remap="cdx"><primary><literal>self()</literal></primary></indexterm>self()</literal> method of the class from anywhere you want. No
 
2876
need to pass <indexterm remap="cdx"><primary><literal>KdedInstance</literal></primary></indexterm>KdedInstance arguments all around in your program ;-) .</para>
 
2877
 
 
2878
<para>For further information about <literal remap="tt"><indexterm remap="cdx"><primary><literal>KdedInstance</literal></primary></indexterm>KdedInstance</literal> you might want to read
 
2879
<literal remap="tt"><indexterm remap="cdx"><primary><literal>kded&&lowbar;;instance.h</literal></primary></indexterm>kded&&lowbar;;instance.h</literal> , it's pretty good documented.</para>
 
2880
</sect1>
 
2881
 
 
2882
<sect1 id="ktrader-ktrader">
 
2883
<title>KTrader <indexterm remap="idx"><primary>KTrader</primary></indexterm></title>
 
2884
 
 
2885
<para>As already mentioned in the introduction, KTrader <indexterm remap="idx"><primary>KTrader</primary></indexterm> gives you access to the registry.
 
2886
"Now what the hell is the registry?" you might ask. As this is just a documentation
 
2887
about kded <indexterm remap="idx"><primary>kded</primary></indexterm>/libkded <indexterm remap="idx"><primary>libkded</primary></indexterm>, I can only respond: "Please consult the documentation of/in
 
2888
<literal remap="tt"><indexterm remap="cdx"><primary><literal>libkio</literal></primary></indexterm>libkio</literal> for more information" :-&&rcub;; . Just one thing about it here: KTrader <indexterm remap="idx"><primary>KTrader</primary></indexterm> loads
 
2889
the whole and bloaty registry for you. Thanks to the magic of <literal remap="tt"><indexterm remap="cdx"><primary><literal>libkio</literal></primary></indexterm>libkio</literal> the loaded
 
2890
registry will always be in sync with the "real" registry, the .desktop <indexterm remap="idx"><primary>.desktop</primary></indexterm> files in
 
2891
the following standard directories (both types, the system wide and the user ones) :
 
2892
<itemizedlist>
 
2893
<listitem>
 
2894
<para>applnk</para>
 
2895
</listitem>
 
2896
<listitem>
 
2897
<para>mimelnk</para>
 
2898
</listitem>
 
2899
<listitem>
 
2900
<para>services</para>
 
2901
</listitem>
 
2902
<listitem>
 
2903
<para>servicetypes</para>
 
2904
</listitem>
 
2905
</itemizedlist>
 
2906
</para>
 
2907
 
 
2908
<para>Now over to KTrader <indexterm remap="idx"><primary>KTrader</primary></indexterm> and it's API. Similar to <literal remap="tt"><indexterm remap="cdx"><primary><literal>KdedInstance</literal></primary></indexterm>KdedInstance</literal> there can
 
2909
be only one single instance. The difference is that you don't have to care
 
2910
about allocating it, just simply get a reference to the KTrader <indexterm remap="idx"><primary>KTrader</primary></indexterm> by calling
 
2911
the <literal remap="tt">ktrader()</literal> method of <literal remap="tt"><indexterm remap="cdx"><primary><literal>KdedInstance</literal></primary></indexterm>KdedInstance</literal> . And: don't
 
2912
even think about deleting the returned reference! Just simply use it and be
 
2913
happy with it :-) . (hey, kded <indexterm remap="idx"><primary>kded</primary></indexterm> is designed to be easy to use, no need for difficult
 
2914
stuff...)</para>
 
2915
 
 
2916
<para>The KTrader <indexterm remap="idx"><primary>KTrader</primary></indexterm> API is even so simple that it contains only two methods ;-) . But
 
2917
before I describe these methods you have to know something about the kind of
 
2918
data KTrader <indexterm remap="idx"><primary>KTrader</primary></indexterm> returns. In simple words: You will always get a list of KService <indexterm remap="idx"><primary>KService</primary></indexterm>
 
2919
objects. More detailed: The returned list is a <literal remap="tt"><indexterm remap="cdx"><primary><literal>QValueList</literal></primary></indexterm>QValueList</literal> and the
 
2920
entries are <literal remap="tt"><indexterm remap="cdx"><primary><literal>KSharedPtr</literal></primary></indexterm>KSharedPtr</literal>'s (FIXME: will soon be renamed to QSharedPtr,
 
2921
as it will become part of Qt.... AFAIK) to <literal remap="tt">KService <indexterm remap="idx"><primary>KService</primary></indexterm></literal> objects. Please
 
2922
read the corresponding Qt documentation about these two classes. The big advantage
 
2923
of using these two template classes is that everything becomes easy for you
 
2924
and that the memory consumption is kept at a minimum . You don't have to care
 
2925
about pointers, freeing them and cleaning up the list, as long as you use
 
2926
<literal remap="tt"><indexterm remap="cdx"><primary><literal>KTrader::ServicePtr</literal></primary></indexterm>KTrader::ServicePtr</literal> variables to hold the KService <indexterm remap="idx"><primary>KService</primary></indexterm> objects and as
 
2927
long as you use <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTrader::OfferList</literal></primary></indexterm>KTrader::OfferList</literal> to pass the list around in your
 
2928
program. So: Remember to always use these two types when dealing with KTrader <indexterm remap="idx"><primary>KTrader</primary></indexterm>!</para>
 
2929
 
 
2930
<para>Now over to the two methods.</para>
 
2931
 
 
2932
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>KTrader::listServices()</literal></primary></indexterm>KTrader::listServices()</literal> returns your a list of <emphasis remap="bf">all</emphasis> available
 
2933
services in the whole KDE. (no need for further explanations I think...)</para>
 
2934
 
 
2935
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>KTrader::query()</literal></primary></indexterm>KTrader::query()</literal> is the key method of this beast. It performs a lookup
 
2936
in the registry database, given your information about what you want to have.
 
2937
The first argument is the name of the servicetype which all returned services
 
2938
must implement. If you're unsure about the word "servicetype" , then you can
 
2939
replace it with "mimetype" , for most, but not all, cases.</para>
 
2940
 
 
2941
<para>The second argument is an additional constraint expression, which has to be
 
2942
fulfilled by a service.</para>
 
2943
 
 
2944
<para>The third argument is a preference expression after which the returned services
 
2945
will be sorted. The value of the expression has to be numeric.</para>
 
2946
 
 
2947
<para>The syntax of these two expressions is equal with the language of the standard
 
2948
CORBA Trader (this is due to the fact that the parsing code is from the COS <indexterm remap="idx"><primary>COS</primary></indexterm>
 
2949
Trader of MICO <indexterm remap="idx"><primary>MICO</primary></indexterm>) . The language is not very difficult and I don't want to bloat
 
2950
this documentation with further explanations about it. Please consult your
 
2951
CORBA literature for more information. Just one thing you have to know:
 
2952
Comparisons are always done with the properties of the KService <indexterm remap="idx"><primary>KService</primary></indexterm> object,
 
2953
which are the standard entries (Name, ServiceType, RepoIds, ...) plus
 
2954
the ones specified in the servicetype declaration and read by KService <indexterm remap="idx"><primary>KService</primary></indexterm>.</para>
 
2955
 
 
2956
<para>Well, after so much theoretical explanations it's time for some practical example
 
2957
code:
 
2958
<indexterm remap="ncdx"><primary><literal>KTrader::OfferList</literal></primary></indexterm>
 
2959
<programlisting>  ...
 
2960
  //get a reference to the KTrader
 
2961
  KTrader *trader = KdedInstance::self()-&gt;ktrader();
 
2962
 
 
2963
  ...
 
2964
  //will return a list of all services which implement the servicetype
 
2965
  //named "text/plain"
 
2966
  KTrader::OfferList offers = trader-&gt;query( "text/plain" );
 
2967
 
 
2968
 
 
2969
  ...
 
2970
  //will return a list of all services which implement the servicetype
 
2971
  //named "image/gif" and which have the AllowAsDefault property set true
 
2972
  KTrader::OfferList offers = trader-&gt;query( "image/gif", "AllowAsDefault == TRUE" );
 
2973
 
 
2974
  ...
 
2975
  //will return KSpread ;-)
 
2976
  KTrader::OfferList offers = trader-&gt;query( "KOfficeDocument", "(Exec == 'kspread') and (Path != '/opt/gnome/bin')" );
 
2977
 
 
2978
  ...
 
2979
  //will return a list of all services which implement the servicetype
 
2980
  //named "BlahFoo" and which will be sorted (from lowest to highest) by
 
2981
  //the value of the property "Price" , declared in the servicetype
 
2982
  //declaration of BlahFoo.
 
2983
  KTrader::OfferList offers = trader-&gt;query( "BlahFoo", QString::null, "min Price" );</programlisting>
 
2984
</para>
 
2985
 
 
2986
<para>Please note that KTrader <indexterm remap="idx"><primary>KTrader</primary></indexterm>, since it queries <literal remap="tt"><indexterm remap="cdx"><primary><literal>libkio</literal></primary></indexterm>libkio</literal> for services, will
 
2987
always return services sorted by the user's preferences for the specific
 
2988
servicetype. These preferences can be specified in the file "profilerc" .</para>
 
2989
 
 
2990
<sect2 id="ktraderserviceprovider">
 
2991
<title>KTraderServiceProvider</title>
 
2992
 
 
2993
<para>This section requires to be familiar with <literal remap="tt"><indexterm remap="cdx"><primary><literal>libkio</literal></primary></indexterm>libkio</literal> and it is meant for everybody who
 
2994
wants to use KRun <indexterm remap="idx"><primary>KRun</primary></indexterm> in his application.</para>
 
2995
 
 
2996
<para>KRun <indexterm remap="idx"><primary>KRun</primary></indexterm> requires a fully loaded registry in order to resolve mimetype &lt;-&gt; application
 
2997
bindings. A fully loaded registry means that you need a <literal remap="tt"><indexterm remap="cdx"><primary><literal>KServiceTypeFactory</literal></primary></indexterm>KServiceTypeFactory</literal> and
 
2998
a KServiceFactory, which both load the appropriate <literal remap="tt"><indexterm remap="cdx"><primary><literal>KServiceType</literal></primary></indexterm>KServiceType</literal><literal remap="tt"><indexterm remap="cdx"><primary><literal>KService</literal></primary></indexterm>KService</literal> objects.
 
2999
Now the KServiceType information doesn't need that much memory, but the KService <indexterm remap="idx"><primary>KService</primary></indexterm>
 
3000
object really eat loooots of it. And isn't it kind of stupid to load this information
 
3001
if this is already done by kded <indexterm remap="idx"><primary>kded</primary></indexterm>? Yes, it is ;-) .</para>
 
3002
 
 
3003
<para>What we would need is to make KRun <indexterm remap="idx"><primary>KRun</primary></indexterm> query KTrader <indexterm remap="idx"><primary>KTrader</primary></indexterm> for KService <indexterm remap="idx"><primary>KService</primary></indexterm> data, instead of
 
3004
directly using KServiceTypeProfile <indexterm remap="idx"><primary>KServiceTypeProfile</primary></indexterm>. Fortunately KRun <indexterm remap="idx"><primary>KRun</primary></indexterm> is flexible enough for this,
 
3005
we just need a re-implementation of the KServiceProvider <indexterm remap="idx"><primary>KServiceProvider</primary></indexterm>, defined in <literal remap="tt"><indexterm remap="cdx"><primary><literal>krun.h</literal></primary></indexterm>krun.h</literal>
 
3006
and used by KRun <indexterm remap="idx"><primary>KRun</primary></indexterm>. Guess what, but KTrader <indexterm remap="idx"><primary>KTrader</primary></indexterm> provides you this re-implementation :-) .
 
3007
Just have a look at the end of <literal remap="tt"><indexterm remap="cdx"><primary><literal>ktrader.h</literal></primary></indexterm>ktrader.h</literal>.</para>
 
3008
 
 
3009
<para>To sum it up: The following line makes KRun <indexterm remap="idx"><primary>KRun</primary></indexterm> query kded <indexterm remap="idx"><primary>kded</primary></indexterm>, in your application:
 
3010
<programlisting>  ...
 
3011
  //place this somewhere BEFORE the first usage of KRun, preferable somewhere
 
3012
  //in main()
 
3013
  KTraderServiceProvider serviceProvider;
 
3014
  ...</programlisting>
 
3015
 
 
3016
That's all, except that you <emphasis remap="bf">must</emphasis> have a <indexterm remap="cdx"><primary><literal>KdedInstance</literal></primary></indexterm>KdedInstance in order to be
 
3017
able to use it.</para>
 
3018
</sect2>
 
3019
</sect1>
 
3020
 
 
3021
<sect1 id="kactivator-kactivator">
 
3022
<title>KActivator <indexterm remap="idx"><primary>KActivator</primary></indexterm></title>
 
3023
 
 
3024
<para>One often mentioned problem, when talking about applications which provide
 
3025
their services via CORBA, is how to start and access these services. Solutions
 
3026
like making apps write the IOR <indexterm remap="idx"><primary>IOR</primary></indexterm> of an object somewhere into a file in the
 
3027
filesystem or similar approaches are just hacks ;-) . Better use KActivator <indexterm remap="idx"><primary>KActivator</primary></indexterm>,
 
3028
since it can automatically, on demand, start servers for you or use already
 
3029
running ones. This is accomplished with the help of the mediators for BOA/POA <indexterm remap="idx"><primary>BOA/POA</primary></indexterm>
 
3030
and the IMR <indexterm remap="idx"><primary>IMR</primary></indexterm> (Implementation Repository), both provided by MICO <indexterm remap="idx"><primary>MICO</primary></indexterm>. Fortunately
 
3031
you don't have to deal with IMR entries and the mediators.</para>
 
3032
 
 
3033
<para>Before you can use KActivator <indexterm remap="idx"><primary>KActivator</primary></indexterm> to start a server for you, you have to register
 
3034
the server's service. There are two possible ways, the last one is highly
 
3035
recommended though:</para>
 
3036
 
 
3037
<para><itemizedlist>
 
3038
<listitem>
 
3039
<para>Register and unregister it manually, by using the two corresponding
 
3040
methods of the KActivator <indexterm remap="idx"><primary>KActivator</primary></indexterm>.</para>
 
3041
</listitem>
 
3042
<listitem>
 
3043
<para>Go the smart way and provide the necessary information in a .desktop <indexterm remap="idx"><primary>.desktop</primary></indexterm> file.
 
3044
Fortunately KService <indexterm remap="idx"><primary>KService</primary></indexterm> supports the necessary properties, like repository
 
3045
ids, activation mode and others.</para>
 
3046
</listitem>
 
3047
</itemizedlist>
 
3048
</para>
 
3049
 
 
3050
<para>For the second point it's important that the .desktop <indexterm remap="idx"><primary>.desktop</primary></indexterm> file is available for
 
3051
KRegistry <indexterm remap="idx"><primary>KRegistry</primary></indexterm>, by placing it in a directory which gets scanned by the registry.
 
3052
If your application has already a .desktop <indexterm remap="idx"><primary>.desktop</primary></indexterm> file in the applnk tree for example,
 
3053
then you're fine with adding the necessary fields in there. Otherwise the
 
3054
directory named "services" (either system-wide or user-local) is the best place
 
3055
for it. If you provide the CORBA service information this way, then KActivator <indexterm remap="idx"><primary>KActivator</primary></indexterm>
 
3056
will automatically detect it and register it automatically at the IMR. This
 
3057
means that it is immediately available for KActivator <indexterm remap="idx"><primary>KActivator</primary></indexterm> and thus to your client app.
 
3058
And since KRegistry <indexterm remap="idx"><primary>KRegistry</primary></indexterm> is such a cool thing :-) , you can do all this even at
 
3059
run-time, when kded <indexterm remap="idx"><primary>kded</primary></indexterm> is running. Just place the .desktop <indexterm remap="idx"><primary>.desktop</primary></indexterm> file in one of the
 
3060
right directories for it and KActivator <indexterm remap="idx"><primary>KActivator</primary></indexterm> will update the IMR on-the-fly. The
 
3061
same applies obviously for just deleted or modified .desktop <indexterm remap="idx"><primary>.desktop</primary></indexterm> files, which will
 
3062
make KActivator <indexterm remap="idx"><primary>KActivator</primary></indexterm> adjust the IMR. Now you might get the idea why this is the
 
3063
preferred way :-)) .</para>
 
3064
 
 
3065
<para>Now that you know how to register CORBA services you will want to know how
 
3066
to "access" it. <literal remap="tt">activateService()</literal> is your friend here. Simply pass
 
3067
it the name of the service, the repository id of the server object and the
 
3068
object's tag and it will return you a functional object reference. That's all :-)</para>
 
3069
 
 
3070
<para>Depending on the service's activation mode, KActivator <indexterm remap="idx"><primary>KActivator</primary></indexterm> will either return a reference
 
3071
to an already running server or it will start a new instance.</para>
 
3072
 
 
3073
<para>One note about the returned object reference: This is a virtual reference,
 
3074
which means that that server object is started when the first call is invoked
 
3075
on this reference, thus making your server get started "lazy", only on-demand.
 
3076
But that's just additional information, you don't have to deal and know about
 
3077
it at all. Just be happy with your functional object reference :-) .</para>
 
3078
 
 
3079
<para>Want some examples? Here we go:</para>
 
3080
 
 
3081
<para>This is how a .desktop <indexterm remap="idx"><primary>.desktop</primary></indexterm> file could look like, assuming that the commandline
 
3082
"--server" starts the app in CORBA server <indexterm remap="idx"><primary>CORBA server</primary></indexterm> mode:
 
3083
<programlisting>Name=MyApp
 
3084
Exec=fooblah
 
3085
CORBAExec=fooblah --server
 
3086
X-KDE-RepoIds=IDL:Foo/Blah:1.0#MyFoo
 
3087
X-KDE-ActivationMode=shared</programlisting>
 
3088
</para>
 
3089
 
 
3090
<para>If KActivator <indexterm remap="idx"><primary>KActivator</primary></indexterm> "gets" this file, it will register the service and then you're
 
3091
able to do something like this:
 
3092
<programlisting>  ...
 
3093
  KActivator *activator = KdedInstance::self()-&gt;kactivator();
 
3094
  ...
 
3095
  CORBA::Object_var obj = activator-&gt;activateServer( "MyApp", "IDL:Foo/Blah:1.0", "MyFoo );
 
3096
  ...</programlisting>
 
3097
</para>
 
3098
 
 
3099
<para>The above example will either start a new fooblah instance or connect to a running
 
3100
one.</para>
 
3101
 
 
3102
<para>For further information please have a look at the examples in kdelibs/corba/tutorials/kded .
 
3103
The example application there registers the server manually via <literal remap="tt">registerService</literal> .</para>
 
3104
 
 
3105
<para>Please note: The server <emphasis remap="bf">has</emphasis> to be started by kded <indexterm remap="idx"><primary>kded</primary></indexterm> in order to make KActivator <indexterm remap="idx"><primary>KActivator</primary></indexterm>
 
3106
return a reference to a running one. Executing "fooblah" from somewhere else
 
3107
will <emphasis remap="bf">not</emphasis> make KActivator <indexterm remap="idx"><primary>KActivator</primary></indexterm> use it. This is a problem for persistent
 
3108
servers like KDesktop <indexterm remap="idx"><primary>KDesktop</primary></indexterm> for example. But there's a solution available, just read
 
3109
the next chapter about the KDE Naming Service :-) .</para>
 
3110
</sect1>
 
3111
 
 
3112
<sect1 id="knaming-knaming">
 
3113
<title>KNaming <indexterm remap="idx"><primary>KNaming</primary></indexterm></title>
 
3114
 
 
3115
<para>The KDE Naming Service, KNaming <indexterm remap="idx"><primary>KNaming</primary></indexterm>, is also a very simple service, but it's pretty
 
3116
useful and in some cases a very nice solution to make a CORBA client connect to
 
3117
a persistent CORBA server <indexterm remap="idx"><primary>CORBA server</primary></indexterm>.</para>
 
3118
 
 
3119
<para>With KNaming <indexterm remap="idx"><primary>KNaming</primary></indexterm> you can bind a freely chooseable name to a CORBA object. And since
 
3120
kded <indexterm remap="idx"><primary>kded</primary></indexterm> is system (session) wide available, your object becomes available for any
 
3121
client which is able to connect to kded <indexterm remap="idx"><primary>kded</primary></indexterm>.</para>
 
3122
 
 
3123
<para>There's not much to explain here :-&&rcub;; , so I suggest having a look at the KNaming <indexterm remap="idx"><primary>KNaming</primary></indexterm>
 
3124
API, in <literal remap="tt"><indexterm remap="cdx"><primary><literal>knaming.h</literal></primary></indexterm>knaming.h</literal>.</para>
 
3125
 
 
3126
<para>Example code can be, again, found in kdelibs/corba/tutorials/kded . Here's just
 
3127
a short real example situation:</para>
 
3128
 
 
3129
<para>Just think of KDesktop <indexterm remap="idx"><primary>KDesktop</primary></indexterm>, that nice app providing your background desktop icons.
 
3130
It provides some functionality via CORBA, just have a look at kdesktop.idl to
 
3131
see what I'm talking about. Now the problem for KDesktop <indexterm remap="idx"><primary>KDesktop</primary></indexterm> is: How can it provide
 
3132
this service to other apps in the system? Writing an IOR <indexterm remap="idx"><primary>IOR</primary></indexterm> into some file is no
 
3133
clean solution IMHO, and using KActivator <indexterm remap="idx"><primary>KActivator</primary></indexterm> doesn't work because KDesktop <indexterm remap="idx"><primary>KDesktop</primary></indexterm> does not
 
3134
get started by kded <indexterm remap="idx"><primary>kded</primary></indexterm> but by the startkde script on KDE startup. So we find a better
 
3135
way and make KDesktop <indexterm remap="idx"><primary>KDesktop</primary></indexterm> register it's object at KNaming <indexterm remap="idx"><primary>KNaming</primary></indexterm>. This is done by the following
 
3136
lines:
 
3137
<programlisting>  ...
 
3138
  KNaming *knaming = KdedInstance::self()-&gt;knaming();
 
3139
  naming-&gt;bind( "KDesktop", kdesktop_object_here );
 
3140
  ...</programlisting>
 
3141
 
 
3142
Well, I told you a lie ;) : KNaming <indexterm remap="idx"><primary>KNaming</primary></indexterm> does not really bind to "KDesktop <indexterm remap="idx"><primary>KDesktop</primary></indexterm>" but
 
3143
instead to "IDL:KDesktopIf:1.0" , but since there's no naming convention
 
3144
for the naming I have choosen a more readable name, IMHO of course :-) (don't
 
3145
mind me David :] ) . I personally prefer human readable names ;) , in contrary
 
3146
to repository ids with tags.</para>
 
3147
 
 
3148
<para>Back to KNaming <indexterm remap="idx"><primary>KNaming</primary></indexterm> and KDesktop <indexterm remap="idx"><primary>KDesktop</primary></indexterm>: Now any client application, kfmclient for example,
 
3149
can "connect" to KDesktop <indexterm remap="idx"><primary>KDesktop</primary></indexterm>. Just like this:
 
3150
<programlisting>  ..
 
3151
  KNaming *knaming = KdedInstance::self()-&gt;knaming();
 
3152
  ...
 
3153
  CORBA::Object_var obj = knaming-&gt;resolve( "KDesktop" );
 
3154
  KDesktopIf_var kdesky = KDesktopIf::_narrow( obj );
 
3155
  kdesky-&gt;selectAll(); //let's confuse the user by selecting all icons ;-)
 
3156
  ...</programlisting>
 
3157
</para>
 
3158
</sect1>
 
3159
</chapter>
 
3160
 
 
3161
<chapter id="dcop">
 
3162
<title>DCOP: Desktop COmmunications Protocol</title>
 
3163
 
 
3164
<para>Preston Brown <ulink url="mailto:pbrown@kde.org">&lt;pbrown@kde.org&gt;</ulink></para>
 
3165
 
 
3166
<para>Version 1.0, October 14, 1999</para>
 
3167
 
 
3168
<para><emphasis>Howto for the KDE Desktop COmmunincations Protocol implementation</emphasis></para>
 
3169
 
 
3170
<sect1 id="motivation-and-background">
 
3171
<title>Motivation and Background</title>
 
3172
 
 
3173
<para>The motivation behind building a protocol like DCOP is simple.  For
 
3174
the past year, we have been attempting to enable interprocess
 
3175
communication between KDE applications. KDE already has an extremely
 
3176
simple IPC mechanism called KWMcom, which is (was!) used for communicating
 
3177
between the panel and the window manager for instance.  It is about as
 
3178
simple as it gets, passing messages via X Atoms.  For this reason it
 
3179
is limited in the size and complexity of the data that can be passed
 
3180
(X atoms must be small to remain efficient) and it also makes it so
 
3181
that X is required.  CORBA was thought to be a more effective IPC/RPC
 
3182
solution.  However, after a year of attempting to make heavy use of
 
3183
CORBA in KDE, we have realized that it is a bit slow and memory
 
3184
intensive for simple use.  It also has no authentication available.</para>
 
3185
 
 
3186
<para>What we really needed was an extremely simple protocol with basic
 
3187
authorization, along the lines of MIT-MAGIC-COOKIE, as used by X.  It
 
3188
would not be able to do NEARLY what CORBA was able to do, but for the
 
3189
simple tasks required it would be sufficient. Some examples of such
 
3190
tasks might be an application sending a message to the panel saying,
 
3191
"I have started, stop displaying the 'application starting' wait
 
3192
state," or having a new application that starts query to see if any
 
3193
other applications of the same name are running.  If they are, simply
 
3194
call a function on the remote application to create a new window,
 
3195
rather than starting a new process.</para>
 
3196
</sect1>
 
3197
 
 
3198
<sect1 id="implementation">
 
3199
<title>Implementation</title>
 
3200
 
 
3201
<para>DCOP is a simple IPC/RPC mechanism built to operate over sockets.
 
3202
Either unix domain sockets or tcp/ip sockets are supported. DCOP is
 
3203
built on top of the Inter Client Exchange (ICE) protocol, which comes
 
3204
standard as a part of X11R6 and later. It also depends on Qt, but
 
3205
beyond that it does not require any other libraries. Because of this,
 
3206
it is extremely lightweight, enabling it to be linked into all KDE
 
3207
applications with low overhead.</para>
 
3208
 
 
3209
<sect2 id="model">
 
3210
<title>Model</title>
 
3211
 
 
3212
<para>The model is simple.  Each application using DCOP is a client.  They
 
3213
communicate to each other through a DCOP server, which functions like
 
3214
a traffic director, dispatching messages/calls to the proper
 
3215
destinations.  All clients are peers of each other.</para>
 
3216
 
 
3217
<para>Two types of actions are possible with DCOP: "send and forget"
 
3218
messages, which do not block, and "calls," which block waiting for
 
3219
some data to be returned.</para>
 
3220
 
 
3221
<para>Any data that will be sent is serialized (marshalled, for you CORBA
 
3222
types) using the built-in QDataStream operators available in all of the
 
3223
Qt classes.  This is fast and easy.  Currently, there is no
 
3224
type checking or parameter checking available for RPC, but this may be
 
3225
provided at some time in the future in the form of a simple IDL-like
 
3226
compiler (NOTE: 5 days later the IDL compiler is already started;
 
3227
look in dcopidl/).  Until that is available, you will have to code
 
3228
some things by hand that normally the compiler or CORBA take care of
 
3229
automatically, but it is not a lot of work.</para>
 
3230
</sect2>
 
3231
 
 
3232
<sect2 id="establishing-the-connection">
 
3233
<title>Establishing the Connection</title>
 
3234
 
 
3235
<para>KApplication has gained a method called "KApplication::dcopClient()"
 
3236
which returns a pointer to a DCOPClient instance.  The first time this
 
3237
method is called, the client class will be created.  DCOPClients have
 
3238
unique identifiers attached to them which are based on what
 
3239
KApplication::name() returns.  In fact, if there is only a single
 
3240
instance of the program running, the appId will be equal to
 
3241
KApplication::name().</para>
 
3242
 
 
3243
<para>To actually enable DCOP communication to begin, you must use
 
3244
DCOPClient::attach().  This will attempt to attach to the DCOP server.
 
3245
If no server is found or there is any other type of error, attach()
 
3246
will return false.  Applications which are DCOP-enabled should
 
3247
probably do something like this at startup time:</para>
 
3248
 
 
3249
<para><programlisting>client = kApp-&gt;dcopClient();
 
3250
if (!client-&gt;attach()) {
 
3251
  QMessageBox::error(this, i18n("Error connecting to DCOP server"),
 
3252
                     i18n("There was an error connecting to the Desktop\n"
 
3253
                          "communications server.  Please make sure that\n"
 
3254
                          "the 'dcopserver' process has been started, and\n"
 
3255
                          "then try again.\n"));
 
3256
  exit(1);
 
3257
}</programlisting>
 
3258
</para>
 
3259
 
 
3260
<para>After connecting with the server via DCOPClient::attach(), you need to
 
3261
register this appId with the server so it knows about you.  Otherwise,
 
3262
you are communicating anonymously.  Use the
 
3263
DCOPClient::registerAs(const QCString &&amp;;name) to do so.  In the simple
 
3264
case:
 
3265
<programlisting>/*
 
3266
 * returns the appId that is actually registered, which _may_ be
 
3267
 * different from what you passed
 
3268
 */
 
3269
appId = client-&gt;registerAs(kApp-&gt;name());</programlisting>
 
3270
</para>
 
3271
 
 
3272
<para>If you never retrieve the DCOPClient pointer from KApplication, the
 
3273
object will not be created and thus there will be no memory overhead.</para>
 
3274
 
 
3275
<para>You may also detach from the server by calling DCOPClient::detach().
 
3276
If you wish to attach again you will need to re-register as well.  If
 
3277
you only wish to change the ID under which you are registered, simply
 
3278
call DCOPClient::registerAs() with the new name.</para>
 
3279
</sect2>
 
3280
 
 
3281
<sect2 id="sending-data-to-a-remote-application">
 
3282
<title>Sending Data to a Remote Application</title>
 
3283
 
 
3284
<para>To actually communicate, you have one of two choices.  You may either
 
3285
call the "send" or the "call" method.  Both methods require three
 
3286
identification parameters: an application identifier, a remote object,
 
3287
a remote function. Sending is asynchronous (i.e. it returns immediately)
 
3288
and may or may not result in your own application being sent a message at
 
3289
some point in the future. Then "send" requires one and "call" requires
 
3290
two data parameters.</para>
 
3291
 
 
3292
<para>The remote object must be specified as an object hierarchy.  That is,
 
3293
if the toplevel object is called "fooObject" and has the child
 
3294
"barObject", you would reference this object as "fooObject/barObject".
 
3295
Functions must be described by a full function signature.  If the
 
3296
remote function is called "doIt", and it takes an int, it would be
 
3297
described as "doIt(int)".  Please note that the return type is not
 
3298
specified here, as it is not part of the function signature (or at
 
3299
least the C++ understanding of a function signature).  You will get
 
3300
the return type of a function back as an extra parameter to
 
3301
DCOPClient::call().  See the section on call() for more details.</para>
 
3302
 
 
3303
<para>In order to actually get the data to the remote client, it must be
 
3304
"serialized" via a QDataStream operating on a QByteArray. This is how
 
3305
the data parameter is "built". A few examples will make clear how this
 
3306
works.</para>
 
3307
 
 
3308
<para>Say you want to call "doIt" as described above, and not block (or wait
 
3309
for a response).  You will not receive the return value of the remotely
 
3310
called function, but you will not hang while the RPC is processed either.
 
3311
The return value of send() indicates whether DCOP communication succeeded
 
3312
or not.</para>
 
3313
 
 
3314
<para><programlisting>QByteArray params;
 
3315
QDataStream stream(params, IO_WriteOnly);
 
3316
params &lt;&lt; 5;
 
3317
if (!client-&gt;send("someAppId", "fooObject/barObject", "QString doIt(int)",
 
3318
                  params))
 
3319
  qDebug("there was some error using DCOP.");</programlisting>
 
3320
</para>
 
3321
 
 
3322
<para>OK, now let's say we wanted to get the data back from the remotely
 
3323
called function.  You have to execute a call() instead of a send().
 
3324
The returned value will then be available in the data parameter "reply".
 
3325
The actual return value of call() is still whether or not DCOP
 
3326
communication was successful.</para>
 
3327
 
 
3328
<para><programlisting>QByteArray params, reply;
 
3329
QCString replyType;
 
3330
QDataStream stream(params, IO_WriteOnly);
 
3331
params &lt;&lt; 5;
 
3332
if (!client-&gt;call("someAppId", "fooObject/barObject", "doIt(int)",
 
3333
                  params, replyType, reply))
 
3334
  qDebug("there was some error using DCOP.");
 
3335
else {
 
3336
  QDataStream stream2(reply, IO_ReadOnly);
 
3337
  if (replyType == "QString") {
 
3338
    QString result;
 
3339
    stream2 &gt;&gt; result;
 
3340
    print("the result is: %s",result.latin1());
 
3341
  } else
 
3342
    qDebug("doIt returned an unexpected type of reply!");
 
3343
}
 
3344
</programlisting>
 
3345
</para>
 
3346
</sect2>
 
3347
 
 
3348
<sect2 id="receiving-data-via-dcop">
 
3349
<title>Receiving Data via DCOP</title>
 
3350
 
 
3351
<para>Currently the only real way to receive data from DCOP is to multiply
 
3352
inherit from the normal class that you are inheriting (usually some
 
3353
sort of QWidget subclass or QObject) as well as the DCOPObject class.
 
3354
DCOPObject provides one very important method: DCOPObject::process().
 
3355
This is a pure virtual method that you must implement in order to
 
3356
process DCOP messages that you receive.  It takes a function
 
3357
signature, QByteArray of parameters, and a reference to a QByteArray
 
3358
for the reply data that you must fill in.</para>
 
3359
 
 
3360
<para>Think of DCOPObject::process() as a sort of dispatch agent.  In the
 
3361
future, there will probably be a precompiler for your sources to write
 
3362
this method for you.  However, until that point you need to examine
 
3363
the incoming function signature and take action accordingly.  Here is
 
3364
an example implementation.</para>
 
3365
 
 
3366
<para><programlisting>bool BarObject::process(const QCString &&amp;;fun, const QByteArray &&amp;;data,
 
3367
                        QCString &&amp;;replyType, QByteArray &&amp;;replyData)
 
3368
{
 
3369
  if (fun == "doIt(int)") {
 
3370
    QDataStream stream(data, IO_ReadOnly);
 
3371
    int arg;
 
3372
    QString res;
 
3373
    stream &gt;&gt; arg;
 
3374
    res = self-&gt;doIt(arg);
 
3375
    QDataStream stream2(replyData, IO_WriteOnly);
 
3376
    stream2 &lt;&lt; res;
 
3377
    replyType = "QString";
 
3378
    return true;
 
3379
  } else {
 
3380
    qDebug("unknown function call to BarObject::process()");
 
3381
    return false;
 
3382
  }
 
3383
}</programlisting>
 
3384
</para>
 
3385
</sect2>
 
3386
</sect1>
 
3387
 
 
3388
<sect1 id="conclusion">
 
3389
<title>Conclusion</title>
 
3390
 
 
3391
<para>Hopefully this document will get you well on your way into the world
 
3392
of inter-process communication with KDE!  Please direct all comments
 
3393
and/or suggestions to Preston Brown <ulink url="mailto:pbrown@kde.org">&lt;pbrown@kde.org&gt;</ulink>.</para>
 
3394
 
 
3395
<sect2 id="performance-tests">
 
3396
<title>Performance Tests</title>
 
3397
 
 
3398
<para>A few back-of-the-napkin tests folks:</para>
 
3399
 
 
3400
<para>Code:
 
3401
<programlisting>#include &lt;kapp.h&gt;
 
3402
 
 
3403
int main(int argc, char **argv)
 
3404
{
 
3405
  KApplication *app;
 
3406
 
 
3407
  app = new KApplication(argc, argv, "testit");
 
3408
  return app-&gt;exec();
 
3409
}</programlisting>
 
3410
 
 
3411
Compiled with:</para>
 
3412
 
 
3413
<para>g++ -O2 -o testit testit.cpp -I$QTDIR/include -L$QTDIR/lib -lkdecore</para>
 
3414
 
 
3415
<para>on Linux yields the following memory use statistics:
 
3416
<screen>VmSize:     8076 kB
 
3417
VmLck:         0 kB
 
3418
VmRSS:      4532 kB
 
3419
VmData:      208 kB
 
3420
VmStk:        20 kB
 
3421
VmExe:         4 kB
 
3422
VmLib:      6588 kB
 
3423
</screen>
 
3424
</para>
 
3425
 
 
3426
<para>If I create the KApplication's DCOPClient, and call attach() and
 
3427
registerAs(), it changes to this:</para>
 
3428
 
 
3429
<para><screen>VmSize:     8080 kB
 
3430
VmLck:         0 kB
 
3431
VmRSS:      4624 kB
 
3432
VmData:      208 kB
 
3433
VmStk:        20 kB
 
3434
VmExe:         4 kB
 
3435
VmLib:      6588 kB
 
3436
</screen>
 
3437
</para>
 
3438
 
 
3439
<para>Basically it appears that using DCOP causes 100k more memory to be
 
3440
resident, but no more data or stack.  So this will be shared between all
 
3441
processes, right?  100k to enable DCOP in all apps doesn't seem bad at
 
3442
all. :)</para>
 
3443
 
 
3444
<para>OK now for some timings.  Just creating a KApplication and then exiting
 
3445
(i.e. removing the call to KApplication::exec) takes this much time:</para>
 
3446
 
 
3447
<para>0.28user 0.02system 0:00.32elapsed 92&&percnt;;CPU (0avgtext+0avgdata 0maxresident)k
 
3448
0inputs+0outputs (1084major+62minor)pagefaults 0swaps</para>
 
3449
 
 
3450
<para>I.e. about 1/3 of a second on my PII-233.  Now, if we create our DCOP
 
3451
object and attach to the server, it takes this long:</para>
 
3452
 
 
3453
<para>0.27user 0.03system 0:00.34elapsed 87&&percnt;;CPU (0avgtext+0avgdata 0maxresident)k
 
3454
0inputs+0outputs (1107major+65minor)pagefaults 0swaps</para>
 
3455
 
 
3456
<para>I.e. about 1/3 of a second.  Basically DCOPClient creation and attaching
 
3457
gets lost in the statistical variation ("noise").  I was getting times
 
3458
between .32 and .48 over several runs for both of the example programs, so
 
3459
obviously system load is more relevant than the extra two calls to
 
3460
DCOPClient::attach and DCOPClient::registerAs, as well as the actual
 
3461
DCOPClient constructor time.</para>
 
3462
</sect2>
 
3463
</sect1>
 
3464
</chapter>
 
3465
 
 
3466
<chapter id="copyright-0">
 
3467
<title>Copyright</title>
 
3468
 
 
3469
<para><screen>
 
3470
KDevelop Copyright 1998, 1999, 2000 The KDevelop Team.
 
3471
 
 
3472
This program is free software; you can redistribute it and/or modify
 
3473
it under the terms of the GNU General Public License as published by
 
3474
the Free Software Foundation; either version 2 of the License, or
 
3475
(at your option) any later version.
 
3476
 
 
3477
This program is distributed in the hope that it will be useful,
 
3478
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
3479
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
3480
GNU General Public License for more details.
 
3481
 
 
3482
You should have received a copy of the GNU General Public License
 
3483
along with this program; if not, write to the Free Software
 
3484
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
3485
</screen>
 
3486
</para>
 
3487
 
 
3488
<para>Each chapter of this handbook contains the documentation of the according authors, therefore the copyright remains on the side of
 
3489
those. This handbook has been assembled by agreement with each author about the usage of his documentation. Reprint is therefore only
 
3490
allowed on agreement with the KDevelop Team and the authors of each chapter.</para>
 
3491
 
 
3492
<para>KDevelop is Copyright 1998,1999,2000 The KDevelop Team.</para>
 
3493
 
 
3494
<para>This handbook itself is part of the KDevelop Intergrated Development environment.</para>
 
3495
 
 
3496
<para><link linkend="mini-HOWTO">The KDE Developer's mini-HOWTO</link> is copyright of David Sweet.<ulink url="mailto:dsweet@chaos.umd.edu">&lt;dsweet@chaos.umd.edu&gt;</ulink></para>
 
3497
 
 
3498
<para><link linkend="KOMOP">KDE KOM / OpenParts</link> is copyright of Torben Weis <ulink url="mailto:weis@kde.org">&lt;weis@kde.org&gt;</ulink> and
 
3499
Bernd Wuebben <ulink url="mailto:wuebben@kde.org">&lt;wuebben@kde.org&gt;</ulink></para>
 
3500
 
 
3501
<para><link linkend="KOMHOWTO">Using KDE KOM / OpenParts HOWTO</link> and <link linkend="KDEDAEMON">The KDE Daemon</link> are copyright of Simon
 
3502
Hausmann <ulink url="mailto:hausmann@kde.org">&lt;hausmann@kde.org&gt;</ulink></para>
 
3503
 
 
3504
<para><link linkend="DCOP">DCOP: Desktop COmmunications Protocol</link> is copyright of Preston Brown <ulink url="mailto:pbrown@kde.org">&lt;pbrown@kde.org&gt;</ulink></para>
 
3505
</chapter>
 
3506
<appendix id="glossary">
 
3507
<title>Glossary</title>
 
3508
 
 
3509
<para><variablelist>
 
3510
<varlistentry>
 
3511
<term>CORBA</term>
 
3512
<listitem>
 
3513
<para>Common Object Request Broker Architecture, standard introduced by the OMG for distributed components that can be used
 
3514
independently of platform, implementation and operating system. CORBA itself is only the standard which requires a corresponding
 
3515
implementation that fulfills the requirements of the standard. KDE uses the MICO implementation, which provides a C++ interface to
 
3516
CORBA services.</para>
 
3517
</listitem>
 
3518
</varlistentry>
 
3519
<varlistentry>
 
3520
<term>BOA</term>
 
3521
<listitem>
 
3522
<para>Basic Object Adapter. Interface defined by the OMG, which offers fundamental operations for managing remote objects.</para>
 
3523
</listitem>
 
3524
</varlistentry>
 
3525
<varlistentry>
 
3526
<term>COS</term>
 
3527
<listitem>
 
3528
<para>Common Object Services. Collection of standard services to simplify developing standard applications. Naming, Event and
 
3529
Lifecycle-services are a part of the COS collection.</para>
 
3530
</listitem>
 
3531
</varlistentry>
 
3532
<varlistentry>
 
3533
<term>DII</term>
 
3534
<listitem>
 
3535
<para>Dynamic Invocation Interface, interface to execute dynamic invocations in opposition to static invocations (clent side)</para>
 
3536
</listitem>
 
3537
</varlistentry>
 
3538
<varlistentry>
 
3539
<term>Dynamic Invocation</term>
 
3540
<listitem>
 
3541
<para>Creation and execution of a request, whose signature is probably first known at runtime in opposition to
 
3542
static invocation.</para>
 
3543
</listitem>
 
3544
</varlistentry>
 
3545
<varlistentry>
 
3546
<term>DSI</term>
 
3547
<listitem>
 
3548
<para>Dynamic Skeleton Interface. Server side in opposition to a DII.</para>
 
3549
</listitem>
 
3550
</varlistentry>
 
3551
<varlistentry>
 
3552
<term>GIOP</term>
 
3553
<listitem>
 
3554
<para>General-Inter-ORB-Protocol</para>
 
3555
</listitem>
 
3556
</varlistentry>
 
3557
<varlistentry>
 
3558
<term>IIOP</term>
 
3559
<listitem>
 
3560
<para>Internet-Inter-ORB-Protocol</para>
 
3561
</listitem>
 
3562
</varlistentry>
 
3563
<varlistentry>
 
3564
<term>IMR</term>
 
3565
<listitem>
 
3566
<para>Implementation Repository</para>
 
3567
</listitem>
 
3568
</varlistentry>
 
3569
<varlistentry>
 
3570
<term>IOR</term>
 
3571
<listitem>
 
3572
<para>Interoperable Object Reference. The reference is specificated in the two parts GIOP and IIOP.</para>
 
3573
</listitem>
 
3574
</varlistentry>
 
3575
<varlistentry>
 
3576
<term>IDL</term>
 
3577
<listitem>
 
3578
<para>Interface Definition Language. C++-Syntax similar programming language to describe object interfaces. The implementation
 
3579
translates IDL's to their target programming language.</para>
 
3580
</listitem>
 
3581
</varlistentry>
 
3582
<varlistentry>
 
3583
<term>Interface</term>
 
3584
<listitem>
 
3585
<para>in CORBA, all exported methods and attributes of an object are called an interface, whereby these are defined in IDL.
 
3586
Elements which are not specified in the interface are not accessible by clients.</para>
 
3587
</listitem>
 
3588
</varlistentry>
 
3589
<varlistentry>
 
3590
<term>IOP</term>
 
3591
<listitem>
 
3592
<para>Interoperability Profile</para>
 
3593
</listitem>
 
3594
</varlistentry>
 
3595
<varlistentry>
 
3596
<term>MICO</term>
 
3597
<listitem>
 
3598
<para>free implementation of the CORBA standard. KDE's KOM/OpenParts technology is based on the MICO implementation.</para>
 
3599
</listitem>
 
3600
</varlistentry>
 
3601
<varlistentry>
 
3602
<term>OMA</term>
 
3603
<listitem>
 
3604
<para>Object Management Architecture</para>
 
3605
</listitem>
 
3606
</varlistentry>
 
3607
<varlistentry>
 
3608
<term>OMG</term>
 
3609
<listitem>
 
3610
<para>Object Management Group</para>
 
3611
</listitem>
 
3612
</varlistentry>
 
3613
<varlistentry>
 
3614
<term>ORB</term>
 
3615
<listitem>
 
3616
<para>Object Request Broker, abstract name for the communication service between clients and remote objects.</para>
 
3617
</listitem>
 
3618
</varlistentry>
 
3619
<varlistentry>
 
3620
<term>POA</term>
 
3621
<listitem>
 
3622
<para>Portable Object Adapter. The POA extends the features the BOA provides; introduced in the CORBA 2.2 standard.</para>
 
3623
</listitem>
 
3624
</varlistentry>
 
3625
</variablelist>
 
3626
</para>
 
3627
  </appendix>
 
3628
<![ %addindex; [ &docindex; ]]>
 
3629
</book>
 
3630
<!--
 
3631
Local Variables:
 
3632
mode: sgml
 
3633
sgml-omittag: nil
 
3634
sgml-shorttag: t
 
3635
sgml-general-insert-case: lower
 
3636
End:
 
3637
-->