|
|
Developing Filters for KOfficePrepare the Environment
As KOffice needs KDE 2 it's necessary to install at least parts of KDE 2
(Qt+patch, kdesupport, kdelibs, kdebase - exactly in this order) and - of course -
KOffice. I recommend looking for further information on
how to install it. To get some help from real KOffice experts please
join the KOffice mailing list (koffice@kde.org).
One final hint: Add -debug to your ./configure
options for Qt and --enable-debug to your ./configure
options for all KDE packages. The resulting binaries are quite large and a little bit
slower, but nonetheless this is an enormous help if you are developing (=debugging :)
something. Oh, and use gdb-4.18 or later, because gdb-4.17
always crashed on KOffice stuff (at least for me).
Behind the Scenes
There are several ways for programming a filter depending on your needs.
However, unless you really need a non-standard filtering method (e.g.
because you'd like to import huge amounts of data and the performance is bad)
we recommend using the plain and easy standard method. All the following
descriptions are based on the assumption that you use the standard filtering
method. The gory details about the optimized (read: hacky) methods of filtering
are provided at the bottom of this page (Note: I didn't add a link, because you
have to scroll the standard description, at least :).
KOffice uses a quite straightforward approach to convert files to the native
format of the matching KOffice part. I'll try to explain this via a simple
example (from the user's point of view) before providing further (more detailed)
information:
- The user activates
File -> Open...
- The file dialog pops up
- She/He selects a file extension (e.g. *.csv (=Comma Separated Value))
- Now the file dialog shows only the matching files
- Depending on the filter, the user might see a configuration dialog. This
(optional) dialog is "embedded" in the file dialog. It can be used to pass
configuration options to the filter (i.e. a kind of replacement for commandline
arguments)
- After selecting a file she/he presses
Ok
- The filter converts the file to KSpread's native format (taking the
configuartion options into account)
- KSpread opens a (native!) file
- The user is happy :)
When saving documents the filtering works nearly identical. The whole
process of looking for available filters,... is done by the KOffice Libraries
so you don't have to care about that. As you can see there is no magic
involved and as we now know the basics let's have a look how this really works!
After the user clicked File -> Open... the part queries the
KoFilterManager (koffice/lib/kofficecore/koFilterManager.cc) to
prepare the file dialog. The filter manager (=KoFilterManager)
queries the trader for information on the supported filter types (e.g. HTML,
TXT,...) and configuration dialogs. Then it prepares the KFD (K File Dialog)
to show all this stuff. The file dialog pops up and now the user can select
a specific filter (e.g. '*.csv'). After selecting a file (with the correct
extension - the file dialog ensures that) the user might have to set some
configuration options (Note: You don't have to provide such a dialog, it's
just a nifty feature for some obscure filters which need passwords and so on
(i.e. some kind of user input)!),
clicks Ok and the filename is returned to the part. The part
passes the filename to the filter manager. The filter manager checks whether
the file is native or not. If if is native, the filter manager returns the
name and the part opens it. If it is not, the filter manager returns another
filename - this is the name of the converted file (a temporary file somewhere
in /tmp). Finally the part opens the converted (=native) file.
But when does the real converting occur? Let's see... the filter manager gets
the filename (and the mimetype of the calling part). It tries to find out the
mimetype of the file which should be opened. Then the trader is queried if
there is a filter which is able to handle those two mimetypes (the one of the
file to convert and the native format of the application, e.g. HTML -> KWord).
If such a filter is found the filter manager loads it and passes the information
of the optional configuration dialog.
Filters are shared libs which are opened on demand (via KLibLoader,
which is a wrapper for dlopen) and closed after a few minutes of inactivity
(so that we don't waste too much memory). All the filters have to inherit
KoFilter (koffice/lib/kofficecore/koFilter.h) and they have to
override the pure virtual method filter(...). This method is called
by the filter manager (for details see below) and the filter starts to convert the
file (i.e. opens the file, reads it, converts the contents, writes it).
How to Develop a Filter?
Please have a look at koffice/filters/kword/ascii/asciiimport* if you want to
write an import filter, at koffice/filters/kword/ascii/asciiexport* if you
want to write an export filter. (and exchange "import" by "export" below). To
create a filter you have to:
- Copy the appropriate files from the koffice/filters/kword/ascii directory
to a separate directory (at least Makefile.am, asciiimport*, and
kword_ascii_import.desktop).
- Create a "factory" class for your filter. This factory is needed to load
the filter (as we've heard, technically the filter is a shared library which
is "dlopened" on demand). You only have to change all the names in
'asciiimport_factory.cc' and 'asciiimport_factory.h' (i.e. all the
ASCII,
Ascii, and ascii stuff has to be replaced by YOURFILTER
, YourFilter, and yourfilter).
- Derive your "main-filter-class" from
KoFilter. Look at
'asciiimport.cc' and 'asciiimport.h' how this is done. Don't forget that you
have to include or link the moc file - otherwise the filter won't work!
(the classname is needed during "incarnation," and all this information is
stored in those nifty little moc files).
- Rename the files (ascii* -> yourfilter*) if you haven't done this, yet.
- Add your classes (i.e. the files containing the C++ headers/sources)
which are needed to convert the file (for an example have a look at the
export filter in koffice/filters/kword/html/). Remember: The filter is a
"normal" library, so you may do whatever you can do with libraries :)
- Adjust the *.desktop file (Note: You'll have to rename the file or it won't
work correctly because you'll overwrite something!). In the file you'll have to
change the "Name", "Comment", "Export", "ExportDescription", "Import",
"ImportDescription", "X-KDE-Library", and probably the "Icon" and "MiniIcon" fields.
- If KDE doesn't "know" your filetype up to now, please add a x-*.desktop
file (see koffice/filters/kspread/csv). Make sure that it gets installed to
the correct directory. If KDE knows your filetype, you don't have to care about
that.
- Adapt the local Makefile.am by renaming/adding files to meet your needs.
- If your directory is located somewhere in the koffice/filters directory,
just add your directory to the Makefile.am file of the parent directory. Execute
make -f Makefile.cvs in the top directory (koffice/) (or use
create_makefile(s) from kdesdk/scripts) and ./configure the whole
stuff again. If it compiles you've won :) .
Install (make install) and test it...
To create an optional configuration dialog you have to:
- Create a "factory" class for the dialog (like for the filter above). If
you look for an example/template: koffice/filters/kspread/csv/csvfilterdia* is
quite straightforward.
- Design and implement the real dialog. It has to inherit
KoFilterDialog.
Of course you have to override the pure virtual method state(). This
method returns a QString which contains the configuration information.
You might want to use some Qt geometry management magic to make the dialog look nice.
- The format of this string is up to you, but I suggest using a simple
XML-like format (using QDom/QXML) because it's easy to debug.
- Create (or modify) the .desktop file (template from the CSV filter)
- Extend the Makefile.am file (see koffice/kspread/csv/Makefile.am for details)
and re-run
make -f Makefile.cvs and ./configure.
- Make sure that your dialog neither has any
Ok and/or Cancel
buttons, nor menubars/toolbars. Shortly put: Make it really simple.
- Note: A KOffice part may be launched from the commandline passing a filename.
This file gets opened regardless if it is a native one or not. Of course then no
file dialog gets opened and your dialog is not shown. You can detect this situation
by testing the QString in the filter() method against QString::null. If you still
want to have the dialog, you have to show it "manually." To give you some ideas:
Fist you have to load the dialog's lib (via KLibLoader) and use the factory class
to create a dialog (maybe you'll have to adapt the factory class to be able to do
that). Then you'll have to create a real dialog (with an
Ok
button, at least) and embed your configuration dialog (i.e. the real dialog
is the parent of your dialog widget). Then wait for the user to click Ok
and use the dialog's status() method to read the information.
Wow - you wrote a filter! But what now? You don't have a CVS account and you
want to check it in? No problem. Please send all the files to me, Werner Trobin,
<trobin@kde.org>. Note: It's
no problem whatsoever if you send your "drafts" - that's what CVS is good for!
Most Wanted
At the moment I think the "most wanted" filter would be a RTF import and
export filter for KWord as you can exchange RTF documents with nearly all
office suites. Obviously there is more need for KWord and KSpread filters
than for KPresenter filters.
Remaining Questions?
Feel free to ask me if there are
any remaining questions. BTW: It's generally a good idea to ask on koffice@kde.org
whether anyone works on a filter before starting to implement it :)
Goodies
This section contains some useful documentation (I'll add more stuff here,
soon):
Special Filters
As I already said above sometimes the standard filter interface is just a little
bit to slow, complicated(?!?), annoying,... To prevent you from trying to
circumvent our interface we've done it for you, already. It's not clean, it's not
save, but it should at least be fast. Once again I'd like to warn you, but I'm sure
you won't listen to me, anyways.
If you read the definiton of the KoFilter class, you can see that
there are more pure virtual methods, than just filter(...):
virtual const bool I_filter(const QCString &file, const QCString &from,
QDomDocument &doc, const QCString &to, const QString &config=QString::null);
This method can only be used to import documents (hence the 'I_'). The difference to
the standard method is that you don't write to a file, but to a QDomDocument. This
document is opened directly from the KOffice application. The advantage is, that
there are no temporary files involved; the disadvantage is, that the application
has to support it. At the moment only KSpread supports this kind of import.
virtual const bool I_filter(const QCString &file, KoDocument *document,
const QCString &from, const QCString &to, const QString &config=QString::null);
This one is even more hacky than the above one (and it's also for importing documents).
Here you get direct access to an empty KoDocument(!). Please use this one only in
very rare cases (e.g. where you have to transfer enormous amounts of data). Another
huge disadvantage of that method (besides being insecure) is, that you'll have to
change the filter, if the interface of the part changes.
virtual const bool E_filter(const QCString &file, const KoDocument * const document,
const QCString &from, const QCString &to, const QString &config=QString::null);
Well - that's still not enough for you? This method delivers a KoDocument which is
used by the application (i.e. it's "full," not empty like the above one). Of course
this method is used to export documents. Did I already say that you should use this
method only if this is the only way out?
If you need some inspiration how to implement these kinds of methods, just have a look
at koffice/filters/kspread/csv. You surely already know, that you can even use a
configuration dialog with these filtering methods, too.
Maintained by the KOffice Web team.
Last modified May 05, 2000.
|