~ubuntu-branches/debian/squeeze/quodlibet/squeeze

« back to all changes in this revision

Viewing changes to plugins/songsmenu.py

  • Committer: Bazaar Package Importer
  • Author(s): Christine Spang
  • Date: 2009-02-16 07:09:42 UTC
  • mfrom: (2.1.17 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090216070942-bd2iy1qva7fmpf4m
Upload to unstable now that Lenny has been released (woo!).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2006 Joe Wreschnig
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License version 2 as
5
 
# published by the Free Software Foundation
6
 
#
7
 
# $Id: songsmenu.py 3640 2006-07-16 05:51:52Z piman $
8
 
 
9
 
import gtk
10
 
 
11
 
import qltk
12
 
 
13
 
from traceback import print_exc
14
 
 
15
 
from plugins import ListWrapper, Manager
16
 
 
17
 
__all__ = [] # trick out old plugin manager
18
 
 
19
 
class SongsMenuPlugin(gtk.ImageMenuItem):
20
 
    """Plugins of this type are subclasses of gtk.ImageMenuItem.
21
 
    They will be added, in alphabetical order, to the "Plugins" menu
22
 
    that appears when songs or lists of songs are right-clicked.
23
 
    They provide one or more of the following instance methods:
24
 
    
25
 
        self.plugin_single_song(song)
26
 
        self.plugin_song(song)
27
 
        self.plugin_songs(songs)
28
 
        self.plugin_single_album(album)
29
 
        self.plugin_album(album)
30
 
        self.plugin_albums(albums)
31
 
 
32
 
    All matching provided callables on a single object are called in the
33
 
    above order if they match until one returns a true value. They are
34
 
    not called with real AudioFile objects, but rather wrappers that
35
 
    automatically detect metadata or disk changes, and save or reload
36
 
    the files as appropriate.
37
 
 
38
 
    The single_ variant is only called if a single song/album is selected.
39
 
 
40
 
    The singular tense is called once for each selected song/album, but the
41
 
    plural tense is called with a list of songs/albums.
42
 
 
43
 
    An album is a list of songs all with the same album, labelid,
44
 
    and/or musicbrainz_albumid tags (like in the Album List).
45
 
 
46
 
    To make your plugin insensitive if unsupported songs are selected,
47
 
    a method that takes a list of songs and returns True or False to set
48
 
    the sensitivity of the menu entry:
49
 
        self.plugin_handles(songs)
50
 
 
51
 
    When these functions are called, the self.plugin_window will be
52
 
    available. This is the gtk.Window the plugin was invoked from. This
53
 
    provides access to two important widgets, self.plugin_window.browser
54
 
    and self.plugin_window.songlist.
55
 
 
56
 
    All of this is managed by the constructor for SongsMenuPlugin, so
57
 
    make sure it gets called if you override it (you shouldn't have to).
58
 
    """
59
 
 
60
 
    plugin_single_song = None
61
 
    plugin_song = None
62
 
    plugin_songs = None
63
 
    plugin_single_album = None
64
 
    plugin_album = None
65
 
    plugin_albums = None
66
 
 
67
 
    def __init__(self, songs):
68
 
        super(SongsMenuPlugin, self).__init__(self.PLUGIN_NAME)
69
 
        try: i = gtk.image_new_from_stock(self.PLUGIN_ICON, gtk.ICON_SIZE_MENU)
70
 
        except AttributeError: pass
71
 
        else: self.set_image(i)
72
 
        self.set_sensitive(bool(self.plugin_handles(songs)))
73
 
 
74
 
    def plugin_handles(self, songs):
75
 
        return True
76
 
 
77
 
class SongsMenuPlugins(Manager):
78
 
    Kinds = [SongsMenuPlugin]
79
 
 
80
 
    def Menu(self, library, parent, songs):
81
 
        songs = ListWrapper(songs)
82
 
        parent = qltk.get_top_parent(parent)
83
 
 
84
 
        albums = {}
85
 
        for song in songs:
86
 
            key = song.album_key
87
 
            if key not in albums:
88
 
                albums[key] = []
89
 
            albums[key].append(song)
90
 
 
91
 
        albums = albums.values()
92
 
        map(list.sort, albums)
93
 
 
94
 
        attrs = ['plugin_song', 'plugin_songs',
95
 
                 'plugin_album', 'plugin_albums']
96
 
            
97
 
        if len(songs) == 1: attrs.append('plugin_single_song')
98
 
        if len(albums) == 1: attrs.append('plugin_single_album')
99
 
 
100
 
        items = []
101
 
        kinds = self.find_subclasses(SongsMenuPlugin)
102
 
        kinds.sort(key=lambda plugin: plugin.PLUGIN_ID)
103
 
        for Kind in kinds:
104
 
            usable = max([callable(getattr(Kind, s)) for s in attrs])
105
 
            if usable:
106
 
                try: items.append(Kind(songs))
107
 
                except: print_exc()
108
 
 
109
 
        if items:
110
 
            menu = gtk.Menu()
111
 
            for item in items:
112
 
                try:
113
 
                    menu.append(item)
114
 
                    item.connect('activate', self.__handle,
115
 
                                 library, parent, songs, albums)
116
 
                except:
117
 
                    print_exc()
118
 
                    item.destroy()
119
 
 
120
 
        else: menu = None
121
 
        return menu
122
 
 
123
 
    def __handle(self, plugin, library, parent, songs, albums):
124
 
        plugin.plugin_window = parent
125
 
 
126
 
        try:
127
 
            if len(songs) == 1 and callable(plugin.plugin_single_song):
128
 
                try: ret = plugin.plugin_single_song(songs[0])
129
 
                except Exception: print_exc()
130
 
                else:
131
 
                    if ret: return
132
 
            if callable(plugin.plugin_song):
133
 
                try: ret = map(plugin.plugin_song, songs)
134
 
                except Exception: print_exc()
135
 
                else:
136
 
                    if max(ret): return
137
 
            if callable(plugin.plugin_songs):
138
 
                try: ret = plugin.plugin_songs(songs)
139
 
                except Exception: print_exc()
140
 
                else:
141
 
                    if ret: return
142
 
 
143
 
            if len(albums) == 1 and callable(plugin.plugin_single_album):
144
 
                try: ret = plugin.plugin_single_album(albums[0])
145
 
                except Exception: print_exc()
146
 
                else:
147
 
                    if ret: return
148
 
            if callable(plugin.plugin_album):
149
 
                try: ret = map(plugin.plugin_album, albums)
150
 
                except Exception: print_exc()
151
 
                else:
152
 
                    if max(ret): return
153
 
            if callable(plugin.plugin_albums):
154
 
                try: ret = plugin.plugin_albums(albums)
155
 
                except Exception: print_exc()
156
 
                else:
157
 
                    if ret: return
158
 
 
159
 
        finally:
160
 
            del(plugin.plugin_window)
161
 
            self._check_change(library, parent, filter(None, songs))