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>
42class StatisticsProxyModel::Private
47 , mToolTipEnabled(false)
48 , mExtraColumnsEnabled(true)
52 int sourceColumnCount(
const QModelIndex &parent)
54 return mParent->sourceModel()->columnCount(mParent->mapToSource(parent));
57 void getCountRecursive(
const QModelIndex &index, qint64 &totalSize)
const
62 if (collection.isValid()) {
64 totalSize += qMax(0LL, statistics.
size());
65 if (index.model()->hasChildren(index)) {
66 const int rowCount = index.model()->rowCount(index);
67 for (
int row = 0; row < rowCount; row++) {
68 static const int column = 0;
69 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);
94 tip += QString::fromLatin1(
96 " <td align=\"%1\" valign=\"top\">\n"
100 tipInfo += QString::fromLatin1(
101 " <strong>%1</strong>: %2<br>\n"
102 " <strong>%3</strong>: %4<br><br>\n"
103 ).arg(i18n(
"Total Messages")).arg(collection.statistics().count())
104 .arg(i18n(
"Unread Messages")).arg(collection.statistics().unreadCount());
111 if (qAbs(percentage) >= 0.01) {
112 QString percentStr = QString::number(percentage,
'f', 2);
113 tipInfo += QString::fromLatin1(
114 " <strong>%1</strong>: %2%<br>\n"
115 ).arg(i18n(
"Quota")).arg(percentStr);
120 qint64 currentFolderSize(collection.statistics().size());
121 tipInfo += QString::fromLatin1(
122 " <strong>%1</strong>: %2<br>\n"
123 ).arg(i18n(
"Storage Size")).arg(KIO::convertSize((KIO::filesize_t)(currentFolderSize)));
125 qint64 totalSize = 0;
126 getCountRecursive(index, totalSize);
127 totalSize -= currentFolderSize;
129 tipInfo += QString::fromLatin1(
130 "<strong>%1</strong>: %2<br>"
131 ).arg(i18n(
"Subfolder Storage Size")).arg(KIO::convertSize((KIO::filesize_t)(totalSize)));
134 QString iconName = CollectionUtils::defaultIconName(collection);
144 int iconSizes[] = { 32, 22 };
145 int icon_size_found = 32;
149 for (
int i = 0; i < 2; i++) {
150 iconPath = KIconLoader::global()->iconPath(iconName, -iconSizes[i],
true);
151 if (!iconPath.isEmpty()) {
152 icon_size_found = iconSizes[i];
157 if (iconPath.isEmpty()) {
158 iconPath = KIconLoader::global()->iconPath(QLatin1String(
"folder"), -32,
false);
161 QString tipIcon = QString::fromLatin1(
162 " <table border=\"0\"><tr><td width=\"32\" height=\"32\" align=\"center\" valign=\"middle\">\n"
163 " <img src=\"%1\" width=\"%2\" height=\"32\">\n"
164 " </td></tr></table>\n"
166 ).arg(iconPath).arg(icon_size_found) ;
168 if (QApplication::layoutDirection() == Qt::LeftToRight) {
169 tip += tipInfo + QString::fromLatin1(
"</td><td align=\"%3\" valign=\"top\">").arg(textDirection) + tipIcon;
171 tip += tipIcon + QString::fromLatin1(
"</td><td align=\"%3\" valign=\"top\">").arg(textDirection) + tipInfo;
174 tip += QString::fromLatin1(
182 void proxyDataChanged(
const QModelIndex &topLeft,
const QModelIndex &bottomRight);
184 void sourceLayoutAboutToBeChanged();
185 void sourceLayoutChanged();
187 QVector<QModelIndex> m_nonPersistent;
188 QVector<QModelIndex> m_nonPersistentFirstColumn;
189 QVector<QPersistentModelIndex> m_persistent;
190 QVector<QPersistentModelIndex> m_persistentFirstColumn;
194 bool mToolTipEnabled;
195 bool mExtraColumnsEnabled;
198void StatisticsProxyModel::Private::proxyDataChanged(
const QModelIndex &topLeft,
const QModelIndex &bottomRight)
200 if (mExtraColumnsEnabled) {
203 QModelIndex parent = topLeft.parent();
204 int parentColumnCount = mParent->columnCount(parent);
205 QModelIndex extraTopLeft = mParent->index(topLeft.row(), parentColumnCount - 1 - 3 , parent);
206 QModelIndex extraBottomRight = mParent->index(bottomRight.row(), parentColumnCount - 1, parent);
207 mParent->disconnect(mParent, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
208 mParent, SLOT(proxyDataChanged(QModelIndex,QModelIndex)));
209 emit mParent->dataChanged(extraTopLeft, extraBottomRight);
214 while (parent.isValid()) {
215 emit mParent->dataChanged(parent.sibling(parent.row(), parentColumnCount - 1 - 3),
216 parent.sibling(parent.row(), parentColumnCount - 1));
217 parent = parent.parent();
218 parentColumnCount = mParent->columnCount(parent);
220 mParent->connect(mParent, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
221 SLOT(proxyDataChanged(QModelIndex,QModelIndex)));
225void StatisticsProxyModel::Private::sourceLayoutAboutToBeChanged()
227 QModelIndexList persistent = mParent->persistentIndexList();
228 const int columnCount = mParent->sourceModel()->columnCount();
229 foreach (
const QModelIndex &idx, persistent) {
230 if (idx.column() >= columnCount) {
231 m_nonPersistent.push_back(idx);
232 m_persistent.push_back(idx);
233 const QModelIndex firstColumn = idx.sibling(0, idx.column());
234 m_nonPersistentFirstColumn.push_back(firstColumn);
235 m_persistentFirstColumn.push_back(firstColumn);
240void StatisticsProxyModel::Private::sourceLayoutChanged()
242 QModelIndexList oldList;
243 QModelIndexList newList;
245 const int columnCount = mParent->sourceModel()->columnCount();
247 for (
int i = 0; i < m_persistent.size(); ++i) {
248 const QModelIndex persistentIdx = m_persistent.at(i);
249 const QModelIndex nonPersistentIdx = m_nonPersistent.at(i);
250 if (m_persistentFirstColumn.at(i) != m_nonPersistentFirstColumn.at(i) && persistentIdx.column() >= columnCount) {
251 oldList.append(nonPersistentIdx);
252 newList.append(persistentIdx);
255 mParent->changePersistentIndexList(oldList, newList);
258void StatisticsProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
262 disconnect(
this, SIGNAL(layoutChanged()),
this, SLOT(sourceLayoutChanged()));
263 connect(
this, SIGNAL(layoutChanged()), SLOT(sourceLayoutChanged()));
264 QSortFilterProxyModel::setSourceModel(sourceModel);
267 disconnect(
this, SIGNAL(layoutAboutToBeChanged()),
this, SLOT(sourceLayoutAboutToBeChanged()));
268 connect(
this, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged()));
271void StatisticsProxyModel::connectNotify(
const char *signal)
273 static bool ignore =
false;
274 if (ignore || QLatin1String(signal) == SIGNAL(layoutAboutToBeChanged())) {
275 return QSortFilterProxyModel::connectNotify(signal);
278 disconnect(
this, SIGNAL(layoutAboutToBeChanged()),
this, SLOT(sourceLayoutAboutToBeChanged()));
279 connect(
this, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged()));
281 QSortFilterProxyModel::connectNotify(signal);
285 : QSortFilterProxyModel(parent)
286 , d(new Private(this))
288 connect(
this, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
289 SLOT(proxyDataChanged(QModelIndex,QModelIndex)));
299 d->mToolTipEnabled = enable;
304 return d->mToolTipEnabled;
309 d->mExtraColumnsEnabled = enable;
314 return d->mExtraColumnsEnabled;
317QModelIndex Akonadi::StatisticsProxyModel::index(
int row,
int column,
const QModelIndex &parent)
const
319 if (!hasIndex(row, column, parent)) {
320 return QModelIndex();
323 int sourceColumn = column;
325 if (column >= d->sourceColumnCount(parent)) {
329 QModelIndex i = QSortFilterProxyModel::index(row, sourceColumn, parent);
330 return createIndex(i.row(), column, i.internalPointer());
333QVariant StatisticsProxyModel::data(
const QModelIndex &index,
int role)
const
335 if (!sourceModel()) {
338 if (role == Qt::DisplayRole && index.column() >= d->sourceColumnCount(index.parent())) {
339 const QModelIndex sourceIndex = mapToSource(index.sibling(index.row(), 0));
342 if (collection.isValid() && collection.statistics().count() >= 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) {
346 return collection.statistics().count();
347 }
else if (index.column() == d->sourceColumnCount(QModelIndex())) {
348 if (collection.statistics().unreadCount() > 0) {
349 return collection.statistics().unreadCount();
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));
366 if (collection.isValid() && collection.statistics().count() > 0) {
367 return d->toolTipForCollection(index, collection);
370 }
else if (role == Qt::DecorationRole && index.column() == 0) {
371 const QModelIndex sourceIndex = mapToSource(index.sibling(index.row(), 0));
374 if (collection.isValid()) {
375 return KIcon(CollectionUtils::displayIconName(collection));
381 return QAbstractProxyModel::data(index, role);
384QVariant StatisticsProxyModel::headerData(
int section, Qt::Orientation orientation,
int role)
const
386 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
387 if (section == d->sourceColumnCount(QModelIndex()) + 2) {
388 return i18nc(
"collection size",
"Size");
389 }
else if (section == d->sourceColumnCount(QModelIndex()) + 1) {
390 return i18nc(
"number of entities in the collection",
"Total");
391 }
else if (section == d->sourceColumnCount(QModelIndex())) {
392 return i18nc(
"number of unread entities in the collection",
"Unread");
396 return QSortFilterProxyModel::headerData(section, orientation, role);
399Qt::ItemFlags StatisticsProxyModel::flags(
const QModelIndex &index)
const
401 if (index.column() >= d->sourceColumnCount(index.parent())) {
402 return QSortFilterProxyModel::flags(index.sibling(index.row(), 0))
403 & (Qt::ItemIsSelectable | Qt::ItemIsDragEnabled
404 | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled);
407 return QSortFilterProxyModel::flags(index);
410int StatisticsProxyModel::columnCount(
const QModelIndex &parent)
const
412 if (sourceModel() == 0) {
415 return d->sourceColumnCount(parent)
416 + (d->mExtraColumnsEnabled ? 3 : 0);
420QModelIndexList StatisticsProxyModel::match(
const QModelIndex &start,
int role,
const QVariant &value,
421 int hits, Qt::MatchFlags flags)
const
423 if (role < Qt::UserRole) {
424 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()) {
439#include "moc_statisticsproxymodel.cpp"
Attribute that provides quota information for a collection.
qint64 currentValue() const
Returns the current quota value in bytes.
qint64 maximumValue() const
Returns the maximum quota value in bytes.
Provides statistics information of a Collection.
qint64 size() const
Returns the total size of the items in this collection or -1 if this information is not available.
Represents a collection of PIM items.
Attribute that stores the properties that are used to display an entity.
QString activeIconName() const
Returns the icon name of an active item.
QString iconName() const
Returns the icon name of the icon returned by icon().
@ CollectionRole
The collection.
A proxy model that exposes collection statistics through extra columns.
virtual ~StatisticsProxyModel()
Destroys the statistics proxy model.
void setExtraColumnsEnabled(bool enable)
StatisticsProxyModel(QObject *parent=0)
Creates a new statistics proxy model.
bool isToolTipEnabled() const
Return true if we display tooltips, otherwise false.
bool isExtraColumnsEnabled() const
Return true if we display extra statistics columns, otherwise false.
void setToolTipEnabled(bool enable)
FreeBusyManager::Singleton.