[Bug 262735] Group by date message up sometimes, e.g. showing yesterday - saturday - yesterday - saturday
Tobias Koenig
tokoe at kde.org
Wed Jan 12 12:50:53 GMT 2011
https://bugs.kde.org/show_bug.cgi?id=262735
Tobias Koenig <tokoe at kde.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|NEW |RESOLVED
Resolution| |FIXED
--- Comment #3 from Tobias Koenig <tokoe kde org> 2011-01-12 13:50:50 ---
commit b984b66bd8e090d96bcd451a9d19e4af0c5d86ca
branch master
Author: Tobias Koenig <tokoe at kde.org>
Date: Wed Jan 12 13:51:40 2011 +0100
Fix grouping of messages in 'most recent' mode
Let ThreadGrouperComparator handle the grouper string, since
it knows what are the thread leader and the most recent items in
a thread.
BUG: 262735
diff --git a/mobile/lib/threadgroupermodel.cpp
b/mobile/lib/threadgroupermodel.cpp
index 8a00c09..cedb635 100644
--- a/mobile/lib/threadgroupermodel.cpp
+++ b/mobile/lib/threadgroupermodel.cpp
@@ -60,6 +60,11 @@ ThreadGrouperComparator::~ThreadGrouperComparator()
{
}
+QString ThreadGrouperComparator::grouperString( const Akonadi::Item& ) const
+{
+ return QString();
+}
+
Akonadi::Item ThreadGrouperComparator::threadItem( const Akonadi::Item &item )
const
{
Q_ASSERT( m_grouper );
@@ -186,6 +191,9 @@ QVariant ThreadGrouperModel::data( const QModelIndex
&index, int role ) const
if ( role == ThreadIdRole )
return d->threadRoot( index ).id();
+ else if ( role == GrouperRole ) {
+ return d->m_comparator->grouperString( index.data(
Akonadi::EntityTreeModel::ItemRole ).value<Akonadi::Item>() );
+ }
return QSortFilterProxyModel::data( index, role );
}
@@ -209,6 +217,10 @@ void ThreadGrouperModel::setSourceModel(
QAbstractItemModel *sourceModel )
if ( d->m_dynamicModelRepopulation )
connect( sourceModel, SIGNAL( dataChanged( const QModelIndex&, const
QModelIndex& ) ),
this, SLOT( populateThreadGrouperModel() ) );
+
+ QHash<int, QByteArray> names = roleNames();
+ names.insert( GrouperRole, "grouperString" );
+ setRoleNames( names );
}
bool ThreadGrouperModel::lessThan( const QModelIndex &left, const QModelIndex
&right ) const
@@ -228,6 +240,7 @@ void ThreadGrouperModel::setThreadingEnabled( bool enabled
)
d->m_threadingEnabled = enabled;
invalidate();
+ reset();
}
bool ThreadGrouperModel::threadingEnabled() const
diff --git a/mobile/lib/threadgroupermodel.h b/mobile/lib/threadgroupermodel.h
index ba43ea0..0e05171 100644
--- a/mobile/lib/threadgroupermodel.h
+++ b/mobile/lib/threadgroupermodel.h
@@ -62,6 +62,11 @@ class MOBILEUI_EXPORT ThreadGrouperComparator
*/
virtual bool lessThan( const Akonadi::Item &left, const Akonadi::Item
&right ) const = 0;
+ /**
+ * Returns the grouper string for the given @p item.
+ */
+ virtual QString grouperString( const Akonadi::Item &item ) const;
+
protected:
/**
* Returns the thread item for @p item.
@@ -102,7 +107,8 @@ class MOBILEUI_EXPORT ThreadGrouperModel : public
QSortFilterProxyModel
public:
enum CustomRoles {
// FIXME Fix custom role handling in proxies.
- ThreadIdRole = Akonadi::EntityTreeModel::UserRole + 30
+ ThreadIdRole = Akonadi::EntityTreeModel::UserRole + 30,
+ GrouperRole
};
/**
diff --git a/mobile/mail/HeaderView.qml b/mobile/mail/HeaderView.qml
index 7cabc62..3e99446 100644
--- a/mobile/mail/HeaderView.qml
+++ b/mobile/mail/HeaderView.qml
@@ -29,7 +29,6 @@ KPIM.ItemListView {
property variant checkModel
property string collapsedSections
property bool showSections : true
- property string groupingRole : "dateGroup"
delegate: [
KPIM.ItemListViewDelegate {
@@ -37,7 +36,7 @@ KPIM.ItemListView {
showCheckBox : _top.showCheckBox
checkModel : _top.checkModel
navigationModel : _top.navigationModel
- height : (_top.collapsedSections.indexOf(model[groupingRole]) >= 0) ? 0
: (itemListView.height / 7)
+ height : (_top.collapsedSections.indexOf(model.grouperString) >= 0) ? 0
: (itemListView.height / 7)
clip: true
summaryContent : [
QML.Text {
@@ -208,7 +207,7 @@ KPIM.ItemListView {
}
]
- section.property: showSections ? _top.groupingRole : ""
+ section.property: showSections ? "grouperString" : ""
section.criteria: QML.ViewSection.FullString
section.delegate: QML.Item {
id: sectionDelegate
diff --git a/mobile/mail/kmail-mobile.qml b/mobile/mail/kmail-mobile.qml
index 6c77807..66fb2fd 100644
--- a/mobile/mail/kmail-mobile.qml
+++ b/mobile/mail/kmail-mobile.qml
@@ -296,7 +296,6 @@ KPIM.MainView {
navigationModel : _threadSelector
showDeleteButton : false // too easy to accidentally hit it, although
very useful...
opacity : threadContentsViewContainer.opacity == 0 ? 1 : 0
- groupingRole : messageListSettings.groupingRole
showSections : messageListSettings.groupingRole != ""
}
QML.Connections {
diff --git a/mobile/mail/mailthreadgroupercomparator.cpp
b/mobile/mail/mailthreadgroupercomparator.cpp
index 35dec0f..c931509 100644
--- a/mobile/mail/mailthreadgroupercomparator.cpp
+++ b/mobile/mail/mailthreadgroupercomparator.cpp
@@ -24,6 +24,10 @@
#include <akonadi/kmime/messageflags.h>
#include <messagecore/stringutil.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kcalendarsystem.h>
+
MailThreadGrouperComparator::MailThreadGrouperComparator()
: mSortingOption( SortByDateTimeMostRecent ),
mIsOutboundCollection( false )
@@ -87,8 +91,8 @@ bool MailThreadGrouperComparator::lessThan( const
Akonadi::Item &leftItem, const
break;
case SortByDateTimeMostRecent:
{
- const KDateTime leftNewest = mostRecentUpdate(
leftThreadRootMessage, leftThreadRootItem.id() );
- const KDateTime rightNewest = mostRecentUpdate(
rightThreadRootMessage, rightThreadRootItem.id() );
+ const KDateTime leftNewest = mostRecentDateTimeInThread(
leftThreadRootMessage, leftThreadRootItem.id() );
+ const KDateTime rightNewest = mostRecentDateTimeInThread(
rightThreadRootMessage, rightThreadRootItem.id() );
if ( leftNewest != rightNewest ) {
return leftNewest > rightNewest;
@@ -183,6 +187,18 @@ MailThreadGrouperComparator::SortingOption
MailThreadGrouperComparator::sortingO
return mSortingOption;
}
+void MailThreadGrouperComparator::setGroupingOption( GroupingOption option )
+{
+ mGroupingOption = option;
+
+ invalidate();
+}
+
+MailThreadGrouperComparator::GroupingOption
MailThreadGrouperComparator::groupingOption() const
+{
+ return mGroupingOption;
+}
+
void MailThreadGrouperComparator::setIsOutboundCollection( bool outbound )
{
mIsOutboundCollection = outbound;
@@ -190,6 +206,72 @@ void MailThreadGrouperComparator::setIsOutboundCollection(
bool outbound )
invalidate();
}
+QString MailThreadGrouperComparator::grouperString( const Akonadi::Item &item
) const
+{
+ KMime::Message::Ptr msg;
+
+ if ( mSortingOption == SortByDateTimeMostRecent ) {
+ const Akonadi::Item::Id newestItem = mostRecentIdInThread( messageForItem(
item ), item.id() );
+ msg = messageForItem( Akonadi::Item( newestItem ) );
+ } else {
+ const Akonadi::Item rootItem = threadItem( item );
+ msg = messageForItem( rootItem );
+ }
+
+ if ( mGroupingOption == GroupByDate ) {
+ // simplified version taken from libmessagelist
+ const KDateTime& dt = msg->date()->dateTime();
+ const QDate dDate = dt.date();
+ const KCalendarSystem *calendar = KGlobal::locale()->calendar();
+ int daysAgo = -1;
+ if ( calendar->isValid( dDate ) && calendar->isValid( QDate::currentDate()
) ) {
+ daysAgo = dDate.daysTo( QDate::currentDate() );
+ }
+
+ if ( daysAgo < 0 || !dt.isValid() ) // In the future or invalid
+ return i18n( "Unknown" );
+ else if( daysAgo == 0 ) // Today
+ return i18n( "Today" );
+ else if ( daysAgo == 1 ) // Yesterday
+ return i18n( "Yesterday" );
+ else if ( daysAgo > 1 && daysAgo < calendar->daysInWeek(
QDate::currentDate() ) ) // Within last seven days
+ return KGlobal::locale()->calendar()->weekDayName( dDate );
+ else if( calendar->month( dDate ) == calendar->month( QDate::currentDate()
) && calendar->year( dDate ) == calendar->year( QDate::currentDate() ) ) { //
within this month
+ const int startOfWeekDaysAgo = ( calendar->daysInWeek(
QDate::currentDate() ) + calendar->dayOfWeek( QDate::currentDate() ) -
+ KGlobal::locale()->weekStartDay() ) %
calendar->daysInWeek( QDate::currentDate() );
+ const int weeksAgo = ( ( daysAgo - startOfWeekDaysAgo ) /
calendar->daysInWeek( QDate::currentDate() ) ) + 1;
+ if ( weeksAgo == 0 )
+ return KGlobal::locale()->calendar()->weekDayName( dDate );
+ else
+ return i18np( "One Week Ago", "%1 Weeks Ago", weeksAgo );
+ } else if ( calendar->year( dDate ) == calendar->year(
QDate::currentDate() ) ) { // within this year
+ return calendar->monthName( dDate );
+ } else { // in previous years
+ static QHash<int, QString> yearNameHash;
+
+ QString yearName;
+ if ( yearNameHash.contains( dDate.year() ) ) {
+ yearName = yearNameHash.value( dDate.year() );
+ } else {
+ yearName = calendar->yearString( dDate );
+ yearNameHash.insert( dDate.year(), yearName );
+ }
+ return i18nc( "Message Aggregation Group Header: Month name and Year
number", "%1 %2", calendar->monthName( dDate ), yearName );
+ }
+ } else if ( mGroupingOption == GroupBySenderReceiver ) {
+ QStringList l;
+ foreach ( const KMime::Types::Mailbox &mbox, msg->from()->mailboxes() ) {
+ if ( mbox.hasName() )
+ l.append( mbox.name() );
+ else
+ l.append( mbox.addrSpec().asPrettyString() );
+ }
+ return l.join( ", " );
+ } else {
+ return QLatin1String( "dummy" );
+ }
+}
+
void MailThreadGrouperComparator::resetCaches()
{
mMessageCache.clear();
@@ -205,18 +287,22 @@ QByteArray
MailThreadGrouperComparator::identifierForMessage( const KMime::Messa
return identifier;
}
-KDateTime MailThreadGrouperComparator::mostRecentUpdate( const
KMime::Message::Ptr &threadRoot, Akonadi::Item::Id itemId ) const
+KDateTime MailThreadGrouperComparator::mostRecentDateTimeInThread( const
KMime::Message::Ptr &threadRoot, Akonadi::Item::Id itemId ) const
{
- const QHash<Akonadi::Item::Id, KDateTime>::const_iterator it =
mMostRecentCache.constFind( itemId );
+ const QHash<Akonadi::Item::Id, MostRecentEntry>::const_iterator it =
mMostRecentCache.constFind( itemId );
if ( it != mMostRecentCache.constEnd() )
- return *it;
+ return (*it).dateTime;
const QSet<QByteArray> messageIds = threadDescendants( identifierForMessage(
threadRoot, itemId ) );
KDateTime newest = threadRoot->date()->dateTime();
+ Akonadi::Item::Id newestId = itemId;
if ( messageIds.isEmpty() ) {
- mMostRecentCache.insert( itemId, newest );
+ MostRecentEntry entry;
+ entry.id = newestId;
+ entry.dateTime = newest;
+ mMostRecentCache.insert( itemId, entry );
return newest;
}
@@ -227,14 +313,59 @@ KDateTime MailThreadGrouperComparator::mostRecentUpdate(
const KMime::Message::P
const KMime::Message::Ptr message = messageForItem( item );
const KDateTime messageDateTime = message->date()->dateTime();
- if ( messageDateTime > newest )
+ if ( messageDateTime > newest ) {
newest = messageDateTime;
+ newestId = item.id();
+ }
}
- mMostRecentCache.insert( itemId, newest );
+ MostRecentEntry entry;
+ entry.id = newestId;
+ entry.dateTime = newest;
+
+ mMostRecentCache.insert( itemId, entry );
return newest;
}
+Akonadi::Item::Id MailThreadGrouperComparator::mostRecentIdInThread( const
KMime::Message::Ptr &threadRoot, Akonadi::Item::Id itemId ) const
+{
+ const QHash<Akonadi::Item::Id, MostRecentEntry>::const_iterator it =
mMostRecentCache.constFind( itemId );
+ if ( it != mMostRecentCache.constEnd() )
+ return (*it).id;
+
+ const QSet<QByteArray> messageIds = threadDescendants( identifierForMessage(
threadRoot, itemId ) );
+
+ KDateTime newest = threadRoot->date()->dateTime();
+ Akonadi::Item::Id newestId = itemId;
+
+ if ( messageIds.isEmpty() ) {
+ MostRecentEntry entry;
+ entry.id = newestId;
+ entry.dateTime = newest;
+ mMostRecentCache.insert( itemId, entry );
+ return itemId;
+ }
+
+ foreach ( const QByteArray &messageId, messageIds ) {
+ const Akonadi::Item item = itemForIdentifier( messageId );
+ Q_ASSERT( item.isValid() );
+ Q_ASSERT( item.hasPayload<KMime::Message::Ptr>() );
+
+ const KMime::Message::Ptr message = messageForItem( item );
+ const KDateTime messageDateTime = message->date()->dateTime();
+ if ( messageDateTime > newest )
+ newest = messageDateTime;
+ newestId = item.id();
+ }
+
+ MostRecentEntry entry;
+ entry.id = newestId;
+ entry.dateTime = newest;
+
+ mMostRecentCache.insert( itemId, entry );
+ return itemId;
+}
+
KMime::Message::Ptr MailThreadGrouperComparator::messageForItem( const
Akonadi::Item &item ) const
{
const QHash<Akonadi::Item::Id, KMime::Message::Ptr>::const_iterator it =
mMessageCache.constFind( item.id() );
diff --git a/mobile/mail/mailthreadgroupercomparator.h
b/mobile/mail/mailthreadgroupercomparator.h
index 5c3d696..4fa41e4 100644
--- a/mobile/mail/mailthreadgroupercomparator.h
+++ b/mobile/mail/mailthreadgroupercomparator.h
@@ -39,6 +39,13 @@ class MailThreadGrouperComparator : public
ThreadGrouperComparator
SortByActionItem
};
+ enum GroupingOption
+ {
+ GroupByNone,
+ GroupByDate,
+ GroupBySenderReceiver
+ };
+
/**
* Creates a new mail thread grouper comparator.
*/
@@ -67,24 +74,38 @@ class MailThreadGrouperComparator : public
ThreadGrouperComparator
void setSortingOption( SortingOption option );
SortingOption sortingOption() const;
+ void setGroupingOption( GroupingOption option );
+ GroupingOption groupingOption() const;
+
/**
* Sets whether the currently compared items come from an outbound mail
collection
* (e.g. outbox, sent or drafts).
*/
void setIsOutboundCollection( bool outbound );
+ virtual QString grouperString( const Akonadi::Item &item ) const;
+
protected:
virtual void resetCaches();
private:
QByteArray identifierForMessage( const KMime::Message::Ptr&,
Akonadi::Item::Id ) const;
- KDateTime mostRecentUpdate( const KMime::Message::Ptr&, Akonadi::Item::Id
) const;
+ KDateTime mostRecentDateTimeInThread( const KMime::Message::Ptr&,
Akonadi::Item::Id ) const;
+ Akonadi::Item::Id mostRecentIdInThread( const KMime::Message::Ptr&,
Akonadi::Item::Id ) const;
KMime::Message::Ptr messageForItem( const Akonadi::Item &item ) const;
SortingOption mSortingOption;
+ GroupingOption mGroupingOption;
bool mIsOutboundCollection;
mutable QHash<Akonadi::Item::Id, KMime::Message::Ptr> mMessageCache;
- mutable QHash<Akonadi::Item::Id, KDateTime> mMostRecentCache;
+
+ struct MostRecentEntry
+ {
+ Akonadi::Item::Id id;
+ KDateTime dateTime;
+ };
+
+ mutable QHash<Akonadi::Item::Id, MostRecentEntry> mMostRecentCache;
};
#endif
diff --git a/mobile/mail/mainview.cpp b/mobile/mail/mainview.cpp
index 35f0d14..cdfae0e 100644
--- a/mobile/mail/mainview.cpp
+++ b/mobile/mail/mainview.cpp
@@ -1753,6 +1753,18 @@ void MainView::messageListSettingsChanged( const
MessageListSettings &settings )
break;
}
+ switch ( settings.groupingOption() ) {
+ case MessageListSettings::GroupByDate:
+ m_grouperComparator->setGroupingOption(
MailThreadGrouperComparator::GroupByDate );
+ break;
+ case MessageListSettings::GroupBySenderReceiver:
+ m_grouperComparator->setGroupingOption(
MailThreadGrouperComparator::GroupBySenderReceiver );
+ break;
+ case MessageListSettings::GroupByNone:
+ m_grouperComparator->setGroupingOption(
MailThreadGrouperComparator::GroupByNone );
+ break;
+ }
+
m_threadGrouperModel->setThreadingEnabled( settings.useThreading() );
m_threadGrouperModel->sort( 0, settings.sortingOrder() );
--
Configure bugmail: https://bugs.kde.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.
More information about the Kdepim-bugs
mailing list