• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDEUI

kxmlguiclient.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
00003    Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License version 2 as published by the Free Software Foundation.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kxmlguiclient.h"
00021 #include "kxmlguiversionhandler_p.h"
00022 #include "kxmlguifactory.h"
00023 #include "kxmlguibuilder.h"
00024 
00025 #include <QtCore/QDir>
00026 #include <QtCore/QFile>
00027 #include <QtXml/QDomDocument>
00028 #include <QtCore/QTextIStream>
00029 #include <QtCore/QRegExp>
00030 #include <QtCore/QPointer>
00031 
00032 #include <kcomponentdata.h>
00033 #include <kstandarddirs.h>
00034 #include <kdebug.h>
00035 #include <kauthorized.h>
00036 
00037 #include "kaction.h"
00038 #include "kactioncollection.h"
00039 
00040 #include <assert.h>
00041 
00042 class KXMLGUIClientPrivate
00043 {
00044 public:
00045   KXMLGUIClientPrivate()
00046   {
00047     m_componentData = KGlobal::mainComponent();
00048     m_parent = 0L;
00049     m_builder = 0L;
00050     m_actionCollection = 0;
00051   }
00052   ~KXMLGUIClientPrivate()
00053   {
00054   }
00055 
00056   bool mergeXML( QDomElement &base, const QDomElement &additive,
00057                  KActionCollection *actionCollection );
00058 
00059   QDomElement findMatchingElement( const QDomElement &base,
00060                                    const QDomElement &additive );
00061 
00062   KComponentData m_componentData;
00063 
00064   QDomDocument m_doc;
00065   KActionCollection *m_actionCollection;
00066   QDomDocument m_buildDocument;
00067   QPointer<KXMLGUIFactory> m_factory;
00068   KXMLGUIClient *m_parent;
00069   //QPtrList<KXMLGUIClient> m_supers;
00070   QList<KXMLGUIClient*> m_children;
00071   KXMLGUIBuilder *m_builder;
00072   QString m_xmlFile;
00073   QString m_localXMLFile;
00074 
00075   // Actions to enable/disable on a state change
00076   QMap<QString,KXMLGUIClient::StateChange> m_actionsStateMap;
00077 };
00078 
00079 
00080 KXMLGUIClient::KXMLGUIClient()
00081     : d( new KXMLGUIClientPrivate )
00082 {
00083 }
00084 
00085 KXMLGUIClient::KXMLGUIClient( KXMLGUIClient *parent )
00086     : d( new KXMLGUIClientPrivate )
00087 {
00088   parent->insertChildClient( this );
00089 }
00090 
00091 KXMLGUIClient::~KXMLGUIClient()
00092 {
00093   if ( d->m_parent )
00094     d->m_parent->removeChildClient( this );
00095 
00096   foreach (KXMLGUIClient* client, d->m_children) {
00097       assert( client->d->m_parent == this );
00098       client->d->m_parent = 0;
00099   }
00100 
00101   delete d->m_actionCollection;
00102   delete d;
00103 }
00104 
00105 QAction *KXMLGUIClient::action( const char *name ) const
00106 {
00107   QAction* act = actionCollection()->action( name );
00108   if ( !act ) {
00109     foreach (KXMLGUIClient* client, d->m_children) {
00110       act = client->actionCollection()->action( name );
00111       if ( act )
00112         break;
00113     }
00114   }
00115   return act;
00116 }
00117 
00118 KActionCollection *KXMLGUIClient::actionCollection() const
00119 {
00120   if ( !d->m_actionCollection )
00121   {
00122       d->m_actionCollection = new KActionCollection( this );
00123       d->m_actionCollection->setObjectName( "KXMLGUIClient-KActionCollection" );
00124   }
00125   return d->m_actionCollection;
00126 }
00127 
00128 QAction *KXMLGUIClient::action( const QDomElement &element ) const
00129 {
00130   static const QString &attrName = KGlobal::staticQString( "name" );
00131   return actionCollection()->action( qPrintable(element.attribute( attrName )) );
00132 }
00133 
00134 KComponentData KXMLGUIClient::componentData() const
00135 {
00136   return d->m_componentData;
00137 }
00138 
00139 QDomDocument KXMLGUIClient::domDocument() const
00140 {
00141   return d->m_doc;
00142 }
00143 
00144 QString KXMLGUIClient::xmlFile() const
00145 {
00146   return d->m_xmlFile;
00147 }
00148 
00149 QString KXMLGUIClient::localXMLFile() const
00150 {
00151   if ( !d->m_localXMLFile.isEmpty() )
00152     return d->m_localXMLFile;
00153 
00154   if ( !QDir::isRelativePath(d->m_xmlFile) )
00155       return QString(); // can't save anything here
00156 
00157   return KStandardDirs::locateLocal( "data", componentData().componentName() + '/' + d->m_xmlFile );
00158 }
00159 
00160 
00161 void KXMLGUIClient::reloadXML()
00162 {
00163     QString file( xmlFile() );
00164     if ( !file.isEmpty() )
00165         setXMLFile( file );
00166 }
00167 
00168 void KXMLGUIClient::setComponentData(const KComponentData &componentData)
00169 {
00170   d->m_componentData = componentData;
00171   actionCollection()->setComponentData( componentData );
00172   if ( d->m_builder )
00173     d->m_builder->setBuilderClient( this );
00174 }
00175 
00176 void KXMLGUIClient::setXMLFile( const QString& _file, bool merge, bool setXMLDoc )
00177 {
00178   // store our xml file name
00179   if ( !_file.isNull() )
00180     d->m_xmlFile = _file;
00181 
00182   if ( !setXMLDoc )
00183     return;
00184 
00185   QString file = _file;
00186   if ( QDir::isRelativePath(file) )
00187   {
00188     QString doc;
00189 
00190     const QString filter = componentData().componentName() + '/' + _file;
00191     const QStringList allFiles = componentData().dirs()->findAllResources("data", filter) +
00192                                  componentData().dirs()->findAllResources("data", _file);
00193 
00194     if (!allFiles.isEmpty())
00195         file = findMostRecentXMLFile(allFiles, doc);
00196 
00197     if ( file.isEmpty() )
00198     {
00199       // this might or might not be an error.  for the time being,
00200       // let's treat this as if it isn't a problem and the user just
00201       // wants the global standards file
00202 
00203       // however if a non-empty file gets passed and we can't find it we might
00204       // inform the developer using some debug output
00205       if ( !_file.isEmpty() )
00206           kWarning() << "cannot find .rc file" << _file << "in" << filter;
00207 
00208       setXML( QString(), true );
00209       return;
00210     }
00211     else if ( !doc.isEmpty() )
00212     {
00213       setXML( doc, merge );
00214       return;
00215     }
00216   }
00217 
00218   QString xml = KXMLGUIFactory::readConfigFile( file );
00219   setXML( xml, merge );
00220 }
00221 
00222 void KXMLGUIClient::setLocalXMLFile( const QString &file )
00223 {
00224     d->m_localXMLFile = file;
00225 }
00226 
00227 void KXMLGUIClient::setXML( const QString &document, bool merge )
00228 {
00229   QDomDocument doc;
00230   doc.setContent( document );
00231   setDOMDocument( doc, merge );
00232 }
00233 
00234 void KXMLGUIClient::setDOMDocument( const QDomDocument &document, bool merge )
00235 {
00236   Q_ASSERT(!document.isNull());
00237 
00238   if ( merge && !d->m_doc.isNull() )
00239   {
00240     QDomElement base = d->m_doc.documentElement();
00241 
00242     QDomElement e = document.documentElement();
00243 
00244     // merge our original (global) xml with our new one
00245     d->mergeXML(base, e, actionCollection());
00246 
00247     // reassign our pointer as mergeXML might have done something
00248     // strange to it
00249     base = d->m_doc.documentElement();
00250 
00251     // we want some sort of failsafe.. just in case
00252     if ( base.isNull() )
00253       d->m_doc = document;
00254   }
00255   else
00256   {
00257     d->m_doc = document;
00258   }
00259 
00260   setXMLGUIBuildDocument( QDomDocument() );
00261 }
00262 
00263 bool KXMLGUIClientPrivate::mergeXML( QDomElement &base, const QDomElement &additive, KActionCollection *actionCollection )
00264 {
00265   static const QString &tagAction = KGlobal::staticQString( "Action" );
00266   static const QString &tagMerge = KGlobal::staticQString( "Merge" );
00267   static const QString &tagSeparator = KGlobal::staticQString( "Separator" );
00268   static const QString &attrName = KGlobal::staticQString( "name" );
00269   static const QString &attrAppend = KGlobal::staticQString( "append" );
00270   static const QString &attrWeakSeparator = KGlobal::staticQString( "weakSeparator" );
00271   static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" );
00272   static const QString &tagText = KGlobal::staticQString( "text" );
00273   static const QString &attrAlreadyVisited = KGlobal::staticQString( "alreadyVisited" );
00274   static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" );
00275   static const QString &attrOne = KGlobal::staticQString( "1" );
00276 
00277   // there is a possibility that we don't want to merge in the
00278   // additive.. rather, we might want to *replace* the base with the
00279   // additive.  this can be for any container.. either at a file wide
00280   // level or a simple container level.  we look for the 'noMerge'
00281   // tag, in any event and just replace the old with the new
00282   if ( additive.attribute(attrNoMerge) == attrOne ) // ### use toInt() instead? (Simon)
00283   {
00284     base.parentNode().replaceChild(additive, base);
00285     return true;
00286   }
00287 
00288   QString tag;
00289 
00290   // iterate over all elements in the container (of the global DOM tree)
00291   QDomNode n = base.firstChild();
00292   while ( !n.isNull() )
00293   {
00294     QDomElement e = n.toElement();
00295     n = n.nextSibling(); // Advance now so that we can safely delete e
00296     if (e.isNull())
00297        continue;
00298 
00299     tag = e.tagName();
00300 
00301     // if there's an action tag in the global tree and the action is
00302     // not implemented, then we remove the element
00303     if ( tag == tagAction )
00304     {
00305       QByteArray name =  e.attribute( attrName ).toUtf8(); // WABA
00306       if ( !actionCollection->action( name.constData() ) ||
00307            (!KAuthorized::authorizeKAction(name)))
00308       {
00309         // remove this child as we aren't using it
00310         base.removeChild( e );
00311         continue;
00312       }
00313     }
00314 
00315     // if there's a separator defined in the global tree, then add an
00316     // attribute, specifying that this is a "weak" separator
00317     else if ( tag == tagSeparator )
00318     {
00319       e.setAttribute( attrWeakSeparator, (uint)1 );
00320 
00321       // okay, hack time. if the last item was a weak separator OR
00322       // this is the first item in a container, then we nuke the
00323       // current one
00324       QDomElement prev = e.previousSibling().toElement();
00325       if ( prev.isNull() ||
00326      ( prev.tagName() == tagSeparator && !prev.attribute( attrWeakSeparator ).isNull() ) ||
00327      ( prev.tagName() == tagText ) )
00328       {
00329         // the previous element was a weak separator or didn't exist
00330         base.removeChild( e );
00331         continue;
00332       }
00333     }
00334 
00335     // the MergeLocal tag lets us specify where non-standard elements
00336     // of the local tree shall be merged in.  After inserting the
00337     // elements we delete this element
00338     else if ( tag == tagMergeLocal )
00339     {
00340       QDomNode it = additive.firstChild();
00341       while ( !it.isNull() )
00342       {
00343         QDomElement newChild = it.toElement();
00344         it = it.nextSibling();
00345         if (newChild.isNull() )
00346           continue;
00347 
00348         if ( newChild.tagName() == tagText )
00349           continue;
00350 
00351         if ( newChild.attribute( attrAlreadyVisited ) == attrOne )
00352           continue;
00353 
00354         QString itAppend( newChild.attribute( attrAppend ) );
00355         QString elemName( e.attribute( attrName ) );
00356 
00357         if ( ( itAppend.isNull() && elemName.isEmpty() ) ||
00358              ( itAppend == elemName ) )
00359         {
00360           // first, see if this new element matches a standard one in
00361           // the global file.  if it does, then we skip it as it will
00362           // be merged in, later
00363           QDomElement matchingElement = findMatchingElement( newChild, base );
00364           if ( matchingElement.isNull() || newChild.tagName() == tagSeparator )
00365             base.insertBefore( newChild, e );
00366         }
00367       }
00368 
00369       base.removeChild( e );
00370       continue;
00371     }
00372 
00373     // in this last case we check for a separator tag and, if not, we
00374     // can be sure that its a container --> proceed with child nodes
00375     // recursively and delete the just proceeded container item in
00376     // case its empty (if the recursive call returns true)
00377     else if ( tag != tagMerge )
00378     {
00379       // handle the text tag
00380       if ( tag == tagText )
00381         continue;
00382 
00383       QDomElement matchingElement = findMatchingElement( e, additive );
00384 
00385       if ( !matchingElement.isNull() )
00386       {
00387         matchingElement.setAttribute( attrAlreadyVisited, (uint)1 );
00388 
00389         if ( mergeXML( e, matchingElement, actionCollection ) )
00390         {
00391           base.removeChild( e );
00392           continue;
00393         }
00394 
00395         // Merge attributes
00396         const QDomNamedNodeMap attribs = matchingElement.attributes();
00397         const uint attribcount = attribs.count();
00398 
00399         for(uint i = 0; i < attribcount; ++i)
00400         {
00401           const QDomNode node = attribs.item(i);
00402           e.setAttribute(node.nodeName(), node.nodeValue());
00403         }
00404 
00405         continue;
00406       }
00407       else
00408       {
00409         // this is an important case here! We reach this point if the
00410         // "local" tree does not contain a container definition for
00411         // this container. However we have to call mergeXML recursively
00412         // and make it check if there are actions implemented for this
00413         // container. *If* none, then we can remove this container now
00414         if ( mergeXML( e, QDomElement(), actionCollection ) )
00415           base.removeChild( e );
00416         continue;
00417       }
00418     }
00419   }
00420 
00421   //here we append all child elements which were not inserted
00422   //previously via the LocalMerge tag
00423   n = additive.firstChild();
00424   while ( !n.isNull() )
00425   {
00426     QDomElement e = n.toElement();
00427     n = n.nextSibling(); // Advance now so that we can safely delete e
00428     if (e.isNull())
00429        continue;
00430 
00431     QDomElement matchingElement = findMatchingElement( e, base );
00432 
00433     if ( matchingElement.isNull() )
00434     {
00435       base.appendChild( e );
00436     }
00437   }
00438 
00439   // do one quick check to make sure that the last element was not
00440   // a weak separator
00441   QDomElement last = base.lastChild().toElement();
00442   if ( (last.tagName() == tagSeparator) && (!last.attribute( attrWeakSeparator ).isNull()) )
00443   {
00444     base.removeChild( last );
00445   }
00446 
00447   // now we check if we are empty (in which case we return "true", to
00448   // indicate the caller that it can delete "us" (the base element
00449   // argument of "this" call)
00450   bool deleteMe = true;
00451 
00452   n = base.firstChild();
00453   while ( !n.isNull() )
00454   {
00455     QDomElement e = n.toElement();
00456     n = n.nextSibling(); // Advance now so that we can safely delete e
00457     if (e.isNull())
00458        continue;
00459 
00460     tag = e.tagName();
00461 
00462     if ( tag == tagAction )
00463     {
00464       // if base contains an implemented action, then we must not get
00465       // deleted (note that the actionCollection contains both,
00466       // "global" and "local" actions
00467       if ( actionCollection->action( e.attribute( attrName ).toUtf8().constData() ) )
00468       {
00469         deleteMe = false;
00470         break;
00471       }
00472     }
00473     else if ( tag == tagSeparator )
00474     {
00475       // if we have a separator which has *not* the weak attribute
00476       // set, then it must be owned by the "local" tree in which case
00477       // we must not get deleted either
00478       QString weakAttr = e.attribute( attrWeakSeparator );
00479       if ( weakAttr.isEmpty() || weakAttr.toInt() != 1 )
00480       {
00481         deleteMe = false;
00482         break;
00483       }
00484     }
00485 
00486     // in case of a merge tag we have unlimited lives, too ;-)
00487     else if ( tag == tagMerge )
00488     {
00489 //      deleteMe = false;
00490 //      break;
00491         continue;
00492     }
00493 
00494     // a text tag is NOT enough to spare this container
00495     else if ( tag == tagText )
00496     {
00497       continue;
00498     }
00499 
00500     // what's left are non-empty containers! *don't* delete us in this
00501     // case (at this position we can be *sure* that the container is
00502     // *not* empty, as the recursive call for it was in the first loop
00503     // which deleted the element in case the call returned "true"
00504     else
00505     {
00506       deleteMe = false;
00507       break;
00508     }
00509   }
00510 
00511   return deleteMe;
00512 }
00513 
00514 QDomElement KXMLGUIClientPrivate::findMatchingElement( const QDomElement &base, const QDomElement &additive )
00515 {
00516   static const QString &tagAction = KGlobal::staticQString( "Action" );
00517   static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" );
00518   static const QString &attrName = KGlobal::staticQString( "name" );
00519 
00520   QDomNode n = additive.firstChild();
00521   while ( !n.isNull() )
00522   {
00523     QDomElement e = n.toElement();
00524     n = n.nextSibling(); // Advance now so that we can safely delete e
00525     if (e.isNull())
00526        continue;
00527 
00528     // skip all action and merge tags as we will never use them
00529     if ( ( e.tagName() == tagAction ) || ( e.tagName() == tagMergeLocal ) )
00530     {
00531       continue;
00532     }
00533 
00534     // now see if our tags are equivalent
00535     if ( ( e.tagName() == base.tagName() ) &&
00536          ( e.attribute( attrName ) == base.attribute( attrName ) ) )
00537     {
00538         return e;
00539     }
00540   }
00541 
00542   // nope, return a (now) null element
00543   return QDomElement();
00544 }
00545 
00546 void KXMLGUIClient::setXMLGUIBuildDocument( const QDomDocument &doc )
00547 {
00548   d->m_buildDocument = doc;
00549 }
00550 
00551 QDomDocument KXMLGUIClient::xmlguiBuildDocument() const
00552 {
00553   return d->m_buildDocument;
00554 }
00555 
00556 void KXMLGUIClient::setFactory( KXMLGUIFactory *factory )
00557 {
00558   d->m_factory = factory;
00559 }
00560 
00561 KXMLGUIFactory *KXMLGUIClient::factory() const
00562 {
00563   return d->m_factory;
00564 }
00565 
00566 KXMLGUIClient *KXMLGUIClient::parentClient() const
00567 {
00568   return d->m_parent;
00569 }
00570 
00571 void KXMLGUIClient::insertChildClient( KXMLGUIClient *child )
00572 {
00573   if (  child->d->m_parent )
00574     child->d->m_parent->removeChildClient( child );
00575    d->m_children.append( child );
00576    child->d->m_parent = this;
00577 }
00578 
00579 void KXMLGUIClient::removeChildClient( KXMLGUIClient *child )
00580 {
00581   assert( d->m_children.contains( child ) );
00582   d->m_children.removeAll( child );
00583   child->d->m_parent = 0;
00584 }
00585 
00586 /*bool KXMLGUIClient::addSuperClient( KXMLGUIClient *super )
00587 {
00588   if ( d->m_supers.contains( super ) )
00589     return false;
00590   d->m_supers.append( super );
00591   return true;
00592 }*/
00593 
00594 QList<KXMLGUIClient*> KXMLGUIClient::childClients()
00595 {
00596   return d->m_children;
00597 }
00598 
00599 void KXMLGUIClient::setClientBuilder( KXMLGUIBuilder *builder )
00600 {
00601   d->m_builder = builder;
00602   if ( builder )
00603     builder->setBuilderComponentData( componentData() );
00604 }
00605 
00606 KXMLGUIBuilder *KXMLGUIClient::clientBuilder() const
00607 {
00608   return d->m_builder;
00609 }
00610 
00611 void KXMLGUIClient::plugActionList( const QString &name, const QList<QAction*> &actionList )
00612 {
00613   if ( !d->m_factory )
00614     return;
00615 
00616   d->m_factory->plugActionList( this, name, actionList );
00617 }
00618 
00619 void KXMLGUIClient::unplugActionList( const QString &name )
00620 {
00621   if ( !d->m_factory )
00622     return;
00623 
00624   d->m_factory->unplugActionList( this, name );
00625 }
00626 
00627 QString KXMLGUIClient::findMostRecentXMLFile( const QStringList &files, QString &doc )
00628 {
00629     KXmlGuiVersionHandler versionHandler(files);
00630     doc = versionHandler.finalDocument();
00631     return versionHandler.finalFile();
00632 }
00633 
00634 void KXMLGUIClient::addStateActionEnabled(const QString& state,
00635                                           const QString& action)
00636 {
00637   StateChange stateChange = getActionsToChangeForState(state);
00638 
00639   stateChange.actionsToEnable.append( action );
00640   //kDebug(260) << "KXMLGUIClient::addStateActionEnabled( " << state << ", " << action << ")";
00641 
00642   d->m_actionsStateMap.insert( state, stateChange );
00643 }
00644 
00645 
00646 void KXMLGUIClient::addStateActionDisabled(const QString& state,
00647                                            const QString& action)
00648 {
00649   StateChange stateChange = getActionsToChangeForState(state);
00650 
00651   stateChange.actionsToDisable.append( action );
00652   //kDebug(260) << "KXMLGUIClient::addStateActionDisabled( " << state << ", " << action << ")";
00653 
00654   d->m_actionsStateMap.insert( state, stateChange );
00655 }
00656 
00657 
00658 KXMLGUIClient::StateChange KXMLGUIClient::getActionsToChangeForState(const QString& state)
00659 {
00660   return d->m_actionsStateMap[state];
00661 }
00662 
00663 
00664 void KXMLGUIClient::stateChanged(const QString &newstate, KXMLGUIClient::ReverseStateChange reverse)
00665 {
00666   StateChange stateChange = getActionsToChangeForState(newstate);
00667 
00668   bool setTrue = (reverse == StateNoReverse);
00669   bool setFalse = !setTrue;
00670 
00671   // Enable actions which need to be enabled...
00672   //
00673   for ( QStringList::Iterator it = stateChange.actionsToEnable.begin();
00674         it != stateChange.actionsToEnable.end(); ++it ) {
00675 
00676     QAction *action = actionCollection()->action(qPrintable((*it)));
00677     if (action) action->setEnabled(setTrue);
00678   }
00679 
00680   // and disable actions which need to be disabled...
00681   //
00682   for ( QStringList::Iterator it = stateChange.actionsToDisable.begin();
00683         it != stateChange.actionsToDisable.end(); ++it ) {
00684 
00685     QAction *action = actionCollection()->action(qPrintable((*it)));
00686     if (action) action->setEnabled(setFalse);
00687   }
00688 
00689 }
00690 
00691 void KXMLGUIClient::beginXMLPlug( QWidget* w )
00692 {
00693   actionCollection()->addAssociatedWidget( w );
00694   foreach (KXMLGUIClient* client, d->m_children)
00695     client->beginXMLPlug( w );
00696 }
00697 
00698 void KXMLGUIClient::endXMLPlug()
00699 {
00700 }
00701 
00702 void KXMLGUIClient::prepareXMLUnplug( QWidget * w )
00703 {
00704   actionCollection()->removeAssociatedWidget( w );
00705   foreach (KXMLGUIClient* client, d->m_children)
00706     client->prepareXMLUnplug( w );
00707 }
00708 
00709 void KXMLGUIClient::virtual_hook( int, void* )
00710 { /*BASE::virtual_hook( id, data );*/ }

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal