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>
42 class 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
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"
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);
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;
198 void 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)));
225 void 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);
240 void 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);
258 void 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()));
271 void 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;
317 QModelIndex 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());
333 QVariant 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));
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));
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));
375 return KIcon(CollectionUtils::displayIconName(collection));
381 return QAbstractProxyModel::data(index, role);
384 QVariant 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);
399 Qt::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);
410 int StatisticsProxyModel::columnCount(
const QModelIndex &parent)
const
412 if (sourceModel() == 0) {
415 return d->sourceColumnCount(parent)
416 + (d->mExtraColumnsEnabled ? 3 : 0);
420 QModelIndexList 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"
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.
FreeBusyManager::Singleton.
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...