1# -*- coding: utf-8 -*- 2# 3# Picard, the next-generation MusicBrainz tagger 4# 5# Copyright (C) 2008, 2018-2019 Philipp Wolfer 6# Copyright (C) 2011, 2013 Michael Wiencek 7# Copyright (C) 2013, 2018 Laurent Monin 8# Copyright (C) 2016-2017 Sambhav Kothari 9# Copyright (C) 2018 Vishal Choudhary 10# 11# This program is free software; you can redistribute it and/or 12# modify it under the terms of the GNU General Public License 13# as published by the Free Software Foundation; either version 2 14# of the License, or (at your option) any later version. 15# 16# This program is distributed in the hope that it will be useful, 17# but WITHOUT ANY WARRANTY; without even the implied warranty of 18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19# GNU General Public License for more details. 20# 21# You should have received a copy of the GNU General Public License 22# along with this program; if not, write to the Free Software 23# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 24 25 26from PyQt5 import ( 27 QtCore, 28 QtGui, 29 QtWidgets, 30) 31 32from picard.config import get_config 33 34 35class RatingWidget(QtWidgets.QWidget): 36 37 def __init__(self, parent, track): 38 super().__init__(parent) 39 self._track = track 40 config = get_config() 41 self._maximum = config.setting["rating_steps"] - 1 42 try: 43 self._rating = int(track.metadata["~rating"] or 0) 44 except ValueError: 45 self._rating = 0 46 self._highlight = 0 47 self._star_pixmap = QtGui.QPixmap(":/images/star.png") 48 self._star_gray_pixmap = QtGui.QPixmap(":/images/star-gray.png") 49 self._star_size = 16 50 self._star_spacing = 2 51 self._offset = 16 52 self._width = self._maximum * (self._star_size + self._star_spacing) + self._offset 53 self._height = self._star_size + 6 54 self.setMaximumSize(self._width, self._height) 55 self.setMinimumSize(self._width, self._height) 56 self.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)) 57 self.setMouseTracking(True) 58 59 def sizeHint(self): 60 return QtCore.QSize(self._width, self._height) 61 62 def _setHighlight(self, highlight): 63 assert 0 <= highlight <= self._maximum 64 if highlight != self._highlight: 65 self._highlight = highlight 66 self.update() 67 68 def mousePressEvent(self, event): 69 if event.button() == QtCore.Qt.LeftButton: 70 x = event.x() 71 if x < self._offset: 72 return 73 rating = self._getRatingFromPosition(x) 74 if self._rating == rating: 75 rating = 0 76 self._rating = rating 77 self._update_track() 78 self.update() 79 event.accept() 80 81 def mouseMoveEvent(self, event): 82 self._setHighlight(self._getRatingFromPosition(event.x())) 83 event.accept() 84 85 def leaveEvent(self, event): 86 self._setHighlight(0) 87 event.accept() 88 89 def _getRatingFromPosition(self, position): 90 rating = int((position - self._offset) / (self._star_size + self._star_spacing)) + 1 91 if rating > self._maximum: 92 rating = self._maximum 93 return rating 94 95 def _update_track(self): 96 track = self._track 97 rating = str(self._rating) 98 track.metadata["~rating"] = rating 99 for file in track.files: 100 file.metadata["~rating"] = rating 101 config = get_config() 102 if config.setting["submit_ratings"]: 103 ratings = {("recording", track.id): self._rating} 104 self.tagger.mb_api.submit_ratings(ratings, None) 105 106 def paintEvent(self, event=None): 107 painter = QtGui.QPainter(self) 108 offset = self._offset 109 for i in range(1, self._maximum + 1): 110 if i <= self._rating or i <= self._highlight: 111 pixmap = self._star_pixmap 112 else: 113 pixmap = self._star_gray_pixmap 114 painter.drawPixmap(offset, 3, pixmap) 115 offset += self._star_size + self._star_spacing 116