KXmlGui

kactioncollection.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 1999 Reginald Stadlbauer <reggie@kde.org>
4 SPDX-FileCopyrightText: 1999 Simon Hausmann <hausmann@kde.org>
5 SPDX-FileCopyrightText: 2000 Nicolas Hadacek <haadcek@kde.org>
6 SPDX-FileCopyrightText: 2000 Kurt Granroth <granroth@kde.org>
7 SPDX-FileCopyrightText: 2000 Michael Koch <koch@kde.org>
8 SPDX-FileCopyrightText: 2001 Holger Freyther <freyther@kde.org>
9 SPDX-FileCopyrightText: 2002 Ellis Whitehead <ellis@kde.org>
10 SPDX-FileCopyrightText: 2002 Joseph Wenninger <jowenn@kde.org>
11 SPDX-FileCopyrightText: 2005-2007 Hamish Rodda <rodda@kde.org>
12
13 SPDX-License-Identifier: LGPL-2.0-only
14*/
15
16#include "config-xmlgui.h"
17
18#include "kactioncollection.h"
19
20#include "debug.h"
21#include "kactioncategory.h"
22#include "kxmlguiclient.h"
23#include "kxmlguifactory.h"
24
25#include <KAuthorized>
26#include <KConfigGroup>
27#if HAVE_GLOBALACCEL
28#include <KGlobalAccel>
29#endif
30#include <KSharedConfig>
31
32#include <QDomDocument>
33#include <QGuiApplication>
34#include <QList>
35#include <QMetaMethod>
36#include <QSet>
37
38static bool actionHasGlobalShortcut(const QAction *action)
39{
40#if HAVE_GLOBALACCEL
41 return KGlobalAccel::self()->hasShortcut(action);
42#else
43 Q_UNUSED(action)
44 return false;
45#endif
46}
47
48struct ActionStorage {
49 void addAction(const QString &name, QAction *action)
50 {
51 Q_ASSERT(std::find(m_actions.begin(), m_actions.end(), action) == m_actions.end());
52 m_actions.push_back(action);
53 m_names.push_back(name);
54 Q_ASSERT(m_names.size() == m_actions.size());
55 }
56
57 bool removeAction(QAction *action)
58 {
59 auto it = std::find(m_actions.begin(), m_actions.end(), action);
60 if (it != m_actions.end()) {
61 // We can't have the same action twice.
62 Q_ASSERT(std::find(it + 1, m_actions.end(), action) == m_actions.end());
63 auto idx = std::distance(m_actions.begin(), it);
64 m_names.erase(m_names.begin() + idx);
65 m_actions.erase(it);
66 return true;
67 }
68 Q_ASSERT(m_names.size() == m_actions.size());
69 return false;
70 }
71
72 QAction *findAction(const QString &name) const
73 {
74 auto it = std::find(m_names.begin(), m_names.end(), name);
75 if (it != m_names.end() && *it == name) {
76 return m_actions[std::distance(m_names.begin(), it)];
77 }
78 return nullptr;
79 }
80
81 void clear()
82 {
83 m_actions = {};
84 m_names = {};
85 }
86
87 int size() const
88 {
89 return m_actions.size();
90 }
91
92 template<typename F>
93 void foreachAction(F f)
94 {
95 Q_ASSERT(m_names.size() == m_actions.size());
96 for (int i = 0; i < m_actions.size(); ++i) {
97 f(m_names.at(i), m_actions.at(i));
98 }
99 }
100
101 const QList<QAction *> &actions() const
102 {
103 return m_actions;
104 }
105
106private:
107 // 1:1 list of names and actions
108 QList<QString> m_names;
109 QList<QAction *> m_actions;
110};
111
112class KActionCollectionPrivate
113{
114public:
115 KActionCollectionPrivate(KActionCollection *qq)
116 : q(qq)
117 , configIsGlobal(false)
118 , connectTriggered(false)
119 , connectHovered(false)
120
121 {
122 }
123
124 void setComponentForAction(QAction *action)
125 {
126 const bool hasGlobalShortcut = actionHasGlobalShortcut(action);
127 if (!hasGlobalShortcut) {
128 action->setProperty("componentName", m_componentName);
129 action->setProperty("componentDisplayName", m_componentDisplayName);
130 }
131 }
132
133 static QList<KActionCollection *> s_allCollections;
134
135 void _k_associatedWidgetDestroyed(QObject *obj);
136 void _k_actionDestroyed(QObject *obj);
137
138 bool writeKXMLGUIConfigFile();
139
140 QString m_componentName;
141 QString m_componentDisplayName;
142
143 //! Remove a action from our internal bookkeeping. Returns a nullptr if the
144 //! action doesn't belong to us.
145 QAction *unlistAction(QAction *);
146
147 ActionStorage actionStore;
148
149 KActionCollection *q = nullptr;
150
151 const KXMLGUIClient *m_parentGUIClient = nullptr;
152
153 QString configGroup{QStringLiteral("Shortcuts")};
154 bool configIsGlobal : 1;
155
156 bool connectTriggered : 1;
157 bool connectHovered : 1;
158
159 QList<QWidget *> associatedWidgets;
160};
161
162QList<KActionCollection *> KActionCollectionPrivate::s_allCollections;
163
165 : QObject(parent)
166 , d(new KActionCollectionPrivate(this))
167{
168 KActionCollectionPrivate::s_allCollections.append(this);
169
170 setComponentName(cName);
171}
172
174 : QObject(nullptr)
175 , d(new KActionCollectionPrivate(this))
176{
177 KActionCollectionPrivate::s_allCollections.append(this);
178
179 d->m_parentGUIClient = parent;
180 d->m_componentName = parent->componentName();
181}
182
184{
185 KActionCollectionPrivate::s_allCollections.removeAll(this);
186}
187
189{
190 const QList<QAction *> copy = d->actionStore.actions();
191 qDeleteAll(copy);
192 d->actionStore.clear();
193}
194
196{
197 if (!name.isEmpty()) {
198 return d->actionStore.findAction(name);
199 }
200 return nullptr;
201}
202
204{
205 // ### investigate if any apps use this at all
206 return actions().value(index);
207}
208
210{
211 return d->actionStore.size();
212}
213
215{
216 return count() == 0;
217}
218
220{
221 for (auto *a : d->actionStore.actions()) {
222 if (actionHasGlobalShortcut(a)) {
223 // Its component name is part of an action's signature in the context of
224 // global shortcuts and the semantics of changing an existing action's
225 // signature are, as it seems, impossible to get right.
226 qCWarning(DEBUG_KXMLGUI) << "KActionCollection::setComponentName does not work on a KActionCollection containing actions with global shortcuts!"
227 << cName;
228 break;
229 }
230 }
231
232 if (!cName.isEmpty()) {
233 d->m_componentName = cName;
234 } else {
235 d->m_componentName = QCoreApplication::applicationName();
236 }
237}
238
240{
241 return d->m_componentName;
242}
243
245{
246 d->m_componentDisplayName = displayName;
247}
248
250{
251 if (!d->m_componentDisplayName.isEmpty()) {
252 return d->m_componentDisplayName;
253 }
256 }
258}
259
261{
262 return d->m_parentGUIClient;
263}
264
266{
267 return d->actionStore.actions();
268}
269
271{
273 for (auto *action : std::as_const(d->actionStore.actions())) {
274 if (!action->actionGroup()) {
275 ret.append(action);
276 }
277 }
278 return ret;
279}
280
282{
284 for (auto *action : std::as_const(d->actionStore.actions())) {
285 if (action->actionGroup()) {
286 set.insert(action->actionGroup());
287 }
288 }
289 return set.values();
290}
291
293{
294 if (!action) {
295 return action;
296 }
297
299 QString indexName = name;
300
301 if (indexName.isEmpty()) {
302 // No name provided. Use the objectName.
303 indexName = objectName;
304
305 } else {
306 // A name was provided. Check against objectName.
307 if ((!objectName.isEmpty()) && (objectName != indexName)) {
308 // The user specified a new name and the action already has a
309 // different one. The objectName is used for saving shortcut
310 // settings to disk. Both for local and global shortcuts.
311 qCDebug(DEBUG_KXMLGUI) << "Registering action " << objectName << " under new name " << indexName;
312 // If there is a global shortcuts it's a very bad idea.
313#if HAVE_GLOBALACCEL
314 if (KGlobalAccel::self()->hasShortcut(action)) {
315 // In debug mode assert
316 Q_ASSERT(!KGlobalAccel::self()->hasShortcut(action));
317 // In release mode keep the old name
318 qCCritical(DEBUG_KXMLGUI) << "Changing action name from " << objectName << " to " << indexName
319 << "\nignored because of active global shortcut.";
320 indexName = objectName;
321 }
322#endif
323 }
324
325 // Set the new name
326 action->setObjectName(indexName);
327 }
328
329 // No name provided and the action had no name. Make one up. This will not
330 // work when trying to save shortcuts. Both local and global shortcuts.
331 if (indexName.isEmpty()) {
332 indexName = QString::asprintf("unnamed-%p", (void *)action);
333 action->setObjectName(indexName);
334 }
335
336 // From now on the objectName has to have a value. Else we cannot safely
337 // remove actions.
338 Q_ASSERT(!action->objectName().isEmpty());
339
340 // look if we already have THIS action under THIS name ;)
341 auto oldAction = d->actionStore.findAction(indexName);
342 if (oldAction == action) {
343 return action;
344 }
345
346 if (!KAuthorized::authorizeAction(indexName)) {
347 // Disable this action
348 action->setEnabled(false);
349 action->setVisible(false);
350 action->blockSignals(true);
351 }
352
353 // Check if we have another action under this name
354 if (oldAction) {
355 takeAction(oldAction);
356 }
357
358 // Remove if we have this action under a different name.
359 // Not using takeAction because we don't want to remove it from categories,
360 // and because it has the new name already.
361 d->actionStore.removeAction(action);
362
363 // Add action to our lists.
364 d->actionStore.addAction(indexName, action);
365
366 for (QWidget *widget : std::as_const(d->associatedWidgets)) {
367 widget->addAction(action);
368 }
369
370 connect(action, &QObject::destroyed, this, [this](QObject *obj) {
371 d->_k_actionDestroyed(obj);
372 });
373
374 d->setComponentForAction(action);
375
376 if (d->connectHovered) {
377 connect(action, &QAction::hovered, this, &KActionCollection::slotActionHovered);
378 }
379
380 if (d->connectTriggered) {
381 connect(action, &QAction::triggered, this, &KActionCollection::slotActionTriggered);
382 }
383
385 Q_EMIT changed();
386 return action;
387}
388
390{
391 for (QAction *action : actions) {
393 }
394}
395
397{
398 delete takeAction(action);
399}
400
402{
403 if (!d->unlistAction(action)) {
404 return nullptr;
405 }
406
407 // Remove the action from all widgets
408 for (QWidget *widget : std::as_const(d->associatedWidgets)) {
409 widget->removeAction(action);
410 }
411
412 action->disconnect(this);
413
414 Q_EMIT changed();
415 return action;
416}
417
418QAction *KActionCollection::addAction(KStandardAction::StandardAction actionType, const QObject *receiver, const char *member)
419{
420 QAction *action = KStandardAction::create(actionType, receiver, member, this);
421 return action;
422}
423
424QAction *KActionCollection::addAction(KStandardAction::StandardAction actionType, const QString &name, const QObject *receiver, const char *member)
425{
426 // pass 0 as parent, because if the parent is a KActionCollection KStandardAction::create automatically
427 // adds the action to it under the default name. We would trigger the
428 // warning about renaming the action then.
429 QAction *action = KStandardAction::create(actionType, receiver, member, nullptr);
430 // Give it a parent for gc.
431 action->setParent(this);
432 // Remove the name to get rid of the "rename action" warning above
433 action->setObjectName(name);
434 // And now add it with the desired name.
435 return addAction(name, action);
436}
437
439{
440 // Use implementation from KConfigWidgets instead of KConfigGui
441 // as it provides tighter integration with QtWidgets applications.
442 // KStandardAction automatically adds it to the collection.
443 QAction *action = KStandardAction::create(static_cast<KStandardAction::StandardAction>(actionType), nullptr, {}, this);
444 return action;
445}
446
447QAction *KActionCollection::addAction(const QString &name, const QObject *receiver, const char *member)
448{
449 QAction *a = new QAction(this);
450 if (receiver && member) {
451 connect(a, SIGNAL(triggered(bool)), receiver, member);
452 }
453 return addAction(name, a);
454}
455
457{
459 return shortcuts.isEmpty() ? QKeySequence() : shortcuts.first();
460}
461
466
471
473{
474 action->setShortcuts(shortcuts);
475 action->setProperty("defaultShortcuts", QVariant::fromValue(shortcuts));
476}
477
479{
480 // Considered as true by default
481 const QVariant value = action->property("isShortcutConfigurable");
482 return value.isValid() ? value.toBool() : true;
483}
484
486{
487 action->setProperty("isShortcutConfigurable", configurable);
488}
489
490QString KActionCollection::configGroup() const
491{
492 return d->configGroup;
493}
494
496{
497 d->configGroup = group;
498}
499
500bool KActionCollection::configIsGlobal() const
501{
502 return d->configIsGlobal;
503}
504
506{
507 d->configIsGlobal = global;
508}
509
511{
512#if HAVE_GLOBALACCEL
513 Q_ASSERT(config);
514 if (!config || !config->exists()) {
515 return;
516 }
517
518 d->actionStore.foreachAction([config](const QString &actionName, QAction *action) {
519 if (!action) {
520 return;
521 }
522
524 QString entry = config->readEntry(actionName, QString());
525 if (!entry.isEmpty()) {
527 } else {
530 }
531 }
532 });
533#else
534 Q_UNUSED(config);
535#endif
536}
537
539{
540 KConfigGroup cg(KSharedConfig::openConfig(), configGroup());
541 if (!config) {
542 config = &cg;
543 }
544
545 if (!config->exists()) {
546 return;
547 }
548
549 d->actionStore.foreachAction([config](const QString &actionName, QAction *action) {
550 if (!action) {
551 return;
552 }
553
555 QString entry = config->readEntry(actionName, QString());
556 if (!entry.isEmpty()) {
558 } else {
560 }
561 }
562 });
563
564 // qCDebug(DEBUG_KXMLGUI) << " done";
565}
566
568{
569#if HAVE_GLOBALACCEL
570 Q_ASSERT(config);
571 if (!config) {
572 return;
573 }
574
575 d->actionStore.foreachAction([config, this, writeAll](const QString &actionName, QAction *action) {
576 if (!action) {
577 return;
578 }
579 // If the action name starts with unnamed- spit out a warning. That name
580 // will change at will and will break loading writing
581 if (actionName.startsWith(QLatin1String("unnamed-"))) {
582 qCCritical(DEBUG_KXMLGUI) << "Skipped exporting Shortcut for action without name " << action->text() << "!";
583 return;
584 }
585
587 bool bConfigHasAction = !config->readEntry(actionName, QString()).isEmpty();
589 // If we're using a global config or this setting
590 // differs from the default, then we want to write.
592 if (configIsGlobal()) {
593 flags |= KConfigGroup::Global;
594 }
595 if (writeAll || !bSameAsDefault) {
597 if (s.isEmpty()) {
598 s = QStringLiteral("none");
599 }
600 qCDebug(DEBUG_KXMLGUI) << "\twriting " << actionName << " = " << s;
601 config->writeEntry(actionName, s, flags);
602 }
603 // Otherwise, this key is the same as default
604 // but exists in config file. Remove it.
605 else if (bConfigHasAction) {
606 qCDebug(DEBUG_KXMLGUI) << "\tremoving " << actionName << " because == default";
607 config->deleteEntry(actionName, flags);
608 }
609 }
610 });
611
612 config->sync();
613#else
614 Q_UNUSED(config);
615 Q_UNUSED(writeAll);
616#endif
617}
618
619bool KActionCollectionPrivate::writeKXMLGUIConfigFile()
620{
621 const KXMLGUIClient *kxmlguiClient = q->parentGUIClient();
622 // return false if there is no KXMLGUIClient
623 if (!kxmlguiClient || kxmlguiClient->xmlFile().isEmpty()) {
624 return false;
625 }
626
627 qCDebug(DEBUG_KXMLGUI) << "xmlFile=" << kxmlguiClient->xmlFile();
628
629 QString attrShortcut = QStringLiteral("shortcut");
630
631 // Read XML file
632 QString sXml(KXMLGUIFactory::readConfigFile(kxmlguiClient->xmlFile(), q->componentName()));
633 QDomDocument doc;
634 doc.setContent(sXml);
635
636 // Process XML data
637
638 // Get hold of ActionProperties tag
640
641 // now, iterate through our actions
642 actionStore.foreachAction([&elem, &attrShortcut, this](const QString &actionName, QAction *action) {
643 if (!action) {
644 return;
645 }
646
647 // If the action name starts with unnamed- spit out a warning and ignore
648 // it. That name will change at will and will break loading writing
649 if (actionName.startsWith(QLatin1String("unnamed-"))) {
650 qCCritical(DEBUG_KXMLGUI) << "Skipped writing shortcut for action " << actionName << "(" << action->text() << ")!";
651 return;
652 }
653
654 bool bSameAsDefault = (action->shortcuts() == q->defaultShortcuts(action));
655 qCDebug(DEBUG_KXMLGUI) << "name = " << actionName << " shortcut = " << QKeySequence::listToString(action->shortcuts())
656#if HAVE_GLOBALACCEL
657 << " globalshortcut = " << QKeySequence::listToString(KGlobalAccel::self()->shortcut(action))
658#endif
659 << " def = " << QKeySequence::listToString(q->defaultShortcuts(action));
660
661 // now see if this element already exists
662 // and create it if necessary (unless bSameAsDefault)
663 QDomElement act_elem = KXMLGUIFactory::findActionByName(elem, actionName, !bSameAsDefault);
664 if (act_elem.isNull()) {
665 return;
666 }
667
668 if (bSameAsDefault) {
669 act_elem.removeAttribute(attrShortcut);
670 // qCDebug(DEBUG_KXMLGUI) << "act_elem.attributes().count() = " << act_elem.attributes().count();
671 if (act_elem.attributes().count() == 1) {
672 elem.removeChild(act_elem);
673 }
674 } else {
675 act_elem.setAttribute(attrShortcut, QKeySequence::listToString(action->shortcuts()));
676 }
677 });
678
679 // Write back to XML file
680 KXMLGUIFactory::saveConfigFile(doc, kxmlguiClient->localXMLFile(), q->componentName());
681 // and since we just changed the xml file clear the dom we have in memory
682 // it'll be rebuilt if needed
683 const_cast<KXMLGUIClient *>(kxmlguiClient)->setXMLGUIBuildDocument({});
684 return true;
685}
686
687void KActionCollection::writeSettings(KConfigGroup *config, bool writeAll, QAction *oneAction) const
688{
689 // If the caller didn't provide a config group we try to save the KXMLGUI
690 // Configuration file. If that succeeds we are finished.
691 if (config == nullptr && d->writeKXMLGUIConfigFile()) {
692 return;
693 }
694
695 KConfigGroup cg(KSharedConfig::openConfig(), configGroup());
696 if (!config) {
697 config = &cg;
698 }
699
700 QList<QAction *> writeActions;
701 if (oneAction) {
702 writeActions.append(oneAction);
703 } else {
704 writeActions = actions();
705 }
706
707 d->actionStore.foreachAction([config, this, writeAll](const QString &actionName, QAction *action) {
708 if (!action) {
709 return;
710 }
711
712 // If the action name starts with unnamed- spit out a warning and ignore
713 // it. That name will change at will and will break loading writing
714 if (actionName.startsWith(QLatin1String("unnamed-"))) {
715 qCCritical(DEBUG_KXMLGUI) << "Skipped saving Shortcut for action without name " << action->text() << "!";
716 return;
717 }
718
719 // Write the shortcut
721 bool bConfigHasAction = !config->readEntry(actionName, QString()).isEmpty();
722 bool bSameAsDefault = (action->shortcuts() == defaultShortcuts(action));
723 // If we're using a global config or this setting
724 // differs from the default, then we want to write.
726
727 // Honor the configIsGlobal() setting
728 if (configIsGlobal()) {
729 flags |= KConfigGroup::Global;
730 }
731
732 if (writeAll || !bSameAsDefault) {
733 // We are instructed to write all shortcuts or the shortcut is
734 // not set to its default value. Write it
736 if (s.isEmpty()) {
737 s = QStringLiteral("none");
738 }
739 qCDebug(DEBUG_KXMLGUI) << "\twriting " << actionName << " = " << s;
740 config->writeEntry(actionName, s, flags);
741
742 } else if (bConfigHasAction) {
743 // Otherwise, this key is the same as default but exists in
744 // config file. Remove it.
745 qCDebug(DEBUG_KXMLGUI) << "\tremoving " << actionName << " because == default";
746 config->deleteEntry(actionName, flags);
747 }
748 }
749 });
750
751 config->sync();
752}
753
754void KActionCollection::slotActionTriggered()
755{
757 if (action) {
759 }
760}
761
762void KActionCollection::slotActionHovered()
763{
765 if (action) {
767 }
768}
769
770// The downcast from a QObject to a QAction triggers UBSan
771// but we're only comparing pointers, so UBSan shouldn't check vptrs
772// Similar to https://github.com/itsBelinda/plog/pull/1/files
773#if defined(__clang__) || __GNUC__ >= 8
774__attribute__((no_sanitize("vptr")))
775#endif
776void KActionCollectionPrivate::_k_actionDestroyed(QObject *obj)
777{
778 // obj isn't really a QAction anymore. So make sure we don't do fancy stuff
779 // with it.
780 QAction *action = static_cast<QAction *>(obj);
781
782 if (!unlistAction(action)) {
783 return;
784 }
785
786 Q_EMIT q->changed();
787}
788
790{
791 if (d->connectHovered && d->connectTriggered) {
792 return;
793 }
794
795 if (signal.methodSignature() == "actionHovered(QAction*)") {
796 if (!d->connectHovered) {
797 d->connectHovered = true;
798
799 for (auto *action : d->actionStore.actions()) {
800 connect(action, &QAction::hovered, this, &KActionCollection::slotActionHovered);
801 }
802 }
803
804 } else if (signal.methodSignature() == "actionTriggered(QAction*)") {
805 if (!d->connectTriggered) {
806 d->connectTriggered = true;
807 for (auto *action : d->actionStore.actions()) {
808 connect(action, &QAction::triggered, this, &KActionCollection::slotActionTriggered);
809 }
810 }
811 }
812
814}
815
817{
818 return KActionCollectionPrivate::s_allCollections;
819}
820
822{
823 for (auto *action : d->actionStore.actions()) {
824 if (!widget->actions().contains(action)) {
825 widget->addAction(action);
826 }
827 }
828}
829
831{
832 if (!d->associatedWidgets.contains(widget)) {
833 widget->addActions(actions());
834
835 d->associatedWidgets.append(widget);
836 connect(widget, &QObject::destroyed, this, [this](QObject *obj) {
837 d->_k_associatedWidgetDestroyed(obj);
838 });
839 }
840}
841
843{
844 for (auto *action : d->actionStore.actions()) {
845 widget->removeAction(action);
846 }
847
848 d->associatedWidgets.removeAll(widget);
849 disconnect(widget, &QObject::destroyed, this, nullptr);
850}
851
852QAction *KActionCollectionPrivate::unlistAction(QAction *action)
853{
854 // ATTENTION:
855 // This method is called with an QObject formerly known as a QAction
856 // during _k_actionDestroyed(). So don't do fancy stuff here that needs a
857 // real QAction!
858
859 // Remove the action
860 if (!actionStore.removeAction(action)) {
861 return nullptr;
862 }
863
864 // Remove the action from the categories. Should be only one
865 const QList<KActionCategory *> categories = q->findChildren<KActionCategory *>();
866 for (KActionCategory *category : categories) {
867 category->unlistAction(action);
868 }
869
870 return action;
871}
872
874{
875 return d->associatedWidgets;
876}
877
879{
880 for (QWidget *widget : std::as_const(d->associatedWidgets)) {
881 for (auto *action : d->actionStore.actions()) {
882 widget->removeAction(action);
883 }
884 }
885
886 d->associatedWidgets.clear();
887}
888
889void KActionCollectionPrivate::_k_associatedWidgetDestroyed(QObject *obj)
890{
891 associatedWidgets.removeAll(static_cast<QWidget *>(obj));
892}
893
894#include "moc_kactioncollection.cpp"
Categorize actions for KShortcutsEditor.
A container for a set of QAction objects.
Q_INVOKABLE QAction * addAction(const QString &name, QAction *action)
Add an action under the given name to the collection.
static QKeySequence defaultShortcut(QAction *action)
Get the default primary shortcut for the given action.
static bool isShortcutsConfigurable(QAction *action)
Returns true if the given action's shortcuts may be configured by the user.
void addActions(const QList< QAction * > &actions)
Adds a list of actions to the collection.
void addAssociatedWidget(QWidget *widget)
Associate all actions in this collection to the given widget, including any actions added after this ...
int count() const
Returns the number of actions in the collection.
~KActionCollection() override
Destructor.
QList< QWidget * > associatedWidgets() const
Return a list of all associated widgets.
void actionHovered(QAction *action)
Indicates that action was hovered.
QString componentDisplayName() const
The display name for the associated component.
void connectNotify(const QMetaMethod &signal) override
Overridden to perform connections when someone wants to know whether an action was highlighted or tri...
void clear()
Clears the entire action collection, deleting all actions.
void importGlobalShortcuts(KConfigGroup *config)
Import from config all configurable global key associations.
void exportGlobalShortcuts(KConfigGroup *config, bool writeDefaults=false) const
Export the current configurable global key associations to config.
void setConfigGroup(const QString &group)
Sets group as the KConfig group with which settings will be loaded and saved.
void setComponentName(const QString &componentName)
Set the componentName associated with this action collection.
void clearAssociatedWidgets()
Clear all associated widgets and remove the actions from those widgets.
static void setShortcutsConfigurable(QAction *action, bool configurable)
Indicate whether the user may configure the action's shortcuts.
void associateWidget(QWidget *widget) const
Associate all actions in this collection to the given widget.
const KXMLGUIClient * parentGUIClient() const
The parent KXMLGUIClient, or null if not available.
const QList< QAction * > actionsWithoutGroup() const
Returns the list of QActions without an QAction::actionGroup() which belong to this action collection...
QAction * takeAction(QAction *action)
Removes an action from the collection.
bool isEmpty() const
Returns whether the action collection is empty or not.
KActionCollection(QObject *parent, const QString &cName=QString())
Constructor.
static void setDefaultShortcut(QAction *action, const QKeySequence &shortcut)
Set the default shortcut for the given action.
const QList< QActionGroup * > actionGroups() const
Returns the list of all QActionGroups associated with actions in this action collection.
static Q_INVOKABLE void setDefaultShortcuts(QAction *action, const QList< QKeySequence > &shortcuts)
Set the default shortcuts for the given action.
void changed()
Emitted when an action has been inserted into, or removed from, this action collection.
void writeSettings(KConfigGroup *config=nullptr, bool writeDefaults=false, QAction *oneAction=nullptr) const
Write the current configurable key associations to config.
void removeAction(QAction *action)
Removes an action from the collection and deletes it.
void inserted(QAction *action)
Indicates that action was inserted into this action collection.
QString componentName() const
The component name with which this class is associated.
static const QList< KActionCollection * > & allCollections()
Access the list of all action collections in existence for this app.
void setComponentDisplayName(const QString &displayName)
Set the component display name associated with this action collection.
static QList< QKeySequence > defaultShortcuts(QAction *action)
Get the default shortcuts for the given action.
void removeAssociatedWidget(QWidget *widget)
Remove an association between all actions in this collection and the given widget,...
void readSettings(KConfigGroup *config=nullptr)
Read all key associations from config.
QList< QAction * > actions() const
Returns the list of QActions which belong to this action collection.
void setConfigGlobal(bool global)
Set whether this action collection's configuration should be global to KDE ( true ),...
QAction * action(int index) const
Return the QAction* at position index in the action collection.
void actionTriggered(QAction *action)
Indicates that action was triggered.
static Q_INVOKABLE bool authorizeAction(const QString &action)
void deleteEntry(const char *key, WriteConfigFlags pFlags=Normal)
void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags=Normal)
QString readEntry(const char *key, const char *aDefault=nullptr) const
bool exists() const
bool sync() override
bool hasShortcut(const QAction *action) const
static KGlobalAccel * self()
bool setShortcut(QAction *action, const QList< QKeySequence > &shortcut, GlobalShortcutLoading loadFlag=Autoloading)
QList< QKeySequence > shortcut(const QAction *action) const
QList< QKeySequence > defaultShortcut(const QAction *action) const
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
A KXMLGUIClient can be used with KXMLGUIFactory to create a GUI from actions and an XML document,...
virtual QString xmlFile() const
This will return the name of the XML file as set by setXMLFile().
static QString readConfigFile(const QString &filename, const QString &componentName=QString())
static bool saveConfigFile(const QDomDocument &doc, const QString &filename, const QString &componentName=QString())
static QDomElement actionPropertiesElement(QDomDocument &doc)
static QDomElement findActionByName(QDomElement &elem, const QString &sName, bool create)
QAction * create(StandardAction id, const QObject *recvr, const char *slot, QObject *parent)
Category category(StandardShortcut id)
const QList< QKeySequence > & shortcut(StandardShortcut id)
QActionGroup * actionGroup() const const
void setEnabled(bool)
void hovered()
void setShortcuts(QKeySequence::StandardKey key)
QList< QKeySequence > shortcuts() const const
void triggered(bool checked)
void setVisible(bool)
ParseResult setContent(QAnyStringView text, ParseOptions options)
QDomNamedNodeMap attributes() const const
void removeAttribute(const QString &name)
void setAttribute(const QString &name, const QString &value)
int count() const const
bool isNull() const const
QDomNode removeChild(const QDomNode &oldChild)
QList< QKeySequence > listFromString(const QString &str, SequenceFormat format)
QString listToString(const QList< QKeySequence > &list, SequenceFormat format)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
iterator begin()
bool contains(const AT &value) const const
iterator end()
iterator erase(const_iterator begin, const_iterator end)
T & first()
bool isEmpty() const const
void push_back(parameter_type value)
qsizetype removeAll(const AT &t)
qsizetype size() const const
T value(qsizetype i) const const
QByteArray methodSignature() const const
Q_EMITQ_EMIT
bool blockSignals(bool block)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual void connectNotify(const QMetaMethod &signal)
void destroyed(QObject *obj)
bool disconnect(const QMetaObject::Connection &connection)
QList< T > findChildren(Qt::FindChildOptions options) const const
QObject * parent() const const
QVariant property(const char *name) const const
T qobject_cast(QObject *object)
QObject * sender() const const
void setObjectName(QAnyStringView name)
void setParent(QObject *parent)
bool setProperty(const char *name, QVariant &&value)
iterator insert(const T &value)
QList< T > values() const const
QString asprintf(const char *cformat,...)
bool isEmpty() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QVariant fromValue(T &&value)
bool isValid() const const
bool toBool() const const
T value() const const
QList< QAction * > actions() const const
QAction * addAction(const QIcon &icon, const QString &text)
void addActions(const QList< QAction * > &actions)
void removeAction(QAction *action)
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.