summaryrefslogtreecommitdiffabout
path: root/microkde/kdeui/kxmlguiclient.cpp
Unidiff
Diffstat (limited to 'microkde/kdeui/kxmlguiclient.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--microkde/kdeui/kxmlguiclient.cpp958
1 files changed, 958 insertions, 0 deletions
diff --git a/microkde/kdeui/kxmlguiclient.cpp b/microkde/kdeui/kxmlguiclient.cpp
new file mode 100644
index 0000000..073e30b
--- a/dev/null
+++ b/microkde/kdeui/kxmlguiclient.cpp
@@ -0,0 +1,958 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
3 Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20#include "kxmlguiclient.h"
21
22/*US
23#include "kxmlguifactory.h"
24#include "kxmlguibuilder.h"
25*/
26
27/*US
28#include <qdir.h>
29#include <qfile.h>
30#include <qdom.h>
31#include <qtextstream.h>
32#include <qregexp.h>
33*/
34
35//US #include <kinstance.h>
36#include <kstandarddirs.h>
37#include <kdebug.h>
38#include <kaction.h>
39#include <kapplication.h>
40
41#include <assert.h>
42
43class KXMLGUIClientPrivate
44{
45public:
46 KXMLGUIClientPrivate()
47 {
48//US m_instance = KGlobal::instance();
49//US m_factory = 0L;
50 m_parent = 0L;
51//US m_builder = 0L;
52 m_actionCollection = 0;
53 }
54 ~KXMLGUIClientPrivate()
55 {
56 }
57
58//US KInstance *m_instance;
59
60//US QDomDocument m_doc;
61 KActionCollection *m_actionCollection;
62//US QDomDocument m_buildDocument;
63//US KXMLGUIFactory *m_factory;
64 KXMLGUIClient *m_parent;
65 //QPtrList<KXMLGUIClient> m_supers;
66 QPtrList<KXMLGUIClient> m_children;
67//US KXMLGUIBuilder *m_builder;
68//US QString m_xmlFile;
69//US QString m_localXMLFile;
70};
71
72KXMLGUIClient::KXMLGUIClient()
73{
74 d = new KXMLGUIClientPrivate;
75}
76
77KXMLGUIClient::KXMLGUIClient( KXMLGUIClient *parent )
78{
79 d = new KXMLGUIClientPrivate;
80 parent->insertChildClient( this );
81}
82
83KXMLGUIClient::~KXMLGUIClient()
84{
85 if ( d->m_parent )
86 d->m_parent->removeChildClient( this );
87
88 QPtrListIterator<KXMLGUIClient> it( d->m_children );
89 for ( ; it.current(); ++it ) {
90 assert( it.current()->d->m_parent == this );
91 it.current()->d->m_parent = 0;
92 }
93
94 delete d->m_actionCollection;
95 delete d;
96}
97
98KAction *KXMLGUIClient::action( const char *name ) const
99{
100 KAction* act = actionCollection()->action( name );
101 if ( !act ) {
102 QPtrListIterator<KXMLGUIClient> childIt( d->m_children );
103 for (; childIt.current(); ++childIt ) {
104 act = childIt.current()->actionCollection()->action( name );
105 if ( act )
106 break;
107 }
108 }
109 return act;
110}
111
112KActionCollection *KXMLGUIClient::actionCollection() const
113{
114 if ( !d->m_actionCollection )
115 d->m_actionCollection = new KActionCollection( 0, 0,
116 "KXMLGUILClient-KActionCollection" );
117 return d->m_actionCollection;
118}
119
120/*US
121KAction *KXMLGUIClient::action( const QDomElement &element ) const
122{
123 static const QString &attrName = KGlobal::staticQString( "name" );
124 return actionCollection()->action( element.attribute( attrName ).latin1() );
125}
126
127KInstance *KXMLGUIClient::instance() const
128{
129 return d->m_instance;
130}
131
132QDomDocument KXMLGUIClient::domDocument() const
133{
134 return d->m_doc;
135}
136
137QString KXMLGUIClient::xmlFile() const
138{
139 return d->m_xmlFile;
140}
141
142QString KXMLGUIClient::localXMLFile() const
143{
144 if ( !d->m_localXMLFile.isEmpty() )
145 return d->m_localXMLFile;
146
147 if ( d->m_xmlFile[0] == '/' )
148 return QString::null; // can't save anything here
149
150 return locateLocal( "data", QString::fromLatin1( instance()->instanceName() + '/' ) + d->m_xmlFile );
151}
152
153
154void KXMLGUIClient::reloadXML()
155{
156 QString file( xmlFile() );
157 if ( !file.isEmpty() )
158 setXMLFile( file );
159}
160
161void KXMLGUIClient::setInstance( KInstance *instance )
162{
163 d->m_instance = instance;
164 actionCollection()->setInstance( instance );
165 if ( d->m_builder )
166 d->m_builder->setBuilderClient( this );
167}
168
169void KXMLGUIClient::setXMLFile( const QString& _file, bool merge, bool setXMLDoc )
170{
171 // store our xml file name
172 if ( !_file.isNull() ) {
173 d->m_xmlFile = _file;
174 actionCollection()->setXMLFile( _file );
175 }
176
177 if ( !setXMLDoc )
178 return;
179
180 QString file = _file;
181 if ( file[0] != '/' )
182 {
183 QString doc;
184
185 QString filter = QString::fromLatin1( instance()->instanceName() + '/' ) + _file;
186
187 QStringList allFiles = instance()->dirs()->findAllResources( "data", filter ) + instance()->dirs()->findAllResources( "data", _file );
188
189 file = findMostRecentXMLFile( allFiles, doc );
190
191 if ( file.isEmpty() )
192 {
193 // this might or might not be an error. for the time being,
194 // let's treat this as if it isn't a problem and the user just
195 // wants the global standards file
196 setXML( QString::null, true );
197 return;
198 }
199 else if ( !doc.isEmpty() )
200 {
201 setXML( doc, merge );
202 return;
203 }
204 }
205
206 QString xml = KXMLGUIFactory::readConfigFile( file );
207 setXML( xml, merge );
208}
209
210void KXMLGUIClient::setLocalXMLFile( const QString &file )
211{
212 d->m_localXMLFile = file;
213}
214
215void KXMLGUIClient::setXML( const QString &document, bool merge )
216{
217 QDomDocument doc;
218 doc.setContent( document );
219 setDOMDocument( doc, merge );
220}
221
222void KXMLGUIClient::setDOMDocument( const QDomDocument &document, bool merge )
223{
224 if ( merge )
225 {
226 QDomElement base = d->m_doc.documentElement();
227
228 QDomElement e = document.documentElement();
229 KXMLGUIFactory::removeDOMComments( e );
230
231 // merge our original (global) xml with our new one
232 mergeXML(base, e, actionCollection());
233
234 // reassign our pointer as mergeXML might have done something
235 // strange to it
236 base = d->m_doc.documentElement();
237
238 // we want some sort of failsafe.. just in case
239 if ( base.isNull() )
240 d->m_doc = document;
241 }
242 else
243 {
244 d->m_doc = document;
245 KXMLGUIFactory::removeDOMComments( d->m_doc );
246 }
247
248 setXMLGUIBuildDocument( QDomDocument() );
249}
250*/
251
252/*US
253bool KXMLGUIClient::mergeXML( QDomElement &base, const QDomElement &additive, KActionCollection *actionCollection )
254{
255 static const QString &tagAction = KGlobal::staticQString( "Action" );
256 static const QString &tagMerge = KGlobal::staticQString( "Merge" );
257 static const QString &tagSeparator = KGlobal::staticQString( "Separator" );
258 static const QString &attrName = KGlobal::staticQString( "name" );
259 static const QString &attrAppend = KGlobal::staticQString( "append" );
260 static const QString &attrWeakSeparator = KGlobal::staticQString( "weakSeparator" );
261 static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" );
262 static const QString &tagText = KGlobal::staticQString( "text" );
263 static const QString &attrAlreadyVisited = KGlobal::staticQString( "alreadyVisited" );
264 static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" );
265 static const QString &attrOne = KGlobal::staticQString( "1" );
266
267 // there is a possibility that we don't want to merge in the
268 // additive.. rather, we might want to *replace* the base with the
269 // additive. this can be for any container.. either at a file wide
270 // level or a simple container level. we look for the 'noMerge'
271 // tag, in any event and just replace the old with the new
272 if ( additive.attribute(attrNoMerge) == attrOne ) // ### use toInt() instead? (Simon)
273 {
274 base.parentNode().replaceChild(additive, base);
275 return true;
276 }
277
278 QString tag;
279
280 QDomElement e = base.firstChild().toElement();
281 // iterate over all elements in the container (of the global DOM tree)
282 while ( !e.isNull() )
283 {
284 tag = e.tagName();
285
286 // if there's an action tag in the global tree and the action is
287 // not implemented, then we remove the element
288 if ( tag == tagAction )
289 {
290 QCString name = e.attribute( attrName ).utf8(); // WABA
291 if ( !actionCollection->action( name ) ||
292 (kapp && !kapp->authorizeKAction(name)))
293 {
294 // remove this child as we aren't using it
295 QDomElement oldChild = e;
296 e = e.nextSibling().toElement();
297 base.removeChild( oldChild );
298 continue;
299 }
300 }
301
302 // if there's a separator defined in the global tree, then add an
303 // attribute, specifying that this is a "weak" separator
304 else if ( tag == tagSeparator )
305 {
306 e.setAttribute( attrWeakSeparator, (uint)1 );
307
308 // okay, hack time. if the last item was a weak separator OR
309 // this is the first item in a container, then we nuke the
310 // current one
311 QDomElement prev = e.previousSibling().toElement();
312 if ( prev.isNull() ||
313 ( prev.tagName() == tagSeparator && !prev.attribute( attrWeakSeparator ).isNull() ) ||
314 ( prev.tagName() == tagText ) )
315 {
316 // the previous element was a weak separator or didn't exist
317 QDomElement oldChild = e;
318 e = e.nextSibling().toElement();
319 base.removeChild( oldChild );
320 continue;
321 }
322 }
323
324 // the MergeLocal tag lets us specify where non-standard elements
325 // of the local tree shall be merged in. After inserting the
326 // elements we delete this element
327 else if ( tag == tagMergeLocal )
328 {
329 QDomElement currElement = e;
330
331 // switch our iterator "e" to the next sibling, so that we don't
332 // process the local tree's inserted items!
333 e = e.nextSibling().toElement();
334
335 QDomElement it = additive.firstChild().toElement();
336 while ( !it.isNull() )
337 {
338 QDomElement newChild = it;
339
340 it = it.nextSibling().toElement();
341
342 if ( newChild.tagName() == tagText )
343 continue;
344
345 if ( newChild.attribute( attrAlreadyVisited ) == attrOne )
346 continue;
347
348 QString itAppend( newChild.attribute( attrAppend ) );
349 QString elemName( currElement.attribute( attrName ) );
350
351 if ( ( itAppend.isNull() && elemName.isEmpty() ) ||
352 ( itAppend == elemName ) )
353 {
354 // first, see if this new element matches a standard one in
355 // the global file. if it does, then we skip it as it will
356 // be merged in, later
357 QDomElement matchingElement = findMatchingElement( newChild, base );
358 if ( matchingElement.isNull() || newChild.tagName() == tagSeparator )
359 base.insertBefore( newChild, currElement );
360 }
361 }
362
363 base.removeChild( currElement );
364 continue;
365 }
366
367 // in this last case we check for a separator tag and, if not, we
368 // can be sure that its a container --> proceed with child nodes
369 // recursively and delete the just proceeded container item in
370 // case its empty (if the recursive call returns true)
371 else if ( tag != tagMerge )
372 {
373 // handle the text tag
374 if ( tag == tagText )
375 {
376 e = e.nextSibling().toElement();
377 continue;
378 }
379
380 QDomElement matchingElement = findMatchingElement( e, additive );
381
382 QDomElement currElement = e;
383 e = e.nextSibling().toElement();
384
385 if ( !matchingElement.isNull() )
386 {
387 matchingElement.setAttribute( attrAlreadyVisited, (uint)1 );
388
389 if ( mergeXML( currElement, matchingElement, actionCollection ) )
390 {
391 base.removeChild( currElement );
392 continue;
393 }
394
395 // Merge attributes
396 QDomNamedNodeMap attribs = matchingElement.attributes();
397 for(uint i = 0; i < attribs.count(); i++)
398 {
399 QDomNode node = attribs.item(i);
400 currElement.setAttribute(node.nodeName(), node.nodeValue());
401 }
402
403 continue;
404 }
405 else
406 {
407 // this is an important case here! We reach this point if the
408 // "local" tree does not contain a container definition for
409 // this container. However we have to call mergeXML recursively
410 // and make it check if there are actions implemented for this
411 // container. *If* none, then we can remove this container now
412 if ( mergeXML( currElement, QDomElement(), actionCollection ) )
413 base.removeChild( currElement );
414 continue;
415 }
416 }
417
418 //I think this can be removed ;-)
419 e = e.nextSibling().toElement();
420 }
421
422 //here we append all child elements which were not inserted
423 //previously via the LocalMerge tag
424 e = additive.firstChild().toElement();
425 while ( !e.isNull() )
426 {
427 QDomElement matchingElement = findMatchingElement( e, base );
428
429 if ( matchingElement.isNull() )
430 {
431 QDomElement newChild = e;
432 e = e.nextSibling().toElement();
433 base.appendChild( newChild );
434 }
435 else
436 e = e.nextSibling().toElement();
437 }
438
439 // do one quick check to make sure that the last element was not
440 // a weak separator
441 QDomElement last = base.lastChild().toElement();
442 if ( (last.tagName() == tagSeparator) && (!last.attribute( attrWeakSeparator ).isNull()) )
443 {
444 base.removeChild( base.lastChild() );
445 }
446
447 // now we check if we are empty (in which case we return "true", to
448 // indicate the caller that it can delete "us" (the base element
449 // argument of "this" call)
450 bool deleteMe = true;
451 e = base.firstChild().toElement();
452 for ( ; !e.isNull(); e = e.nextSibling().toElement() )
453 {
454 tag = e.tagName();
455
456 if ( tag == tagAction )
457 {
458 // if base contains an implemented action, then we must not get
459 // deleted (note that the actionCollection contains both,
460 // "global" and "local" actions
461 if ( actionCollection->action( e.attribute( attrName ).utf8() ) )
462 {
463 deleteMe = false;
464 break;
465 }
466 }
467 else if ( tag == tagSeparator )
468 {
469 // if we have a separator which has *not* the weak attribute
470 // set, then it must be owned by the "local" tree in which case
471 // we must not get deleted either
472 QString weakAttr = e.attribute( attrWeakSeparator );
473 if ( weakAttr.isEmpty() || weakAttr.toInt() != 1 )
474 {
475 deleteMe = false;
476 break;
477 }
478 }
479
480 // in case of a merge tag we have unlimited lives, too ;-)
481 else if ( tag == tagMerge )
482 {
483// deleteMe = false;
484// break;
485 continue;
486 }
487
488 // a text tag is NOT enough to spare this container
489 else if ( tag == tagText )
490 {
491 continue;
492 }
493
494 // what's left are non-empty containers! *don't* delete us in this
495 // case (at this position we can be *sure* that the container is
496 // *not* empty, as the recursive call for it was in the first loop
497 // which deleted the element in case the call returned "true"
498 else
499 {
500 deleteMe = false;
501 break;
502 }
503 }
504
505 return deleteMe;
506}
507
508QDomElement KXMLGUIClient::findMatchingElement( const QDomElement &base, const QDomElement &additive )
509{
510 static const QString &tagAction = KGlobal::staticQString( "Action" );
511 static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" );
512 static const QString &attrName = KGlobal::staticQString( "name" );
513
514 QDomElement e = additive.firstChild().toElement();
515 for ( ; !e.isNull(); e = e.nextSibling().toElement() )
516 {
517 // skip all action and merge tags as we will never use them
518 if ( ( e.tagName() == tagAction ) || ( e.tagName() == tagMergeLocal ) )
519 {
520 continue;
521 }
522
523 // now see if our tags are equivalent
524 if ( ( e.tagName() == base.tagName() ) &&
525 ( e.attribute( attrName ) == base.attribute( attrName ) ) )
526 {
527 return e;
528 }
529 }
530
531 // nope, return a (now) null element
532 return e;
533}
534
535void KXMLGUIClient::conserveMemory()
536{
537 d->m_doc = QDomDocument();
538 d->m_buildDocument = QDomDocument();
539}
540
541void KXMLGUIClient::setXMLGUIBuildDocument( const QDomDocument &doc )
542{
543 d->m_buildDocument = doc;
544}
545
546QDomDocument KXMLGUIClient::xmlguiBuildDocument() const
547{
548 return d->m_buildDocument;
549}
550*/
551
552/*US
553void KXMLGUIClient::setFactory( KXMLGUIFactory *factory )
554{
555 d->m_factory = factory;
556}
557
558KXMLGUIFactory *KXMLGUIClient::factory() const
559{
560 return d->m_factory;
561}
562*/
563KXMLGUIClient *KXMLGUIClient::parentClient() const
564{
565 return d->m_parent;
566}
567
568void KXMLGUIClient::insertChildClient( KXMLGUIClient *child )
569{
570 if ( child->d->m_parent )
571 child->d->m_parent->removeChildClient( child );
572 d->m_children.append( child );
573 child->d->m_parent = this;
574}
575
576void KXMLGUIClient::removeChildClient( KXMLGUIClient *child )
577{
578 assert( d->m_children.containsRef( child ) );
579 d->m_children.removeRef( child );
580 child->d->m_parent = 0;
581}
582
583/*bool KXMLGUIClient::addSuperClient( KXMLGUIClient *super )
584{
585 if ( d->m_supers.contains( super ) )
586 return false;
587 d->m_supers.append( super );
588 return true;
589}*/
590
591const QPtrList<KXMLGUIClient> *KXMLGUIClient::childClients()
592{
593 return &d->m_children;
594}
595/*US
596void KXMLGUIClient::setClientBuilder( KXMLGUIBuilder *builder )
597{
598 d->m_builder = builder;
599 if ( builder )
600 builder->setBuilderInstance( instance() );
601}
602
603KXMLGUIBuilder *KXMLGUIClient::clientBuilder() const
604{
605 return d->m_builder;
606}
607*/
608
609void KXMLGUIClient::plugActionList( const QString &name, const QPtrList<KAction> &actionList )
610{
611/*US
612 if ( !d->m_factory )
613 return;
614
615 d->m_factory->plugActionList( this, name, actionList );
616*/
617}
618
619void KXMLGUIClient::unplugActionList( const QString &name )
620{
621/*US
622 if ( !d->m_factory )
623 return;
624
625 d->m_factory->unplugActionList( this, name );
626*/
627}
628
629/*US
630QString KXMLGUIClient::findMostRecentXMLFile( const QStringList &files, QString &doc )
631{
632
633 QValueList<DocStruct> allDocuments;
634
635 QStringList::ConstIterator it = files.begin();
636 QStringList::ConstIterator end = files.end();
637 for (; it != end; ++it )
638 {
639 //kdDebug() << "KXMLGUIClient::findMostRecentXMLFile " << *it << endl;
640 QString data = KXMLGUIFactory::readConfigFile( *it );
641 DocStruct d;
642 d.file = *it;
643 d.data = data;
644 allDocuments.append( d );
645 }
646
647 QValueList<DocStruct>::Iterator best = allDocuments.end();
648 uint bestVersion = 0;
649
650 QValueList<DocStruct>::Iterator docIt = allDocuments.begin();
651 QValueList<DocStruct>::Iterator docEnd = allDocuments.end();
652 for (; docIt != docEnd; ++docIt )
653 {
654 QString versionStr = findVersionNumber( (*docIt).data );
655 if ( versionStr.isEmpty() )
656 continue;
657
658 bool ok = false;
659 uint version = versionStr.toUInt( &ok );
660 if ( !ok )
661 continue;
662 //kdDebug() << "FOUND VERSION " << version << endl;
663
664 if ( version > bestVersion )
665 {
666 best = docIt;
667 //kdDebug() << "best version is now " << version << endl;
668 bestVersion = version;
669 }
670 }
671
672 if ( best != docEnd )
673 {
674 if ( best != allDocuments.begin() )
675 {
676 QValueList<DocStruct>::Iterator local = allDocuments.begin();
677
678 // load the local document and extract the action properties
679 QDomDocument document;
680 document.setContent( (*local).data );
681
682 ActionPropertiesMap properties = extractActionProperties( document );
683
684 // in case the document has a ActionProperties section
685 // we must not delete it but copy over the global doc
686 // to the local and insert the ActionProperties section
687 if ( !properties.isEmpty() )
688 {
689 // now load the global one with the higher version number
690 // into memory
691 document.setContent( (*best).data );
692 // and store the properties in there
693 storeActionProperties( document, properties );
694
695 (*local).data = document.toString();
696 // make sure we pick up the new local doc, when we return later
697 best = local;
698
699 // write out the new version of the local document
700 QFile f( (*local).file );
701 if ( f.open( IO_WriteOnly ) )
702 {
703 QCString utf8data = (*local).data.utf8();
704 f.writeBlock( utf8data.data(), utf8data.length() );
705 f.close();
706 }
707 }
708 else
709 {
710 QString f = (*local).file;
711 QString backup = f + QString::fromLatin1( ".backup" );
712 QDir dir;
713 dir.rename( f, backup );
714 }
715 }
716 doc = (*best).data;
717 return (*best).file;
718 }
719 else if ( files.count() > 0 )
720 {
721 //kdDebug() << "returning first one..." << endl;
722 doc = (*allDocuments.begin()).data;
723 return (*allDocuments.begin()).file;
724 }
725
726 return QString::null;
727}
728
729
730
731QString KXMLGUIClient::findVersionNumber( const QString &xml )
732{
733 enum { ST_START, ST_AFTER_OPEN, ST_AFTER_GUI,
734 ST_EXPECT_VERSION, ST_VERSION_NUM} state = ST_START;
735 for (unsigned int pos = 0; pos < xml.length(); pos++)
736 {
737 switch (state)
738 {
739 case ST_START:
740 if (xml[pos] == '<')
741 state = ST_AFTER_OPEN;
742 break;
743 case ST_AFTER_OPEN:
744 {
745 //Jump to gui..
746 int guipos = xml.find("gui", pos, false);
747 if (guipos == -1)
748 return QString::null; //Reject
749
750 pos = guipos + 2; //Position at i, so we're moved ahead to the next character by the ++;
751 state = ST_AFTER_GUI;
752 break;
753 }
754 case ST_AFTER_GUI:
755 state = ST_EXPECT_VERSION;
756 break;
757 case ST_EXPECT_VERSION:
758 {
759 int verpos = xml.find("version=\"", pos, false );
760 if (verpos == -1)
761 return QString::null; //Reject
762
763 pos = verpos + 8; //v = 0, e = +1, r = +2, s = +3 , i = +4, o = +5, n = +6, = = +7, " = + 8
764 state = ST_VERSION_NUM;
765 break;
766 }
767 case ST_VERSION_NUM:
768 {
769 unsigned int endpos;
770 for (endpos = pos; endpos < xml.length(); endpos++)
771 {
772 if (xml[endpos].unicode() >= '0' && xml[endpos].unicode() <= '9')
773 continue; //Number..
774 if (xml[endpos].unicode() == '"') //End of parameter
775 break;
776 else //This shouldn't be here..
777 {
778 endpos = xml.length();
779 }
780 }
781
782 if (endpos != pos && endpos < xml.length() )
783 {
784 QString matchCandidate = xml.mid(pos, endpos - pos); //Don't include " ".
785 return matchCandidate;
786 }
787
788 state = ST_EXPECT_VERSION; //Try to match a well-formed version..
789 break;
790 } //case..
791 } //switch
792 } //for
793
794 return QString::null;
795}
796
797KXMLGUIClient::ActionPropertiesMap KXMLGUIClient::extractActionProperties( const QDomDocument &doc )
798{
799 ActionPropertiesMap properties;
800
801 QDomElement actionPropElement = doc.documentElement().namedItem( "ActionProperties" ).toElement();
802
803 if ( actionPropElement.isNull() )
804 return properties;
805
806 QDomNode n = actionPropElement.firstChild();
807 for (; !n.isNull(); n = n.nextSibling() )
808 {
809 QDomElement e = n.toElement();
810 if ( e.isNull() )
811 continue;
812
813 if ( e.tagName().lower() != "action" )
814 continue;
815
816 QString actionName = e.attribute( "name" );
817
818 if ( actionName.isEmpty() )
819 continue;
820
821 QMap<QString, QMap<QString, QString> >::Iterator propIt = properties.find( actionName );
822 if ( propIt == properties.end() )
823 propIt = properties.insert( actionName, QMap<QString, QString>() );
824
825 QDomNamedNodeMap attributes = e.attributes();
826 for ( uint i = 0; i < attributes.length(); ++i )
827 {
828 QDomAttr attr = attributes.item( i ).toAttr();
829
830 if ( attr.isNull() )
831 continue;
832
833 QString name = attr.name();
834
835 if ( name == "name" || name.isEmpty() )
836 continue;
837
838 (*propIt)[ name ] = attr.value();
839 }
840
841 }
842
843 return properties;
844}
845
846void KXMLGUIClient::storeActionProperties( QDomDocument &doc, const ActionPropertiesMap &properties )
847{
848 QDomElement actionPropElement = doc.documentElement().namedItem( "ActionProperties" ).toElement();
849
850 if ( actionPropElement.isNull() )
851 {
852 actionPropElement = doc.createElement( "ActionProperties" );
853 doc.documentElement().appendChild( actionPropElement );
854 }
855
856 while ( !actionPropElement.firstChild().isNull() )
857 actionPropElement.removeChild( actionPropElement.firstChild() );
858
859 ActionPropertiesMap::ConstIterator it = properties.begin();
860 ActionPropertiesMap::ConstIterator end = properties.end();
861 for (; it != end; ++it )
862 {
863 QDomElement action = doc.createElement( "Action" );
864 action.setAttribute( "name", it.key() );
865 actionPropElement.appendChild( action );
866
867 QMap<QString, QString> attributes = (*it);
868 QMap<QString, QString>::ConstIterator attrIt = attributes.begin();
869 QMap<QString, QString>::ConstIterator attrEnd = attributes.end();
870 for (; attrIt != attrEnd; ++attrIt )
871 action.setAttribute( attrIt.key(), attrIt.data() );
872 }
873}
874*/
875
876void KXMLGUIClient::addStateActionEnabled(const QString& state,
877 const QString& action)
878{
879 StateChange stateChange = getActionsToChangeForState(state);
880
881 stateChange.actionsToEnable.append( action );
882 //kdDebug() << "KXMLGUIClient::addStateActionEnabled( " << state << ", " << action << ")" << endl;
883
884 m_actionsStateMap.replace( state, stateChange );
885}
886
887
888void KXMLGUIClient::addStateActionDisabled(const QString& state,
889 const QString& action)
890{
891 StateChange stateChange = getActionsToChangeForState(state);
892
893 stateChange.actionsToDisable.append( action );
894 //kdDebug() << "KXMLGUIClient::addStateActionDisabled( " << state << ", " << action << ")" << endl;
895
896 m_actionsStateMap.replace( state, stateChange );
897}
898
899
900KXMLGUIClient::StateChange KXMLGUIClient::getActionsToChangeForState(const QString& state)
901{
902 return m_actionsStateMap[state];
903}
904
905
906void KXMLGUIClient::stateChanged(const QString &newstate, KXMLGUIClient::ReverseStateChange reverse)
907{
908 StateChange stateChange = getActionsToChangeForState(newstate);
909
910 bool setTrue = (reverse == StateNoReverse);
911 bool setFalse = !setTrue;
912
913 // Enable actions which need to be enabled...
914 //
915 for ( QStringList::Iterator it = stateChange.actionsToEnable.begin();
916 it != stateChange.actionsToEnable.end(); ++it ) {
917
918 KAction *action = actionCollection()->action((*it).latin1());
919 if (action) action->setEnabled(setTrue);
920 }
921
922 // and disable actions which need to be disabled...
923 //
924 for ( QStringList::Iterator it = stateChange.actionsToDisable.begin();
925 it != stateChange.actionsToDisable.end(); ++it ) {
926
927 KAction *action = actionCollection()->action((*it).latin1());
928 if (action) action->setEnabled(setFalse);
929 }
930
931}
932/*US
933void KXMLGUIClient::beginXMLPlug( QWidget *w )
934{
935 actionCollection()->beginXMLPlug( w );
936 QPtrListIterator<KXMLGUIClient> childIt( d->m_children );
937 for (; childIt.current(); ++childIt )
938 childIt.current()->actionCollection()->beginXMLPlug( w );
939}
940
941void KXMLGUIClient::endXMLPlug()
942{
943 actionCollection()->endXMLPlug();
944 QPtrListIterator<KXMLGUIClient> childIt( d->m_children );
945 for (; childIt.current(); ++childIt )
946 childIt.current()->actionCollection()->endXMLPlug();
947}
948
949void KXMLGUIClient::prepareXMLUnplug( QWidget * )
950{
951 actionCollection()->prepareXMLUnplug();
952 QPtrListIterator<KXMLGUIClient> childIt( d->m_children );
953 for (; childIt.current(); ++childIt )
954 childIt.current()->actionCollection()->prepareXMLUnplug();
955}
956*/
957void KXMLGUIClient::virtual_hook( int, void* )
958{ /*BASE::virtual_hook( id, data );*/ }