KXmlGui

kxmlguifactory.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 1999, 2000 Simon Hausmann <hausmann@kde.org>
4 SPDX-FileCopyrightText: 2000 Kurt Granroth <granroth@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#include "config-xmlgui.h"
10
11#include "kxmlguifactory.h"
12
13#include "debug.h"
14#include "kactioncollection.h"
15#include "kshortcutschemeshelper_p.h"
16#include "kshortcutsdialog.h"
17#include "kxmlguibuilder.h"
18#include "kxmlguiclient.h"
19#include "kxmlguifactory_p.h"
20
21#include <QAction>
22#include <QCoreApplication>
23#include <QDir>
24#include <QDomDocument>
25#include <QFile>
26#include <QStandardPaths>
27#include <QTextStream>
28#include <QVariant>
29#include <QWidget>
30
31#include <KConfigGroup>
32#include <KSharedConfig>
33#if HAVE_GLOBALACCEL
34#include <KGlobalAccel>
35#endif
36
37using namespace KXMLGUI;
38
39class KXMLGUIFactoryPrivate : public BuildState
40{
41public:
42 enum ShortcutOption { SetActiveShortcut = 1, SetDefaultShortcut = 2 };
43
44 KXMLGUIFactoryPrivate()
45 {
46 m_rootNode = new ContainerNode(nullptr, QString(), QString());
47 attrName = QStringLiteral("name");
48 }
49 ~KXMLGUIFactoryPrivate()
50 {
51 delete m_rootNode;
52 }
53
54 void pushState()
55 {
56 m_stateStack.push(*this);
57 }
58
59 void popState()
60 {
61 BuildState::operator=(m_stateStack.pop());
62 }
63
64 bool emptyState() const
65 {
66 return m_stateStack.isEmpty();
67 }
68
69 QWidget *findRecursive(KXMLGUI::ContainerNode *node, bool tag);
70 QList<QWidget *> findRecursive(KXMLGUI::ContainerNode *node, const QString &tagName);
71 void applyActionProperties(const QDomElement &element, ShortcutOption shortcutOption = KXMLGUIFactoryPrivate::SetActiveShortcut);
72 void configureAction(QAction *action, const QDomNamedNodeMap &attributes, ShortcutOption shortcutOption = KXMLGUIFactoryPrivate::SetActiveShortcut);
73 void configureAction(QAction *action, const QDomAttr &attribute, ShortcutOption shortcutOption = KXMLGUIFactoryPrivate::SetActiveShortcut);
74
75 void applyShortcutScheme(const QString &schemeName, KXMLGUIClient *client, const QList<QAction *> &actions);
76 void refreshActionProperties(KXMLGUIClient *client, const QList<QAction *> &actions, const QDomDocument &doc);
77 void saveDefaultActionProperties(const QList<QAction *> &actions);
78
79 ContainerNode *m_rootNode;
80
81 /*
82 * Contains the container which is searched for in ::container .
83 */
84 QString m_containerName;
85
86 /*
87 * List of all clients
88 */
89 QList<KXMLGUIClient *> m_clients;
90
91 QString attrName;
92
93 BuildStateStack m_stateStack;
94};
95
96QString KXMLGUIFactory::readConfigFile(const QString &filename, const QString &_componentName)
97{
98 QString componentName = _componentName.isEmpty() ? QCoreApplication::applicationName() : _componentName;
99 QString xml_file;
100
101 if (!QDir::isRelativePath(filename)) {
102 xml_file = filename;
103 } else {
104 // first look for any custom user config, admin config or the default deployed as file
105 xml_file = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("kxmlgui5/") + componentName + QLatin1Char('/') + filename);
106 if (!QFile::exists(xml_file)) {
107 // fall-back to any built-in resource file
108 xml_file = QLatin1String(":/kxmlgui5/") + componentName + QLatin1Char('/') + filename;
109 }
110 }
111
112 QFile file(xml_file);
113 if (xml_file.isEmpty() || !file.open(QIODevice::ReadOnly)) {
114 qCCritical(DEBUG_KXMLGUI) << "No such XML file" << filename;
115 return QString();
116 }
117
118 QByteArray buffer(file.readAll());
119 return QString::fromUtf8(buffer.constData(), buffer.size());
120}
121
122bool KXMLGUIFactory::saveConfigFile(const QDomDocument &doc, const QString &filename, const QString &_componentName)
123{
124 QString componentName = _componentName.isEmpty() ? QCoreApplication::applicationName() : _componentName;
125 QString xml_file(filename);
126
127 if (QDir::isRelativePath(xml_file)) {
128 xml_file = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kxmlgui5/%1/%2").arg(componentName, filename);
129 }
130
131 QFileInfo fileInfo(xml_file);
132 QDir().mkpath(fileInfo.absolutePath());
133 QFile file(xml_file);
134 if (xml_file.isEmpty() || !file.open(QIODevice::WriteOnly)) {
135 qCCritical(DEBUG_KXMLGUI) << "Could not write to" << filename;
136 return false;
137 }
138
139 // write out our document
140 QTextStream ts(&file);
141 ts << doc;
142
143 file.close();
144 return true;
145}
146
148 : QObject(parent)
149 , d(new KXMLGUIFactoryPrivate)
150{
151 Q_INIT_RESOURCE(kxmlgui);
152
153 d->builder = builder;
154 d->guiClient = nullptr;
155 if (d->builder) {
156 d->builderContainerTags = d->builder->containerTags();
157 d->builderCustomTags = d->builder->customTags();
158 }
159}
160
162{
163 for (KXMLGUIClient *client : std::as_const(d->m_clients)) {
164 client->setFactory(nullptr);
165 }
166}
167
169{
170 // qCDebug(DEBUG_KXMLGUI) << client;
171 if (client->factory()) {
172 if (client->factory() == this) {
173 return;
174 } else {
175 client->factory()->removeClient(client); // just in case someone does stupid things ;-)
176 }
177 }
178
179 if (d->emptyState()) {
180 Q_EMIT makingChanges(true);
181 }
182 d->pushState();
183
184 // QTime dt; dt.start();
185
186 d->guiClient = client;
187
188 // add this client to our client list
189 if (!d->m_clients.contains(client)) {
190 d->m_clients.append(client);
191 }
192 // else
193 // qCDebug(DEBUG_KXMLGUI) << "XMLGUI client already added " << client;
194
195 // Tell the client that plugging in is process and
196 // let it know what builder widget its mainwindow shortcuts
197 // should be attached to.
198 client->beginXMLPlug(d->builder->widget());
199
200 // try to use the build document for building the client's GUI, as the build document
201 // contains the correct container state information (like toolbar positions, sizes, etc.) .
202 // if there is non available, then use the "real" document.
203 QDomDocument doc = client->xmlguiBuildDocument();
204 if (doc.documentElement().isNull()) {
205 doc = client->domDocument();
206 }
207
208 QDomElement docElement = doc.documentElement();
209
210 d->m_rootNode->index = -1;
211
212 // cache some variables
213
214 d->clientName = docElement.attribute(d->attrName);
215 d->clientBuilder = client->clientBuilder();
216
217 if (d->clientBuilder) {
218 d->clientBuilderContainerTags = d->clientBuilder->containerTags();
219 d->clientBuilderCustomTags = d->clientBuilder->customTags();
220 } else {
221 d->clientBuilderContainerTags.clear();
222 d->clientBuilderCustomTags.clear();
223 }
224
225 // load shortcut schemes, user-defined shortcuts and other action properties
226 d->saveDefaultActionProperties(client->actionCollection()->actions());
227 if (!doc.isNull()) {
228 d->refreshActionProperties(client, client->actionCollection()->actions(), doc);
229 }
230
231 BuildHelper(*d, d->m_rootNode).build(docElement);
232
233 // let the client know that we built its GUI.
234 client->setFactory(this);
235
236 // call the finalizeGUI method, to fix up the positions of toolbars for example.
237 // Note: the client argument is ignored
238 d->builder->finalizeGUI(d->guiClient);
239
240 // reset some variables, for safety
241 d->BuildState::reset();
242
243 client->endXMLPlug();
244
245 d->popState();
246
247 Q_EMIT clientAdded(client);
248
249 // build child clients
250 const auto children = client->childClients();
251 for (KXMLGUIClient *child : children) {
252 addClient(child);
253 }
254
255 if (d->emptyState()) {
256 Q_EMIT makingChanges(false);
257 }
258 /*
259 QString unaddedActions;
260 Q_FOREACH (KActionCollection* ac, KActionCollection::allCollections())
261 Q_FOREACH (QAction* action, ac->actions())
262 if (action->associatedWidgets().isEmpty())
263 unaddedActions += action->objectName() + ' ';
264
265 if (!unaddedActions.isEmpty())
266 qCWarning(DEBUG_KXMLGUI) << "The following actions are not plugged into the gui (shortcuts will not work): " << unaddedActions;
267 */
268
269 // qCDebug(DEBUG_KXMLGUI) << "addClient took " << dt.elapsed();
270}
271
273{
274 for (KXMLGUIClient *client : std::as_const(d->m_clients)) {
275 d->guiClient = client;
276 QDomDocument doc = client->xmlguiBuildDocument();
277 if (doc.documentElement().isNull()) {
278 client->reloadXML();
279 doc = client->domDocument();
280 }
281 d->refreshActionProperties(client, client->actionCollection()->actions(), doc);
282 }
283 d->guiClient = nullptr;
284}
285
286static QString currentShortcutScheme()
287{
288 const KConfigGroup cg = KSharedConfig::openConfig()->group(QStringLiteral("Shortcut Schemes"));
289 return cg.readEntry("Current Scheme", "Default");
290}
291
292// Find the right ActionProperties element, otherwise return null element
293static QDomElement findActionPropertiesElement(const QDomDocument &doc)
294{
295 const QLatin1String tagActionProp("ActionProperties");
296 const QString schemeName = currentShortcutScheme();
298 for (; !e.isNull(); e = e.nextSiblingElement()) {
299 if (QString::compare(e.tagName(), tagActionProp, Qt::CaseInsensitive) == 0
300 && (e.attribute(QStringLiteral("scheme"), QStringLiteral("Default")) == schemeName)) {
301 return e;
302 }
303 }
304 return QDomElement();
305}
306
307void KXMLGUIFactoryPrivate::refreshActionProperties(KXMLGUIClient *client, const QList<QAction *> &actions, const QDomDocument &doc)
308{
309 // try to find and apply shortcuts schemes
310 const QString schemeName = KShortcutSchemesHelper::currentShortcutSchemeName();
311 // qCDebug(DEBUG_KXMLGUI) << client->componentName() << ": applying shortcut scheme" << schemeName;
312
313 if (schemeName != QLatin1String("Default")) {
314 applyShortcutScheme(schemeName, client, actions);
315 } else {
316 // apply saved default shortcuts
317 for (QAction *action : actions) {
318 QVariant savedDefaultShortcut = action->property("_k_DefaultShortcut");
319 if (savedDefaultShortcut.isValid()) {
320 QList<QKeySequence> shortcut = savedDefaultShortcut.value<QList<QKeySequence>>();
321 action->setShortcuts(shortcut);
322 action->setProperty("defaultShortcuts", QVariant::fromValue(shortcut));
323 // qCDebug(DEBUG_KXMLGUI) << "scheme said" << action->shortcut().toString() << "for action" << action->objectName();
324 } else {
325 action->setShortcuts(QList<QKeySequence>());
326 }
327 }
328 }
329
330 // try to find and apply user-defined shortcuts
331 const QDomElement actionPropElement = findActionPropertiesElement(doc);
332 if (!actionPropElement.isNull()) {
333 applyActionProperties(actionPropElement);
334 }
335}
336
337void KXMLGUIFactoryPrivate::saveDefaultActionProperties(const QList<QAction *> &actions)
338{
339 // This method is called every time the user activated a new
340 // kxmlguiclient. We only want to execute the following code only once in
341 // the lifetime of an action.
342 for (QAction *action : actions) {
343 // Skip nullptr actions or those we have seen already.
344 if (!action || action->property("_k_DefaultShortcut").isValid()) {
345 continue;
346 }
347
348 // Check if the default shortcut is set
349 QList<QKeySequence> defaultShortcut = action->property("defaultShortcuts").value<QList<QKeySequence>>();
350 QList<QKeySequence> activeShortcut = action->shortcuts();
351 // qCDebug(DEBUG_KXMLGUI) << action->objectName() << "default=" << defaultShortcut.toString() << "active=" << activeShortcut.toString();
352
353 // Check if we have an empty default shortcut and an non empty
354 // custom shortcut. Print out a warning and correct the mistake.
355 if ((!activeShortcut.isEmpty()) && defaultShortcut.isEmpty()) {
356 qCCritical(DEBUG_KXMLGUI) << "Shortcut for action " << action->objectName() << action->text()
357 << "set with QAction::setShortcut()! Use KActionCollection::setDefaultShortcut(s) instead.";
358 action->setProperty("_k_DefaultShortcut", QVariant::fromValue(activeShortcut));
359 } else {
360 action->setProperty("_k_DefaultShortcut", QVariant::fromValue(defaultShortcut));
361 }
362 }
363}
364
365void KXMLGUIFactory::changeShortcutScheme(const QString &scheme)
366{
367 qCDebug(DEBUG_KXMLGUI) << "Changing shortcut scheme to" << scheme;
368 KConfigGroup cg = KSharedConfig::openConfig()->group(QStringLiteral("Shortcut Schemes"));
369 cg.writeEntry("Current Scheme", scheme);
370
372}
373
374void KXMLGUIFactory::forgetClient(KXMLGUIClient *client)
375{
376 d->m_clients.erase(std::remove(d->m_clients.begin(), d->m_clients.end(), client), d->m_clients.end());
377}
378
380{
381 // qCDebug(DEBUG_KXMLGUI) << client;
382
383 // don't try to remove the client's GUI if we didn't build it
384 if (!client || client->factory() != this) {
385 return;
386 }
387
388 if (d->emptyState()) {
389 Q_EMIT makingChanges(true);
390 }
391
392 // remove this client from our client list
393 forgetClient(client);
394
395 // remove child clients first (create a copy of the list just in case the
396 // original list is modified directly or indirectly in removeClient())
397 const QList<KXMLGUIClient *> childClients(client->childClients());
398 for (KXMLGUIClient *child : childClients) {
399 removeClient(child);
400 }
401
402 // qCDebug(DEBUG_KXMLGUI) << "calling removeRecursive";
403
404 d->pushState();
405
406 // cache some variables
407
408 d->guiClient = client;
409 d->clientName = client->domDocument().documentElement().attribute(d->attrName);
410 d->clientBuilder = client->clientBuilder();
411
412 client->setFactory(nullptr);
413
414 // if we don't have a build document for that client, yet, then create one by
415 // cloning the original document, so that saving container information in the
416 // DOM tree does not touch the original document.
417 QDomDocument doc = client->xmlguiBuildDocument();
418 if (doc.documentElement().isNull()) {
419 doc = client->domDocument().cloneNode(true).toDocument();
420 client->setXMLGUIBuildDocument(doc);
421 }
422
423 d->m_rootNode->destruct(doc.documentElement(), *d);
424
425 // reset some variables
426 d->BuildState::reset();
427
428 // This will destruct the KAccel object built around the given widget.
429 client->prepareXMLUnplug(d->builder->widget());
430
431 d->popState();
432
433 if (d->emptyState()) {
434 Q_EMIT makingChanges(false);
435 }
436
437 Q_EMIT clientRemoved(client);
438}
439
441{
442 return d->m_clients;
443}
444
445QWidget *KXMLGUIFactory::container(const QString &containerName, KXMLGUIClient *client, bool useTagName)
446{
447 d->pushState();
448 d->m_containerName = containerName;
449 d->guiClient = client;
450
451 QWidget *result = d->findRecursive(d->m_rootNode, useTagName);
452
453 d->guiClient = nullptr;
454 d->m_containerName.clear();
455
456 d->popState();
457
458 return result;
459}
460
461QList<QWidget *> KXMLGUIFactory::containers(const QString &tagName)
462{
463 return d->findRecursive(d->m_rootNode, tagName);
464}
465
467{
468 d->m_rootNode->reset();
469
470 d->m_rootNode->clearChildren();
471}
472
473void KXMLGUIFactory::resetContainer(const QString &containerName, bool useTagName)
474{
475 if (containerName.isEmpty()) {
476 return;
477 }
478
479 ContainerNode *container = d->m_rootNode->findContainer(containerName, useTagName);
480 if (container && container->parent) {
481 container->parent->removeChild(container);
482 }
483}
484
485QWidget *KXMLGUIFactoryPrivate::findRecursive(KXMLGUI::ContainerNode *node, bool tag)
486{
487 if (((!tag && node->name == m_containerName) || (tag && node->tagName == m_containerName)) //
488 && (!guiClient || node->client == guiClient)) {
489 return node->container;
490 }
491
492 for (ContainerNode *child : std::as_const(node->children)) {
493 QWidget *cont = findRecursive(child, tag);
494 if (cont) {
495 return cont;
496 }
497 }
498
499 return nullptr;
500}
501
502// Case insensitive equality without calling toLower which allocates a new string
503static inline bool equals(const QString &str1, const char *str2)
504{
505 return str1.compare(QLatin1String(str2), Qt::CaseInsensitive) == 0;
506}
507static inline bool equals(const QString &str1, const QString &str2)
508{
509 return str1.compare(str2, Qt::CaseInsensitive) == 0;
510}
511
512QList<QWidget *> KXMLGUIFactoryPrivate::findRecursive(KXMLGUI::ContainerNode *node, const QString &tagName)
513{
515
516 if (equals(node->tagName, tagName)) {
517 res.append(node->container);
518 }
519
520 for (KXMLGUI::ContainerNode *child : std::as_const(node->children)) {
521 res << findRecursive(child, tagName);
522 }
523
524 return res;
525}
526
527void KXMLGUIFactory::plugActionList(KXMLGUIClient *client, const QString &name, const QList<QAction *> &actionList)
528{
529 d->pushState();
530 d->guiClient = client;
531 d->actionListName = name;
532 d->actionList = actionList;
533 d->clientName = client->domDocument().documentElement().attribute(d->attrName);
534
535 d->m_rootNode->plugActionList(*d);
536
537 // Load shortcuts for these new actions
538 d->saveDefaultActionProperties(actionList);
539 d->refreshActionProperties(client, actionList, client->domDocument());
540
541 d->BuildState::reset();
542 d->popState();
543}
544
545void KXMLGUIFactory::unplugActionList(KXMLGUIClient *client, const QString &name)
546{
547 d->pushState();
548 d->guiClient = client;
549 d->actionListName = name;
550 d->clientName = client->domDocument().documentElement().attribute(d->attrName);
551
552 d->m_rootNode->unplugActionList(*d);
553
554 d->BuildState::reset();
555 d->popState();
556}
557
558void KXMLGUIFactoryPrivate::applyActionProperties(const QDomElement &actionPropElement, ShortcutOption shortcutOption)
559{
560 for (QDomElement e = actionPropElement.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) {
561 if (!equals(e.tagName(), "action")) {
562 continue;
563 }
564
565 QAction *action = guiClient->action(e);
566 if (!action) {
567 continue;
568 }
569
570 configureAction(action, e.attributes(), shortcutOption);
571 }
572}
573
574void KXMLGUIFactoryPrivate::configureAction(QAction *action, const QDomNamedNodeMap &attributes, ShortcutOption shortcutOption)
575{
576 for (int i = 0; i < attributes.length(); i++) {
577 QDomAttr attr = attributes.item(i).toAttr();
578 if (attr.isNull()) {
579 continue;
580 }
581
582 configureAction(action, attr, shortcutOption);
583 }
584}
585
586void KXMLGUIFactoryPrivate::configureAction(QAction *action, const QDomAttr &attribute, ShortcutOption shortcutOption)
587{
588 QString attrName = attribute.name();
589 // If the attribute is a deprecated "accel", change to "shortcut".
590 if (equals(attrName, "accel")) {
591 attrName = QStringLiteral("shortcut");
592 }
593
594 // No need to re-set name, particularly since it's "objectName" in Qt4
595 if (equals(attrName, "name")) {
596 return;
597 }
598
599 if (equals(attrName, "icon")) {
600 action->setIcon(QIcon::fromTheme(attribute.value()));
601 return;
602 }
603
604 QVariant propertyValue;
605
606 const int propertyType = action->property(attrName.toLatin1().constData()).typeId();
607 bool isShortcut = (propertyType == QMetaType::QKeySequence);
608
609 if (propertyType == QMetaType::Int) {
610 propertyValue = QVariant(attribute.value().toInt());
611 } else if (propertyType == QMetaType::UInt) {
612 propertyValue = QVariant(attribute.value().toUInt());
613 } else if (isShortcut) {
614 // Setting the shortcut by property also sets the default shortcut (which is incorrect), so we have to do it directly
615 if (attrName == QLatin1String("globalShortcut")) {
616#if HAVE_GLOBALACCEL
618#endif
619 } else {
620 action->setShortcuts(QKeySequence::listFromString(attribute.value()));
621 }
622 if (shortcutOption & KXMLGUIFactoryPrivate::SetDefaultShortcut) {
623 action->setProperty("defaultShortcuts", QVariant::fromValue(QKeySequence::listFromString(attribute.value())));
624 }
625 } else {
626 propertyValue = QVariant(attribute.value());
627 }
628 if (!isShortcut && !action->setProperty(attrName.toLatin1().constData(), propertyValue)) {
629 qCWarning(DEBUG_KXMLGUI) << "Error: Unknown action property " << attrName << " will be ignored!";
630 }
631}
632
633void KXMLGUIFactoryPrivate::applyShortcutScheme(const QString &schemeName, KXMLGUIClient *client, const QList<QAction *> &actions)
634{
635 // First clear all existing shortcuts
636 for (QAction *action : actions) {
638 // We clear the default shortcut as well because the shortcut scheme will set its own defaults
639 action->setProperty("defaultShortcuts", QVariant::fromValue(QList<QKeySequence>()));
640 }
641
642 // Find the document for the shortcut scheme using the current application path.
643 // This allows to install a single XML file for a shortcut scheme for kdevelop
644 // rather than 10.
645 // Also look for the current xmlguiclient path.
646 // Per component xml files make sense for making kmail shortcuts available in kontact.
647 QString schemeFileName = KShortcutSchemesHelper::shortcutSchemeFileName(client->componentName(), schemeName);
648 if (schemeFileName.isEmpty()) {
649 schemeFileName = KShortcutSchemesHelper::applicationShortcutSchemeFileName(schemeName);
650 }
651 if (schemeFileName.isEmpty()) {
652 qCWarning(DEBUG_KXMLGUI) << client->componentName() << ": shortcut scheme file not found:" << schemeName << "after trying"
653 << QCoreApplication::applicationName() << "and" << client->componentName();
654 return;
655 }
656
657 QDomDocument scheme;
658 QFile schemeFile(schemeFileName);
659 if (schemeFile.open(QIODevice::ReadOnly)) {
660 qCDebug(DEBUG_KXMLGUI) << client->componentName() << ": found shortcut scheme XML" << schemeFileName;
661 scheme.setContent(&schemeFile);
662 }
663
664 if (scheme.isNull()) {
665 return;
666 }
667
668 QDomElement docElement = scheme.documentElement();
669 QDomElement actionPropElement = docElement.namedItem(QStringLiteral("ActionProperties")).toElement();
670
671 // Check if we really have the shortcut configuration here
672 if (!actionPropElement.isNull()) {
673 // qCDebug(DEBUG_KXMLGUI) << "Applying shortcut scheme for XMLGUI client" << client->componentName();
674
675 // Apply all shortcuts we have
676 applyActionProperties(actionPropElement, KXMLGUIFactoryPrivate::SetDefaultShortcut);
677 //} else {
678 // qCDebug(DEBUG_KXMLGUI) << "Invalid shortcut scheme file";
679 }
680}
681
683{
685 dlg->setAttribute(Qt::WA_DeleteOnClose);
686
687 for (KXMLGUIClient *client : std::as_const(d->m_clients)) {
688 if (client) {
689 qCDebug(DEBUG_KXMLGUI) << "Adding collection from client" << client->componentName() << "with" << client->actionCollection()->count() << "actions";
690
691 dlg->addCollection(client->actionCollection(), client->componentName());
692 }
693 }
694
696 dlg->configure(true /*save settings on accept*/);
697}
698
699// Find or create
701{
702 // first, lets see if we have existing properties
703 QDomElement elem = findActionPropertiesElement(doc);
704
705 // if there was none, create one
706 if (elem.isNull()) {
707 elem = doc.createElement(QStringLiteral("ActionProperties"));
708 elem.setAttribute(QStringLiteral("scheme"), currentShortcutScheme());
709 doc.documentElement().appendChild(elem);
710 }
711 return elem;
712}
713
715{
716 const QLatin1String attrName("name");
717 for (QDomNode it = elem.firstChild(); !it.isNull(); it = it.nextSibling()) {
718 QDomElement e = it.toElement();
719 if (e.attribute(attrName) == sName) {
720 return e;
721 }
722 }
723
724 if (create) {
725 QDomElement act_elem = elem.ownerDocument().createElement(QStringLiteral("Action"));
726 act_elem.setAttribute(attrName, sName);
727 elem.appendChild(act_elem);
728 return act_elem;
729 }
730 return QDomElement();
731}
732
733#include "moc_kxmlguifactory.cpp"
int count() const
Returns the number of actions in the collection.
QList< QAction * > actions() const
Returns the list of QActions which belong to this action collection.
KConfigGroup group(const QString &group)
void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags=Normal)
QString readEntry(const char *key, const char *aDefault=nullptr) const
static KGlobalAccel * self()
bool setShortcut(QAction *action, const QList< QKeySequence > &shortcut, GlobalShortcutLoading loadFlag=Autoloading)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
Dialog for configuration of KActionCollection and KGlobalAccel.
void saved()
Emitted after the dialog is accepted (by clicking the OK button) and settings are saved.
Implements the creation of the GUI (menubar, menus and toolbars) as requested by the GUI factory.
A KXMLGUIClient can be used with KXMLGUIFactory to create a GUI from actions and an XML document,...
virtual QString componentName() const
virtual QDomDocument domDocument() const
virtual KActionCollection * actionCollection() const
Retrieves the entire action collection for the GUI client.
QList< 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 nullptr if the ...
void setXMLGUIBuildDocument(const QDomDocument &doc)
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 nullptr if no client specific builder has been assigned via set...
QDomDocument xmlguiBuildDocument() const
static QString readConfigFile(const QString &filename, const QString &componentName=QString())
QList< KXMLGUIClient * > clients() const
Returns a list of all clients currently added to this factory.
void removeClient(KXMLGUIClient *client)
Removes the GUI described by the client, by unplugging all provided actions and removing all owned co...
static bool saveConfigFile(const QDomDocument &doc, const QString &filename, const QString &componentName=QString())
void shortcutsSaved()
Emitted when the shortcuts have been saved (i.e.
void addClient(KXMLGUIClient *client)
Creates the GUI described by the QDomDocument of the client, using the client's actions,...
KXMLGUIFactory(KXMLGUIBuilder *builder, QObject *parent=nullptr)
Constructs a KXMLGUIFactory.
static QDomElement actionPropertiesElement(QDomDocument &doc)
~KXMLGUIFactory() override
Destructor.
void reset()
Use this method to free all memory allocated by the KXMLGUIFactory.
void showConfigureShortcutsDialog()
Shows a dialog (KShortcutsDialog) that lists every action in this factory, and which can be used to c...
static QDomElement findActionByName(QDomElement &elem, const QString &sName, bool create)
void makingChanges(bool)
Emitted when the factory is currently making changes to the GUI, i.e.
void refreshActionProperties()
Use this method to reset and reread action properties (shortcuts, etc.) for all actions.
QWidget * container(const QString &containerName, KXMLGUIClient *client, bool useTagName=false)
Use this method to get access to a container widget with the name specified with containerName and wh...
void resetContainer(const QString &containerName, bool useTagName=false)
Use this method to free all memory allocated by the KXMLGUIFactory for a specific container,...
QString name(StandardAction id)
KGuiItem cont()
const QList< QKeySequence > & shortcut(StandardShortcut id)
bool equals(const QVariant &lhs, const QVariant &rhs)
void setIcon(const QIcon &icon)
void setShortcuts(QKeySequence::StandardKey key)
const char * constData() const const
qsizetype size() const const
bool isRelativePath(const QString &path)
bool mkpath(const QString &dirPath) const const
QString name() const const
QString value() const const
QDomElement createElement(const QString &tagName)
QDomElement documentElement() const const
ParseResult setContent(QAnyStringView text, ParseOptions options)
QString attribute(const QString &name, const QString &defValue) const const
QDomNamedNodeMap attributes() const const
void setAttribute(const QString &name, const QString &value)
QString tagName() const const
QDomNode item(int index) const const
int length() const const
QDomNode appendChild(const QDomNode &newChild)
QDomNode cloneNode(bool deep) const const
QDomNode firstChild() const const
QDomElement firstChildElement(const QString &tagName, const QString &namespaceURI) const const
bool isNull() const const
QDomNode namedItem(const QString &name) const const
QDomElement nextSiblingElement(const QString &tagName, const QString &namespaceURI) const const
QDomDocument ownerDocument() const const
QDomAttr toAttr() const const
QDomDocument toDocument() const const
QDomElement toElement() const const
bool exists() const const
bool open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
virtual void close() override
QString absolutePath() const const
QIcon fromTheme(const QString &name)
QByteArray readAll()
QList< QKeySequence > listFromString(const QString &str, SequenceFormat format)
void append(QList< T > &&value)
bool isEmpty() const const
T value(qsizetype i) const const
Q_EMITQ_EMIT
const QObjectList & children() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
QVariant property(const char *name) const const
T qobject_cast(QObject *object)
bool setProperty(const char *name, QVariant &&value)
QString locate(StandardLocation type, const QString &fileName, LocateOptions options)
QString writableLocation(StandardLocation type)
int compare(QLatin1StringView s1, const QString &s2, Qt::CaseSensitivity cs)
QString fromUtf8(QByteArrayView str)
bool isEmpty() const const
int toInt(bool *ok, int base) const const
QByteArray toLatin1() const const
uint toUInt(bool *ok, int base) const const
CaseInsensitive
WA_DeleteOnClose
QVariant fromValue(T &&value)
bool isValid() const const
int typeId() const const
T value() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:19:32 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.