KXmlGui

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

KDE's Doxygen guidelines are available online.