• Skip to content
  • Skip to link menu
KDE 4.5 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

akonadi

collectionstatisticsdelegate.cpp

00001 /*
00002     Copyright (c) 2008 Thomas McGuire <thomas.mcguire@gmx.net>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
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   // First, paint the basic, but without the text. We remove the text
00195   // in initStyleOption(), which gets called by QStyledItemDelegate::paint().
00196   QStyledItemDelegate::paint( painter, option, index );
00197 
00198   // No, we retrieve the correct style option by calling intiStyleOption from
00199   // the superclass.
00200   QStyleOptionViewItemV4 option4 = option;
00201   QStyledItemDelegate::initStyleOption( &option4, index );
00202   QString text = option4.text;
00203 
00204   // Now calculate the rectangle for the text
00205   QStyle *s = d->parent->style();
00206   const QWidget *widget = option4.widget;
00207   QRect textRect = s->subElementRect( QStyle::SE_ItemViewItemText, &option4, widget );
00208 
00209    // When checking if the item is expanded, we need to check that for the first
00210   // column, as Qt only recogises the index as expanded for the first column
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   // Draw the unread count after the folder name (in parenthesis)
00228   if ( d->drawUnreadAfterFolder && index.column() == 0 ) {
00229     // Construct the string which will appear after the foldername (with the
00230     // unread count)
00231     QString unread;
00232 //     qDebug() << expanded << unreadCount << unreadRecursiveCount;
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     // Squeeze the folder text if it is to big and calculate the rectangles
00251     // where the folder text and the unread count will be drawn to
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     // Draw folder name and unread count
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   // For the unread/total column, paint the summed up count if the item
00276   // is collapsed
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"

akonadi

Skip menu "akonadi"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.7.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal