diff --git a/calendarsupport/kcalprefs.cpp b/calendarsupport/kcalprefs.cpp index 559377bc98..46e521da84 100644 --- a/calendarsupport/kcalprefs.cpp +++ b/calendarsupport/kcalprefs.cpp @@ -1,342 +1,401 @@ /* Copyright (c) 2001,2003 Cornelius Schumacher Copyright (C) 2003-2004 Reinhold Kainhofer This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. */ #include "kcalprefs.h" #include "identitymanager.h" -#include "categoryconfig.h" + +#include +#include +#include +#include +#include #include #include #include #include #include #include using namespace CalendarSupport; + K_GLOBAL_STATIC( KCalPrefs, globalPrefs ) class KCalPrefs::Private { public: Private( KCalPrefs *qq ) : mDefaultCalendarId( -1 ), q( qq ) { mDefaultCategoryColor = QColor( 151, 235, 121 ); - mCategoryConfig = new CategoryConfig( q ); } ~Private() { - delete mCategoryConfig; } KDateTime::Spec mTimeSpec; Akonadi::Entity::Id mDefaultCalendarId; - CategoryConfig *mCategoryConfig; - QHash mCategoryColors; + TagCache mTagCache; QColor mDefaultCategoryColor; QDateTime mDayBegins; private: KCalPrefs *q; }; KCalPrefs::KCalPrefs() : KCalPrefsBase(), d( new Private( this ) ) { } KCalPrefs::~KCalPrefs() { delete d; } KCalPrefs *KCalPrefs::instance() { static bool firstCall = true; if ( firstCall ) { firstCall = false; globalPrefs->readConfig(); } return globalPrefs; } void KCalPrefs::usrSetDefaults() { // Default should be set a bit smarter, respecting username and locale // settings for example. KEMailSettings settings; QString tmp = settings.getSetting( KEMailSettings::RealName ); if ( !tmp.isEmpty() ) { setUserName( tmp ); } tmp = settings.getSetting( KEMailSettings::EmailAddress ); if ( !tmp.isEmpty() ) { setUserEmail( tmp ); } fillMailDefaults(); setTimeZoneDefault(); KConfigSkeleton::usrSetDefaults(); } KDateTime::Spec KCalPrefs::timeSpec() { return KSystemTimeZones::local(); } void KCalPrefs::setTimeSpec( const KDateTime::Spec &spec ) { d->mTimeSpec = spec; } Akonadi::Entity::Id KCalPrefs::defaultCalendarId() const { return d->mDefaultCalendarId; } void KCalPrefs::setDefaultCalendarId( const Akonadi::Entity::Id id ) { d->mDefaultCalendarId = id; } void KCalPrefs::setTimeZoneDefault() { KTimeZone zone = KSystemTimeZones::local(); if ( !zone.isValid() ) { kError() << "KSystemTimeZones::local() return 0"; return; } kDebug () << "----- time zone:" << zone.name(); d->mTimeSpec = zone; } void KCalPrefs::fillMailDefaults() { userEmailItem()->swapDefault(); QString defEmail = userEmailItem()->value(); userEmailItem()->swapDefault(); if ( userEmail() == defEmail ) { // No korg settings - but maybe there's a kcontrol[/kmail] setting available KEMailSettings settings; if ( !settings.getSetting( KEMailSettings::EmailAddress ).isEmpty() ) { mEmailControlCenter = true; } } } void KCalPrefs::usrReadConfig() { KConfigGroup generalConfig( config(), "General" ); if ( !d->mTimeSpec.isValid() ) { setTimeZoneDefault(); } KConfigGroup defaultCalendarConfig( config(), "Calendar" ); d->mDefaultCalendarId = defaultCalendarConfig.readEntry( "Default Calendar", -1 ); - // Category colors - d->mCategoryColors = d->mCategoryConfig->readColors(); #if 0 config()->setGroup( "FreeBusy" ); if ( mRememberRetrievePw ) { d->mRetrievePassword = KStringHandler::obscure( config()->readEntry( "Retrieve Server Password" ) ); } #endif KConfigSkeleton::usrReadConfig(); fillMailDefaults(); } void KCalPrefs::usrWriteConfig() { KConfigGroup generalConfig( config(), "General" ); - d->mCategoryConfig->setColors( d->mCategoryColors ); #if 0 if ( mRememberRetrievePw ) { config()->writeEntry( "Retrieve Server Password", KStringHandler::obscure( d->mRetrievePassword ) ); } else { config()->deleteEntry( "Retrieve Server Password" ); } #endif KConfigGroup defaultCalendarConfig( config(), "Calendar" ); defaultCalendarConfig.writeEntry( "Default Calendar", defaultCalendarId() ); KConfigSkeleton::usrWriteConfig(); } QString KCalPrefs::fullName() { QString tusername; if ( mEmailControlCenter ) { KEMailSettings settings; tusername = settings.getSetting( KEMailSettings::RealName ); } else { tusername = userName(); } // Quote the username as it might contain commas and other quotable chars. tusername = KPIMUtils::quoteNameIfNecessary( tusername ); QString tname, temail; // ignore the return value from extractEmailAddressAndName() because // it will always be false since tusername does not contain "@domain". KPIMUtils::extractEmailAddressAndName( tusername, temail, tname ); return tname; } QString KCalPrefs::email() { if ( mEmailControlCenter ) { KEMailSettings settings; return settings.getSetting( KEMailSettings::EmailAddress ); } else { return userEmail(); } } QStringList KCalPrefs::allEmails() { // Grab emails from the email identities QStringList lst = CalendarSupport::identityManager()->allEmails(); // Add emails configured in korganizer lst += mAdditionalMails; // Add the email entered as the userEmail here lst += email(); // Warning, this list could contain duplicates. return lst; } QStringList KCalPrefs::fullEmails() { QStringList fullEmails; // The user name and email from the config dialog: fullEmails << QString::fromUtf8( "%1 <%2>" ).arg( fullName() ).arg( email() ); QStringList::Iterator it; // Grab emails from the email identities KPIMIdentities::IdentityManager *idmanager = CalendarSupport::identityManager(); QStringList lst = idmanager->identities(); KPIMIdentities::IdentityManager::ConstIterator it1; for ( it1 = idmanager->begin(); it1 != idmanager->end(); ++it1 ) { fullEmails << (*it1).fullEmailAddr(); } // Add emails configured in korganizer lst = mAdditionalMails; for ( it = lst.begin(); it != lst.end(); ++it ) { fullEmails << QString::fromUtf8( "%1 <%2>" ).arg( fullName() ).arg( *it ); } // Warning, this list could contain duplicates. return fullEmails; } bool KCalPrefs::thatIsMe( const QString &_email ) { // NOTE: this method is called for every created agenda view item, // so we need to keep performance in mind /* identityManager()->thatIsMe() is quite expensive since it does parsing of _email in a way which is unnecessarily complex for what we can have here, so we do that ourselves. This makes sense since this if ( Akonadi::identityManager()->thatIsMe( _email ) ) { return true; } */ // in case email contains a full name, strip it out. // the below is the simpler but slower version of the following code: // const QString email = KPIM::getEmailAddress( _email ); const QByteArray tmp = _email.toUtf8(); const char *cursor = tmp.constData(); const char *end = tmp.data() + tmp.length(); KMime::Types::Mailbox mbox; KMime::HeaderParsing::parseMailbox( cursor, end, mbox ); const QString email = mbox.addrSpec().asString(); if ( this->email() == email ) { return true; } CalendarSupport::IdentityManager::ConstIterator it; for ( it = CalendarSupport::identityManager()->begin(); it != CalendarSupport::identityManager()->end(); ++it ) { if ( (*it).matchesEmailAddress( email ) ) { return true; } } if ( mAdditionalMails.contains( email ) ) { return true; } return false; } void KCalPrefs::setCategoryColor( const QString &cat, const QColor &color ) { - d->mCategoryColors.insert( cat, color ); + Akonadi::Tag tag = d->mTagCache.getTagByGid(cat.toUtf8()); + Akonadi::TagAttribute *attr = tag.attribute(Akonadi::AttributeEntity::AddIfMissing); + attr->setBackgroundColor(color); + new Akonadi::TagModifyJob(tag); } QColor KCalPrefs::categoryColor( const QString &cat ) const { QColor color; if ( !cat.isEmpty() ) { - color = d->mCategoryColors.value( cat ); + Akonadi::Tag tag = d->mTagCache.getTagByGid(cat.toUtf8()); + if (Akonadi::TagAttribute *attr = tag.attribute()) { + color = attr->backgroundColor(); + } } return color.isValid() ? color : d->mDefaultCategoryColor; } bool KCalPrefs::hasCategoryColor( const QString &cat ) const { - return d->mCategoryColors[ cat ].isValid(); + return (categoryColor(cat) != d->mDefaultCategoryColor); } void KCalPrefs::setDayBegins( const QDateTime &dateTime ) { d->mDayBegins = dateTime; } QDateTime KCalPrefs::dayBegins() const { return d->mDayBegins; } + +TagCache::TagCache() + : QObject(), + mMonitor(new Akonadi::Monitor(this)) +{ + mMonitor->setTypeMonitored(Akonadi::Monitor::Tags); + mMonitor->tagFetchScope().fetchAttribute(); + connect(mMonitor, SIGNAL(tagAdded(Akonadi::Tag)), this, SLOT(onTagAdded(Akonadi::Tag))); + connect(mMonitor, SIGNAL(tagRemoved(Akonadi::Tag)), this, SLOT(onTagRemoved(Akonadi::Tag))); + connect(mMonitor, SIGNAL(tagChanged(Akonadi::Tag)), this, SLOT(onTagChanged(Akonadi::Tag))); + retrieveTags(); +} + +Akonadi::Tag TagCache::getTagByGid(const QByteArray &gid) +{ + return mCache.value(mGidCache.value(gid)); +} + +void TagCache::onTagAdded(const Akonadi::Tag &tag) +{ + mCache.insert(tag.id(), tag); + mGidCache.insert(tag.gid(), tag.id()); +} + +void TagCache::onTagChanged(const Akonadi::Tag &tag) +{ + onTagAdded(tag); +} + +void TagCache::onTagRemoved(const Akonadi::Tag &tag) +{ + mCache.remove(tag.id()); + mGidCache.remove(tag.gid()); +} + +void TagCache::retrieveTags() +{ + Akonadi::TagFetchJob *tagFetchJob = new Akonadi::TagFetchJob(this); + tagFetchJob->fetchScope().fetchAttribute(); + connect(tagFetchJob, SIGNAL(result(KJob*)), this, SLOT(onTagsFetched(KJob*))); +} + +void TagCache::onTagsFetched(KJob *job) +{ + if (job->error()) { + kWarning() << "Failed to fetch tags: " << job->errorString(); + return; + } + Akonadi::TagFetchJob *fetchJob = static_cast(job); + Q_FOREACH(const Akonadi::Tag &tag, fetchJob->tags()) { + onTagAdded(tag); + } +} diff --git a/calendarsupport/kcalprefs.h b/calendarsupport/kcalprefs.h index e12c005eca..4e01c57746 100644 --- a/calendarsupport/kcalprefs.h +++ b/calendarsupport/kcalprefs.h @@ -1,96 +1,126 @@ /* Copyright (c) 2000,2001 Cornelius Schumacher This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. */ #ifndef CALENDARSUPPORT_KCALPREFS_H #define CALENDARSUPPORT_KCALPREFS_H #include "calendarsupport_export.h" #include "kcalprefs_base.h" #include +#include #include +namespace Akonadi { + class Monitor; +}; +class KJob; + namespace CalendarSupport { class CALENDARSUPPORT_EXPORT KCalPrefs : public KCalPrefsBase { public: /** Constructor disabled for public. Use instance() to create a KCalPrefs object. */ KCalPrefs(); virtual ~KCalPrefs(); /** Get instance of KCalPrefs. It is made sure that there is only one instance. */ static KCalPrefs *instance(); /** Set preferences to default values */ void usrSetDefaults(); /** Read preferences from config file */ void usrReadConfig(); /** Write preferences to config file */ void usrWriteConfig(); protected: void setTimeZoneDefault(); /** Fill empty mail fields with default values. */ void fillMailDefaults(); public: // preferences data void setFullName( const QString & ); QString fullName(); void setEmail( const QString & ); QString email(); /// Returns all email addresses for the user. QStringList allEmails(); /// Returns all email addresses together with the full username for the user. QStringList fullEmails(); /// Return true if the given email belongs to the user bool thatIsMe( const QString &email ); void setTimeSpec( const KDateTime::Spec &spec ); KDateTime::Spec timeSpec(); QString mailTransport() const; Akonadi::Entity::Id defaultCalendarId() const; void setDefaultCalendarId( const Akonadi::Entity::Id ); void setCategoryColor( const QString &cat, const QColor &color ); QColor categoryColor( const QString &cat ) const; bool hasCategoryColor( const QString &cat ) const; void setDayBegins( const QDateTime &dateTime ); QDateTime dayBegins() const; private: class Private; Private *const d; }; +/** + * A tag cache + */ +class TagCache : public QObject +{ + Q_OBJECT +public: + TagCache(); + Akonadi::Tag getTagByGid(const QByteArray &gid); + +private Q_SLOTS: + void onTagAdded(const Akonadi::Tag &); + void onTagChanged(const Akonadi::Tag &); + void onTagRemoved(const Akonadi::Tag &); + void onTagsFetched(KJob*); + +private: + void retrieveTags(); + + QHash mCache; + QHash mGidCache; + Akonadi::Monitor *mMonitor; +}; + } #endif