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)
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()
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 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