mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 18:32:49 +00:00
746 lines
24 KiB
C++
746 lines
24 KiB
C++
/* This file is part of the KDE libraries
|
|
Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
|
|
Copyright (C) 2000 Kurt Granroth <granroth@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 version 2 as published by the Free Software Foundation.
|
|
|
|
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 "kxmlguiclient.h"
|
|
#include "kxmlguiversionhandler_p.h"
|
|
#include "kxmlguifactory.h"
|
|
#include "kxmlguibuilder.h"
|
|
#include "kcomponentdata.h"
|
|
#include "kstandarddirs.h"
|
|
#include "kdebug.h"
|
|
#include "kaction.h"
|
|
#include "kactioncollection.h"
|
|
|
|
#include <QtCore/QDir>
|
|
#include <QtCore/QFile>
|
|
#include <QtXml/qdom.h>
|
|
#include <QtCore/QTextStream>
|
|
#include <QtCore/QRegExp>
|
|
#include <QtCore/QPointer>
|
|
|
|
#include <assert.h>
|
|
|
|
class KXMLGUIClientPrivate
|
|
{
|
|
public:
|
|
KXMLGUIClientPrivate()
|
|
: m_componentData(KGlobal::mainComponent()),
|
|
m_actionCollection(0),
|
|
m_parent(0L),
|
|
m_builder(0L)
|
|
{
|
|
}
|
|
~KXMLGUIClientPrivate()
|
|
{
|
|
if (m_actionCollection) {
|
|
m_actionCollection->deleteLater();
|
|
}
|
|
if (m_builder) {
|
|
delete m_builder;
|
|
}
|
|
}
|
|
|
|
bool mergeXML( QDomElement &base, QDomElement &additive,
|
|
KActionCollection *actionCollection );
|
|
bool isEmptyContainer(const QDomElement& base,
|
|
KActionCollection *actionCollection) const;
|
|
|
|
QDomElement findMatchingElement( const QDomElement &base,
|
|
const QDomElement &additive );
|
|
|
|
KComponentData m_componentData;
|
|
|
|
QDomDocument m_doc;
|
|
KActionCollection *m_actionCollection;
|
|
QDomDocument m_buildDocument;
|
|
QPointer<KXMLGUIFactory> m_factory;
|
|
KXMLGUIClient *m_parent;
|
|
//QPtrList<KXMLGUIClient> m_supers;
|
|
QList<KXMLGUIClient*> m_children;
|
|
KXMLGUIBuilder *m_builder;
|
|
QString m_xmlFile;
|
|
QString m_localXMLFile;
|
|
|
|
// Actions to enable/disable on a state change
|
|
QMap<QString,KXMLGUIClient::StateChange> m_actionsStateMap;
|
|
};
|
|
|
|
|
|
KXMLGUIClient::KXMLGUIClient()
|
|
: d( new KXMLGUIClientPrivate )
|
|
{
|
|
}
|
|
|
|
KXMLGUIClient::KXMLGUIClient( KXMLGUIClient *parent )
|
|
: d( new KXMLGUIClientPrivate )
|
|
{
|
|
parent->insertChildClient( this );
|
|
}
|
|
|
|
KXMLGUIClient::~KXMLGUIClient()
|
|
{
|
|
if ( d->m_parent ) {
|
|
d->m_parent->removeChildClient( this );
|
|
}
|
|
|
|
if ( d->m_factory ) {
|
|
kWarning() << this << "deleted without having been removed from the factory first. This will leak standalone popupmenus and could lead to crashes.";
|
|
d->m_factory->forgetClient(this);
|
|
}
|
|
|
|
foreach (KXMLGUIClient* client, d->m_children) {
|
|
if (d->m_factory)
|
|
d->m_factory->forgetClient(client);
|
|
assert( client->d->m_parent == this );
|
|
client->d->m_parent = 0;
|
|
}
|
|
|
|
delete d;
|
|
}
|
|
|
|
QAction *KXMLGUIClient::action( const char *name ) const
|
|
{
|
|
QAction* act = actionCollection()->action( name );
|
|
if ( !act ) {
|
|
foreach (KXMLGUIClient* client, d->m_children) {
|
|
act = client->actionCollection()->action( name );
|
|
if ( act )
|
|
break;
|
|
}
|
|
}
|
|
return act;
|
|
}
|
|
|
|
KActionCollection *KXMLGUIClient::actionCollection() const
|
|
{
|
|
if ( !d->m_actionCollection )
|
|
{
|
|
d->m_actionCollection = new KActionCollection( this );
|
|
d->m_actionCollection->setObjectName( "KXMLGUIClient-KActionCollection" );
|
|
}
|
|
return d->m_actionCollection;
|
|
}
|
|
|
|
QAction *KXMLGUIClient::action( const QDomElement &element ) const
|
|
{
|
|
static const QString attrName = QString::fromLatin1( "name" );
|
|
return actionCollection()->action( qPrintable(element.attribute( attrName )) );
|
|
}
|
|
|
|
KComponentData KXMLGUIClient::componentData() const
|
|
{
|
|
return d->m_componentData;
|
|
}
|
|
|
|
QDomDocument KXMLGUIClient::domDocument() const
|
|
{
|
|
return d->m_doc;
|
|
}
|
|
|
|
QString KXMLGUIClient::xmlFile() const
|
|
{
|
|
return d->m_xmlFile;
|
|
}
|
|
|
|
QString KXMLGUIClient::localXMLFile() const
|
|
{
|
|
if ( !d->m_localXMLFile.isEmpty() )
|
|
return d->m_localXMLFile;
|
|
|
|
if ( !QDir::isRelativePath(d->m_xmlFile) )
|
|
return QString(); // can't save anything here
|
|
|
|
if (d->m_xmlFile.isEmpty()) // setXMLFile not called at all, can't save. Use case: ToolBarHandler
|
|
return QString();
|
|
|
|
return KStandardDirs::locateLocal( "data", componentData().componentName() + '/' + d->m_xmlFile );
|
|
}
|
|
|
|
|
|
void KXMLGUIClient::reloadXML()
|
|
{
|
|
// TODO: this method can't be used for the KXmlGuiWindow, since it doesn't merge in ui_standards.rc!
|
|
// -> KDE5: load ui_standards_rc in setXMLFile using a flag, and remember that flag?
|
|
// and then KEditToolBar can use reloadXML.
|
|
QString file( xmlFile() );
|
|
if ( !file.isEmpty() )
|
|
setXMLFile( file );
|
|
}
|
|
|
|
void KXMLGUIClient::setComponentData(const KComponentData &componentData)
|
|
{
|
|
d->m_componentData = componentData;
|
|
actionCollection()->setComponentData( componentData );
|
|
if ( d->m_builder )
|
|
d->m_builder->setBuilderClient( this );
|
|
}
|
|
|
|
void KXMLGUIClient::loadStandardsXmlFile()
|
|
{
|
|
const QString file = KStandardDirs::locate("config", "ui/ui_standards.rc", componentData());
|
|
if (file.isEmpty()) {
|
|
kWarning() << "ui/ui_standards.rc not found in" << componentData().dirs()->resourceDirs("config");
|
|
} else {
|
|
const QString doc = KXMLGUIFactory::readConfigFile( file );
|
|
setXML( doc );
|
|
}
|
|
}
|
|
|
|
void KXMLGUIClient::setXMLFile( const QString& _file, bool merge, bool setXMLDoc )
|
|
{
|
|
// store our xml file name
|
|
if ( !_file.isNull() )
|
|
d->m_xmlFile = _file;
|
|
|
|
if ( !setXMLDoc )
|
|
return;
|
|
|
|
QString file = _file;
|
|
QStringList allFiles;
|
|
if ( !QDir::isRelativePath( file ) ) {
|
|
allFiles.append( file );
|
|
} else {
|
|
const QString filter = componentData().componentName() + '/' + _file;
|
|
allFiles = componentData().dirs()->findAllResources("data", filter) +
|
|
componentData().dirs()->findAllResources("data", _file);
|
|
}
|
|
if ( allFiles.isEmpty() && !_file.isEmpty() ) {
|
|
// if a non-empty file gets passed and we can't find it,
|
|
// inform the developer using some debug output
|
|
kWarning() << "cannot find .rc file" << _file << "for component" << componentData().componentName();
|
|
}
|
|
|
|
// make sure to merge the settings from any file specified by setLocalXMLFile()
|
|
if ( !d->m_localXMLFile.isEmpty() && !file.endsWith("ui_standards.rc") ) {
|
|
const bool exists = QDir::isRelativePath(d->m_localXMLFile) || QFile::exists(d->m_localXMLFile);
|
|
if (exists && !allFiles.contains(d->m_localXMLFile))
|
|
allFiles.prepend( d->m_localXMLFile );
|
|
}
|
|
|
|
QString doc;
|
|
if ( !allFiles.isEmpty() )
|
|
file = findMostRecentXMLFile(allFiles, doc);
|
|
|
|
// Always call setXML, even on error, so that we don't keep all ui_standards.rc menus.
|
|
setXML( doc, merge );
|
|
}
|
|
|
|
void KXMLGUIClient::setLocalXMLFile( const QString &file )
|
|
{
|
|
d->m_localXMLFile = file;
|
|
}
|
|
|
|
void KXMLGUIClient::replaceXMLFile( const QString& xmlfile, const QString& localxmlfile, bool merge )
|
|
{
|
|
if ( !QDir::isAbsolutePath ( xmlfile ) ) {
|
|
kWarning() << "xml file" << xmlfile << "is not an absolute path";
|
|
}
|
|
|
|
setLocalXMLFile ( localxmlfile );
|
|
setXMLFile ( xmlfile, merge );
|
|
}
|
|
|
|
void KXMLGUIClient::setXML( const QString &document, bool merge )
|
|
{
|
|
QDomDocument doc;
|
|
QString errorMsg;
|
|
int errorLine, errorColumn;
|
|
// QDomDocument raises a parse error on empty document, but we accept no app-specific document,
|
|
// in which case you only get ui_standards.rc layout.
|
|
bool result = document.isEmpty() || doc.setContent(document, &errorMsg, &errorLine, &errorColumn);
|
|
if ( result ) {
|
|
setDOMDocument( doc, merge );
|
|
} else {
|
|
#ifdef NDEBUG
|
|
kError() << "Error parsing XML document:" << errorMsg << "at line" << errorLine << "column" << errorColumn;
|
|
setDOMDocument(QDomDocument(), merge); // otherwise empty menus from ui_standards.rc stay around
|
|
#else
|
|
kFatal() << "Error parsing XML document:" << errorMsg << "at line" << errorLine << "column" << errorColumn;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void KXMLGUIClient::setDOMDocument( const QDomDocument &document, bool merge )
|
|
{
|
|
if ( merge && !d->m_doc.isNull() )
|
|
{
|
|
QDomElement base = d->m_doc.documentElement();
|
|
|
|
QDomElement e = document.documentElement();
|
|
|
|
// merge our original (global) xml with our new one
|
|
d->mergeXML(base, e, actionCollection());
|
|
|
|
// reassign our pointer as mergeXML might have done something
|
|
// strange to it
|
|
base = d->m_doc.documentElement();
|
|
|
|
//kDebug(260) << "Result of xmlgui merging:" << d->m_doc.toString();
|
|
|
|
// we want some sort of failsafe.. just in case
|
|
if ( base.isNull() )
|
|
d->m_doc = document;
|
|
}
|
|
else
|
|
{
|
|
d->m_doc = document;
|
|
}
|
|
|
|
setXMLGUIBuildDocument( QDomDocument() );
|
|
}
|
|
|
|
// if (equals(a,b)) is more readable than if (a.compare(b, Qt::CaseInsensitive)==0)
|
|
static bool equalstr(const QString& a, const QString& b) {
|
|
return a.compare(b, Qt::CaseInsensitive) == 0;
|
|
}
|
|
|
|
bool KXMLGUIClientPrivate::mergeXML( QDomElement &base, QDomElement &additive, KActionCollection *actionCollection )
|
|
{
|
|
static const QString tagAction = QString::fromLatin1( "Action" );
|
|
static const QString tagMerge = QString::fromLatin1( "Merge" );
|
|
static const QString tagSeparator = QString::fromLatin1( "Separator" );
|
|
static const QString attrName = QString::fromLatin1( "name" );
|
|
static const QString attrAppend = QString::fromLatin1( "append" );
|
|
static const QString attrWeakSeparator = QString::fromLatin1( "weakSeparator" );
|
|
static const QString tagMergeLocal = QString::fromLatin1( "MergeLocal" );
|
|
static const QString tagText = QString::fromLatin1( "text" );
|
|
static const QString attrAlreadyVisited = QString::fromLatin1( "alreadyVisited" );
|
|
static const QString attrNoMerge = QString::fromLatin1( "noMerge" );
|
|
static const QString attrOne = QString::fromLatin1( "1" );
|
|
|
|
// there is a possibility that we don't want to merge in the
|
|
// additive.. rather, we might want to *replace* the base with the
|
|
// additive. this can be for any container.. either at a file wide
|
|
// level or a simple container level. we look for the 'noMerge'
|
|
// tag, in any event and just replace the old with the new
|
|
if ( additive.attribute(attrNoMerge) == attrOne ) // ### use toInt() instead? (Simon)
|
|
{
|
|
base.parentNode().replaceChild(additive, base);
|
|
return true;
|
|
} else {
|
|
// Merge attributes
|
|
{
|
|
const QDomNamedNodeMap attribs = additive.attributes();
|
|
const uint attribcount = attribs.count();
|
|
|
|
for(uint i = 0; i < attribcount; ++i) {
|
|
const QDomNode node = attribs.item(i);
|
|
base.setAttribute(node.nodeName(), node.nodeValue());
|
|
}
|
|
}
|
|
|
|
// iterate over all elements in the container (of the global DOM tree)
|
|
QDomNode n = base.firstChild();
|
|
while ( !n.isNull() )
|
|
{
|
|
QDomElement e = n.toElement();
|
|
n = n.nextSibling(); // Advance now so that we can safely delete e
|
|
if (e.isNull())
|
|
continue;
|
|
|
|
const QString tag = e.tagName();
|
|
|
|
// if there's an action tag in the global tree and the action is
|
|
// not implemented, then we remove the element
|
|
if (equalstr(tag, tagAction)) {
|
|
const QString name = e.attribute(attrName);
|
|
if (!actionCollection->action(name))
|
|
{
|
|
// remove this child as we aren't using it
|
|
base.removeChild( e );
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// if there's a separator defined in the global tree, then add an
|
|
// attribute, specifying that this is a "weak" separator
|
|
else if (equalstr(tag, tagSeparator)) {
|
|
e.setAttribute( attrWeakSeparator, (uint)1 );
|
|
|
|
// okay, hack time. if the last item was a weak separator OR
|
|
// this is the first item in a container, then we nuke the
|
|
// current one
|
|
QDomElement prev = e.previousSibling().toElement();
|
|
if (prev.isNull() ||
|
|
(equalstr(prev.tagName(), tagSeparator) && !prev.attribute(attrWeakSeparator).isNull() ) ||
|
|
(equalstr(prev.tagName(), tagText))) {
|
|
// the previous element was a weak separator or didn't exist
|
|
base.removeChild( e );
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// the MergeLocal tag lets us specify where non-standard elements
|
|
// of the local tree shall be merged in. After inserting the
|
|
// elements we delete this element
|
|
else if (equalstr(tag, tagMergeLocal)) {
|
|
QDomNode it = additive.firstChild();
|
|
while ( !it.isNull() )
|
|
{
|
|
QDomElement newChild = it.toElement();
|
|
it = it.nextSibling();
|
|
if (newChild.isNull() )
|
|
continue;
|
|
|
|
if (equalstr(newChild.tagName(), tagText))
|
|
continue;
|
|
|
|
if ( newChild.attribute( attrAlreadyVisited ) == attrOne )
|
|
continue;
|
|
|
|
QString itAppend( newChild.attribute( attrAppend ) );
|
|
QString elemName( e.attribute( attrName ) );
|
|
|
|
if ( ( itAppend.isNull() && elemName.isEmpty() ) ||
|
|
( itAppend == elemName ) )
|
|
{
|
|
// first, see if this new element matches a standard one in
|
|
// the global file. if it does, then we skip it as it will
|
|
// be merged in, later
|
|
QDomElement matchingElement = findMatchingElement( newChild, base );
|
|
if (matchingElement.isNull() || equalstr(newChild.tagName(), tagSeparator))
|
|
base.insertBefore( newChild, e );
|
|
}
|
|
}
|
|
|
|
base.removeChild( e );
|
|
continue;
|
|
}
|
|
|
|
else if (equalstr(tag, tagText)) {
|
|
continue;
|
|
}
|
|
else if (equalstr(tag, tagMerge)) {
|
|
continue;
|
|
}
|
|
|
|
// in this last case we check for a separator tag and, if not, we
|
|
// can be sure that it is a container --> proceed with child nodes
|
|
// recursively and delete the just proceeded container item in
|
|
// case it is empty (if the recursive call returns true)
|
|
else {
|
|
QDomElement matchingElement = findMatchingElement( e, additive );
|
|
if ( !matchingElement.isNull() )
|
|
{
|
|
matchingElement.setAttribute( attrAlreadyVisited, (uint)1 );
|
|
|
|
if ( mergeXML( e, matchingElement, actionCollection ) )
|
|
{
|
|
base.removeChild( e );
|
|
additive.removeChild(matchingElement); // make sure we don't append it below
|
|
continue;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
// this is an important case here! We reach this point if the
|
|
// "local" tree does not contain a container definition for
|
|
// this container. However we have to call mergeXML recursively
|
|
// and make it check if there are actions implemented for this
|
|
// container. *If* none, then we can remove this container now
|
|
QDomElement dummy;
|
|
if ( mergeXML( e, dummy, actionCollection ) )
|
|
base.removeChild( e );
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
//here we append all child elements which were not inserted
|
|
//previously via the LocalMerge tag
|
|
n = additive.firstChild();
|
|
while ( !n.isNull() )
|
|
{
|
|
QDomElement e = n.toElement();
|
|
n = n.nextSibling(); // Advance now so that we can safely delete e
|
|
if (e.isNull())
|
|
continue;
|
|
|
|
QDomElement matchingElement = findMatchingElement( e, base );
|
|
|
|
if ( matchingElement.isNull() )
|
|
{
|
|
base.appendChild( e );
|
|
}
|
|
}
|
|
|
|
// do one quick check to make sure that the last element was not
|
|
// a weak separator
|
|
QDomElement last = base.lastChild().toElement();
|
|
if (equalstr(last.tagName(), tagSeparator) &&
|
|
(!last.attribute(attrWeakSeparator).isNull())) {
|
|
base.removeChild( last );
|
|
}
|
|
}
|
|
|
|
return isEmptyContainer(base, actionCollection);
|
|
}
|
|
|
|
bool KXMLGUIClientPrivate::isEmptyContainer(const QDomElement& base, KActionCollection *actionCollection) const
|
|
{
|
|
// now we check if we are empty (in which case we return "true", to
|
|
// indicate the caller that it can delete "us" (the base element
|
|
// argument of "this" call)
|
|
QDomNode n = base.firstChild();
|
|
while (!n.isNull()) {
|
|
const QDomElement e = n.toElement();
|
|
n = n.nextSibling(); // Advance now so that we can safely delete e
|
|
if (e.isNull())
|
|
continue;
|
|
|
|
const QString tag = e.tagName();
|
|
|
|
static const QString tagAction = QString::fromLatin1("Action");
|
|
static const QString tagSeparator = QString::fromLatin1("Separator");
|
|
static const QString tagText = QString::fromLatin1("text");
|
|
static const QString tagMerge = QString::fromLatin1("Merge");
|
|
if (equalstr(tag, tagAction)) {
|
|
// if base contains an implemented action, then we must not get
|
|
// deleted (note that the actionCollection contains both,
|
|
// "global" and "local" actions)
|
|
static const QString attrName = QString::fromLatin1("name");
|
|
if (actionCollection->action(e.attribute(attrName))) {
|
|
return false;
|
|
}
|
|
}
|
|
else if (equalstr(tag, tagSeparator)) {
|
|
// if we have a separator which has *not* the weak attribute
|
|
// set, then it must be owned by the "local" tree in which case
|
|
// we must not get deleted either
|
|
static const QString attrWeakSeparator = QString::fromLatin1("weakSeparator");
|
|
const QString weakAttr = e.attribute(attrWeakSeparator);
|
|
if (weakAttr.isEmpty() || weakAttr.toInt() != 1) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
else if (equalstr(tag, tagMerge)) {
|
|
continue;
|
|
}
|
|
|
|
// a text tag is NOT enough to spare this container
|
|
else if (equalstr(tag, tagText)) {
|
|
continue;
|
|
}
|
|
|
|
// what's left are non-empty containers! *don't* delete us in this
|
|
// case (at this position we can be *sure* that the container is
|
|
// *not* empty, as the recursive call for it was in the first loop
|
|
// which deleted the element in case the call returned "true"
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true; // I'm empty, please delete me.
|
|
}
|
|
|
|
QDomElement KXMLGUIClientPrivate::findMatchingElement( const QDomElement &base, const QDomElement &additive )
|
|
{
|
|
static const QString tagAction = QString::fromLatin1( "Action" );
|
|
static const QString tagMergeLocal = QString::fromLatin1( "MergeLocal" );
|
|
static const QString attrName = QString::fromLatin1( "name" );
|
|
|
|
QDomNode n = additive.firstChild();
|
|
while ( !n.isNull() )
|
|
{
|
|
QDomElement e = n.toElement();
|
|
n = n.nextSibling(); // Advance now so that we can safely delete e -- TODO we don't, so simplify this
|
|
if (e.isNull())
|
|
continue;
|
|
|
|
const QString tag = e.tagName();
|
|
// skip all action and merge tags as we will never use them
|
|
if (equalstr(tag, tagAction)
|
|
|| equalstr(tag, tagMergeLocal)) {
|
|
continue;
|
|
}
|
|
|
|
// now see if our tags are equivalent
|
|
if (equalstr(tag, base.tagName()) &&
|
|
e.attribute(attrName) == base.attribute(attrName)) {
|
|
return e;
|
|
}
|
|
}
|
|
|
|
// nope, return a (now) null element
|
|
return QDomElement();
|
|
}
|
|
|
|
void KXMLGUIClient::setXMLGUIBuildDocument( const QDomDocument &doc )
|
|
{
|
|
d->m_buildDocument = doc;
|
|
}
|
|
|
|
QDomDocument KXMLGUIClient::xmlguiBuildDocument() const
|
|
{
|
|
return d->m_buildDocument;
|
|
}
|
|
|
|
void KXMLGUIClient::setFactory( KXMLGUIFactory *factory )
|
|
{
|
|
d->m_factory = factory;
|
|
}
|
|
|
|
KXMLGUIFactory *KXMLGUIClient::factory() const
|
|
{
|
|
return d->m_factory;
|
|
}
|
|
|
|
KXMLGUIClient *KXMLGUIClient::parentClient() const
|
|
{
|
|
return d->m_parent;
|
|
}
|
|
|
|
void KXMLGUIClient::insertChildClient( KXMLGUIClient *child )
|
|
{
|
|
if ( child->d->m_parent )
|
|
child->d->m_parent->removeChildClient( child );
|
|
d->m_children.append( child );
|
|
child->d->m_parent = this;
|
|
}
|
|
|
|
void KXMLGUIClient::removeChildClient( KXMLGUIClient *child )
|
|
{
|
|
assert( d->m_children.contains( child ) );
|
|
d->m_children.removeAll( child );
|
|
child->d->m_parent = 0;
|
|
}
|
|
|
|
/*bool KXMLGUIClient::addSuperClient( KXMLGUIClient *super )
|
|
{
|
|
if ( d->m_supers.contains( super ) )
|
|
return false;
|
|
d->m_supers.append( super );
|
|
return true;
|
|
}*/
|
|
|
|
QList<KXMLGUIClient*> KXMLGUIClient::childClients()
|
|
{
|
|
return d->m_children;
|
|
}
|
|
|
|
void KXMLGUIClient::setClientBuilder( KXMLGUIBuilder *builder )
|
|
{
|
|
d->m_builder = builder;
|
|
if ( builder )
|
|
builder->setBuilderComponentData( componentData() );
|
|
}
|
|
|
|
KXMLGUIBuilder *KXMLGUIClient::clientBuilder() const
|
|
{
|
|
return d->m_builder;
|
|
}
|
|
|
|
void KXMLGUIClient::plugActionList( const QString &name, const QList<QAction*> &actionList )
|
|
{
|
|
if ( !d->m_factory )
|
|
return;
|
|
|
|
d->m_factory->plugActionList( this, name, actionList );
|
|
}
|
|
|
|
void KXMLGUIClient::unplugActionList( const QString &name )
|
|
{
|
|
if ( !d->m_factory )
|
|
return;
|
|
|
|
d->m_factory->unplugActionList( this, name );
|
|
}
|
|
|
|
QString KXMLGUIClient::findMostRecentXMLFile( const QStringList &files, QString &doc )
|
|
{
|
|
KXmlGuiVersionHandler versionHandler(files);
|
|
doc = versionHandler.finalDocument();
|
|
return versionHandler.finalFile();
|
|
}
|
|
|
|
void KXMLGUIClient::addStateActionEnabled(const QString& state,
|
|
const QString& action)
|
|
{
|
|
StateChange stateChange = getActionsToChangeForState(state);
|
|
|
|
stateChange.actionsToEnable.append( action );
|
|
//kDebug(260) << "KXMLGUIClient::addStateActionEnabled( " << state << ", " << action << ")";
|
|
|
|
d->m_actionsStateMap.insert( state, stateChange );
|
|
}
|
|
|
|
|
|
void KXMLGUIClient::addStateActionDisabled(const QString& state,
|
|
const QString& action)
|
|
{
|
|
StateChange stateChange = getActionsToChangeForState(state);
|
|
|
|
stateChange.actionsToDisable.append( action );
|
|
//kDebug(260) << "KXMLGUIClient::addStateActionDisabled( " << state << ", " << action << ")";
|
|
|
|
d->m_actionsStateMap.insert( state, stateChange );
|
|
}
|
|
|
|
|
|
KXMLGUIClient::StateChange KXMLGUIClient::getActionsToChangeForState(const QString& state)
|
|
{
|
|
return d->m_actionsStateMap[state];
|
|
}
|
|
|
|
|
|
void KXMLGUIClient::stateChanged(const QString &newstate, KXMLGUIClient::ReverseStateChange reverse)
|
|
{
|
|
StateChange stateChange = getActionsToChangeForState(newstate);
|
|
|
|
bool setTrue = (reverse == StateNoReverse);
|
|
bool setFalse = !setTrue;
|
|
|
|
// Enable actions which need to be enabled...
|
|
//
|
|
foreach ( const QString it, stateChange.actionsToEnable ) {
|
|
QAction *action = actionCollection()->action(qPrintable(it));
|
|
if (action) action->setEnabled(setTrue);
|
|
}
|
|
|
|
// and disable actions which need to be disabled...
|
|
//
|
|
foreach ( const QString it, stateChange.actionsToDisable ) {
|
|
QAction *action = actionCollection()->action(qPrintable(it));
|
|
if (action) action->setEnabled(setFalse);
|
|
}
|
|
|
|
}
|
|
|
|
void KXMLGUIClient::beginXMLPlug( QWidget* w )
|
|
{
|
|
actionCollection()->addAssociatedWidget( w );
|
|
foreach (KXMLGUIClient* client, d->m_children)
|
|
client->beginXMLPlug( w );
|
|
}
|
|
|
|
void KXMLGUIClient::endXMLPlug()
|
|
{
|
|
}
|
|
|
|
void KXMLGUIClient::prepareXMLUnplug( QWidget * w )
|
|
{
|
|
actionCollection()->removeAssociatedWidget( w );
|
|
foreach (KXMLGUIClient* client, d->m_children)
|
|
client->prepareXMLUnplug( w );
|
|
}
|
|
|