1# Copyright 2011-2016 Nick Boultbee 2# 2005 Joe Wreschnig 3# 4# This program is free software; you can redistribute it and/or modify 5# it under the terms of the GNU General Public License as published by 6# the Free Software Foundation; either version 2 of the License, or 7# (at your option) any later version. 8 9from gi.repository import Gtk 10 11from quodlibet import _ 12from quodlibet import util 13from quodlibet import config 14from quodlibet import qltk 15from quodlibet.config import RATINGS 16from quodlibet.qltk import Icons 17from quodlibet.qltk import SeparatorMenuItem 18 19 20class ConfirmRateMultipleDialog(qltk.Message): 21 def __init__(self, parent, action_title, count, value): 22 assert count > 1 23 24 title = (_("Are you sure you want to change the " 25 "rating of all %d songs?") % count) 26 desc = (_("The saved ratings will be removed") if value is None 27 else _("The rating of all selected songs will be changed to " 28 "'%s'") % util.format_rating(value)) 29 30 super(ConfirmRateMultipleDialog, self).__init__( 31 Gtk.MessageType.WARNING, parent, title, desc, Gtk.ButtonsType.NONE) 32 33 self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) 34 self.add_button(action_title, Gtk.ResponseType.YES) 35 36 37class RatingsMenuItem(Gtk.ImageMenuItem): 38 39 def __init__(self, songs, library, label=_("_Rating")): 40 super(RatingsMenuItem, self).__init__(label=label, use_underline=True) 41 self._songs = songs 42 image = Gtk.Image.new_from_icon_name(Icons.FAVORITE, Gtk.IconSize.MENU) 43 image.show() 44 self.set_image(image) 45 46 submenu = Gtk.Menu() 47 self.set_submenu(submenu) 48 self._rating_menu_items = [] 49 for i in RATINGS.all: 50 text = "%0.2f\t%s" % (i, util.format_rating(i)) 51 itm = Gtk.CheckMenuItem(label=text) 52 itm.rating = i 53 submenu.append(itm) 54 handler = itm.connect( 55 'toggled', self._on_rating_change, i, library) 56 self._rating_menu_items.append((itm, handler)) 57 reset = Gtk.MenuItem(label=_("_Remove Rating"), use_underline=True) 58 reset.connect('activate', self._on_rating_remove, library) 59 self._select_ratings() 60 61 submenu.append(SeparatorMenuItem()) 62 submenu.append(reset) 63 submenu.show_all() 64 65 def set_songs(self, songs): 66 """Set a new set of songs affected by the rating menu""" 67 self._songs = songs 68 self._select_ratings() 69 70 def _select_ratings(self): 71 ratings = [song("~#rating") for song in self._songs 72 if song and song.has_rating] 73 song_count = len(self._songs) 74 for (menu_item, handler) in self._rating_menu_items: 75 rating_val = menu_item.rating 76 rated_count = ratings.count(rating_val) 77 menu_item.handler_block(handler) 78 if rated_count == 0: 79 menu_item.set_active(False) 80 elif rated_count == song_count: 81 menu_item.set_active(True) 82 else: 83 menu_item.set_inconsistent(True) 84 menu_item.handler_unblock(handler) 85 86 def _on_rating_change(self, menuitem, value, library): 87 self.set_rating(value, self._songs, library) 88 89 def _on_rating_remove(self, menutitem, library): 90 self.remove_rating(self._songs, library) 91 92 def set_rating(self, value, songs, librarian): 93 count = len(songs) 94 if (count > 1 and 95 config.getboolean("browsers", "rating_confirm_multiple")): 96 parent = qltk.get_menu_item_top_parent(self) 97 dialog = ConfirmRateMultipleDialog( 98 parent, _("Change _Rating"), count, value) 99 if dialog.run() != Gtk.ResponseType.YES: 100 return 101 for song in songs: 102 song["~#rating"] = value 103 librarian.changed(songs) 104 105 def remove_rating(self, songs, librarian): 106 count = len(songs) 107 if (count > 1 and 108 config.getboolean("browsers", "rating_confirm_multiple")): 109 parent = qltk.get_menu_item_top_parent(self) 110 dialog = ConfirmRateMultipleDialog( 111 parent, _("_Remove Rating"), count, None) 112 if dialog.run() != Gtk.ResponseType.YES: 113 return 114 reset = [] 115 for song in songs: 116 if "~#rating" in song: 117 del song["~#rating"] 118 reset.append(song) 119 librarian.changed(reset) 120