Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "qxtstars.h"
00026
00027 #include <QStyleOptionSlider>
00028 #include <QPainterPath>
00029 #include <QMouseEvent>
00030 #include <QPainter>
00031
00032 class QxtStarsPrivate : public QxtPrivate<QxtStars>
00033 {
00034 public:
00035 QXT_DECLARE_PUBLIC(QxtStars);
00036 QxtStarsPrivate();
00037 int pixelPosToRangeValue(int pos) const;
00038 inline int pick(const QPoint& pt) const;
00039 QStyleOptionSlider getStyleOption() const;
00040 QSize getStarSize() const;
00041 int snapBackPosition;
00042 bool readOnly;
00043 QSize starSize;
00044 QPainterPath star;
00045 };
00046
00047 QxtStarsPrivate::QxtStarsPrivate()
00048 : snapBackPosition(0), readOnly(false)
00049 {
00050 star.moveTo(14.285716, -43.352104);
00051 star.lineTo(38.404536, 9.1654726);
00052 star.lineTo(95.804846, 15.875014);
00053 star.lineTo(53.310787, 55.042197);
00054 star.lineTo(64.667306, 111.7065);
00055 star.lineTo(14.285714, 83.395573);
00056 star.lineTo(-36.095881, 111.7065);
00057 star.lineTo(-24.739359, 55.042198);
00058 star.lineTo(-67.233416, 15.875009);
00059 star.lineTo(-9.8331075, 9.1654728);
00060 star.closeSubpath();
00061 }
00062
00063 int QxtStarsPrivate::pixelPosToRangeValue(int pos) const
00064 {
00065 const QxtStars* p = &qxt_p();
00066 QStyleOptionSlider opt = getStyleOption();
00067 QRect gr = p->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, p);
00068 QRect sr = p->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, p);
00069 int sliderMin, sliderMax, sliderLength;
00070
00071 gr.setSize(qxt_p().sizeHint());
00072 if (p->orientation() == Qt::Horizontal)
00073 {
00074 sliderLength = sr.width();
00075 sliderMin = gr.x();
00076 sliderMax = gr.right() - sliderLength + 1;
00077 }
00078 else
00079 {
00080 sliderLength = sr.height();
00081 sliderMin = gr.y();
00082 sliderMax = gr.bottom() - sliderLength + 1;
00083 }
00084 return QStyle::sliderValueFromPosition(p->minimum(), p->maximum(), pos - sliderMin,
00085 sliderMax - sliderMin, opt.upsideDown);
00086 }
00087
00088 inline int QxtStarsPrivate::pick(const QPoint& pt) const
00089 {
00090 return qxt_p().orientation() == Qt::Horizontal ? pt.x() : pt.y();
00091 }
00092
00093
00094 QStyleOptionSlider QxtStarsPrivate::getStyleOption() const
00095 {
00096 const QxtStars* p = &qxt_p();
00097 QStyleOptionSlider opt;
00098 opt.initFrom(p);
00099 opt.subControls = QStyle::SC_None;
00100 opt.activeSubControls = QStyle::SC_None;
00101 opt.orientation = p->orientation();
00102 opt.maximum = p->maximum();
00103 opt.minimum = p->minimum();
00104 opt.upsideDown = (p->orientation() == Qt::Horizontal) ?
00105 (p->invertedAppearance() != (opt.direction == Qt::RightToLeft)) : (!p->invertedAppearance());
00106 opt.direction = Qt::LeftToRight;
00107 opt.sliderPosition = p->sliderPosition();
00108 opt.sliderValue = p->value();
00109 opt.singleStep = p->singleStep();
00110 opt.pageStep = p->pageStep();
00111 if (p->orientation() == Qt::Horizontal)
00112 opt.state |= QStyle::State_Horizontal;
00113 return opt;
00114 }
00115
00116 QSize QxtStarsPrivate::getStarSize() const
00117 {
00118 QSize size = starSize;
00119 if (!size.isValid() || size.isNull())
00120 {
00121 const int width = qxt_p().style()->pixelMetric(QStyle::PM_SmallIconSize);
00122 size = QSize(width, width);
00123 }
00124 return size;
00125 }
00126
00156 QxtStars::QxtStars(QWidget* parent) : QAbstractSlider(parent)
00157 {
00158 QXT_INIT_PRIVATE(QxtStars);
00159 setOrientation(Qt::Horizontal);
00160 setFocusPolicy(Qt::FocusPolicy(style()->styleHint(QStyle::SH_Button_FocusPolicy)));
00161 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
00162 setRange(0, 5);
00163 }
00164
00168 QxtStars::~QxtStars()
00169 {}
00170
00178 bool QxtStars::isReadOnly() const
00179 {
00180 return qxt_d().readOnly;
00181 }
00182
00183 void QxtStars::setReadOnly(bool readOnly)
00184 {
00185 if (qxt_d().readOnly != readOnly)
00186 {
00187 qxt_d().readOnly = readOnly;
00188 if (readOnly)
00189 setFocusPolicy(Qt::NoFocus);
00190 else
00191 setFocusPolicy(Qt::FocusPolicy(style()->styleHint(QStyle::SH_Button_FocusPolicy)));
00192 }
00193 }
00194
00201 QSize QxtStars::starSize() const
00202 {
00203 return qxt_d().starSize;
00204 }
00205
00206 void QxtStars::setStarSize(const QSize& size)
00207 {
00208 if (qxt_d().starSize != size)
00209 {
00210 qxt_d().starSize = size;
00211 updateGeometry();
00212 update();
00213 }
00214 }
00215
00219 QSize QxtStars::sizeHint() const
00220 {
00221 return minimumSizeHint();
00222 }
00223
00227 QSize QxtStars::minimumSizeHint() const
00228 {
00229 QSize size = qxt_d().getStarSize();
00230 size.rwidth() *= maximum() - minimum();
00231 if (orientation() == Qt::Vertical)
00232 size.transpose();
00233 return size;
00234 }
00235
00239 void QxtStars::paintEvent(QPaintEvent* event)
00240 {
00241 QAbstractSlider::paintEvent(event);
00242
00243 QPainter painter(this);
00244 painter.save();
00245 painter.setPen(palette().color(QPalette::Text));
00246 painter.setRenderHint(QPainter::Antialiasing);
00247
00248 const bool invert = invertedAppearance();
00249 const QSize size = qxt_d().getStarSize();
00250 const QRectF star = qxt_d().star.boundingRect();
00251 painter.scale(size.width() / star.width(), size.height() / star.height());
00252 const int count = maximum() - minimum();
00253 if (orientation() == Qt::Horizontal)
00254 {
00255 painter.translate(-star.x(), -star.y());
00256 if (invert != isRightToLeft())
00257 painter.translate((count - 1) * star.width(), 0);
00258 }
00259 else
00260 {
00261 painter.translate(-star.x(), -star.y());
00262 if (!invert)
00263 painter.translate(0, (count - 1) * star.height());
00264 }
00265 for (int i = 0; i < count; ++i)
00266 {
00267 if (value() > minimum() + i)
00268 painter.setBrush(palette().highlight());
00269 else
00270 painter.setBrush(palette().base());
00271 painter.drawPath(qxt_d().star);
00272
00273 if (orientation() == Qt::Horizontal)
00274 painter.translate(invert != isRightToLeft() ? -star.width() : star.width(), 0);
00275 else
00276 painter.translate(0, invert ? star.height() : -star.height());
00277 }
00278
00279 painter.restore();
00280 if (hasFocus())
00281 {
00282 QStyleOptionFocusRect opt;
00283 opt.initFrom(this);
00284 opt.rect.setSize(sizeHint());
00285 style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, &painter, this);
00286 }
00287 }
00288
00292 void QxtStars::keyPressEvent(QKeyEvent* event)
00293 {
00294 if (qxt_d().readOnly)
00295 {
00296 event->ignore();
00297 return;
00298 }
00299 QAbstractSlider::keyPressEvent(event);
00300 }
00301
00305 void QxtStars::mousePressEvent(QMouseEvent* event)
00306 {
00307 if (qxt_d().readOnly)
00308 {
00309 event->ignore();
00310 return;
00311 }
00312 QAbstractSlider::mousePressEvent(event);
00313
00314 if (maximum() == minimum() || (event->buttons() ^ event->button()))
00315 {
00316 event->ignore();
00317 return;
00318 }
00319
00320 event->accept();
00321 QStyleOptionSlider opt = qxt_d().getStyleOption();
00322 const QRect sliderRect = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
00323 const QPoint center = sliderRect.center() - sliderRect.topLeft();
00324 const int pos = qxt_d().pixelPosToRangeValue(qxt_d().pick(event->pos() - center));
00325 setSliderPosition(pos);
00326 triggerAction(SliderMove);
00327 setRepeatAction(SliderNoAction);
00328 qxt_d().snapBackPosition = pos;
00329 update();
00330 }
00331
00335 void QxtStars::mouseMoveEvent(QMouseEvent* event)
00336 {
00337 if (qxt_d().readOnly)
00338 {
00339 event->ignore();
00340 return;
00341 }
00342 QAbstractSlider::mouseMoveEvent(event);
00343
00344 event->accept();
00345 int newPosition = qxt_d().pixelPosToRangeValue(qxt_d().pick(event->pos()));
00346 QStyleOptionSlider opt = qxt_d().getStyleOption();
00347 int m = style()->pixelMetric(QStyle::PM_MaximumDragDistance, &opt, this);
00348 if (m >= 0)
00349 {
00350 QRect r = rect();
00351 r.adjust(-m, -m, m, m);
00352 if (!r.contains(event->pos()))
00353 newPosition = qxt_d().snapBackPosition;
00354 }
00355 setSliderPosition(newPosition);
00356 }
00357
00361 void QxtStars::mouseReleaseEvent(QMouseEvent* event)
00362 {
00363 if (qxt_d().readOnly)
00364 {
00365 event->ignore();
00366 return;
00367 }
00368 QAbstractSlider::mouseReleaseEvent(event);
00369
00370 if (event->buttons())
00371 {
00372 event->ignore();
00373 return;
00374 }
00375
00376 event->accept();
00377 setRepeatAction(SliderNoAction);
00378 }