kdeui Library API Documentation

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( -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 QDomElement e; 00371 // ### slow 00372 for ( e = baseElement.firstChild().toElement(); !e.isNull(); 00373 e = e.nextSibling().toElement() ) 00374 if ( e.tagName().lower() == childNode->tagName && 00375 e.attribute( attrName ) == childNode->name ) 00376 return e; 00377 00378 return QDomElement(); 00379 } 00380 00381 void ContainerNode::unplugActions( BuildState &state ) 00382 { 00383 if ( !container ) 00384 return; 00385 00386 ContainerClientListIt clientIt( clients ); 00387 00388 /* 00389 Disabled because it means in KToolBar::saveState isHidden is always true then, 00390 which is clearly wrong. 00391 00392 if ( clients.count() == 1 && clientIt.current()->client == client && 00393 client == state.guiClient ) 00394 container->hide(); // this container is going to die, that's for sure. 00395 // in this case let's just hide it, which makes the 00396 // destruction faster 00397 */ 00398 00399 while ( clientIt.current() ) 00400 //only unplug the actions of the client we want to remove, as the container might be owned 00401 //by a different client 00402 if ( clientIt.current()->client == state.guiClient ) 00403 { 00404 unplugClient( clientIt.current() ); 00405 clients.removeRef( clientIt.current() ); 00406 } 00407 else 00408 ++clientIt; 00409 } 00410 00411 void ContainerNode::unplugClient( ContainerClient *client ) 00412 { 00413 static const QString &tagActionList = KGlobal::staticQString( "actionlist" ); 00414 00415 assert( builder ); 00416 00417 // now quickly remove all custom elements (i.e. separators) and unplug all actions 00418 00419 QValueList<int>::ConstIterator custIt = client->customElements.begin(); 00420 QValueList<int>::ConstIterator custEnd = client->customElements.end(); 00421 for (; custIt != custEnd; ++custIt ) 00422 builder->removeCustomElement( container, *custIt ); 00423 00424 client->actions.unplug( container ); 00425 00426 // now adjust all merging indices 00427 00428 MergingIndexList::Iterator mergingIt = findIndex( client->mergingName ); 00429 00430 adjustMergingIndices( - ( client->actions.count() 00431 + client->customElements.count() ), 00432 mergingIt ); 00433 00434 // unplug all actionslists 00435 00436 ActionListMap::ConstIterator alIt = client->actionLists.begin(); 00437 ActionListMap::ConstIterator alEnd = client->actionLists.end(); 00438 for (; alIt != alEnd; ++alIt ) 00439 { 00440 alIt.data().unplug( container ); 00441 00442 // construct the merging index key (i.e. like named merging) , find the 00443 // corresponding merging index and adjust all indices 00444 QString mergingKey = alIt.key(); 00445 mergingKey.prepend( tagActionList ); 00446 00447 MergingIndexList::Iterator mIt = findIndex( mergingKey ); 00448 if ( mIt == mergingIndices.end() ) 00449 continue; 00450 00451 adjustMergingIndices( - alIt.data().count(), mIt ); 00452 00453 // remove the actionlists' merging index 00454 // ### still needed? we clean up below anyway? 00455 mergingIndices.remove( mIt ); 00456 } 00457 } 00458 00459 void ContainerNode::reset() 00460 { 00461 QPtrListIterator<ContainerNode> childIt( children ); 00462 for (; childIt.current(); ++childIt ) 00463 childIt.current()->reset(); 00464 00465 if ( client ) 00466 client->setFactory( 0L ); 00467 } 00468 00469 int ContainerNode::calcMergingIndex( const QString &mergingName, 00470 MergingIndexList::Iterator &it, 00471 BuildState &state, 00472 bool ignoreDefaultMergingIndex ) 00473 { 00474 MergingIndexList::Iterator mergingIt; 00475 00476 if ( mergingName.isEmpty() ) 00477 mergingIt = findIndex( state.clientName ); 00478 else 00479 mergingIt = findIndex( mergingName ); 00480 00481 MergingIndexList::Iterator mergingEnd = mergingIndices.end(); 00482 it = mergingEnd; 00483 00484 if ( ( mergingIt == mergingEnd && state.currentDefaultMergingIt == mergingEnd ) || 00485 ignoreDefaultMergingIndex ) 00486 return index; 00487 00488 if ( mergingIt != mergingEnd ) 00489 it = mergingIt; 00490 else 00491 it = state.currentDefaultMergingIt; 00492 00493 return (*it).value; 00494 } 00495 00496 int BuildHelper::calcMergingIndex( const QDomElement &element, MergingIndexList::Iterator &it, QString &group ) 00497 { 00498 static const QString &attrGroup = KGlobal::staticQString( "group" ); 00499 00500 bool haveGroup = false; 00501 group = element.attribute( attrGroup ); 00502 if ( !group.isEmpty() ) { 00503 group.prepend( attrGroup ); 00504 haveGroup = true; 00505 } 00506 00507 int idx; 00508 if ( haveGroup ) 00509 idx = parentNode->calcMergingIndex( group, it, m_state, ignoreDefaultMergingIndex ); 00510 else if ( m_state.currentClientMergingIt == parentNode->mergingIndices.end() ) 00511 idx = parentNode->index; 00512 else 00513 idx = (*m_state.currentClientMergingIt).value; 00514 00515 return idx; 00516 } 00517 00518 BuildHelper::BuildHelper( BuildState &state, ContainerNode *node ) 00519 : containerClient( 0 ), ignoreDefaultMergingIndex( false ), m_state( state ), 00520 parentNode( node ) 00521 { 00522 static const QString &defaultMergingName = KGlobal::staticQString( "<default>" ); 00523 00524 // create a list of supported container and custom tags 00525 customTags = m_state.builderCustomTags; 00526 containerTags = m_state.builderContainerTags; 00527 00528 if ( parentNode->builder != m_state.builder ) 00529 { 00530 customTags += parentNode->builderCustomTags; 00531 containerTags += parentNode->builderContainerTags; 00532 } 00533 00534 if ( m_state.clientBuilder ) { 00535 customTags = m_state.clientBuilderCustomTags + customTags; 00536 containerTags = m_state.clientBuilderContainerTags + containerTags; 00537 } 00538 00539 m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName ); 00540 parentNode->calcMergingIndex( QString::null, m_state.currentClientMergingIt, 00541 m_state, /*ignoreDefaultMergingIndex*/ false ); 00542 } 00543 00544 void BuildHelper::build( const QDomElement &element ) 00545 { 00546 QDomElement e = element.firstChild().toElement(); 00547 for (; !e.isNull(); e = e.nextSibling().toElement() ) 00548 processElement( e ); 00549 } 00550 00551 void BuildHelper::processElement( const QDomElement &e ) 00552 { 00553 // some often used QStrings 00554 static const QString &tagAction = KGlobal::staticQString( "action" ); 00555 static const QString &tagMerge = KGlobal::staticQString( "merge" ); 00556 static const QString &tagState = KGlobal::staticQString( "state" ); 00557 static const QString &tagDefineGroup = KGlobal::staticQString( "definegroup" ); 00558 static const QString &tagActionList = KGlobal::staticQString( "actionlist" ); 00559 static const QString &attrName = KGlobal::staticQString( "name" ); 00560 00561 QString tag( e.tagName().lower() ); 00562 QString currName( e.attribute( attrName ) ); 00563 00564 bool isActionTag = ( tag == tagAction ); 00565 00566 if ( isActionTag || customTags.findIndex( tag ) != -1 ) 00567 processActionOrCustomElement( e, isActionTag ); 00568 else if ( containerTags.findIndex( tag ) != -1 ) 00569 processContainerElement( e, tag, currName ); 00570 else if ( tag == tagMerge || tag == tagDefineGroup || tag == tagActionList ) 00571 processMergeElement( tag, currName, e ); 00572 else if ( tag == tagState ) 00573 processStateElement( e ); 00574 } 00575 00576 void BuildHelper::processActionOrCustomElement( const QDomElement &e, bool isActionTag ) 00577 { 00578 if ( !parentNode->container ) 00579 return; 00580 00581 MergingIndexList::Iterator it( m_state.currentClientMergingIt ); 00582 00583 QString group; 00584 int idx = calcMergingIndex( e, it, group ); 00585 00586 containerClient = parentNode->findChildContainerClient( m_state.guiClient, group, it ); 00587 00588 bool guiElementCreated = false; 00589 if ( isActionTag ) 00590 guiElementCreated = processActionElement( e, idx ); 00591 else 00592 guiElementCreated = processCustomElement( e, idx ); 00593 00594 if ( guiElementCreated ) 00595 // adjust any following merging indices and the current running index for the container 00596 parentNode->adjustMergingIndices( 1, it ); 00597 } 00598 00599 bool BuildHelper::processActionElement( const QDomElement &e, int idx ) 00600 { 00601 assert( m_state.guiClient ); 00602 00603 // look up the action and plug it in 00604 KAction *action = m_state.guiClient->action( e ); 00605 00606 if ( !action ) 00607 return false; 00608 00609 action->plug( parentNode->container, idx ); 00610 00611 // save a reference to the plugged action, in order to properly unplug it afterwards. 00612 containerClient->actions.append( action ); 00613 00614 return true; 00615 } 00616 00617 bool BuildHelper::processCustomElement( const QDomElement &e, int idx ) 00618 { 00619 assert( parentNode->builder ); 00620 00621 int id = parentNode->builder->createCustomElement( parentNode->container, idx, e ); 00622 if ( id == 0 ) 00623 return false; 00624 00625 containerClient->customElements.append( id ); 00626 return true; 00627 } 00628 00629 void BuildHelper::processStateElement( const QDomElement &element ) 00630 { 00631 QString stateName = element.attribute( "name" ); 00632 00633 if ( !stateName || !stateName.length() ) return; 00634 00635 QDomElement e = element.firstChild().toElement(); 00636 00637 for (; !e.isNull(); e = e.nextSibling().toElement() ) { 00638 QString tagName = e.tagName().lower(); 00639 00640 if ( tagName != "enable" && tagName != "disable" ) 00641 continue; 00642 00643 bool processingActionsToEnable = (tagName == "enable"); 00644 00645 // process action names 00646 QDomElement actionEl = e.firstChild().toElement(); 00647 00648 for (; !actionEl.isNull(); actionEl = actionEl.nextSibling().toElement() ) { 00649 if ( actionEl.tagName().lower() != "action" ) continue; 00650 00651 QString actionName = actionEl.attribute( "name" ); 00652 if ( !actionName || !actionName.length() ) return; 00653 00654 if ( processingActionsToEnable ) 00655 m_state.guiClient->addStateActionEnabled( stateName, actionName ); 00656 else 00657 m_state.guiClient->addStateActionDisabled( stateName, actionName ); 00658 00659 } 00660 } 00661 } 00662 00663 void BuildHelper::processMergeElement( const QString &tag, const QString &name, const QDomElement &e ) 00664 { 00665 static const QString &tagDefineGroup = KGlobal::staticQString( "definegroup" ); 00666 static const QString &tagActionList = KGlobal::staticQString( "actionlist" ); 00667 static const QString &defaultMergingName = KGlobal::staticQString( "<default>" ); 00668 static const QString &attrGroup = KGlobal::staticQString( "group" ); 00669 00670 QString mergingName( name ); 00671 if ( mergingName.isEmpty() ) 00672 { 00673 if ( tag == tagDefineGroup ) 00674 { 00675 kdError(1000) << "cannot define group without name!" << endl; 00676 return; 00677 } 00678 if ( tag == tagActionList ) 00679 { 00680 kdError(1000) << "cannot define actionlist without name!" << endl; 00681 return; 00682 } 00683 mergingName = defaultMergingName; 00684 } 00685 00686 if ( tag == tagDefineGroup ) 00687 mergingName.prepend( attrGroup ); //avoid possible name clashes by prepending 00688 // "group" to group definitions 00689 else if ( tag == tagActionList ) 00690 mergingName.prepend( tagActionList ); 00691 00692 if ( parentNode->findIndex( mergingName ) != parentNode->mergingIndices.end() ) 00693 return; //do not allow the redefinition of merging indices! 00694 00695 MergingIndexList::Iterator mIt( parentNode->mergingIndices.end() ); 00696 00697 QString group( e.attribute( attrGroup ) ); 00698 if ( !group.isEmpty() ) 00699 group.prepend( attrGroup ); 00700 00701 // calculate the index of the new merging index. Usually this does not need any calculation, 00702 // we just want the last available index (i.e. append) . But in case the <Merge> tag appears 00703 // "inside" another <Merge> tag from a previously build client, then we have to use the 00704 // "parent's" index. That's why we call calcMergingIndex here. 00705 MergingIndex newIdx; 00706 newIdx.value = parentNode->calcMergingIndex( group, mIt, m_state, ignoreDefaultMergingIndex ); 00707 newIdx.mergingName = mergingName; 00708 newIdx.clientName = m_state.clientName; 00709 00710 // if that merging index is "inside" another one, then append it right after the "parent" . 00711 if ( mIt != parentNode->mergingIndices.end() ) 00712 parentNode->mergingIndices.insert( ++mIt, newIdx ); 00713 else 00714 parentNode->mergingIndices.append( newIdx ); 00715 00716 if ( mergingName == defaultMergingName ) 00717 00718 ignoreDefaultMergingIndex = true; 00719 00720 // re-calculate the running default and client merging indices. 00721 m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName ); 00722 parentNode->calcMergingIndex( QString::null, m_state.currentClientMergingIt, 00723 m_state, ignoreDefaultMergingIndex ); 00724 } 00725 00726 void BuildHelper::processContainerElement( const QDomElement &e, const QString &tag, 00727 const QString &name ) 00728 { 00729 static const QString &defaultMergingName = KGlobal::staticQString( "<default>" ); 00730 00731 ContainerNode *containerNode = parentNode->findContainer( name, tag, 00732 &containerList, 00733 m_state.guiClient ); 00734 00735 if ( !containerNode ) 00736 { 00737 MergingIndexList::Iterator it( m_state.currentClientMergingIt ); 00738 QString group; 00739 00740 int idx = calcMergingIndex( e, it, group ); 00741 00742 int id; 00743 00744 KXMLGUIBuilder *builder; 00745 00746 QWidget *container = createContainer( parentNode->container, idx, e, id, &builder ); 00747 00748 // no container? (probably some <text> tag or so ;-) 00749 if ( !container ) 00750 return; 00751 00752 parentNode->adjustMergingIndices( 1, it ); 00753 00754 assert( parentNode->findContainerNode( container ) == 0 ); 00755 00756 containerList.append( container ); 00757 00758 QString mergingName; 00759 if ( it != parentNode->mergingIndices.end() ) 00760 mergingName = (*it).mergingName; 00761 00762 QStringList cusTags = m_state.builderCustomTags; 00763 QStringList conTags = m_state.builderContainerTags; 00764 if ( builder != m_state.builder ) 00765 { 00766 cusTags = m_state.clientBuilderCustomTags; 00767 conTags = m_state.clientBuilderContainerTags; 00768 } 00769 00770 containerNode = new ContainerNode( container, tag, name, parentNode, 00771 m_state.guiClient, builder, id, 00772 mergingName, group, cusTags, conTags ); 00773 } 00774 00775 BuildHelper( m_state, containerNode ).build( e ); 00776 00777 // and re-calculate running values, for better performance 00778 m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName ); 00779 parentNode->calcMergingIndex( QString::null, m_state.currentClientMergingIt, 00780 m_state, ignoreDefaultMergingIndex ); 00781 } 00782 00783 QWidget *BuildHelper::createContainer( QWidget *parent, int index, 00784 const QDomElement &element, int &id, 00785 KXMLGUIBuilder **builder ) 00786 { 00787 QWidget *res = 0L; 00788 00789 if ( m_state.clientBuilder ) 00790 { 00791 res = m_state.clientBuilder->createContainer( parent, index, element, id ); 00792 00793 if ( res ) 00794 { 00795 *builder = m_state.clientBuilder; 00796 return res; 00797 } 00798 } 00799 00800 KInstance *oldInstance = m_state.builder->builderInstance(); 00801 KXMLGUIClient *oldClient = m_state.builder->builderClient(); 00802 00803 m_state.builder->setBuilderClient( m_state.guiClient ); 00804 00805 res = m_state.builder->createContainer( parent, index, element, id ); 00806 00807 m_state.builder->setBuilderInstance( oldInstance ); 00808 m_state.builder->setBuilderClient( oldClient ); 00809 00810 if ( res ) 00811 *builder = m_state.builder; 00812 00813 return res; 00814 } 00815 00816 void BuildState::reset() 00817 { 00818 clientName = QString::null; 00819 actionListName = QString::null; 00820 actionList.clear(); 00821 guiClient = 0; 00822 clientBuilder = 0; 00823 00824 currentDefaultMergingIt = currentClientMergingIt = MergingIndexList::Iterator(); 00825 } 00826 00827 /* vim: et sw=4 00828 */
KDE Logo
This file is part of the documentation for kdeui Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 8 11:14:29 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003