• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • 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, QDomElement &additive,
00057                  KActionCollection *actionCollection );
00058   bool isEmptyContainer(const QDomElement& base,
00059                         KActionCollection *actionCollection) const;
00060 
00061   QDomElement findMatchingElement( const QDomElement &base,
00062                                    const QDomElement &additive );
00063 
00064   KComponentData m_componentData;
00065 
00066   QDomDocument m_doc;
00067   KActionCollection *m_actionCollection;
00068   QDomDocument m_buildDocument;
00069   QPointer<KXMLGUIFactory> m_factory;
00070   KXMLGUIClient *m_parent;
00071   //QPtrList<KXMLGUIClient> m_supers;
00072   QList<KXMLGUIClient*> m_children;
00073   KXMLGUIBuilder *m_builder;
00074   QString m_xmlFile;
00075   QString m_localXMLFile;
00076 
00077   // Actions to enable/disable on a state change
00078   QMap<QString,KXMLGUIClient::StateChange> m_actionsStateMap;
00079 };
00080 
00081 
00082 KXMLGUIClient::KXMLGUIClient()
00083     : d( new KXMLGUIClientPrivate )
00084 {
00085 }
00086 
00087 KXMLGUIClient::KXMLGUIClient( KXMLGUIClient *parent )
00088     : d( new KXMLGUIClientPrivate )
00089 {
00090   parent->insertChildClient( this );
00091 }
00092 
00093 KXMLGUIClient::~KXMLGUIClient()
00094 {
00095   if ( d->m_parent ) {
00096     d->m_parent->removeChildClient( this );
00097   }
00098 
00099   if ( d->m_factory ) {
00100       kWarning(240) << this << "deleted without having been removed from the factory first. This will leak standalone popupmenus and could lead to crashes.";
00101     d->m_factory->forgetClient(this);
00102   }
00103 
00104   foreach (KXMLGUIClient* client, d->m_children) {
00105       if (d->m_factory)
00106           d->m_factory->forgetClient(client);
00107       assert( client->d->m_parent == this );
00108       client->d->m_parent = 0;
00109   }
00110 
00111   delete d->m_actionCollection;
00112   delete d;
00113 }
00114 
00115 QAction *KXMLGUIClient::action( const char *name ) const
00116 {
00117   QAction* act = actionCollection()->action( name );
00118   if ( !act ) {
00119     foreach (KXMLGUIClient* client, d->m_children) {
00120       act = client->actionCollection()->action( name );
00121       if ( act )
00122         break;
00123     }
00124   }
00125   return act;
00126 }
00127 
00128 KActionCollection *KXMLGUIClient::actionCollection() const
00129 {
00130   if ( !d->m_actionCollection )
00131   {
00132       d->m_actionCollection = new KActionCollection( this );
00133       d->m_actionCollection->setObjectName( "KXMLGUIClient-KActionCollection" );
00134   }
00135   return d->m_actionCollection;
00136 }
00137 
00138 QAction *KXMLGUIClient::action( const QDomElement &element ) const
00139 {
00140   static const QString &attrName = KGlobal::staticQString( "name" );
00141   return actionCollection()->action( qPrintable(element.attribute( attrName )) );
00142 }
00143 
00144 KComponentData KXMLGUIClient::componentData() const
00145 {
00146   return d->m_componentData;
00147 }
00148 
00149 QDomDocument KXMLGUIClient::domDocument() const
00150 {
00151   return d->m_doc;
00152 }
00153 
00154 QString KXMLGUIClient::xmlFile() const
00155 {
00156   return d->m_xmlFile;
00157 }
00158 
00159 QString KXMLGUIClient::localXMLFile() const
00160 {
00161   if ( !d->m_localXMLFile.isEmpty() )
00162     return d->m_localXMLFile;
00163 
00164   if ( !QDir::isRelativePath(d->m_xmlFile) )
00165       return QString(); // can't save anything here
00166 
00167     if (d->m_xmlFile.isEmpty()) // setXMLFile not called at all, can't save. Use case: ToolBarHandler
00168         return QString();
00169 
00170   return KStandardDirs::locateLocal( "data", componentData().componentName() + '/' + d->m_xmlFile );
00171 }
00172 
00173 
00174 void KXMLGUIClient::reloadXML()
00175 {
00176     // TODO: this method can't be used for the KXmlGuiWindow, since it doesn't merge in ui_standards.rc!
00177     //   -> KDE5: load ui_standards_rc in setXMLFile using a flag, and remember that flag?
00178     //            and then KEditToolBar can use reloadXML.
00179     QString file( xmlFile() );
00180     if ( !file.isEmpty() )
00181         setXMLFile( file );
00182 }
00183 
00184 void KXMLGUIClient::setComponentData(const KComponentData &componentData)
00185 {
00186   d->m_componentData = componentData;
00187   actionCollection()->setComponentData( componentData );
00188   if ( d->m_builder )
00189     d->m_builder->setBuilderClient( this );
00190 }
00191 
00192 void KXMLGUIClient::loadStandardsXmlFile()
00193 {
00194     const QString file = KStandardDirs::locate("config", "ui/ui_standards.rc", componentData());
00195     if (file.isEmpty()) {
00196         kWarning() << "ui/ui_standards.rc not found in" << componentData().dirs()->resourceDirs("config");
00197     } else {
00198         const QString doc = KXMLGUIFactory::readConfigFile( file );
00199         setXML( doc );
00200     }
00201 }
00202 
00203 void KXMLGUIClient::setXMLFile( const QString& _file, bool merge, bool setXMLDoc )
00204 {
00205   // store our xml file name
00206   if ( !_file.isNull() )
00207     d->m_xmlFile = _file;
00208 
00209   if ( !setXMLDoc )
00210     return;
00211 
00212   QString file = _file;
00213   QStringList allFiles;
00214   if ( !QDir::isRelativePath( file ) ) {
00215     allFiles.append( file );
00216   } else {
00217     const QString filter = componentData().componentName() + '/' + _file;
00218     allFiles = componentData().dirs()->findAllResources("data", filter) +
00219                  componentData().dirs()->findAllResources("data", _file);
00220   }
00221   if ( allFiles.isEmpty() && !_file.isEmpty() ) {
00222     // if a non-empty file gets passed and we can't find it,
00223     // inform the developer using some debug output
00224     kWarning() << "cannot find .rc file" << _file << "for component" << componentData().componentName();
00225   }
00226 
00227   // make sure to merge the settings from any file specified by setLocalXMLFile()
00228   if ( !d->m_localXMLFile.isEmpty() && !file.endsWith("ui_standards.rc") ) {
00229     const bool exists = QDir::isRelativePath(d->m_localXMLFile) || QFile::exists(d->m_localXMLFile);
00230     if (exists && !allFiles.contains(d->m_localXMLFile))
00231       allFiles.prepend( d->m_localXMLFile );
00232   }
00233 
00234   QString doc;
00235   if ( !allFiles.isEmpty() )
00236     file = findMostRecentXMLFile(allFiles, doc);
00237 
00238   // Always call setXML, even on error, so that we don't keep all ui_standards.rc menus.
00239   setXML( doc, merge );
00240 }
00241 
00242 void KXMLGUIClient::setLocalXMLFile( const QString &file )
00243 {
00244     d->m_localXMLFile = file;
00245 }
00246 
00247 void KXMLGUIClient::replaceXMLFile( const QString& xmlfile, const QString& localxmlfile, bool merge )
00248 {
00249   if ( !QDir::isAbsolutePath ( xmlfile ) ) {
00250     kWarning() << "xml file" << xmlfile << "is not an absolute path";
00251   }
00252 
00253   setLocalXMLFile ( localxmlfile );
00254   setXMLFile ( xmlfile, merge );
00255 }
00256 
00257 void KXMLGUIClient::setXML( const QString &document, bool merge )
00258 {
00259     QDomDocument doc;
00260     QString errorMsg;
00261     int errorLine, errorColumn;
00262     // QDomDocument raises a parse error on empty document, but we accept no app-specific document,
00263     // in which case you only get ui_standards.rc layout.
00264     bool result = document.isEmpty() || doc.setContent(document, &errorMsg, &errorLine, &errorColumn);
00265     if ( result ) {
00266         setDOMDocument( doc, merge );
00267     } else {
00268 #ifdef NDEBUG
00269         kError(240) << "Error parsing XML document:" << errorMsg << "at line" << errorLine << "column" << errorColumn;
00270         setDOMDocument(QDomDocument(), merge); // otherwise empty menus from ui_standards.rc stay around
00271 #else
00272         kFatal() << "Error parsing XML document:" << errorMsg << "at line" << errorLine << "column" << errorColumn;
00273 #endif
00274     }
00275 }
00276 
00277 void KXMLGUIClient::setDOMDocument( const QDomDocument &document, bool merge )
00278 {
00279   if ( merge && !d->m_doc.isNull() )
00280   {
00281     QDomElement base = d->m_doc.documentElement();
00282 
00283     QDomElement e = document.documentElement();
00284 
00285     // merge our original (global) xml with our new one
00286     d->mergeXML(base, e, actionCollection());
00287 
00288     // reassign our pointer as mergeXML might have done something
00289     // strange to it
00290     base = d->m_doc.documentElement();
00291 
00292     //kDebug(260) << "Result of xmlgui merging:" << d->m_doc.toString();
00293 
00294     // we want some sort of failsafe.. just in case
00295     if ( base.isNull() )
00296       d->m_doc = document;
00297   }
00298   else
00299   {
00300     d->m_doc = document;
00301   }
00302 
00303   setXMLGUIBuildDocument( QDomDocument() );
00304 }
00305 
00306 // if (equals(a,b)) is more readable than if (a.compare(b, Qt::CaseInsensitive)==0)
00307 static bool equalstr(const QString& a, const QString& b) {
00308     return a.compare(b, Qt::CaseInsensitive) == 0;
00309 }
00310 
00311 bool KXMLGUIClientPrivate::mergeXML( QDomElement &base, QDomElement &additive, KActionCollection *actionCollection )
00312 {
00313     static const QString &tagAction = KGlobal::staticQString( "Action" );
00314     static const QString &tagMerge = KGlobal::staticQString( "Merge" );
00315     static const QString &tagSeparator = KGlobal::staticQString( "Separator" );
00316     static const QString &attrName = KGlobal::staticQString( "name" );
00317     static const QString &attrAppend = KGlobal::staticQString( "append" );
00318     static const QString &attrWeakSeparator = KGlobal::staticQString( "weakSeparator" );
00319     static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" );
00320     static const QString &tagText = KGlobal::staticQString( "text" );
00321     static const QString &attrAlreadyVisited = KGlobal::staticQString( "alreadyVisited" );
00322     static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" );
00323     static const QString &attrOne = KGlobal::staticQString( "1" );
00324 
00325     // there is a possibility that we don't want to merge in the
00326     // additive.. rather, we might want to *replace* the base with the
00327     // additive.  this can be for any container.. either at a file wide
00328     // level or a simple container level.  we look for the 'noMerge'
00329     // tag, in any event and just replace the old with the new
00330     if ( additive.attribute(attrNoMerge) == attrOne ) // ### use toInt() instead? (Simon)
00331     {
00332         base.parentNode().replaceChild(additive, base);
00333         return true;
00334     } else {
00335         // Merge attributes
00336         {
00337             const QDomNamedNodeMap attribs = additive.attributes();
00338             const uint attribcount = attribs.count();
00339 
00340             for(uint i = 0; i < attribcount; ++i) {
00341                 const QDomNode node = attribs.item(i);
00342                 base.setAttribute(node.nodeName(), node.nodeValue());
00343             }
00344         }
00345 
00346         // iterate over all elements in the container (of the global DOM tree)
00347         QDomNode n = base.firstChild();
00348         while ( !n.isNull() )
00349         {
00350             QDomElement e = n.toElement();
00351             n = n.nextSibling(); // Advance now so that we can safely delete e
00352             if (e.isNull())
00353                 continue;
00354 
00355             const QString tag = e.tagName();
00356 
00357             // if there's an action tag in the global tree and the action is
00358             // not implemented, then we remove the element
00359             if (equalstr(tag, tagAction)) {
00360                 const QString name =  e.attribute(attrName);
00361                 if (!actionCollection->action(name) ||
00362                     !KAuthorized::authorizeKAction(name))
00363                 {
00364                     // remove this child as we aren't using it
00365                     base.removeChild( e );
00366                     continue;
00367                 }
00368             }
00369 
00370             // if there's a separator defined in the global tree, then add an
00371             // attribute, specifying that this is a "weak" separator
00372             else if (equalstr(tag, tagSeparator)) {
00373                 e.setAttribute( attrWeakSeparator, (uint)1 );
00374 
00375                 // okay, hack time. if the last item was a weak separator OR
00376                 // this is the first item in a container, then we nuke the
00377                 // current one
00378                 QDomElement prev = e.previousSibling().toElement();
00379                 if (prev.isNull() ||
00380                     (equalstr(prev.tagName(), tagSeparator) && !prev.attribute(attrWeakSeparator).isNull() ) ||
00381                     (equalstr(prev.tagName(), tagText))) {
00382                     // the previous element was a weak separator or didn't exist
00383                     base.removeChild( e );
00384                     continue;
00385                 }
00386             }
00387 
00388             // the MergeLocal tag lets us specify where non-standard elements
00389             // of the local tree shall be merged in.  After inserting the
00390             // elements we delete this element
00391             else if (equalstr(tag, tagMergeLocal)) {
00392                 QDomNode it = additive.firstChild();
00393                 while ( !it.isNull() )
00394                 {
00395                     QDomElement newChild = it.toElement();
00396                     it = it.nextSibling();
00397                     if (newChild.isNull() )
00398                         continue;
00399 
00400                     if (equalstr(newChild.tagName(), tagText))
00401                         continue;
00402 
00403                     if ( newChild.attribute( attrAlreadyVisited ) == attrOne )
00404                         continue;
00405 
00406                     QString itAppend( newChild.attribute( attrAppend ) );
00407                     QString elemName( e.attribute( attrName ) );
00408 
00409                     if ( ( itAppend.isNull() && elemName.isEmpty() ) ||
00410                          ( itAppend == elemName ) )
00411                     {
00412                         // first, see if this new element matches a standard one in
00413                         // the global file.  if it does, then we skip it as it will
00414                         // be merged in, later
00415                         QDomElement matchingElement = findMatchingElement( newChild, base );
00416                         if (matchingElement.isNull() || equalstr(newChild.tagName(), tagSeparator))
00417                             base.insertBefore( newChild, e );
00418                     }
00419                 }
00420 
00421                 base.removeChild( e );
00422                 continue;
00423             }
00424 
00425             else if (equalstr(tag, tagText)) {
00426                 continue;
00427             }
00428             else if (equalstr(tag, tagMerge)) {
00429                 continue;
00430             }
00431 
00432             // in this last case we check for a separator tag and, if not, we
00433             // can be sure that it is a container --> proceed with child nodes
00434             // recursively and delete the just proceeded container item in
00435             // case it is empty (if the recursive call returns true)
00436             else {
00437                 QDomElement matchingElement = findMatchingElement( e, additive );
00438                 if ( !matchingElement.isNull() )
00439                 {
00440                     matchingElement.setAttribute( attrAlreadyVisited, (uint)1 );
00441 
00442                     if ( mergeXML( e, matchingElement, actionCollection ) )
00443                     {
00444                         base.removeChild( e );
00445                         additive.removeChild(matchingElement); // make sure we don't append it below
00446                         continue;
00447                     }
00448 
00449                     continue;
00450                 }
00451                 else
00452                 {
00453                     // this is an important case here! We reach this point if the
00454                     // "local" tree does not contain a container definition for
00455                     // this container. However we have to call mergeXML recursively
00456                     // and make it check if there are actions implemented for this
00457                     // container. *If* none, then we can remove this container now
00458                     QDomElement dummy;
00459                     if ( mergeXML( e, dummy, actionCollection ) )
00460                         base.removeChild( e );
00461                     continue;
00462                 }
00463             }
00464         }
00465 
00466         //here we append all child elements which were not inserted
00467         //previously via the LocalMerge tag
00468         n = additive.firstChild();
00469         while ( !n.isNull() )
00470         {
00471             QDomElement e = n.toElement();
00472             n = n.nextSibling(); // Advance now so that we can safely delete e
00473             if (e.isNull())
00474                 continue;
00475 
00476             QDomElement matchingElement = findMatchingElement( e, base );
00477 
00478             if ( matchingElement.isNull() )
00479             {
00480                 base.appendChild( e );
00481             }
00482         }
00483 
00484         // do one quick check to make sure that the last element was not
00485         // a weak separator
00486         QDomElement last = base.lastChild().toElement();
00487         if (equalstr(last.tagName(), tagSeparator) &&
00488             (!last.attribute(attrWeakSeparator).isNull())) {
00489             base.removeChild( last );
00490         }
00491     }
00492 
00493     return isEmptyContainer(base, actionCollection);
00494 }
00495 
00496 bool KXMLGUIClientPrivate::isEmptyContainer(const QDomElement& base, KActionCollection *actionCollection) const
00497 {
00498     // now we check if we are empty (in which case we return "true", to
00499     // indicate the caller that it can delete "us" (the base element
00500     // argument of "this" call)
00501     QDomNode n = base.firstChild();
00502     while (!n.isNull()) {
00503         const QDomElement e = n.toElement();
00504         n = n.nextSibling(); // Advance now so that we can safely delete e
00505         if (e.isNull())
00506             continue;
00507 
00508         const QString tag = e.tagName();
00509 
00510         static const QString &tagAction = KGlobal::staticQString("Action");
00511         static const QString &tagSeparator = KGlobal::staticQString("Separator");
00512         static const QString &tagText = KGlobal::staticQString("text");
00513         static const QString &tagMerge = KGlobal::staticQString("Merge");
00514         if (equalstr(tag, tagAction)) {
00515             // if base contains an implemented action, then we must not get
00516             // deleted (note that the actionCollection contains both,
00517             // "global" and "local" actions)
00518             static const QString &attrName = KGlobal::staticQString("name");
00519             if (actionCollection->action(e.attribute(attrName))) {
00520                 return false;
00521             }
00522         }
00523         else if (equalstr(tag, tagSeparator)) {
00524             // if we have a separator which has *not* the weak attribute
00525             // set, then it must be owned by the "local" tree in which case
00526             // we must not get deleted either
00527             static const QString &attrWeakSeparator = KGlobal::staticQString("weakSeparator");
00528             const QString weakAttr = e.attribute(attrWeakSeparator);
00529             if (weakAttr.isEmpty() || weakAttr.toInt() != 1) {
00530                 return false;
00531             }
00532         }
00533 
00534         else if (equalstr(tag, tagMerge)) {
00535             continue;
00536         }
00537 
00538         // a text tag is NOT enough to spare this container
00539         else if (equalstr(tag, tagText)) {
00540             continue;
00541         }
00542 
00543         // what's left are non-empty containers! *don't* delete us in this
00544         // case (at this position we can be *sure* that the container is
00545         // *not* empty, as the recursive call for it was in the first loop
00546         // which deleted the element in case the call returned "true"
00547         else {
00548             return false;
00549         }
00550     }
00551 
00552     return true; // I'm empty, please delete me.
00553 }
00554 
00555 QDomElement KXMLGUIClientPrivate::findMatchingElement( const QDomElement &base, const QDomElement &additive )
00556 {
00557   static const QString &tagAction = KGlobal::staticQString( "Action" );
00558   static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" );
00559   static const QString &attrName = KGlobal::staticQString( "name" );
00560 
00561   QDomNode n = additive.firstChild();
00562   while ( !n.isNull() )
00563   {
00564     QDomElement e = n.toElement();
00565     n = n.nextSibling(); // Advance now so that we can safely delete e -- TODO we don't, so simplify this
00566     if (e.isNull())
00567        continue;
00568 
00569     const QString tag = e.tagName();
00570     // skip all action and merge tags as we will never use them
00571     if (equalstr(tag, tagAction)
00572         || equalstr(tag, tagMergeLocal)) {
00573       continue;
00574     }
00575 
00576     // now see if our tags are equivalent
00577     if (equalstr(tag, base.tagName()) &&
00578         e.attribute(attrName) == base.attribute(attrName)) {
00579         return e;
00580     }
00581   }
00582 
00583   // nope, return a (now) null element
00584   return QDomElement();
00585 }
00586 
00587 void KXMLGUIClient::setXMLGUIBuildDocument( const QDomDocument &doc )
00588 {
00589   d->m_buildDocument = doc;
00590 }
00591 
00592 QDomDocument KXMLGUIClient::xmlguiBuildDocument() const
00593 {
00594   return d->m_buildDocument;
00595 }
00596 
00597 void KXMLGUIClient::setFactory( KXMLGUIFactory *factory )
00598 {
00599   d->m_factory = factory;
00600 }
00601 
00602 KXMLGUIFactory *KXMLGUIClient::factory() const
00603 {
00604   return d->m_factory;
00605 }
00606 
00607 KXMLGUIClient *KXMLGUIClient::parentClient() const
00608 {
00609   return d->m_parent;
00610 }
00611 
00612 void KXMLGUIClient::insertChildClient( KXMLGUIClient *child )
00613 {
00614   if (  child->d->m_parent )
00615     child->d->m_parent->removeChildClient( child );
00616    d->m_children.append( child );
00617    child->d->m_parent = this;
00618 }
00619 
00620 void KXMLGUIClient::removeChildClient( KXMLGUIClient *child )
00621 {
00622   assert( d->m_children.contains( child ) );
00623   d->m_children.removeAll( child );
00624   child->d->m_parent = 0;
00625 }
00626 
00627 /*bool KXMLGUIClient::addSuperClient( KXMLGUIClient *super )
00628 {
00629   if ( d->m_supers.contains( super ) )
00630     return false;
00631   d->m_supers.append( super );
00632   return true;
00633 }*/
00634 
00635 QList<KXMLGUIClient*> KXMLGUIClient::childClients()
00636 {
00637   return d->m_children;
00638 }
00639 
00640 void KXMLGUIClient::setClientBuilder( KXMLGUIBuilder *builder )
00641 {
00642   d->m_builder = builder;
00643   if ( builder )
00644     builder->setBuilderComponentData( componentData() );
00645 }
00646 
00647 KXMLGUIBuilder *KXMLGUIClient::clientBuilder() const
00648 {
00649   return d->m_builder;
00650 }
00651 
00652 void KXMLGUIClient::plugActionList( const QString &name, const QList<QAction*> &actionList )
00653 {
00654   if ( !d->m_factory )
00655     return;
00656 
00657   d->m_factory->plugActionList( this, name, actionList );
00658 }
00659 
00660 void KXMLGUIClient::unplugActionList( const QString &name )
00661 {
00662   if ( !d->m_factory )
00663     return;
00664 
00665   d->m_factory->unplugActionList( this, name );
00666 }
00667 
00668 QString KXMLGUIClient::findMostRecentXMLFile( const QStringList &files, QString &doc )
00669 {
00670     KXmlGuiVersionHandler versionHandler(files);
00671     doc = versionHandler.finalDocument();
00672     return versionHandler.finalFile();
00673 }
00674 
00675 void KXMLGUIClient::addStateActionEnabled(const QString& state,
00676                                           const QString& action)
00677 {
00678   StateChange stateChange = getActionsToChangeForState(state);
00679 
00680   stateChange.actionsToEnable.append( action );
00681   //kDebug(260) << "KXMLGUIClient::addStateActionEnabled( " << state << ", " << action << ")";
00682 
00683   d->m_actionsStateMap.insert( state, stateChange );
00684 }
00685 
00686 
00687 void KXMLGUIClient::addStateActionDisabled(const QString& state,
00688                                            const QString& action)
00689 {
00690   StateChange stateChange = getActionsToChangeForState(state);
00691 
00692   stateChange.actionsToDisable.append( action );
00693   //kDebug(260) << "KXMLGUIClient::addStateActionDisabled( " << state << ", " << action << ")";
00694 
00695   d->m_actionsStateMap.insert( state, stateChange );
00696 }
00697 
00698 
00699 KXMLGUIClient::StateChange KXMLGUIClient::getActionsToChangeForState(const QString& state)
00700 {
00701   return d->m_actionsStateMap[state];
00702 }
00703 
00704 
00705 void KXMLGUIClient::stateChanged(const QString &newstate, KXMLGUIClient::ReverseStateChange reverse)
00706 {
00707   StateChange stateChange = getActionsToChangeForState(newstate);
00708 
00709   bool setTrue = (reverse == StateNoReverse);
00710   bool setFalse = !setTrue;
00711 
00712   // Enable actions which need to be enabled...
00713   //
00714   for ( QStringList::const_iterator it = stateChange.actionsToEnable.constBegin();
00715         it != stateChange.actionsToEnable.constEnd(); ++it ) {
00716 
00717     QAction *action = actionCollection()->action(qPrintable((*it)));
00718     if (action) action->setEnabled(setTrue);
00719   }
00720 
00721   // and disable actions which need to be disabled...
00722   //
00723   for ( QStringList::const_iterator it = stateChange.actionsToDisable.constBegin();
00724         it != stateChange.actionsToDisable.constEnd(); ++it ) {
00725 
00726     QAction *action = actionCollection()->action(qPrintable((*it)));
00727     if (action) action->setEnabled(setFalse);
00728   }
00729 
00730 }
00731 
00732 void KXMLGUIClient::beginXMLPlug( QWidget* w )
00733 {
00734   actionCollection()->addAssociatedWidget( w );
00735   foreach (KXMLGUIClient* client, d->m_children)
00736     client->beginXMLPlug( w );
00737 }
00738 
00739 void KXMLGUIClient::endXMLPlug()
00740 {
00741 }
00742 
00743 void KXMLGUIClient::prepareXMLUnplug( QWidget * w )
00744 {
00745   actionCollection()->removeAssociatedWidget( w );
00746   foreach (KXMLGUIClient* client, d->m_children)
00747     client->prepareXMLUnplug( w );
00748 }
00749 
00750 void KXMLGUIClient::virtual_hook( int, void* )
00751 { /*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
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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