/* This file is part of the Nepomuk KDE project. Copyright (C) 2007 Sebastian Trueg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. 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 "ratingpainter.h" #include #include #include #include #include class Nepomuk::RatingPainter::Private { public: Private() : maxRating(10), icon( "rating" ), bHalfSteps(true), alignment(Qt::AlignCenter), direction(Qt::LeftToRight) { } int maxRating; KIcon icon; bool bHalfSteps; Qt::Alignment alignment; Qt::LayoutDirection direction; QPixmap customPixmap; }; Nepomuk::RatingPainter::RatingPainter() : d(new Private()) { } Nepomuk::RatingPainter::~RatingPainter() { delete d; } int Nepomuk::RatingPainter::maxRating() const { return d->maxRating; } bool Nepomuk::RatingPainter::halfStepsEnabled() const { return d->bHalfSteps; } Qt::Alignment Nepomuk::RatingPainter::alignment() const { return d->alignment; } Qt::LayoutDirection Nepomuk::RatingPainter::direction() const { return d->direction; } KIcon Nepomuk::RatingPainter::icon() const { return d->icon; } QPixmap Nepomuk::RatingPainter::customPixmap() const { return d->customPixmap; } void Nepomuk::RatingPainter::setMaxRating( int max ) { d->maxRating = max; } void Nepomuk::RatingPainter::setHalfStepsEnabled( bool enabled ) { d->bHalfSteps = enabled; } void Nepomuk::RatingPainter::setAlignment( Qt::Alignment align ) { d->alignment = align; } void Nepomuk::RatingPainter::setLayoutDirection( Qt::LayoutDirection direction ) { d->direction = direction; } void Nepomuk::RatingPainter::setIcon( const KIcon& icon ) { d->icon = icon; } void Nepomuk::RatingPainter::setCustomPixmap( const QPixmap& pixmap ) { d->customPixmap = pixmap; } void Nepomuk::RatingPainter::draw( QPainter* painter, const QRect& rect, int rating, int hoverRating ) { rating = qMin( rating, d->maxRating ); hoverRating = qMin( hoverRating, d->maxRating ); int numUsedStars = d->bHalfSteps ? d->maxRating/2 : d->maxRating; if ( hoverRating > 0 && hoverRating < rating ) { int tmp = hoverRating; hoverRating = rating; rating = tmp; } // get the rating pixmaps QPixmap ratingPix; if ( !d->customPixmap.isNull() ) { ratingPix = d->customPixmap; } else { KIcon ratingIcon( "rating" ); int iconSize = qMin( rect.height(), rect.width() / numUsedStars ); ratingPix = ratingIcon.pixmap( iconSize ); } QPixmap disabledRatingPix = KIconEffect().apply( ratingPix, KIconEffect::ToGray, 1.0, QColor(), false ); QPixmap hoverPix; bool half = d->bHalfSteps && rating%2; int numRatingStars = d->bHalfSteps ? rating/2 : rating; int numHoverStars = 0; bool halfHover = false; if ( hoverRating > 0 && rating != hoverRating ) { numHoverStars = d->bHalfSteps ? hoverRating/2 : hoverRating; halfHover = d->bHalfSteps && hoverRating%2; hoverPix = KIconEffect().apply( ratingPix, KIconEffect::ToGray, 0.5, QColor(), false ); } int usedSpacing = 0; if ( d->alignment & Qt::AlignJustify ) { int w = rect.width(); w -= numUsedStars * ratingPix.width(); usedSpacing = w / ( numUsedStars-1 ); } int i = 0; int x = rect.x(); if ( d->alignment & Qt::AlignRight ) { x += ( rect.width() - ratingPix.width()*numUsedStars ); } else if ( d->alignment & Qt::AlignCenter ) { x += ( rect.width() - ratingPix.width()*numUsedStars )/2; } int xInc = ratingPix.width() + usedSpacing; if ( d->direction == Qt::RightToLeft ) { x = rect.width() - ratingPix.width() - x; 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() ); } for(; i < numRatingStars; ++i ) { painter->drawPixmap( x, y, ratingPix ); x += xInc; } if( half ) { painter->drawPixmap( x, y, ratingPix.width()/2, ratingPix.height(), d->direction == Qt::LeftToRight ? ratingPix : ( numHoverStars > 0 ? hoverPix : disabledRatingPix ), 0, 0, ratingPix.width()/2, ratingPix.height() ); painter->drawPixmap( x + ratingPix.width()/2, y, ratingPix.width()/2, ratingPix.height(), d->direction == Qt::LeftToRight ? ( numHoverStars > 0 ? hoverPix : disabledRatingPix ) : ratingPix, ratingPix.width()/2, 0, ratingPix.width()/2, ratingPix.height() ); 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::LeftToRight ? hoverPix : disabledRatingPix, 0, 0, ratingPix.width()/2, ratingPix.height() ); painter->drawPixmap( x + ratingPix.width()/2, y, ratingPix.width()/2, ratingPix.height(), d->direction == Qt::LeftToRight ? disabledRatingPix : hoverPix, ratingPix.width()/2, 0, ratingPix.width()/2, ratingPix.height() ); x += xInc; ++i; } for(; i < numUsedStars; ++i ) { painter->drawPixmap( x, y, disabledRatingPix ); x += xInc; } } int Nepomuk::RatingPainter::fromPosition( const QRect& rect, const QPoint& pos ) { int numUsedStars = d->bHalfSteps ? d->maxRating/2 : d->maxRating; QPixmap ratingPix; if ( !d->customPixmap.isNull() ) { ratingPix = d->customPixmap; } else { KIcon ratingIcon( "rating" ); int iconSize = qMin( rect.height(), rect.width() / numUsedStars ); ratingPix = ratingIcon.pixmap( iconSize ); } QRect usedRect( rect ); if ( d->alignment & Qt::AlignRight ) { usedRect.setLeft( rect.right() - numUsedStars * ratingPix.width() ); } else if ( d->alignment & Qt::AlignHCenter ) { int x = ( rect.width() - numUsedStars * ratingPix.width() )/2; usedRect.setLeft( rect.left() + x ); usedRect.setRight( rect.right() - x ); } else { // d->alignment & Qt::AlignLeft usedRect.setRight( rect.left() + numUsedStars * ratingPix.width() - 1 ); } if ( d->alignment & Qt::AlignBottom ) { usedRect.setTop( rect.bottom() - ratingPix.height() + 1 ); } else if ( d->alignment & Qt::AlignVCenter ) { 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 ); } if ( usedRect.contains( pos ) ) { int x = 0; if ( d->direction == Qt::RightToLeft ) { x = usedRect.right() - pos.x(); } else { x = pos.x() - usedRect.left(); } double one = ( double )usedRect.width() / ( double )d->maxRating; kDebug() << "rating:" << ( int )( ( double )x/one + 0.5 ); return ( int )( ( double )x/one + 0.5 ); } else { return -1; } } void Nepomuk::RatingPainter::drawRating( QPainter* painter, const QRect& rect, Qt::Alignment align, int rating, int hoverRating ) { RatingPainter rp; rp.setAlignment( align ); rp.setLayoutDirection( painter->layoutDirection() ); rp.draw( painter, rect, rating, hoverRating ); } int Nepomuk::RatingPainter::getRatingFromPosition( const QRect& rect, Qt::Alignment align, Qt::LayoutDirection direction, const QPoint& pos ) { RatingPainter rp; rp.setAlignment( align ); rp.setLayoutDirection( direction ); return rp.fromPosition( rect, pos ); }