00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "statisticsproxymodel.h"
00022
00023 #include "entitytreemodel.h"
00024 #include "collectionutils_p.h"
00025
00026 #include <akonadi/collectionquotaattribute.h>
00027 #include <akonadi/collectionstatistics.h>
00028 #include <akonadi/entitydisplayattribute.h>
00029
00030 #include <kdebug.h>
00031 #include <kiconloader.h>
00032 #include <klocale.h>
00033 #include <kio/global.h>
00034
00035 #include <QtGui/QApplication>
00036 #include <QtGui/QPalette>
00037 #include <KIcon>
00038 using namespace Akonadi;
00039
00043 class StatisticsProxyModel::Private
00044 {
00045 public:
00046 Private( StatisticsProxyModel *parent )
00047 : mParent( parent ), mToolTipEnabled( false ), mExtraColumnsEnabled( true )
00048 {
00049 }
00050
00051 int sourceColumnCount( const QModelIndex &parent )
00052 {
00053 return mParent->sourceModel()->columnCount( mParent->mapToSource( parent ) );
00054 }
00055
00056 QString toolTipForCollection( const QModelIndex &index, const Collection &collection )
00057 {
00058 QString bckColor = QApplication::palette().color( QPalette::ToolTipBase ).name();
00059 QString txtColor = QApplication::palette().color( QPalette::ToolTipText ).name();
00060
00061 QString tip = QString::fromLatin1(
00062 "<table width=\"100%\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\">\n"
00063 );
00064
00065 tip += QString::fromLatin1(
00066 " <tr>\n"
00067 " <td bgcolor=\"%1\" colspan=\"2\" align=\"left\" valign=\"middle\">\n"
00068 " <div style=\"color: %2; font-weight: bold;\">\n"
00069 " %3\n"
00070 " </div>\n"
00071 " </td>\n"
00072 " </tr>\n"
00073 ).arg( txtColor ).arg( bckColor ).arg( index.data( Qt::DisplayRole ).toString() );
00074
00075
00076 tip += QString::fromLatin1(
00077 " <tr>\n"
00078 " <td align=\"left\" valign=\"top\">\n"
00079 );
00080
00081 tip += QString::fromLatin1(
00082 " <strong>%1</strong>: %2<br>\n"
00083 " <strong>%3</strong>: %4<br><br>\n"
00084 ).arg( i18n( "Total Messages" ) ).arg( collection.statistics().count() )
00085 .arg( i18n( "Unread Messages" ) ).arg( collection.statistics().unreadCount() );
00086
00087 if ( collection.hasAttribute<CollectionQuotaAttribute>() ) {
00088 CollectionQuotaAttribute *quota = collection.attribute<CollectionQuotaAttribute>();
00089 if ( quota->currentValue() > -1 && quota->maximumValue() > 0 ) {
00090 qreal percentage = ( 100.0 * quota->currentValue() ) / quota->maximumValue();
00091
00092 if ( qAbs( percentage ) >= 0.01 ) {
00093 QString percentStr = QString::number( percentage, 'f', 2 );
00094 tip += QString::fromLatin1(
00095 " <strong>%1</strong>: %2%<br>\n"
00096 ).arg( i18n( "Quota" ) ).arg( percentStr );
00097 }
00098 }
00099 }
00100
00101 tip += QString::fromLatin1(
00102 " <strong>%1</strong>: %2<br>\n"
00103 ).arg( i18n( "Storage Size" ) ).arg( KIO::convertSize( (KIO::filesize_t)( collection.statistics().size() ) ) );
00104
00105
00106 QString iconName = CollectionUtils::defaultIconName( collection );
00107 if ( collection.hasAttribute<EntityDisplayAttribute>() &&
00108 !collection.attribute<EntityDisplayAttribute>()->iconName().isEmpty() ) {
00109 iconName = collection.attribute<EntityDisplayAttribute>()->iconName();
00110 }
00111
00112 int iconSizes[] = { 32, 22 };
00113 QString iconPath;
00114
00115 for ( int i = 0; i < 2; i++ ) {
00116 iconPath = KIconLoader::global()->iconPath( iconName, -iconSizes[ i ], true );
00117 if ( !iconPath.isEmpty() )
00118 break;
00119 }
00120
00121 if ( iconPath.isEmpty() ) {
00122 iconPath = KIconLoader::global()->iconPath( QLatin1String( "folder" ), -32, false );
00123 }
00124
00125 tip += QString::fromLatin1(
00126 " </td>\n"
00127 " <td align=\"right\" valign=\"top\">\n"
00128 " <table border=\"0\"><tr><td width=\"32\" height=\"32\" align=\"center\" valign=\"middle\">\n"
00129 " <img src=\"%1\">\n"
00130 " </td></tr></table>\n"
00131 " </td>\n"
00132 " </tr>\n"
00133 ).arg( iconPath );
00134
00135 tip += QString::fromLatin1(
00136 "</table>"
00137 );
00138
00139 return tip;
00140 }
00141
00142 void proxyDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
00143
00144 StatisticsProxyModel *mParent;
00145
00146 bool mToolTipEnabled;
00147 bool mExtraColumnsEnabled;
00148 };
00149
00150 void StatisticsProxyModel::Private::proxyDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
00151 {
00152 if ( mExtraColumnsEnabled )
00153 {
00154
00155
00156 QModelIndex parent = topLeft.parent();
00157 QModelIndex extraTopLeft = mParent->index( topLeft.row(), mParent->columnCount( parent ) - 1 - 3 , parent );
00158 QModelIndex extraBottomRight = mParent->index( bottomRight.row(), mParent->columnCount( parent ) -1, parent );
00159 mParent->disconnect( mParent, SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
00160 mParent, SLOT( proxyDataChanged( const QModelIndex&, const QModelIndex& ) ) );
00161 emit mParent->dataChanged( extraTopLeft, extraBottomRight );
00162
00163
00164
00165
00166 while ( parent.isValid() )
00167 {
00168 emit mParent->dataChanged( parent.sibling( parent.row(), mParent->columnCount( parent ) - 1 - 3 ),
00169 parent.sibling( parent.row(), mParent->columnCount( parent ) - 1 ) );
00170 parent = parent.parent();
00171 }
00172 mParent->connect( mParent, SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
00173 SLOT( proxyDataChanged( const QModelIndex&, const QModelIndex& ) ) );
00174 }
00175 }
00176
00177
00178 StatisticsProxyModel::StatisticsProxyModel( QObject *parent )
00179 : QSortFilterProxyModel( parent ),
00180 d( new Private( this ) )
00181 {
00182 connect( this, SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
00183 SLOT( proxyDataChanged( const QModelIndex&, const QModelIndex& ) ) );
00184 }
00185
00186 StatisticsProxyModel::~StatisticsProxyModel()
00187 {
00188 delete d;
00189 }
00190
00191 void StatisticsProxyModel::setToolTipEnabled( bool enable )
00192 {
00193 d->mToolTipEnabled = enable;
00194 }
00195
00196 bool StatisticsProxyModel::isToolTipEnabled() const
00197 {
00198 return d->mToolTipEnabled;
00199 }
00200
00201 void StatisticsProxyModel::setExtraColumnsEnabled( bool enable )
00202 {
00203 d->mExtraColumnsEnabled = enable;
00204 }
00205
00206 bool StatisticsProxyModel::isExtraColumnsEnabled() const
00207 {
00208 return d->mExtraColumnsEnabled;
00209 }
00210
00211 QModelIndex Akonadi::StatisticsProxyModel::index( int row, int column, const QModelIndex & parent ) const
00212 {
00213 if (!hasIndex(row, column, parent))
00214 return QModelIndex();
00215
00216
00217 int sourceColumn = column;
00218
00219 if ( column>=d->sourceColumnCount( parent ) ) {
00220 sourceColumn = 0;
00221 }
00222
00223 QModelIndex i = QSortFilterProxyModel::index( row, sourceColumn, parent );
00224 return createIndex( i.row(), column, i.internalPointer() );
00225 }
00226
00227 QVariant StatisticsProxyModel::data( const QModelIndex & index, int role) const
00228 {
00229 if (!sourceModel())
00230 return QVariant();
00231 if ( role == Qt::DisplayRole && index.column()>=d->sourceColumnCount( index.parent() ) ) {
00232 const QModelIndex sourceIndex = mapToSource( index.sibling( index.row(), 0 ) );
00233 Collection collection = sourceModel()->data( sourceIndex, EntityTreeModel::CollectionRole ).value<Collection>();
00234
00235 if ( collection.isValid() && collection.statistics().count()>=0 ) {
00236 if ( index.column() == d->sourceColumnCount( QModelIndex() )+2 ) {
00237 return KIO::convertSize( (KIO::filesize_t)( collection.statistics().size() ) );
00238 } else if ( index.column() == d->sourceColumnCount( QModelIndex() )+1 ) {
00239 return collection.statistics().count();
00240 } else if ( index.column() == d->sourceColumnCount( QModelIndex() ) ) {
00241 if ( collection.statistics().unreadCount() > 0 ) {
00242 return collection.statistics().unreadCount();
00243 } else {
00244 return QString();
00245 }
00246 } else {
00247 kWarning() << "We shouldn't get there for a column which is not total, unread or size.";
00248 return QVariant();
00249 }
00250 }
00251
00252 } else if ( role == Qt::TextAlignmentRole && index.column()>=d->sourceColumnCount( index.parent() ) ) {
00253 return Qt::AlignRight;
00254
00255 } else if ( role == Qt::ToolTipRole && d->mToolTipEnabled ) {
00256 const QModelIndex sourceIndex = mapToSource( index.sibling( index.row(), 0 ) );
00257 Collection collection
00258 = sourceModel()->data( sourceIndex,
00259 EntityTreeModel::CollectionRole ).value<Collection>();
00260
00261 if ( collection.isValid() && collection.statistics().count()>0 ) {
00262 return d->toolTipForCollection( index, collection );
00263 }
00264
00265 } else if ( role == Qt::DecorationRole && index.column() == 0 ) {
00266 const QModelIndex sourceIndex = mapToSource( index.sibling( index.row(), 0 ) );
00267 Collection collection = sourceModel()->data( sourceIndex, EntityTreeModel::CollectionRole ).value<Collection>();
00268
00269 if ( collection.isValid() )
00270 return KIcon( CollectionUtils::displayIconName( collection ) );
00271 else
00272 return QVariant();
00273 }
00274
00275 return QAbstractProxyModel::data( index, role );
00276 }
00277
00278 QVariant StatisticsProxyModel::headerData( int section, Qt::Orientation orientation, int role) const
00279 {
00280 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
00281 if ( section == d->sourceColumnCount( QModelIndex() ) + 2 ) {
00282 return i18nc( "collection size", "Size" );
00283 } else if ( section == d->sourceColumnCount( QModelIndex() ) + 1 ) {
00284 return i18nc( "number of entities in the collection", "Total" );
00285 } else if ( section == d->sourceColumnCount( QModelIndex() ) ) {
00286 return i18nc( "number of unread entities in the collection", "Unread" );
00287 }
00288 }
00289
00290 return QSortFilterProxyModel::headerData( section, orientation, role );
00291 }
00292
00293 Qt::ItemFlags StatisticsProxyModel::flags( const QModelIndex & index ) const
00294 {
00295 if ( index.column()>=d->sourceColumnCount( index.parent() ) ) {
00296 return QSortFilterProxyModel::flags( index.sibling( index.row(), 0 ) )
00297 & ( Qt::ItemIsSelectable | Qt::ItemIsDragEnabled
00298 | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled );
00299 }
00300
00301 return QSortFilterProxyModel::flags( index );
00302 }
00303
00304 int StatisticsProxyModel::columnCount( const QModelIndex & parent ) const
00305 {
00306 if ( sourceModel()==0 ) {
00307 return 0;
00308 } else {
00309 return d->sourceColumnCount( parent )
00310 + ( d->mExtraColumnsEnabled ? 3 : 0 );
00311 }
00312 }
00313
00314 QModelIndexList StatisticsProxyModel::match( const QModelIndex& start, int role, const QVariant& value,
00315 int hits, Qt::MatchFlags flags ) const
00316 {
00317 if ( role < Qt::UserRole )
00318 return QSortFilterProxyModel::match( start, role, value, hits, flags );
00319
00320 QModelIndexList list;
00321 QModelIndex proxyIndex;
00322 foreach ( const QModelIndex &idx, sourceModel()->match( mapToSource( start ), role, value, hits, flags ) ) {
00323 proxyIndex = mapFromSource( idx );
00324 if ( proxyIndex.isValid() )
00325 list << proxyIndex;
00326 }
00327
00328 return list;
00329 }
00330
00331
00332 #include "statisticsproxymodel.moc"
00333