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;
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 // what's left are deleted identities:
406 for (QList<uint>::ConstIterator it = seenUOIDs.constBegin(); it != seenUOIDs.constEnd(); ++it) {
407 qCDebug(KIDENTITYMANAGEMENT_LOG) << "emitting deleted() for identity" << (*it);
408 Q_EMIT deleted(*it);
409 }
410
411 d->mIdentities = d->shadowIdentities;
412 d->writeConfig();
413
414 // now that mIdentities has all the new info, we can Q_EMIT the added/changed
415 // signals that ship a uoid. This is because the slots might use
416 // identityForUoid(uoid)...
417 QList<uint>::ConstIterator changedEnd(changedUOIDs.constEnd());
418 for (QList<uint>::ConstIterator it = changedUOIDs.constBegin(); it != changedEnd; ++it) {
419 Q_EMIT changed(*it);
420 }
421
422 Q_EMIT changed(); // normal signal
423 Q_EMIT identitiesWereChanged(); // normal signal
424
425 // DBus signal for other IdentityManager instances
426 const QString ourIdentifier = QStringLiteral("%1/%2").arg(QDBusConnection::sessionBus().baseService(), property("uniqueDBusPath").toString());
427 Q_EMIT identitiesChanged(ourIdentifier);
428}
429
430void IdentityManager::rollback()
431{
432 d->shadowIdentities = d->mIdentities;
433}
434
435void IdentityManager::saveIdentity(const Identity &ident)
436{
437 const auto existing = std::find_if(modifyBegin(), modifyEnd(), [ident](const auto &existingIdentity) {
438 return existingIdentity.uoid() == ident.uoid();
439 });
440
441 if (existing != modifyEnd()) {
442 d->shadowIdentities.replace(existing - modifyBegin(), ident);
443 } else {
444 d->shadowIdentities << ident;
445 }
446
447 commit();
448}
449
450bool IdentityManager::hasPendingChanges() const
451{
452 return d->mIdentities != d->shadowIdentities;
453}
454
455QStringList IdentityManager::identities() const
456{
457 QStringList result;
458 result.reserve(d->mIdentities.count());
459 ConstIterator end = d->mIdentities.constEnd();
460 for (ConstIterator it = d->mIdentities.constBegin(); it != end; ++it) {
461 result << (*it).identityName();
462 }
463 return result;
464}
465
466QStringList IdentityManager::shadowIdentities() const
467{
468 QStringList result;
469 result.reserve(d->shadowIdentities.count());
470 ConstIterator end = d->shadowIdentities.constEnd();
471 for (ConstIterator it = d->shadowIdentities.constBegin(); it != end; ++it) {
472 result << (*it).identityName();
473 }
474 return result;
475}
476
477void IdentityManager::sort()
478{
479 std::sort(d->shadowIdentities.begin(), d->shadowIdentities.end());
480}
481
482IdentityManager::ConstIterator IdentityManager::begin() const
483{
484 return d->mIdentities.constBegin();
485}
486
487IdentityManager::ConstIterator IdentityManager::end() const
488{
489 return d->mIdentities.constEnd();
490}
491
492IdentityManager::Iterator IdentityManager::modifyBegin()
493{
494 return d->shadowIdentities.begin();
495}
496
497IdentityManager::Iterator IdentityManager::modifyEnd()
498{
499 return d->shadowIdentities.end();
500}
501
502const Identity &IdentityManager::identityForUoid(uint uoid) const
503{
504 for (ConstIterator it = begin(); it != end(); ++it) {
505 if ((*it).uoid() == uoid) {
506 return *it;
507 }
508 }
509 return Identity::null();
510}
511
512const Identity &IdentityManager::identityForUoidOrDefault(uint uoid) const
513{
514 const Identity &ident = identityForUoid(uoid);
515 if (ident.isNull()) {
516 return defaultIdentity();
517 } else {
518 return ident;
519 }
520}
521
522const Identity &IdentityManager::identityForAddress(const QString &addresses) const
523{
524 const QStringList addressList = KEmailAddress::splitAddressList(addresses);
525 for (const QString &fullAddress : addressList) {
526 const QString addrSpec = KEmailAddress::extractEmailAddress(fullAddress).toLower();
527 for (ConstIterator it = begin(); it != end(); ++it) {
528 const Identity &identity = *it;
529 if (identity.matchesEmailAddress(addrSpec)) {
530 return identity;
531 }
532 }
533 }
534 return Identity::null();
535}
536
537bool IdentityManager::thatIsMe(const QString &addressList) const
538{
539 return !identityForAddress(addressList).isNull();
540}
541
542Identity &IdentityManager::modifyIdentityForName(const QString &name)
543{
544 for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) {
545 if ((*it).identityName() == name) {
546 return *it;
547 }
548 }
549
550 qCWarning(KIDENTITYMANAGEMENT_LOG) << "IdentityManager::modifyIdentityForName() used as"
551 << "newFromScratch() replacement!" << Qt::endl
552 << " name == \"" << name << "\"";
553 return newFromScratch(name);
554}
555
556Identity &IdentityManager::modifyIdentityForUoid(uint uoid)
557{
558 for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) {
559 if ((*it).uoid() == uoid) {
560 return *it;
561 }
562 }
563
564 qCWarning(KIDENTITYMANAGEMENT_LOG) << "IdentityManager::identityForUoid() used as"
565 << "newFromScratch() replacement!" << Qt::endl
566 << " uoid == \"" << uoid << "\"";
567 return newFromScratch(i18n("Unnamed"));
568}
569
570const Identity &IdentityManager::defaultIdentity() const
571{
572 for (ConstIterator it = begin(); it != end(); ++it) {
573 if ((*it).isDefault()) {
574 return *it;
575 }
576 }
577
578 if (d->mIdentities.isEmpty()) {
579 qCritical() << "IdentityManager: No default identity found!";
580 } else {
581 qCWarning(KIDENTITYMANAGEMENT_LOG) << "IdentityManager: No default identity found!";
582 }
583 return *begin();
584}
585
586bool IdentityManager::setAsDefault(uint uoid)
587{
588 // First, check if the identity actually exists:
589 bool found = false;
590 ConstIterator end(d->shadowIdentities.constEnd());
591 for (ConstIterator it = d->shadowIdentities.constBegin(); it != end; ++it) {
592 if ((*it).uoid() == uoid) {
593 found = true;
594 break;
595 }
596 }
597
598 if (!found) {
599 return false;
600 }
601
602 // Then, change the default as requested:
603 for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) {
604 (*it).setIsDefault((*it).uoid() == uoid);
605 }
606
607 // and re-sort:
608 sort();
609 return true;
610}
611
612bool IdentityManager::removeIdentity(const QString &name)
613{
614 if (d->shadowIdentities.size() <= 1) {
615 return false;
616 }
617
618 for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) {
619 if ((*it).identityName() == name) {
620 bool removedWasDefault = (*it).isDefault();
621 d->shadowIdentities.erase(it);
622 if (removedWasDefault && !d->shadowIdentities.isEmpty()) {
623 d->shadowIdentities.first().setIsDefault(true);
624 }
625 return true;
626 }
627 }
628 return false;
629}
630
631bool IdentityManager::removeIdentityForced(const QString &name)
632{
633 for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) {
634 if ((*it).identityName() == name) {
635 bool removedWasDefault = (*it).isDefault();
636 d->shadowIdentities.erase(it);
637 if (removedWasDefault && !d->shadowIdentities.isEmpty()) {
638 d->shadowIdentities.first().setIsDefault(true);
639 }
640 return true;
641 }
642 }
643 return false;
644}
645
646Identity &IdentityManager::newFromScratch(const QString &name)
647{
648 return newFromExisting(Identity(name));
649}
650
651Identity &IdentityManager::newFromControlCenter(const QString &name)
652{
655
656 return newFromExisting(Identity(name,
657 es.getSetting(KEMailSettings::RealName),
658 es.getSetting(KEMailSettings::EmailAddress),
659 es.getSetting(KEMailSettings::Organization),
660 es.getSetting(KEMailSettings::ReplyToAddress)));
661}
662
663Identity &IdentityManager::newFromExisting(const Identity &other, const QString &name)
664{
665 d->shadowIdentities << other;
666 Identity &result = d->shadowIdentities.last();
667 result.setIsDefault(false); // we don't want two default identities!
668 result.setUoid(d->newUoid()); // we don't want two identities w/ same UOID
669 if (!name.isNull()) {
670 result.setIdentityName(name);
671 }
672 return result;
673}
674
676{
677 QStringList lst;
678 for (ConstIterator it = begin(); it != end(); ++it) {
679 lst << (*it).primaryEmailAddress();
680 if (!(*it).emailAliases().isEmpty()) {
681 lst << (*it).emailAliases();
682 }
683 }
684 return lst;
685}
686
688{
689}
690
691void KIdentityManagementCore::IdentityManager::slotRollback()
692{
693 rollback();
694}
695
696IdentityManagerPrivate::~IdentityManagerPrivate()
697{
698 delete mConfig;
699}
700}
701#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
Manages the list of identities.
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()
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-2024 The KDE developers.
Generated on Fri Dec 6 2024 12:11:25 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.