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>
32 #include <klocalizedstring.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"
QString activeIconName() const
Returns the icon name of an active item.
qint64 count() const
Returns the number of items in this collection or -1 if this information is not available.
QString iconName() const
Returns the icon name of the icon returned by icon().
Provides statistics information of a Collection.
StatisticsProxyModel(QObject *parent=0)
Creates a new statistics proxy model.
bool isExtraColumnsEnabled() const
Return true if we display extra statistics columns, otherwise false.
Represents a collection of PIM items.
Attribute * attribute(const QByteArray &name) const
Returns the attribute of the given type name if available, 0 otherwise.
qint64 currentValue() const
Returns the current quota value in bytes.
A proxy model that exposes collection statistics through extra columns.
void setToolTipEnabled(bool enable)
qint64 maximumValue() const
Returns the maximum quota value in bytes.
virtual ~StatisticsProxyModel()
Destroys the statistics proxy model.
bool isToolTipEnabled() const
Return true if we display tooltips, otherwise false.
bool hasAttribute(const QByteArray &name) const
Returns true if the entity has an attribute of the given type name, false otherwise.
qint64 unreadCount() const
Returns the number of unread items in this collection or -1 if this information is not available...
bool isValid() const
Returns whether the entity is valid.
void setExtraColumnsEnabled(bool enable)
Attribute that provides quota information for a collection.
CollectionStatistics statistics() const
Returns the collection statistics of the collection.
Attribute that stores the properties that are used to display an entity.
qint64 size() const
Returns the total size of the items in this collection or -1 if this information is not available...