20 #include "kxmlguiclient.h"
21 #include "kxmlguifactory.h"
22 #include "kxmlguibuilder.h"
27 #include <tqtextstream.h>
29 #include <tqguardedptr.h>
31 #include <kinstance.h>
32 #include <kstandarddirs.h>
34 #include <tdeaction.h>
35 #include <tdeapplication.h>
39 class KXMLGUIClientPrivate
42 KXMLGUIClientPrivate()
47 m_actionCollection = 0;
49 ~KXMLGUIClientPrivate()
57 TQDomDocument m_buildDocument;
58 TQGuardedPtr<KXMLGUIFactory> m_factory;
61 TQPtrList<KXMLGUIClient> m_children;
64 TQString m_localXMLFile;
69 d =
new KXMLGUIClientPrivate;
74 d =
new KXMLGUIClientPrivate;
81 d->m_parent->removeChildClient(
this );
83 TQPtrListIterator<KXMLGUIClient> it( d->m_children );
84 for ( ; it.current(); ++it ) {
85 assert( it.current()->d->m_parent == this );
86 it.current()->d->m_parent = 0;
89 delete d->m_actionCollection;
97 TQPtrListIterator<KXMLGUIClient> childIt( d->m_children );
98 for (; childIt.current(); ++childIt ) {
99 act = childIt.current()->actionCollection()->action( name );
109 if ( !d->m_actionCollection )
112 "KXMLGUIClient-TDEActionCollection",
this );
114 return d->m_actionCollection;
125 return d->m_instance;
138 TQString KXMLGUIClient::localXMLFile()
const
140 if ( !d->m_localXMLFile.isEmpty() )
141 return d->m_localXMLFile;
143 if ( !TQDir::isRelativePath(d->m_xmlFile) )
144 return TQString::null;
146 return locateLocal(
"data", TQString::fromLatin1(
instance()->instanceName() +
'/' ) + d->m_xmlFile );
153 if ( !file.isEmpty() )
162 d->m_builder->setBuilderClient(
this );
168 if ( !_file.isNull() ) {
169 d->m_xmlFile = _file;
176 TQString file = _file;
177 if ( TQDir::isRelativePath(file) )
181 TQString filter = TQString::fromLatin1(
instance()->instanceName() +
'/' ) + _file;
183 TQStringList allFiles =
instance()->dirs()->findAllResources(
"data", filter ) +
instance()->dirs()->findAllResources(
"data", _file );
185 file = findMostRecentXMLFile( allFiles, doc );
187 if ( file.isEmpty() )
195 if ( !_file.isEmpty() )
196 kdWarning() <<
"KXMLGUIClient::setXMLFile: cannot find .rc file " << _file <<
endl;
198 setXML( TQString::null,
true );
201 else if ( !doc.isEmpty() )
208 TQString xml = KXMLGUIFactory::readConfigFile( file );
212 void KXMLGUIClient::setLocalXMLFile(
const TQString &file )
214 d->m_localXMLFile = file;
220 doc.setContent( document );
228 TQDomElement base = d->m_doc.documentElement();
230 TQDomElement e = document.documentElement();
237 base = d->m_doc.documentElement();
251 bool KXMLGUIClient::mergeXML( TQDomElement &base,
const TQDomElement &additive,
TDEActionCollection *actionCollection )
270 if ( additive.attribute(attrNoMerge) == attrOne )
272 base.parentNode().replaceChild(additive, base);
279 TQDomNode n = base.firstChild();
280 while ( !n.isNull() )
282 TQDomElement e = n.toElement();
291 if ( tag == tagAction )
293 TQCString
name = e.attribute( attrName ).utf8();
294 if ( !actionCollection->
action( name.data() ) ||
295 (kapp && !kapp->authorizeTDEAction(name)))
298 base.removeChild( e );
305 else if ( tag == tagSeparator )
307 e.setAttribute( attrWeakSeparator, (uint)1 );
312 TQDomElement prev = e.previousSibling().toElement();
313 if ( prev.isNull() ||
314 ( prev.tagName() == tagSeparator && !prev.attribute( attrWeakSeparator ).isNull() ) ||
315 ( prev.tagName() == tagText ) )
318 base.removeChild( e );
326 else if ( tag == tagMergeLocal )
328 TQDomNode it = additive.firstChild();
329 while ( !it.isNull() )
331 TQDomElement newChild = it.toElement();
332 it = it.nextSibling();
333 if (newChild.isNull() )
336 if ( newChild.tagName() == tagText )
339 if ( newChild.attribute( attrAlreadyVisited ) == attrOne )
342 TQString itAppend( newChild.attribute( attrAppend ) );
343 TQString elemName( e.attribute( attrName ) );
345 if ( ( itAppend.isNull() && elemName.isEmpty() ) ||
346 ( itAppend == elemName ) )
351 TQDomElement matchingElement = findMatchingElement( newChild, base );
352 if ( matchingElement.isNull() || newChild.tagName() == tagSeparator )
353 base.insertBefore( newChild, e );
357 base.removeChild( e );
365 else if ( tag != tagMerge )
368 if ( tag == tagText )
371 TQDomElement matchingElement = findMatchingElement( e, additive );
373 if ( !matchingElement.isNull() )
375 matchingElement.setAttribute( attrAlreadyVisited, (uint)1 );
377 if ( mergeXML( e, matchingElement, actionCollection ) )
379 base.removeChild( e );
384 const TQDomNamedNodeMap attribs = matchingElement.attributes();
385 const uint attribcount = attribs.count();
387 for(uint i = 0; i < attribcount; ++i)
389 const TQDomNode node = attribs.item(i);
390 e.setAttribute(node.nodeName(), node.nodeValue());
402 if ( mergeXML( e, TQDomElement(), actionCollection ) )
403 base.removeChild( e );
411 n = additive.firstChild();
412 while ( !n.isNull() )
414 TQDomElement e = n.toElement();
419 TQDomElement matchingElement = findMatchingElement( e, base );
421 if ( matchingElement.isNull() )
423 base.appendChild( e );
429 TQDomElement last = base.lastChild().toElement();
430 if ( (last.tagName() == tagSeparator) && (!last.attribute( attrWeakSeparator ).isNull()) )
432 base.removeChild( last );
438 bool deleteMe =
true;
440 n = base.firstChild();
441 while ( !n.isNull() )
443 TQDomElement e = n.toElement();
450 if ( tag == tagAction )
455 if ( actionCollection->
action( e.attribute( attrName ).utf8().data() ) )
461 else if ( tag == tagSeparator )
466 TQString weakAttr = e.attribute( attrWeakSeparator );
467 if ( weakAttr.isEmpty() || weakAttr.toInt() != 1 )
475 else if ( tag == tagMerge )
483 else if ( tag == tagText )
502 TQDomElement KXMLGUIClient::findMatchingElement(
const TQDomElement &base,
const TQDomElement &additive )
508 TQDomNode n = additive.firstChild();
509 while ( !n.isNull() )
511 TQDomElement e = n.toElement();
517 if ( ( e.tagName() == tagAction ) || ( e.tagName() == tagMergeLocal ) )
523 if ( ( e.tagName() == base.tagName() ) &&
524 ( e.attribute( attrName ) == base.attribute( attrName ) ) )
531 return TQDomElement();
536 d->m_doc = TQDomDocument();
537 d->m_buildDocument = TQDomDocument();
542 d->m_buildDocument = doc;
547 return d->m_buildDocument;
567 if ( child->d->m_parent )
568 child->d->m_parent->removeChildClient( child );
569 d->m_children.append( child );
570 child->d->m_parent =
this;
575 assert( d->m_children.containsRef( child ) );
576 d->m_children.removeRef( child );
577 child->d->m_parent = 0;
590 return &d->m_children;
595 d->m_builder = builder;
597 builder->setBuilderInstance(
instance() );
610 d->m_factory->plugActionList(
this, name, actionList );
618 d->m_factory->unplugActionList(
this, name );
621 TQString KXMLGUIClient::findMostRecentXMLFile(
const TQStringList &files, TQString &doc )
624 TQValueList<DocStruct> allDocuments;
626 TQStringList::ConstIterator it = files.begin();
627 TQStringList::ConstIterator end = files.end();
628 for (; it != end; ++it )
631 TQString data = KXMLGUIFactory::readConfigFile( *it );
635 allDocuments.append( d );
638 TQValueList<DocStruct>::Iterator best = allDocuments.end();
639 uint bestVersion = 0;
641 TQValueList<DocStruct>::Iterator docIt = allDocuments.begin();
642 TQValueList<DocStruct>::Iterator docEnd = allDocuments.end();
643 for (; docIt != docEnd; ++docIt )
645 TQString versionStr = findVersionNumber( (*docIt).data );
646 if ( versionStr.isEmpty() )
650 uint
version = versionStr.toUInt( &ok );
655 if ( version > bestVersion )
659 bestVersion = version;
663 if ( best != docEnd )
665 if ( best != allDocuments.begin() )
667 TQValueList<DocStruct>::Iterator local = allDocuments.begin();
670 TQDomDocument document;
671 document.setContent( (*local).data );
673 ActionPropertiesMap properties = extractActionProperties( document );
678 if ( !properties.isEmpty() )
682 document.setContent( (*best).data );
684 storeActionProperties( document, properties );
686 (*local).data = document.toString();
691 TQFile f( (*local).file );
692 if ( f.open( IO_WriteOnly ) )
694 TQCString utf8data = (*local).data.utf8();
695 f.writeBlock( utf8data.data(), utf8data.length() );
701 TQString f = (*local).file;
702 TQString backup = f + TQString::fromLatin1(
".backup" );
704 dir.rename( f, backup );
710 else if ( files.count() > 0 )
713 doc = (*allDocuments.begin()).data;
714 return (*allDocuments.begin()).file;
717 return TQString::null;
722 TQString KXMLGUIClient::findVersionNumber(
const TQString &xml )
724 enum { ST_START, ST_AFTER_OPEN, ST_AFTER_GUI,
725 ST_EXPECT_VERSION, ST_VERSION_NUM} state = ST_START;
726 for (
unsigned int pos = 0; pos < xml.length(); pos++)
732 state = ST_AFTER_OPEN;
737 int guipos = xml.find(
"gui", pos,
false );
739 return TQString::null;
742 state = ST_AFTER_GUI;
746 state = ST_EXPECT_VERSION;
748 case ST_EXPECT_VERSION:
750 int verpos = xml.find(
"version=\"", pos,
false );
752 return TQString::null;
755 state = ST_VERSION_NUM;
761 for (endpos = pos; endpos < xml.length(); endpos++)
763 if (xml[endpos].unicode() >=
'0' && xml[endpos].unicode() <=
'9')
765 if (xml[endpos].unicode() ==
'"')
769 endpos = xml.length();
773 if (endpos != pos && endpos < xml.length() )
775 TQString matchCandidate = xml.mid(pos, endpos - pos);
776 return matchCandidate;
779 state = ST_EXPECT_VERSION;
785 return TQString::null;
788 KXMLGUIClient::ActionPropertiesMap KXMLGUIClient::extractActionProperties(
const TQDomDocument &doc )
790 ActionPropertiesMap properties;
792 TQDomElement actionPropElement = doc.documentElement().namedItem(
"ActionProperties" ).toElement();
794 if ( actionPropElement.isNull() )
797 TQDomNode n = actionPropElement.firstChild();
800 TQDomElement e = n.toElement();
805 if ( e.tagName().lower() !=
"action" )
808 TQString actionName = e.attribute(
"name" );
810 if ( actionName.isEmpty() )
813 TQMap<TQString, TQMap<TQString, TQString> >::Iterator propIt = properties.find( actionName );
814 if ( propIt == properties.end() )
815 propIt = properties.insert( actionName, TQMap<TQString, TQString>() );
817 const TQDomNamedNodeMap attributes = e.attributes();
818 const uint attributeslength = attributes.length();
820 for ( uint i = 0; i < attributeslength; ++i )
822 const TQDomAttr attr = attributes.item( i ).toAttr();
827 const TQString name = attr.name();
829 if ( name ==
"name" || name.isEmpty() )
832 (*propIt)[ name ] = attr.value();
840 void KXMLGUIClient::storeActionProperties( TQDomDocument &doc,
const ActionPropertiesMap &properties )
842 TQDomElement actionPropElement = doc.documentElement().namedItem(
"ActionProperties" ).toElement();
844 if ( actionPropElement.isNull() )
846 actionPropElement = doc.createElement(
"ActionProperties" );
847 doc.documentElement().appendChild( actionPropElement );
850 while ( !actionPropElement.firstChild().isNull() )
851 actionPropElement.removeChild( actionPropElement.firstChild() );
853 ActionPropertiesMap::ConstIterator it = properties.begin();
854 ActionPropertiesMap::ConstIterator end = properties.end();
855 for (; it != end; ++it )
857 TQDomElement
action = doc.createElement(
"Action" );
858 action.setAttribute(
"name", it.key() );
859 actionPropElement.appendChild( action );
861 TQMap<TQString, TQString> attributes = (*it);
862 TQMap<TQString, TQString>::ConstIterator attrIt = attributes.begin();
863 TQMap<TQString, TQString>::ConstIterator attrEnd = attributes.end();
864 for (; attrIt != attrEnd; ++attrIt )
865 action.setAttribute( attrIt.key(), attrIt.data() );
869 void KXMLGUIClient::addStateActionEnabled(
const TQString& state,
870 const TQString& action)
872 StateChange stateChange = getActionsToChangeForState(state);
874 stateChange.actionsToEnable.append( action );
877 m_actionsStateMap.replace( state, stateChange );
881 void KXMLGUIClient::addStateActionDisabled(
const TQString& state,
882 const TQString& action)
884 StateChange stateChange = getActionsToChangeForState(state);
886 stateChange.actionsToDisable.append( action );
889 m_actionsStateMap.replace( state, stateChange );
893 KXMLGUIClient::StateChange KXMLGUIClient::getActionsToChangeForState(
const TQString& state)
895 return m_actionsStateMap[state];
901 StateChange stateChange = getActionsToChangeForState(newstate);
903 bool setTrue = (reverse == StateNoReverse);
904 bool setFalse = !setTrue;
908 for ( TQStringList::Iterator it = stateChange.actionsToEnable.begin();
909 it != stateChange.actionsToEnable.end(); ++it ) {
917 for ( TQStringList::Iterator it = stateChange.actionsToDisable.begin();
918 it != stateChange.actionsToDisable.end(); ++it ) {
929 TQPtrListIterator<KXMLGUIClient> childIt( d->m_children );
930 for (; childIt.current(); ++childIt )
931 childIt.current()->actionCollection()->beginXMLPlug( w );
937 TQPtrListIterator<KXMLGUIClient> childIt( d->m_children );
938 for (; childIt.current(); ++childIt )
939 childIt.current()->actionCollection()->endXMLPlug();
945 TQPtrListIterator<KXMLGUIClient> childIt( d->m_children );
946 for (; childIt.current(); ++childIt )
947 childIt.current()->actionCollection()->prepareXMLUnplug();
950 void KXMLGUIClient::virtual_hook(
int,
void* )
virtual void conserveMemory()
This function will attempt to give up some memory after the GUI is built.
TQDomDocument xmlguiBuildDocument() const
virtual void setXML(const TQString &document, bool merge=false)
Sets the XML for the part.
virtual void setXMLFile(const TQString &file, bool merge=false, bool setXMLDoc=true)
Sets the name of the rc file containing the XML for the part.
void prepareXMLUnplug(TQWidget *)
A KXMLGUIClient can be used with KXMLGUIFactory to create a GUI from actions and an XML document...
TQString locateLocal(const char *type, const TQString &filename, const TDEInstance *instance=TDEGlobal::instance())
void setXMLGUIBuildDocument(const TQDomDocument &doc)
void removeChildClient(KXMLGUIClient *child)
Removes the given child from the client's children list.
virtual void setDOMDocument(const TQDomDocument &document, bool merge=false)
Sets the Document for the part, describing the layout of the GUI.
void setClientBuilder(KXMLGUIBuilder *builder)
A client can have an own KXMLGUIBuilder.
const TQPtrList< KXMLGUIClient > * childClients()
Retrieves a list of all child clients.
KXMLGUIFactory * factory() const
Retrieves a pointer to the KXMLGUIFactory this client is associated with (will return 0L if the clien...
virtual TDEAction * action(int index) const
Return the TDEAction* at position "index" in the action collection.
void reloadXML()
Forces this client to re-read its XML resource file.
virtual void setInstance(TDEInstance *instance)
Returns true if client was added to super client list.
A managed set of TDEAction objects.
Class to encapsulate user-driven action or event.
virtual void stateChanged(const TQString &newstate, ReverseStateChange reverse=StateNoReverse)
Actions can collectively be assigned a "State".
TDEAction * action(const char *name) const
Retrieves an action of the client by name.
void setFactory(KXMLGUIFactory *factory)
This method is called by the KXMLGUIFactory as soon as the client is added to the KXMLGUIFactory's GU...
void unplugActionList(const TQString &name)
The complement of plugActionList() ...
Abstract interface for a "GUI builder", used by the GUIFactory This interface is implemented by TDEMa...
virtual TDEActionCollection * actionCollection() const
Retrieves the entire action collection for the GUI client.
static TDEInstance * instance()
kdbgstream kdWarning(int area=0)
void setXMLFile(const TQString &)
static const TQString & staticQString(const char *str)
KXMLGUIFactory, together with KXMLGUIClient objects, can be used to create a GUI of container widgets...
virtual void setEnabled(bool enable)
Enables or disables this action.
KXMLGUIClient * parentClient() const
KXMLGUIClients can form a simple child/parent object tree.
virtual TQDomDocument domDocument() const
virtual TDEInstance * instance() const
void beginXMLPlug(TQWidget *)
virtual ~KXMLGUIClient()
Destructs the KXMLGUIClient.
void plugActionList(const TQString &name, const TQPtrList< TDEAction > &actionList)
ActionLists are a way for XMLGUI to support dynamic lists of actions.
void insertChildClient(KXMLGUIClient *child)
Use this method to make a client a child client of another client.
kndbgstream & endl(kndbgstream &s)
TQString name(StdAccel id)
KXMLGUIBuilder * clientBuilder() const
Retrieves the client's GUI builder or 0L if no client specific builder has been assigned via setClien...
virtual TQString xmlFile() const
This will return the name of the XML file as set by setXMLFile().
KXMLGUIClient()
Constructs a KXMLGUIClient which can be used with a KXMLGUIFactory to create a GUI from actions and a...