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)
const QList< QKeySequence > & begin()
const QList< QKeySequence > & end()
QString name(StandardShortcut id)
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 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 Tue Mar 26 2024 11:20:09 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.