mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 18:32:49 +00:00
868 lines
28 KiB
C++
868 lines
28 KiB
C++
/* This file is part of the KDE libraries
|
|
Copyright (C) 2001 Simon Hausmann <hausmann@kde.org>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "kxmlguifactory_p.h"
|
|
#include "kxmlguiclient.h"
|
|
#include "kxmlguibuilder.h"
|
|
#include <kglobal.h>
|
|
#include <kdebug.h>
|
|
#include <kcomponentdata.h>
|
|
#include <ktoolbar.h>
|
|
|
|
#include <QWidget>
|
|
|
|
#include <assert.h>
|
|
|
|
using namespace KXMLGUI;
|
|
|
|
void ActionList::plug( QWidget *container, int index ) const
|
|
{
|
|
QAction* before = 0L; // Insert after end of widget's current actions (default).
|
|
|
|
if ((index < 0) || (index > container->actions().count()))
|
|
kWarning() << "Index " << index << " is not within range (0 - " << container->actions().count();
|
|
else if (index != container->actions().count())
|
|
before = container->actions().at(index); // Insert before indexed action.
|
|
|
|
foreach (QAction* action, *this) {
|
|
container->insertAction(before, action);
|
|
// before = action; // BUG FIX: do not insert actions in reverse order.
|
|
}
|
|
}
|
|
|
|
void ActionList::unplug( QWidget *container ) const
|
|
{
|
|
foreach (QAction* action, *this) {
|
|
if (container->actions().contains(action))
|
|
container->removeAction( action );
|
|
}
|
|
}
|
|
|
|
ContainerNode::ContainerNode( QWidget *_container, const QString &_tagName,
|
|
const QString &_name, ContainerNode *_parent,
|
|
KXMLGUIClient *_client, KXMLGUIBuilder *_builder,
|
|
QAction* _containerAction, const QString &_mergingName,
|
|
const QString &_groupName, const QStringList &customTags,
|
|
const QStringList &containerTags )
|
|
: parent( _parent ), client( _client ), builder( _builder ),
|
|
builderCustomTags( customTags ), builderContainerTags( containerTags ),
|
|
container( _container ), containerAction( _containerAction ), tagName( _tagName ), name( _name ),
|
|
groupName( _groupName ), index( 0 ), mergingName( _mergingName )
|
|
{
|
|
if ( parent )
|
|
parent->children.append( this );
|
|
}
|
|
|
|
ContainerNode::~ContainerNode()
|
|
{
|
|
qDeleteAll(children);
|
|
qDeleteAll(clients);
|
|
}
|
|
|
|
void ContainerNode::removeChild( ContainerNode* child )
|
|
{
|
|
MergingIndexList::Iterator mergingIt = findIndex( child->mergingName );
|
|
adjustMergingIndices( -1, mergingIt );
|
|
children.removeAll(child);
|
|
delete child;
|
|
}
|
|
|
|
void ContainerNode::removeChild( QMutableListIterator<ContainerNode*>& childIterator )
|
|
{
|
|
MergingIndexList::Iterator mergingIt = findIndex( childIterator.peekNext()->mergingName );
|
|
adjustMergingIndices( -1, mergingIt );
|
|
delete childIterator.next();
|
|
childIterator.remove();
|
|
}
|
|
|
|
/*
|
|
* Find a merging index with the given name. Used to find an index defined by <Merge name="blah"/>
|
|
* or by a <DefineGroup name="foo" /> tag.
|
|
*/
|
|
MergingIndexList::Iterator ContainerNode::findIndex( const QString &name )
|
|
{
|
|
MergingIndexList::Iterator it( mergingIndices.begin() );
|
|
MergingIndexList::Iterator end( mergingIndices.end() );
|
|
for (; it != end; ++it )
|
|
if ( (*it).mergingName == name )
|
|
return it;
|
|
return it;
|
|
}
|
|
|
|
/*
|
|
* Check if the given container widget is a child of this node and return the node structure
|
|
* if fonud.
|
|
*/
|
|
ContainerNode *ContainerNode::findContainerNode( QWidget *container )
|
|
{
|
|
foreach (ContainerNode* child, children )
|
|
if ( child->container == container )
|
|
return child;
|
|
|
|
return 0L;
|
|
}
|
|
|
|
/*
|
|
* Find a container recursively with the given name. Either compares _name with the
|
|
* container's tag name or the value of the container's name attribute. Specified by
|
|
* the tag bool .
|
|
*/
|
|
ContainerNode *ContainerNode::findContainer( const QString &_name, bool tag )
|
|
{
|
|
if ( ( tag && tagName == _name ) ||
|
|
( !tag && name == _name ) )
|
|
return this;
|
|
|
|
foreach (ContainerNode* child, children )
|
|
{
|
|
ContainerNode *res = child->findContainer( _name, tag );
|
|
if ( res )
|
|
return res;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Finds a child container node (not recursively) with the given name and tagname. Explicitly
|
|
* leaves out container widgets specified in the exludeList . Also ensures that the containers
|
|
* belongs to currClient.
|
|
*/
|
|
ContainerNode *ContainerNode::findContainer( const QString &name, const QString &tagName,
|
|
const QList<QWidget*> *excludeList,
|
|
KXMLGUIClient * /*currClient*/ )
|
|
{
|
|
ContainerNode *res = 0L;
|
|
ContainerNodeList::ConstIterator nIt = children.constBegin();
|
|
|
|
if ( !name.isEmpty() )
|
|
{
|
|
for (; nIt != children.constEnd(); ++nIt )
|
|
if ( (*nIt)->name == name &&
|
|
!excludeList->contains( (*nIt)->container ) )
|
|
{
|
|
res = *nIt;
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
if ( !tagName.isEmpty() )
|
|
for (; nIt != children.constEnd(); ++nIt )
|
|
{
|
|
if ( (*nIt)->tagName == tagName &&
|
|
!excludeList->contains( (*nIt)->container )
|
|
/*
|
|
* It is a bad idea to also compare the client, because
|
|
* we don't want to do so in situations like these:
|
|
*
|
|
* <MenuBar>
|
|
* <Menu>
|
|
* ...
|
|
*
|
|
* other client:
|
|
* <MenuBar>
|
|
* <Menu>
|
|
* ...
|
|
*
|
|
&& (*nIt)->client == currClient )
|
|
*/
|
|
)
|
|
{
|
|
res = *nIt;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
ContainerClient *ContainerNode::findChildContainerClient( KXMLGUIClient *currentGUIClient,
|
|
const QString &groupName,
|
|
const MergingIndexList::Iterator &mergingIdx )
|
|
{
|
|
if ( !clients.isEmpty() )
|
|
{
|
|
foreach (ContainerClient* client, clients)
|
|
if ( client->client == currentGUIClient )
|
|
{
|
|
if ( groupName.isEmpty() )
|
|
return client;
|
|
|
|
if ( groupName == client->groupName )
|
|
return client;
|
|
}
|
|
}
|
|
|
|
ContainerClient *client = new ContainerClient;
|
|
client->client = currentGUIClient;
|
|
client->groupName = groupName;
|
|
|
|
if ( mergingIdx != mergingIndices.end() )
|
|
client->mergingName = (*mergingIdx).mergingName;
|
|
|
|
clients.append( client );
|
|
|
|
return client;
|
|
}
|
|
|
|
void ContainerNode::plugActionList( BuildState &state )
|
|
{
|
|
MergingIndexList::Iterator mIt( mergingIndices.begin() );
|
|
MergingIndexList::Iterator mEnd( mergingIndices.end() );
|
|
for (; mIt != mEnd; ++mIt )
|
|
plugActionList( state, mIt );
|
|
|
|
foreach (ContainerNode* child, children)
|
|
child->plugActionList( state );
|
|
}
|
|
|
|
void ContainerNode::plugActionList( BuildState &state, const MergingIndexList::Iterator &mergingIdxIt )
|
|
{
|
|
static const QString tagActionList = QString::fromLatin1( "actionlist" );
|
|
|
|
MergingIndex mergingIdx = *mergingIdxIt;
|
|
|
|
QString k( mergingIdx.mergingName );
|
|
|
|
if ( k.indexOf( tagActionList ) == -1 )
|
|
return;
|
|
|
|
k = k.mid( tagActionList.length() );
|
|
|
|
if ( mergingIdx.clientName != state.clientName )
|
|
return;
|
|
|
|
if ( k != state.actionListName )
|
|
return;
|
|
|
|
ContainerClient *client = findChildContainerClient( state.guiClient,
|
|
QString(),
|
|
mergingIndices.end() );
|
|
|
|
client->actionLists.insert( k, state.actionList );
|
|
|
|
state.actionList.plug( container, mergingIdx.value );
|
|
|
|
adjustMergingIndices( state.actionList.count(), mergingIdxIt );
|
|
}
|
|
|
|
void ContainerNode::unplugActionList( BuildState &state )
|
|
{
|
|
MergingIndexList::Iterator mIt( mergingIndices.begin() );
|
|
MergingIndexList::Iterator mEnd( mergingIndices.end() );
|
|
for (; mIt != mEnd; ++mIt )
|
|
unplugActionList( state, mIt );
|
|
|
|
foreach (ContainerNode* child, children)
|
|
child->unplugActionList( state );
|
|
}
|
|
|
|
void ContainerNode::unplugActionList( BuildState &state, const MergingIndexList::Iterator &mergingIdxIt )
|
|
{
|
|
static const QString tagActionList = QString::fromLatin1( "actionlist" );
|
|
|
|
MergingIndex mergingIdx = *mergingIdxIt;
|
|
|
|
QString k = mergingIdx.mergingName;
|
|
|
|
if ( k.indexOf( tagActionList ) == -1 )
|
|
return;
|
|
|
|
k = k.mid( tagActionList.length() );
|
|
|
|
if ( mergingIdx.clientName != state.clientName )
|
|
return;
|
|
|
|
if ( k != state.actionListName )
|
|
return;
|
|
|
|
ContainerClient *client = findChildContainerClient( state.guiClient,
|
|
QString(),
|
|
mergingIndices.end() );
|
|
|
|
ActionListMap::Iterator lIt( client->actionLists.find( k ) );
|
|
if ( lIt == client->actionLists.end() )
|
|
return;
|
|
|
|
lIt.value().unplug( container );
|
|
|
|
adjustMergingIndices( -int(lIt.value().count()), mergingIdxIt );
|
|
|
|
client->actionLists.erase( lIt );
|
|
}
|
|
|
|
void ContainerNode::adjustMergingIndices( int offset,
|
|
const MergingIndexList::Iterator &it )
|
|
{
|
|
MergingIndexList::Iterator mergingIt = it;
|
|
MergingIndexList::Iterator mergingEnd = mergingIndices.end();
|
|
|
|
for (; mergingIt != mergingEnd; ++mergingIt )
|
|
(*mergingIt).value += offset;
|
|
|
|
index += offset;
|
|
}
|
|
|
|
bool ContainerNode::destruct( QDomElement element, BuildState &state ) //krazy:exclude=passbyvalue (this is correct QDom usage, and a ref wouldn't allow passing doc.documentElement() as argument)
|
|
{
|
|
destructChildren( element, state );
|
|
|
|
unplugActions( state );
|
|
|
|
// remove all merging indices the client defined
|
|
QMutableListIterator<MergingIndex> cmIt = mergingIndices;
|
|
while ( cmIt.hasNext() )
|
|
if ( cmIt.next().clientName == state.clientName )
|
|
cmIt.remove();
|
|
|
|
// ### check for merging index count, too?
|
|
if ( clients.count() == 0 && children.count() == 0 && container &&
|
|
client == state.guiClient )
|
|
{
|
|
QWidget *parentContainer = 0L;
|
|
|
|
if ( parent && parent->container )
|
|
parentContainer = parent->container;
|
|
|
|
assert( builder );
|
|
|
|
builder->removeContainer( container, parentContainer, element, containerAction );
|
|
|
|
client = 0L;
|
|
|
|
return true;
|
|
}
|
|
|
|
if ( client == state.guiClient )
|
|
client = 0L;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
void ContainerNode::destructChildren( const QDomElement &element, BuildState &state )
|
|
{
|
|
QMutableListIterator<ContainerNode*> childIt = children;
|
|
while ( childIt.hasNext() )
|
|
{
|
|
ContainerNode *childNode = childIt.peekNext();
|
|
|
|
QDomElement childElement = findElementForChild( element, childNode );
|
|
|
|
// destruct returns true in case the container really got deleted
|
|
if ( childNode->destruct( childElement, state ) )
|
|
removeChild( childIt );
|
|
else
|
|
childIt.next();
|
|
}
|
|
}
|
|
|
|
QDomElement ContainerNode::findElementForChild( const QDomElement &baseElement,
|
|
ContainerNode *childNode )
|
|
{
|
|
static const QString attrName = QString::fromLatin1( "name" );
|
|
|
|
// ### slow
|
|
for ( QDomNode n = baseElement.firstChild(); !n.isNull();
|
|
n = n.nextSibling() )
|
|
{
|
|
QDomElement e = n.toElement();
|
|
if ( e.tagName().toLower() == childNode->tagName &&
|
|
e.attribute( attrName ) == childNode->name )
|
|
return e;
|
|
}
|
|
|
|
return QDomElement();
|
|
}
|
|
|
|
void ContainerNode::unplugActions( BuildState &state )
|
|
{
|
|
if ( !container )
|
|
return;
|
|
|
|
QMutableListIterator<ContainerClient*> clientIt( clients );
|
|
|
|
/*
|
|
Disabled because it means in KToolBar::saveState isHidden is always true then,
|
|
which is clearly wrong.
|
|
|
|
if ( clients.count() == 1 && clientIt.current()->client == client &&
|
|
client == state.guiClient )
|
|
container->hide(); // this container is going to die, that's for sure.
|
|
// in this case let's just hide it, which makes the
|
|
// destruction faster
|
|
*/
|
|
|
|
while ( clientIt.hasNext() )
|
|
//only unplug the actions of the client we want to remove, as the container might be owned
|
|
//by a different client
|
|
if ( clientIt.peekNext()->client == state.guiClient )
|
|
{
|
|
unplugClient( clientIt.peekNext() );
|
|
delete clientIt.next();
|
|
clientIt.remove();
|
|
}
|
|
else
|
|
clientIt.next();
|
|
}
|
|
|
|
void ContainerNode::unplugClient( ContainerClient *client )
|
|
{
|
|
static const QString tagActionList = QString::fromLatin1( "actionlist" );
|
|
|
|
assert( builder );
|
|
|
|
// now quickly remove all custom elements (i.e. separators) and unplug all actions
|
|
|
|
QList<QAction*>::ConstIterator custIt = client->customElements.constBegin();
|
|
QList<QAction*>::ConstIterator custEnd = client->customElements.constEnd();
|
|
for (; custIt != custEnd; ++custIt )
|
|
builder->removeCustomElement( container, *custIt );
|
|
|
|
KToolBar *bar = qobject_cast<KToolBar*>(container);
|
|
if (bar) {
|
|
bar->removeXMLGUIClient(client->client);
|
|
}
|
|
|
|
client->actions.unplug( container );
|
|
|
|
// now adjust all merging indices
|
|
|
|
MergingIndexList::Iterator mergingIt = findIndex( client->mergingName );
|
|
|
|
adjustMergingIndices( - int( client->actions.count()
|
|
+ client->customElements.count() ),
|
|
mergingIt );
|
|
|
|
// unplug all actionslists
|
|
|
|
ActionListMap::ConstIterator alIt = client->actionLists.constBegin();
|
|
ActionListMap::ConstIterator alEnd = client->actionLists.constEnd();
|
|
for (; alIt != alEnd; ++alIt )
|
|
{
|
|
alIt.value().unplug( container );
|
|
|
|
// construct the merging index key (i.e. like named merging) , find the
|
|
// corresponding merging index and adjust all indices
|
|
QString mergingKey = alIt.key();
|
|
mergingKey.prepend( tagActionList );
|
|
|
|
MergingIndexList::Iterator mIt = findIndex( mergingKey );
|
|
if ( mIt == mergingIndices.end() )
|
|
continue;
|
|
|
|
adjustMergingIndices( -int(alIt.value().count()), mIt );
|
|
|
|
// remove the actionlists' merging index
|
|
// ### still needed? we clean up below anyway?
|
|
mergingIndices.erase( mIt );
|
|
}
|
|
}
|
|
|
|
void ContainerNode::reset()
|
|
{
|
|
foreach (ContainerNode* child, children)
|
|
child->reset();
|
|
|
|
if ( client )
|
|
client->setFactory( 0L );
|
|
}
|
|
|
|
int ContainerNode::calcMergingIndex( const QString &mergingName,
|
|
MergingIndexList::Iterator &it,
|
|
BuildState &state,
|
|
bool ignoreDefaultMergingIndex )
|
|
{
|
|
MergingIndexList::Iterator mergingIt;
|
|
|
|
if ( mergingName.isEmpty() )
|
|
mergingIt = findIndex( state.clientName );
|
|
else
|
|
mergingIt = findIndex( mergingName );
|
|
|
|
MergingIndexList::Iterator mergingEnd = mergingIndices.end();
|
|
it = mergingEnd;
|
|
|
|
if ( ( mergingIt == mergingEnd && state.currentDefaultMergingIt == mergingEnd ) ||
|
|
ignoreDefaultMergingIndex )
|
|
return index;
|
|
|
|
if ( mergingIt != mergingEnd )
|
|
it = mergingIt;
|
|
else
|
|
it = state.currentDefaultMergingIt;
|
|
|
|
return (*it).value;
|
|
}
|
|
|
|
int BuildHelper::calcMergingIndex( const QDomElement &element, MergingIndexList::Iterator &it, QString &group )
|
|
{
|
|
static const QString attrGroup = QString::fromLatin1( "group" );
|
|
|
|
bool haveGroup = false;
|
|
group = element.attribute( attrGroup );
|
|
if ( !group.isEmpty() ) {
|
|
group.prepend( attrGroup );
|
|
haveGroup = true;
|
|
}
|
|
|
|
int idx;
|
|
if ( haveGroup )
|
|
idx = parentNode->calcMergingIndex( group, it, m_state, ignoreDefaultMergingIndex );
|
|
else if ( m_state.currentClientMergingIt == parentNode->mergingIndices.end() )
|
|
idx = parentNode->index;
|
|
else
|
|
idx = (*m_state.currentClientMergingIt).value;
|
|
|
|
return idx;
|
|
}
|
|
|
|
BuildHelper::BuildHelper( BuildState &state, ContainerNode *node )
|
|
: containerClient( 0 ), ignoreDefaultMergingIndex( false ), m_state( state ),
|
|
parentNode( node )
|
|
{
|
|
static const QString defaultMergingName = QString::fromLatin1( "<default>" );
|
|
|
|
// create a list of supported container and custom tags
|
|
customTags = m_state.builderCustomTags;
|
|
containerTags = m_state.builderContainerTags;
|
|
|
|
if ( parentNode->builder != m_state.builder )
|
|
{
|
|
customTags += parentNode->builderCustomTags;
|
|
containerTags += parentNode->builderContainerTags;
|
|
}
|
|
|
|
if ( m_state.clientBuilder ) {
|
|
customTags = m_state.clientBuilderCustomTags + customTags;
|
|
containerTags = m_state.clientBuilderContainerTags + containerTags;
|
|
}
|
|
|
|
m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName );
|
|
parentNode->calcMergingIndex( QString(), m_state.currentClientMergingIt,
|
|
m_state, /*ignoreDefaultMergingIndex*/ false );
|
|
}
|
|
|
|
void BuildHelper::build( const QDomElement &element )
|
|
{
|
|
for (QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
|
|
{
|
|
QDomElement e = n.toElement();
|
|
if (e.isNull()) continue;
|
|
processElement( e );
|
|
}
|
|
}
|
|
|
|
void BuildHelper::processElement( const QDomElement &e )
|
|
{
|
|
// some often used QStrings
|
|
static const QString tagAction = QString::fromLatin1( "action" );
|
|
static const QString tagMerge = QString::fromLatin1( "merge" );
|
|
static const QString tagState = QString::fromLatin1( "state" );
|
|
static const QString tagDefineGroup = QString::fromLatin1( "definegroup" );
|
|
static const QString tagActionList = QString::fromLatin1( "actionlist" );
|
|
static const QString attrName = QString::fromLatin1( "name" );
|
|
|
|
QString tag( e.tagName().toLower() );
|
|
QString currName( e.attribute( attrName ) );
|
|
|
|
bool isActionTag = ( tag == tagAction );
|
|
|
|
if ( isActionTag || customTags.indexOf( tag ) != -1 )
|
|
processActionOrCustomElement( e, isActionTag );
|
|
else if ( containerTags.indexOf( tag ) != -1 )
|
|
processContainerElement( e, tag, currName );
|
|
else if ( tag == tagMerge || tag == tagDefineGroup || tag == tagActionList )
|
|
processMergeElement( tag, currName, e );
|
|
else if ( tag == tagState )
|
|
processStateElement( e );
|
|
}
|
|
|
|
void BuildHelper::processActionOrCustomElement( const QDomElement &e, bool isActionTag )
|
|
{
|
|
if ( !parentNode->container )
|
|
return;
|
|
|
|
MergingIndexList::Iterator it( m_state.currentClientMergingIt );
|
|
|
|
QString group;
|
|
int idx = calcMergingIndex( e, it, group );
|
|
|
|
containerClient = parentNode->findChildContainerClient( m_state.guiClient, group, it );
|
|
|
|
bool guiElementCreated = false;
|
|
if ( isActionTag )
|
|
guiElementCreated = processActionElement( e, idx );
|
|
else
|
|
guiElementCreated = processCustomElement( e, idx );
|
|
|
|
if ( guiElementCreated )
|
|
// adjust any following merging indices and the current running index for the container
|
|
parentNode->adjustMergingIndices( 1, it );
|
|
}
|
|
|
|
bool BuildHelper::processActionElement( const QDomElement &e, int idx )
|
|
{
|
|
assert( m_state.guiClient );
|
|
|
|
// look up the action and plug it in
|
|
QAction *action = m_state.guiClient->action( e );
|
|
|
|
//kDebug(260) << "BuildHelper::processActionElement " << e.attribute( "name" ) << " -> " << action << " (in " << m_state.guiClient->actionCollection() << ")";
|
|
if ( !action )
|
|
return false;
|
|
|
|
QAction* before = 0L;
|
|
if (idx >= 0 && idx < parentNode->container->actions().count())
|
|
before = parentNode->container->actions()[idx];
|
|
|
|
parentNode->container->insertAction(before, action);
|
|
|
|
// save a reference to the plugged action, in order to properly unplug it afterwards.
|
|
containerClient->actions.append( action );
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BuildHelper::processCustomElement( const QDomElement &e, int idx )
|
|
{
|
|
assert( parentNode->builder );
|
|
|
|
QAction* action = parentNode->builder->createCustomElement( parentNode->container, idx, e );
|
|
if ( !action )
|
|
return false;
|
|
|
|
containerClient->customElements.append( action );
|
|
return true;
|
|
}
|
|
|
|
void BuildHelper::processStateElement( const QDomElement &element )
|
|
{
|
|
QString stateName = element.attribute( "name" );
|
|
|
|
if ( stateName.isNull() || !stateName.length() ) return;
|
|
|
|
for (QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
|
|
{
|
|
QDomElement e = n.toElement();
|
|
if (e.isNull()) continue;
|
|
|
|
QString tagName = e.tagName().toLower();
|
|
|
|
if ( tagName != "enable" && tagName != "disable" )
|
|
continue;
|
|
|
|
bool processingActionsToEnable = (tagName == "enable");
|
|
|
|
// process action names
|
|
for (QDomNode n2 = n.firstChild(); !n2.isNull(); n2 = n2.nextSibling() )
|
|
{
|
|
QDomElement actionEl = n2.toElement();
|
|
if ( actionEl.tagName().toLower() != "action" ) continue;
|
|
|
|
QString actionName = actionEl.attribute( "name" );
|
|
if ( actionName.isEmpty() ) return;
|
|
|
|
if ( processingActionsToEnable )
|
|
m_state.guiClient->addStateActionEnabled( stateName, actionName );
|
|
else
|
|
m_state.guiClient->addStateActionDisabled( stateName, actionName );
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void BuildHelper::processMergeElement( const QString &tag, const QString &name, const QDomElement &e )
|
|
{
|
|
static const QString tagDefineGroup = QString::fromLatin1( "definegroup" );
|
|
static const QString tagActionList = QString::fromLatin1( "actionlist" );
|
|
static const QString defaultMergingName = QString::fromLatin1( "<default>" );
|
|
static const QString attrGroup = QString::fromLatin1( "group" );
|
|
|
|
QString mergingName( name );
|
|
if ( mergingName.isEmpty() )
|
|
{
|
|
if ( tag == tagDefineGroup )
|
|
{
|
|
kError() << "cannot define group without name!";
|
|
return;
|
|
}
|
|
if ( tag == tagActionList )
|
|
{
|
|
kError() << "cannot define actionlist without name!";
|
|
return;
|
|
}
|
|
mergingName = defaultMergingName;
|
|
}
|
|
|
|
if ( tag == tagDefineGroup )
|
|
mergingName.prepend( attrGroup ); //avoid possible name clashes by prepending
|
|
// "group" to group definitions
|
|
else if ( tag == tagActionList )
|
|
mergingName.prepend( tagActionList );
|
|
|
|
if ( parentNode->findIndex( mergingName ) != parentNode->mergingIndices.end() )
|
|
return; //do not allow the redefinition of merging indices!
|
|
|
|
MergingIndexList::Iterator mIt( parentNode->mergingIndices.end() );
|
|
|
|
QString group( e.attribute( attrGroup ) );
|
|
if ( !group.isEmpty() )
|
|
group.prepend( attrGroup );
|
|
|
|
// calculate the index of the new merging index. Usually this does not need any calculation,
|
|
// we just want the last available index (i.e. append) . But in case the <Merge> tag appears
|
|
// "inside" another <Merge> tag from a previously build client, then we have to use the
|
|
// "parent's" index. That's why we call calcMergingIndex here.
|
|
MergingIndex newIdx;
|
|
newIdx.value = parentNode->calcMergingIndex( group, mIt, m_state, ignoreDefaultMergingIndex );
|
|
newIdx.mergingName = mergingName;
|
|
newIdx.clientName = m_state.clientName;
|
|
|
|
// if that merging index is "inside" another one, then append it right after the "parent" .
|
|
if ( mIt != parentNode->mergingIndices.end() )
|
|
parentNode->mergingIndices.insert( ++mIt, newIdx );
|
|
else
|
|
parentNode->mergingIndices.append( newIdx );
|
|
|
|
if ( mergingName == defaultMergingName )
|
|
|
|
ignoreDefaultMergingIndex = true;
|
|
|
|
// re-calculate the running default and client merging indices.
|
|
m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName );
|
|
parentNode->calcMergingIndex( QString(), m_state.currentClientMergingIt,
|
|
m_state, ignoreDefaultMergingIndex );
|
|
}
|
|
|
|
void BuildHelper::processContainerElement( const QDomElement &e, const QString &tag,
|
|
const QString &name )
|
|
{
|
|
static const QString defaultMergingName = QString::fromLatin1( "<default>" );
|
|
|
|
ContainerNode *containerNode = parentNode->findContainer( name, tag,
|
|
&containerList,
|
|
m_state.guiClient );
|
|
|
|
if ( !containerNode )
|
|
{
|
|
MergingIndexList::Iterator it( m_state.currentClientMergingIt );
|
|
QString group;
|
|
|
|
int idx = calcMergingIndex( e, it, group );
|
|
|
|
QAction* containerAction;
|
|
|
|
KXMLGUIBuilder *builder;
|
|
|
|
QWidget *container = createContainer( parentNode->container, idx, e, containerAction, &builder );
|
|
|
|
// no container? (probably some <text> tag or so ;-)
|
|
if ( !container )
|
|
return;
|
|
|
|
parentNode->adjustMergingIndices( 1, it );
|
|
|
|
assert( !parentNode->findContainerNode( container ) );
|
|
|
|
containerList.append( container );
|
|
|
|
QString mergingName;
|
|
if ( it != parentNode->mergingIndices.end() )
|
|
mergingName = (*it).mergingName;
|
|
|
|
QStringList cusTags = m_state.builderCustomTags;
|
|
QStringList conTags = m_state.builderContainerTags;
|
|
if ( builder != m_state.builder )
|
|
{
|
|
cusTags = m_state.clientBuilderCustomTags;
|
|
conTags = m_state.clientBuilderContainerTags;
|
|
}
|
|
|
|
containerNode = new ContainerNode( container, tag, name, parentNode,
|
|
m_state.guiClient, builder, containerAction,
|
|
mergingName, group, cusTags, conTags );
|
|
} else {
|
|
if ( tag == QLatin1String( "toolbar" ) ) {
|
|
KToolBar *bar = qobject_cast<KToolBar*>(containerNode->container);
|
|
if (bar) {
|
|
if ( m_state.guiClient && !m_state.guiClient->xmlFile().isEmpty() )
|
|
bar->addXMLGUIClient(m_state.guiClient);
|
|
} else {
|
|
kWarning() << "toolbar container is not a KToolBar";
|
|
}
|
|
}
|
|
}
|
|
|
|
BuildHelper( m_state, containerNode ).build( e );
|
|
|
|
// and re-calculate running values, for better performance
|
|
m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName );
|
|
parentNode->calcMergingIndex( QString(), m_state.currentClientMergingIt,
|
|
m_state, ignoreDefaultMergingIndex );
|
|
}
|
|
|
|
QWidget *BuildHelper::createContainer( QWidget *parent, int index,
|
|
const QDomElement &element, QAction*& containerAction,
|
|
KXMLGUIBuilder **builder )
|
|
{
|
|
QWidget *res = 0L;
|
|
|
|
if ( m_state.clientBuilder )
|
|
{
|
|
res = m_state.clientBuilder->createContainer( parent, index, element, containerAction );
|
|
|
|
if ( res )
|
|
{
|
|
*builder = m_state.clientBuilder;
|
|
return res;
|
|
}
|
|
}
|
|
|
|
KComponentData oldInstance = m_state.builder->builderComponentData();
|
|
KXMLGUIClient *oldClient = m_state.builder->builderClient();
|
|
|
|
m_state.builder->setBuilderClient( m_state.guiClient );
|
|
|
|
res = m_state.builder->createContainer( parent, index, element, containerAction );
|
|
|
|
m_state.builder->setBuilderComponentData(oldInstance);
|
|
m_state.builder->setBuilderClient( oldClient );
|
|
|
|
if ( res )
|
|
*builder = m_state.builder;
|
|
|
|
return res;
|
|
}
|
|
|
|
void BuildState::reset()
|
|
{
|
|
clientName.clear();
|
|
actionListName.clear();
|
|
actionList.clear();
|
|
guiClient = 0;
|
|
clientBuilder = 0;
|
|
|
|
currentDefaultMergingIt = currentClientMergingIt = MergingIndexList::Iterator();
|
|
}
|
|
|
|
/* vim: et sw=4
|
|
*/
|