]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Use the same codebase for rating drawing as in KRatingWidget and playground/nepomuk.
authorSebastian Trueg <sebastian@trueg.de>
Fri, 14 Dec 2007 19:23:02 +0000 (19:23 +0000)
committerSebastian Trueg <sebastian@trueg.de>
Fri, 14 Dec 2007 19:23:02 +0000 (19:23 +0000)
For KDE 4.1 we will export this in kdelibs/nepomuk

CCMAIL: peter.penz@gmx.at
CCMAIL: ereslibre@kde.org

svn path=/trunk/KDE/kdebase/apps/; revision=748547

src/CMakeLists.txt
src/dolphincategorydrawer.cpp
src/ratingpainter.cpp [new file with mode: 0644]
src/ratingpainter.h [new file with mode: 0644]

index 50dcec07ecc565c17f2cbffe20e2d8d45e60da9d..028d1ef08e32d2033fa0a4f420a0533828a0e1f6 100644 (file)
@@ -22,6 +22,7 @@ set(dolphinprivate_LIB_SRCS
     dolphinsortfilterproxymodel.cpp
     renamedialog.cpp
     dolphinview.cpp
+    ratingpainter.cpp
     dolphindropcontroller.cpp
     )
 
index 872a0c3377d45b1b001929b569423f72f5d8db77..9996672d718d4367a74776aac8dede0cb6f6fc1a 100644 (file)
@@ -19,7 +19,7 @@
   */
 
 #include "dolphincategorydrawer.h"
-
+#include "ratingpainter.h"
 #include <QPainter>
 #include <QFile>
 #include <QDir>
@@ -211,80 +211,11 @@ void DolphinCategoryDrawer::drawCategory(const QModelIndex &index, int sortRole,
             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", KIconLoader::Small);
-            QPixmap smallPixmap = KIconLoader::global()->loadIcon("rating", KIconLoader::NoGroup, iconSize / 2);
-            QPixmap disabledPixmap = KIconLoader::global()->loadIcon("rating", KIconLoader::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));
-                }
-            }
-
+            painter->setLayoutDirection( option.direction );
+            QRect ratingRect( option.rect );
+            ratingRect.setTop(option.rect.top() + (option.rect.height() / 2) - (iconSize / 2));
+            ratingRect.setHeight( iconSize );
+            Nepomuk::RatingPainter::drawRating( painter, ratingRect, Qt::AlignLeft, category.toInt() );
             break;
         }
 
diff --git a/src/ratingpainter.cpp b/src/ratingpainter.cpp
new file mode 100644 (file)
index 0000000..5dacf16
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+   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 );
+}
diff --git a/src/ratingpainter.h b/src/ratingpainter.h
new file mode 100644 (file)
index 0000000..f2abb0c
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+   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 {
+    /**
+     * Utility class that draws a row of stars for a rating value.
+     */
+    class NEPOMUK_EXPORT RatingPainter
+    {
+    public:
+        /**
+         * Create a new RatingPainter.
+         * Normally the static methods should be sufficient.
+         */
+        RatingPainter();
+        ~RatingPainter();
+
+        int maxRating() const;
+        bool halfStepsEnabled() const;
+        Qt::Alignment alignment() const;
+        Qt::LayoutDirection direction() const;
+        KIcon icon() const;
+        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