KGlobalAccel

kglobalaccel.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2001, 2002 Ellis Whitehead <ellis@kde.org>
4 SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
5 SPDX-FileCopyrightText: 2007 Andreas Hartmetz <ahartmetz@gmail.com>
6 SPDX-FileCopyrightText: 2008 Michael Jansen <kde@michael-jansen.biz>
7
8 SPDX-License-Identifier: LGPL-2.0-or-later
9*/
10
11#include "kglobalaccel.h"
12#include "kglobalaccel_debug.h"
13#include "kglobalaccel_p.h"
14
15#include <memory>
16
17#include <QAction>
18#include <QDBusMessage>
19#include <QDBusMetaType>
20#include <QGuiApplication>
21#include <QMessageBox>
22#include <QPushButton>
23#include <config-kglobalaccel.h>
24
25#if HAVE_X11
26#include <private/qtx11extras_p.h>
27#endif
28
29org::kde::kglobalaccel::Component *KGlobalAccelPrivate::getComponent(const QString &componentUnique, bool remember = false)
30{
31 // Check if we already have this component
32 {
33 auto component = components.value(componentUnique);
34 if (component) {
35 return component;
36 }
37 }
38
39 // Get the path for our component. We have to do that because
40 // componentUnique is probably not a valid dbus object path
41 QDBusReply<QDBusObjectPath> reply = iface()->getComponent(componentUnique);
42 if (!reply.isValid()) {
43 if (reply.error().name() == QLatin1String("org.kde.kglobalaccel.NoSuchComponent")) {
44 // No problem. The component doesn't exists. That's normal
45 return nullptr;
46 }
47
48 // An unknown error.
49 qCDebug(KGLOBALACCEL_LOG) << "Failed to get dbus path for component " << componentUnique << reply.error();
50 return nullptr;
51 }
52
53 // Now get the component
54 org::kde::kglobalaccel::Component *component =
55 new org::kde::kglobalaccel::Component(QStringLiteral("org.kde.kglobalaccel"), reply.value().path(), QDBusConnection::sessionBus(), q);
56
57 // No component no cleaning
58 if (!component->isValid()) {
59 qCDebug(KGLOBALACCEL_LOG) << "Failed to get component" << componentUnique << QDBusConnection::sessionBus().lastError();
60 return nullptr;
61 }
62
63 if (remember) {
64 // Connect to the signals we are interested in.
65 q->connect(component,
66 &org::kde::kglobalaccel::Component::globalShortcutPressed,
67 q,
68 [this](const QString &componentUnique, const QString &shortcutUnique, qlonglong timestamp) {
69 invokeAction(componentUnique, shortcutUnique, timestamp);
70 });
71
72 q->connect(component,
73 &org::kde::kglobalaccel::Component::globalShortcutReleased,
74 q,
75 [this](const QString &componentUnique, const QString &shortcutUnique, qlonglong) {
76 invokeDeactivate(componentUnique, shortcutUnique);
77 });
78
79 components[componentUnique] = component;
80 }
81
82 return component;
83}
84
85namespace
86{
87QString serviceName()
88{
89 return QStringLiteral("org.kde.kglobalaccel");
90}
91}
92
93void KGlobalAccelPrivate::cleanup()
94{
95 qDeleteAll(components);
96 delete m_iface;
97 m_iface = nullptr;
98 delete m_watcher;
99 m_watcher = nullptr;
100}
101
102KGlobalAccelPrivate::KGlobalAccelPrivate(KGlobalAccel *qq)
103 : q(qq)
104{
106 q->connect(m_watcher, &QDBusServiceWatcher::serviceOwnerChanged, q, [this](const QString &serviceName, const QString &oldOwner, const QString &newOwner) {
107 serviceOwnerChanged(serviceName, oldOwner, newOwner);
108 });
109}
110
111org::kde::KGlobalAccel *KGlobalAccelPrivate::iface()
112{
113 if (!m_iface) {
114 m_iface = new org::kde::KGlobalAccel(serviceName(), QStringLiteral("/kglobalaccel"), QDBusConnection::sessionBus());
115 // Make sure kglobalaccel is running. The iface declaration above somehow works anyway.
117 if (bus && !bus->isServiceRegistered(serviceName())) {
118 QDBusReply<void> reply = bus->startService(serviceName());
119 if (!reply.isValid()) {
120 qCritical() << "Couldn't start kglobalaccel from org.kde.kglobalaccel.service:" << reply.error();
121 }
122 }
123
124 q->connect(m_iface, &org::kde::KGlobalAccel::yourShortcutsChanged, q, [this](const QStringList &actionId, const QList<QKeySequence> &newKeys) {
125 shortcutsChanged(actionId, newKeys);
126 });
127 }
128 return m_iface;
129}
130
131KGlobalAccel::KGlobalAccel()
132 : d(new KGlobalAccelPrivate(this))
133{
134 qDBusRegisterMetaType<QList<int>>();
135 qDBusRegisterMetaType<QKeySequence>();
136 qDBusRegisterMetaType<QList<QKeySequence>>();
137 qDBusRegisterMetaType<QList<QStringList>>();
138 qDBusRegisterMetaType<KGlobalShortcutInfo>();
139 qDBusRegisterMetaType<QList<KGlobalShortcutInfo>>();
140 qDBusRegisterMetaType<KGlobalAccel::MatchType>();
141}
142
143KGlobalAccel::~KGlobalAccel()
144{
145 delete d;
146}
147
148// static
149bool KGlobalAccel::cleanComponent(const QString &componentUnique)
150{
151 org::kde::kglobalaccel::Component *component = self()->getComponent(componentUnique);
152 if (!component) {
153 return false;
154 }
155
156 return component->cleanUp();
157}
158
159// static
160bool KGlobalAccel::isComponentActive(const QString &componentUnique)
161{
162 org::kde::kglobalaccel::Component *component = self()->getComponent(componentUnique);
163 if (!component) {
164 return false;
165 }
166
167 return component->isActive();
168}
169
170org::kde::kglobalaccel::Component *KGlobalAccel::getComponent(const QString &componentUnique)
171{
172 return d->getComponent(componentUnique);
173}
174
175class KGlobalAccelSingleton
176{
177public:
178 KGlobalAccelSingleton();
179
180 KGlobalAccel instance;
181};
182
183Q_GLOBAL_STATIC(KGlobalAccelSingleton, s_instance)
184
185KGlobalAccelSingleton::KGlobalAccelSingleton()
186{
187 qAddPostRoutine([]() {
188 s_instance->instance.d->cleanup();
189 });
190}
191
193{
194 return &s_instance()->instance;
195}
196
197bool KGlobalAccelPrivate::doRegister(QAction *action)
198{
199 if (!action || action->objectName().isEmpty() || action->objectName().startsWith(QLatin1String("unnamed-"))) {
200 qWarning() << "Attempt to set global shortcut for action without objectName()."
201 " Read the setGlobalShortcut() documentation.";
202 return false;
203 }
204
205 const bool isRegistered = actions.contains(action);
206 if (isRegistered) {
207 return true;
208 }
209
210 QStringList actionId = makeActionId(action);
211
212 nameToAction.insert(actionId.at(KGlobalAccel::ActionUnique), action);
213 actions.insert(action);
214 iface()->doRegister(actionId);
215
216 QObject::connect(action, &QObject::destroyed, [this, action](QObject *) {
217 if (actions.contains(action) && (actionShortcuts.contains(action) || actionDefaultShortcuts.contains(action))) {
218 remove(action, KGlobalAccelPrivate::SetInactive);
219 }
220 });
221
222 return true;
223}
224
225void KGlobalAccelPrivate::remove(QAction *action, Removal removal)
226{
227 if (!action || action->objectName().isEmpty()) {
228 return;
229 }
230
231 const bool isRegistered = actions.contains(action);
232 if (!isRegistered) {
233 return;
234 }
235
236 QStringList actionId = makeActionId(action);
237
238 nameToAction.remove(actionId.at(KGlobalAccel::ActionUnique), action);
239 actions.remove(action);
240
241 if (removal == UnRegister) {
242 // Complete removal of the shortcut is requested
243 // (forgetGlobalShortcut)
244 unregister(actionId);
245 } else {
246 // If the action is a configurationAction wen only remove it from our
247 // internal registry. That happened above.
248
249 // If we are merely marking a callback as inactive there is nothing for kglobalaccel to do if kglobalaccel is not running
250 // this can happen on shutdown where all apps and kglobalaccel are all torn down at once
251 // For this reason we turn off the autostart flag in the DBus message call
252
253 if (!action->property("isConfigurationAction").toBool()) {
254 // If it's a session shortcut unregister it.
255 if (action->objectName().startsWith(QLatin1String("_k_session:"))) {
256 unregister(actionId);
257 } else {
258 setInactive(actionId);
259 }
260 }
261 }
262
263 actionDefaultShortcuts.remove(action);
264 actionShortcuts.remove(action);
265}
266
267void KGlobalAccelPrivate::unregister(const QStringList &actionId)
268{
269 const auto component = actionId.at(KGlobalAccel::ComponentUnique);
270 const auto action = actionId.at(KGlobalAccel::ActionUnique);
271
272 auto message = QDBusMessage::createMethodCall(iface()->service(), iface()->path(), iface()->interface(), QStringLiteral("unregister"));
273 message.setArguments({component, action});
274 message.setAutoStartService(false);
276}
277
278void KGlobalAccelPrivate::setInactive(const QStringList &actionId)
279{
280 auto message = QDBusMessage::createMethodCall(iface()->service(), iface()->path(), iface()->interface(), QStringLiteral("setInactive"));
281 message.setArguments({actionId});
282 message.setAutoStartService(false);
284}
285
286void KGlobalAccelPrivate::updateGlobalShortcut(/*const would be better*/ QAction *action,
287 ShortcutTypes actionFlags,
289{
290 // No action or no objectname -> Do nothing
291 if (!action || action->objectName().isEmpty()) {
292 return;
293 }
294
295 QStringList actionId = makeActionId(action);
296
297 uint setterFlags = 0;
298 if (globalFlags & NoAutoloading) {
299 setterFlags |= NoAutoloading;
300 }
301
302 if (actionFlags & ActiveShortcut) {
303 const QList<QKeySequence> activeShortcut = actionShortcuts.value(action);
304 bool isConfigurationAction = action->property("isConfigurationAction").toBool();
305 uint activeSetterFlags = setterFlags;
306
307 // setPresent tells kglobalaccel that the shortcut is active
308 if (!isConfigurationAction) {
309 activeSetterFlags |= SetPresent;
310 }
311
312 // Sets the shortcut, returns the active/real keys
313 const auto result = iface()->setShortcutKeys(actionId, activeShortcut, activeSetterFlags);
314
315 // Make sure we get informed about changes in the component by kglobalaccel
316 getComponent(componentUniqueForAction(action), true);
317
318 // Create a shortcut from the result
319 const QList<QKeySequence> scResult(result);
320
321 if (isConfigurationAction && (globalFlags & NoAutoloading)) {
322 // If this is a configuration action and we have set the shortcut,
323 // inform the real owner of the change.
324 // Note that setForeignShortcut will cause a signal to be sent to applications
325 // even if it did not "see" that the shortcut has changed. This is Good because
326 // at the time of comparison (now) the action *already has* the new shortcut.
327 // We called setShortcut(), remember?
328 // Also note that we will see our own signal so we may not need to call
329 // setActiveGlobalShortcutNoEnable - shortcutGotChanged() does it.
330 // In practice it's probably better to get the change propagated here without
331 // DBus delay as we do below.
332 iface()->setForeignShortcutKeys(actionId, result);
333 }
334 if (scResult != activeShortcut) {
335 // If kglobalaccel returned a shortcut that differs from the one we
336 // sent, use that one. There must have been clashes or some other problem.
337 actionShortcuts.insert(action, scResult);
338 Q_EMIT q->globalShortcutChanged(action, scResult.isEmpty() ? QKeySequence() : scResult.first());
339 }
340 }
341
342 if (actionFlags & DefaultShortcut) {
343 const QList<QKeySequence> defaultShortcut = actionDefaultShortcuts.value(action);
344 iface()->setShortcutKeys(actionId, defaultShortcut, setterFlags | IsDefault);
345 }
346}
347
348QStringList KGlobalAccelPrivate::makeActionId(const QAction *action)
349{
350 QStringList ret(componentUniqueForAction(action)); // Component Unique Id ( see actionIdFields )
351 Q_ASSERT(!ret.at(KGlobalAccel::ComponentUnique).isEmpty());
352 Q_ASSERT(!action->objectName().isEmpty());
353 ret.append(action->objectName()); // Action Unique Name
354 ret.append(componentFriendlyForAction(action)); // Component Friendly name
355 const QString actionText = action->text().replace(QLatin1Char('&'), QStringLiteral(""));
356 ret.append(actionText); // Action Friendly Name
357 return ret;
358}
359
360QList<int> KGlobalAccelPrivate::intListFromShortcut(const QList<QKeySequence> &cut)
361{
362 QList<int> ret;
363 for (const QKeySequence &sequence : cut) {
364 ret.append(sequence[0].toCombined());
365 }
366 while (!ret.isEmpty() && ret.last() == 0) {
367 ret.removeLast();
368 }
369 return ret;
370}
371
372QList<QKeySequence> KGlobalAccelPrivate::shortcutFromIntList(const QList<int> &list)
373{
375 ret.reserve(list.size());
376 std::transform(list.begin(), list.end(), std::back_inserter(ret), [](int i) {
377 return QKeySequence(i);
378 });
379 return ret;
380}
381
382QString KGlobalAccelPrivate::componentUniqueForAction(const QAction *action)
383{
384 if (!action->property("componentName").isValid()) {
386 } else {
387 return action->property("componentName").toString();
388 }
389}
390
391QString KGlobalAccelPrivate::componentFriendlyForAction(const QAction *action)
392{
393 QString property = action->property("componentDisplayName").toString();
394 if (!property.isEmpty()) {
395 return property;
396 }
399 }
401}
402
403#if HAVE_X11
404int timestampCompare(unsigned long time1_, unsigned long time2_) // like strcmp()
405{
406 quint32 time1 = time1_;
407 quint32 time2 = time2_;
408 if (time1 == time2) {
409 return 0;
410 }
411 return quint32(time1 - time2) < 0x7fffffffU ? 1 : -1; // time1 > time2 -> 1, handle wrapping
412}
413#endif
414
415QAction *KGlobalAccelPrivate::findAction(const QString &componentUnique, const QString &actionUnique)
416{
417 QAction *action = nullptr;
418 const QList<QAction *> candidates = nameToAction.values(actionUnique);
419 for (QAction *const a : candidates) {
420 if (componentUniqueForAction(a) == componentUnique) {
421 action = a;
422 }
423 }
424
425 // We do not trigger if
426 // - there is no action
427 // - the action is not enabled
428 // - the action is an configuration action
429 if (!action || !action->isEnabled() || action->property("isConfigurationAction").toBool()) {
430 return nullptr;
431 }
432 return action;
433}
434
435void KGlobalAccelPrivate::invokeAction(const QString &componentUnique, const QString &actionUnique, qlonglong timestamp)
436{
437 QAction *action = findAction(componentUnique, actionUnique);
438 if (!action) {
439 return;
440 }
441
442#if HAVE_X11
443 // Update this application's X timestamp if needed.
444 // TODO The 100%-correct solution should probably be handling this action
445 // in the proper place in relation to the X events queue in order to avoid
446 // the possibility of wrong ordering of user events.
447 if (QX11Info::isPlatformX11()) {
448 if (timestampCompare(timestamp, QX11Info::appTime()) > 0) {
449 QX11Info::setAppTime(timestamp);
450 }
451 if (timestampCompare(timestamp, QX11Info::appUserTime()) > 0) {
452 QX11Info::setAppUserTime(timestamp);
453 }
454 }
455#endif
456 action->setProperty("org.kde.kglobalaccel.activationTimestamp", timestamp);
457
458 if (m_lastActivatedAction != action) {
459 Q_EMIT q->globalShortcutActiveChanged(action, true);
460 m_lastActivatedAction = action;
461 }
462 action->trigger();
463}
464
465void KGlobalAccelPrivate::invokeDeactivate(const QString &componentUnique, const QString &actionUnique)
466{
467 QAction *action = findAction(componentUnique, actionUnique);
468 if (!action) {
469 return;
470 }
471
472 m_lastActivatedAction.clear();
473
474 Q_EMIT q->globalShortcutActiveChanged(action, false);
475}
476
477void KGlobalAccelPrivate::shortcutsChanged(const QStringList &actionId, const QList<QKeySequence> &keys)
478{
479 QAction *action = nameToAction.value(actionId.at(KGlobalAccel::ActionUnique));
480 if (!action) {
481 return;
482 }
483
484 actionShortcuts.insert(action, keys);
485 Q_EMIT q->globalShortcutChanged(action, keys.isEmpty() ? QKeySequence() : keys.first());
486}
487
488void KGlobalAccelPrivate::serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
489{
490 Q_UNUSED(oldOwner);
491 if (name == QLatin1String("org.kde.kglobalaccel") && !newOwner.isEmpty()) {
492 // kglobalaccel was restarted
493 qCDebug(KGLOBALACCEL_LOG) << "detected kglobalaccel restarting, re-registering all shortcut keys";
494 reRegisterAll();
495 }
496}
497
498void KGlobalAccelPrivate::reRegisterAll()
499{
500 // We clear all our data, assume that all data on the other side is clear too,
501 // and register each action as if it just was allowed to have global shortcuts.
502 // If the kded side still has the data it doesn't matter because of the
503 // autoloading mechanism. The worst case I can imagine is that an action's
504 // shortcut was changed but the kded side died before it got the message so
505 // autoloading will now assign an old shortcut to the action. Particularly
506 // picky apps might assert or misbehave.
507 const QSet<QAction *> allActions = actions;
508 nameToAction.clear();
509 actions.clear();
510 for (QAction *const action : allActions) {
511 if (doRegister(action)) {
512 updateGlobalShortcut(action, ActiveShortcut, KGlobalAccel::Autoloading);
513 }
514 }
515}
516
518{
519 return self()->d->iface()->globalShortcutsByKey(seq, type);
520}
521
523{
524 return self()->d->iface()->globalShortcutAvailable(seq, comp);
525}
526
527// static
529{
530 if (shortcuts.isEmpty()) {
531 // Usage error. Just say no
532 return false;
533 }
534
535 QString component = shortcuts[0].componentFriendlyName();
536
537 QString message;
538 if (shortcuts.size() == 1) {
539 message = tr("The '%1' key combination is registered by application %2 for action %3.").arg(seq.toString(), component, shortcuts[0].friendlyName());
540 } else {
541 QString actionList;
542 for (const KGlobalShortcutInfo &info : shortcuts) {
543 actionList += tr("In context '%1' for action '%2'\n").arg(info.contextFriendlyName(), info.friendlyName());
544 }
545 message = tr("The '%1' key combination is registered by application %2.\n%3").arg(seq.toString(), component, actionList);
546 }
547
548 QString title = tr("Conflict With Registered Global Shortcut");
549
550 QMessageBox box(parent);
551 box.setWindowTitle(title);
552 box.setText(message);
553 box.addButton(QMessageBox::Ok)->setText(tr("Reassign"));
555
556 return box.exec() == QMessageBox::Ok;
557}
558
559// static
561{
562 // get the shortcut, remove seq, and set the new shortcut
563 const QStringList actionId = self()->d->iface()->actionList(seq);
564 if (actionId.size() < 4) { // not a global shortcut
565 return;
566 }
567 QList<QKeySequence> sc = self()->d->iface()->shortcutKeys(actionId);
568
569 for (int i = 0; i < sc.count(); i++) {
570 if (sc[i] == seq) {
571 sc[i] = QKeySequence();
572 }
573 }
574
575 self()->d->iface()->setForeignShortcutKeys(actionId, sc);
576}
577
578bool checkGarbageKeycode(const QList<QKeySequence> &shortcut)
579{
580 // protect against garbage keycode -1 that Qt sometimes produces for exotic keys;
581 // at the moment (~mid 2008) Multimedia PlayPause is one of those keys.
582 for (const QKeySequence &sequence : shortcut) {
583 for (int i = 0; i < 4; i++) {
584 if (sequence[i].toCombined() == -1) {
585 qWarning() << "Encountered garbage keycode (keycode = -1) in input, not doing anything.";
586 return true;
587 }
588 }
589 }
590 return false;
591}
592
594{
595 if (checkGarbageKeycode(shortcut)) {
596 return false;
597 }
598
599 if (!d->doRegister(action)) {
600 return false;
601 }
602
603 d->actionDefaultShortcuts.insert(action, shortcut);
604 d->updateGlobalShortcut(action, KGlobalAccelPrivate::DefaultShortcut, loadFlag);
605 return true;
606}
607
609{
610 if (checkGarbageKeycode(shortcut)) {
611 return false;
612 }
613
614 if (!d->doRegister(action)) {
615 return false;
616 }
617
618 d->actionShortcuts.insert(action, shortcut);
619 d->updateGlobalShortcut(action, KGlobalAccelPrivate::ActiveShortcut, loadFlag);
620 return true;
621}
622
624{
625 return d->actionDefaultShortcuts.value(action);
626}
627
629{
630 return d->actionShortcuts.value(action);
631}
632
633QList<QKeySequence> KGlobalAccel::globalShortcut(const QString &componentName, const QString &actionId) const
634{
635 // see also d->updateGlobalShortcut(action, KGlobalAccelPrivate::ActiveShortcut, KGlobalAccel::Autoloading);
636
637 // how componentName and actionId map to QAction, e.g:
638 // action->setProperty("componentName", "kwin");
639 // action->setObjectName("Kill Window");
640
641 const QList<QKeySequence> scResult = self()->d->iface()->shortcutKeys({componentName, actionId, QString(), QString()});
642 return scResult;
643}
644
646{
647 d->remove(action, KGlobalAccelPrivate::UnRegister);
648}
649
650bool KGlobalAccel::hasShortcut(const QAction *action) const
651{
652 return d->actionShortcuts.contains(action) || d->actionDefaultShortcuts.contains(action);
653}
654
656{
658 return g->d->setShortcutWithDefault(action, shortcut, Autoloading);
659}
660
665
666bool KGlobalAccelPrivate::setShortcutWithDefault(QAction *action, const QList<QKeySequence> &shortcut, KGlobalAccel::GlobalShortcutLoading loadFlag)
667{
668 if (checkGarbageKeycode(shortcut)) {
669 return false;
670 }
671
672 if (!doRegister(action)) {
673 return false;
674 }
675
676 actionDefaultShortcuts.insert(action, shortcut);
677 actionShortcuts.insert(action, shortcut);
678 updateGlobalShortcut(action, KGlobalAccelPrivate::DefaultShortcut | KGlobalAccelPrivate::ActiveShortcut, loadFlag);
679 return true;
680}
681
683{
684 argument.beginStructure();
685 argument << static_cast<int>(type);
686 argument.endStructure();
687 return argument;
688}
689
691{
692 argument.beginStructure();
693 int arg;
694 argument >> arg;
695 type = static_cast<KGlobalAccel::MatchType>(arg);
696 argument.endStructure();
697 return argument;
698}
699
700#include "moc_kglobalaccel.cpp"
Configurable global shortcut support.
static QList< KGlobalShortcutInfo > globalShortcutsByKey(const QKeySequence &seq, MatchType type=Equal)
Returns a list of global shortcuts registered for the shortcut seq.
bool hasShortcut(const QAction *action) const
Returns true if a shortcut or a default shortcut has been registered for the given action.
static bool promptStealShortcutSystemwide(QWidget *parent, const QList< KGlobalShortcutInfo > &shortcuts, const QKeySequence &seq)
Show a messagebox to inform the user that a global shortcut is already occupied, and ask to take it a...
static void stealShortcutSystemwide(const QKeySequence &seq)
Take away the given shortcut from the named action it belongs to.
static bool isComponentActive(const QString &componentName)
Check if component is active.
MatchType
Keysequence match semantics.
static bool cleanComponent(const QString &componentUnique)
Clean the shortcuts for component componentUnique.
static KGlobalAccel * self()
Returns (and creates if necessary) the singleton instance.
bool setShortcut(QAction *action, const QList< QKeySequence > &shortcut, GlobalShortcutLoading loadFlag=Autoloading)
Assign a global shortcut for the given action.
GlobalShortcutLoading
An enum about global shortcut setter semantics.
@ Autoloading
Look up the action in global settings (using its main component's name and text()) and set the shortc...
void removeAllShortcuts(QAction *action)
Unregister and remove all defined global shortcuts for the given action.
bool setDefaultShortcut(QAction *action, const QList< QKeySequence > &shortcut, GlobalShortcutLoading loadFlag=Autoloading)
Assign a default global shortcut for a given QAction.
static bool isGlobalShortcutAvailable(const QKeySequence &seq, const QString &component=QString())
Check if the shortcut @seq is available for the component.
static bool setGlobalShortcut(QAction *action, const QList< QKeySequence > &shortcut)
Convenient method to set both active and default shortcut.
QList< QKeySequence > shortcut(const QAction *action) const
Get the global shortcut for this action, if one exists.
QList< QKeySequence > globalShortcut(const QString &componentName, const QString &actionId) const
Retrieves the shortcut as defined in global settings by componentName (e.g.
@ ComponentUnique
Components Unique Name (ID)
@ ActionUnique
Actions Unique Name(ID)
QList< QKeySequence > defaultShortcut(const QAction *action) const
Get the global default shortcut for this action, if one exists.
Type type(const QSqlDatabase &db)
KCALENDARCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &)
QString path(const QString &relativePath)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
const QList< QKeySequence > & cut()
QDebug operator<<(QDebug dbg, const PerceptualColor::LchaDouble &value)
void setText(const QString &text)
bool isEnabled() const const
void trigger()
void beginStructure()
void endStructure()
QDBusMessage call(const QDBusMessage &message, QDBus::CallMode mode, int timeout) const const
QDBusConnectionInterface * interface() const const
QDBusError lastError() const const
QDBusConnection sessionBus()
QDBusReply< bool > isServiceRegistered(const QString &serviceName) const const
QDBusReply< void > startService(const QString &name)
QString name() const const
QDBusMessage createMethodCall(const QString &service, const QString &path, const QString &interface, const QString &method)
const QDBusError & error()
bool isValid() const const
void serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner)
QString toString(SequenceFormat format) const const
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
iterator begin()
qsizetype count() const const
iterator end()
bool isEmpty() const const
T & last()
void removeLast()
void reserve(qsizetype size)
qsizetype size() const const
T value(qsizetype i) const const
QPushButton * addButton(StandardButton button)
virtual int exec() override
void setWindowTitle(const QString &title)
void setText(const QString &text)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void destroyed(QObject *obj)
QObject * parent() const const
QVariant property(const char *name) const const
bool setProperty(const char *name, QVariant &&value)
QString tr(const char *sourceText, const char *disambiguation, int n)
void clear()
QString arg(Args &&... args) const const
bool isEmpty() const const
bool isValid() const const
bool toBool() const const
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:15:12 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.