First at all, why writing plugins for an editor ? Good question, and I hope I have a good answer: Because we want the base app be small and all extended features not all users need should go into plugins (like CVS suppport, project managment, coffee cooking ;) Therefore Kate provides a quite fullfeatured plugin interface and interfaces to all important stuff in the kate application (the documents, views, mainwindows, sidebar ...).
This tutorial is for people knowing the Qt/KDE libs (and how to code regular KDE apps) and will not describe how to compile, make ... a kde/qt program/lib in detail.
The "helloworld" plugin which is here described can be found in the "kdeaddons" package of kde (located in kdeaddons/kate/helloworld). A detailed description of the Kate API is available here..
Like in each programming language learning book I start with an easy "Hello World!" plugin, too ;) This plugin only implements a menuitem and inserts the string "Hello World!" into the current document. The example should show only the basic stuff you need to get your first plugin running, extensions won't be too hard because some existing plugins in kdeaddons are available to steal some code and the API is quiet self-explaining (I hope ;)
Each plugin consists of at least 3 files which are needed:
The desktop file needs the syntax shown here and must be located in kde services directory with the name kate"yourpluginname".desktop,
Example: katehelloworld.desktop
[Desktop Entry] Type=Service ServiceTypes=Kate/Plugin X-KDE-Library=katehelloworldplugin X-Kate-Version=2.5 Name=My first Kate Plugin Comment=Your short description about the plugin goes here
To get your file to kde services dir, for example in kde cvs the entry:
kde_services_DATA = katehelloworld.desktop
in your Makefile.am will do the trick, or manually copy it to $(kdedir)/share/services
The "X-Kate-Version=2.5" line is important! Kate 2.2 and up won't load your plugin unless the property is similar to the version with which you want to use the plugin!
The xmlGUI file must be named ui.rc and installed into $(kde_datadir)/kate/plugins/kate"yourpluginname". The content is free (should describe your needed menuitems + button for the plugin GUI ;)
Example: ui.rc for katehelloworldplugin
<!DOCTYPE kpartgui>
<kpartplugin name="katehelloworld" library="libkatehelloworldplugin" version="1">
<MenuBar>
<Menu name="edit"><Text>&Edit</Text>
<Action name="edit_insert_helloworld" />
</Menu>
</MenuBar>
</kpartplugin>
Each kate plugin is a lib which will be dynamically loaded by kate via KLibLoader. The name of the lib must be kate"yourpluginname"plugin.la and should be installed into the kde module dir.
Short example out of helloworld plugin Makefile.am
# Install this plugin in the KDE modules directory kde_module_LTLIBRARIES = katehelloworldplugin.la katehelloworldplugin_la_SOURCES = plugin_katehelloworld.cpp katehelloworldplugin_la_LIBADD = -lkateinterfaces katehelloworldplugin_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
Now we can start with the real coding, The Hello World! plugin consists of 2 files, plugin_katehelloworld.cpp and .h.
#ifndef _PLUGIN_KATE_HELLOWORLD_H_
#define _PLUGIN_KATE_HELLOWORLD_H_
#include <kate/application.h>
#include <kate/documentmanager.h>
#include <kate/document.h>
#include <kate/mainwindow.h>
#include <kate/plugin.h>
#include <kate/view.h>
#include <kate/viewmanager.h>
#include <klibloader.h>
#include <klocale.h>
class KatePluginFactory : public KLibFactory
{
Q_OBJECT
public:
KatePluginFactory();
virtual ~KatePluginFactory();
virtual QObject* createObject( QObject* parent = 0,
const char* pname = 0,
const char* name = "QObject",
const QStringList &args = QStringList() );
private:
static KInstance* s_instance;
};
class KatePluginHelloWorld : public Kate::Plugin, Kate::PluginViewInterface
{
Q_OBJECT
public:
KatePluginHelloWorld( QObject* parent = 0, const char* name = 0 );
virtual ~KatePluginHelloWorld();
void addView (Kate::MainWindow *win);
void removeView (Kate::MainWindow *win);
public slots:
void slotInsertHello();
private:
QPtrList<class PluginView> m_views;
};
#endif
#ifndef _PLUGIN_KATE_HELLOWORLD_H_ #define _PLUGIN_KATE_HELLOWORLD_H_
Avoids the file to be included more than once.
#include <kate/application.h> #include <kate/docmanager.h> #include <kate/document.h> #include <kate/mainwindow.h> #include <kate/plugin.h> #include <kate/view.h> #include <kate/viewmanager.h> #include <klibloader.h> #include <klocale.h>
Includes the Kate Plugin Interface headers and some other needed kde headers.
class KatePluginFactory : public KLibFactory
{
Q_OBJECT
public:
KatePluginFactory();
virtual ~KatePluginFactory();
virtual QObject* createObject( QObject* parent = 0,
const char* pname = 0,
const char* name = "QObject",
const QStringList &args = QStringList() );
private:
static KInstance* s_instance;
};
Standard factory, is the same in each Kate plugin, is needed to load the plugin nicely via KLibLoader.
class KatePluginHelloWorld : public Kate::Plugin, Kate::PluginViewInterface
{
Q_OBJECT
public:
KatePluginHelloWorld( QObject* parent = 0, const char* name = 0 );
virtual ~KatePluginHelloWorld();
void addView (Kate::MainWindow *win);
void removeView (Kate::MainWindow *win);
};
This methode create the GUI (via xmlGUI) of the plugin for each Kate MainWindow. (if you open a new
mainwindow in kate, addView will be called, if a main win will be destroyed, removeView will be called)
public slots:
void slotInsertHello();
private:
QPtrList<class PluginView> m_views;
};
#endif
KatePluginHelloWorld is the real plugin class in the file. derivered from Kate::Plugin.
#include "plugin_katehelloworld.h"
#include "plugin_katehelloworld.moc"
#include <kaction.h>
#include <klocale.h>
#include <kstandarddirs.h>
class PluginView : public KXMLGUIClient
{
friend class KatePluginHelloWorld;
public:
Kate::MainWindow *win;
};
extern "C"
{
void* init_katehelloworldplugin()
{
KGlobal::locale()->insertCatalogue("katehelloworld");
return new KatePluginFactory;
}
}
KatePluginFactory::KatePluginFactory()
{
s_instance = new KInstance( "kate" );
}
KatePluginFactory::~KatePluginFactory()
{
delete s_instance;
}
QObject* KatePluginFactory::createObject( QObject* parent,
const char* name,
const char*,
const QStringList & )
{
return new KatePluginHelloWorld( parent, name );
}
KInstance* KatePluginFactory::s_instance = 0L;
KatePluginHelloWorld::KatePluginHelloWorld( QObject* parent, const char* name )
: Kate::Plugin ( (Kate::Application*)parent, name )
{
}
KatePluginHelloWorld::~KatePluginHelloWorld()
{
}
void KatePluginHelloWorld::addView(Kate::MainWindow *win)
{
// TODO: doesn't this have to be deleted?
PluginView *view = new PluginView ();
(void) new KAction ( i18n("Insert Hello World"), 0, this,
SLOT( slotInsertHello() ),
view->actionCollection(),
"edit_insert_helloworld" );
view->setInstance (new KInstance("kate"));
view->setXMLFile("plugins/katehelloworld/ui.rc");
win->guiFactory()->addClient (view);
view->win = win;
m_views.append (view);
}
void KatePluginHelloWorld::removeView(Kate::MainWindow *win)
{
for (uint z=0; z < m_views.count(); z++)
if (m_views.at(z)->win == win)
{
PluginView *view = m_views.at(z);
m_views.remove (view);
win->guiFactory()->removeClient (view);
delete view;
}
}
void KatePluginHelloWorld::slotInsertHello()
{
Kate::View *kv = application()->activeMainWindow()->viewManager()->activeView();
if (kv)
kv->insertText ("Hello World");
}
#include "plugin_katehelloworld.h" #include "plugin_katehelloworld.moc" #include <kaction.h> #include <klocale.h> #include <kstddirs.h>
Include the header + moc file of the plugin + some kde includes needed by the plugin.
extern "C"
{
void* init_libkatehelloworldplugin()
{
return new KatePluginFactory;
}
}
Allow to load the lib via factory, init_libkatehelloworldplugin() must be renamed to init_libkate"yourpluginname"plugin() if you write your own plugin, it must match libname.
KatePluginFactory::KatePluginFactory()
{
s_instance = new KInstance( "kate" );
}
KatePluginFactory::~KatePluginFactory()
{
delete s_instance;
}
QObject* KatePluginFactory::createObject( QObject* parent,
const char* name, const char*,
const QStringList & )
{
return new KatePluginHelloWorld( parent, name );
}
KInstance* KatePluginFactory::s_instance = 0L;
Some factory stuff, same in each plugin, only the createObject methode must call the constructor of your plugin class.
KatePluginHelloWorld::KatePluginHelloWorld( QObject* parent,
const char* name )
: Kate::Plugin ( parent, name )
{
}
KatePluginHelloWorld::~KatePluginHelloWorld()
{
}
Constructor/Destructor of our example plugin class, nothing to do for us, only pass the arguments to Kate::Plugin.
void KatePluginHelloWorld::addView(Kate::MainWindow *win)
{
// TODO: doesn't this have to be deleted?
PluginView *view = new PluginView ();
(void) new KAction ( i18n("Insert Hello World"), 0, this,
SLOT( slotInsertHello() ), view->actionCollection(),
"edit_insert_helloworld" );
view->setInstance (new KInstance("kate"));
view->setXMLFile("plugins/katehelloworld/ui.rc");
win->guiFactory()->addClient (view);
view->win = win;
m_views.append (view);
}
Here the GUI is created. The connected slot is part of the helloworld
plugin class.
void KatePluginHelloWorld::slotInsertHello()
{
Kate::View *kv = application()->activeMainWindow()->viewManager()->activeView();
if (kv)
kv->insertText ("Hello World");
}
Here the actions takes place ;) This slot is called if you hit the "Insert Hello World" menuitem which is created by the pluginview.
application()->activeMainWindow()->viewManager()->activeView() gets the current active view of kate and kv->insertText("Hello World") inserts the text at the current cursor position. Done ;)
You first have to go to the settings->plugins->manager configpage in Kate and activate the Hello World plugin, after that you have a "Insert Hello World" menuitem in your edit menu like on the screenshot. If you activate the menuitem the text "Hello World" will appear at the cursorposition in your current document.
To get more information about the plugin interface and its advanced functions please look at the Kate API documentation or drop me a mail ;).
The complete sources (with Makefile.am) of this example can be found in kde cvs under kdeaddons/kate/helloworld or via webcvs here.
Comments
Nice
I have found two interesting sources and would like to give the benefit of my experience to you. I am tuning my pc by the best software for free, with the file search engine http://fileshunt.com and http://filesfinds.com May be you have your own experience and could give some useful sites too. Because this two social sites help me much.
Good to see, that there are
Good to see, that there are people that bother with this kind of information. Helloworld paruresis
services
Applications support plugins for many reasons. Some of the main reasons include: enabling third-party developers to create capabilities to extend an application, to support features yet unforeseen, reducing the size of an application, and separating source code from an application because of incompatible software licenses. mold removal
Plugin to modify printed output?
I’d like to print from Kate, but have the printout highlight alternating lines of text so lines that wrap will be visually easier to see. Is that possible with the Kate plugins, or do I need to look to something else? (I’m using Kubuntu 7.10)
A Letter to Kate
Just as a sidenote you might be interested in this letter from a certain J. Appleseed. :-)
/Andreas
make
compiling is most difficult to newbies; more difficult than reading and understanding sources !!!!
how to compile
Makefile.am Should this be compiled with automake?
automake:
configure.ac' orconfigure.in’ is requiredautom4te: configure.ac: no such file or directory
??
How can I compile it with automake? How to compile this by directly invoking gcc (if automake is not installed)?
Broken links
The link to KDE API documentation and the link to the source are broken. Particularly, the source link should point to the SVN not CVS ;-)
Post new comment