21 #include "statisticsproxymodel.h"
23 #include "entitytreemodel.h"
24 #include "collectionutils_p.h"
26 #include <akonadi/collectionquotaattribute.h>
27 #include <akonadi/collectionstatistics.h>
28 #include <akonadi/entitydisplayattribute.h>
31 #include <kiconloader.h>
33 #include <kio/global.h>
35 #include <QApplication>
38 using namespace Akonadi;
43 class StatisticsProxyModel::Private
47 : mParent( parent ), mToolTipEnabled( false ), mExtraColumnsEnabled( true )
51 int sourceColumnCount(
const QModelIndex &parent )
53 return mParent->sourceModel()->columnCount( mParent->mapToSource( parent ) );
56 void getCountRecursive(
const QModelIndex &index, qint64 &totalSize )
const
63 totalSize += qMax( 0LL, statistics.
size() );
64 if ( index.model()->hasChildren( index ) ) {
65 const int rowCount = index.model()->rowCount( index );
66 for (
int row = 0; row < rowCount; row++ ) {
67 static const int column = 0;
68 getCountRecursive( index.model()->index( row, column, index ), totalSize );
75 QString toolTipForCollection(
const QModelIndex &index,
const Collection &collection )
77 QString bckColor = QApplication::palette().color( QPalette::ToolTipBase ).name();
78 QString txtColor = QApplication::palette().color( QPalette::ToolTipText ).name();
80 QString tip = QString::fromLatin1(
81 "<table width=\"100%\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\">\n"
83 const QString textDirection = ( QApplication::layoutDirection() == Qt::LeftToRight ) ? QLatin1String(
"left" ) : QLatin1String(
"right" );
84 tip += QString::fromLatin1(
86 " <td bgcolor=\"%1\" colspan=\"2\" align=\"%4\" valign=\"middle\">\n"
87 " <div style=\"color: %2; font-weight: bold;\">\n"
92 ).arg( txtColor ).arg( bckColor ).arg( index.data( Qt::DisplayRole ).toString() ).arg( textDirection );
95 tip += QString::fromLatin1(
97 " <td align=\"%1\" valign=\"top\">\n"
98 ).arg( textDirection );
101 tipInfo += QString::fromLatin1(
102 " <strong>%1</strong>: %2<br>\n"
103 " <strong>%3</strong>: %4<br><br>\n"
104 ).arg( i18n(
"Total Messages" ) ).arg( collection.
statistics().
count() )
112 if ( qAbs( percentage ) >= 0.01 ) {
113 QString percentStr = QString::number( percentage,
'f', 2 );
114 tipInfo += QString::fromLatin1(
115 " <strong>%1</strong>: %2%<br>\n"
116 ).arg( i18n(
"Quota" ) ).arg( percentStr );
122 tipInfo += QString::fromLatin1(
123 " <strong>%1</strong>: %2<br>\n"
124 ).arg( i18n(
"Storage Size" ) ).arg( KIO::convertSize( (KIO::filesize_t)( currentFolderSize ) ) );
127 qint64 totalSize = 0;
128 getCountRecursive( index, totalSize );
129 totalSize -= currentFolderSize;
130 if (totalSize > 0 ) {
131 tipInfo += QString::fromLatin1(
132 "<strong>%1</strong>: %2<br>"
133 ).arg( i18n(
"Subfolder Storage Size") ).arg( KIO::convertSize( (KIO::filesize_t)( totalSize ) ) );
137 QString iconName = CollectionUtils::defaultIconName( collection );
148 int iconSizes[] = { 32, 22 };
149 int icon_size_found = 32;
153 for (
int i = 0; i < 2; i++ ) {
154 iconPath = KIconLoader::global()->iconPath( iconName, -iconSizes[ i ],
true );
155 if ( !iconPath.isEmpty() ) {
156 icon_size_found = iconSizes[ i ];
161 if ( iconPath.isEmpty() ) {
162 iconPath = KIconLoader::global()->iconPath( QLatin1String(
"folder" ), -32,
false );
165 QString tipIcon = QString::fromLatin1(
166 " <table border=\"0\"><tr><td width=\"32\" height=\"32\" align=\"center\" valign=\"middle\">\n"
167 " <img src=\"%1\" width=\"%2\" height=\"32\">\n"
168 " </td></tr></table>\n"
170 ).arg( iconPath ).arg( icon_size_found ) ;
172 if ( QApplication::layoutDirection() == Qt::LeftToRight )
174 tip += tipInfo + QString::fromLatin1(
"</td><td align=\"%3\" valign=\"top\">" ).arg( textDirection ) + tipIcon;
178 tip += tipIcon + QString::fromLatin1(
"</td><td align=\"%3\" valign=\"top\">" ).arg( textDirection ) + tipInfo;
182 tip += QString::fromLatin1(
190 void proxyDataChanged(
const QModelIndex &topLeft,
const QModelIndex &bottomRight);
192 void sourceLayoutAboutToBeChanged();
193 void sourceLayoutChanged();
195 QVector<QModelIndex> m_nonPersistent;
196 QVector<QModelIndex> m_nonPersistentFirstColumn;
197 QVector<QPersistentModelIndex> m_persistent;
198 QVector<QPersistentModelIndex> m_persistentFirstColumn;
202 bool mToolTipEnabled;
203 bool mExtraColumnsEnabled;
206 void StatisticsProxyModel::Private::proxyDataChanged(
const QModelIndex& topLeft,
const QModelIndex& bottomRight)
208 if ( mExtraColumnsEnabled )
212 QModelIndex parent = topLeft.parent();
213 int parentColumnCount = mParent->columnCount( parent );
214 QModelIndex extraTopLeft = mParent->index( topLeft.row(), parentColumnCount - 1 - 3 , parent );
215 QModelIndex extraBottomRight = mParent->index( bottomRight.row(), parentColumnCount -1, parent );
216 mParent->disconnect( mParent, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
217 mParent, SLOT(proxyDataChanged(QModelIndex,QModelIndex)) );
218 emit mParent->dataChanged( extraTopLeft, extraBottomRight );
223 while ( parent.isValid() )
225 emit mParent->dataChanged( parent.sibling( parent.row(), parentColumnCount - 1 - 3 ),
226 parent.sibling( parent.row(), parentColumnCount - 1 ) );
227 parent = parent.parent();
228 parentColumnCount = mParent->columnCount( parent );
230 mParent->connect( mParent, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
231 SLOT(proxyDataChanged(QModelIndex,QModelIndex)) );
235 void StatisticsProxyModel::Private::sourceLayoutAboutToBeChanged()
237 QModelIndexList persistent = mParent->persistentIndexList();
238 const int columnCount = mParent->sourceModel()->columnCount();
239 foreach(
const QModelIndex &idx, persistent ) {
240 if ( idx.column() >= columnCount ) {
241 m_nonPersistent.push_back( idx );
242 m_persistent.push_back( idx );
243 const QModelIndex firstColumn = idx.sibling( 0, idx.column() );
244 m_nonPersistentFirstColumn.push_back( firstColumn );
245 m_persistentFirstColumn.push_back( firstColumn );
250 void StatisticsProxyModel::Private::sourceLayoutChanged()
252 QModelIndexList oldList;
253 QModelIndexList newList;
255 const int columnCount = mParent->sourceModel()->columnCount();
257 for(
int i = 0; i < m_persistent.size(); ++i ) {
258 const QModelIndex persistentIdx = m_persistent.at( i );
259 const QModelIndex nonPersistentIdx = m_nonPersistent.at( i );
260 if ( m_persistentFirstColumn.at( i ) != m_nonPersistentFirstColumn.at( i ) && persistentIdx.column() >= columnCount ) {
261 oldList.append( nonPersistentIdx );
262 newList.append( persistentIdx );
265 mParent->changePersistentIndexList( oldList, newList );
268 void StatisticsProxyModel::setSourceModel(QAbstractItemModel* sourceModel)
272 disconnect(
this, SIGNAL(layoutChanged()),
this, SLOT(sourceLayoutChanged()));
273 connect(
this, SIGNAL(layoutChanged()), SLOT(sourceLayoutChanged()));
274 QSortFilterProxyModel::setSourceModel(sourceModel);
277 disconnect(
this, SIGNAL(layoutAboutToBeChanged()),
this, SLOT(sourceLayoutAboutToBeChanged()));
278 connect(
this, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged()));
281 void StatisticsProxyModel::connectNotify(
const char *signal)
283 static bool ignore =
false;
284 if (ignore || QLatin1String(signal) == SIGNAL(layoutAboutToBeChanged()))
285 return QSortFilterProxyModel::connectNotify(signal);
287 disconnect(
this, SIGNAL(layoutAboutToBeChanged()),
this, SLOT(sourceLayoutAboutToBeChanged()));
288 connect(
this, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged()));
290 QSortFilterProxyModel::connectNotify(signal);
295 : QSortFilterProxyModel( parent ),
296 d( new Private( this ) )
298 connect(
this, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
299 SLOT(proxyDataChanged(QModelIndex,QModelIndex)) );
309 d->mToolTipEnabled = enable;
314 return d->mToolTipEnabled;
319 d->mExtraColumnsEnabled = enable;
324 return d->mExtraColumnsEnabled;
327 QModelIndex Akonadi::StatisticsProxyModel::index(
int row,
int column,
const QModelIndex & parent )
const
329 if (!hasIndex(row, column, parent))
330 return QModelIndex();
333 int sourceColumn = column;
335 if ( column>=d->sourceColumnCount( parent ) ) {
339 QModelIndex i = QSortFilterProxyModel::index( row, sourceColumn, parent );
340 return createIndex( i.row(), column, i.internalPointer() );
343 QVariant StatisticsProxyModel::data(
const QModelIndex & index,
int role)
const
347 if ( role == Qt::DisplayRole && index.column()>=d->sourceColumnCount( index.parent() ) ) {
348 const QModelIndex sourceIndex = mapToSource( index.sibling( index.row(), 0 ) );
352 if ( index.column() == d->sourceColumnCount( QModelIndex() )+2 ) {
353 return KIO::convertSize( (KIO::filesize_t)( collection.
statistics().
size() ) );
354 }
else if ( index.column() == d->sourceColumnCount( QModelIndex() )+1 ) {
356 }
else if ( index.column() == d->sourceColumnCount( QModelIndex() ) ) {
363 kWarning() <<
"We shouldn't get there for a column which is not total, unread or size.";
368 }
else if ( role == Qt::TextAlignmentRole && index.column()>=d->sourceColumnCount( index.parent() ) ) {
369 return Qt::AlignRight;
371 }
else if ( role == Qt::ToolTipRole && d->mToolTipEnabled ) {
372 const QModelIndex sourceIndex = mapToSource( index.sibling( index.row(), 0 ) );
374 = sourceModel()->data( sourceIndex,
378 return d->toolTipForCollection( index, collection );
381 }
else if ( role == Qt::DecorationRole && index.column() == 0 ) {
382 const QModelIndex sourceIndex = mapToSource( index.sibling( index.row(), 0 ) );
386 return KIcon( CollectionUtils::displayIconName( collection ) );
391 return QAbstractProxyModel::data( index, role );
394 QVariant StatisticsProxyModel::headerData(
int section, Qt::Orientation orientation,
int role)
const
396 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
397 if ( section == d->sourceColumnCount( QModelIndex() ) + 2 ) {
398 return i18nc(
"collection size",
"Size" );
399 }
else if ( section == d->sourceColumnCount( QModelIndex() ) + 1 ) {
400 return i18nc(
"number of entities in the collection",
"Total" );
401 }
else if ( section == d->sourceColumnCount( QModelIndex() ) ) {
402 return i18nc(
"number of unread entities in the collection",
"Unread" );
406 return QSortFilterProxyModel::headerData( section, orientation, role );
409 Qt::ItemFlags StatisticsProxyModel::flags(
const QModelIndex & index )
const
411 if ( index.column()>=d->sourceColumnCount( index.parent() ) ) {
412 return QSortFilterProxyModel::flags( index.sibling( index.row(), 0 ) )
413 & ( Qt::ItemIsSelectable | Qt::ItemIsDragEnabled
414 | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled );
417 return QSortFilterProxyModel::flags( index );
420 int StatisticsProxyModel::columnCount(
const QModelIndex & parent )
const
422 if ( sourceModel()==0 ) {
425 return d->sourceColumnCount( parent )
426 + ( d->mExtraColumnsEnabled ? 3 : 0 );
430 QModelIndexList StatisticsProxyModel::match(
const QModelIndex& start,
int role,
const QVariant& value,
431 int hits, Qt::MatchFlags flags )
const
433 if ( role < Qt::UserRole )
434 return QSortFilterProxyModel::match( start, role, value, hits, flags );
436 QModelIndexList list;
437 QModelIndex proxyIndex;
438 foreach (
const QModelIndex &idx, sourceModel()->match( mapToSource( start ), role, value, hits, flags ) ) {
439 proxyIndex = mapFromSource( idx );
440 if ( proxyIndex.isValid() )
448 #include "moc_statisticsproxymodel.cpp"