KIdentityManagement

identitymanager.cpp
1/*
2 SPDX-FileCopyrightText: 2002 Marc Mutz <mutz@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7// config keys:
8static const char configKeyDefaultIdentity[] = "Default Identity";
9
10#include "identitymanager.h"
11#include "identity.h" // for IdentityList::{export,import}Data
12
13#include <KEmailAddress> // for static helper functions
14
15#include "kidentitymanagementcore_debug.h"
16#include <KConfig>
17#include <KConfigGroup>
18#include <KEMailSettings> // for IdentityEntry::fromControlCenter()
19#include <KLocalizedString>
20#include <KSharedConfig>
21#include <kuser.h>
22
23#include <QDBusConnection>
24#include <QHostInfo>
25#include <QRandomGenerator>
26
27#include <QRegularExpression>
28#include <cassert>
29
30#include "identitymanageradaptor.h"
31
32namespace KIdentityManagementCore
33{
34static QString newDBusObjectName()
35{
36 static int s_count = 0;
37 QString name(QStringLiteral("/KIDENTITYMANAGER_IdentityManager"));
38 if (s_count++) {
39 name += QLatin1Char('_');
40 name += QString::number(s_count);
41 }
42 return name;
43}
44
45/**
46 * Private class that helps to provide binary compatibility between releases.
47 * @internal
48 */
49//@cond PRIVATE
50class IdentityManagerPrivate
51{
52public:
53 IdentityManagerPrivate(KIdentityManagementCore::IdentityManager *);
54 ~IdentityManagerPrivate();
55 void writeConfig() const;
56 void readConfig(KConfig *config);
57 void createDefaultIdentity();
58 [[nodiscard]] QStringList groupList(KConfig *config) const;
59 void slotIdentitiesChanged(const QString &id);
60 KConfig *mConfig = nullptr;
61
62 QList<Identity> mIdentities;
63 QList<Identity> shadowIdentities;
64
65 // returns a new Unique Object Identifier
66 [[nodiscard]] int newUoid();
67
68 bool mReadOnly = true;
69 KIdentityManagementCore::IdentityManager *const q;
70};
71
72IdentityManagerPrivate::IdentityManagerPrivate(KIdentityManagementCore::IdentityManager *manager)
73 : q(manager)
74{
75}
76
77void IdentityManagerPrivate::writeConfig() const
78{
79 const QStringList identities = groupList(mConfig);
80 QStringList::const_iterator groupEnd = identities.constEnd();
81 for (QStringList::const_iterator group = identities.constBegin(); group != groupEnd; ++group) {
82 mConfig->deleteGroup(*group);
83 }
84 int i = 0;
85 IdentityManager::ConstIterator end = mIdentities.constEnd();
86 for (IdentityManager::ConstIterator it = mIdentities.constBegin(); it != end; ++it, ++i) {
87 KConfigGroup cg(mConfig, QStringLiteral("Identity #%1").arg(i));
88 (*it).writeConfig(cg);
89 if ((*it).isDefault()) {
90 // remember which one is default:
91 KConfigGroup general(mConfig, QStringLiteral("General"));
92 general.writeEntry(configKeyDefaultIdentity, (*it).uoid());
93
94 // Also write the default identity to emailsettings
96 es.setSetting(KEMailSettings::RealName, (*it).fullName());
97 es.setSetting(KEMailSettings::EmailAddress, (*it).primaryEmailAddress());
98 es.setSetting(KEMailSettings::Organization, (*it).organization());
99 es.setSetting(KEMailSettings::ReplyToAddress, (*it).replyToAddr());
100 }
101 }
102 mConfig->sync();
103}
104
105void IdentityManagerPrivate::readConfig(KConfig *config)
106{
107 mIdentities.clear();
108
109 const QStringList identities = groupList(config);
110 if (identities.isEmpty()) {
111 return; // nothing to be done...
112 }
113
114 KConfigGroup general(config, QStringLiteral("General"));
115 uint defaultIdentity = general.readEntry(configKeyDefaultIdentity, 0);
116 bool haveDefault = false;
117 QStringList::const_iterator groupEnd = identities.constEnd();
118 for (QStringList::const_iterator group = identities.constBegin(); group != groupEnd; ++group) {
119 KConfigGroup configGroup(config, *group);
120 Identity identity;
121 identity.readConfig(configGroup);
122 // Don't load invalid identity
123 if (!identity.isNull() && !identity.primaryEmailAddress().isEmpty()) {
124 if (!haveDefault && identity.uoid() == defaultIdentity) {
125 haveDefault = true;
126 identity.setIsDefault(true);
127 }
128 }
129 mIdentities << identity;
130 }
131 if (!haveDefault) {
132 if (mIdentities.isEmpty()) {
133 mIdentities << Identity();
134 }
135
136 qCDebug(KIDENTITYMANAGEMENT_LOG) << "IdentityManager: There was no default identity."
137 << "Marking first one as default.";
138 mIdentities.first().setIsDefault(true);
139 }
140 std::sort(mIdentities.begin(), mIdentities.end());
141
142 shadowIdentities = mIdentities;
143}
144
145void IdentityManagerPrivate::createDefaultIdentity()
146{
148 QString emailAddress;
149 bool done = false;
150
151 // Check if the application has any settings
152 q->createDefaultIdentity(fullName, emailAddress);
153
154 // If not, then use the kcontrol settings
155 if (fullName.isEmpty() && emailAddress.isEmpty()) {
156 KEMailSettings emailSettings;
157 fullName = emailSettings.getSetting(KEMailSettings::RealName);
158 emailAddress = emailSettings.getSetting(KEMailSettings::EmailAddress);
159
160 if (!fullName.isEmpty() && !emailAddress.isEmpty()) {
161 q->newFromControlCenter(i18nc("use default address from control center", "Default"));
162 done = true;
163 } else {
164 // If KEmailSettings doesn't have name and address, generate something from KUser
165 KUser user;
166 if (fullName.isEmpty()) {
167 fullName = user.property(KUser::FullName).toString();
168 }
169 if (emailAddress.isEmpty()) {
170 emailAddress = user.loginName();
171 if (!emailAddress.isEmpty()) {
172 KConfigGroup general(mConfig, QStringLiteral("General"));
173 QString defaultdomain = general.readEntry("Default domain");
174 if (!defaultdomain.isEmpty()) {
175 emailAddress += QLatin1Char('@') + defaultdomain;
176 } else {
177 emailAddress.clear();
178 }
179 }
180 }
181 }
182 }
183
184 if (!done) {
185 // Default identity name
186 QString name(i18nc("Default name for new email accounts/identities.", "Unnamed"));
187
188 if (!emailAddress.isEmpty()) {
189 // If we have an email address, create a default identity name from it
190 QString idName = emailAddress;
191 int pos = idName.indexOf(QLatin1Char('@'));
192 if (pos != -1) {
193 name = idName.mid(pos + 1, -1);
194 }
195
196 // Make the name a bit more human friendly
198 pos = name.indexOf(QLatin1Char(' '));
199 if (pos != 0) {
200 name[pos + 1] = name[pos + 1].toUpper();
201 }
202 name[0] = name[0].toUpper();
203 } else if (!fullName.isEmpty()) {
204 // If we have a full name, create a default identity name from it
205 name = fullName;
206 }
207 shadowIdentities << Identity(name, fullName, emailAddress);
208 }
209
210 shadowIdentities.last().setIsDefault(true);
211 shadowIdentities.last().setUoid(newUoid());
212 if (mReadOnly) { // commit won't do it in readonly mode
213 mIdentities = shadowIdentities;
214 }
215}
216
217QStringList IdentityManagerPrivate::groupList(KConfig *config) const
218{
219 return config->groupList().filter(QRegularExpression(QStringLiteral("^Identity #\\d+$")));
220}
221
222int IdentityManagerPrivate::newUoid()
223{
224 int uoid;
225
226 // determine the UOIDs of all saved identities
227 QList<uint> usedUOIDs;
228 usedUOIDs.reserve(mIdentities.count() + (q->hasPendingChanges() ? shadowIdentities.count() : 0));
229 const QList<Identity>::ConstIterator end(mIdentities.constEnd());
230 for (QList<Identity>::ConstIterator it = mIdentities.constBegin(); it != end; ++it) {
231 usedUOIDs << (*it).uoid();
232 }
233
234 if (q->hasPendingChanges()) {
235 // add UOIDs of all shadow identities. Yes, we will add a lot of duplicate
236 // UOIDs, but avoiding duplicate UOIDs isn't worth the effort.
237 const QList<Identity>::ConstIterator endShadow(shadowIdentities.constEnd());
238 for (QList<Identity>::ConstIterator it = shadowIdentities.constBegin(); it != endShadow; ++it) {
239 usedUOIDs << (*it).uoid();
240 }
241 }
242
243 do {
244 // 0 refers to the default identity, so accept 1 only as lowest value
245 uoid = QRandomGenerator::global()->bounded(1, RAND_MAX);
246 } while (usedUOIDs.contains(uoid));
247
248 return uoid;
249}
250
251void IdentityManagerPrivate::slotIdentitiesChanged(const QString &id)
252{
253 qCDebug(KIDENTITYMANAGEMENT_LOG) << " KIdentityManagementCore::IdentityManager::slotIdentitiesChanged :" << id;
254 const QString ourIdentifier = QStringLiteral("%1/%2").arg(QDBusConnection::sessionBus().baseService(), q->property("uniqueDBusPath").toString());
255 if (id != ourIdentifier) {
256 mConfig->reparseConfiguration();
257 Q_ASSERT(!q->hasPendingChanges());
258 readConfig(mConfig);
259 Q_EMIT q->needToReloadIdentitySettings();
260 Q_EMIT q->changed();
261 Q_EMIT q->identitiesWereChanged();
262 }
263}
264
265Q_GLOBAL_STATIC(IdentityManager, s_self)
266
267IdentityManager *IdentityManager::self()
268{
269 return s_self;
270}
271
272IdentityManager::IdentityManager(bool readonly, QObject *parent, const char *name)
273 : QObject(parent)
274 , d(new IdentityManagerPrivate(this))
275{
276 setObjectName(QLatin1StringView(name));
277 new IdentityManagerAdaptor(this);
279 const QString dbusPath = newDBusObjectName();
280 setProperty("uniqueDBusPath", dbusPath);
281 const QString dbusInterface = QStringLiteral("org.kde.pim.IdentityManager");
282 dbus.registerObject(dbusPath, this);
283 dbus.connect(QString(), QString(), dbusInterface, QStringLiteral("identitiesChanged"), this, SLOT(slotIdentitiesChanged(QString)));
284
285 d->mReadOnly = readonly;
286 d->mConfig = new KConfig(QStringLiteral("emailidentities"));
287 if (!d->mConfig->isConfigWritable(true)) {
288 qCWarning(KIDENTITYMANAGEMENT_LOG) << "impossible to write on this file";
289 }
290 d->readConfig(d->mConfig);
291 // we need at least a default identity:
292 if (d->mIdentities.isEmpty()) {
293 qCDebug(KIDENTITYMANAGEMENT_LOG) << "IdentityManager: No identity found. Creating default.";
294 d->createDefaultIdentity();
295 commit();
296 }
297
298 KSharedConfig::Ptr kmailConf(KSharedConfig::openConfig(QStringLiteral("kmail2rc")));
299 if (!d->mReadOnly) {
300 bool needCommit = false;
301 if (kmailConf->hasGroup(QStringLiteral("Composer"))) {
302 KConfigGroup composerGroup = kmailConf->group(QStringLiteral("Composer"));
303 if (composerGroup.hasKey(QStringLiteral("pgp-auto-sign"))) {
304 const bool pgpAutoSign = composerGroup.readEntry(QStringLiteral("pgp-auto-sign"), false);
305 const QList<Identity>::iterator end = d->mIdentities.end();
306 for (QList<Identity>::iterator it = d->mIdentities.begin(); it != end; ++it) {
307 it->setPgpAutoSign(pgpAutoSign);
308 }
309 composerGroup.deleteEntry(QStringLiteral("pgp-auto-sign"));
310 composerGroup.sync();
311 needCommit = true;
312 }
313 }
314 if (kmailConf->hasGroup(QStringLiteral("General"))) {
315 KConfigGroup generalGroup = kmailConf->group(QStringLiteral("General"));
316 if (generalGroup.hasKey(QStringLiteral("Default domain"))) {
317 QString defaultDomain = generalGroup.readEntry(QStringLiteral("Default domain"));
318 if (defaultDomain.isEmpty()) {
319 defaultDomain = QHostInfo::localHostName();
320 }
321 const QList<Identity>::iterator end = d->mIdentities.end();
322 for (QList<Identity>::iterator it = d->mIdentities.begin(); it != end; ++it) {
323 it->setDefaultDomainName(defaultDomain);
324 }
325 generalGroup.deleteEntry(QStringLiteral("Default domain"));
326 generalGroup.sync();
327 needCommit = true;
328 }
329 }
330 if (needCommit) {
331 commit();
332 }
333 }
334
335 // Migration: people without settings in kemailsettings should get some
336 if (KEMailSettings().getSetting(KEMailSettings::EmailAddress).isEmpty()) {
337 d->writeConfig();
338 }
339}
340
341IdentityManager::~IdentityManager()
342{
343 if (hasPendingChanges()) {
344 qCWarning(KIDENTITYMANAGEMENT_LOG) << "IdentityManager: There were uncommitted changes!";
345 }
346}
347
348QString IdentityManager::makeUnique(const QString &name) const
349{
350 int suffix = 1;
351 QString result = name;
352 while (identities().contains(result)) {
353 result = i18nc(
354 "%1: name; %2: number appended to it to make it unique "
355 "among a list of names",
356 "%1 #%2",
357 name,
358 suffix);
359 ++suffix;
360 }
361 return result;
362}
363
364bool IdentityManager::isUnique(const QString &name) const
365{
366 return !identities().contains(name);
367}
368
369void IdentityManager::commit()
370{
371 // early out:
372 if (!hasPendingChanges() || d->mReadOnly) {
373 return;
374 }
375
376 QList<uint> seenUOIDs;
377 seenUOIDs.reserve(d->mIdentities.count());
378 const QList<Identity>::ConstIterator end = d->mIdentities.constEnd();
379 for (QList<Identity>::ConstIterator it = d->mIdentities.constBegin(); it != end; ++it) {
380 seenUOIDs << (*it).uoid();
381 }
382
383 QList<uint> changedUOIDs;
384 // find added and changed identities:
385 for (QList<Identity>::ConstIterator it = d->shadowIdentities.constBegin(); it != d->shadowIdentities.constEnd(); ++it) {
386 const int index = seenUOIDs.indexOf((*it).uoid());
387 if (index != -1) {
388 uint uoid = seenUOIDs.at(index);
389 const Identity &orig = identityForUoid(uoid); // look up in mIdentities
390 if (*it != orig) {
391 // changed identity
392 qCDebug(KIDENTITYMANAGEMENT_LOG) << "emitting changed() for identity" << uoid;
393 Q_EMIT changed(*it);
394 Q_EMIT identityChanged(*it);
395 changedUOIDs << uoid;
396 }
397 seenUOIDs.removeAll(uoid);
398 } else {
399 // new identity
400 qCDebug(KIDENTITYMANAGEMENT_LOG) << "emitting added() for identity" << (*it).uoid();
401 Q_EMIT added(*it);
402 }
403 }
404
405 d->mIdentities = d->shadowIdentities;
406
407 // we cannot throw the signal earlier as it would lead to a call to
408 // modifyIdentityForUoid, in turn creating a new entry for the one we are
409 // trying to destroy...
410 for (QList<uint>::ConstIterator it = seenUOIDs.constBegin(); it != seenUOIDs.constEnd(); ++it) {
411 qCDebug(KIDENTITYMANAGEMENT_LOG) << "emitting deleted() for identity" << (*it);
412 Q_EMIT deleted(*it);
413 }
414
415 d->writeConfig();
416
417 // now that mIdentities has all the new info, we can Q_EMIT the added/changed
418 // signals that ship a uoid. This is because the slots might use
419 // identityForUoid(uoid)...
420 QList<uint>::ConstIterator changedEnd(changedUOIDs.constEnd());
421 for (QList<uint>::ConstIterator it = changedUOIDs.constBegin(); it != changedEnd; ++it) {
422 Q_EMIT changed(*it);
423 }
424
425 Q_EMIT changed(); // normal signal
426 Q_EMIT identitiesWereChanged(); // normal signal
427
428 // DBus signal for other IdentityManager instances
429 const QString ourIdentifier = QStringLiteral("%1/%2").arg(QDBusConnection::sessionBus().baseService(), property("uniqueDBusPath").toString());
430 Q_EMIT identitiesChanged(ourIdentifier);
431}
432
433void IdentityManager::rollback()
434{
435 d->shadowIdentities = d->mIdentities;
436}
437
438void IdentityManager::saveIdentity(const Identity &ident)
439{
440 const auto existing = std::find_if(modifyBegin(), modifyEnd(), [ident](const auto &existingIdentity) {
441 return existingIdentity.uoid() == ident.uoid();
442 });
443
444 if (existing != modifyEnd()) {
445 d->shadowIdentities.replace(existing - modifyBegin(), ident);
446 } else {
447 d->shadowIdentities << ident;
448 }
449
450 commit();
451}
452
453bool IdentityManager::hasPendingChanges() const
454{
455 return d->mIdentities != d->shadowIdentities;
456}
457
458QStringList IdentityManager::identities() const
459{
460 QStringList result;
461 result.reserve(d->mIdentities.count());
462 ConstIterator end = d->mIdentities.constEnd();
463 for (ConstIterator it = d->mIdentities.constBegin(); it != end; ++it) {
464 result << (*it).identityName();
465 }
466 return result;
467}
468
469QStringList IdentityManager::shadowIdentities() const
470{
471 QStringList result;
472 result.reserve(d->shadowIdentities.count());
473 ConstIterator end = d->shadowIdentities.constEnd();
474 for (ConstIterator it = d->shadowIdentities.constBegin(); it != end; ++it) {
475 result << (*it).identityName();
476 }
477 return result;
478}
479
480void IdentityManager::sort()
481{
482 std::sort(d->shadowIdentities.begin(), d->shadowIdentities.end());
483}
484
485IdentityManager::ConstIterator IdentityManager::begin() const
486{
487 return d->mIdentities.constBegin();
488}
489
490IdentityManager::ConstIterator IdentityManager::end() const
491{
492 return d->mIdentities.constEnd();
493}
494
495IdentityManager::Iterator IdentityManager::modifyBegin()
496{
497 return d->shadowIdentities.begin();
498}
499
500IdentityManager::Iterator IdentityManager::modifyEnd()
501{
502 return d->shadowIdentities.end();
503}
504
505const Identity &IdentityManager::identityForUoid(uint uoid) const
506{
507 for (ConstIterator it = begin(); it != end(); ++it) {
508 if ((*it).uoid() == uoid) {
509 return *it;
510 }
511 }
512 return Identity::null();
513}
514
515const Identity &IdentityManager::identityForUoidOrDefault(uint uoid) const
516{
517 const Identity &ident = identityForUoid(uoid);
518 if (ident.isNull()) {
519 return defaultIdentity();
520 } else {
521 return ident;
522 }
523}
524
525const Identity &IdentityManager::identityForAddress(const QString &addresses) const
526{
527 const QStringList addressList = KEmailAddress::splitAddressList(addresses);
528 for (const QString &fullAddress : addressList) {
529 const QString addrSpec = KEmailAddress::extractEmailAddress(fullAddress).toLower();
530 for (ConstIterator it = begin(); it != end(); ++it) {
531 const Identity &identity = *it;
532 if (identity.matchesEmailAddress(addrSpec)) {
533 return identity;
534 }
535 }
536 }
537 return Identity::null();
538}
539
540bool IdentityManager::thatIsMe(const QString &addressList) const
541{
542 return !identityForAddress(addressList).isNull();
543}
544
545Identity &IdentityManager::modifyIdentityForName(const QString &name)
546{
547 for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) {
548 if ((*it).identityName() == name) {
549 return *it;
550 }
551 }
552
553 qCWarning(KIDENTITYMANAGEMENT_LOG) << "IdentityManager::modifyIdentityForName() used as"
554 << "newFromScratch() replacement!" << Qt::endl
555 << " name == \"" << name << "\"";
556 return newFromScratch(name);
557}
558
559Identity &IdentityManager::modifyIdentityForUoid(uint uoid)
560{
561 for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) {
562 if ((*it).uoid() == uoid) {
563 return *it;
564 }
565 }
566
567 qCWarning(KIDENTITYMANAGEMENT_LOG) << "IdentityManager::identityForUoid() used as"
568 << "newFromScratch() replacement!" << Qt::endl
569 << " uoid == \"" << uoid << "\"";
570 return newFromScratch(i18n("Unnamed"));
571}
572
573const Identity &IdentityManager::defaultIdentity() const
574{
575 for (ConstIterator it = begin(); it != end(); ++it) {
576 if ((*it).isDefault()) {
577 return *it;
578 }
579 }
580
581 if (d->mIdentities.isEmpty()) {
582 qCritical() << "IdentityManager: No default identity found!";
583 } else {
584 qCWarning(KIDENTITYMANAGEMENT_LOG) << "IdentityManager: No default identity found!";
585 }
586 return *begin();
587}
588
589bool IdentityManager::setAsDefault(uint uoid)
590{
591 // First, check if the identity actually exists:
592 bool found = false;
593 ConstIterator end(d->shadowIdentities.constEnd());
594 for (ConstIterator it = d->shadowIdentities.constBegin(); it != end; ++it) {
595 if ((*it).uoid() == uoid) {
596 found = true;
597 break;
598 }
599 }
600
601 if (!found) {
602 return false;
603 }
604
605 // Then, change the default as requested:
606 for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) {
607 (*it).setIsDefault((*it).uoid() == uoid);
608 }
609
610 // and re-sort:
611 sort();
612 return true;
613}
614
615bool IdentityManager::removeIdentity(const QString &name)
616{
617 if (d->shadowIdentities.size() <= 1) {
618 return false;
619 }
620
621 for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) {
622 if ((*it).identityName() == name) {
623 bool removedWasDefault = (*it).isDefault();
624 d->shadowIdentities.erase(it);
625 if (removedWasDefault && !d->shadowIdentities.isEmpty()) {
626 d->shadowIdentities.first().setIsDefault(true);
627 }
628 return true;
629 }
630 }
631 return false;
632}
633
634bool IdentityManager::removeIdentityForced(const QString &name)
635{
636 for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) {
637 if ((*it).identityName() == name) {
638 bool removedWasDefault = (*it).isDefault();
639 d->shadowIdentities.erase(it);
640 if (removedWasDefault && !d->shadowIdentities.isEmpty()) {
641 d->shadowIdentities.first().setIsDefault(true);
642 }
643 return true;
644 }
645 }
646 return false;
647}
648
649Identity &IdentityManager::newFromScratch(const QString &name)
650{
651 return newFromExisting(Identity(name));
652}
653
654Identity &IdentityManager::newFromControlCenter(const QString &name)
655{
658
659 return newFromExisting(Identity(name,
660 es.getSetting(KEMailSettings::RealName),
661 es.getSetting(KEMailSettings::EmailAddress),
662 es.getSetting(KEMailSettings::Organization),
663 es.getSetting(KEMailSettings::ReplyToAddress)));
664}
665
666Identity &IdentityManager::newFromExisting(const Identity &other, const QString &name)
667{
668 d->shadowIdentities << other;
669 Identity &result = d->shadowIdentities.last();
670 result.setIsDefault(false); // we don't want two default identities!
671 result.setUoid(d->newUoid()); // we don't want two identities w/ same UOID
672 if (!name.isNull()) {
673 result.setIdentityName(name);
674 }
675 return result;
676}
677
679{
680 QStringList lst;
681 for (ConstIterator it = begin(); it != end(); ++it) {
682 lst << (*it).primaryEmailAddress();
683 if (!(*it).emailAliases().isEmpty()) {
684 lst << (*it).emailAliases();
685 }
686 }
687 return lst;
688}
689
690void IdentityManager::createDefaultIdentity(QString &, QString &)
691{
692}
693
694void KIdentityManagementCore::IdentityManager::slotRollback()
695{
696 rollback();
697}
698
699IdentityManagerPrivate::~IdentityManagerPrivate()
700{
701 delete mConfig;
702}
703}
704#include "moc_identitymanager.cpp"
KConfigGroup group(const QString &group)
void deleteEntry(const char *key, WriteConfigFlags pFlags=Normal)
bool hasKey(const char *key) const
QString readEntry(const char *key, const char *aDefault=nullptr) const
bool sync() override
QStringList groupList() const override
QString getSetting(KEMailSettings::Setting s) const
void setProfile(const QString &s)
void setSetting(KEMailSettings::Setting s, const QString &v)
QString defaultProfileName() const
QStringList allEmails() const
Returns the list of all email addresses (only name@host) from all identities.
virtual void createDefaultIdentity(QString &, QString &)
This is called when no identity has been defined, so we need to create a default one.
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
QVariant property(UserProperty which) const
QString loginName() const
KCODECS_EXPORT QByteArray extractEmailAddress(const QByteArray &address)
KCODECS_EXPORT QStringList splitAddressList(const QString &aStr)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QString fullName(const PartType &type)
char * toString(const EngineQuery &query)
QString name(StandardAction id)
const QList< QKeySequence > & begin()
const QList< QKeySequence > & end()
QCA_EXPORT void setProperty(const QString &name, const QVariant &value)
QByteArray toLower() const const
bool connect(const QString &service, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *slot)
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
QDBusConnection sessionBus()
QString localHostName()
typedef ConstIterator
const_reference at(qsizetype i) const const
const_iterator constBegin() const const
const_iterator constEnd() const const
bool contains(const AT &value) const const
qsizetype indexOf(const AT &value, qsizetype from) const const
bool isEmpty() const const
T & last()
qsizetype removeAll(const AT &t)
void reserve(qsizetype size)
double bounded(double highest)
QRandomGenerator * global()
QString arg(Args &&... args) const const
void clear()
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
bool isNull() const const
QString last(qsizetype n) const const
QString mid(qsizetype position, qsizetype n) const const
QString number(double n, char format, int precision)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
QString toUpper() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QStringList filter(QStringView str, Qt::CaseSensitivity cs) const const
QTextStream & endl(QTextStream &stream)
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:51:27 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.