kdelibs/kdeui/widgets/kratingpainter.cpp

323 lines
8.9 KiB
C++
Raw Normal View History

2014-11-13 01:04:59 +02:00
/*
This file is part of the Nepomuk KDE project.
Copyright (C) 2007-2008 Sebastian Trueg <trueg@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kratingpainter.h"
#include <QtGui/QPainter>
#include <QtGui/QPixmap>
#include <QtGui/QIcon>
#include <QtCore/QRect>
#include <QtCore/QPoint>
#include <kicon.h>
#include <kiconeffect.h>
#include <kiconloader.h>
#include <kdebug.h>
class KRatingPainter::Private
{
public:
Private()
: maxRating(10),
isEnabled(true),
bHalfSteps(true),
alignment(Qt::AlignCenter),
direction(Qt::LeftToRight),
spacing(0)
{
2014-11-13 01:04:59 +02:00
}
QPixmap getPixmap(int size);
2014-11-13 01:04:59 +02:00
int maxRating;
QIcon icon;
bool isEnabled;
bool bHalfSteps;
Qt::Alignment alignment;
Qt::LayoutDirection direction;
int spacing;
};
QPixmap KRatingPainter::Private::getPixmap(int size)
2014-11-13 01:04:59 +02:00
{
QIcon _icon(icon);
if (_icon.isNull()) {
_icon = KIcon("rating");
2014-11-13 01:04:59 +02:00
}
return _icon.pixmap(size);
2014-11-13 01:04:59 +02:00
}
KRatingPainter::KRatingPainter()
: d(new Private())
{
}
KRatingPainter::~KRatingPainter()
{
delete d;
}
int KRatingPainter::maxRating() const
{
return d->maxRating;
}
bool KRatingPainter::halfStepsEnabled() const
{
return d->bHalfSteps;
}
Qt::Alignment KRatingPainter::alignment() const
{
return d->alignment;
}
Qt::LayoutDirection KRatingPainter::layoutDirection() const
{
return d->direction;
}
QIcon KRatingPainter::icon() const
{
return d->icon;
}
bool KRatingPainter::isEnabled() const
{
return d->isEnabled;
}
int KRatingPainter::spacing() const
{
return d->spacing;
}
void KRatingPainter::setMaxRating(int max)
2014-11-13 01:04:59 +02:00
{
d->maxRating = max;
}
void KRatingPainter::setHalfStepsEnabled(bool enabled)
2014-11-13 01:04:59 +02:00
{
d->bHalfSteps = enabled;
}
void KRatingPainter::setAlignment(Qt::Alignment align)
2014-11-13 01:04:59 +02:00
{
d->alignment = align;
}
void KRatingPainter::setLayoutDirection(Qt::LayoutDirection direction)
2014-11-13 01:04:59 +02:00
{
d->direction = direction;
}
void KRatingPainter::setIcon(const QIcon &icon)
2014-11-13 01:04:59 +02:00
{
d->icon = icon;
}
void KRatingPainter::setEnabled(bool enabled)
2014-11-13 01:04:59 +02:00
{
d->isEnabled = enabled;
}
void KRatingPainter::setSpacing(int s)
2014-11-13 01:04:59 +02:00
{
d->spacing = qMax(0, s);
2014-11-13 01:04:59 +02:00
}
void KRatingPainter::paint(QPainter* painter, const QRect &rect, int rating, int hoverRating) const
2014-11-13 01:04:59 +02:00
{
rating = qMin(rating, d->maxRating);
hoverRating = qMin(hoverRating, d->maxRating);
2014-11-13 01:04:59 +02:00
int numUsedStars = (d->bHalfSteps ? d->maxRating / 2 : d->maxRating);
2014-11-13 01:04:59 +02:00
if ( hoverRating > 0 && hoverRating < rating ) {
int tmp = hoverRating;
hoverRating = rating;
rating = tmp;
}
int usedSpacing = d->spacing;
// get the rating pixmaps
int maxHSizeOnePix = ((rect.width() - (numUsedStars - 1) * usedSpacing ) / numUsedStars);
QPixmap ratingPix = d->getPixmap(qMin(rect.height(), maxHSizeOnePix));
2014-11-13 01:04:59 +02:00
QPixmap disabledRatingPix = KIconEffect::apply(ratingPix, KIconEffect::ToGray, 1.0, QColor(), QColor(), false);
2014-11-13 01:04:59 +02:00
QPixmap hoverPix;
// if we are disabled we become gray and more transparent
if ( !d->isEnabled ) {
ratingPix = disabledRatingPix;
KIconEffect::semiTransparent( disabledRatingPix );
}
bool half = (d->bHalfSteps && (rating % 2));
int numRatingStars = (d->bHalfSteps ? rating / 2 : rating);
2014-11-13 01:04:59 +02:00
int numHoverStars = 0;
bool halfHover = false;
if (hoverRating > 0 && rating != hoverRating && d->isEnabled) {
numHoverStars = d->bHalfSteps ? hoverRating / 2 : hoverRating;
halfHover = d->bHalfSteps && (hoverRating % 2);
hoverPix = KIconEffect::apply(ratingPix, KIconEffect::ToGray, 0.5, QColor(), QColor(), false);
2014-11-13 01:04:59 +02:00
}
if (d->alignment & Qt::AlignJustify) {
2014-11-13 01:04:59 +02:00
int w = rect.width();
w -= numUsedStars * ratingPix.width();
usedSpacing = w / (numUsedStars - 1);
2014-11-13 01:04:59 +02:00
}
int ratingAreaWidth = ratingPix.width()*numUsedStars + usedSpacing*(numUsedStars-1);
int i = 0;
int x = rect.x();
if (d->alignment & Qt::AlignRight) {
x += ( rect.width() - ratingAreaWidth);
} else if (d->alignment & Qt::AlignHCenter) {
x += ((rect.width() - ratingAreaWidth) / 2);
2014-11-13 01:04:59 +02:00
}
int xInc = ratingPix.width() + usedSpacing;
if (d->direction == Qt::RightToLeft) {
x = (rect.width() - ratingPix.width() - x);
2014-11-13 01:04:59 +02:00
xInc = -xInc;
}
int y = rect.y();
if (d->alignment & Qt::AlignVCenter) {
y += (rect.height() / 2 - ratingPix.height() / 2);
} else if (d->alignment & Qt::AlignBottom ) {
y += (rect.height() - ratingPix.height() );
2014-11-13 01:04:59 +02:00
}
for(; i < numRatingStars; ++i) {
painter->drawPixmap(x, y, ratingPix);
2014-11-13 01:04:59 +02:00
x += xInc;
}
if (half) {
painter->drawPixmap(
x, y, ratingPix.width()/2, ratingPix.height(),
d->direction == Qt::RightToLeft ? (numHoverStars > 0 ? hoverPix : disabledRatingPix) : ratingPix,
0, 0, ratingPix.width()/2, ratingPix.height()
);
painter->drawPixmap(
x + ratingPix.width() / 2, y, ratingPix.width() / 2, ratingPix.height(),
d->direction == Qt::RightToLeft ? ratingPix : (numHoverStars > 0 ? hoverPix : disabledRatingPix),
ratingPix.width() / 2, 0, ratingPix.width() / 2, ratingPix.height()
);
2014-11-13 01:04:59 +02:00
x += xInc;
++i;
}
for(; i < numHoverStars; ++i ) {
painter->drawPixmap( x, y, hoverPix );
x += xInc;
}
if( halfHover ) {
painter->drawPixmap(
x, y, ratingPix.width()/2, ratingPix.height(),
d->direction == Qt::RightToLeft ? disabledRatingPix : hoverPix,
0, 0, ratingPix.width()/2, ratingPix.height()
);
painter->drawPixmap(
x + ratingPix.width() / 2, y, ratingPix.width() / 2, ratingPix.height(),
d->direction == Qt::RightToLeft ? hoverPix : disabledRatingPix,
ratingPix.width() / 2, 0, ratingPix.width() / 2, ratingPix.height()
);
2014-11-13 01:04:59 +02:00
x += xInc;
++i;
}
for(; i < numUsedStars; ++i) {
painter->drawPixmap(x, y, disabledRatingPix);
2014-11-13 01:04:59 +02:00
x += xInc;
}
}
int KRatingPainter::ratingFromPosition(const QRect &rect, const QPoint &pos) const
2014-11-13 01:04:59 +02:00
{
int usedSpacing = d->spacing;
int numUsedStars = (d->bHalfSteps ? d->maxRating / 2 : d->maxRating);
int maxHSizeOnePix = ((rect.width() - (numUsedStars - 1) * usedSpacing) / numUsedStars);
QPixmap ratingPix = d->getPixmap(qMin(rect.height(), maxHSizeOnePix));
2014-11-13 01:04:59 +02:00
int ratingAreaWidth = ratingPix.width()*numUsedStars + usedSpacing*(numUsedStars-1);
QRect usedRect(rect);
if (d->alignment & Qt::AlignRight ) {
usedRect.setLeft(rect.right() - ratingAreaWidth);
} else if (d->alignment & Qt::AlignHCenter) {
int x = (rect.width() - ratingAreaWidth) / 2;
usedRect.setLeft(rect.left() + x);
usedRect.setRight(rect.right() - x);
} else {
// d->alignment & Qt::AlignLeft
usedRect.setRight(rect.left() + ratingAreaWidth - 1);
2014-11-13 01:04:59 +02:00
}
if (d->alignment & Qt::AlignBottom) {
usedRect.setTop(rect.bottom() - ratingPix.height() + 1);
} else if (d->alignment & Qt::AlignVCenter) {
2014-11-13 01:04:59 +02:00
int x = ( rect.height() - ratingPix.height() )/2;
usedRect.setTop( rect.top() + x );
usedRect.setBottom( rect.bottom() - x );
} else {
// d->alignment & Qt::AlignTop
usedRect.setBottom(rect.top() + ratingPix.height() - 1);
2014-11-13 01:04:59 +02:00
}
if (usedRect.contains(pos)) {
2014-11-13 01:04:59 +02:00
int x = 0;
if (d->direction == Qt::RightToLeft) {
2014-11-13 01:04:59 +02:00
x = usedRect.right() - pos.x();
} else {
2014-11-13 01:04:59 +02:00
x = pos.x() - usedRect.left();
}
double one = ( double )usedRect.width() / ( double )d->maxRating;
// kDebug() << "rating:" << ( int )( ( double )x/one + 0.5 );
2014-11-13 01:04:59 +02:00
return ( int )( ( double )x/one + 0.5 );
}
return -1;
2014-11-13 01:04:59 +02:00
}
void KRatingPainter::paintRating(QPainter *painter, const QRect &rect, Qt::Alignment align, int rating, int hoverRating)
2014-11-13 01:04:59 +02:00
{
KRatingPainter rp;
rp.setAlignment(align);
rp.setLayoutDirection(painter->layoutDirection());
rp.paint(painter, rect, rating, hoverRating);
2014-11-13 01:04:59 +02:00
}
int KRatingPainter::getRatingFromPosition(const QRect &rect, Qt::Alignment align, Qt::LayoutDirection direction, const QPoint &pos)
2014-11-13 01:04:59 +02:00
{
KRatingPainter rp;
rp.setAlignment(align);
rp.setLayoutDirection(direction);
return rp.ratingFromPosition(rect, pos);
2014-11-13 01:04:59 +02:00
}