KWallet

kwallet_mac.cpp
1/*
2 This file is part of the KDE project
3
4 SPDX-FileCopyrightText: 2002-2004 George Staikos <staikos@kde.org>
5 SPDX-FileCopyrightText: 2008 Michael Leupold <lemma@confuego.org>
6 SPDX-FileCopyrightText: 2010 Frank Osterfeld <osterfeld@kde.org>
7
8 SPDX-License-Identifier: LGPL-2.0-or-later
9*/
10
11#include "kwallet.h"
12#include <KConfigGroup>
13#include <KSharedConfig>
14
15#include <QApplication>
16#include <QDebug>
17#include <QPointer>
18#include <QWidget>
19
20#include <Carbon/Carbon.h>
21#include <Security/SecKeychain.h>
22#include <Security/Security.h>
23
24// TODO: OSX_KEYCHAIN_PORT_DISABLED is never defined, all the enclosing code should be removed
25
26using namespace KWallet;
27
29Q_DECLARE_METATYPE(StringStringMap)
31Q_DECLARE_METATYPE(StringToStringStringMapMap)
33Q_DECLARE_METATYPE(StringByteArrayMap)
34
35namespace
36{
37template<typename T>
38struct CFReleaser {
39 explicit CFReleaser(const T &r)
40 : ref(r)
41 {
42 }
43 ~CFReleaser()
44 {
45 CFRelease(ref);
46 }
47 T ref;
48};
49}
50
51static QString asQString(CFStringRef sr)
52{
53 return QString::fromLatin1(CFStringGetCStringPtr(sr, NULL)); // TODO Latin1 correct?
54}
55
56static QString errorString(OSStatus s)
57{
58 const CFReleaser<CFStringRef> ref(SecCopyErrorMessageString(s, NULL));
59 return asQString(ref.ref);
60}
61
62static bool isError(OSStatus s, QString *errMsg)
63{
64 if (errMsg) {
65 *errMsg = errorString(s);
66 }
67 return s != 0;
68}
69
70static QString appid()
71{
72 return qApp->applicationName();
73}
74
75static OSStatus removeEntryImplementation(const QString &walletName, const QString &key)
76{
77 const QByteArray serviceName(walletName.toUtf8());
78 const QByteArray accountName(key.toUtf8());
79 SecKeychainItemRef itemRef;
80 QString errMsg;
81 OSStatus result =
82 SecKeychainFindGenericPassword(NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), NULL, NULL, &itemRef);
83 if (isError(result, &errMsg)) {
84 qWarning() << "Could not retrieve password:" << qPrintable(errMsg);
85 return result;
86 }
87 const CFReleaser<SecKeychainItemRef> itemReleaser(itemRef);
88 result = SecKeychainItemDelete(itemRef);
89 if (isError(result, &errMsg)) {
90 qWarning() << "Could not delete password:" << qPrintable(errMsg);
91 return result;
92 }
93 return result;
94}
95
97{
98 KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("kwalletrc"))->group("Wallet"));
99 if (!cfg.readEntry("Use One Wallet", true)) {
100 QString tmp = cfg.readEntry("Local Wallet", "localwallet");
101 if (tmp.isEmpty()) {
102 return QStringLiteral("localwallet");
103 }
104 return tmp;
105 }
106
107 QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
108 if (tmp.isEmpty()) {
109 return QStringLiteral("kdewallet");
110 }
111 return tmp;
112}
113
115{
116 KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("kwalletrc"))->group("Wallet"));
117
118 QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
119 if (tmp.isEmpty()) {
120 return QStringLiteral("kdewallet");
121 }
122 return tmp;
123}
124
126{
127 return QStringLiteral("Passwords");
128}
129
131{
132 return QStringLiteral("Form Data");
133}
134
135class Q_DECL_HIDDEN Wallet::WalletPrivate
136{
137public:
138 WalletPrivate(Wallet *wallet, int h, const QString &n)
139 : q(wallet)
140 , name(n)
141 , handle(h)
142 {
143 }
144
145 void walletServiceUnregistered();
146
147 Wallet *q;
149 QString folder;
150 int handle;
151 int transactionId;
152};
153
154void Wallet::WalletPrivate::walletServiceUnregistered()
155{
156 if (handle >= 0) {
157 q->slotWalletClosed(handle);
158 }
159}
160
161Wallet::Wallet(int handle, const QString &name)
162 : QObject(0L)
163 , d(new WalletPrivate(this, handle, name))
164{
165 Q_UNUSED(handle);
166}
167
169{
170 delete d;
171}
172
174{
175#ifdef OSX_KEYCHAIN_PORT_DISABLED
176 return walletLauncher->getInterface().wallets();
177#else
178 return QStringList();
179#endif
180}
181
182void Wallet::changePassword(const QString &name, WId w)
183{
184#ifdef OSX_KEYCHAIN_PORT_DISABLED
185 if (w == 0) {
186 qDebug() << "Pass a valid window to KWallet::Wallet::changePassword().";
187 }
188 walletLauncher->getInterface().changePassword(name, (qlonglong)w, appid());
189#endif
190}
191
193{
194 // PENDING(frank) check
195 return true;
196}
197
198bool Wallet::isOpen(const QString &name)
199{
200#ifdef OSX_KEYCHAIN_PORT_DISABLED
201 return walletLauncher->getInterface().isOpen(name); // default is false
202#else
203 return true;
204#endif
205}
206
207int Wallet::closeWallet(const QString &name, bool force)
208{
209#ifdef OSX_KEYCHAIN_PORT_DISABLED
210 QDBusReply<int> r = walletLauncher->getInterface().close(name, force);
211 return r.isValid() ? r : -1;
212#else
213 return 0;
214#endif
215}
216
217int Wallet::deleteWallet(const QString &name)
218{
219#ifdef OSX_KEYCHAIN_PORT_DISABLED
220 QDBusReply<int> r = walletLauncher->getInterface().deleteWallet(name);
221 return r.isValid() ? r : -1;
222#else
223 return -1;
224#endif
225}
226
227Wallet *Wallet::openWallet(const QString &name, WId w, OpenType ot)
228{
229 Q_UNUSED(w);
230 Q_UNUSED(ot);
231 Wallet *wallet = new Wallet(-1, name);
232 QMetaObject::invokeMethod(wallet, "emitWalletOpened", Qt::QueuedConnection);
233 return wallet;
234}
235
236bool Wallet::disconnectApplication(const QString &wallet, const QString &app)
237{
238#ifdef OSX_KEYCHAIN_PORT_DISABLED
239 return walletLauncher->getInterface().disconnectApplication(wallet, app); // default is false
240#else
241 return true;
242#endif
243}
244
246{
247#ifdef OSX_KEYCHAIN_PORT_DISABLED
248 return walletLauncher->getInterface().users(name); // default is QStringList()
249#else
250 return QStringList();
251#endif
252}
253
254int Wallet::sync()
255{
256#ifdef OSX_KEYCHAIN_PORT_DISABLED
257 if (d->handle == -1) {
258 return -1;
259 }
260
261 walletLauncher->getInterface().sync(d->handle, appid());
262#endif
263 return 0;
264}
265
267{
268#ifdef OSX_KEYCHAIN_PORT_DISABLED
269 if (d->handle == -1) {
270 return -1;
271 }
272
273 QDBusReply<int> r = walletLauncher->getInterface().close(d->handle, true, appid());
274 d->handle = -1;
275 d->folder.clear();
276 d->name.clear();
277 if (r.isValid()) {
278 return r;
279 }
280#endif
281 return -1;
282}
283
284const QString &Wallet::walletName() const
285{
286 return d->name;
287}
288
289bool Wallet::isOpen() const
290{
291#ifdef OSX_KEYCHAIN_PORT_DISABLED
292 return d->handle != -1;
293#else
294 return true;
295#endif
296}
297
299{
300#ifdef OSX_KEYCHAIN_PORT_DISABLED
301 if (w == 0) {
302 qDebug() << "Pass a valid window to KWallet::Wallet::requestChangePassword().";
303 }
304 if (d->handle == -1) {
305 return;
306 }
307
308 walletLauncher->getInterface().changePassword(d->name, (qlonglong)w, appid());
309#endif
310}
311
312void Wallet::slotWalletClosed(int handle)
313{
314#ifdef OSX_KEYCHAIN_PORT_DISABLED
315 if (d->handle == handle) {
316 d->handle = -1;
317 d->folder.clear();
318 d->name.clear();
320 }
321#endif
322}
323
325{
326#ifdef OSX_KEYCHAIN_PORT_DISABLED
327 if (d->handle == -1) {
328 return QStringList();
329 }
330
331 QDBusReply<QStringList> r = walletLauncher->getInterface().folderList(d->handle, appid());
332 return r;
333#else
334 return QStringList();
335#endif
336}
337
339{
340#ifdef OSX_KEYCHAIN_PORT_DISABLED
341 if (d->handle == -1) {
342 return QStringList();
343 }
344
345 QDBusReply<QStringList> r = walletLauncher->getInterface().entryList(d->handle, d->folder, appid());
346 return r;
347#else
348 return QStringList();
349#endif
350}
351
352bool Wallet::hasFolder(const QString &f)
353{
354#ifdef OSX_KEYCHAIN_PORT_DISABLED
355 if (d->handle == -1) {
356 return false;
357 }
358
359 QDBusReply<bool> r = walletLauncher->getInterface().hasFolder(d->handle, f, appid());
360 return r; // default is false
361#else
362 return true;
363#endif
364}
365
366bool Wallet::createFolder(const QString &f)
367{
368#ifdef OSX_KEYCHAIN_PORT_DISABLED
369 if (d->handle == -1) {
370 return false;
371 }
372
373 if (!hasFolder(f)) {
374 QDBusReply<bool> r = walletLauncher->getInterface().createFolder(d->handle, f, appid());
375 return r;
376 }
377
378 return true; // folder already exists
379#else
380 return true;
381#endif
382}
383
384bool Wallet::setFolder(const QString &f)
385{
386#ifdef OSX_KEYCHAIN_PORT_DISABLED
387 bool rc = false;
388
389 if (d->handle == -1) {
390 return rc;
391 }
392
393 // Don't do this - the folder could have disappeared?
394#if 0
395 if (f == d->folder) {
396 return true;
397 }
398#endif
399
400 if (hasFolder(f)) {
401 d->folder = f;
402 rc = true;
403 }
404
405 return rc;
406#else
407 return true;
408#endif
409}
410
411bool Wallet::removeFolder(const QString &f)
412{
413#ifdef OSX_KEYCHAIN_PORT_DISABLED
414 if (d->handle == -1) {
415 return false;
416 }
417
418 QDBusReply<bool> r = walletLauncher->getInterface().removeFolder(d->handle, f, appid());
419 if (d->folder == f) {
421 }
422
423 return r; // default is false
424#else
425 return true;
426#endif
427}
428
429const QString &Wallet::currentFolder() const
430{
431 return d->folder;
432}
433
434int Wallet::readEntry(const QString &key, QByteArray &value)
435{
436 const QByteArray serviceName(walletName().toUtf8());
437 const QByteArray accountName(key.toUtf8());
438 UInt32 passwordSize = 0;
439 void *passwordData = 0;
440 QString errMsg;
441 if (isError(SecKeychainFindGenericPassword(NULL,
442 serviceName.size(),
443 serviceName.constData(),
444 accountName.size(),
445 accountName.constData(),
446 &passwordSize,
447 &passwordData,
448 NULL),
449 &errMsg)) {
450 qWarning() << "Could not retrieve password:" << qPrintable(errMsg);
451 return -1;
452 }
453
454 value = QByteArray(reinterpret_cast<const char *>(passwordData), passwordSize);
455 SecKeychainItemFreeContent(NULL, passwordData);
456 return 0;
457}
458
459int Wallet::readEntryList(const QString &key, QMap<QString, QByteArray> &value)
460{
461#ifdef OSX_KEYCHAIN_PORT_DISABLED
462 registerTypes();
463
464 int rc = -1;
465
466 if (d->handle == -1) {
467 return rc;
468 }
469
470 QDBusReply<QVariantMap> r = walletLauncher->getInterface().readEntryList(d->handle, d->folder, key, appid());
471 if (r.isValid()) {
472 rc = 0;
473 // convert <QString, QVariant> to <QString, QByteArray>
474 const QVariantMap val = r.value();
475 for (QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it) {
476 value.insert(it.key(), it.value().toByteArray());
477 }
478 }
479
480 return rc;
481#else
482 return -1;
483#endif
484}
485
486int Wallet::renameEntry(const QString &oldName, const QString &newName)
487{
488#ifdef OSX_KEYCHAIN_PORT_DISABLED
489 int rc = -1;
490
491 if (d->handle == -1) {
492 return rc;
493 }
494
495 QDBusReply<int> r = walletLauncher->getInterface().renameEntry(d->handle, d->folder, oldName, newName, appid());
496 if (r.isValid()) {
497 rc = r;
498 }
499
500 return rc;
501#else
502 return -1;
503#endif
504}
505
506int Wallet::readMap(const QString &key, QMap<QString, QString> &value)
507{
508 QByteArray v;
509 const int ret = readEntry(key, v);
510 if (ret != 0) {
511 return ret;
512 }
513 if (!v.isEmpty()) {
515 ds >> value;
516 }
517 return 0;
518}
519
520int Wallet::readMapList(const QString &key, QMap<QString, QMap<QString, QString>> &value)
521{
522#ifdef OSX_KEYCHAIN_PORT_DISABLED
523 registerTypes();
524
525 int rc = -1;
526
527 if (d->handle == -1) {
528 return rc;
529 }
530
531 QDBusReply<QVariantMap> r = walletLauncher->getInterface().readMapList(d->handle, d->folder, key, appid());
532 if (r.isValid()) {
533 rc = 0;
534 const QVariantMap val = r.value();
535 for (QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it) {
536 QByteArray mapData = it.value().toByteArray();
537 if (!mapData.isEmpty()) {
538 QDataStream ds(&mapData, QIODevice::ReadOnly);
540 ds >> v;
541 value.insert(it.key(), v);
542 }
543 }
544 }
545
546 return rc;
547#else
548 return -1;
549#endif
550}
551
552int Wallet::readPassword(const QString &key, QString &value)
553{
554 QByteArray ba;
555 const int ret = readEntry(key, ba);
556 if (ret == 0) {
557 value = QString::fromUtf8(ba.constData());
558 }
559 return ret;
560}
561
562int Wallet::readPasswordList(const QString &key, QMap<QString, QString> &value)
563{
564 return -1;
565}
566
567static OSStatus writeEntryImplementation(const QString &walletName, const QString &key, const QByteArray &value)
568{
569 const QByteArray serviceName(walletName.toUtf8());
570 const QByteArray accountName(key.toUtf8());
571 QString errMsg;
572 OSStatus err = SecKeychainAddGenericPassword(NULL,
573 serviceName.size(),
574 serviceName.constData(),
575 accountName.size(),
576 accountName.constData(),
577 value.size(),
578 value.constData(),
579 NULL);
580 if (err == errSecDuplicateItem) {
581 err = removeEntryImplementation(walletName, key);
582 if (isError(err, &errMsg)) {
583 qWarning() << "Could not delete old key in keychain for replacing: " << qPrintable(errMsg);
584 return err;
585 }
586 }
587 if (isError(err, &errMsg)) {
588 qWarning() << "Could not store password in keychain: " << qPrintable(errMsg);
589 return err;
590 }
591 // qDebug() << "Successfully written out key:" << key;
592 return err;
593}
594
595int Wallet::writeEntry(const QString &key, const QByteArray &password, EntryType entryType)
596{
597 Q_UNUSED(entryType)
598 return writeEntryImplementation(walletName(), key, password);
599}
600
601int Wallet::writeEntry(const QString &key, const QByteArray &value)
602{
603 return writeEntryImplementation(walletName(), key, value);
604}
605
606int Wallet::writeMap(const QString &key, const QMap<QString, QString> &value)
607{
608 QByteArray mapData;
609 QDataStream ds(&mapData, QIODevice::WriteOnly);
610 ds << value;
611 return writeEntry(key, mapData);
612}
613
614int Wallet::writePassword(const QString &key, const QString &value)
615{
616 return writeEntry(key, value.toUtf8());
617}
618
619bool Wallet::hasEntry(const QString &key)
620{
621 const QByteArray serviceName(walletName().toUtf8());
622 const QByteArray accountName(key.toUtf8());
623 return !isError(
624 SecKeychainFindGenericPassword(NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), NULL, NULL, NULL),
625 0);
626}
627
628int Wallet::removeEntry(const QString &key)
629{
630 return removeEntryImplementation(walletName(), key);
631}
632
633Wallet::EntryType Wallet::entryType(const QString &key)
634{
635#ifdef OSX_KEYCHAIN_PORT_DISABLED
636 int rc = 0;
637
638 if (d->handle == -1) {
639 return Wallet::Unknown;
640 }
641
642 QDBusReply<int> r = walletLauncher->getInterface().entryType(d->handle, d->folder, key, appid());
643 if (r.isValid()) {
644 rc = r;
645 }
646
647 return static_cast<EntryType>(rc);
648#else
649 return Wallet::Unknown;
650#endif
651}
652
653void Wallet::slotFolderUpdated(const QString &wallet, const QString &folder)
654{
655 if (d->name == wallet) {
656 Q_EMIT folderUpdated(folder);
657 }
658}
659
660void Wallet::slotFolderListUpdated(const QString &wallet)
661{
662 if (d->name == wallet) {
664 }
665}
666
667void Wallet::slotApplicationDisconnected(const QString &wallet, const QString &application)
668{
669#ifdef OSX_KEYCHAIN_PORT_DISABLED
670 if (d->handle >= 0 && d->name == wallet && application == appid()) {
671 slotWalletClosed(d->handle);
672 }
673#endif
674}
675
676void Wallet::walletAsyncOpened(int tId, int handle)
677{
678#ifdef OSX_KEYCHAIN_PORT_DISABLED
679 // ignore responses to calls other than ours
680 if (d->transactionId != tId || d->handle != -1) {
681 return;
682 }
683
684 // disconnect the async signal
685 disconnect(this, SLOT(walletAsyncOpened(int, int)));
686
687 d->handle = handle;
688 Q_EMIT walletOpened(handle > 0);
689#endif
690}
691
692void Wallet::emitWalletAsyncOpenError()
693{
694 Q_EMIT walletOpened(false);
695}
696
697void Wallet::emitWalletOpened()
698{
699 Q_EMIT walletOpened(true);
700}
701
702bool Wallet::folderDoesNotExist(const QString &wallet, const QString &folder)
703{
704#ifdef OSX_KEYCHAIN_PORT_DISABLED
705 QDBusReply<bool> r = walletLauncher->getInterface().folderDoesNotExist(wallet, folder);
706 return r;
707#else
708 return false;
709#endif
710}
711
712bool Wallet::keyDoesNotExist(const QString &wallet, const QString &folder, const QString &key)
713{
714#ifdef OSX_KEYCHAIN_PORT_DISABLED
715 QDBusReply<bool> r = walletLauncher->getInterface().keyDoesNotExist(wallet, folder, key);
716 return r;
717#else
718 return false;
719#endif
720}
721
722void Wallet::slotCollectionStatusChanged(int status)
723{
724}
725
726void Wallet::slotCollectionDeleted()
727{
728 d->folder.clear();
729 d->name.clear();
731}
732
733void Wallet::virtual_hook(int, void *)
734{
735 // BASE::virtual_hook( id, data );
736}
737
738#include "moc_kwallet.cpp"
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
KDE Wallet.
Definition kwallet.h:48
static const QString PasswordFolder()
The standardized name of the password folder.
Definition kwallet.cpp:87
Wallet(int handle, const QString &name)
Construct a KWallet object.
Definition kwallet.cpp:118
virtual void virtual_hook(int id, void *data)
Definition kwallet.cpp:878
virtual int renameEntry(const QString &oldName, const QString &newName)
Rename the entry oldName to newName.
Definition kwallet.cpp:561
virtual int sync()
This syncs the wallet file on disk with what is in memory.
Definition kwallet.cpp:343
virtual bool createFolder(const QString &f)
Created the folder f.
Definition kwallet.cpp:449
virtual int lockWallet()
This closes and locks the current wallet.
Definition kwallet.cpp:353
static QStringList users(const QString &wallet)
List the applications that are using the wallet wallet.
Definition kwallet.cpp:328
virtual int removeEntry(const QString &key)
Remove the entry key from the current folder.
Definition kwallet.cpp:765
void folderUpdated(const QString &folder)
Emitted when a folder in this wallet is updated.
static int closeWallet(const QString &name, bool force)
Close the wallet name.
Definition kwallet.cpp:206
virtual bool hasEntry(const QString &key)
Determine if the current folder has they entry key.
Definition kwallet.cpp:750
virtual QStringList folderList()
Obtain the list of all folders contained in the wallet.
Definition kwallet.cpp:404
static QStringList walletList()
List all the wallets available.
Definition kwallet.cpp:159
virtual bool isOpen() const
Determine if the current wallet is open, and is a valid wallet handle.
Definition kwallet.cpp:376
static const QString NetworkWallet()
The name of the wallet used to store network passwords.
Definition kwallet.cpp:76
virtual const QString & currentFolder() const
Determine the current working folder in the wallet.
Definition kwallet.cpp:511
void walletClosed()
Emitted when this wallet is closed.
static int deleteWallet(const QString &name)
Delete the wallet name.
Definition kwallet.cpp:222
void folderListUpdated()
Emitted when the folder list is changed in this wallet.
virtual int writeEntry(const QString &key, const QByteArray &value, EntryType entryType)
Write key = value as a binary entry to the current folder.
Definition kwallet.cpp:681
virtual bool hasFolder(const QString &f)
Determine if the folder f exists in the wallet.
Definition kwallet.cpp:434
static void changePassword(const QString &name, WId w)
Request to the wallet service to change the password of the wallet name.
Definition kwallet.cpp:174
virtual int readEntry(const QString &key, QByteArray &value)
Read the entry key from the current folder.
Definition kwallet.cpp:516
virtual QStringList entryList()
Return the list of keys of all entries in this folder.
Definition kwallet.cpp:419
~Wallet() override
Destroy a KWallet object.
Definition kwallet.cpp:143
virtual int readMap(const QString &key, QMap< QString, QString > &value)
Read the map entry key from the current folder.
Definition kwallet.cpp:581
virtual void requestChangePassword(WId w)
Request to the wallet service to change the password of the current wallet.
Definition kwallet.cpp:381
static bool isEnabled()
Determine if the KDE wallet is enabled.
Definition kwallet.cpp:185
static bool disconnectApplication(const QString &wallet, const QString &app)
Disconnect the application app from wallet.
Definition kwallet.cpp:312
virtual bool removeFolder(const QString &f)
Remove the folder f and all its entries from the wallet.
Definition kwallet.cpp:492
static const QString LocalWallet()
The name of the wallet used to store local passwords.
Definition kwallet.cpp:58
static bool folderDoesNotExist(const QString &wallet, const QString &folder)
Determine if a folder does not exist in a wallet.
Definition kwallet.cpp:848
virtual EntryType entryType(const QString &key)
Determine the type of the entry key in this folder.
Definition kwallet.cpp:781
virtual int readPassword(const QString &key, QString &value)
Read the password entry key from the current folder.
Definition kwallet.cpp:637
static Wallet * openWallet(const QString &name, WId w, OpenType ot=Synchronous)
Open the wallet name.
Definition kwallet.cpp:238
virtual int writePassword(const QString &key, const QString &value)
Write key = value as a password to the current folder.
Definition kwallet.cpp:734
virtual const QString & walletName() const
The name of the current wallet.
Definition kwallet.cpp:371
virtual bool setFolder(const QString &f)
Set the current working folder to f.
Definition kwallet.cpp:469
void walletOpened(bool success)
Emitted when a wallet is opened in asynchronous mode.
static bool keyDoesNotExist(const QString &wallet, const QString &folder, const QString &key)
Determine if an entry in a folder does not exist in a wallet.
Definition kwallet.cpp:863
static const QString FormDataFolder()
The standardized name of the form data folder.
Definition kwallet.cpp:92
virtual int writeMap(const QString &key, const QMap< QString, QString > &value)
Write key = value as a map to the current folder.
Definition kwallet.cpp:713
Q_SCRIPTABLE CaptureState status()
QString name(StandardShortcut id)
const char * constData() const const
bool isEmpty() const const
qsizetype size() const const
bool isValid() const const
iterator insert(const Key &key, const T &value)
bool invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret)
Q_EMITQ_EMIT
bool disconnect(const QMetaObject::Connection &connection)
void clear()
QString fromLatin1(QByteArrayView str)
QString fromUtf8(QByteArrayView str)
bool isEmpty() const const
QByteArray toUtf8() const const
QueuedConnection
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:16:05 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.