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;
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();
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 );
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());
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 )
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 )
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* )
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,...
KXMLGUIClient * parentClient() const
KXMLGUIClients can form a simple child/parent object tree.
void plugActionList(const TQString &name, const TQPtrList< TDEAction > &actionList)
ActionLists are a way for XMLGUI to support dynamic lists of actions.
virtual TQString xmlFile() const
This will return the name of the XML file as set by setXMLFile().
void unplugActionList(const TQString &name)
The complement of plugActionList() ...
KXMLGUIClient()
Constructs a KXMLGUIClient which can be used with a KXMLGUIFactory to create a GUI from actions and a...
void removeChildClient(KXMLGUIClient *child)
Removes the given child from the client's children list.
virtual TDEInstance * instance() const
TQDomDocument xmlguiBuildDocument() const
void reloadXML()
Forces this client to re-read its XML resource file.
void setXMLGUIBuildDocument(const TQDomDocument &doc)
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.
KXMLGUIFactory * factory() const
Retrieves a pointer to the KXMLGUIFactory this client is associated with (will return 0L if the clien...
virtual void setDOMDocument(const TQDomDocument &document, bool merge=false)
Sets the Document for the part, describing the layout of the GUI.
void prepareXMLUnplug(TQWidget *)
virtual ~KXMLGUIClient()
Destructs the KXMLGUIClient.
void setClientBuilder(KXMLGUIBuilder *builder)
A client can have an own KXMLGUIBuilder.
void beginXMLPlug(TQWidget *)
TDEAction * action(const char *name) const
Retrieves an action of the client by name.
virtual void setXML(const TQString &document, bool merge=false)
Sets the XML for the part.
virtual void conserveMemory()
This function will attempt to give up some memory after the GUI is built.
virtual void stateChanged(const TQString &newstate, ReverseStateChange reverse=StateNoReverse)
Actions can collectively be assigned a "State".
void setFactory(KXMLGUIFactory *factory)
This method is called by the KXMLGUIFactory as soon as the client is added to the KXMLGUIFactory's GU...
KXMLGUIBuilder * clientBuilder() const
Retrieves the client's GUI builder or 0L if no client specific builder has been assigned via setClien...
const TQPtrList< KXMLGUIClient > * childClients()
Retrieves a list of all child clients.
virtual TDEActionCollection * actionCollection() const
Retrieves the entire action collection for the GUI client.
void insertChildClient(KXMLGUIClient *child)
Use this method to make a client a child client of another client.
virtual void setInstance(TDEInstance *instance)
Returns true if client was added to super client list.
virtual TQDomDocument domDocument() const
KXMLGUIFactory, together with KXMLGUIClient objects, can be used to create a GUI of container widgets...
A managed set of TDEAction objects.
virtual TDEAction * action(int index) const
Return the TDEAction* at position "index" in the action collection.
void setXMLFile(const TQString &)
Class to encapsulate user-driven action or event.
virtual void setEnabled(bool enable)
Enables or disables this action.
static TDEInstance * instance()
static const TQString & staticQString(const char *str)
TDEStandardDirs * dirs() const
TQStringList findAllResources(const char *type, const TQString &filter=TQString::null, bool recursive=false, bool unique=false) const
kndbgstream & endl(kndbgstream &s)
kdbgstream kdWarning(int area=0)
TQString locateLocal(const char *type, const TQString &filename, const TDEInstance *instance=TDEGlobal::instance())
TQString name(StdAccel id)
const TDEShortcut & end()