[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    Making the rating painter class public
From:       Sebastian =?iso-8859-1?q?Tr=FCg?= <strueg () mandriva ! com>
Date:       2008-02-25 13:08:58
Message-ID: 200802251408.58392.strueg () mandriva ! com
[Download RAW message or body]

The Nepomuk::RatingPainter class is used in the Nepomuk lib to draw ratings, 
in Dolphin to draw rating categorizations, and in nepomuk playground to draw 
ratings for search results. Thus, having 3 places where it is used, I propose 
to make it public API for 4.1.

Please see the attached files for the class. Any objections?

Cheers,
Sebastian

["ratingpainter.h" (text/x-c++hdr)]

/*
   This file is part of the Nepomuk KDE project.
   Copyright (C) 2007 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 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.
 */

#ifndef _NEPOMUK_RATING_PAINTER_H_
#define _NEPOMUK_RATING_PAINTER_H_

class QPainter;

#include <QtCore/QRect>
#include <QtCore/QPoint>

#include <kicon.h>

#include <nepomuk/nepomuk_export.h>


namespace Nepomuk {
    /**
     * \brief Utility class that draws a row of stars for a rating value.
     *
     * The RatingPainter also allows to determine a rating value from
     * a position in the draw area. it supports all different alignments
     * and custom icons.
     *
     * \author Sebastian Trueg <trueg@kde.org>
     */
    class NEPOMUK_EXPORT RatingPainter
    {
    public:
        /**
         * Create a new RatingPainter.
         * For most cases the static methods drawRating and getRatingFromPosition
         * should be sufficient.
         */
        RatingPainter();
        
        /**
         * Destructor
         */
        ~RatingPainter();

        /**
         * The maximum rating, i.e. how many stars are drawn
         * in total.
         *
         * \sa setMaxRating
         */
        int maxRating() const;

        /**
         * If half steps are enabled one star equals to 2 rating
         * points and uneven rating values result in half-stars being
         * drawn.
         *
         * \sa setHalfStepsEnabled
         */
        bool halfStepsEnabled() const;

        /**
         * The alignment of the stars.
         *
         * \sa setAlignment
         */
        Qt::Alignment alignment() const;

        /**
         * The layout direction. If RTL the stars
         * representing the rating value will be drawn from the 
         * right.
         *
         * \sa setLayoutDirection
         */
        Qt::LayoutDirection direction() const;

        /**
         * The icon used to draw a star. In case a custom pixmap has been set
         * this value is ignored.
         *
         * \sa setIcon, setCustomPixmap
         */
        KIcon icon() const;

        /**
         * The custom pixmap set to draw a star. If no custom
         * pixmap has been set, an invalid pixmap is returned.
         *
         * \sa setCustomPixmap
         */
        QPixmap customPixmap() const;

        /**
         * The maximum rating. Defaults to 10.
         */
        void setMaxRating( int max );

        /**
         * If half steps are enabled (the default) then
         * one rating step corresponds to half a star.
         */
        void setHalfStepsEnabled( bool enabled );
        
        /**
         * The alignment of the stars in the drawing rect.
         * All alignment flags are supported.
         */
        void setAlignment( Qt::Alignment align );

        /**
         * LTR or RTL
         */
        void setLayoutDirection( Qt::LayoutDirection direction );

        /**
         * Set a custom icon. Defaults to "rating".
         */
        void setIcon( const KIcon& icon );

        /**
         * Set a custom pixmap.
         */
        void setCustomPixmap( const QPixmap& pixmap );

        /**
         * Draw the rating into the configured rect.
         */
        void draw( QPainter* painter, const QRect& rect, int rating, int hoverRating \
= -1 );

        /**
         * Calculate the rating value from mouse position pos.
         *
         * \return The rating corresponding to pos or -1 if pos is
         * outside of the configured rect.
         */
        int fromPosition( const QRect& rect, const QPoint& pos );

        /**
         * Convenience method that draws a rating into the given rect.
         *
         * LayoutDirection is read from QPainter.
         *
         * \param align can be aligned vertically and horizontally. Using \
                Qt::AlignJustify will insert spacing
         * between the stars.
         */
        static void drawRating( QPainter* p, const QRect& rect, Qt::Alignment align, \
int rating, int hoverRating = -1 );

        /**
         * Get the rating that would be selected if the user clicked position pos
         * within rect if the rating has been drawn with drawRating() using the same
         * rect and align values.
         *
         * \return The new rating or -1 if pos is outside of the rating area.
         */
        static int getRatingFromPosition( const QRect& rect, Qt::Alignment align, \
Qt::LayoutDirection direction, const QPoint& pos );

    private:
        class Private;
        Private* const d;
    };
}

#endif


["ratingpainter.cpp" (text/x-c++src)]

/*
   This file is part of the Nepomuk KDE project.
   Copyright (C) 2007 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 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 <QtGui/QPainter>
#include <QtGui/QPixmap>

#include <kicon.h>
#include <kiconeffect.h>
#include <kdebug.h>


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 );
}



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic