/** \file HowToAddPlugins.dox
  * \brief How to extend KDevelop via plugins
  */
/** \page howToAddPlugins How to extend KDevelop via plugins
\section createDesktop Step 1: Make your plugin loadable
For a plugin foo, create a file foo.desktop which contains KDevelop/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=
    ##########################
FooFactory which inherits
KDevFactory. Put a section
    extern "C" {
        void *init_libfoo()
        {
            return new FooFactory;
        }
    }
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 KDevelop 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" );
CFLAGS variable set by the user, and uses the statement similar to
    DomUtil::writeEntry( *part->document(),
                         "kdevautoproject/cflags",
                         "--no-exceptions" );
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);
}
}