Krita Source Code Documentation
Loading...
Searching...
No Matches
kxmlguiclient.cpp
Go to the documentation of this file.
1/* This file is part of the KDE libraries
2 SPDX-FileCopyrightText: 2000 Simon Hausmann <hausmann@kde.org>
3 SPDX-FileCopyrightText: 2000 Kurt Granroth <granroth@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-only
6*/
7
8#include "kxmlguiclient.h"
9
11#include "kxmlguifactory.h"
12#include "kxmlguibuilder.h"
13#include "kactioncollection.h"
14
15#include <QAction>
16#include <QDir>
17#include <QFile>
18#include <QDomDocument>
19#include <QRegExp>
20#include <QPointer>
21#include <QCoreApplication>
22#include <QStandardPaths>
23#include <QDebug>
24
25#include <klocalizedstring.h>
26
27#include <assert.h>
28
29#if defined(KCONFIG_BEFORE_5_24)
30# define authorizeAction authorizeKAction
31#endif
32
34{
35public:
37 : m_componentName(QCoreApplication::applicationName()),
39 m_parent(0L),
40 m_builder(0L)
41 {
42 m_textTagNames.append(QLatin1String("text"));
43 m_textTagNames.append(QLatin1String("Text"));
44 m_textTagNames.append(QLatin1String("title"));
45 }
49
50 bool mergeXML(QDomElement &base, QDomElement &additive,
51 KisKActionCollection *actionCollection);
52 bool isEmptyContainer(const QDomElement &base,
53 KisKActionCollection *actionCollection) const;
54
55 QDomElement findMatchingElement(const QDomElement &base,
56 const QDomElement &additive);
57
59
60 QDomDocument m_doc;
62 QDomDocument m_buildDocument;
65 //QPtrList<KisKXMLGUIClient> m_supers;
68 QString m_xmlFile;
71
72 // Actions to enable/disable on a state change
73 QMap<QString, KisKXMLGUIClient::StateChange> m_actionsStateMap;
74};
75
80
83{
84 parent->insertChildClient(this);
85}
86
88{
89 if (d->m_parent) {
91 }
92
93 if (d->m_factory) {
94 qWarning() << this << "deleted without having been removed from the factory first. This will leak standalone popupmenus and could lead to crashes.";
95 d->m_factory->forgetClient(this);
96 }
97
98 Q_FOREACH (KisKXMLGUIClient *client, d->m_children) {
99 if (d->m_factory) {
100 d->m_factory->forgetClient(client);
101 }
102 assert(client->d->m_parent == this);
103 client->d->m_parent = 0;
104 }
105
106 delete d->m_actionCollection;
107 delete d;
108}
109
110QAction *KisKXMLGUIClient::action(const char *name) const
111{
112 QAction *act = actionCollection()->action(QLatin1String(name));
113 if (!act) {
114 Q_FOREACH (KisKXMLGUIClient *client, d->m_children) {
115 act = client->actionCollection()->action(QLatin1String(name));
116 if (act) {
117 break;
118 }
119 }
120 }
121 return act;
122}
123
125{
126 if (!d->m_actionCollection) {
128 d->m_actionCollection->setObjectName(QStringLiteral("KisKXMLGUIClient-KisKActionCollection"));
129 }
130 return d->m_actionCollection;
131}
132
133QAction *KisKXMLGUIClient::action(const QDomElement &element) const
134{
135 return actionCollection()->action(element.attribute(QStringLiteral("name")));
136}
137
139{
140 return d->m_componentName;
141}
142
144{
145 return d->m_doc;
146}
147
149{
150 return d->m_xmlFile;
151}
152
154{
155 if (!d->m_localXMLFile.isEmpty()) {
156 return d->m_localXMLFile;
157 }
158
159 if (!QDir::isRelativePath(d->m_xmlFile)) {
160 return QString(); // can't save anything here
161 }
162
163 if (d->m_xmlFile.isEmpty()) { // setXMLFile not called at all, can't save. Use case: ToolBarHandler
164 return QString();
165 }
166
167 return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/kxmlgui5/") +
168 componentName() + QLatin1Char('/') + d->m_xmlFile;
169}
170
172{
173 // TODO: this method can't be used for the KXmlGuiWindow, since it doesn't merge in ui_standards.xmlgui!
174 // -> KDE5: load ui_standards_rc in setXMLFile using a flag, and remember that flag?
175 // and then KisKEditToolBar can use reloadXML.
176 QString file(xmlFile());
177 if (!file.isEmpty()) {
178 setXMLFile(file);
179 }
180}
181
182void KisKXMLGUIClient::setComponentName(const QString &componentName, const QString &componentDisplayName)
183{
186 actionCollection()->setComponentDisplayName(componentDisplayName);
187 if (d->m_builder) {
189 }
190}
191
193{
194 QString file = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QStringLiteral("ui/ui_standards.xmlgui"));
195 if (file.isEmpty()) {
196 // fallback to resource, to allow to use the rc file compiled into this framework, must exist!
197 file = QStringLiteral(":/kxmlgui5/ui_standards.xmlgui");
198 Q_ASSERT(QFile::exists(file));
199 }
200 return file;
201}
202
207
208void KisKXMLGUIClient::setXMLFile(const QString &_file, bool merge, bool setXMLDoc)
209{
210 // store our xml file name
211 if (!_file.isNull()) {
212 d->m_xmlFile = _file;
213 }
214
215 if (!setXMLDoc) {
216 return;
217 }
218
219 QString file = _file;
220 QStringList allFiles;
221 if (!QDir::isRelativePath(file)) {
222 allFiles.append(file);
223 } else {
224 const QString filter = componentName() + QLatin1Char('/') + _file;
225
226 // files on filesystem
227 allFiles << QStandardPaths::locateAll(QStandardPaths::AppDataLocation, QStringLiteral("kxmlgui5/") + filter); // KF >= 5.1
228
229 // KF >= 5.4 (resource file)
230 const QString qrcFile(QStringLiteral(":/kxmlgui5/") + filter);
231 if (QFile::exists(qrcFile)) {
232 allFiles << qrcFile;
233 }
234
235 // then compat locations
236 const QStringList compatFiles =
237 QStandardPaths::locateAll(QStandardPaths::AppDataLocation, filter) + // kdelibs4, KF 5.0
238 QStandardPaths::locateAll(QStandardPaths::AppDataLocation, _file); // kdelibs4, KF 5.0, caller passes component name
239
240 if (allFiles.isEmpty() && !compatFiles.isEmpty()) {
241 qWarning() << "kxmlguiclient: KisKXMLGUI file found at deprecated location" << compatFiles << "-- please use ${KisKXMLGUI_INSTALL_DIR} to install this file instead.";
242 }
243 allFiles += compatFiles;
244 }
245 if (allFiles.isEmpty() && !_file.isEmpty()) {
246 // if a non-empty file gets passed and we can't find it,
247 // inform the developer using some debug output
248 qWarning() << "cannot find .xmlgui file" << _file << "for component" << componentName();
249 }
250
251 // make sure to merge the settings from any file specified by setLocalXMLFile()
252 if (!d->m_localXMLFile.isEmpty() && !file.endsWith(QStringLiteral("ui_standards.xmlgui"))) {
253 const bool exists = QDir::isRelativePath(d->m_localXMLFile) || QFile::exists(d->m_localXMLFile);
254 if (exists && !allFiles.contains(d->m_localXMLFile)) {
255 allFiles.prepend(d->m_localXMLFile);
256 }
257 }
258
259 QString doc;
260 if (!allFiles.isEmpty()) {
261 file = findMostRecentXMLFile(allFiles, doc);
262 }
263
264 // Always call setXML, even on error, so that we don't keep all ui_standards.xmlgui menus.
265 setXML(doc, merge);
266}
267
268void KisKXMLGUIClient::setLocalXMLFile(const QString &file)
269{
270 d->m_localXMLFile = file;
271}
272
273void KisKXMLGUIClient::replaceXMLFile(const QString &xmlfile, const QString &localxmlfile, bool merge)
274{
275 if (!QDir::isAbsolutePath(xmlfile)) {
276 qWarning() << "xml file" << xmlfile << "is not an absolute path";
277 }
278
279 setLocalXMLFile(localxmlfile);
280 setXMLFile(xmlfile, merge);
281}
282
283// The top document element may have translation domain attribute set,
284// or the translation domain may be implicitly the application domain.
285// This domain must be used to fetch translations for all text elements
286// in the document that do not have their own domain attribute.
287// In order to preserve this semantics through document mergings,
288// the top or application domain must be propagated to all text elements
289// lacking their own domain attribute.
290static void propagateTranslationDomain(QDomDocument &doc, const QStringList tagNames)
291{
292 const QLatin1String attrDomain("translationDomain");
293 QDomElement base = doc.documentElement();
294 QString domain = base.attribute(attrDomain);
295 if (domain.isEmpty()) {
296 domain = QString::fromUtf8(KLocalizedString::applicationDomain());
297 if (domain.isEmpty()) {
298 return;
299 }
300 }
301 foreach (const QString &tagName, tagNames) {
302 QDomNodeList textNodes = base.elementsByTagName(tagName);
303 for (int i = 0; i < textNodes.length(); ++i) {
304 QDomElement e = textNodes.item(i).toElement();
305 QString localDomain = e.attribute(attrDomain);
306 if (localDomain.isEmpty()) {
307 e.setAttribute(attrDomain, domain);
308 }
309 }
310 }
311}
312
313void KisKXMLGUIClient::setXML(const QString &document, bool merge)
314{
315 QDomDocument doc;
316 QString errorMsg;
317 int errorLine, errorColumn;
318 // QDomDocument raises a parse error on empty document, but we accept no app-specific document,
319 // in which case you only get ui_standards.xmlgui layout.
320 bool result = document.isEmpty() || doc.setContent(document, &errorMsg, &errorLine, &errorColumn);
321 if (result) {
323 setDOMDocument(doc, merge);
324 } else {
325#ifdef NDEBUG
326 qCritical() << "Error parsing XML document:" << errorMsg << "at line" << errorLine << "column" << errorColumn;
327 setDOMDocument(QDomDocument(), merge); // otherwise empty menus from ui_standards.xmlgui stay around
328#else
329 qCritical() << "Error parsing XML document:" << errorMsg << "at line" << errorLine << "column" << errorColumn;
330 abort();
331#endif
332 }
333}
334
335void KisKXMLGUIClient::setDOMDocument(const QDomDocument &document, bool merge)
336{
337 if (merge && !d->m_doc.isNull()) {
338 QDomElement base = d->m_doc.documentElement();
339
340 QDomElement e = document.documentElement();
341
342 // merge our original (global) xml with our new one
343 d->mergeXML(base, e, actionCollection());
344
345 // reassign our pointer as mergeXML might have done something
346 // strange to it
347 base = d->m_doc.documentElement();
348
349 //qDebug(260) << "Result of xmlgui merging:" << d->m_doc.toString();
350
351 // we want some sort of failsafe.. just in case
352 if (base.isNull()) {
353 d->m_doc = document;
354 }
355 } else {
356 d->m_doc = document;
357 }
358
359 setXMLGUIBuildDocument(QDomDocument());
360}
361
362// if (equals(a,b)) is more readable than if (a.compare(b, Qt::CaseInsensitive)==0)
363static inline bool equalstr(const QString &a, const QString &b)
364{
365 return a.compare(b, Qt::CaseInsensitive) == 0;
366}
367static inline bool equalstr(const QString &a, const QLatin1String &b)
368{
369 return a.compare(b, Qt::CaseInsensitive) == 0;
370}
371
372bool KisKXMLGUIClientPrivate::mergeXML(QDomElement &base, QDomElement &additive, KisKActionCollection *actionCollection)
373{
374 const QLatin1String tagAction("Action");
375 const QLatin1String tagMerge("Merge");
376 const QLatin1String tagSeparator("Separator");
377 const QLatin1String tagMergeLocal("MergeLocal");
378 const QLatin1String tagText("text");
379 const QLatin1String attrAppend("append");
380 const QString attrName(QStringLiteral("name"));
381 const QString attrWeakSeparator(QStringLiteral("weakSeparator"));
382 const QString attrAlreadyVisited(QStringLiteral("alreadyVisited"));
383 const QString attrNoMerge(QStringLiteral("noMerge"));
384 const QLatin1String attrOne("1");
385
386 // there is a possibility that we don't want to merge in the
387 // additive.. rather, we might want to *replace* the base with the
388 // additive. this can be for any container.. either at a file wide
389 // level or a simple container level. we look for the 'noMerge'
390 // tag, in any event and just replace the old with the new
391 if (additive.attribute(attrNoMerge) == attrOne) { // ### use toInt() instead? (Simon)
392 base.parentNode().replaceChild(additive, base);
393 return true;
394 } else {
395 // Merge attributes
396 {
397 const QDomNamedNodeMap attribs = additive.attributes();
398 const uint attribcount = attribs.count();
399
400 for (uint i = 0; i < attribcount; ++i) {
401 const QDomNode node = attribs.item(i);
402 base.setAttribute(node.nodeName(), node.nodeValue());
403 }
404 }
405
406 // iterate over all elements in the container (of the global DOM tree)
407 QDomNode n = base.firstChild();
408 while (!n.isNull()) {
409 QDomElement e = n.toElement();
410 n = n.nextSibling(); // Advance now so that we can safely delete e
411 if (e.isNull()) {
412 continue;
413 }
414
415 const QString tag = e.tagName();
416
417 // if there's an action tag in the global tree and the action is
418 // not implemented, then we remove the element
419 if (equalstr(tag, tagAction)) {
420 const QString name = e.attribute(attrName);
421 if (!actionCollection->action(name)) {
422 // remove this child as we aren't using it
423 base.removeChild(e);
424 continue;
425 }
426 }
427
428 // if there's a separator defined in the global tree, then add an
429 // attribute, specifying that this is a "weak" separator
430 else if (equalstr(tag, tagSeparator)) {
431 e.setAttribute(attrWeakSeparator, (uint)1);
432
433 // okay, hack time. if the last item was a weak separator OR
434 // this is the first item in a container, then we nuke the
435 // current one
436 QDomElement prev = e.previousSibling().toElement();
437 if (prev.isNull() ||
438 (equalstr(prev.tagName(), tagSeparator) && !prev.attribute(attrWeakSeparator).isNull()) ||
439 (equalstr(prev.tagName(), tagText))) {
440 // the previous element was a weak separator or didn't exist
441 base.removeChild(e);
442 continue;
443 }
444 }
445
446 // the MergeLocal tag lets us specify where non-standard elements
447 // of the local tree shall be merged in. After inserting the
448 // elements we delete this element
449 else if (equalstr(tag, tagMergeLocal)) {
450 QDomNode it = additive.firstChild();
451 while (!it.isNull()) {
452 QDomElement newChild = it.toElement();
453 it = it.nextSibling();
454 if (newChild.isNull()) {
455 continue;
456 }
457
458 if (equalstr(newChild.tagName(), tagText)) {
459 continue;
460 }
461
462 if (newChild.attribute(attrAlreadyVisited) == attrOne) {
463 continue;
464 }
465
466 QString itAppend(newChild.attribute(attrAppend));
467 QString elemName(e.attribute(attrName));
468
469 if ((itAppend.isNull() && elemName.isEmpty()) ||
470 (itAppend == elemName)) {
471 // first, see if this new element matches a standard one in
472 // the global file. if it does, then we skip it as it will
473 // be merged in, later
474 QDomElement matchingElement = findMatchingElement(newChild, base);
475 if (matchingElement.isNull() || equalstr(newChild.tagName(), tagSeparator)) {
476 base.insertBefore(newChild, e);
477 }
478 }
479 }
480
481 base.removeChild(e);
482 continue;
483 }
484
485 else if (equalstr(tag, tagText)) {
486 continue;
487 } else if (equalstr(tag, tagMerge)) {
488 continue;
489 }
490
491 // in this last case we check for a separator tag and, if not, we
492 // can be sure that it is a container --> proceed with child nodes
493 // recursively and delete the just proceeded container item in
494 // case it is empty (if the recursive call returns true)
495 else {
496 QDomElement matchingElement = findMatchingElement(e, additive);
497 if (!matchingElement.isNull()) {
498 matchingElement.setAttribute(attrAlreadyVisited, (uint)1);
499
500 if (mergeXML(e, matchingElement, actionCollection)) {
501 base.removeChild(e);
502 additive.removeChild(matchingElement); // make sure we don't append it below
503 continue;
504 }
505
506 continue;
507 } else {
508 // this is an important case here! We reach this point if the
509 // "local" tree does not contain a container definition for
510 // this container. However we have to call mergeXML recursively
511 // and make it check if there are actions implemented for this
512 // container. *If* none, then we can remove this container now
513 QDomElement dummy;
514 if (mergeXML(e, dummy, actionCollection)) {
515 base.removeChild(e);
516 }
517 continue;
518 }
519 }
520 }
521
522 //here we append all child elements which were not inserted
523 //previously via the LocalMerge tag
524 n = additive.firstChild();
525 while (!n.isNull()) {
526 QDomElement e = n.toElement();
527 n = n.nextSibling(); // Advance now so that we can safely delete e
528 if (e.isNull()) {
529 continue;
530 }
531
532 QDomElement matchingElement = findMatchingElement(e, base);
533
534 if (matchingElement.isNull()) {
535 base.appendChild(e);
536 }
537 }
538
539 // do one quick check to make sure that the last element was not
540 // a weak separator
541 QDomElement last = base.lastChild().toElement();
542 if (equalstr(last.tagName(), tagSeparator) &&
543 (!last.attribute(attrWeakSeparator).isNull())) {
544 base.removeChild(last);
545 }
546 }
547
548 return isEmptyContainer(base, actionCollection);
549}
550
551bool KisKXMLGUIClientPrivate::isEmptyContainer(const QDomElement &base, KisKActionCollection *actionCollection) const
552{
553 // now we check if we are empty (in which case we return "true", to
554 // indicate the caller that it can delete "us" (the base element
555 // argument of "this" call)
556 QDomNode n = base.firstChild();
557 while (!n.isNull()) {
558 const QDomElement e = n.toElement();
559 n = n.nextSibling(); // Advance now so that we can safely delete e
560 if (e.isNull()) {
561 continue;
562 }
563
564 const QString tag = e.tagName();
565
566 if (equalstr(tag, QLatin1String("Action"))) {
567 // if base contains an implemented action, then we must not get
568 // deleted (note that the actionCollection contains both,
569 // "global" and "local" actions)
570 if (actionCollection->action(e.attribute(QStringLiteral("name")))) {
571 return false;
572 }
573 } else if (equalstr(tag, QLatin1String("Separator"))) {
574 // if we have a separator which has *not* the weak attribute
575 // set, then it must be owned by the "local" tree in which case
576 // we must not get deleted either
577 const QString weakAttr = e.attribute(QStringLiteral("weakSeparator"));
578 if (weakAttr.isEmpty() || weakAttr.toInt() != 1) {
579 return false;
580 }
581 }
582
583 else if (equalstr(tag, QLatin1String("merge"))) {
584 continue;
585 }
586
587 // a text tag is NOT enough to spare this container
588 else if (equalstr(tag, QLatin1String("text"))) {
589 continue;
590 }
591
592 // what's left are non-empty containers! *don't* delete us in this
593 // case (at this position we can be *sure* that the container is
594 // *not* empty, as the recursive call for it was in the first loop
595 // which deleted the element in case the call returned "true"
596 else {
597 return false;
598 }
599 }
600
601 return true; // I'm empty, please delete me.
602}
603
604QDomElement KisKXMLGUIClientPrivate::findMatchingElement(const QDomElement &base, const QDomElement &additive)
605{
606 QDomNode n = additive.firstChild();
607 while (!n.isNull()) {
608 QDomElement e = n.toElement();
609 n = n.nextSibling(); // Advance now so that we can safely delete e -- TODO we don't, so simplify this
610 if (e.isNull()) {
611 continue;
612 }
613
614 const QString tag = e.tagName();
615 // skip all action and merge tags as we will never use them
616 if (equalstr(tag, QLatin1String("Action"))
617 || equalstr(tag, QLatin1String("MergeLocal"))) {
618 continue;
619 }
620
621 // now see if our tags are equivalent
622 if (equalstr(tag, base.tagName()) &&
623 e.attribute(QStringLiteral("name")) == base.attribute(QStringLiteral("name"))) {
624 return e;
625 }
626 }
627
628 // nope, return a (now) null element
629 return QDomElement();
630}
631
632void KisKXMLGUIClient::setXMLGUIBuildDocument(const QDomDocument &doc)
633{
634 d->m_buildDocument = doc;
635}
636
638{
639 return d->m_buildDocument;
640}
641
646
651
656
658{
659 if (child->d->m_parent) {
660 child->d->m_parent->removeChildClient(child);
661 }
662 d->m_children.append(child);
663 child->d->m_parent = this;
664}
665
667{
668 assert(d->m_children.contains(child));
669 d->m_children.removeAll(child);
670 child->d->m_parent = 0;
671}
672
673/*bool KisKXMLGUIClient::addSuperClient( KisKXMLGUIClient *super )
674{
675 if ( d->m_supers.contains( super ) )
676 return false;
677 d->m_supers.append( super );
678 return true;
679}*/
680
685
687{
688 d->m_builder = builder;
689}
690
695
696void KisKXMLGUIClient::plugActionList(const QString &name, const QList<QAction *> &actionList)
697{
698 if (!d->m_factory) {
699 return;
700 }
701
702 d->m_factory->plugActionList(this, name, actionList);
703}
704
705void KisKXMLGUIClient::unplugActionList(const QString &name)
706{
707 if (!d->m_factory) {
708 return;
709 }
710
711 d->m_factory->unplugActionList(this, name);
712}
713
714QString KisKXMLGUIClient::findMostRecentXMLFile(const QStringList &files, QString &doc)
715{
716 KXmlGuiVersionHandler versionHandler(files);
717 doc = versionHandler.finalDocument();
718 return versionHandler.finalFile();
719}
720
722 const QString &action)
723{
724 StateChange stateChange = getActionsToChangeForState(state);
725
726 stateChange.actionsToEnable.append(action);
727 //qDebug(260) << "KisKXMLGUIClient::addStateActionEnabled( " << state << ", " << action << ")";
728
729 d->m_actionsStateMap.insert(state, stateChange);
730}
731
733 const QString &action)
734{
735 StateChange stateChange = getActionsToChangeForState(state);
736
737 stateChange.actionsToDisable.append(action);
738 //qDebug(260) << "KisKXMLGUIClient::addStateActionDisabled( " << state << ", " << action << ")";
739
740 d->m_actionsStateMap.insert(state, stateChange);
741}
742
747
749{
750 StateChange stateChange = getActionsToChangeForState(newstate);
751
752 bool setTrue = (reverse == StateNoReverse);
753 bool setFalse = !setTrue;
754
755 // Enable actions which need to be enabled...
756 //
757 for (QStringList::const_iterator it = stateChange.actionsToEnable.constBegin();
758 it != stateChange.actionsToEnable.constEnd(); ++it) {
759
760 QAction *action = actionCollection()->action(*it);
761 if (action) {
762 action->setEnabled(setTrue);
763 }
764 }
765
766 // and disable actions which need to be disabled...
767 //
768 for (QStringList::const_iterator it = stateChange.actionsToDisable.constBegin();
769 it != stateChange.actionsToDisable.constEnd(); ++it) {
770
771 QAction *action = actionCollection()->action(*it);
772 if (action) {
773 action->setEnabled(setFalse);
774 }
775 }
776
777}
778
780{
782 foreach (KisKXMLGUIClient *client, d->m_children) {
783 client->beginXMLPlug(w);
784 }
785}
786
790
792{
794 foreach (KisKXMLGUIClient *client, d->m_children) {
795 client->prepareXMLUnplug(w);
796 }
797}
798
800{
801 /*BASE::virtual_hook( id, data );*/
802}
unsigned int uint
A container for a set of QAction objects.
void setComponentDisplayName(const QString &displayName)
void removeAssociatedWidget(QWidget *widget)
void setComponentName(const QString &componentName)
QAction * action(int index) const
void addAssociatedWidget(QWidget *widget)
void setBuilderClient(KisKXMLGUIClient *client)
QList< KisKXMLGUIClient * > m_children
QMap< QString, KisKXMLGUIClient::StateChange > m_actionsStateMap
bool isEmptyContainer(const QDomElement &base, KisKActionCollection *actionCollection) const
bool mergeXML(QDomElement &base, QDomElement &additive, KisKActionCollection *actionCollection)
QDomElement findMatchingElement(const QDomElement &base, const QDomElement &additive)
KisKXMLGUIBuilder * m_builder
QPointer< KisKXMLGUIFactory > m_factory
KisKActionCollection * m_actionCollection
KisKXMLGUIClient * m_parent
void setFactory(KisKXMLGUIFactory *factory)
static QString findMostRecentXMLFile(const QStringList &files, QString &doc)
virtual void setComponentName(const QString &componentName, const QString &componentDisplayName)
KisKXMLGUIClientPrivate *const d
void beginXMLPlug(QWidget *)
QDomDocument xmlguiBuildDocument() const
void setXMLGUIBuildDocument(const QDomDocument &doc)
void setDOMDocument(const QDomDocument &document, bool merge=false)
KisKXMLGUIBuilder * clientBuilder() const
void setClientBuilder(KisKXMLGUIBuilder *builder)
virtual QString xmlFile() const
KisKXMLGUIClient * parentClient() const
StateChange getActionsToChangeForState(const QString &state)
virtual QDomDocument domDocument() const
void setLocalXMLFile(const QString &file)
QAction * action(const char *name) const
void unplugActionList(const QString &name)
static QString standardsXmlFileLocation()
void prepareXMLUnplug(QWidget *)
void addStateActionEnabled(const QString &state, const QString &action)
virtual void stateChanged(const QString &newstate, ReverseStateChange reverse=StateNoReverse)
virtual QString localXMLFile() const
void replaceXMLFile(const QString &xmlfile, const QString &localxmlfile, bool merge=false)
void removeChildClient(KisKXMLGUIClient *child)
virtual void virtual_hook(int id, void *data)
KisKXMLGUIFactory * factory() const
void setXMLFile(const QString &file, bool merge=false, bool setXMLDoc=true)
QList< KisKXMLGUIClient * > childClients()
void insertChildClient(KisKXMLGUIClient *child)
void setXML(const QString &document, bool merge=false)
virtual QString componentName() const
void plugActionList(const QString &name, const QList< QAction * > &actionList)
virtual KisKActionCollection * actionCollection() const
void addStateActionDisabled(const QString &state, const QString &action)
virtual ~KisKXMLGUIClient()
static QString readConfigFile(const QString &filename, const QString &componentName=QString())
static bool equalstr(const QString &a, const QString &b)
static void propagateTranslationDomain(QDomDocument &doc, const QStringList tagNames)