| # kdeui Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kxmlguifactory_p.cpp

    00001 /* This file is part of the KDE libraries
    00002    Copyright (C) 2001 Simon Hausmann <hausmann@kde.org>
    00003
    00004    This library is free software; you can redistribute it and/or
    00005    modify it under the terms of the GNU Library General Public
    00006    License as published by the Free Software Foundation; either
    00007    version 2 of the License, or (at your option) any later version.
    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., 59 Temple Place - Suite 330,
    00017    Boston, MA 02111-1307, USA.
    00018 */
    00019
    00020 #include "kxmlguifactory_p.h"
    00021 #include "kxmlguiclient.h"
    00022 #include "kxmlguibuilder.h"
    00023
    00024 #include <qwidget.h>
    00025
    00026 #include <kglobal.h>
    00027 #include <kdebug.h>
    00028
    00029 #include <assert.h>
    00030
    00031 using namespace KXMLGUI;
    00032
    00033 void ActionList::plug( QWidget *container, int index ) const
    00034 {
    00035     ActionListIt it( *this );
    00036     for (; it.current(); ++it )
    00037         it.current()->plug( container, index++ );
    00038 }
    00039
    00040 void ActionList::unplug( QWidget *container ) const
    00041 {
    00042     ActionListIt it( *this );
    00043     for (; it.current(); ++it )
    00044         it.current()->unplug( container );
    00045 }
    00046
    00047 ContainerNode::ContainerNode( QWidget *_container, const QString &_tagName,
    00048                               const QString &_name, ContainerNode *_parent,
    00049                               KXMLGUIClient *_client, KXMLGUIBuilder *_builder,
    00050                               int id, const QString &_mergingName,
    00051                               const QString &_groupName, const QStringList &customTags,
    00052                               const QStringList &containerTags )
    00053     : parent( _parent ), client( _client ), builder( _builder ),
    00054       builderCustomTags( customTags ), builderContainerTags( containerTags ),
    00055       container( _container ), containerId( id ), tagName( _tagName ), name( _name ),
    00056       groupName( _groupName ), index( 0 ), mergingName( _mergingName )
    00057 {
    00058     children.setAutoDelete( true );
    00059     clients.setAutoDelete( true );
    00060
    00061     if ( parent )
    00062         parent->children.append( this );
    00063 }
    00064
    00065 void ContainerNode::removeChild( ContainerNode *child )
    00066 {
    00067     MergingIndexList::Iterator mergingIt = findIndex( child->mergingName );
    00068     adjustMergingIndices( -1, mergingIt );
    00069     children.removeRef( child );
    00070 }
    00071
    00072 /*
    00073  * Find a merging index with the given name. Used to find an index defined by <Merge name="blah"/>
    00074  * or by a <DefineGroup name="foo" /> tag.
    00075  */
    00076 MergingIndexList::Iterator ContainerNode::findIndex( const QString &name )
    00077 {
    00078     MergingIndexList::Iterator it( mergingIndices.begin() );
    00079     MergingIndexList::Iterator end( mergingIndices.end() );
    00080     for (; it != end; ++it )
    00081         if ( (*it).mergingName == name )
    00082             return it;
    00083     return it;
    00084 }
    00085
    00086 /*
    00087  * Check if the given container widget is a child of this node and return the node structure
    00088  * if fonud.
    00089  */
    00090 ContainerNode *ContainerNode::findContainerNode( QWidget *container )
    00091 {
    00092     ContainerNodeListIt it( children );
    00093
    00094     for (; it.current(); ++it )
    00095         if ( it.current()->container == container )
    00096             return it.current();
    00097
    00098     return 0L;
    00099 }
    00100
    00101 /*
    00102  * Find a container recursively with the given name. Either compares _name with the
    00103  * container's tag name or the value of the container's name attribute. Specified by
    00104  * the tag bool .
    00105  */
    00106 ContainerNode *ContainerNode::findContainer( const QString &_name, bool tag )
    00107 {
    00108     if ( ( tag && tagName == _name ) ||
    00109          ( !tag && name == _name ) )
    00110         return this;
    00111
    00112     ContainerNodeListIt it( children );
    00113     for (; it.current(); ++it )
    00114     {
    00115         ContainerNode *res = it.current()->findContainer( _name, tag );
    00116         if ( res )
    00117             return res;
    00118     }
    00119
    00120     return 0;
    00121 }
    00122
    00123 /*
    00124  * Finds a child container node (not recursively) with the given name and tagname. Explicitly
    00125  * leaves out container widgets specified in the exludeList . Also ensures that the containers
    00126  * belongs to currClient.
    00127  */
    00128 ContainerNode *ContainerNode::findContainer( const QString &name, const QString &tagName,
    00129                                              const QPtrList<QWidget> *excludeList,
    00130                                              KXMLGUIClient * /*currClient*/ )
    00131 {
    00132     ContainerNode *res = 0L;
    00133     ContainerNodeListIt nIt( children );
    00134
    00135     if ( !name.isEmpty() )
    00136     {
    00137         for (; nIt.current(); ++nIt )
    00138             if ( nIt.current()->name == name &&
    00139                  !excludeList->containsRef( nIt.current()->container ) )
    00140             {
    00141                 res = nIt.current();
    00142                 break;
    00143             }
    00144
    00145         return res;
    00146     }
    00147
    00148     if ( !tagName.isEmpty() )
    00149         for (; nIt.current(); ++nIt )
    00150         {
    00151             if ( nIt.current()->tagName == tagName &&
    00152                  !excludeList->containsRef( nIt.current()->container )
    00153                  /*
    00154                   * It is a bad idea to also compare the client, because
    00155                   * we don't want to do so in situations like these:
    00156                   *
    00157                   * <MenuBar>
    00158                   *   <Menu>
    00159                   *     ...
    00160                   *
    00161                   * other client:
    00162                   * <MenuBar>
    00163                   *   <Menu>
    00164                   *    ...
    00165                   *
    00166                  && nIt.current()->client == currClient )
    00167                  */
    00168                 )
    00169             {
    00170                 res = nIt.current();
    00171                 break;
    00172             }
    00173         }
    00174
    00175     return res;
    00176 }
    00177
    00178 ContainerClient *ContainerNode::findChildContainerClient( KXMLGUIClient *currentGUIClient,
    00179                                                           const QString &groupName,
    00180                                                           const MergingIndexList::Iterator &mergingIdx )
    00181 {
    00182     if ( !clients.isEmpty() )
    00183     {
    00184         ContainerClientListIt clientIt( clients );
    00185
    00186         for (; clientIt.current(); ++clientIt )
    00187             if ( clientIt.current()->client == currentGUIClient )
    00188             {
    00189                 if ( groupName.isEmpty() )
    00190                     return clientIt.current();
    00191
    00192                 if ( groupName == clientIt.current()->groupName )
    00193                     return clientIt.current();
    00194             }
    00195     }
    00196
    00197     ContainerClient *client = new ContainerClient;
    00198     client->client = currentGUIClient;
    00199     client->groupName = groupName;
    00200
    00201     if ( mergingIdx != mergingIndices.end() )
    00202         client->mergingName = (*mergingIdx).mergingName;
    00203
    00204     clients.append( client );
    00205
    00206     return client;
    00207 }
    00208
    00209 void ContainerNode::plugActionList( BuildState &state )
    00210 {
    00211     MergingIndexList::Iterator mIt( mergingIndices.begin() );
    00212     MergingIndexList::Iterator mEnd( mergingIndices.end() );
    00213     for (; mIt != mEnd; ++mIt )
    00214         plugActionList( state, mIt );
    00215
    00216     QPtrListIterator<ContainerNode> childIt( children );
    00217     for (; childIt.current(); ++childIt )
    00218         childIt.current()->plugActionList( state );
    00219 }
    00220
    00221 void ContainerNode::plugActionList( BuildState &state, const MergingIndexList::Iterator &mergingIdxIt )
    00222 {
    00223     static const QString &tagActionList = KGlobal::staticQString( "actionlist" );
    00224
    00225     MergingIndex mergingIdx = *mergingIdxIt;
    00226
    00227     QString k( mergingIdx.mergingName );
    00228
    00229     if ( k.find( tagActionList ) == -1 )
    00230         return;
    00231
    00232     k = k.mid( tagActionList.length() );
    00233
    00234     if ( mergingIdx.clientName != state.clientName )
    00235         return;
    00236
    00237     if ( k != state.actionListName )
    00238         return;
    00239
    00240     ContainerClient *client = findChildContainerClient( state.guiClient,
    00241                                                         QString::null,
    00242                                                         mergingIndices.end() );
    00243
    00244     client->actionLists.insert( k, state.actionList );
    00245
    00246     state.actionList.plug( container, mergingIdx.value );
    00247
    00248     adjustMergingIndices( state.actionList.count(), mergingIdxIt );
    00249 }
    00250
    00251 void ContainerNode::unplugActionList( BuildState &state )
    00252 {
    00253     MergingIndexList::Iterator mIt( mergingIndices.begin() );
    00254     MergingIndexList::Iterator mEnd( mergingIndices.end() );
    00255     for (; mIt != mEnd; ++mIt )
    00256         unplugActionList( state, mIt );
    00257
    00258     QPtrListIterator<ContainerNode> childIt( children );
    00259     for (; childIt.current(); ++childIt )
    00260         childIt.current()->unplugActionList( state );
    00261 }
    00262
    00263 void ContainerNode::unplugActionList( BuildState &state, const MergingIndexList::Iterator &mergingIdxIt )
    00264 {
    00265     static const QString &tagActionList = KGlobal::staticQString( "actionlist" );
    00266
    00267     MergingIndex mergingIdx = *mergingIdxIt;
    00268
    00269     QString k = mergingIdx.mergingName;
    00270
    00271     if ( k.find( tagActionList ) == -1 )
    00272         return;
    00273
    00274     k = k.mid( tagActionList.length() );
    00275
    00276     if ( mergingIdx.clientName != state.clientName )
    00277         return;
    00278
    00279     if ( k != state.actionListName )
    00280         return;
    00281
    00282     ContainerClient *client = findChildContainerClient( state.guiClient,
    00283                                                         QString::null,
    00284                                                         mergingIndices.end() );
    00285
    00286     ActionListMap::Iterator lIt( client->actionLists.find( k ) );
    00287     if ( lIt == client->actionLists.end() )
    00288         return;
    00289
    00290     lIt.data().unplug( container );
    00291
    00292     adjustMergingIndices( -int(lIt.data().count()), mergingIdxIt );
    00293
    00294     client->actionLists.remove( lIt );
    00295 }
    00296
    00297 void ContainerNode::adjustMergingIndices( int offset,
    00298                                           const MergingIndexList::Iterator &it )
    00299 {
    00300     MergingIndexList::Iterator mergingIt = it;
    00301     MergingIndexList::Iterator mergingEnd = mergingIndices.end();
    00302
    00303     for (; mergingIt != mergingEnd; ++mergingIt )
    00304         (*mergingIt).value += offset;
    00305
    00306     index += offset;
    00307 }
    00308
    00309 bool ContainerNode::destruct( QDomElement element, BuildState &state )
    00310 {
    00311     destructChildren( element, state );
    00312
    00313     unplugActions( state );
    00314
    00315     // remove all merging indices the client defined
    00316     MergingIndexList::Iterator cmIt = mergingIndices.begin();
    00317     while ( cmIt != mergingIndices.end() )
    00318         if ( (*cmIt).clientName == state.clientName )
    00319             cmIt = mergingIndices.remove( cmIt );
    00320         else
    00321             ++cmIt;
    00322
    00323     // ### check for merging index count, too?
    00324     if ( clients.count() == 0 && children.count() == 0 && container &&
    00325          client == state.guiClient )
    00326     {
    00327         QWidget *parentContainer = 0L;
    00328
    00329         if ( parent && parent->container )
    00330             parentContainer = parent->container;
    00331
    00332         assert( builder );
    00333
    00334         builder->removeContainer( container, parentContainer, element, containerId );
    00335
    00336         client = 0L;
    00337
    00338         return true;
    00339     }
    00340
    00341     if ( client == state.guiClient )
    00342         client = 0L;
    00343
    00344     return false;
    00345
    00346 }
    00347
    00348 void ContainerNode::destructChildren( const QDomElement &element, BuildState &state )
    00349 {
    00350     QPtrListIterator<ContainerNode> childIt( children );
    00351     while ( childIt.current() )
    00352     {
    00353         ContainerNode *childNode = childIt.current();
    00354
    00355         QDomElement childElement = findElementForChild( element, childNode );
    00356
    00357         // destruct returns true in case the container really got deleted
    00358         if ( childNode->destruct( childElement, state ) )
    00359             removeChild( childNode );
    00360         else
    00361             ++childIt;
    00362     }
    00363 }
    00364
    00365 QDomElement ContainerNode::findElementForChild( const QDomElement &baseElement,
    00366                                                 ContainerNode *childNode )
    00367 {
    00368     static const QString &attrName = KGlobal::staticQString( "name" );
    00369
    00370     // ### slow
    00371     for ( QDomNode n = baseElement.firstChild(); !n.isNull();
    00372           n = n.nextSibling() )
    00373     {
    00374         QDomElement e = n.toElement();
    00375         if ( e.tagName().lower() == childNode->tagName &&
    00376              e.attribute( attrName ) == childNode->name )
    00377             return e;
    00378     }
    00379
    00380     return QDomElement();
    00381 }
    00382
    00383 void ContainerNode::unplugActions( BuildState &state )
    00384 {
    00385     if ( !container )
    00386         return;
    00387
    00388     ContainerClientListIt clientIt( clients );
    00389
    00390     /*
    00391         Disabled because it means in KToolBar::saveState isHidden is always true then,
    00392         which is clearly wrong.
    00393
    00394     if ( clients.count() == 1 && clientIt.current()->client == client &&
    00395          client == state.guiClient )
    00396         container->hide(); // this container is going to die, that's for sure.
    00397                            // in this case let's just hide it, which makes the
    00398                            // destruction faster
    00399      */
    00400
    00401     while ( clientIt.current() )
    00402         //only unplug the actions of the client we want to remove, as the container might be owned
    00403         //by a different client
    00404         if ( clientIt.current()->client == state.guiClient )
    00405         {
    00406             unplugClient( clientIt.current() );
    00407             clients.removeRef( clientIt.current() );
    00408         }
    00409         else
    00410             ++clientIt;
    00411 }
    00412
    00413 void ContainerNode::unplugClient( ContainerClient *client )
    00414 {
    00415     static const QString &tagActionList = KGlobal::staticQString( "actionlist" );
    00416
    00417     assert( builder );
    00418
    00419     // now quickly remove all custom elements (i.e. separators) and unplug all actions
    00420
    00421     QValueList<int>::ConstIterator custIt = client->customElements.begin();
    00422     QValueList<int>::ConstIterator custEnd = client->customElements.end();
    00423     for (; custIt != custEnd; ++custIt )
    00424         builder->removeCustomElement( container, *custIt );
    00425
    00426     client->actions.unplug( container );
    00427
    00428     // now adjust all merging indices
    00429
    00430     MergingIndexList::Iterator mergingIt = findIndex( client->mergingName );
    00431
    00432     adjustMergingIndices( - int( client->actions.count()
    00433                           + client->customElements.count() ),
    00434                           mergingIt );
    00435
    00436     // unplug all actionslists
    00437
    00438     ActionListMap::ConstIterator alIt = client->actionLists.begin();
    00439     ActionListMap::ConstIterator alEnd = client->actionLists.end();
    00440     for (; alIt != alEnd; ++alIt )
    00441     {
    00442         alIt.data().unplug( container );
    00443
    00444         // construct the merging index key (i.e. like named merging) , find the
    00445         // corresponding merging index and adjust all indices
    00446         QString mergingKey = alIt.key();
    00447         mergingKey.prepend( tagActionList );
    00448
    00449         MergingIndexList::Iterator mIt = findIndex( mergingKey );
    00450         if ( mIt == mergingIndices.end() )
    00451             continue;
    00452
    00453         adjustMergingIndices( -int(alIt.data().count()), mIt );
    00454
    00455         // remove the actionlists' merging index
    00456         // ### still needed? we clean up below anyway?
    00457         mergingIndices.remove( mIt );
    00458     }
    00459 }
    00460
    00461 void ContainerNode::reset()
    00462 {
    00463     QPtrListIterator<ContainerNode> childIt( children );
    00464     for (; childIt.current(); ++childIt )
    00465         childIt.current()->reset();
    00466
    00467     if ( client )
    00468         client->setFactory( 0L );
    00469 }
    00470
    00471 int ContainerNode::calcMergingIndex( const QString &mergingName,
    00472                                      MergingIndexList::Iterator &it,
    00473                                      BuildState &state,
    00474                                      bool ignoreDefaultMergingIndex )
    00475 {
    00476     MergingIndexList::Iterator mergingIt;
    00477
    00478     if ( mergingName.isEmpty() )
    00479         mergingIt = findIndex( state.clientName );
    00480     else
    00481         mergingIt = findIndex( mergingName );
    00482
    00483     MergingIndexList::Iterator mergingEnd = mergingIndices.end();
    00484     it = mergingEnd;
    00485
    00486     if ( ( mergingIt == mergingEnd && state.currentDefaultMergingIt == mergingEnd ) ||
    00487          ignoreDefaultMergingIndex )
    00488         return index;
    00489
    00490     if ( mergingIt != mergingEnd )
    00491         it = mergingIt;
    00492     else
    00493         it = state.currentDefaultMergingIt;
    00494
    00495     return (*it).value;
    00496 }
    00497
    00498 int BuildHelper::calcMergingIndex( const QDomElement &element, MergingIndexList::Iterator &it, QString &group )
    00499 {
    00500     static const QString &attrGroup = KGlobal::staticQString( "group" );
    00501
    00502     bool haveGroup = false;
    00503     group = element.attribute( attrGroup );
    00504     if ( !group.isEmpty() ) {
    00505         group.prepend( attrGroup );
    00506         haveGroup = true;
    00507     }
    00508
    00509     int idx;
    00510     if ( haveGroup )
    00511         idx = parentNode->calcMergingIndex( group, it, m_state, ignoreDefaultMergingIndex );
    00512     else if ( m_state.currentClientMergingIt == parentNode->mergingIndices.end() )
    00513         idx = parentNode->index;
    00514     else
    00515         idx = (*m_state.currentClientMergingIt).value;
    00516
    00517     return idx;
    00518 }
    00519
    00520 BuildHelper::BuildHelper( BuildState &state, ContainerNode *node )
    00521     : containerClient( 0 ), ignoreDefaultMergingIndex( false ), m_state( state ),
    00522       parentNode( node )
    00523 {
    00524     static const QString &defaultMergingName = KGlobal::staticQString( "<default>" );
    00525
    00526     // create a list of supported container and custom tags
    00527     customTags = m_state.builderCustomTags;
    00528     containerTags = m_state.builderContainerTags;
    00529
    00530     if ( parentNode->builder != m_state.builder )
    00531     {
    00532         customTags += parentNode->builderCustomTags;
    00533         containerTags += parentNode->builderContainerTags;
    00534     }
    00535
    00536     if ( m_state.clientBuilder ) {
    00537         customTags = m_state.clientBuilderCustomTags + customTags;
    00538         containerTags = m_state.clientBuilderContainerTags + containerTags;
    00539     }
    00540
    00541     m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName );
    00542     parentNode->calcMergingIndex( QString::null, m_state.currentClientMergingIt,
    00543                                   m_state, /*ignoreDefaultMergingIndex*/ false );
    00544 }
    00545
    00546 void BuildHelper::build( const QDomElement &element )
    00547 {
    00548     for (QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
    00549     {
    00550         QDomElement e = n.toElement();
    00551         if (e.isNull()) continue;
    00552         processElement( e );
    00553     }
    00554 }
    00555
    00556 void BuildHelper::processElement( const QDomElement &e )
    00557 {
    00558     // some often used QStrings
    00559     static const QString &tagAction = KGlobal::staticQString( "action" );
    00560     static const QString &tagMerge = KGlobal::staticQString( "merge" );
    00561     static const QString &tagState = KGlobal::staticQString( "state" );
    00562     static const QString &tagDefineGroup = KGlobal::staticQString( "definegroup" );
    00563     static const QString &tagActionList = KGlobal::staticQString( "actionlist" );
    00564     static const QString &attrName = KGlobal::staticQString( "name" );
    00565
    00566     QString tag( e.tagName().lower() );
    00567     QString currName( e.attribute( attrName ) );
    00568
    00569     bool isActionTag = ( tag == tagAction );
    00570
    00571     if ( isActionTag || customTags.findIndex( tag ) != -1 )
    00572         processActionOrCustomElement( e, isActionTag );
    00573     else if ( containerTags.findIndex( tag ) != -1 )
    00574         processContainerElement( e, tag, currName );
    00575     else if ( tag == tagMerge || tag == tagDefineGroup || tag == tagActionList )
    00576         processMergeElement( tag, currName, e );
    00577     else if ( tag == tagState )
    00578         processStateElement( e );
    00579 }
    00580
    00581 void BuildHelper::processActionOrCustomElement( const QDomElement &e, bool isActionTag )
    00582 {
    00583     if ( !parentNode->container )
    00584         return;
    00585
    00586     MergingIndexList::Iterator it( m_state.currentClientMergingIt );
    00587
    00588     QString group;
    00589     int idx = calcMergingIndex( e, it, group );
    00590
    00591     containerClient = parentNode->findChildContainerClient( m_state.guiClient, group, it );
    00592
    00593     bool guiElementCreated = false;
    00594     if ( isActionTag )
    00595         guiElementCreated = processActionElement( e, idx );
    00596     else
    00597         guiElementCreated = processCustomElement( e, idx );
    00598
    00599     if ( guiElementCreated )
    00600         // adjust any following merging indices and the current running index for the container
    00601         parentNode->adjustMergingIndices( 1, it );
    00602 }
    00603
    00604 bool BuildHelper::processActionElement( const QDomElement &e, int idx )
    00605 {
    00606     assert( m_state.guiClient );
    00607
    00608     // look up the action and plug it in
    00609     KAction *action = m_state.guiClient->action( e );
    00610
    00611     //kdDebug() << "BuildHelper::processActionElement " << e.attribute( "name" ) << " -> " << action << " (in " << m_state.guiClient->actionCollection() << ")" << endl;
    00612     if ( !action )
    00613         return false;
    00614
    00615     action->plug( parentNode->container, idx );
    00616
    00617     // save a reference to the plugged action, in order to properly unplug it afterwards.
    00618     containerClient->actions.append( action );
    00619
    00620     return true;
    00621 }
    00622
    00623 bool BuildHelper::processCustomElement( const QDomElement &e, int idx )
    00624 {
    00625     assert( parentNode->builder );
    00626
    00627     int id = parentNode->builder->createCustomElement( parentNode->container, idx, e );
    00628     if ( id == 0 )
    00629         return false;
    00630
    00631     containerClient->customElements.append( id );
    00632     return true;
    00633 }
    00634
    00635 void BuildHelper::processStateElement( const QDomElement &element )
    00636 {
    00637     QString stateName = element.attribute( "name" );
    00638
    00639     if ( !stateName || !stateName.length() ) return;
    00640
    00641     for (QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
    00642     {
    00643         QDomElement e = n.toElement();
    00644         if (e.isNull()) continue;
    00645
    00646         QString tagName = e.tagName().lower();
    00647
    00648         if ( tagName != "enable" && tagName != "disable" )
    00649             continue;
    00650
    00651         bool processingActionsToEnable = (tagName == "enable");
    00652
    00653         // process action names
    00654         for (QDomNode n2 = n.firstChild(); !n2.isNull(); n2 = n2.nextSibling() )
    00655         {
    00656             QDomElement actionEl = n2.toElement();
    00657             if ( actionEl.tagName().lower() != "action" ) continue;
    00658
    00659             QString actionName = actionEl.attribute( "name" );
    00660             if ( !actionName || !actionName.length() ) return;
    00661
    00662             if ( processingActionsToEnable )
    00663                 m_state.guiClient->addStateActionEnabled( stateName, actionName );
    00664             else
    00665                 m_state.guiClient->addStateActionDisabled( stateName, actionName );
    00666
    00667         }
    00668     }
    00669 }
    00670
    00671 void BuildHelper::processMergeElement( const QString &tag, const QString &name, const QDomElement &e )
    00672 {
    00673     static const QString &tagDefineGroup = KGlobal::staticQString( "definegroup" );
    00674     static const QString &tagActionList = KGlobal::staticQString( "actionlist" );
    00675     static const QString &defaultMergingName = KGlobal::staticQString( "<default>" );
    00676     static const QString &attrGroup = KGlobal::staticQString( "group" );
    00677
    00678     QString mergingName( name );
    00679     if ( mergingName.isEmpty() )
    00680     {
    00681         if ( tag == tagDefineGroup )
    00682         {
    00683             kdError(1000) << "cannot define group without name!" << endl;
    00684             return;
    00685         }
    00686         if ( tag == tagActionList )
    00687         {
    00688             kdError(1000) << "cannot define actionlist without name!" << endl;
    00689             return;
    00690         }
    00691         mergingName = defaultMergingName;
    00692     }
    00693
    00694     if ( tag == tagDefineGroup )
    00695         mergingName.prepend( attrGroup ); //avoid possible name clashes by prepending
    00696                                               // "group" to group definitions
    00697     else if ( tag == tagActionList )
    00698         mergingName.prepend( tagActionList );
    00699
    00700     if ( parentNode->findIndex( mergingName ) != parentNode->mergingIndices.end() )
    00701         return; //do not allow the redefinition of merging indices!
    00702
    00703     MergingIndexList::Iterator mIt( parentNode->mergingIndices.end() );
    00704
    00705     QString group( e.attribute( attrGroup ) );
    00706     if ( !group.isEmpty() )
    00707         group.prepend( attrGroup );
    00708
    00709     // calculate the index of the new merging index. Usually this does not need any calculation,
    00710     // we just want the last available index (i.e. append) . But in case the <Merge> tag appears
    00711     // "inside" another <Merge> tag from a previously build client, then we have to use the
    00712     // "parent's" index. That's why we call calcMergingIndex here.
    00713     MergingIndex newIdx;
    00714     newIdx.value = parentNode->calcMergingIndex( group, mIt, m_state, ignoreDefaultMergingIndex );
    00715     newIdx.mergingName = mergingName;
    00716     newIdx.clientName = m_state.clientName;
    00717
    00718     // if that merging index is "inside" another one, then append it right after the "parent" .
    00719     if ( mIt != parentNode->mergingIndices.end() )
    00720         parentNode->mergingIndices.insert( ++mIt, newIdx );
    00721     else
    00722         parentNode->mergingIndices.append( newIdx );
    00723
    00724     if ( mergingName == defaultMergingName )
    00725
    00726         ignoreDefaultMergingIndex = true;
    00727
    00728     // re-calculate the running default and client merging indices.
    00729     m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName );
    00730     parentNode->calcMergingIndex( QString::null, m_state.currentClientMergingIt,
    00731                                   m_state, ignoreDefaultMergingIndex );
    00732 }
    00733
    00734 void BuildHelper::processContainerElement( const QDomElement &e, const QString &tag,
    00735                                            const QString &name )
    00736 {
    00737     static const QString &defaultMergingName = KGlobal::staticQString( "<default>" );
    00738
    00739     ContainerNode *containerNode = parentNode->findContainer( name, tag,
    00740                                                               &containerList,
    00741                                                               m_state.guiClient );
    00742
    00743     if ( !containerNode )
    00744     {
    00745         MergingIndexList::Iterator it( m_state.currentClientMergingIt );
    00746         QString group;
    00747
    00748         int idx = calcMergingIndex( e, it, group );
    00749
    00750         int id;
    00751
    00752         KXMLGUIBuilder *builder;
    00753
    00754         QWidget *container = createContainer( parentNode->container, idx, e, id, &builder );
    00755
    00756         // no container? (probably some <text> tag or so ;-)
    00757         if ( !container )
    00758             return;
    00759
    00760         parentNode->adjustMergingIndices( 1, it );
    00761
    00762         assert( !parentNode->findContainerNode( container ) );
    00763
    00764         containerList.append( container );
    00765
    00766         QString mergingName;
    00767         if ( it != parentNode->mergingIndices.end() )
    00768             mergingName = (*it).mergingName;
    00769
    00770         QStringList cusTags = m_state.builderCustomTags;
    00771         QStringList conTags = m_state.builderContainerTags;
    00772         if ( builder != m_state.builder )
    00773         {
    00774             cusTags = m_state.clientBuilderCustomTags;
    00775             conTags = m_state.clientBuilderContainerTags;
    00776         }
    00777
    00778         containerNode = new ContainerNode( container, tag, name, parentNode,
    00779                                            m_state.guiClient, builder, id,
    00780                                            mergingName, group, cusTags, conTags );
    00781     }
    00782
    00783     BuildHelper( m_state, containerNode ).build( e );
    00784
    00785     // and re-calculate running values, for better performance
    00786     m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName );
    00787     parentNode->calcMergingIndex( QString::null, m_state.currentClientMergingIt,
    00788                                   m_state, ignoreDefaultMergingIndex );
    00789 }
    00790
    00791 QWidget *BuildHelper::createContainer( QWidget *parent, int index,
    00792                                        const QDomElement &element, int &id,
    00793                                        KXMLGUIBuilder **builder )
    00794 {
    00795     QWidget *res = 0L;
    00796
    00797     if ( m_state.clientBuilder )
    00798     {
    00799         res = m_state.clientBuilder->createContainer( parent, index, element, id );
    00800
    00801         if ( res )
    00802         {
    00803             *builder = m_state.clientBuilder;
    00804             return res;
    00805         }
    00806     }
    00807
    00808     KInstance *oldInstance = m_state.builder->builderInstance();
    00809     KXMLGUIClient *oldClient = m_state.builder->builderClient();
    00810
    00811     m_state.builder->setBuilderClient( m_state.guiClient );
    00812
    00813     res = m_state.builder->createContainer( parent, index, element, id );
    00814
    00815     m_state.builder->setBuilderInstance( oldInstance );
    00816     m_state.builder->setBuilderClient( oldClient );
    00817
    00818     if ( res )
    00819         *builder = m_state.builder;
    00820
    00821     return res;
    00822 }
    00823
    00824 void BuildState::reset()
    00825 {
    00826     clientName = QString::null;
    00827     actionListName = QString::null;
    00828     actionList.clear();
    00829     guiClient = 0;
    00830     clientBuilder = 0;
    00831
    00832     currentDefaultMergingIt = currentClientMergingIt = MergingIndexList::Iterator();
    00833 }
    00834
    00835 /* vim: et sw=4
    00836  */

This file is part of the documentation for kdeui Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:20:25 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003