/** \file HowToAddPlugins.dox
* \brief How to extend TDevelop via plugins
*/
/** \page howToAddPlugins How to extend TDevelop via plugins
\section createDesktop Step 1: Make your plugin loadable
For a plugin foo
, create a file foo.desktop
which contains TDevelop/Part in its list of ServiceTypes.
- See parts/doctreeview/kdevdoctreeview.desktop
for an example.
.
If you install this file into \$(kde_servicesdir)
, your plugin will automatically be loaded.
\subsection changeLoading How to change the default loading
You can change the default loading by changing some settings in your foo.desktop
file:
- Set X-TDevelop-Scope=
to Global
or
Project
- Note: This property is not optional
.
- You can add a list of programming languages which are supported by your
plugin
- If your plugin works with all languages leave the
X-TDevelop-ProgrammingLanguages=
field empty
(optional)
.
- You can add a list of keywords.
- The plugin will only be loaded if all keywords match with the
Keywords=
field in the projectfile (optional).
.
.
An example from the Java Debugger Plugin:
#######################
X-TDevelop-Scope=Project
X-TDevelop-ProgrammingLanguages=Java
Keywords=
##########################
\section createFactory Step 2: Make the plugin accessible by the factory
Create a factory class FooFactory
which inherits
KDevFactory
. Put a section
extern "C" {
void *init_libfoo()
{
return new FooFactory;
}
}
into the source file, so that the factory can be accessed by KDE's library
loader. Keep in mind that the name of the method init_libfoo()
is
required for a library with the name libfoo.so
.
This may be simplified by the use of the
K_EXPORT_COMPONENT_FACTORY
macro which is defined in
klibloader.h
:
K_EXPORT_COMPONENT_FACTORY( libfoo, FooFactory );
- Note: Your factory must reimplement the
createPartObject()
method of KDevFactory
and
produce the part there.
.
See parts/doctreeview/doctreeviewfactory.cpp
for an example.
\section implementPart Step 3: Implement your part.
Your part must be derived from KDevPlugin
.
- KDevPlugin takes two arguments:
- 1) A parent argument. This also comes from
createPartObject()
.
- 2) A name, which in turn is given to the QObject
constructor.
.
.
\subsection accessIDE How to access other IDE components
A part can access other components of the IDE via some accessors
of KDevPlugin
:
- The application core via core()
,
- the build tools via project()
,
- the programming language specific stuff via
languageSupport()
,
- the make frontend via makeFrontend()
,
- the part which displays appication output via
appFrontend()
,
and finally
- the symbol database via classStore()
.
.
In order to see what these components provide, see lib/interfaces/kdev*.h
.
\subsection userPrefs How to store user preferences
Parts can also store user preferences on a per-project basis. To this
end, they can access a QDomDocument
representing the project file
(which is stored as xml) via document()
.
Take attention to the issue that the project file usually is shared in a team of
developers (e.g. via version control application CVS). So some user preferences might be
very individual, and some may be valid for all of the team - project-wide so to speak.
That's why the TDevelop architecture makes a difference here and supports two files
which will be stored in the project root directory. They are the project file (*.tdevelop)
and the session (*.kdevses) file. The later is for individual settings, not to be thought
to be shared.
\subsection domProject Project file (*.tdevelop)
For your convenience, you don't have to use the quite complex DOM API. Strings
can very easily be read from and written to this document using the
DomUtil
class. Here, entries are identified by a 'path' in the
document. You can think of the DOM document as representing a file system
rooted in the dom
document node.
For example, the autoproject
part uses the statement
QString cflags = DomUtil::readEntry( *part->document(),
"/kdevautoproject/cflags" );
to read the CFLAGS
variable set by the user, and uses the statement similar to
DomUtil::writeEntry( *part->document(),
"kdevautoproject/cflags",
"--no-exceptions" );
to write it back.
- Note: In order to avoid conflicts between different plugins, you
should use your part name as top-level 'directory' in the configuration
tree.
.
\subsection sessionAccess Project session file (*.kdevses)
The base class of all TDevelop plugins is KDevPlugin. It provides two virtual methods
restorePartialProjectSession(..) and savePartialProjectSession(..)
that you should reimplement in your special plugin to attach to session loading and saving.
When TDevelop loads or closes a project, the program's project session manager
(class ProjectSession) calls them for each plugin. That manager gives a QDOM node to the
plugin where it can read out or build up its partial DOM subtree with the session settings.
That subtree will be stored in the .kdevses file by that session manager.
For example each programmer has set breakpoints in different files than the other ones of
the team. So the debugger plugin saves them to project session file:
void DebuggerPart::savePartialProjectSession(QDomElement* el)
{
gdbBreakpointWidget->savePartialProjectSession(el);
}
void GDBBreakpointWidget::savePartialProjectSession(QDomElement* el)
{
QDomDocument domDoc = el->ownerDocument();
if (domDoc.isNull()) return;
QDomElement breakpointListEl = domDoc.createElement("breakpointList");
for ( int row = 0; row < m_table->numRows(); row++ )
{
BreakpointTableRow* btr = (BreakpointTableRow *) m_table->item(row, Control);
Breakpoint* bp = btr->breakpoint();
QDomElement breakpointEl = domDoc.createElement("breakpoint"+QString::number(row));
breakpointEl.setAttribute("type", bp->type());
breakpointEl.setAttribute("location", bp->location(false));
breakpointEl.setAttribute("enabled", bp->isEnabled());
breakpointEl.setAttribute("condition", bp->conditional());
breakpointListEl.appendChild(breakpointEl);
}
if (!breakpointListEl.isNull()) el->appendChild(breakpointListEl);
}
}
Note that the .kdevses is related to a project. User settings equal for all projects don't
belong to here. You save them to ~/.trinity/share/config/tdeveloprc via class TDEConfig of the
tdecore library.
Document your part in the way described at \ref howToDocument (doc/api/HowToDocument.dox file).
*/