/* * Cantata * * Copyright (c) 2011-2021 Craig Drummond * * ---- * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "ratingwidget.h" #include "support/icon.h" #include "mpd-interface/song.h" #include #include #include #include #include #include static bool allowHalfStars=true; // TODO: Make this configurable??? static const int constNumStars=Song::Rating_Max/Song::Rating_Step; static const int constBorder=2; RatingPainter::RatingPainter(int s) : starSz(s) , pixmapSize((starSz*constNumStars)+(constBorder*(constNumStars-1)), starSz) , col(QApplication::palette().text().color()) { } void RatingPainter::paint(QPainter *p, const QRect &r, int rating) { if (rating<0 || rating>Song::Rating_Max) { return; } double pixelRatio=p && p->device() ? p->device()->DEVICE_PIXEL_RATIO() : 1.0; if (!isNull() && !Utils::equal(pixelRatio, pixmaps[0].DEVICE_PIXEL_RATIO())) { pixmaps[0]=QPixmap(); } if (isNull()) { QSvgRenderer renderer; QFile f(":stars.svg"); QByteArray bytes; if (f.open(QIODevice::ReadOnly)) { bytes=f.readAll(); } if (!bytes.isEmpty()) { bytes.replace("#000", col.name().toLatin1()); if (pixelRatio>1.25) { bytes.replace("stroke-width=\"3\"", "stroke-width=\"6\""); } } renderer.load(bytes); int pixSize=starSz*pixelRatio; for (int p=0; p<2; ++p) { pixmaps[p]=QPixmap(pixSize, pixSize); pixmaps[p].fill(Qt::transparent); QPainter painter(&(pixmaps[p])); renderer.render(&painter, 1==p ? "on" : "off", QRectF(0, 0, pixSize, pixSize)); } pixmaps[2]=QPixmap(pixSize, pixSize); pixmaps[2].fill(Qt::transparent); QPainter painter(&(pixmaps[2])); int halfSz=(pixSize/2.0)+0.5; painter.drawPixmap(0, 0, pixmaps[1], 0, 0, halfSz, pixSize); painter.drawPixmap(halfSz, 0, pixmaps[0], halfSz, 0, pixSize-halfSz, pixSize); painter.end(); for (int p=0; p<3; ++p) { pixmaps[p].setDevicePixelRatio(pixelRatio); } } int fullStars=rating/Song::Rating_Step; bool half=allowHalfStars && rating%Song::Rating_Step; QSize layoutSize = pixmaps[0].size() / pixmaps[0].DEVICE_PIXEL_RATIO(); QRect pr(r.x(), r.y()+(r.height()-layoutSize.width())/2, layoutSize.width(), layoutSize.height()); for (int i=0; idrawPixmap(pr, pixmaps[half && i==fullStars ? 2 : ipos()); emit valueChanged(val); } void RatingWidget::mouseMoveEvent(QMouseEvent *e) { Q_UNUSED(e) hoverVal = valueForPos(e->pos()); update(); } void RatingWidget::leaveEvent(QEvent *e) { Q_UNUSED(e) hoverVal = -1; update(); } QRect RatingWidget::contentsRect() const { const QRect &r=rect(); const int width = rp.size().width(); const int x = r.x() + (r.width() - width) / 2; return QRect(x, r.y(), width, r.height()); } int RatingWidget::valueForPos(const QPoint &pos) const { const QRect contents = contentsRect(); const double raw = double(pos.x() - contents.left()) / contents.width(); if (!allowHalfStars) { int v=(raw*Song::Rating_Max); if (v%Song::Rating_Step) { v++; } return v; } return (raw*Song::Rating_Max)+0.5; } #include "moc_ratingwidget.cpp"