You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1032 lines
33 KiB
1032 lines
33 KiB
/****************************************************************************** |
|
* |
|
* Copyright 2008 Szymon Tomasz Stefanek <pragma@kvirc.net> |
|
* |
|
* 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. |
|
* |
|
*******************************************************************************/ |
|
|
|
#include "messagelistview/core/manager.h" |
|
|
|
#include "messagelistview/core/aggregation.h" |
|
#include "messagelistview/core/configureaggregationsdialog.h" |
|
#include "messagelistview/core/theme.h" |
|
#include "messagelistview/core/view.h" |
|
#include "messagelistview/core/configurethemesdialog.h" |
|
#include "messagelistview/core/widgetbase.h" |
|
#include "messagelistview/core/storagemodelbase.h" |
|
#include "messagelistview/core/model.h" |
|
|
|
#include <QPixmap> |
|
#include <QTimer> |
|
|
|
#include <kmime/kmime_dateformatter.h> // kdepimlibs |
|
|
|
#include <KConfig> |
|
#include <KIconLoader> |
|
#include <KGlobalSettings> |
|
#include <KApplication> |
|
#include <KLocale> |
|
|
|
#include "kmkernel.h" // These includes add a soft dependancy on stuff outside MessageListView::Core. |
|
#include "globalsettings.h" // It should be quite simple to remove it if we need this stuff to become a library. |
|
|
|
namespace KMail |
|
{ |
|
|
|
namespace MessageListView |
|
{ |
|
|
|
namespace Core |
|
{ |
|
|
|
Manager * Manager::mInstance = 0; |
|
|
|
Manager::Manager() |
|
: QObject() |
|
{ |
|
mInstance = this; |
|
|
|
mDateFormatter = new KMime::DateFormatter(); |
|
|
|
mDisplayMessageToolTips = true; |
|
|
|
mPixmapMessageNew = new QPixmap( SmallIcon( "mail-unread-new" ) ); |
|
mPixmapMessageUnread = new QPixmap( SmallIcon( "mail-unread" ) ); |
|
mPixmapMessageRead = new QPixmap( SmallIcon( "mail-read" ) ); |
|
mPixmapMessageDeleted = new QPixmap( SmallIcon( "mail-deleted" ) ); |
|
mPixmapMessageReplied = new QPixmap( SmallIcon( "mail-replied" ) ); |
|
mPixmapMessageRepliedAndForwarded = new QPixmap( SmallIcon( "mail-forwarded-replied" ) ); |
|
mPixmapMessageQueued = new QPixmap( SmallIcon( "mail-queued" ) ); // mail-queue ? |
|
mPixmapMessageActionItem = new QPixmap( SmallIcon( "mail-task" ) ); |
|
mPixmapMessageSent = new QPixmap( SmallIcon( "mail-sent" ) ); |
|
mPixmapMessageForwarded = new QPixmap( SmallIcon( "mail-forwarded" ) ); |
|
mPixmapMessageImportant = new QPixmap( SmallIcon( "emblem-important" ) ); // "flag" |
|
mPixmapMessageWatched = new QPixmap( SmallIcon( "mail-thread-watch" ) ); |
|
mPixmapMessageIgnored = new QPixmap( SmallIcon( "mail-thread-ignored" ) ); |
|
mPixmapMessageSpam = new QPixmap( SmallIcon( "mail-mark-junk" ) ); |
|
mPixmapMessageHam = new QPixmap( SmallIcon( "mail-mark-notjunk" ) ); |
|
mPixmapMessageFullySigned = new QPixmap( SmallIcon( "mail-signed-verified" ) ); |
|
mPixmapMessagePartiallySigned = new QPixmap( SmallIcon( "mail-signed-part" ) ); |
|
mPixmapMessageUndefinedSigned = new QPixmap( SmallIcon( "mail-signed" ) ); |
|
mPixmapMessageNotSigned = new QPixmap( SmallIcon( "text-plain" ) ); |
|
mPixmapMessageFullyEncrypted = new QPixmap( SmallIcon( "mail-encrypted-full" ) ); |
|
mPixmapMessagePartiallyEncrypted = new QPixmap( SmallIcon( "mail-encrypted-part" ) ); |
|
mPixmapMessageUndefinedEncrypted = new QPixmap( SmallIcon( "mail-encrypted" ) ); |
|
mPixmapMessageNotEncrypted = new QPixmap( SmallIcon( "text-plain" ) ); |
|
mPixmapMessageAttachment = new QPixmap( SmallIcon( "mail-attachment" ) ); |
|
//mPixmapShowMore = new QPixmap( SmallIcon( "list-add.png" ) ); |
|
//mPixmapShowLess = new QPixmap( SmallIcon( "list-remove.png" ) ); |
|
if ( KApplication::isRightToLeft() ) |
|
mPixmapShowMore = new QPixmap( SmallIcon( "arrow-left" ) ); |
|
else |
|
mPixmapShowMore = new QPixmap( SmallIcon( "arrow-right" ) ); |
|
mPixmapShowLess = new QPixmap( SmallIcon( "arrow-down" ) ); |
|
mPixmapVerticalLine = new QPixmap( SmallIcon( "mail-vertical-separator-line" ) ); |
|
mPixmapHorizontalSpacer = new QPixmap( SmallIcon( "mail-horizontal-space" ) ); |
|
|
|
mCachedLocalizedUnknownText = i18nc( "Unknown date", "Unknown" ) ; |
|
|
|
mHeartBeatTimer = new QTimer(this); |
|
QObject::connect( |
|
mHeartBeatTimer,SIGNAL(timeout()), |
|
this,SLOT(slotHeartBeat()) |
|
); |
|
|
|
mHeartBeatTimer->start(60000); // 1 minute |
|
|
|
loadConfiguration(); |
|
} |
|
|
|
Manager::~Manager() |
|
{ |
|
mHeartBeatTimer->stop(); |
|
|
|
saveConfiguration(); |
|
removeAllAggregations(); |
|
|
|
delete mHeartBeatTimer; |
|
|
|
delete mPixmapMessageNew; |
|
delete mPixmapMessageUnread; |
|
delete mPixmapMessageRead; |
|
delete mPixmapMessageDeleted; |
|
delete mPixmapMessageReplied; |
|
delete mPixmapMessageRepliedAndForwarded; |
|
delete mPixmapMessageQueued; |
|
delete mPixmapMessageActionItem; |
|
delete mPixmapMessageSent; |
|
delete mPixmapMessageForwarded; |
|
delete mPixmapMessageImportant; // "flag" |
|
delete mPixmapMessageWatched; |
|
delete mPixmapMessageIgnored; |
|
delete mPixmapMessageSpam; |
|
delete mPixmapMessageHam; |
|
delete mPixmapMessageFullySigned; |
|
delete mPixmapMessagePartiallySigned; |
|
delete mPixmapMessageUndefinedSigned; |
|
delete mPixmapMessageNotSigned; |
|
delete mPixmapMessageFullyEncrypted; |
|
delete mPixmapMessagePartiallyEncrypted; |
|
delete mPixmapMessageUndefinedEncrypted; |
|
delete mPixmapMessageNotEncrypted; |
|
delete mPixmapMessageAttachment; |
|
delete mPixmapShowMore; |
|
delete mPixmapShowLess; |
|
delete mPixmapVerticalLine; |
|
delete mPixmapHorizontalSpacer; |
|
|
|
delete mDateFormatter; |
|
|
|
ConfigureAggregationsDialog::cleanup(); // make sure it's dead |
|
ConfigureThemesDialog::cleanup(); // make sure it's dead |
|
|
|
mInstance = 0; |
|
} |
|
|
|
void Manager::slotHeartBeat() |
|
{ |
|
// sweep through all the models asking them to check their dates |
|
for( QList< Widget * >::Iterator it = mWidgetList.begin(); it != mWidgetList.end(); ++it ) |
|
{ |
|
if ( !( *it )->view() ) |
|
continue; |
|
if ( !( *it )->view()->model() ) |
|
continue; |
|
( *it )->view()->model()->checkIfDateChanged(); |
|
} |
|
} |
|
|
|
void Manager::showConfigureAggregationsDialog( Widget *requester, const QString &preselectAggregationId ) |
|
{ |
|
ConfigureAggregationsDialog::display( requester ? requester->window() : 0, preselectAggregationId ); |
|
} |
|
|
|
void Manager::showConfigureThemesDialog( Widget *requester, const QString &preselectThemeId ) |
|
{ |
|
ConfigureThemesDialog::display( requester ? requester->window() : 0, preselectThemeId ); |
|
} |
|
|
|
|
|
void Manager::registerWidget( Widget *pWidget ) |
|
{ |
|
if ( !mInstance ) |
|
mInstance = new Manager(); |
|
|
|
mInstance->mWidgetList.append( pWidget ); |
|
} |
|
|
|
void Manager::unregisterWidget( Widget *pWidget ) |
|
{ |
|
if ( !mInstance ) |
|
{ |
|
qWarning("ERROR: MessageListView::Manager::unregisterWidget() called when Manager::mInstance is 0"); |
|
return; |
|
} |
|
|
|
mInstance->mWidgetList.removeAll( pWidget ); |
|
|
|
if ( mInstance->mWidgetList.count() < 1 ) |
|
{ |
|
delete mInstance; |
|
mInstance = 0; |
|
} |
|
} |
|
|
|
unsigned long Manager::preSelectedMessageForStorageModel( const StorageModel *storageModel ) |
|
{ |
|
KConfigGroup conf( KMKernel::config(), "MessageListView::StorageModelSelectedMessages" ); |
|
|
|
// QVariant supports unsigned int OR unsigned long long int, NOT unsigned long int... doh... |
|
qulonglong defValue = 0; |
|
|
|
return conf.readEntry( QString( "MessageUniqueIdForStorageModel%1" ).arg( storageModel->id() ), defValue ); |
|
} |
|
|
|
void Manager::savePreSelectedMessageForStorageModel( const StorageModel * storageModel, unsigned long uniqueIdOfMessage ) |
|
{ |
|
KConfigGroup conf( KMKernel::config(), "MessageListView::StorageModelSelectedMessages" ); |
|
|
|
|
|
if ( uniqueIdOfMessage ) |
|
{ |
|
// QVariant supports unsigned int OR unsigned long long int, NOT unsigned long int... doh... |
|
qulonglong val = uniqueIdOfMessage; |
|
|
|
conf.writeEntry( QString( "MessageUniqueIdForStorageModel%1" ).arg( storageModel->id() ), val ); |
|
} else |
|
conf.deleteEntry( QString( "MessageUniqueIdForStorageModel%1" ).arg( storageModel->id() ) ); |
|
} |
|
|
|
const Aggregation * Manager::aggregation( const QString &id ) |
|
{ |
|
Aggregation * opt = mAggregations.value( id ); |
|
if ( opt ) |
|
return opt; |
|
|
|
return defaultAggregation(); |
|
} |
|
|
|
const Aggregation * Manager::defaultAggregation() |
|
{ |
|
KConfigGroup conf( KMKernel::config(), "MessageListView::StorageModelAggregations" ); |
|
|
|
QString aggregationId = conf.readEntry( QString( "DefaultSet" ), "" ); |
|
|
|
Aggregation * opt = 0; |
|
|
|
if ( !aggregationId.isEmpty() ) |
|
opt = mAggregations.value( aggregationId ); |
|
|
|
if ( opt ) |
|
return opt; |
|
|
|
// try just the first one |
|
QHash< QString, Aggregation * >::Iterator it = mAggregations.begin(); |
|
if ( it != mAggregations.end() ) |
|
return *it; |
|
|
|
// aargh |
|
createDefaultAggregations(); |
|
|
|
it = mAggregations.begin(); |
|
return *it; |
|
} |
|
|
|
void Manager::saveAggregationForStorageModel( const StorageModel *storageModel, const QString &id, bool storageUsesPrivateAggregation ) |
|
{ |
|
KConfigGroup conf( KMKernel::config(), "MessageListView::StorageModelAggregations" ); |
|
|
|
if ( storageUsesPrivateAggregation ) |
|
conf.writeEntry( QString( "SetForStorageModel%1" ).arg( storageModel->id() ), id ); |
|
else |
|
conf.deleteEntry( QString( "SetForStorageModel%1" ).arg( storageModel->id() ) ); |
|
|
|
if ( !storageUsesPrivateAggregation ) |
|
conf.writeEntry( QString( "DefaultSet" ), id ); |
|
} |
|
|
|
|
|
const Aggregation * Manager::aggregationForStorageModel( const StorageModel *storageModel, bool *storageUsesPrivateAggregation ) |
|
{ |
|
Q_ASSERT( storageUsesPrivateAggregation ); |
|
|
|
*storageUsesPrivateAggregation = false; // this is by default |
|
|
|
if ( !storageModel ) |
|
return defaultAggregation(); |
|
|
|
KConfigGroup conf( KMKernel::config(), "MessageListView::StorageModelAggregations" ); |
|
|
|
QString aggregationId = conf.readEntry( QString( "SetForStorageModel%1" ).arg( storageModel->id() ), "" ); |
|
|
|
Aggregation * opt = 0; |
|
|
|
if ( !aggregationId.isEmpty() ) |
|
{ |
|
// a private aggregation was stored |
|
opt = mAggregations.value( aggregationId ); |
|
*storageUsesPrivateAggregation = ( opt != 0 ); |
|
} |
|
|
|
if ( opt ) |
|
return opt; |
|
|
|
// FIXME: If the storageModel is a mailing list, maybe suggest a mailing-list like preset... |
|
// We could even try to guess if the storageModel is a mailing list |
|
|
|
return defaultAggregation(); |
|
} |
|
|
|
void Manager::addAggregation( Aggregation *set ) |
|
{ |
|
Aggregation * old = mAggregations.value( set->id() ); |
|
delete old; |
|
mAggregations.insert( set->id(), set ); |
|
} |
|
|
|
void Manager::createDefaultAggregations() |
|
{ |
|
addAggregation( |
|
new Aggregation( |
|
i18n( "Current Activity, Threaded" ), |
|
i18n( "This view uses smart date range groups. " \ |
|
"Messages are threaded. " \ |
|
"So for example, in \"Today\" you will find all the messages arrived today " \ |
|
"and all the threads that have been active today." |
|
), |
|
Aggregation::GroupByDateRange, |
|
Aggregation::ExpandRecentGroups, |
|
Aggregation::PerfectReferencesAndSubject, |
|
Aggregation::MostRecentMessage, |
|
Aggregation::ExpandThreadsWithUnreadOrImportantMessages, |
|
Aggregation::FavorInteractivity |
|
) |
|
); |
|
|
|
addAggregation( |
|
new Aggregation( |
|
i18n( "Current Activity, Flat" ), |
|
i18n( "This view uses smart date range groups. " \ |
|
"Messages are not threaded. " \ |
|
"So for example, in \"Today\" you will simply find all the messages arrived today." |
|
), |
|
Aggregation::GroupByDateRange, |
|
Aggregation::ExpandRecentGroups, |
|
Aggregation::NoThreading, |
|
Aggregation::MostRecentMessage, |
|
Aggregation::NeverExpandThreads, |
|
Aggregation::FavorInteractivity |
|
) |
|
); |
|
|
|
addAggregation( |
|
new Aggregation( |
|
i18n( "Activity by Date, Threaded" ), |
|
i18n( "This view uses day-by-day groups. " \ |
|
"Messages are threaded. " \ |
|
"So for example, in \"Today\" you will find all the messages arrived today " \ |
|
"and all the threads that have been active today." |
|
), |
|
Aggregation::GroupByDate, |
|
Aggregation::ExpandRecentGroups, |
|
Aggregation::PerfectReferencesAndSubject, |
|
Aggregation::MostRecentMessage, |
|
Aggregation::ExpandThreadsWithUnreadOrImportantMessages, |
|
Aggregation::FavorInteractivity |
|
) |
|
); |
|
|
|
addAggregation( |
|
new Aggregation( |
|
i18n( "Activity by Date, Flat" ), |
|
i18n( "This view uses day-by-day groups. " \ |
|
"Messages are not threaded. " \ |
|
"So for example, in \"Today\" you will simply find all the messages arrived today." |
|
), |
|
Aggregation::GroupByDate, |
|
Aggregation::ExpandRecentGroups, |
|
Aggregation::NoThreading, |
|
Aggregation::MostRecentMessage, |
|
Aggregation::NeverExpandThreads, |
|
Aggregation::FavorInteractivity |
|
) |
|
); |
|
|
|
addAggregation( |
|
new Aggregation( |
|
i18n( "Standard Mailing List" ), |
|
i18n( "This is a plain and old mailing list view: no groups and heavy threading." ), |
|
Aggregation::NoGrouping, |
|
Aggregation::NeverExpandGroups, |
|
Aggregation::PerfectReferencesAndSubject, |
|
Aggregation::TopmostMessage, |
|
Aggregation::ExpandThreadsWithUnreadOrImportantMessages, |
|
Aggregation::FavorInteractivity |
|
) |
|
); |
|
|
|
addAggregation( |
|
new Aggregation( |
|
i18n( "Flat Date View" ), |
|
i18n( "This is a plain and old list of messages sorted by date: no groups and no threading." \ |
|
), |
|
Aggregation::NoGrouping, |
|
Aggregation::NeverExpandGroups, |
|
Aggregation::NoThreading, |
|
Aggregation::TopmostMessage, |
|
Aggregation::NeverExpandThreads, |
|
Aggregation::FavorInteractivity |
|
) |
|
); |
|
|
|
addAggregation( |
|
new Aggregation( |
|
i18n( "Senders/Receivers, Flat" ), |
|
i18n( "This view groups the messages by senders or receivers (depending on the folder " \ |
|
"type). " \ |
|
"Messages are not threaded." |
|
), |
|
Aggregation::GroupBySenderOrReceiver, |
|
Aggregation::NeverExpandGroups, |
|
Aggregation::NoThreading, |
|
Aggregation::TopmostMessage, |
|
Aggregation::NeverExpandThreads, |
|
Aggregation::FavorSpeed |
|
) |
|
); |
|
|
|
addAggregation( |
|
new Aggregation( |
|
i18n( "Thread Starters" ), |
|
i18n( "This view groups the messages in threads and then groups the threads by the starting user." ), |
|
Aggregation::GroupBySenderOrReceiver, |
|
Aggregation::NeverExpandGroups, |
|
Aggregation::PerfectReferencesAndSubject, |
|
Aggregation::TopmostMessage, |
|
Aggregation::NeverExpandThreads, |
|
Aggregation::FavorSpeed |
|
) |
|
); |
|
|
|
/* |
|
FIX THIS |
|
addAggregation( |
|
new Aggregation( |
|
i18n( "Recent Thread Starters" ), |
|
i18n( "This view groups the messages in threads and then groups the threads by the starting user. " \ |
|
"Groups are sorted by the date of the first thread start. " |
|
), |
|
Aggregation::GroupBySenderOrReceiver, |
|
Aggregation::SortGroupsByDateTimeOfMostRecent, |
|
Aggregation::Descending, |
|
Aggregation::PerfectReferencesAndSubject, |
|
Aggregation::TopmostMessage, |
|
Aggregation::SortMessagesByDateTime, |
|
Aggregation::Descending |
|
) |
|
); |
|
*/ |
|
} |
|
|
|
void Manager::removeAllAggregations() |
|
{ |
|
for( QHash< QString, Aggregation * >::Iterator it = mAggregations.begin(); it != mAggregations.end(); ++it ) |
|
delete ( *it ); |
|
|
|
mAggregations.clear(); |
|
} |
|
|
|
void Manager::aggregationsConfigurationCompleted() |
|
{ |
|
if ( mAggregations.count() < 1 ) |
|
createDefaultAggregations(); // panic |
|
|
|
saveConfiguration(); // just to be sure :) |
|
|
|
// notify all the widgets that they should reload the option set combos |
|
for( QList< Widget * >::Iterator it = mWidgetList.begin(); it != mWidgetList.end(); ++it ) |
|
( *it )->aggregationsChanged(); |
|
} |
|
|
|
const SortOrder Manager::sortOrderForStorageModel( const StorageModel *storageModel, bool *storageUsesPrivateSortOrder ) |
|
{ |
|
Q_ASSERT( storageUsesPrivateSortOrder ); |
|
|
|
*storageUsesPrivateSortOrder = false; // this is by default |
|
|
|
if ( !storageModel ) |
|
return SortOrder(); |
|
|
|
KConfigGroup conf( KMKernel::config(), "MessageListView::StorageModelSortOrder" ); |
|
SortOrder ret; |
|
ret.readConfig( conf, storageModel->id(), storageUsesPrivateSortOrder ); |
|
return ret; |
|
} |
|
|
|
void Manager::saveSortOrderForStorageModel( const StorageModel *storageModel, |
|
const SortOrder& order, bool storageUsesPrivateSortOrder ) |
|
{ |
|
KConfigGroup conf( KMKernel::config(), "MessageListView::StorageModelSortOrder" ); |
|
order.writeConfig( conf, storageModel->id(), storageUsesPrivateSortOrder ); |
|
} |
|
|
|
const Theme * Manager::theme( const QString &id ) |
|
{ |
|
Theme * opt = mThemes.value( id ); |
|
if ( opt ) |
|
return opt; |
|
|
|
return defaultTheme(); |
|
} |
|
|
|
const Theme * Manager::defaultTheme() |
|
{ |
|
KConfigGroup conf( KMKernel::config(), "MessageListView::StorageModelThemes" ); |
|
|
|
QString themeId = conf.readEntry( QString( "DefaultSet" ), "" ); |
|
|
|
Theme * opt = 0; |
|
|
|
if ( !themeId.isEmpty() ) |
|
opt = mThemes.value( themeId ); |
|
|
|
if ( opt ) |
|
return opt; |
|
|
|
// try just the first one |
|
QHash< QString, Theme * >::Iterator it = mThemes.begin(); |
|
if ( it != mThemes.end() ) |
|
return *it; |
|
|
|
// aargh |
|
createDefaultThemes(); |
|
|
|
it = mThemes.begin(); |
|
|
|
Q_ASSERT( it != mThemes.end() ); |
|
|
|
return *it; |
|
} |
|
|
|
void Manager::saveThemeForStorageModel( const StorageModel *storageModel, const QString &id, bool storageUsesPrivateTheme ) |
|
{ |
|
KConfigGroup conf( KMKernel::config(), "MessageListView::StorageModelThemes" ); |
|
|
|
if ( storageUsesPrivateTheme ) |
|
conf.writeEntry( QString( "SetForStorageModel%1" ).arg( storageModel->id() ), id ); |
|
else |
|
conf.deleteEntry( QString( "SetForStorageModel%1" ).arg( storageModel->id() ) ); |
|
|
|
if ( !storageUsesPrivateTheme ) |
|
conf.writeEntry( QString( "DefaultSet" ), id ); |
|
} |
|
|
|
|
|
const Theme * Manager::themeForStorageModel( const StorageModel *storageModel, bool *storageUsesPrivateTheme ) |
|
{ |
|
Q_ASSERT( storageUsesPrivateTheme ); |
|
|
|
*storageUsesPrivateTheme = false; // this is by default |
|
|
|
if ( !storageModel ) |
|
return defaultTheme(); |
|
|
|
KConfigGroup conf( KMKernel::config(), "MessageListView::StorageModelThemes" ); |
|
QString themeId = conf.readEntry( QString( "SetForStorageModel%1" ).arg( storageModel->id() ), "" ); |
|
|
|
Theme * opt = 0; |
|
|
|
if ( !themeId.isEmpty() ) |
|
{ |
|
// a private theme was stored |
|
opt = mThemes.value( themeId ); |
|
*storageUsesPrivateTheme = (opt != 0); |
|
} |
|
|
|
if ( opt ) |
|
return opt; |
|
|
|
// FIXME: If the storageModel is a mailing list, maybe suggest a mailing-list like preset... |
|
// We could even try to guess if the storageModel is a mailing list |
|
|
|
// FIXME: Prefer right-to-left themes when application layout is RTL. |
|
|
|
return defaultTheme(); |
|
} |
|
|
|
void Manager::addTheme( Theme *set ) |
|
{ |
|
Theme * old = mThemes.value( set->id() ); |
|
delete old; |
|
mThemes.insert( set->id(), set ); |
|
} |
|
|
|
static Theme::Column * add_theme_simple_text_column( Theme * s, const QString &name, Theme::ContentItem::Type type, bool visibleByDefault, SortOrder::MessageSorting messageSorting, bool alignRight, bool addGroupHeaderItem ) |
|
{ |
|
Theme::Column * c = new Theme::Column(); |
|
c->setLabel( name ); |
|
c->setVisibleByDefault( visibleByDefault ); |
|
c->setMessageSorting( messageSorting ); |
|
|
|
Theme::Row * r = new Theme::Row(); |
|
|
|
Theme::ContentItem * i = new Theme::ContentItem( type ); |
|
i->setFont( KGlobalSettings::generalFont() ); |
|
|
|
if ( alignRight ) |
|
r->addRightItem( i ); |
|
else |
|
r->addLeftItem( i ); |
|
|
|
c->addMessageRow( r ); |
|
|
|
if ( addGroupHeaderItem ) |
|
{ |
|
Theme::Row * r = new Theme::Row(); |
|
|
|
Theme::ContentItem * i = new Theme::ContentItem( type ); |
|
i->setFont( KGlobalSettings::generalFont() ); |
|
|
|
if ( alignRight ) |
|
r->addRightItem( i ); |
|
else |
|
r->addLeftItem( i ); |
|
|
|
c->addGroupHeaderRow( r ); |
|
} |
|
|
|
|
|
s->addColumn( c ); |
|
|
|
return c; |
|
} |
|
|
|
static Theme::Column * add_theme_simple_icon_column( Theme * s, const QString &name, Theme::ContentItem::Type type, bool visibleByDefault, SortOrder::MessageSorting messageSorting ) |
|
{ |
|
Theme::Column * c = new Theme::Column(); |
|
c->setLabel( name ); |
|
c->setVisibleByDefault( visibleByDefault ); |
|
c->setMessageSorting( messageSorting ); |
|
|
|
Theme::Row * r = new Theme::Row(); |
|
|
|
Theme::ContentItem * i = new Theme::ContentItem( type ); |
|
i->setSoftenByBlendingWhenDisabled( true ); |
|
|
|
r->addLeftItem( i ); |
|
|
|
c->addMessageRow( r ); |
|
|
|
s->addColumn( c ); |
|
|
|
return c; |
|
} |
|
|
|
|
|
void Manager::createDefaultThemes() |
|
{ |
|
Theme * s; |
|
Theme::Column * c; |
|
Theme::Row * r; |
|
Theme::ContentItem * i; |
|
|
|
// The "Classic" backward compatible theme |
|
|
|
s = new Theme( |
|
i18nc( "Default theme name", "Classic" ), |
|
i18n( "A simple, backward compatible, single row theme" ) |
|
); |
|
|
|
c = new Theme::Column(); |
|
c->setLabel( i18nc( "@title:column Subject of messages", "Subject" ) ); |
|
c->setMessageSorting( SortOrder::SortMessagesBySubject ); |
|
|
|
r = new Theme::Row(); |
|
i = new Theme::ContentItem( Theme::ContentItem::ExpandedStateIcon ); |
|
r->addLeftItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::GroupHeaderLabel ); |
|
QFont bigFont = KGlobalSettings::generalFont(); |
|
bigFont.setBold( true ); |
|
i->setFont( bigFont ); |
|
i->setUseCustomFont( true ); |
|
r->addLeftItem( i ); |
|
c->addGroupHeaderRow( r ); |
|
|
|
r = new Theme::Row(); |
|
i = new Theme::ContentItem( Theme::ContentItem::CombinedReadRepliedStateIcon ); |
|
r->addLeftItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::AttachmentStateIcon ); |
|
i->setHideWhenDisabled( true ); |
|
r->addLeftItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::SignatureStateIcon ); |
|
i->setHideWhenDisabled( true ); |
|
r->addLeftItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::EncryptionStateIcon ); |
|
i->setHideWhenDisabled( true ); |
|
r->addLeftItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::Subject ); |
|
r->addLeftItem( i ); |
|
c->addMessageRow( r ); |
|
|
|
s->addColumn( c ); |
|
|
|
c = add_theme_simple_text_column( s, i18n( "Sender/Receiver" ), Theme::ContentItem::SenderOrReceiver, true, SortOrder::SortMessagesBySenderOrReceiver, false, false); |
|
c->setIsSenderOrReceiver( true ); |
|
add_theme_simple_text_column( s, i18nc( "Sender of a message", "Sender" ), Theme::ContentItem::Sender, false, SortOrder::SortMessagesBySender, false, false ); |
|
add_theme_simple_text_column( s, i18nc( "Receiver of a message", "Receiver" ), Theme::ContentItem::Receiver, false, SortOrder::SortMessagesByReceiver, false, false ); |
|
add_theme_simple_text_column( s, i18nc( "Date of a message", "Date" ), Theme::ContentItem::Date, true, SortOrder::SortMessagesByDateTime, false, false ); |
|
add_theme_simple_text_column( s, i18n( "Most Recent Date" ), Theme::ContentItem::MostRecentDate, false, SortOrder::SortMessagesByDateTimeOfMostRecent, false, true ); |
|
add_theme_simple_text_column( s, i18nc( "Size of a message", "Size" ), Theme::ContentItem::Size, false, SortOrder::SortMessagesBySize, false, false ); |
|
add_theme_simple_icon_column( s, i18nc( "Attachement indication", "Attachment" ), Theme::ContentItem::AttachmentStateIcon, false, SortOrder::NoMessageSorting ); |
|
add_theme_simple_icon_column( s, i18n( "New/Unread" ), Theme::ContentItem::ReadStateIcon, false, SortOrder::SortMessagesByNewUnreadStatus ); |
|
add_theme_simple_icon_column( s, i18n( "Replied" ), Theme::ContentItem::RepliedStateIcon, false, SortOrder::NoMessageSorting ); |
|
add_theme_simple_icon_column( s, i18nc( "Message importance indication", "Important" ), Theme::ContentItem::ImportantStateIcon, false, SortOrder::NoMessageSorting ); |
|
add_theme_simple_icon_column( s, i18n( "Action Item" ), Theme::ContentItem::ActionItemStateIcon, false, SortOrder::SortMessagesByActionItemStatus ); |
|
add_theme_simple_icon_column( s, i18n( "Spam/Ham" ), Theme::ContentItem::SpamHamStateIcon, false, SortOrder::NoMessageSorting ); |
|
add_theme_simple_icon_column( s, i18n( "Watched/Ignored" ), Theme::ContentItem::WatchedIgnoredStateIcon, false, SortOrder::NoMessageSorting ); |
|
add_theme_simple_icon_column( s, i18n( "Encryption" ), Theme::ContentItem::EncryptionStateIcon, false, SortOrder::NoMessageSorting ); |
|
add_theme_simple_icon_column( s, i18n( "Signature" ), Theme::ContentItem::SignatureStateIcon, false, SortOrder::NoMessageSorting ); |
|
add_theme_simple_icon_column( s, i18n( "Tag List" ), Theme::ContentItem::TagList, false, SortOrder::NoMessageSorting ); |
|
|
|
s->resetColumnState(); // so it's initially set from defaults |
|
|
|
addTheme( s ); |
|
|
|
// The Fancy theme |
|
|
|
s = new Theme( |
|
i18n( "Fancy" ), |
|
i18n( "A fancy multiline and multi item theme" ) |
|
); |
|
|
|
c = new Theme::Column(); |
|
c->setLabel( i18n( "Message" ) ); |
|
|
|
r = new Theme::Row(); |
|
i = new Theme::ContentItem( Theme::ContentItem::ExpandedStateIcon ); |
|
r->addLeftItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::GroupHeaderLabel ); |
|
QFont aBigFont = KGlobalSettings::generalFont(); |
|
aBigFont.setBold( true ); |
|
i->setFont( aBigFont ); |
|
i->setUseCustomFont( true ); |
|
r->addLeftItem( i ); |
|
c->addGroupHeaderRow( r ); |
|
|
|
r = new Theme::Row(); |
|
i = new Theme::ContentItem( Theme::ContentItem::Subject ); |
|
r->addLeftItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::ReadStateIcon ); |
|
r->addRightItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::RepliedStateIcon ); |
|
i->setHideWhenDisabled( true ); |
|
r->addRightItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::AttachmentStateIcon ); |
|
i->setHideWhenDisabled( true ); |
|
r->addRightItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::EncryptionStateIcon ); |
|
i->setHideWhenDisabled( true ); |
|
r->addRightItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::SignatureStateIcon ); |
|
i->setHideWhenDisabled( true ); |
|
r->addRightItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::TagList ); |
|
i->setHideWhenDisabled( true ); |
|
r->addRightItem( i ); |
|
c->addMessageRow( r ); |
|
|
|
Theme::Row * firstFancyRow = r; // save it so we can continue adding stuff below (after cloning the theme) |
|
|
|
r = new Theme::Row(); |
|
i = new Theme::ContentItem( Theme::ContentItem::SenderOrReceiver ); |
|
i->setSoftenByBlending( true ); |
|
QFont aItalicFont = KGlobalSettings::generalFont(); |
|
aItalicFont.setItalic( true ); |
|
i->setFont( aItalicFont ); |
|
i->setUseCustomFont( true ); |
|
r->addLeftItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::Date ); |
|
i->setSoftenByBlending( true ); |
|
i->setFont( aItalicFont ); |
|
i->setUseCustomFont( true ); |
|
r->addRightItem( i ); |
|
c->addMessageRow( r ); |
|
|
|
s->addColumn( c ); |
|
|
|
// clone the "Fancy theme" here so we'll use it as starting point for the "Fancy with clickable status" |
|
Theme * fancyWithClickableStatus = new Theme( *s ); |
|
fancyWithClickableStatus->detach(); |
|
fancyWithClickableStatus->generateUniqueId(); |
|
|
|
// and continue the "Fancy" specific settings |
|
r = firstFancyRow; |
|
|
|
i = new Theme::ContentItem( Theme::ContentItem::ActionItemStateIcon ); |
|
i->setHideWhenDisabled( true ); |
|
r->addRightItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::ImportantStateIcon ); |
|
i->setHideWhenDisabled( true ); |
|
r->addRightItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::SpamHamStateIcon ); |
|
i->setHideWhenDisabled( true ); |
|
r->addRightItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::WatchedIgnoredStateIcon ); |
|
i->setHideWhenDisabled( true ); |
|
r->addRightItem( i ); |
|
|
|
s->setViewHeaderPolicy( Theme::NeverShowHeader ); |
|
|
|
s->resetColumnState(); // so it's initially set from defaults |
|
|
|
addTheme( s ); |
|
|
|
|
|
// The "Fancy with Clickable Status" theme |
|
|
|
s = fancyWithClickableStatus; |
|
|
|
s->setName( i18n( "Fancy with Clickable Status" ) ); |
|
s->setDescription( i18n( "A fancy multiline and multi item theme with a clickable status column" ) ); |
|
|
|
c = new Theme::Column(); |
|
c->setLabel( i18n( "Status" ) ); |
|
c->setVisibleByDefault( true ); |
|
|
|
r = new Theme::Row(); |
|
i = new Theme::ContentItem( Theme::ContentItem::ActionItemStateIcon ); |
|
i->setSoftenByBlendingWhenDisabled( true ); |
|
r->addLeftItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::ImportantStateIcon ); |
|
i->setSoftenByBlendingWhenDisabled( true ); |
|
r->addLeftItem( i ); |
|
c->addMessageRow( r ); |
|
|
|
r = new Theme::Row(); |
|
i = new Theme::ContentItem( Theme::ContentItem::SpamHamStateIcon ); |
|
i->setSoftenByBlendingWhenDisabled( true ); |
|
r->addLeftItem( i ); |
|
i = new Theme::ContentItem( Theme::ContentItem::WatchedIgnoredStateIcon ); |
|
i->setSoftenByBlendingWhenDisabled( true ); |
|
r->addLeftItem( i ); |
|
c->addMessageRow( r ); |
|
|
|
s->addColumn( c ); |
|
|
|
s->resetColumnState(); // so it's initially set from defaults |
|
|
|
addTheme( s ); |
|
} |
|
|
|
void Manager::removeAllThemes() |
|
{ |
|
for( QHash< QString, Theme * >::Iterator it = mThemes.begin(); it != mThemes.end(); ++it ) |
|
delete ( *it ); |
|
|
|
mThemes.clear(); |
|
} |
|
|
|
void Manager::themesConfigurationCompleted() |
|
{ |
|
if ( mThemes.count() < 1 ) |
|
createDefaultThemes(); // panic |
|
|
|
saveConfiguration(); // just to be sure :) |
|
|
|
// notify all the widgets that they should reload the option set combos |
|
for( QList< Widget * >::Iterator it = mWidgetList.begin(); it != mWidgetList.end(); ++it ) |
|
( *it )->themesChanged(); |
|
} |
|
|
|
void Manager::reloadAllWidgets() |
|
{ |
|
for( QList< Widget * >::Iterator it = mWidgetList.begin(); it != mWidgetList.end(); ++it ) |
|
{ |
|
if ( !( *it )->view() ) |
|
continue; |
|
( *it )->view()->reload(); |
|
} |
|
} |
|
|
|
|
|
void Manager::reloadGlobalConfiguration() |
|
{ |
|
// This is called when configuration changes (probably edited by the options dialog) |
|
int oldDateFormat = (int)mDateFormatter->format(); |
|
QString oldDateCustomFormat = mDateFormatter->customFormat(); |
|
|
|
loadGlobalConfiguration(); |
|
|
|
if ( |
|
( oldDateFormat != (int)mDateFormatter->format() ) || |
|
( oldDateCustomFormat != mDateFormatter->customFormat() ) |
|
) |
|
reloadAllWidgets(); |
|
} |
|
|
|
|
|
void Manager::loadGlobalConfiguration() |
|
{ |
|
// Load the date format |
|
KConfigGroup config( KMKernel::config(), "General" ); |
|
|
|
KMime::DateFormatter::FormatType t = (KMime::DateFormatter::FormatType) config.readEntry( |
|
"dateFormat", |
|
( int )KMime::DateFormatter::Fancy |
|
); |
|
mDateFormatter->setCustomFormat( config.readEntry( "customDateFormat", QString() ) ); |
|
mDateFormatter->setFormat( t ); |
|
|
|
mDisplayMessageToolTips = GlobalSettings::self()->displayMessageToolTips(); |
|
} |
|
|
|
void Manager::loadConfiguration() |
|
{ |
|
loadGlobalConfiguration(); |
|
|
|
{ |
|
// load Aggregations |
|
|
|
KConfigGroup conf( KMKernel::config(), "MessageListView::Aggregations" ); |
|
|
|
mAggregations.clear(); |
|
|
|
int cnt = conf.readEntry( "Count", (int)0 ); |
|
|
|
int idx = 0; |
|
while ( idx < cnt ) |
|
{ |
|
QString data = conf.readEntry( QString( "Set%1" ).arg( idx ), QString() ); |
|
if ( !data.isEmpty() ) |
|
{ |
|
Aggregation * set = new Aggregation(); |
|
if ( set->loadFromString( data ) ) |
|
{ |
|
if ( Aggregation * old = mAggregations.value( set->id() ) ) |
|
delete old; |
|
mAggregations.insert( set->id(), set ); |
|
} else { |
|
delete set; // b0rken |
|
} |
|
} |
|
idx++; |
|
} |
|
|
|
if ( mAggregations.count() == 0 ) |
|
{ |
|
// don't allow zero configuration, create some presets |
|
createDefaultAggregations(); |
|
} |
|
} |
|
|
|
{ |
|
// load Themes |
|
|
|
KConfigGroup conf( KMKernel::config(), "MessageListView::Themes" ); |
|
|
|
mThemes.clear(); |
|
|
|
int cnt = conf.readEntry( "Count", (int)0 ); |
|
|
|
int idx = 0; |
|
while ( idx < cnt ) |
|
{ |
|
QString data = conf.readEntry( QString( "Set%1" ).arg( idx ), QString() ); |
|
if ( !data.isEmpty() ) |
|
{ |
|
Theme * set = new Theme(); |
|
if ( set->loadFromString( data ) ) |
|
{ |
|
if ( Theme * old = mThemes.value( set->id() ) ) |
|
delete old; |
|
mThemes.insert( set->id(), set ); |
|
} else { |
|
kWarning() << "Saved theme loading failed"; |
|
delete set; // b0rken |
|
} |
|
} |
|
idx++; |
|
} |
|
|
|
if ( mThemes.count() == 0 ) |
|
{ |
|
// don't allow zero configuration, create some presets |
|
createDefaultThemes(); |
|
} |
|
} |
|
|
|
} |
|
|
|
void Manager::saveConfiguration() |
|
{ |
|
{ |
|
// store aggregations |
|
|
|
KConfigGroup conf( KMKernel::config(), "MessageListView::Aggregations" ); |
|
//conf.clear(); |
|
|
|
conf.writeEntry( "Count", mAggregations.count() ); |
|
|
|
int idx = 0; |
|
for( QHash< QString, Aggregation * >::Iterator it = mAggregations.begin(); it != mAggregations.end(); ++it ) |
|
{ |
|
conf.writeEntry( QString( "Set%1" ).arg( idx ), ( *it )->saveToString() ); |
|
idx++; |
|
} |
|
} |
|
|
|
{ |
|
// store themes |
|
|
|
KConfigGroup conf( KMKernel::config(), "MessageListView::Themes" ); |
|
//conf.clear(); |
|
|
|
conf.writeEntry( "Count", mThemes.count() ); |
|
|
|
int idx = 0; |
|
for( QHash< QString, Theme * >::Iterator it = mThemes.begin(); it != mThemes.end(); ++it ) |
|
{ |
|
conf.writeEntry( QString( "Set%1" ).arg( idx ), ( *it )->saveToString() ); |
|
idx++; |
|
} |
|
} |
|
} |
|
|
|
} // namespace Core |
|
|
|
} // namespace MessageListView |
|
|
|
} // namespace KMail
|
|
|