KWidgetsAddons

kratingwidget.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 2006-2007 Sebastian Trueg <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #include "kratingwidget.h"
9 #include "kratingpainter.h"
10 
11 #include <QIcon>
12 #include <QMouseEvent>
13 #include <QPainter>
14 #include <QPixmap>
15 
16 class KRatingWidgetPrivate
17 {
18 public:
19  int rating = 0;
20  int hoverRating = -1;
21  int pixSize = 16;
22 
23  KRatingPainter ratingPainter;
24 };
25 
27  : QFrame(parent)
28  , d(new KRatingWidgetPrivate())
29 {
30  setMouseTracking(true);
31 }
32 
34 
35 #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 0)
37 {
38  setCustomPixmap(pix);
39 }
40 #endif
41 
43 {
44  d->ratingPainter.setCustomPixmap(pix);
45  update();
46 }
47 
48 void KRatingWidget::setIcon(const QIcon &icon)
49 {
50  d->ratingPainter.setIcon(icon);
51  update();
52 }
53 
55 {
56  d->pixSize = size;
58 }
59 
60 int KRatingWidget::spacing() const
61 {
62  return d->ratingPainter.spacing();
63 }
64 
65 QIcon KRatingWidget::icon() const
66 {
67  return d->ratingPainter.icon();
68 }
69 
71 {
72  d->ratingPainter.setSpacing(s);
73  update();
74 }
75 
76 Qt::Alignment KRatingWidget::alignment() const
77 {
78  return d->ratingPainter.alignment();
79 }
80 
82 {
83  d->ratingPainter.setAlignment(align);
84  update();
85 }
86 
88 {
89  return d->ratingPainter.layoutDirection();
90 }
91 
93 {
94  d->ratingPainter.setLayoutDirection(direction);
95  update();
96 }
97 
98 #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 85)
99 unsigned int KRatingWidget::rating() const
100 #else
101 int KRatingWidget::rating() const
102 #endif
103 {
104  return d->rating;
105 }
106 
107 int KRatingWidget::maxRating() const
108 {
109  return d->ratingPainter.maxRating();
110 }
111 
112 bool KRatingWidget::halfStepsEnabled() const
113 {
114  return d->ratingPainter.halfStepsEnabled();
115 }
116 
117 #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 0)
118 void KRatingWidget::setRating(unsigned int rating)
119 {
120  setRating((int)rating);
121 }
122 #endif
123 
124 void KRatingWidget::setRating(int rating)
125 {
126  if (rating != d->rating) {
127  d->rating = rating;
128  d->hoverRating = rating;
129  Q_EMIT ratingChanged(rating);
130 #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 85)
131  Q_EMIT ratingChanged((unsigned int)rating);
132 #endif
133  update();
134  }
135 }
136 
137 #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 0)
138 void KRatingWidget::setMaxRating(unsigned int max)
139 {
140  setMaxRating((int)max);
141 }
142 #endif
143 
145 {
146  d->ratingPainter.setMaxRating(max);
147  update();
148 }
149 
151 {
152  d->ratingPainter.setHalfStepsEnabled(enabled);
153  update();
154 }
155 
156 #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 0)
158 {
159  setHalfStepsEnabled(!fs);
160 }
161 #endif
162 
163 static inline int adjustedHoverRating(bool halfStep, int hoverRating, int rating)
164 {
165  // intentionally skip zero, or half step is disabled.
166  if (!halfStep || hoverRating == 0) {
167  return hoverRating;
168  }
169 
170  // See bug 171343, if we click on a star we want it to be full star, click again
171  // make it half, click third time make it clear.
172 
173  // round up hoverRating to next full star rating
174  const int hoveredFullStarRating = hoverRating + (hoverRating % 2);
175  // Check if the star under mouse is the last half or whole star of the rating.
176  if (hoveredFullStarRating == rating || hoveredFullStarRating == rating + 1) {
177  // If current pointed star is not empty, next rating will be rating - 1
178  // if we point at 4th star and rating is 8 (4 star), next click will make it 7
179  // if we point at 4th star and rating is 7 (3.5 star), next click will make it 6
180  hoverRating = rating - 1;
181  } else {
182  // otherwise make it a full star rating
183  hoverRating = hoveredFullStarRating;
184  }
185  return hoverRating;
186 }
187 
188 void KRatingWidget::mousePressEvent(QMouseEvent *e)
189 {
190  if (e->button() == Qt::LeftButton) {
191  d->hoverRating = adjustedHoverRating(halfStepsEnabled(), d->ratingPainter.ratingFromPosition(contentsRect(), e->pos()), d->rating);
192  // avoid set a rating to something less than zero, it may happen if widget is scaled and
193  // mouse is clicked outside the star region.
194  if (d->hoverRating >= 0) {
195  setRating(d->hoverRating);
196  }
197  }
198 }
199 
200 void KRatingWidget::mouseMoveEvent(QMouseEvent *e)
201 {
202  // when moving the mouse we show the user what the result of clicking will be
203  const int prevHoverRating = d->hoverRating;
204  d->hoverRating = adjustedHoverRating(halfStepsEnabled(), d->ratingPainter.ratingFromPosition(contentsRect(), e->pos()), d->rating);
205  if (d->hoverRating != prevHoverRating) {
206  update();
207  }
208 }
209 
210 void KRatingWidget::leaveEvent(QEvent *)
211 {
212  d->hoverRating = -1;
213  update();
214 }
215 
216 void KRatingWidget::paintEvent(QPaintEvent *e)
217 {
219  QPainter p(this);
220  d->ratingPainter.setEnabled(isEnabled());
221  d->ratingPainter.paint(&p, contentsRect(), d->rating, d->hoverRating);
222 }
223 
224 QSize KRatingWidget::sizeHint() const
225 {
226  int numPix = d->ratingPainter.maxRating();
227  if (d->ratingPainter.halfStepsEnabled()) {
228  numPix /= 2;
229  }
230 
231  QSize pixSize(d->pixSize, d->pixSize);
232  if (!d->ratingPainter.customPixmap().isNull()) {
233  pixSize = d->ratingPainter.customPixmap().size() / d->ratingPainter.customPixmap().devicePixelRatio();
234  }
235 
236  return QSize(pixSize.width() * numPix + spacing() * (numPix - 1) + frameWidth() * 2, pixSize.height() + frameWidth() * 2);
237 }
238 
239 void KRatingWidget::resizeEvent(QResizeEvent *e)
240 {
242 }
243 
244 #include "moc_kratingwidget.cpp"
QPoint pos() const const
KRatingWidget(QWidget *parent=nullptr)
Creates a new rating widget.
typedef Alignment
Utility class that draws a row of stars for a rating value.
Q_EMITQ_EMIT
Qt::MouseButton button() const const
void update()
virtual void resizeEvent(QResizeEvent *event)
~KRatingWidget() override
Destructor.
Qt::LayoutDirection layoutDirection() const
The layout direction.
void setLayoutDirection(Qt::LayoutDirection direction)
LTR or RTL.
LeftButton
void setOnlyPaintFullSteps(bool)
void setCustomPixmap(const QPixmap &pixmap)
Set a custom pixmap.
void setAlignment(Qt::Alignment align)
The alignment of the stars in the drawing rect.
void setPixmap(const QPixmap &)
Set the pixap to be used to display a rating step.
void setSpacing(int)
Set the spacing between the pixmaps.
void setHalfStepsEnabled(bool enabled)
If half steps are enabled (the default) then one rating step corresponds to half a star.
void setMaxRating(int max)
Set the maximum allowed rating value.
void setMouseTracking(bool enable)
void updateGeometry()
void ratingChanged(unsigned int rating)
virtual void paintEvent(QPaintEvent *) override
LayoutDirection
void setIcon(const QIcon &icon)
Set a custom icon.
void setRating(int rating)
Set the current rating.
void setPixmapSize(int size)
Set the recommended size of the pixmaps.
QRect contentsRect() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Dec 11 2023 04:01:37 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.