remove some useless conversions to unicode
[nephilim.git] / nephilim / plugins / Playlist.py
blobed863933e0248f19bc1104eaf676efd2d1d20f6d
2 # Copyright (C) 2009 Anton Khirnov <wyskas@gmail.com>
4 # Nephilim 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 3 of the License, or
7 # (at your option) any later version.
9 # Nephilim is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Nephilim. If not, see <http://www.gnu.org/licenses/>.
18 from PyQt4 import QtGui, QtCore
19 from PyQt4.QtCore import QVariant
21 from ..plugin import Plugin
22 from ..common import MIMETYPES, SongsMimeData
23 from ..song import PlaylistEntryRef
25 class Playlist(Plugin):
26 # public, const
27 info = 'Shows the playlist.'
29 # public, read-only
30 o = None
32 # private
33 DEFAULTS = {'columns': ['track', 'title', 'artist',
34 'date', 'album', 'length']}
36 def _load(self):
37 self.o = PlaylistWidget(self)
39 def _unload(self):
40 self.o = None
42 def _get_dock_widget(self):
43 return self._create_dock(self.o)
45 class PlaylistWidget(QtGui.QWidget):
46 plugin = None
47 playlist = None
50 def __init__(self, plugin):
51 QtGui.QWidget.__init__(self)
52 self.plugin = plugin
54 self.playlist = PlaylistTree(self.plugin)
56 self.setLayout(QtGui.QVBoxLayout())
57 self.layout().setSpacing(0)
58 self.layout().setMargin(0)
59 self.layout().addWidget(self.playlist)
61 if self.plugin.mpclient.is_connected():
62 self.playlist.fill()
64 def fill_playlist(self):
65 self.playlist.fill()
67 class PlaylistTree(QtGui.QTreeWidget):
68 plugin = None
70 ### PRIVATE ###
71 # popup menu
72 _menu = None
73 # add same... menu
74 _same_menu = None
76 def __init__(self, plugin):
77 QtGui.QTreeWidget.__init__(self)
78 self.plugin = plugin
80 self.setSelectionMode(QtGui.QTreeWidget.ExtendedSelection)
81 self.setAlternatingRowColors(True)
82 self.setRootIsDecorated(False)
84 # drag&drop
85 self.viewport().setAcceptDrops(True)
86 self.setDropIndicatorShown(True)
87 self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
89 columns = self.plugin.settings.value(self.plugin.name + '/columns').toStringList()
90 self.setColumnCount(len(columns))
91 self.setHeaderLabels(columns)
92 self.header().restoreState(self.plugin.settings.value(self.plugin.name + '/header_state').toByteArray())
94 # menu
95 self._menu = QtGui.QMenu()
96 self._same_menu = self._menu.addMenu('Add same...')
97 self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
98 self.customContextMenuRequested.connect(self._show_context_menu)
100 self.itemActivated.connect(self._song_activated)
101 self.header().geometriesChanged.connect(self._save_state)
102 self.plugin.mpclient.playlist_changed.connect(self.fill)
103 self.plugin.mpclient.connect_changed.connect(self._update_menu)
105 def _save_state(self):
106 self.plugin.settings.setValue(self.plugin.name + '/header_state', QVariant(self.header().saveState()))
108 def _song_activated(self, item):
109 self.plugin.mpclient.play(item.song['id'])
111 def fill(self):
112 columns = self.plugin.settings.value(self.plugin.name + '/columns').toStringList()
113 self.clear()
114 for song in self.plugin.mpclient.playlistinfo():
115 item = PlaylistSongItem(PlaylistEntryRef(self.plugin.mpclient, song['id']))
116 for i in range(len(columns)):
117 item.setText(i, song[columns[i]])
118 self.addTopLevelItem(item)
120 def keyPressEvent(self, event):
121 if event.matches(QtGui.QKeySequence.Delete):
122 ids = []
123 for item in self.selectedItems():
124 ids.append(item.song['id'])
126 self.plugin.mpclient.delete(ids)
127 else:
128 QtGui.QTreeWidget.keyPressEvent(self, event)
130 def mimeData(self, items):
131 data = SongsMimeData()
132 data.set_plistsongs([items[0].song['id']])
133 return data
135 def dropMimeData(self, parent, index, data, action):
136 if data.hasFormat(MIMETYPES['plistsongs']):
137 if parent:
138 index = self.indexOfTopLevelItem(parent)
139 elif index >= self.topLevelItemCount():
140 index = self.topLevelItemCount() - 1
141 self.plugin.mpclient.move(data.plistsongs()[0], index)
142 return True
143 elif data.hasFormat(MIMETYPES['songs']):
144 if parent:
145 index = self.indexOfTopLevelItem(parent)
146 self.plugin.mpclient.add(data.songs(), index)
147 return True
148 return False
150 def supportedDropActions(self):
151 return QtCore.Qt.CopyAction | QtCore.Qt.MoveAction
153 def mimeTypes(self):
154 return [MIMETYPES['songs'], MIMETYPES['plistsongs']]
156 def _update_menu(self):
157 """Update popup menu. Invoked on (dis)connect."""
158 self._same_menu.clear()
159 for tag in self.plugin.mpclient.tagtypes:
160 self._same_menu.addAction(tag, lambda tag = tag: self._add_selected_same(tag))
162 def _add_selected_same(self, tag):
163 """Adds all tracks in DB with tag 'tag' same as selected tracks."""
164 for it in self.selectedItems():
165 self.plugin.mpclient.findadd(tag, it.song[tag])
167 def _show_context_menu(self, pos):
168 if not self.indexAt(pos).isValid():
169 return
170 self._menu.popup(self.mapToGlobal(pos))
172 class PlaylistSongItem(QtGui.QTreeWidgetItem):
173 ### PUBLIC ###
174 song = None
176 def __init__(self, song):
177 QtGui.QTreeWidgetItem.__init__(self)
178 self.song = song