20 #include "statisticsproxymodel.h"
22 #include "entitytreemodel.h"
23 #include "collectionutils_p.h"
25 #include <akonadi/collectionquotaattribute.h>
26 #include <akonadi/collectionstatistics.h>
27 #include <akonadi/entitydisplayattribute.h>
30 #include <kiconloader.h>
31 #include <klocalizedstring.h>
32 #include <kio/global.h>
34 #include <QApplication>
37 using namespace Akonadi;
42 class StatisticsProxyModel::Private
46 : mParent( parent ), mToolTipEnabled( false ), mExtraColumnsEnabled( true )
50 int sourceColumnCount(
const QModelIndex &parent )
52 return mParent->sourceModel()->columnCount( mParent->mapToSource( parent ) );
55 void getCountRecursive(
const QModelIndex &index, qint64 &totalSize )
const
62 totalSize += qMax( 0LL, statistics.
size() );
63 if ( index.model()->hasChildren( index ) ) {
64 const int rowCount = index.model()->rowCount( index );
65 for (
int row = 0; row < rowCount; row++ ) {
66 static const int column = 0;
67 getCountRecursive( index.model()->index( row, column, index ), totalSize );
73 QString toolTipForCollection(
const QModelIndex &index,
const Collection &collection )
75 QString bckColor = QApplication::palette().color( QPalette::ToolTipBase ).name();
76 QString txtColor = QApplication::palette().color( QPalette::ToolTipText ).name();
78 QString tip = QString::fromLatin1(
79 "<table width=\"100%\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\">\n"
81 const QString textDirection = ( QApplication::layoutDirection() == Qt::LeftToRight ) ? QLatin1String(
"left" ) : QLatin1String(
"right" );
82 tip += QString::fromLatin1(
84 " <td bgcolor=\"%1\" colspan=\"2\" align=\"%4\" valign=\"middle\">\n"
85 " <div style=\"color: %2; font-weight: bold;\">\n"
90 ).arg( txtColor ).arg( bckColor ).arg( index.data( Qt::DisplayRole ).toString() ).arg( textDirection );
92 tip += QString::fromLatin1(
94 " <td align=\"%1\" valign=\"top\">\n"
95 ).arg( textDirection );
98 tipInfo += QString::fromLatin1(
99 " <strong>%1</strong>: %2<br>\n"
100 " <strong>%3</strong>: %4<br><br>\n"
101 ).arg( i18n(
"Total Messages" ) ).arg( collection.
statistics().
count() )
109 if ( qAbs( percentage ) >= 0.01 ) {
110 QString percentStr = QString::number( percentage,
'f', 2 );
111 tipInfo += QString::fromLatin1(
112 " <strong>%1</strong>: %2%<br>\n"
113 ).arg( i18n(
"Quota" ) ).arg( percentStr );
119 tipInfo += QString::fromLatin1(
120 " <strong>%1</strong>: %2<br>\n"
121 ).arg( i18n(
"Storage Size" ) ).arg( KIO::convertSize( (KIO::filesize_t)( currentFolderSize ) ) );
123 qint64 totalSize = 0;
124 getCountRecursive( index, totalSize );
125 totalSize -= currentFolderSize;
126 if (totalSize > 0 ) {
127 tipInfo += QString::fromLatin1(
128 "<strong>%1</strong>: %2<br>"
129 ).arg( i18n(
"Subfolder Storage Size") ).arg( KIO::convertSize( (KIO::filesize_t)( totalSize ) ) );
132 QString iconName = CollectionUtils::defaultIconName( collection );
142 int iconSizes[] = { 32, 22 };
143 int icon_size_found = 32;
147 for (
int i = 0; i < 2; i++ ) {
148 iconPath = KIconLoader::global()->iconPath( iconName, -iconSizes[ i ],
true );
149 if ( !iconPath.isEmpty() ) {
150 icon_size_found = iconSizes[ i ];
155 if ( iconPath.isEmpty() ) {
156 iconPath = KIconLoader::global()->iconPath( QLatin1String(
"folder" ), -32,
false );
159 QString tipIcon = QString::fromLatin1(
160 " <table border=\"0\"><tr><td width=\"32\" height=\"32\" align=\"center\" valign=\"middle\">\n"
161 " <img src=\"%1\" width=\"%2\" height=\"32\">\n"
162 " </td></tr></table>\n"
164 ).arg( iconPath ).arg( icon_size_found ) ;
166 if ( QApplication::layoutDirection() == Qt::LeftToRight )
168 tip += tipInfo + QString::fromLatin1(
"</td><td align=\"%3\" valign=\"top\">" ).arg( textDirection ) + tipIcon;
172 tip += tipIcon + QString::fromLatin1(
"</td><td align=\"%3\" valign=\"top\">" ).arg( textDirection ) + tipInfo;
175 tip += QString::fromLatin1(
183 void proxyDataChanged(
const QModelIndex &topLeft,
const QModelIndex &bottomRight);
185 void sourceLayoutAboutToBeChanged();
186 void sourceLayoutChanged();
188 QVector<QModelIndex> m_nonPersistent;
189 QVector<QModelIndex> m_nonPersistentFirstColumn;
190 QVector<QPersistentModelIndex> m_persistent;
191 QVector<QPersistentModelIndex> m_persistentFirstColumn;
195 bool mToolTipEnabled;
196 bool mExtraColumnsEnabled;
199 void StatisticsProxyModel::Private::proxyDataChanged(
const QModelIndex& topLeft,
const QModelIndex& bottomRight)
201 if ( mExtraColumnsEnabled )
205 QModelIndex parent = topLeft.parent();
206 int parentColumnCount = mParent->columnCount( parent );
207 QModelIndex extraTopLeft = mParent->index( topLeft.row(), parentColumnCount - 1 - 3 , parent );
208 QModelIndex extraBottomRight = mParent->index( bottomRight.row(), parentColumnCount -1, parent );
209 mParent->disconnect( mParent, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
210 mParent, SLOT(proxyDataChanged(QModelIndex,QModelIndex)) );
211 emit mParent->dataChanged( extraTopLeft, extraBottomRight );
216 while ( parent.isValid() )
218 emit mParent->dataChanged( parent.sibling( parent.row(), parentColumnCount - 1 - 3 ),
219 parent.sibling( parent.row(), parentColumnCount - 1 ) );
220 parent = parent.parent();
221 parentColumnCount = mParent->columnCount( parent );
223 mParent->connect( mParent, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
224 SLOT(proxyDataChanged(QModelIndex,QModelIndex)) );
228 void StatisticsProxyModel::Private::sourceLayoutAboutToBeChanged()
230 QModelIndexList persistent = mParent->persistentIndexList();
231 const int columnCount = mParent->sourceModel()->columnCount();
232 foreach(
const QModelIndex &idx, persistent ) {
233 if ( idx.column() >= columnCount ) {
234 m_nonPersistent.push_back( idx );
235 m_persistent.push_back( idx );
236 const QModelIndex firstColumn = idx.sibling( 0, idx.column() );
237 m_nonPersistentFirstColumn.push_back( firstColumn );
238 m_persistentFirstColumn.push_back( firstColumn );
243 void StatisticsProxyModel::Private::sourceLayoutChanged()
245 QModelIndexList oldList;
246 QModelIndexList newList;
248 const int columnCount = mParent->sourceModel()->columnCount();
250 for (
int i = 0; i < m_persistent.size(); ++i ) {
251 const QModelIndex persistentIdx = m_persistent.at( i );
252 const QModelIndex nonPersistentIdx = m_nonPersistent.at( i );
253 if ( m_persistentFirstColumn.at( i ) != m_nonPersistentFirstColumn.at( i ) && persistentIdx.column() >= columnCount ) {
254 oldList.append( nonPersistentIdx );
255 newList.append( persistentIdx );
258 mParent->changePersistentIndexList( oldList, newList );
261 void StatisticsProxyModel::setSourceModel(QAbstractItemModel* sourceModel)
265 disconnect(
this, SIGNAL(layoutChanged()),
this, SLOT(sourceLayoutChanged()));
266 connect(
this, SIGNAL(layoutChanged()), SLOT(sourceLayoutChanged()));
267 QSortFilterProxyModel::setSourceModel(sourceModel);
270 disconnect(
this, SIGNAL(layoutAboutToBeChanged()),
this, SLOT(sourceLayoutAboutToBeChanged()));
271 connect(
this, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged()));
274 void StatisticsProxyModel::connectNotify(
const char *signal)
276 static bool ignore =
false;
277 if (ignore || QLatin1String(signal) == SIGNAL(layoutAboutToBeChanged()))
278 return QSortFilterProxyModel::connectNotify(signal);
280 disconnect(
this, SIGNAL(layoutAboutToBeChanged()),
this, SLOT(sourceLayoutAboutToBeChanged()));
281 connect(
this, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged()));
283 QSortFilterProxyModel::connectNotify(signal);
287 : QSortFilterProxyModel( parent ),
288 d( new Private( this ) )
290 connect(
this, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
291 SLOT(proxyDataChanged(QModelIndex,QModelIndex)) );
301 d->mToolTipEnabled = enable;
306 return d->mToolTipEnabled;
311 d->mExtraColumnsEnabled = enable;
316 return d->mExtraColumnsEnabled;
319 QModelIndex Akonadi::StatisticsProxyModel::index(
int row,
int column,
const QModelIndex & parent )
const
321 if (!hasIndex(row, column, parent))
322 return QModelIndex();
324 int sourceColumn = column;
326 if ( column>=d->sourceColumnCount( parent ) ) {
330 QModelIndex i = QSortFilterProxyModel::index( row, sourceColumn, parent );
331 return createIndex( i.row(), column, i.internalPointer() );
334 QVariant StatisticsProxyModel::data(
const QModelIndex & index,
int role)
const
338 if ( role == Qt::DisplayRole && index.column()>=d->sourceColumnCount( index.parent() ) ) {
339 const QModelIndex sourceIndex = mapToSource( index.sibling( index.row(), 0 ) );
343 if ( index.column() == d->sourceColumnCount( QModelIndex() )+2 ) {
344 return KIO::convertSize( (KIO::filesize_t)( collection.
statistics().
size() ) );
345 }
else if ( index.column() == d->sourceColumnCount( QModelIndex() )+1 ) {
347 }
else if ( index.column() == d->sourceColumnCount( QModelIndex() ) ) {
354 kWarning() <<
"We shouldn't get there for a column which is not total, unread or size.";
359 }
else if ( role == Qt::TextAlignmentRole && index.column()>=d->sourceColumnCount( index.parent() ) ) {
360 return Qt::AlignRight;
362 }
else if ( role == Qt::ToolTipRole && d->mToolTipEnabled ) {
363 const QModelIndex sourceIndex = mapToSource( index.sibling( index.row(), 0 ) );
365 = sourceModel()->data( sourceIndex,
369 return d->toolTipForCollection( index, collection );
372 }
else if ( role == Qt::DecorationRole && index.column() == 0 ) {
373 const QModelIndex sourceIndex = mapToSource( index.sibling( index.row(), 0 ) );
377 return KIcon( CollectionUtils::displayIconName( collection ) );
382 return QAbstractProxyModel::data( index, role );
385 QVariant StatisticsProxyModel::headerData(
int section, Qt::Orientation orientation,
int role)
const
387 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
388 if ( section == d->sourceColumnCount( QModelIndex() ) + 2 ) {
389 return i18nc(
"collection size",
"Size" );
390 }
else if ( section == d->sourceColumnCount( QModelIndex() ) + 1 ) {
391 return i18nc(
"number of entities in the collection",
"Total" );
392 }
else if ( section == d->sourceColumnCount( QModelIndex() ) ) {
393 return i18nc(
"number of unread entities in the collection",
"Unread" );
397 return QSortFilterProxyModel::headerData( section, orientation, role );
400 Qt::ItemFlags StatisticsProxyModel::flags(
const QModelIndex & index )
const
402 if ( index.column()>=d->sourceColumnCount( index.parent() ) ) {
403 return QSortFilterProxyModel::flags( index.sibling( index.row(), 0 ) )
404 & ( Qt::ItemIsSelectable | Qt::ItemIsDragEnabled
405 | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled );
408 return QSortFilterProxyModel::flags( index );
411 int StatisticsProxyModel::columnCount(
const QModelIndex & parent )
const
413 if ( sourceModel()==0 ) {
416 return d->sourceColumnCount( parent )
417 + ( d->mExtraColumnsEnabled ? 3 : 0 );
421 QModelIndexList StatisticsProxyModel::match(
const QModelIndex& start,
int role,
const QVariant& value,
422 int hits, Qt::MatchFlags flags )
const
424 if ( role < Qt::UserRole )
425 return QSortFilterProxyModel::match( start, role, value, hits, flags );
427 QModelIndexList list;
428 QModelIndex proxyIndex;
429 foreach (
const QModelIndex &idx, sourceModel()->match( mapToSource( start ), role, value, hits, flags ) ) {
430 proxyIndex = mapFromSource( idx );
431 if ( proxyIndex.isValid() )
438 #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...