20 #include "kxmlguifactory_p.h"
21 #include "kxmlguiclient.h"
22 #include "kxmlguibuilder.h"
26 #include <tdeglobal.h>
31 using namespace KXMLGUI;
33 void ActionList::plug( TQWidget *container,
int index )
const
35 ActionListIt it( *
this );
36 for (; it.current(); ++it )
37 it.current()->plug( container, index++ );
40 void ActionList::unplug( TQWidget *container )
const
42 ActionListIt it( *
this );
43 for (; it.current(); ++it )
44 it.current()->unplug( container );
47 ContainerNode::ContainerNode( TQWidget *_container,
const TQString &_tagName,
48 const TQString &_name, ContainerNode *_parent,
50 int id,
const TQString &_mergingName,
51 const TQString &_groupName,
const TQStringList &customTags,
52 const TQStringList &containerTags )
53 : parent( _parent ), client( _client ), builder( _builder ),
54 builderCustomTags( customTags ), builderContainerTags( containerTags ),
55 container( _container ), containerId( id ), tagName( _tagName ),
name( _name ),
56 groupName( _groupName ), index( 0 ), mergingName( _mergingName )
58 children.setAutoDelete(
true );
59 clients.setAutoDelete(
true );
62 parent->children.append(
this );
65 void ContainerNode::removeChild( ContainerNode *child )
67 MergingIndexList::Iterator mergingIt = findIndex( child->mergingName );
68 adjustMergingIndices( -1, mergingIt );
69 children.removeRef( child );
76 MergingIndexList::Iterator ContainerNode::findIndex(
const TQString &name )
78 MergingIndexList::Iterator it( mergingIndices.begin() );
79 MergingIndexList::Iterator
end( mergingIndices.end() );
80 for (; it !=
end; ++it )
81 if ( (*it).mergingName == name )
90 ContainerNode *ContainerNode::findContainerNode( TQWidget *container )
92 ContainerNodeListIt it( children );
94 for (; it.current(); ++it )
95 if ( it.current()->container == container )
106 ContainerNode *ContainerNode::findContainer(
const TQString &_name,
bool tag )
108 if ( ( tag && tagName == _name ) ||
109 ( !tag && name == _name ) )
112 ContainerNodeListIt it( children );
113 for (; it.current(); ++it )
115 ContainerNode *res = it.current()->findContainer( _name, tag );
128 ContainerNode *ContainerNode::findContainer(
const TQString &name,
const TQString &tagName,
129 const TQPtrList<TQWidget> *excludeList,
132 ContainerNode *res = 0L;
133 ContainerNodeListIt nIt( children );
135 if ( !
name.isEmpty() )
137 for (; nIt.current(); ++nIt )
138 if ( nIt.current()->name == name &&
139 !excludeList->containsRef( nIt.current()->container ) )
148 if ( !tagName.isEmpty() )
149 for (; nIt.current(); ++nIt )
151 if ( nIt.current()->tagName == tagName &&
152 !excludeList->containsRef( nIt.current()->container )
178 ContainerClient *ContainerNode::findChildContainerClient(
KXMLGUIClient *currentGUIClient,
179 const TQString &groupName,
180 const MergingIndexList::Iterator &mergingIdx )
182 if ( !clients.isEmpty() )
184 ContainerClientListIt clientIt( clients );
186 for (; clientIt.current(); ++clientIt )
187 if ( clientIt.current()->client == currentGUIClient )
189 if ( groupName.isEmpty() )
190 return clientIt.current();
192 if ( groupName == clientIt.current()->groupName )
193 return clientIt.current();
197 ContainerClient *client =
new ContainerClient;
198 client->client = currentGUIClient;
199 client->groupName = groupName;
201 if ( mergingIdx != mergingIndices.end() )
202 client->mergingName = (*mergingIdx).mergingName;
204 clients.append( client );
209 void ContainerNode::plugActionList( BuildState &state )
211 MergingIndexList::Iterator mIt( mergingIndices.begin() );
212 MergingIndexList::Iterator mEnd( mergingIndices.end() );
213 for (; mIt != mEnd; ++mIt )
214 plugActionList( state, mIt );
216 TQPtrListIterator<ContainerNode> childIt( children );
217 for (; childIt.current(); ++childIt )
218 childIt.current()->plugActionList( state );
221 void ContainerNode::plugActionList( BuildState &state,
const MergingIndexList::Iterator &mergingIdxIt )
225 MergingIndex mergingIdx = *mergingIdxIt;
227 TQString k( mergingIdx.mergingName );
229 if ( k.find( tagActionList ) == -1 )
232 k = k.mid( tagActionList.length() );
234 if ( mergingIdx.clientName != state.clientName )
237 if ( k != state.actionListName )
240 ContainerClient *client = findChildContainerClient( state.guiClient,
242 mergingIndices.end() );
244 client->actionLists.insert( k, state.actionList );
246 state.actionList.plug( container, mergingIdx.value );
248 adjustMergingIndices( state.actionList.count(), mergingIdxIt );
251 void ContainerNode::unplugActionList( BuildState &state )
253 MergingIndexList::Iterator mIt( mergingIndices.begin() );
254 MergingIndexList::Iterator mEnd( mergingIndices.end() );
255 for (; mIt != mEnd; ++mIt )
256 unplugActionList( state, mIt );
258 TQPtrListIterator<ContainerNode> childIt( children );
259 for (; childIt.current(); ++childIt )
260 childIt.current()->unplugActionList( state );
263 void ContainerNode::unplugActionList( BuildState &state,
const MergingIndexList::Iterator &mergingIdxIt )
267 MergingIndex mergingIdx = *mergingIdxIt;
269 TQString k = mergingIdx.mergingName;
271 if ( k.find( tagActionList ) == -1 )
274 k = k.mid( tagActionList.length() );
276 if ( mergingIdx.clientName != state.clientName )
279 if ( k != state.actionListName )
282 ContainerClient *client = findChildContainerClient( state.guiClient,
284 mergingIndices.end() );
286 ActionListMap::Iterator lIt( client->actionLists.find( k ) );
287 if ( lIt == client->actionLists.end() )
290 lIt.data().unplug( container );
292 adjustMergingIndices( -
int(lIt.data().count()), mergingIdxIt );
294 client->actionLists.remove( lIt );
297 void ContainerNode::adjustMergingIndices(
int offset,
298 const MergingIndexList::Iterator &it )
300 MergingIndexList::Iterator mergingIt = it;
301 MergingIndexList::Iterator mergingEnd = mergingIndices.end();
303 for (; mergingIt != mergingEnd; ++mergingIt )
304 (*mergingIt).value += offset;
309 bool ContainerNode::destruct( TQDomElement element, BuildState &state )
311 destructChildren( element, state );
313 unplugActions( state );
316 MergingIndexList::Iterator cmIt = mergingIndices.begin();
317 while ( cmIt != mergingIndices.end() )
318 if ( (*cmIt).clientName == state.clientName )
319 cmIt = mergingIndices.remove( cmIt );
324 if ( clients.count() == 0 && children.count() == 0 && container &&
325 client == state.guiClient )
327 TQWidget *parentContainer = 0L;
329 if ( parent && parent->container )
330 parentContainer = parent->container;
334 builder->removeContainer( container, parentContainer, element, containerId );
341 if ( client == state.guiClient )
348 void ContainerNode::destructChildren(
const TQDomElement &element, BuildState &state )
350 TQPtrListIterator<ContainerNode> childIt( children );
351 while ( childIt.current() )
353 ContainerNode *childNode = childIt.current();
355 TQDomElement childElement = findElementForChild( element, childNode );
358 if ( childNode->destruct( childElement, state ) )
359 removeChild( childNode );
365 TQDomElement ContainerNode::findElementForChild(
const TQDomElement &baseElement,
366 ContainerNode *childNode )
371 for ( TQDomNode n = baseElement.firstChild(); !n.isNull();
372 n = n.nextSibling() )
374 TQDomElement e = n.toElement();
375 if ( e.tagName().lower() == childNode->tagName &&
376 e.attribute( attrName ) == childNode->name )
380 return TQDomElement();
383 void ContainerNode::unplugActions( BuildState &state )
388 ContainerClientListIt clientIt( clients );
401 while ( clientIt.current() )
404 if ( clientIt.current()->client == state.guiClient )
406 unplugClient( clientIt.current() );
407 clients.removeRef( clientIt.current() );
413 void ContainerNode::unplugClient( ContainerClient *client )
421 TQValueList<int>::ConstIterator custIt = client->customElements.begin();
422 TQValueList<int>::ConstIterator custEnd = client->customElements.end();
423 for (; custIt != custEnd; ++custIt )
424 builder->removeCustomElement( container, *custIt );
426 client->actions.unplug( container );
430 MergingIndexList::Iterator mergingIt = findIndex( client->mergingName );
432 adjustMergingIndices( -
int( client->actions.count()
433 + client->customElements.count() ),
438 ActionListMap::ConstIterator alIt = client->actionLists.begin();
439 ActionListMap::ConstIterator alEnd = client->actionLists.end();
440 for (; alIt != alEnd; ++alIt )
442 alIt.data().unplug( container );
446 TQString mergingKey = alIt.key();
447 mergingKey.prepend( tagActionList );
449 MergingIndexList::Iterator mIt = findIndex( mergingKey );
450 if ( mIt == mergingIndices.end() )
453 adjustMergingIndices( -
int(alIt.data().count()), mIt );
457 mergingIndices.remove( mIt );
461 void ContainerNode::reset()
463 TQPtrListIterator<ContainerNode> childIt( children );
464 for (; childIt.current(); ++childIt )
465 childIt.current()->reset();
468 client->setFactory( 0L );
471 int ContainerNode::calcMergingIndex(
const TQString &mergingName,
472 MergingIndexList::Iterator &it,
474 bool ignoreDefaultMergingIndex )
476 MergingIndexList::Iterator mergingIt;
478 if ( mergingName.isEmpty() )
479 mergingIt = findIndex( state.clientName );
481 mergingIt = findIndex( mergingName );
483 MergingIndexList::Iterator mergingEnd = mergingIndices.end();
486 if ( ( mergingIt == mergingEnd && state.currentDefaultMergingIt == mergingEnd ) ||
487 ignoreDefaultMergingIndex )
490 if ( mergingIt != mergingEnd )
493 it = state.currentDefaultMergingIt;
498 int BuildHelper::calcMergingIndex(
const TQDomElement &element, MergingIndexList::Iterator &it, TQString &group )
502 bool haveGroup =
false;
503 group = element.attribute( attrGroup );
504 if ( !group.isEmpty() ) {
505 group.prepend( attrGroup );
511 idx = parentNode->calcMergingIndex( group, it, m_state, ignoreDefaultMergingIndex );
512 else if ( m_state.currentClientMergingIt == parentNode->mergingIndices.end() )
513 idx = parentNode->index;
515 idx = (*m_state.currentClientMergingIt).value;
520 BuildHelper::BuildHelper( BuildState &state, ContainerNode *node )
521 : containerClient( 0 ), ignoreDefaultMergingIndex( false ), m_state( state ),
527 customTags = m_state.builderCustomTags;
528 containerTags = m_state.builderContainerTags;
530 if ( parentNode->builder != m_state.builder )
532 customTags += parentNode->builderCustomTags;
533 containerTags += parentNode->builderContainerTags;
536 if ( m_state.clientBuilder ) {
537 customTags = m_state.clientBuilderCustomTags + customTags;
538 containerTags = m_state.clientBuilderContainerTags + containerTags;
541 m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName );
542 parentNode->calcMergingIndex( TQString(), m_state.currentClientMergingIt,
546 void BuildHelper::build(
const TQDomElement &element )
548 for (TQDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
550 TQDomElement e = n.toElement();
551 if (e.isNull())
continue;
556 void BuildHelper::processElement(
const TQDomElement &e )
566 TQString tag( e.tagName().lower() );
567 TQString currName( e.attribute( attrName ) );
569 bool isActionTag = ( tag == tagAction );
571 if ( isActionTag || customTags.findIndex( tag ) != -1 )
572 processActionOrCustomElement( e, isActionTag );
573 else if ( containerTags.findIndex( tag ) != -1 )
574 processContainerElement( e, tag, currName );
575 else if ( tag == tagMerge || tag == tagDefineGroup || tag == tagActionList )
576 processMergeElement( tag, currName, e );
577 else if ( tag == tagState )
578 processStateElement( e );
581 void BuildHelper::processActionOrCustomElement(
const TQDomElement &e,
bool isActionTag )
583 if ( !parentNode->container )
586 MergingIndexList::Iterator it( m_state.currentClientMergingIt );
589 int idx = calcMergingIndex( e, it, group );
591 containerClient = parentNode->findChildContainerClient( m_state.guiClient, group, it );
593 bool guiElementCreated =
false;
595 guiElementCreated = processActionElement( e, idx );
597 guiElementCreated = processCustomElement( e, idx );
599 if ( guiElementCreated )
601 parentNode->adjustMergingIndices( 1, it );
604 bool BuildHelper::processActionElement(
const TQDomElement &e,
int idx )
606 assert( m_state.guiClient );
615 action->plug( parentNode->container, idx );
618 containerClient->actions.append( action );
623 bool BuildHelper::processCustomElement(
const TQDomElement &e,
int idx )
625 assert( parentNode->builder );
627 int id = parentNode->builder->createCustomElement( parentNode->container, idx, e );
631 containerClient->customElements.append(
id );
635 void BuildHelper::processStateElement(
const TQDomElement &element )
637 TQString stateName = element.attribute(
"name" );
639 if ( !stateName || !stateName.length() )
return;
641 for (TQDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
643 TQDomElement e = n.toElement();
644 if (e.isNull())
continue;
646 TQString tagName = e.tagName().lower();
648 if ( tagName !=
"enable" && tagName !=
"disable" )
651 bool processingActionsToEnable = (tagName ==
"enable");
654 for (TQDomNode n2 = n.firstChild(); !n2.isNull(); n2 = n2.nextSibling() )
656 TQDomElement actionEl = n2.toElement();
657 if ( actionEl.tagName().lower() !=
"action" )
continue;
659 TQString actionName = actionEl.attribute(
"name" );
660 if ( !actionName || !actionName.length() )
return;
662 if ( processingActionsToEnable )
663 m_state.guiClient->addStateActionEnabled( stateName, actionName );
665 m_state.guiClient->addStateActionDisabled( stateName, actionName );
671 void BuildHelper::processMergeElement(
const TQString &tag,
const TQString &name,
const TQDomElement &e )
678 TQString mergingName( name );
679 if ( mergingName.isEmpty() )
681 if ( tag == tagDefineGroup )
683 kdError(1000) <<
"cannot define group without name!" <<
endl;
686 if ( tag == tagActionList )
688 kdError(1000) <<
"cannot define actionlist without name!" <<
endl;
691 mergingName = defaultMergingName;
694 if ( tag == tagDefineGroup )
695 mergingName.prepend( attrGroup );
697 else if ( tag == tagActionList )
698 mergingName.prepend( tagActionList );
700 if ( parentNode->findIndex( mergingName ) != parentNode->mergingIndices.end() )
703 MergingIndexList::Iterator mIt( parentNode->mergingIndices.end() );
705 TQString group( e.attribute( attrGroup ) );
706 if ( !group.isEmpty() )
707 group.prepend( attrGroup );
714 newIdx.value = parentNode->calcMergingIndex( group, mIt, m_state, ignoreDefaultMergingIndex );
715 newIdx.mergingName = mergingName;
716 newIdx.clientName = m_state.clientName;
719 if ( mIt != parentNode->mergingIndices.end() )
720 parentNode->mergingIndices.insert( ++mIt, newIdx );
722 parentNode->mergingIndices.append( newIdx );
724 if ( mergingName == defaultMergingName )
726 ignoreDefaultMergingIndex =
true;
729 m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName );
730 parentNode->calcMergingIndex( TQString(), m_state.currentClientMergingIt,
731 m_state, ignoreDefaultMergingIndex );
734 void BuildHelper::processContainerElement(
const TQDomElement &e,
const TQString &tag,
735 const TQString &name )
739 ContainerNode *containerNode = parentNode->findContainer( name, tag,
743 if ( !containerNode )
745 MergingIndexList::Iterator it( m_state.currentClientMergingIt );
748 int idx = calcMergingIndex( e, it, group );
754 TQWidget *container = createContainer( parentNode->container, idx, e,
id, &builder );
760 parentNode->adjustMergingIndices( 1, it );
762 assert( !parentNode->findContainerNode( container ) );
764 containerList.append( container );
766 TQString mergingName;
767 if ( it != parentNode->mergingIndices.end() )
768 mergingName = (*it).mergingName;
770 TQStringList cusTags = m_state.builderCustomTags;
771 TQStringList conTags = m_state.builderContainerTags;
772 if ( builder != m_state.builder )
774 cusTags = m_state.clientBuilderCustomTags;
775 conTags = m_state.clientBuilderContainerTags;
778 containerNode =
new ContainerNode( container, tag, name, parentNode,
779 m_state.guiClient, builder,
id,
780 mergingName, group, cusTags, conTags );
783 BuildHelper( m_state, containerNode ).build( e );
786 m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName );
787 parentNode->calcMergingIndex( TQString(), m_state.currentClientMergingIt,
788 m_state, ignoreDefaultMergingIndex );
791 TQWidget *BuildHelper::createContainer( TQWidget *parent,
int index,
792 const TQDomElement &element,
int &
id,
797 if ( m_state.clientBuilder )
799 res = m_state.clientBuilder->createContainer( parent, index, element,
id );
803 *builder = m_state.clientBuilder;
808 TDEInstance *oldInstance = m_state.builder->builderInstance();
811 m_state.builder->setBuilderClient( m_state.guiClient );
813 res = m_state.builder->createContainer( parent, index, element,
id );
815 m_state.builder->setBuilderInstance( oldInstance );
816 m_state.builder->setBuilderClient( oldClient );
819 *builder = m_state.builder;
824 void BuildState::reset()
826 clientName = TQString();
827 actionListName = TQString();
832 currentDefaultMergingIt = currentClientMergingIt = MergingIndexList::Iterator();
Abstract interface for a "GUI builder", used by the GUIFactory This interface is implemented by TDEMa...
A KXMLGUIClient can be used with KXMLGUIFactory to create a GUI from actions and an XML document,...
Class to encapsulate user-driven action or event.
static const TQString & staticQString(const char *str)
kndbgstream & endl(kndbgstream &s)
kdbgstream kdError(int area=0)
TQString name(StdAccel id)
const TDEShortcut & end()
TQString action(StdAccel id)