8static const char configKeyDefaultIdentity[] =
"Default Identity";
10#include "identitymanager.h"
13#include <KEmailAddress>
15#include "kidentitymanagementcore_debug.h"
17#include <KConfigGroup>
18#include <KEMailSettings>
19#include <KLocalizedString>
20#include <KSharedConfig>
23#include <QDBusConnection>
25#include <QRandomGenerator>
27#include <QRegularExpression>
30#include "identitymanageradaptor.h"
32namespace KIdentityManagementCore
34static QString newDBusObjectName()
36 static int s_count = 0;
37 QString name(QStringLiteral(
"/KIDENTITYMANAGER_IdentityManager"));
50class IdentityManagerPrivate
54 ~IdentityManagerPrivate();
55 void writeConfig()
const;
56 void readConfig(
KConfig *config);
57 void createDefaultIdentity();
59 void slotIdentitiesChanged(
const QString &
id);
66 [[nodiscard]]
int newUoid();
68 bool mReadOnly =
true;
77void IdentityManagerPrivate::writeConfig()
const
82 mConfig->deleteGroup(*group);
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()) {
91 KConfigGroup general(mConfig, QStringLiteral(
"General"));
92 general.writeEntry(configKeyDefaultIdentity, (*it).uoid());
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());
105void IdentityManagerPrivate::readConfig(
KConfig *config)
114 KConfigGroup general(config, QStringLiteral(
"General"));
115 uint defaultIdentity = general.readEntry(configKeyDefaultIdentity, 0);
116 bool haveDefault =
false;
121 identity.readConfig(configGroup);
123 if (!identity.isNull() && !identity.primaryEmailAddress().isEmpty()) {
124 if (!haveDefault && identity.uoid() == defaultIdentity) {
126 identity.setIsDefault(
true);
129 mIdentities << identity;
132 if (mIdentities.isEmpty()) {
133 mIdentities << Identity();
136 qCDebug(KIDENTITYMANAGEMENT_LOG) <<
"IdentityManager: There was no default identity."
137 <<
"Marking first one as default.";
138 mIdentities.first().setIsDefault(
true);
140 std::sort(mIdentities.begin(), mIdentities.end());
142 shadowIdentities = mIdentities;
145void IdentityManagerPrivate::createDefaultIdentity()
152 q->createDefaultIdentity(fullName, emailAddress);
158 emailAddress = emailSettings.
getSetting(KEMailSettings::EmailAddress);
161 q->newFromControlCenter(
i18nc(
"use default address from control center",
"Default"));
172 KConfigGroup general(mConfig, QStringLiteral(
"General"));
173 QString defaultdomain = general.readEntry(
"Default domain");
174 if (!defaultdomain.
isEmpty()) {
177 emailAddress.
clear();
186 QString name(
i18nc(
"Default name for new email accounts/identities.",
"Unnamed"));
193 name = idName.
mid(pos + 1, -1);
207 shadowIdentities << Identity(name, fullName, emailAddress);
210 shadowIdentities.last().setIsDefault(
true);
211 shadowIdentities.last().setUoid(newUoid());
213 mIdentities = shadowIdentities;
222int IdentityManagerPrivate::newUoid()
228 usedUOIDs.
reserve(mIdentities.count() + (q->hasPendingChanges() ? shadowIdentities.count() : 0));
231 usedUOIDs << (*it).uoid();
234 if (q->hasPendingChanges()) {
239 usedUOIDs << (*it).uoid();
251void IdentityManagerPrivate::slotIdentitiesChanged(
const QString &
id)
253 qCDebug(KIDENTITYMANAGEMENT_LOG) <<
" KIdentityManagementCore::IdentityManager::slotIdentitiesChanged :" << id;
255 if (
id != ourIdentifier) {
256 mConfig->reparseConfiguration();
257 Q_ASSERT(!q->hasPendingChanges());
259 Q_EMIT q->needToReloadIdentitySettings();
261 Q_EMIT q->identitiesWereChanged();
265Q_GLOBAL_STATIC(IdentityManager, s_self)
267IdentityManager *IdentityManager::self()
272IdentityManager::IdentityManager(
bool readonly,
QObject *parent,
const char *name)
274 , d(new IdentityManagerPrivate(this))
277 new IdentityManagerAdaptor(
this);
279 const QString dbusPath = newDBusObjectName();
281 const QString dbusInterface = QStringLiteral(
"org.kde.pim.IdentityManager");
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";
290 d->readConfig(d->mConfig);
292 if (d->mIdentities.isEmpty()) {
293 qCDebug(KIDENTITYMANAGEMENT_LOG) <<
"IdentityManager: No identity found. Creating default.";
294 d->createDefaultIdentity();
300 bool needCommit =
false;
301 if (kmailConf->hasGroup(QStringLiteral(
"Composer"))) {
303 if (composerGroup.
hasKey(QStringLiteral(
"pgp-auto-sign"))) {
304 const bool pgpAutoSign = composerGroup.
readEntry(QStringLiteral(
"pgp-auto-sign"),
false);
307 it->setPgpAutoSign(pgpAutoSign);
309 composerGroup.
deleteEntry(QStringLiteral(
"pgp-auto-sign"));
310 composerGroup.
sync();
314 if (kmailConf->hasGroup(QStringLiteral(
"General"))) {
316 if (generalGroup.
hasKey(QStringLiteral(
"Default domain"))) {
317 QString defaultDomain = generalGroup.
readEntry(QStringLiteral(
"Default domain"));
323 it->setDefaultDomainName(defaultDomain);
325 generalGroup.
deleteEntry(QStringLiteral(
"Default domain"));
336 if (
KEMailSettings().getSetting(KEMailSettings::EmailAddress).isEmpty()) {
341IdentityManager::~IdentityManager()
343 if (hasPendingChanges()) {
344 qCWarning(KIDENTITYMANAGEMENT_LOG) <<
"IdentityManager: There were uncommitted changes!";
352 while (identities().contains(result)) {
354 "%1: name; %2: number appended to it to make it unique "
355 "among a list of names",
364bool IdentityManager::isUnique(
const QString &name)
const
366 return !identities().
contains(name);
369void IdentityManager::commit()
372 if (!hasPendingChanges() || d->mReadOnly) {
377 seenUOIDs.
reserve(d->mIdentities.count());
380 seenUOIDs << (*it).uoid();
386 const int index = seenUOIDs.
indexOf((*it).uoid());
388 uint uoid = seenUOIDs.
at(index);
389 const Identity &orig = identityForUoid(uoid);
392 qCDebug(KIDENTITYMANAGEMENT_LOG) <<
"emitting changed() for identity" << uoid;
394 Q_EMIT identityChanged(*it);
395 changedUOIDs << uoid;
400 qCDebug(KIDENTITYMANAGEMENT_LOG) <<
"emitting added() for identity" << (*it).uoid();
407 qCDebug(KIDENTITYMANAGEMENT_LOG) <<
"emitting deleted() for identity" << (*it);
411 d->mIdentities = d->shadowIdentities;
423 Q_EMIT identitiesWereChanged();
427 Q_EMIT identitiesChanged(ourIdentifier);
430void IdentityManager::rollback()
432 d->shadowIdentities = d->mIdentities;
435void IdentityManager::saveIdentity(
const Identity &ident)
437 const auto existing = std::find_if(modifyBegin(), modifyEnd(), [ident](
const auto &existingIdentity) {
438 return existingIdentity.uoid() == ident.uoid();
441 if (existing != modifyEnd()) {
442 d->shadowIdentities.replace(existing - modifyBegin(), ident);
444 d->shadowIdentities << ident;
450bool IdentityManager::hasPendingChanges()
const
452 return d->mIdentities != d->shadowIdentities;
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();
466QStringList IdentityManager::shadowIdentities()
const
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();
477void IdentityManager::sort()
479 std::sort(d->shadowIdentities.begin(), d->shadowIdentities.end());
482IdentityManager::ConstIterator IdentityManager::begin()
const
484 return d->mIdentities.constBegin();
487IdentityManager::ConstIterator IdentityManager::end()
const
489 return d->mIdentities.constEnd();
492IdentityManager::Iterator IdentityManager::modifyBegin()
494 return d->shadowIdentities.begin();
497IdentityManager::Iterator IdentityManager::modifyEnd()
499 return d->shadowIdentities.end();
502const Identity &IdentityManager::identityForUoid(uint uoid)
const
504 for (ConstIterator it =
begin(); it !=
end(); ++it) {
505 if ((*it).uoid() == uoid) {
509 return Identity::null();
512const Identity &IdentityManager::identityForUoidOrDefault(uint uoid)
const
514 const Identity &ident = identityForUoid(uoid);
515 if (ident.isNull()) {
516 return defaultIdentity();
522const Identity &IdentityManager::identityForAddress(
const QString &addresses)
const
525 for (
const QString &fullAddress : addressList) {
527 for (ConstIterator it =
begin(); it !=
end(); ++it) {
528 const Identity &identity = *it;
529 if (identity.matchesEmailAddress(addrSpec)) {
534 return Identity::null();
537bool IdentityManager::thatIsMe(
const QString &addressList)
const
539 return !identityForAddress(addressList).isNull();
542Identity &IdentityManager::modifyIdentityForName(
const QString &name)
544 for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) {
545 if ((*it).identityName() ==
name) {
550 qCWarning(KIDENTITYMANAGEMENT_LOG) <<
"IdentityManager::modifyIdentityForName() used as"
551 <<
"newFromScratch() replacement!" <<
Qt::endl
552 <<
" name == \"" <<
name <<
"\"";
553 return newFromScratch(name);
556Identity &IdentityManager::modifyIdentityForUoid(uint uoid)
558 for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) {
559 if ((*it).uoid() == uoid) {
564 qCWarning(KIDENTITYMANAGEMENT_LOG) <<
"IdentityManager::identityForUoid() used as"
565 <<
"newFromScratch() replacement!" <<
Qt::endl
566 <<
" uoid == \"" << uoid <<
"\"";
567 return newFromScratch(
i18n(
"Unnamed"));
570const Identity &IdentityManager::defaultIdentity()
const
572 for (ConstIterator it =
begin(); it !=
end(); ++it) {
573 if ((*it).isDefault()) {
578 if (d->mIdentities.isEmpty()) {
579 qCritical() <<
"IdentityManager: No default identity found!";
581 qCWarning(KIDENTITYMANAGEMENT_LOG) <<
"IdentityManager: No default identity found!";
586bool IdentityManager::setAsDefault(uint uoid)
590 ConstIterator
end(d->shadowIdentities.constEnd());
591 for (ConstIterator it = d->shadowIdentities.constBegin(); it !=
end; ++it) {
592 if ((*it).uoid() == uoid) {
603 for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) {
604 (*it).setIsDefault((*it).uoid() == uoid);
612bool IdentityManager::removeIdentity(
const QString &name)
614 if (d->shadowIdentities.size() <= 1) {
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);
631bool IdentityManager::removeIdentityForced(
const QString &name)
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);
646Identity &IdentityManager::newFromScratch(
const QString &name)
648 return newFromExisting(Identity(name));
651Identity &IdentityManager::newFromControlCenter(
const QString &name)
656 return newFromExisting(Identity(name,
660 es.
getSetting(KEMailSettings::ReplyToAddress)));
663Identity &IdentityManager::newFromExisting(
const Identity &other,
const QString &name)
665 d->shadowIdentities << other;
666 Identity &result = d->shadowIdentities.
last();
667 result.setIsDefault(
false);
668 result.setUoid(d->newUoid());
670 result.setIdentityName(name);
678 for (ConstIterator it = begin(); it !=
end(); ++it) {
679 lst << (*it).primaryEmailAddress();
680 if (!(*it).emailAliases().isEmpty()) {
681 lst << (*it).emailAliases();
691void KIdentityManagementCore::IdentityManager::slotRollback()
696IdentityManagerPrivate::~IdentityManagerPrivate()
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
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 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()
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
qsizetype removeAll(const AT &t)
void reserve(qsizetype size)
double bounded(double highest)
QRandomGenerator * global()
QString arg(Args &&... args) const const
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