00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "collectionstatisticsdelegate.h"
00021 #include "collectionstatisticsmodel.h"
00022
00023 #include <kcolorscheme.h>
00024 #include <kdebug.h>
00025
00026 #include <QtGui/QPainter>
00027 #include <QtGui/QStyle>
00028 #include <QtGui/QStyleOption>
00029 #include <QtGui/QStyleOptionViewItemV4>
00030 #include <QtGui/QTreeView>
00031
00032 #include "entitytreemodel.h"
00033 #include "collectionstatistics.h"
00034 #include "collection.h"
00035 #include "progressspinnerdelegate_p.h"
00036
00037 using namespace Akonadi;
00038
00039 namespace Akonadi {
00040
00041 enum CountType
00042 {
00043 UnreadCount,
00044 TotalCount
00045 };
00046
00047 class CollectionStatisticsDelegatePrivate
00048 {
00049 public:
00050 QTreeView *parent;
00051 bool drawUnreadAfterFolder;
00052 DelegateAnimator *animator;
00053 QColor mSelectedUnreadColor;
00054 QColor mDeselectedUnreadColor;
00055
00056 CollectionStatisticsDelegatePrivate( QTreeView *treeView )
00057 : parent( treeView ),
00058 drawUnreadAfterFolder( false ),
00059 animator( 0 )
00060 {
00061 mSelectedUnreadColor = KColorScheme( QPalette::Active, KColorScheme::Selection )
00062 .foreground( KColorScheme::LinkText ).color();
00063 mDeselectedUnreadColor = KColorScheme( QPalette::Active, KColorScheme::View )
00064 .foreground( KColorScheme::LinkText ).color();
00065 }
00066
00067 template<CountType countType>
00068 qint64 getCountRecursive( const QModelIndex &index ) const
00069 {
00070 Collection collection = qvariant_cast<Collection>( index.data( EntityTreeModel::CollectionRole ) );
00071 Q_ASSERT( collection.isValid() );
00072 CollectionStatistics statistics = collection.statistics();
00073 qint64 count = qMax( 0LL, countType == UnreadCount ? statistics.unreadCount() : statistics.count() );
00074
00075 if ( index.model()->hasChildren( index ) )
00076 {
00077 const int rowCount = index.model()->rowCount( index );
00078 for ( int row = 0; row < rowCount; row++ )
00079 {
00080 static const int column = 0;
00081 count += getCountRecursive<countType>( index.model()->index( row, column, index ) );
00082 }
00083 }
00084 return count;
00085 }
00086 };
00087
00088 }
00089
00090 CollectionStatisticsDelegate::CollectionStatisticsDelegate( QTreeView *parent )
00091 : QStyledItemDelegate( parent ),
00092 d_ptr( new CollectionStatisticsDelegatePrivate( parent ) )
00093 {
00094
00095 }
00096
00097 CollectionStatisticsDelegate::~CollectionStatisticsDelegate()
00098 {
00099 delete d_ptr;
00100 }
00101
00102 void CollectionStatisticsDelegate::setUnreadCountShown( bool enable )
00103 {
00104 Q_D( CollectionStatisticsDelegate );
00105 d->drawUnreadAfterFolder = enable;
00106 }
00107
00108 bool CollectionStatisticsDelegate::unreadCountShown() const
00109 {
00110 Q_D( const CollectionStatisticsDelegate );
00111 return d->drawUnreadAfterFolder;
00112 }
00113
00114 void CollectionStatisticsDelegate::setProgressAnimationEnabled( bool enable )
00115 {
00116 Q_D( CollectionStatisticsDelegate );
00117 if ( enable == ( d->animator != 0 ) )
00118 return;
00119 if ( enable ) {
00120 Q_ASSERT( !d->animator );
00121 Akonadi::DelegateAnimator *animator = new Akonadi::DelegateAnimator( d->parent );
00122 d->animator = animator;
00123 } else {
00124 delete d->animator;
00125 d->animator = 0;
00126 }
00127 }
00128
00129 bool CollectionStatisticsDelegate::progressAnimationEnabled() const
00130 {
00131 Q_D( const CollectionStatisticsDelegate );
00132 return d->animator != 0;
00133 }
00134
00135 void CollectionStatisticsDelegate::initStyleOption( QStyleOptionViewItem *option,
00136 const QModelIndex &index ) const
00137 {
00138 Q_D( const CollectionStatisticsDelegate );
00139
00140 QStyleOptionViewItemV4 *noTextOption =
00141 qstyleoption_cast<QStyleOptionViewItemV4 *>( option );
00142 QStyledItemDelegate::initStyleOption( noTextOption, index );
00143 noTextOption->text.clear();
00144
00145 if ( d->animator ) {
00146
00147 const Akonadi::Collection collection = index.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
00148
00149 if (!collection.isValid())
00150 {
00151 d->animator->pop(index);
00152 return;
00153 }
00154
00155 if (index.data(Akonadi::EntityTreeModel::FetchStateRole).toInt() != Akonadi::EntityTreeModel::FetchingState)
00156 {
00157 d->animator->pop(index);
00158 return;
00159 }
00160
00161 d->animator->push(index);
00162
00163 if (QStyleOptionViewItemV4 *v4 = qstyleoption_cast<QStyleOptionViewItemV4 *>(option)) {
00164 v4->icon = d->animator->sequenceFrame(index);
00165 }
00166 }
00167 }
00168
00169 class PainterStateSaver
00170 {
00171 public:
00172 PainterStateSaver( QPainter *painter )
00173 {
00174 mPainter = painter;
00175 mPainter->save();
00176 }
00177
00178 ~PainterStateSaver()
00179 {
00180 mPainter->restore();
00181 }
00182
00183 private:
00184 QPainter *mPainter;
00185 };
00186
00187 void CollectionStatisticsDelegate::paint( QPainter *painter,
00188 const QStyleOptionViewItem &option,
00189 const QModelIndex &index ) const
00190 {
00191 Q_D( const CollectionStatisticsDelegate );
00192 PainterStateSaver stateSaver( painter );
00193
00194
00195
00196 QStyledItemDelegate::paint( painter, option, index );
00197
00198
00199
00200 QStyleOptionViewItemV4 option4 = option;
00201 QStyledItemDelegate::initStyleOption( &option4, index );
00202 QString text = option4.text;
00203
00204
00205 QStyle *s = d->parent->style();
00206 const QWidget *widget = option4.widget;
00207 QRect textRect = s->subElementRect( QStyle::SE_ItemViewItemText, &option4, widget );
00208
00209
00210
00211 QModelIndex firstColumn = index.model()->index( index.row(), 0, index.parent() );
00212 bool expanded = d->parent->isExpanded( firstColumn );
00213
00214 if ( option.state & QStyle::State_Selected ) {
00215 painter->setPen( option.palette.highlightedText().color() );
00216 }
00217
00218 Collection collection = index.sibling( index.row(), 0 ).data( EntityTreeModel::CollectionRole ).value<Collection>();
00219
00220 Q_ASSERT(collection.isValid());
00221
00222 CollectionStatistics statistics = collection.statistics();
00223
00224 qint64 unreadCount = qMax( 0LL, statistics.unreadCount() );
00225 qint64 unreadRecursiveCount = d->getCountRecursive<UnreadCount>( index.sibling( index.row(), 0 ) );
00226
00227
00228 if ( d->drawUnreadAfterFolder && index.column() == 0 ) {
00229
00230
00231 QString unread;
00232
00233 if ( expanded && unreadCount > 0 )
00234 unread = QString( QLatin1String( " (%1)" ) ).arg( unreadCount );
00235 else if ( !expanded ) {
00236 if ( unreadCount != unreadRecursiveCount )
00237 unread = QString( QLatin1String( " (%1 + %2)" ) ).arg( unreadCount ).arg( unreadRecursiveCount - unreadCount );
00238 else if ( unreadCount > 0 )
00239 unread = QString( QLatin1String( " (%1)" ) ).arg( unreadCount );
00240 }
00241
00242 PainterStateSaver stateSaver( painter );
00243
00244 if ( !unread.isEmpty() ) {
00245 QFont font = painter->font();
00246 font.setBold( true );
00247 painter->setFont( font );
00248 }
00249
00250
00251
00252 QString folderName = text;
00253 QFontMetrics fm( painter->fontMetrics() );
00254 int unreadWidth = fm.width( unread );
00255 if ( fm.width( folderName ) + unreadWidth > textRect.width() ) {
00256 folderName = fm.elidedText( folderName, Qt::ElideRight,
00257 textRect.width() - unreadWidth );
00258 }
00259 int folderWidth = fm.width( folderName );
00260 QRect folderRect = textRect;
00261 QRect unreadRect = textRect;
00262 folderRect.setRight( textRect.left() + folderWidth );
00263 unreadRect.setLeft( folderRect.right() );
00264
00265
00266 painter->drawText( folderRect, Qt::AlignLeft, folderName );
00267
00268 const QColor unreadColor = (option.state & QStyle::State_Selected) ? d->mSelectedUnreadColor : d->mDeselectedUnreadColor;
00269 painter->setPen( unreadColor );
00270 painter->drawText( unreadRect, Qt::AlignLeft, unread );
00271
00272 return;
00273 }
00274
00275
00276
00277 if ( ( index.column() == 1 || index.column() == 2 ) ) {
00278
00279 PainterStateSaver stateSaver( painter );
00280
00281 QStyleOptionViewItem opt = option;
00282
00283 QString sumText;
00284 if ( index.column() == 1 && ( ( !expanded && unreadRecursiveCount > 0 ) || ( expanded && unreadCount > 0 ) ) ) {
00285 QFont font = painter->font();
00286 font.setBold( true );
00287 painter->setFont( font );
00288 sumText = QString::number( expanded ? unreadCount : unreadRecursiveCount );
00289 } else {
00290
00291 qint64 totalCount = statistics.count();
00292 qint64 totalRecursiveCount = d->getCountRecursive<TotalCount>( index.sibling( index.row(), 0 ) );
00293 if (index.column() == 2 && ( ( !expanded && totalRecursiveCount > 0 ) || ( expanded && totalCount > 0 ) ) ) {
00294 sumText = QString::number( expanded ? totalCount : totalRecursiveCount );
00295 }
00296 }
00297
00298 painter->drawText( textRect, Qt::AlignRight, sumText );
00299
00300 return;
00301 }
00302
00303 painter->drawText( textRect, option4.displayAlignment, text );
00304 }
00305
00306 #include "collectionstatisticsdelegate.moc"