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