-/**
+/*
* This file is part of the KDE project
- * Copyright (C) 2007 Rafael Fernández López <ereslibre@gmail.com>
+ * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
#include "dolphincategorydrawer.h"
+#include <config-nepomuk.h>
+
#include <QPainter>
#include <QFile>
#include <QDir>
+#include <QApplication>
+#include <QStyleOption>
+
+#ifdef HAVE_NEPOMUK
+#include <nepomuk/kratingpainter.h>
+#endif
#include <kiconloader.h>
#include <kcategorizedsortfilterproxymodel.h>
#include <qimageblitz.h>
#include <kuser.h>
-#include <config-nepomuk.h>
-#ifdef HAVE_NEPOMUK
-#include <nepomuk/global.h>
-#include <nepomuk/resource.h>
-#include <nepomuk/tag.h>
-#endif
-
#include "dolphinview.h"
#include "dolphinmodel.h"
+#define HORIZONTAL_HINT 3
+
DolphinCategoryDrawer::DolphinCategoryDrawer()
+ : KCategoryDrawer()
{
}
void DolphinCategoryDrawer::drawCategory(const QModelIndex &index, int sortRole,
const QStyleOption &option, QPainter *painter) const
{
- QRect starRect = option.rect;
-
- int iconSize = KIconLoader::global()->currentSize(K3Icon::Small);
- QVariant categoryVariant = index.model()->data(index, KCategorizedSortFilterProxyModel::CategoryRole);
-
- if (!categoryVariant.isValid())
- {
- return;
- }
+ Q_UNUSED(sortRole);
+ painter->setRenderHint(QPainter::Antialiasing);
- const QString category = categoryVariant.toString();
+ const QString category = index.model()->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
+ const QRect optRect = option.rect;
+ QFont font(QApplication::font());
+ font.setBold(true);
+ const QFontMetrics fontMetrics = QFontMetrics(font);
- QColor color;
+ QColor outlineColor = option.palette.text().color();
+ outlineColor.setAlphaF(0.35);
- if (option.state & QStyle::State_Selected)
- {
- color = option.palette.color(QPalette::HighlightedText);
- }
- else
+ //BEGIN: top left corner
{
- color = option.palette.color(QPalette::Text);
+ painter->save();
+ painter->setPen(outlineColor);
+ const QPointF topLeft(optRect.topLeft());
+ QRectF arc(topLeft, QSizeF(4, 4));
+ arc.translate(0.5, 0.5);
+ painter->drawArc(arc, 1440, 1440);
+ painter->restore();
}
+ //END: top left corner
- painter->save();
- painter->setRenderHint(QPainter::Antialiasing);
-
- QStyleOptionButton opt;
-
- opt.rect = option.rect;
- opt.palette = option.palette;
- opt.direction = option.direction;
- opt.text = category;
-
- if (option.state & QStyle::State_Selected)
+ //BEGIN: left vertical line
{
- QColor selected = option.palette.color(QPalette::Highlight);
-
- QLinearGradient gradient(option.rect.topLeft(),
- option.rect.bottomRight());
- gradient.setColorAt(option.direction == Qt::LeftToRight ? 0
- : 1, selected);
- gradient.setColorAt(option.direction == Qt::LeftToRight ? 1
- : 0, Qt::transparent);
-
- painter->fillRect(option.rect, gradient);
+ QPoint start(optRect.topLeft());
+ start.ry() += 3;
+ QPoint verticalGradBottom(optRect.topLeft());
+ verticalGradBottom.ry() += fontMetrics.height() + 5;
+ QLinearGradient gradient(start, verticalGradBottom);
+ gradient.setColorAt(0, outlineColor);
+ gradient.setColorAt(1, Qt::transparent);
+ painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient);
}
- else if (option.state & QStyle::State_MouseOver)
- {
- QColor hover = option.palette.color(QPalette::Highlight).light();
- hover.setAlpha(88);
+ //END: left vertical line
- QLinearGradient gradient(option.rect.topLeft(),
- option.rect.bottomRight());
- gradient.setColorAt(option.direction == Qt::LeftToRight ? 0
- : 1, hover);
- gradient.setColorAt(option.direction == Qt::LeftToRight ? 1
- : 0, Qt::transparent);
-
- painter->fillRect(option.rect, gradient);
+ //BEGIN: horizontal line
+ {
+ QPoint start(optRect.topLeft());
+ start.rx() += 3;
+ QPoint horizontalGradTop(optRect.topLeft());
+ horizontalGradTop.rx() += optRect.width() - 6;
+ painter->fillRect(QRect(start, QSize(optRect.width() - 6, 1)), outlineColor);
}
+ //END: horizontal line
- QFont painterFont = painter->font();
- painterFont.setWeight(QFont::Bold);
- QFontMetrics metrics(painterFont);
- painter->setFont(painterFont);
-
- QPainterPath path;
- path.addRect(option.rect.left(),
- option.rect.bottom() - 2,
- option.rect.width(),
- 2);
-
- QLinearGradient gradient(option.rect.topLeft(),
- option.rect.bottomRight());
- gradient.setColorAt(option.direction == Qt::LeftToRight ? 0
- : 1, color);
- gradient.setColorAt(option.direction == Qt::LeftToRight ? 1
- : 0, Qt::transparent);
-
- painter->setBrush(gradient);
- painter->fillPath(path, gradient);
-
- if (option.direction == Qt::LeftToRight)
+ //BEGIN: top right corner
{
- opt.rect.setLeft(opt.rect.left() + (iconSize / 4));
- starRect.setLeft(starRect.left() + (iconSize / 4));
- starRect.setRight(starRect.right() + (iconSize / 4));
+ painter->save();
+ painter->setPen(outlineColor);
+ QPointF topRight(optRect.topRight());
+ topRight.rx() -= 4;
+ QRectF arc(topRight, QSizeF(4, 4));
+ arc.translate(0.5, 0.5);
+ painter->drawArc(arc, 0, 1440);
+ painter->restore();
}
- else
+ //END: top right corner
+
+ //BEGIN: right vertical line
{
- opt.rect.setRight(opt.rect.width() - (iconSize / 4));
- starRect.setLeft(starRect.width() - iconSize);
- starRect.setRight(starRect.width() - (iconSize / 4));
+ QPoint start(optRect.topRight());
+ start.ry() += 3;
+ QPoint verticalGradBottom(optRect.topRight());
+ verticalGradBottom.ry() += fontMetrics.height() + 5;
+ QLinearGradient gradient(start, verticalGradBottom);
+ gradient.setColorAt(0, outlineColor);
+ gradient.setColorAt(1, Qt::transparent);
+ painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient);
}
+ //END: right vertical line
- bool paintIcon = true;
- bool paintText = true;
-
- QPixmap icon;
- switch (index.column()) {
- case KDirModel::Name:
- paintIcon = false;
- break;
-
- case KDirModel::Size:
- paintIcon = false;
- break;
-
- case KDirModel::ModifiedTime:
- paintIcon = false;
- break;
-
- case KDirModel::Permissions:
- paintIcon = false; // TODO: let's think about how to represent permissions
- break;
-
- case KDirModel::Owner: {
- opt.rect.setTop(option.rect.bottom() - (iconSize / 4));
- KUser user(category);
- QString faceIconPath = user.faceIconPath();
-
- if (!faceIconPath.isEmpty())
- {
- icon = QPixmap::fromImage(QImage(faceIconPath).scaledToHeight(option.fontMetrics.height(), Qt::SmoothTransformation));
- }
- else
- {
- icon = KIconLoader::global()->loadIcon("user", K3Icon::NoGroup, option.fontMetrics.height());
- }
-
- opt.rect.setTop(opt.rect.top() - icon.height());
-
- break;
- }
-
- case KDirModel::Group:
- paintIcon = false;
- break;
-
- case KDirModel::Type: {
- opt.rect.setTop(option.rect.bottom() - (iconSize / 4));
- const KCategorizedSortFilterProxyModel *proxyModel = static_cast<const KCategorizedSortFilterProxyModel*>(index.model());
- const DolphinModel *model = static_cast<const DolphinModel*>(proxyModel->sourceModel());
- KFileItem item = model->itemForIndex(proxyModel->mapToSource(index));
- // This is the only way of getting the icon right. Others will fail on corner
- // cases like the item representing this group has been set a different icon,
- // so the group icon drawn is that one particularly. This way assures the drawn
- // icon is the one of the mimetype of the group itself. (ereslibre)
- icon = KIconLoader::global()->loadMimeTypeIcon(item.mimeTypePtr()->iconName(),
- K3Icon::NoGroup, option.fontMetrics.height());
-
- opt.rect.setTop(opt.rect.top() - icon.height());
-
- break;
- }
-
-#ifdef HAVE_NEPOMUK
- case DolphinModel::Rating: {
- paintText = false;
- paintIcon = false;
-
- starRect.setTop(option.rect.top() + (option.rect.height() / 2) - (iconSize / 2));
- starRect.setSize(QSize(iconSize, iconSize));
-
- QPixmap pixmap = KIconLoader::global()->loadIcon("rating", K3Icon::Small);
- QPixmap smallPixmap = KIconLoader::global()->loadIcon("rating", K3Icon::NoGroup, iconSize / 2);
- QPixmap disabledPixmap = KIconLoader::global()->loadIcon("rating", K3Icon::Small);
-
- QImage img = disabledPixmap.toImage();
- Blitz::grayscale(img);
- disabledPixmap = QPixmap::fromImage(img);
-
- int rating = category.toInt();
-
- for (int i = 0; i < rating - (rating % 2); i += 2) {
- painter->drawPixmap(starRect, pixmap);
-
- if (option.direction == Qt::LeftToRight)
- {
- starRect.setLeft(starRect.left() + iconSize + (iconSize / 4) /* separator between stars */);
- starRect.setRight(starRect.right() + iconSize + (iconSize / 4) /* separator between stars */);
- }
- else
- {
- starRect.setLeft(starRect.left() - iconSize - (iconSize / 4) /* separator between stars */);
- starRect.setRight(starRect.right() - iconSize - (iconSize / 4) /* separator between stars */);
- }
- }
-
- if (rating && rating % 2) {
- if (option.direction == Qt::RightToLeft)
- {
- starRect.setLeft(starRect.left() + (iconSize / 2) /* separator between stars */);
- }
-
- starRect.setTop(option.rect.top() + (option.rect.height() / 2) - (iconSize / 4));
- starRect.setSize(QSize(iconSize / 2, iconSize / 2));
- painter->drawPixmap(starRect, smallPixmap);
- starRect.setTop(opt.rect.top() + (option.rect.height() / 2) - (iconSize / 2));
-
- if (option.direction == Qt::LeftToRight)
- {
- starRect.setLeft(starRect.left() + (iconSize / 2) + (iconSize / 4));
- starRect.setRight(starRect.right() + (iconSize / 2) + (iconSize / 4));
- }
- else
- {
- starRect.setLeft(starRect.left() - (iconSize / 2) - (iconSize / 4));
- starRect.setRight(starRect.right() - (iconSize / 2) - (iconSize / 4));
- }
-
- if (option.direction == Qt::RightToLeft)
- {
- starRect.setLeft(starRect.left() - (iconSize / 2));
- starRect.setRight(starRect.right() - (iconSize / 2));
- }
-
- starRect.setSize(QSize(iconSize, iconSize));
- }
-
- for (int i = rating; i < 9; i += 2) {
- painter->drawPixmap(starRect, disabledPixmap);
-
- if (option.direction == Qt::LeftToRight)
- {
- starRect.setLeft(starRect.left() + iconSize + (iconSize / 4));
- starRect.setRight(starRect.right() + iconSize + (iconSize / 4));
- }
- else
- {
- starRect.setLeft(starRect.left() - iconSize - (iconSize / 4));
- starRect.setRight(starRect.right() - iconSize - (iconSize / 4));
- }
- }
-
- break;
+ //BEGIN: category information
+ {
+ const int iconSize = KIconLoader::global()->currentSize(KIconLoader::Small);
+
+ bool paintIcon;
+ QPixmap icon;
+ switch (index.column()) {
+ case KDirModel::Owner: {
+ paintIcon = true;
+ KUser user(category);
+ const QString faceIconPath = user.faceIconPath();
+ if (faceIconPath.isEmpty()) {
+ icon = KIconLoader::global()->loadIcon("user-identity", KIconLoader::NoGroup, iconSize);
+ } else {
+ icon = QPixmap::fromImage(QImage(faceIconPath).scaledToHeight(iconSize, Qt::SmoothTransformation));
+ }
+ }
+ break;
+ case KDirModel::Type: {
+ paintIcon = true;
+ const KCategorizedSortFilterProxyModel *proxyModel = static_cast<const KCategorizedSortFilterProxyModel*>(index.model());
+ const DolphinModel *model = static_cast<const DolphinModel*>(proxyModel->sourceModel());
+ KFileItem item = model->itemForIndex(proxyModel->mapToSource(index));
+ // This is the only way of getting the icon right. Others will fail on corner
+ // cases like the item representing this group has been set a different icon,
+ // so the group icon drawn is that one particularly. This way assures the drawn
+ // icon is the one of the mimetype of the group itself. (ereslibre)
+ icon = KIconLoader::global()->loadMimeTypeIcon(item.mimeTypePtr()->iconName(), KIconLoader::NoGroup, iconSize);
+ }
+ break;
+ default:
+ paintIcon = false;
+ }
+
+ if (paintIcon) {
+ QRect iconRect(option.rect);
+ iconRect.setTop(iconRect.top() + 4);
+ iconRect.setLeft(iconRect.left() + 7);
+ iconRect.setSize(QSize(iconSize, iconSize));
+
+ painter->drawPixmap(iconRect, icon);
}
- case DolphinModel::Tags:
- paintIcon = false;
- break;
-#endif
- }
-
- if (paintIcon) {
- painter->drawPixmap(QRect(option.direction == Qt::LeftToRight ? opt.rect.left()
- : opt.rect.right() - icon.width() + (iconSize / 4), opt.rect.top(), icon.width(), icon.height()), icon);
-
- if (option.direction == Qt::LeftToRight)
- {
- opt.rect.setLeft(opt.rect.left() + icon.width() + (iconSize / 4));
- }
- else
+ //BEGIN: text
{
- opt.rect.setRight(opt.rect.right() + (iconSize / 4));
+ QRect textRect(option.rect);
+ textRect.setTop(textRect.top() + 7);
+ textRect.setLeft(textRect.left() + 7 + (paintIcon ? (iconSize + 6) : 0));
+ textRect.setHeight(qMax(fontMetrics.height(), iconSize));
+ textRect.setRight(textRect.right() - 7);
+ textRect.setBottom(textRect.bottom() - 5); // only one pixel separation here (no gradient)
+
+ painter->save();
+ painter->setFont(font);
+ QColor penColor(option.palette.text().color());
+ penColor.setAlphaF(0.6);
+ painter->setPen(penColor);
+ painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, category);
+ painter->restore();
}
+ //END: text
}
+ //BEGIN: category information
+}
- if (paintText) {
- opt.rect.setTop(option.rect.top() + (iconSize / 4));
- opt.rect.setBottom(opt.rect.bottom() - 2);
- painter->setPen(color);
-
- QRect textRect = opt.rect;
-
- if (option.direction == Qt::RightToLeft)
- {
- textRect.setWidth(textRect.width() - (paintIcon ? icon.width() + (iconSize / 2)
- : -(iconSize / 4)));
- }
+int DolphinCategoryDrawer::categoryHeight(const QModelIndex &index, const QStyleOption &option) const
+{
+ int iconSize = KIconLoader::global()->currentSize(KIconLoader::Small);
+ int heightWithoutIcon = option.fontMetrics.height() + (iconSize / 4) * 2 + 1; /* 1 pixel-width gradient */
+ bool paintIcon;
- painter->drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft,
- metrics.elidedText(category, Qt::ElideRight, textRect.width()));
+ switch (index.column()) {
+ case KDirModel::Owner:
+ case KDirModel::Type:
+ paintIcon = true;
+ break;
+ default:
+ paintIcon = false;
}
- painter->restore();
-}
-
-int DolphinCategoryDrawer::categoryHeight(const QStyleOption &option) const
-{
- int iconSize = KIconLoader::global()->currentSize(K3Icon::Small);
+ if (paintIcon) {
+ return qMax(heightWithoutIcon + 5, iconSize + 1 /* 1 pixel-width gradient */
+ + 5 /* top and bottom separation */);
+ }
- return qMax(option.fontMetrics.height() + (iconSize / 4) * 2 + 2, iconSize + (iconSize / 4) * 2 + 2) /* 2 gradient */;
+ return heightWithoutIcon + 5;
}