diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e17f7a9..4557a2b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,95 +1,95 @@ cmake_minimum_required(VERSION 3.5) -set(PIM_VERSION "5.11.40") +set(PIM_VERSION "5.11.41") project(KIdentityManagement VERSION ${PIM_VERSION}) # ECM setup set(KF5_MIN_VERSION "5.57.0") find_package(ECM ${KF5_MIN_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) include(GenerateExportHeader) include(ECMGenerateHeaders) include(ECMGeneratePriFile) include(ECMSetupVersion) include(FeatureSummary) include(KDEInstallDirs) include(KDECMakeSettings) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(ECMQtDeclareLoggingCategory) set(KIDENTITYMANAGEMENT_LIB_VERSION ${PIM_VERSION}) set(PIMTEXTEDIT_LIB_VERSION "5.11.40") ecm_setup_version(PROJECT VARIABLE_PREFIX KIDENTITYMANAGEMENT VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kidentitymanagement_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5IdentityManagementConfigVersion.cmake" SOVERSION 5 ) ########### Find packages ########### find_package(Qt5Network NO_MODULE REQUIRED) find_package(KF5CoreAddons ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Completion ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5TextWidgets ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5XmlGui ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5KIO ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Config ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Codecs ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5IconThemes ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5PimTextEdit ${PIMTEXTEDIT_LIB_VERSION} CONFIG REQUIRED) add_definitions(-DTRANSLATION_DOMAIN=\"libkpimidentities5\") # workaround for https://bugreports.qt.io/browse/QTBUG-74665 (bug in qt5.13 reevaluate it) if (${Qt5Widgets_VERSION} STREQUAL "5.13.0") MESSAGE(STATUS "Qt version: ${Qt5Widgets_VERSION} DISABLE compile without deprecated methods. bug QTBUG-74665") else() add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) endif() add_definitions(-DQT_NO_FOREACH) ########### Targets ########### add_subdirectory(src) if(BUILD_TESTING) add_subdirectory(autotests) endif() ########### CMake Config Files ########### set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5IdentityManagement") configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KF5IdentityManagementConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KF5IdentityManagementConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KF5IdentityManagementConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KF5IdentityManagementConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) install(EXPORT KF5IdentityManagementTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5IdentityManagementTargets.cmake NAMESPACE KF5:: ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kidentitymanagement_version.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5} COMPONENT Devel ) install( FILES kidentitymanagement.categories kidentitymanagement.renamecategories DESTINATION ${KDE_INSTALL_CONFDIR} ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/identitymanager.cpp b/src/identitymanager.cpp index 0a192fc4..ab55e116 100644 --- a/src/identitymanager.cpp +++ b/src/identitymanager.cpp @@ -1,718 +1,719 @@ /* Copyright (c) 2002 Marc Mutz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // config keys: static const char configKeyDefaultIdentity[] = "Default Identity"; #include "identitymanager.h" #include "identity.h" // for IdentityList::{export,import}Data #include // for static helper functions #include // for IdentityEntry::fromControlCenter() #include #include "kidentitymanagement_debug.h" #include #include #include #include #include #include #include #include #include #include #include #include "identitymanageradaptor.h" namespace KIdentityManagement { static QString newDBusObjectName() { static int s_count = 0; QString name(QStringLiteral("/KIDENTITYMANAGER_IdentityManager")); if (s_count++) { name += QLatin1Char('_'); name += QString::number(s_count); } return name; } /** * Private class that helps to provide binary compatibility between releases. * @internal */ //@cond PRIVATE class Q_DECL_HIDDEN KIdentityManagement::IdentityManager::Private { public: Private(KIdentityManagement::IdentityManager *); ~Private(); void writeConfig() const; void readConfig(KConfig *config); void createDefaultIdentity(); QStringList groupList(KConfig *config) const; void slotIdentitiesChanged(const QString &id); KConfig *mConfig = nullptr; QList mIdentities; QList shadowIdentities; // returns a new Unique Object Identifier int newUoid(); bool mReadOnly = true; KIdentityManagement::IdentityManager *q; }; IdentityManager::Private::Private(KIdentityManagement::IdentityManager *manager) : q(manager) { } void IdentityManager::Private::writeConfig() const { const QStringList identities = groupList(mConfig); QStringList::const_iterator groupEnd = identities.constEnd(); for (QStringList::const_iterator group = identities.constBegin(); group != groupEnd; ++group) { mConfig->deleteGroup(*group); } int i = 0; ConstIterator end = mIdentities.constEnd(); for (ConstIterator it = mIdentities.constBegin(); it != end; ++it, ++i) { KConfigGroup cg(mConfig, QStringLiteral("Identity #%1").arg(i)); (*it).writeConfig(cg); if ((*it).isDefault()) { // remember which one is default: KConfigGroup general(mConfig, "General"); general.writeEntry(configKeyDefaultIdentity, (*it).uoid()); // Also write the default identity to emailsettings KEMailSettings es; es.setSetting(KEMailSettings::RealName, (*it).fullName()); es.setSetting(KEMailSettings::EmailAddress, (*it).primaryEmailAddress()); es.setSetting(KEMailSettings::Organization, (*it).organization()); es.setSetting(KEMailSettings::ReplyToAddress, (*it).replyToAddr()); } } mConfig->sync(); } void IdentityManager::Private::readConfig(KConfig *config) { mIdentities.clear(); const QStringList identities = groupList(config); if (identities.isEmpty()) { return; // nothing to be done... } KConfigGroup general(config, "General"); uint defaultIdentity = general.readEntry(configKeyDefaultIdentity, 0); bool haveDefault = false; QStringList::const_iterator groupEnd = identities.constEnd(); for (QStringList::const_iterator group = identities.constBegin(); group != groupEnd; ++group) { KConfigGroup configGroup(config, *group); Identity identity; identity.readConfig(configGroup); //Don't load invalid identity if (!identity.isNull() && !identity.primaryEmailAddress().isEmpty()) { if (!haveDefault && identity.uoid() == defaultIdentity) { haveDefault = true; identity.setIsDefault(true); } } mIdentities << identity; } if (!haveDefault) { if (mIdentities.isEmpty()) { mIdentities << Identity(); } qCWarning(KIDENTITYMANAGEMENT_LOG) << "IdentityManager: There was no default identity." << "Marking first one as default."; mIdentities.first().setIsDefault(true); } std::sort(mIdentities.begin(), mIdentities.end()); shadowIdentities = mIdentities; } void IdentityManager::Private::createDefaultIdentity() { QString fullName, emailAddress; bool done = false; // Check if the application has any settings q->createDefaultIdentity(fullName, emailAddress); // If not, then use the kcontrol settings if (fullName.isEmpty() && emailAddress.isEmpty()) { KEMailSettings emailSettings; fullName = emailSettings.getSetting(KEMailSettings::RealName); emailAddress = emailSettings.getSetting(KEMailSettings::EmailAddress); if (!fullName.isEmpty() && !emailAddress.isEmpty()) { q->newFromControlCenter(i18nc("use default address from control center", "Default")); done = true; } else { // If KEmailSettings doesn't have name and address, generate something from KUser KUser user; if (fullName.isEmpty()) { fullName = user.property(KUser::FullName).toString(); } if (emailAddress.isEmpty()) { emailAddress = user.loginName(); if (!emailAddress.isEmpty()) { KConfigGroup general(mConfig, "General"); QString defaultdomain = general.readEntry("Default domain"); if (!defaultdomain.isEmpty()) { emailAddress += QLatin1Char('@') + defaultdomain; } else { emailAddress.clear(); } } } } } if (!done) { // Default identity name QString name(i18nc("Default name for new email accounts/identities.", "Unnamed")); if (!emailAddress.isEmpty()) { // If we have an email address, create a default identity name from it QString idName = emailAddress; int pos = idName.indexOf(QLatin1Char('@')); if (pos != -1) { name = idName.mid(pos + 1, -1); } // Make the name a bit more human friendly name.replace(QLatin1Char('.'), QLatin1Char(' ')); pos = name.indexOf(QLatin1Char(' ')); if (pos != 0) { name[pos + 1] = name[pos + 1].toUpper(); } name[0] = name[0].toUpper(); } else if (!fullName.isEmpty()) { // If we have a full name, create a default identity name from it name = fullName; } shadowIdentities << Identity(name, fullName, emailAddress); } shadowIdentities.last().setIsDefault(true); shadowIdentities.last().setUoid(newUoid()); if (mReadOnly) { // commit won't do it in readonly mode mIdentities = shadowIdentities; } } QStringList IdentityManager::Private::groupList(KConfig *config) const { return config->groupList().filter(QRegularExpression(QStringLiteral("^Identity #\\d+$"))); } int IdentityManager::Private::newUoid() { int uoid; // determine the UOIDs of all saved identities QList usedUOIDs; usedUOIDs.reserve(1 + mIdentities.count() + (q->hasPendingChanges() ? shadowIdentities.count() : 0)); QList::ConstIterator end(mIdentities.constEnd()); for (QList::ConstIterator it = mIdentities.constBegin(); it != end; ++it) { usedUOIDs << (*it).uoid(); } if (q->hasPendingChanges()) { // add UOIDs of all shadow identities. Yes, we will add a lot of duplicate // UOIDs, but avoiding duplicate UOIDs isn't worth the effort. QList::ConstIterator endShadow(shadowIdentities.constEnd()); for (QList::ConstIterator it = shadowIdentities.constBegin(); it != endShadow; ++it) { usedUOIDs << (*it).uoid(); } } usedUOIDs << 0; // no UOID must be 0 because this value always refers to the // default identity do { uoid = KRandom::random(); } while (usedUOIDs.indexOf(uoid) != -1); return uoid; } void IdentityManager::Private::slotIdentitiesChanged(const QString &id) { qCDebug(KIDENTITYMANAGEMENT_LOG) << " KIdentityManagement::IdentityManager::slotIdentitiesChanged :" << id; const QString ourIdentifier = QStringLiteral("%1/%2"). arg(QDBusConnection::sessionBus().baseService(), q->property("uniqueDBusPath").toString()); if (id != ourIdentifier) { mConfig->reparseConfiguration(); Q_ASSERT(!q->hasPendingChanges()); readConfig(mConfig); + emit q->needToReloadIdentitySettings(); emit q->changed(); } } Q_GLOBAL_STATIC(IdentityManager, s_self) IdentityManager *IdentityManager::self() { return s_self; } IdentityManager::IdentityManager(bool readonly, QObject *parent, const char *name) : QObject(parent) , d(new Private(this)) { static bool triedMigration = false; if (!triedMigration) { triedMigration = true; Kdelibs4ConfigMigrator migrate(QStringLiteral("identitymanager")); migrate.setConfigFiles(QStringList() << QStringLiteral("emailidentities")); migrate.migrate(); } setObjectName(QLatin1String(name)); new IdentityManagerAdaptor(this); QDBusConnection dbus = QDBusConnection::sessionBus(); const QString dbusPath = newDBusObjectName(); setProperty("uniqueDBusPath", dbusPath); const QString dbusInterface = QStringLiteral("org.kde.pim.IdentityManager"); dbus.registerObject(dbusPath, this); dbus.connect(QString(), QString(), dbusInterface, QStringLiteral("identitiesChanged"), this, SLOT(slotIdentitiesChanged(QString))); d->mReadOnly = readonly; d->mConfig = new KConfig(QStringLiteral("emailidentities")); d->readConfig(d->mConfig); // we need at least a default identity: if (d->mIdentities.isEmpty()) { qCDebug(KIDENTITYMANAGEMENT_LOG) << "IdentityManager: No identity found. Creating default."; d->createDefaultIdentity(); commit(); } KSharedConfig::Ptr kmailConf(KSharedConfig::openConfig(QStringLiteral("kmail2rc"))); if (!d->mReadOnly) { bool needCommit = false; if (kmailConf->hasGroup(QStringLiteral("Composer"))) { KConfigGroup composerGroup = kmailConf->group(QStringLiteral("Composer")); if (composerGroup.hasKey(QStringLiteral("pgp-auto-sign"))) { const bool pgpAutoSign = composerGroup.readEntry(QStringLiteral("pgp-auto-sign"), false); QList::iterator end = d->mIdentities.end(); for (QList::iterator it = d->mIdentities.begin(); it != end; ++it) { it->setPgpAutoSign(pgpAutoSign); } composerGroup.deleteEntry(QStringLiteral("pgp-auto-sign")); composerGroup.sync(); needCommit = true; } } if (kmailConf->hasGroup(QStringLiteral("General"))) { KConfigGroup generalGroup = kmailConf->group(QStringLiteral("General")); if (generalGroup.hasKey(QStringLiteral("Default domain"))) { QString defaultDomain = generalGroup.readEntry(QStringLiteral("Default domain")); if (defaultDomain.isEmpty()) { defaultDomain = QHostInfo::localHostName(); } QList::iterator end = d->mIdentities.end(); for (QList::iterator it = d->mIdentities.begin(); it != end; ++it) { it->setDefaultDomainName(defaultDomain); } generalGroup.deleteEntry(QStringLiteral("Default domain")); generalGroup.sync(); needCommit = true; } } if (needCommit) { commit(); } } // Migration: people without settings in kemailsettings should get some if (KEMailSettings().getSetting(KEMailSettings::EmailAddress).isEmpty()) { d->writeConfig(); } } IdentityManager::~IdentityManager() { if (hasPendingChanges()) { qCWarning(KIDENTITYMANAGEMENT_LOG) << "IdentityManager: There were uncommitted changes!"; } delete d; } QString IdentityManager::makeUnique(const QString &name) const { int suffix = 1; QString result = name; while (identities().contains(result)) { result = i18nc("%1: name; %2: number appended to it to make it unique " "among a list of names", "%1 #%2", name, suffix); ++suffix; } return result; } bool IdentityManager::isUnique(const QString &name) const { return !identities().contains(name); } void IdentityManager::commit() { // early out: if (!hasPendingChanges() || d->mReadOnly) { return; } QList seenUOIDs; seenUOIDs.reserve(d->mIdentities.count()); QList::ConstIterator end = d->mIdentities.constEnd(); for (QList::ConstIterator it = d->mIdentities.constBegin(); it != end; ++it) { seenUOIDs << (*it).uoid(); } QList changedUOIDs; // find added and changed identities: for (QList::ConstIterator it = d->shadowIdentities.constBegin(); it != d->shadowIdentities.constEnd(); ++it) { int index = seenUOIDs.indexOf((*it).uoid()); if (index != -1) { uint uoid = seenUOIDs.at(index); const Identity &orig = identityForUoid(uoid); // look up in mIdentities if (*it != orig) { // changed identity qCDebug(KIDENTITYMANAGEMENT_LOG) << "emitting changed() for identity" << uoid; emit changed(*it); changedUOIDs << uoid; } seenUOIDs.removeAll(uoid); } else { // new identity qCDebug(KIDENTITYMANAGEMENT_LOG) << "emitting added() for identity" << (*it).uoid(); emit added(*it); } } // what's left are deleted identities: for (QList::ConstIterator it = seenUOIDs.constBegin(); it != seenUOIDs.constEnd(); ++it) { qCDebug(KIDENTITYMANAGEMENT_LOG) << "emitting deleted() for identity" << (*it); emit deleted(*it); } d->mIdentities = d->shadowIdentities; d->writeConfig(); // now that mIdentities has all the new info, we can emit the added/changed // signals that ship a uoid. This is because the slots might use // identityForUoid(uoid)... QList::ConstIterator changedEnd(changedUOIDs.constEnd()); for (QList::ConstIterator it = changedUOIDs.constBegin(); it != changedEnd; ++it) { emit changed(*it); } emit changed(); // normal signal // DBus signal for other IdentityManager instances const QString ourIdentifier = QStringLiteral("%1/%2"). arg(QDBusConnection::sessionBus().baseService(), property("uniqueDBusPath").toString()); emit identitiesChanged(ourIdentifier); } void IdentityManager::rollback() { d->shadowIdentities = d->mIdentities; } bool IdentityManager::hasPendingChanges() const { return d->mIdentities != d->shadowIdentities; } QStringList IdentityManager::identities() const { QStringList result; result.reserve(d->mIdentities.count()); ConstIterator end = d->mIdentities.constEnd(); for (ConstIterator it = d->mIdentities.constBegin(); it != end; ++it) { result << (*it).identityName(); } return result; } QStringList IdentityManager::shadowIdentities() const { QStringList result; result.reserve(d->shadowIdentities.count()); ConstIterator end = d->shadowIdentities.constEnd(); for (ConstIterator it = d->shadowIdentities.constBegin(); it != end; ++it) { result << (*it).identityName(); } return result; } void IdentityManager::sort() { std::sort(d->shadowIdentities.begin(), d->shadowIdentities.end()); } IdentityManager::ConstIterator IdentityManager::begin() const { return d->mIdentities.constBegin(); } IdentityManager::ConstIterator IdentityManager::end() const { return d->mIdentities.constEnd(); } IdentityManager::Iterator IdentityManager::modifyBegin() { return d->shadowIdentities.begin(); } IdentityManager::Iterator IdentityManager::modifyEnd() { return d->shadowIdentities.end(); } const Identity &IdentityManager::identityForUoid(uint uoid) const { for (ConstIterator it = begin(); it != end(); ++it) { if ((*it).uoid() == uoid) { return *it; } } return Identity::null(); } const Identity &IdentityManager::identityForUoidOrDefault(uint uoid) const { const Identity &ident = identityForUoid(uoid); if (ident.isNull()) { return defaultIdentity(); } else { return ident; } } const Identity &IdentityManager::identityForAddress( const QString &addresses) const { const QStringList addressList = KEmailAddress::splitAddressList(addresses); for (const QString &fullAddress : addressList) { const QString addrSpec = KEmailAddress::extractEmailAddress(fullAddress).toLower(); for (ConstIterator it = begin(); it != end(); ++it) { const Identity &identity = *it; if (identity.matchesEmailAddress(addrSpec)) { return identity; } } } return Identity::null(); } bool IdentityManager::thatIsMe(const QString &addressList) const { return !identityForAddress(addressList).isNull(); } Identity &IdentityManager::modifyIdentityForName(const QString &name) { for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) { if ((*it).identityName() == name) { return *it; } } qCWarning(KIDENTITYMANAGEMENT_LOG) << "IdentityManager::modifyIdentityForName() used as" << "newFromScratch() replacement!" << endl << " name == \"" << name << "\""; return newFromScratch(name); } Identity &IdentityManager::modifyIdentityForUoid(uint uoid) { for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) { if ((*it).uoid() == uoid) { return *it; } } qCWarning(KIDENTITYMANAGEMENT_LOG) << "IdentityManager::identityForUoid() used as" << "newFromScratch() replacement!" << endl << " uoid == \"" << uoid << "\""; return newFromScratch(i18n("Unnamed")); } const Identity &IdentityManager::defaultIdentity() const { for (ConstIterator it = begin(); it != end(); ++it) { if ((*it).isDefault()) { return *it; } } if (d->mIdentities.isEmpty()) { qCritical() << "IdentityManager: No default identity found!"; } else { qCWarning(KIDENTITYMANAGEMENT_LOG) << "IdentityManager: No default identity found!"; } return *begin(); } bool IdentityManager::setAsDefault(uint uoid) { // First, check if the identity actually exists: bool found = false; ConstIterator end(d->shadowIdentities.constEnd()); for (ConstIterator it = d->shadowIdentities.constBegin(); it != end; ++it) { if ((*it).uoid() == uoid) { found = true; break; } } if (!found) { return false; } // Then, change the default as requested: for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) { (*it).setIsDefault((*it).uoid() == uoid); } // and re-sort: sort(); return true; } bool IdentityManager::removeIdentity(const QString &name) { if (d->shadowIdentities.size() <= 1) { return false; } for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) { if ((*it).identityName() == name) { bool removedWasDefault = (*it).isDefault(); d->shadowIdentities.erase(it); if (removedWasDefault && !d->shadowIdentities.isEmpty()) { d->shadowIdentities.first().setIsDefault(true); } return true; } } return false; } bool IdentityManager::removeIdentityForced(const QString &name) { for (Iterator it = modifyBegin(); it != modifyEnd(); ++it) { if ((*it).identityName() == name) { bool removedWasDefault = (*it).isDefault(); d->shadowIdentities.erase(it); if (removedWasDefault && !d->shadowIdentities.isEmpty()) { d->shadowIdentities.first().setIsDefault(true); } return true; } } return false; } Identity &IdentityManager::newFromScratch(const QString &name) { return newFromExisting(Identity(name)); } Identity &IdentityManager::newFromControlCenter(const QString &name) { KEMailSettings es; es.setProfile(es.defaultProfileName()); return newFromExisting(Identity(name, es.getSetting(KEMailSettings::RealName), es.getSetting(KEMailSettings::EmailAddress), es.getSetting(KEMailSettings::Organization), es.getSetting(KEMailSettings::ReplyToAddress))); } Identity &IdentityManager::newFromExisting(const Identity &other, const QString &name) { d->shadowIdentities << other; Identity &result = d->shadowIdentities.last(); result.setIsDefault(false); // we don't want two default identities! result.setUoid(d->newUoid()); // we don't want two identities w/ same UOID if (!name.isNull()) { result.setIdentityName(name); } return result; } QStringList KIdentityManagement::IdentityManager::allEmails() const { QStringList lst; for (ConstIterator it = begin(); it != end(); ++it) { lst << (*it).primaryEmailAddress(); if (!(*it).emailAliases().isEmpty()) { lst << (*it).emailAliases(); } } return lst; } void IdentityManager::createDefaultIdentity(QString &, QString &) { } void KIdentityManagement::IdentityManager::slotRollback() { rollback(); } IdentityManager::Private::~Private() { delete mConfig; } } #include "moc_identitymanager.cpp" diff --git a/src/identitymanager.h b/src/identitymanager.h index 06721522..332ca3e1 100644 --- a/src/identitymanager.h +++ b/src/identitymanager.h @@ -1,236 +1,238 @@ /* Copyright (c) 2002 Marc Mutz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIDENTITYMANAGER_IDENTITYMANAGER_H #define KIDENTITYMANAGER_IDENTITYMANAGER_H #include #include #include class QStringList; namespace KIdentityManagement { class Identity; /** * @short Manages the list of identities. * @author Marc Mutz **/ class KIDENTITYMANAGEMENT_EXPORT IdentityManager : public QObject { Q_OBJECT public: /** * Create an identity manager, which loads the emailidentities file * to create identities. * @param readonly if true, no changes can be made to the identity manager * This means in particular that if there is no identity configured, * the default identity created here will not be saved. * It is assumed that a minimum of one identity is always present. */ explicit IdentityManager(bool readonly = false, QObject *parent = nullptr, const char *name = nullptr); ~IdentityManager() override; /** * Creates or reuses the identity manager instance for this process. * It loads the emailidentities file to create identities. * This sets readonly to false, so you should create a separate instance * if you need it to be readonly. * @since 5.2.91 */ static IdentityManager *self(); public: typedef QList::Iterator Iterator; typedef QList::ConstIterator ConstIterator; /** * Typedef for STL style iterator */ typedef Iterator iterator; /** * Typedef for STL style iterator */ typedef ConstIterator const_iterator; /** @return a unique name for a new identity based on @p name * @param name the name of the base identity */ Q_REQUIRED_RESULT QString makeUnique(const QString &name) const; /** @return whether the @p name is unique * @param name the name to be examined */ Q_REQUIRED_RESULT bool isUnique(const QString &name) const; /** Commit changes to disk and emit changed() if necessary. */ void commit(); /** Re-read the config from disk and forget changes. */ void rollback(); /** Check whether there are any unsaved changes. */ Q_REQUIRED_RESULT bool hasPendingChanges() const; /** @return the list of identities */ Q_REQUIRED_RESULT QStringList identities() const; /** Convenience method. @return the list of (shadow) identities, ie. the ones currently under configuration. */ Q_REQUIRED_RESULT QStringList shadowIdentities() const; /** Sort the identities by name (the default is always first). This operates on the @em shadow list, so you need to @ref commit for the changes to take effect. **/ void sort(); /** @return an identity whose address matches any in @p addresses or @ref Identity::null if no such identity exists. @param addresses the string of addresses to scan for matches **/ const Identity &identityForAddress(const QString &addresses) const; /** @return true if @p addressList contains any of our addresses, false otherwise. @param addressList the addressList to examine @see #identityForAddress **/ Q_REQUIRED_RESULT bool thatIsMe(const QString &addressList) const; /** @return the identity with Unique Object Identifier (UOID) @p uoid or @ref Identity::null if not found. @param uoid the Unique Object Identifier to find identity with **/ const Identity &identityForUoid(uint uoid) const; /** Convenience method. @return the identity with Unique Object Identifier (UOID) @p uoid or the default identity if not found. @param uoid the Unique Object Identifier to find identity with **/ const Identity &identityForUoidOrDefault(uint uoid) const; /** @return the default identity */ const Identity &defaultIdentity() const; /** Sets the identity with Unique Object Identifier (UOID) @p uoid to be new the default identity. As usual, use @ref commit to make this permanent. @param uoid the default identity to set @return false if an identity with UOID @p uoid was not found **/ Q_REQUIRED_RESULT bool setAsDefault(uint uoid); /** @return the identity named @p identityName. This method returns a reference to the identity that can be modified. To let others see this change, use @ref commit. @param identityName the identity name to return modifiable reference **/ Identity &modifyIdentityForName(const QString &identityName); /** @return the identity with Unique Object Identifier (UOID) @p uoid. This method returns a reference to the identity that can be modified. To let others see this change, use @ref commit. **/ Identity &modifyIdentityForUoid(uint uoid); /** Removes the identity with name @p identityName Will return false if the identity is not found, or when one tries to remove the last identity. @param identityName the identity to remove **/ Q_REQUIRED_RESULT bool removeIdentity(const QString &identityName); /** * Removes the identity with name @p identityName * Will return @c false if the identity is not found, @c true otherwise. * * @note In opposite to removeIdentity, this method allows to remove the * last remaining identity. * * @since 4.6 */ Q_REQUIRED_RESULT bool removeIdentityForced(const QString &identityName); ConstIterator begin() const; ConstIterator end() const; /// Iterator used by the configuration dialog, which works on a separate list /// of identities, for modification. Changes are made effective by commit(). Iterator modifyBegin(); Iterator modifyEnd(); Identity &newFromScratch(const QString &name); Identity &newFromControlCenter(const QString &name); Identity &newFromExisting(const Identity &other, const QString &name = QString()); /** Returns the list of all email addresses (only name@host) from all identities */ Q_REQUIRED_RESULT QStringList allEmails() const; Q_SIGNALS: /** Emitted whenever a commit changes any configure option */ void changed(); /** Emitted whenever the identity with Unique Object Identifier (UOID) @p uoid changed. Useful for more fine-grained change notifications than what is possible with the standard @ref changed() signal. */ void changed(uint uoid); /** Emitted whenever the identity @p ident changed. Useful for more fine-grained change notifications than what is possible with the standard @ref changed() signal. */ void changed(const KIdentityManagement::Identity &ident); /** Emitted on @ref commit() for each deleted identity. At the time this signal is emitted, the identity does still exist and can be retrieved by @ref identityForUoid() if needed */ void deleted(uint uoid); /** Emitted on @ref commit() for each new identity */ void added(const KIdentityManagement::Identity &ident); + void needToReloadIdentitySettings(); + protected: /** * This is called when no identity has been defined, so we need to * create a default one. The parameters are filled with some default * values from KUser, but reimplementations of this method can give * them another value. */ virtual void createDefaultIdentity(QString & /*fullName*/, QString & /*emailAddress*/); protected Q_SLOTS: void slotRollback(); Q_SIGNALS: void identitiesChanged(const QString &id); private: //@cond PRIVATE class Private; Private *d; //@endcond Q_PRIVATE_SLOT(d, void slotIdentitiesChanged(const QString &id)) }; } // namespace #endif // _KMAIL_IDENTITYMANAGER_H_